protocol = $protocol; $this->config = $config; $this->persistent = $persistent; if ($connection === null) { $this->setConnection(); } else { $this->connection = $connection; } } /** * Returns empty ISO8583 Message * * @return \ISO8583\Message ISO8583 Message object */ protected function getEmptyMessage() { return new Message($this->protocol, [ 'lengthPrefix' => 0 ]); } protected function getHeaderMessage() { $message = $this->getEmptyMessage(); //设置 TUDU头(10位) => ID(60H)+目的地址(N2)+源地址(N2) 60 0016 0000 $message->setTPDU('6000060000'); /** * 设置 报文头(12位) => {应用类别(N2)}+软件版本号(N2)+终端状态(N1)+处理要求(N1)+保留使用(N6) 60 02 0 0 000000 * 应用类别定义 磁条卡:60 IC卡: 61 * 软件版本 01 国际,非全报文加密 02 国密,非全报文加密 80 全报文加密 * 终端状态 0 正常交易状态 1 测试交易状态 * 处理要求 0 无处理要求 1 下传终端参数 2 上传终端版本号及状态信息 3 重新签到 4 通知终端发起更新公钥信息操作 5 下载终端IC卡参数 * 保留使用 000000 */ $message->setHeader('600210000000'); /** * 加密信息域 => 报文长度(A3)+算法标识(A1)+{商户号(A15)}+{终端号(A8)}+交易标识(A10)+响应码(A2)+保留(A2) * 108 3 105431080620049 10009464 0200 000155 00 FF * 报文长度: 指应用数据明文长度,此处不设置,pack时生成 * 算法标识: 0 明文数据(仅限于签到交易) 1 DES算法(不支持) 2 3DES 算法 3 国密算法 * 交易标识:4个MTI(8583d的MsgType)+流水号;若交易报文存在11域,则流水号需要与8583的11域相等。 * 响应码:2位ASCII;若系统解密OK,则填充“00”;否则填充“ER”表示系统解密失败;系统原包返回。 * 保留:填充“FF” */ $message->setEncrypted('010543108062004910009464020000015500FF'); return $message; } /** * Get fully prepared ISO8583 Message. * * @return \ISO8583\Message */ protected function getPreparedMessage() { $message = $this->getEmptyMessage(); // $message->setField(4, "000000000000"); // $message->setField(7, date('mdHis')); // $message->setField(11, substr($this->generateRequestId(), -6)); // $message->setField(18, Settings::MERCHANT_TYPE); // $message->setField(19, Settings::CURRENCY_CODE); // $message->setField(22, Settings::POS_ENTRY_MODE_MAGNETIC); // $message->setField(25, Settings::POS_CONDITION_CODE_NORMAL); // $message->setField(32, Settings::ACQUIRING_INSTITUTION_ID); // $message->setField(37, substr(date('yz'), 1) . substr($this->generateRequestId(), -8)); // $message->setField(41, Settings::TERMINAL_ID); // $message->setField(42, Settings::ACCEPTOR_ID); // $message->setField(49, Settings::CURRENCY_CODE); // $message->setField(60, Settings::ADDITIONAL_POS_INFO); return $message; } /** * Return random request ID * * @return integer */ protected function generateRequestId() { return rand(10000000, 99999999); } public function check() { $message = $this->request()->pack(); $answer = $this->sendMessage($message); $unpackedAnswer = $this->getEmptyMessage(); $unpackedAnswer->unpack($answer); return $this->expectation($unpackedAnswer); } public function setConnection() { $config = []; if ($this->config->get('host')) { $config['host'] = $this->config->get('host'); } if ($this->config->get('port')) { $config['port'] = $this->config->get('port'); } $attempts = 0; $lastError = null; $errors = []; while($attempts < 10) { try { $connection = new Connection($config); $connection->connect(); break; } catch(\Exception $e) { sleep(1); $attempts++; $lastError = $e->getMessage(); $errors[] = $e->getMessage(); } } var_dump($errors); if ($attempts === 10) { throw new \Exception($lastError); } $this->connection = $connection; } public function resetConnection() { $this->connection->disconnect(); $this->connection = null; } protected function sendMessage($message) { return $this->connection->write($message); } abstract protected function request(); abstract protected function expectation($response); }