接入的是shopnc,代码改改就可以用了,虽然不是一个完善的类,也可以按照类的方法直接调用,省得再去扣开发文档 农行在接收返回信息也会验证一次,还有一点就是页面通知返回结果
一定要用服务器通知,不然会出异常问题,导致问题
2016年5月12日11:15:41
大概有一下几个文件,
<?php class abchina{ //农行网关 const GATEWAY = 'https://pay.abchina.com/ebus/trustpay/ReceiveMerchantTrxReqServlet'; //标示 private $code = 'abchina'; /** * 支付接口配置信息 * * @var array */ private $payment; /** * 订单信息 * * @var array */ private $order; /** * 发送至农行的参数 * * @var array */ private $parameter; //发送请求 private $request; //订单数据 private $orderitems; private $payment_info; private $order_info; private $res; //签名算法 const SIGNATURE_ALGORITHM = 'SHA1withRSA'; //商户编号 const MERCHANTID = ''; //商户私钥加密密码 const MERCHANTCERTPASSWORD = ''; //网上支付平台证书 const TRUSTPAYCERTFILE= './TrustPay.cer'; //商户证书储存目录档名 const MERCHANTCERTFILE= './fuwuqi.pfx'; //报文里有的东西 const TRX_TYPE_PAY_REQ = "PayReq"; public function __construct($payment_info = array(),$order_info = array()) { $this->payment_info = $payment_info; $this->order_info = $order_info; } //提交订单 public function submit() { // var_dump($this->payment_info); // // var_dump($this->order_info); // die; //没有自己传参的不要随意修改 $this->order["PayTypeID"] = 'ImmediatePay'; //设定交易类型 $this->order["OrderNo"] = $this->order_info['pay_sn']; //设定订单编号 自己传参数 $this->order["OrderAmount"] = $this->order_info['api_pay_amount']; //设定交易金额 自己传参数 // $this->order["OrderAmount"] = '0.01'; //设定交易金额 自己传参数 测试使用 $this->order["CurrencyCode"] = 156; //设定交易币种 $this->order["InstallmentMark"] = 0; //分期标识 $this->order["OrderDate"] = date('Y/m/d'); //设定订单日期 (必要信息 - YYYY/MM/DD) $this->order["OrderTime"] = date('H:i:s'); //设定订单时间 (必要信息 - HH:MM:SS) $this->order["CommodityType"] = '0202'; //设置商品种类 //2、订单明细 $orderitem = array (); $orderitem["ProductName"] = "GG"; //商品名称 自己写随意 $this->orderitems[0] = $orderitem; //3、生成支付请求对象 $this->request["TrxType"] = self::TRX_TYPE_PAY_REQ; //设定交易类型 $this->request["PaymentType"] = 'A'; //设定支付类型 $this->request["PaymentLinkType"] = 1; //设定支付接入方式 $this->request["NotifyType"] = 1; //设定通知方式 $this->request["ResultNotifyURL"] = SHOP_SITE_URL."/api/payment/abchina/notify_url.php"; //设定通知URL地址 自己设定 $this->request["IsBreakAccount"] = 0; //设定交易是否分账 $aMerchantNo =1; //取得交易报文 $tRequestMessage = $this->getRequestMessage(); // echo '<pre>'; // var_export($tRequestMessage); // echo '</pre>'; // die; //组成完整交易报文 $tRequestMessage = $this->composeRequestMessage($aMerchantNo,$tRequestMessage); // echo '<pre>'; // var_export($tRequestMessage); // echo '</pre>'; // die; //对交易报文进行签名 $tRequestMessage = $this->signMessage($aMerchantNo, $tRequestMessage); // echo '<pre>'; // var_export($tRequestMessage); // echo '</pre>'; // die; //发送交易报文至网上支付平台 $tResponseMessage = $this->sendMessage($aMerchantNo,$tRequestMessage); //验证网上支付平台响应报文的签名 $this->res = $this->verifySign($tResponseMessage); // echo '<pre>'; // var_export($tResponseMessage); // echo '</pre>'; $PaymentURL = self::GetValue($tResponseMessage,'PaymentURL') ; $ReturnCode = self::GetValue($tResponseMessage,'ReturnCode') ; //验证报文签名正确而却返回码是0000,就可以跳转支付页面 if($this->res == 1 && $ReturnCode=='0000' ){ header("Location:".$PaymentURL); die; }else{ header('<meta http-equiv="content-type" content="text/html;charset=utf-8">'); die('abchina pay check error'); } // var_dump($PaymentURL); // // var_dump($ReturnCode); // echo '<pre>'; // var_export(json_decode($tResponseMessage,true)); // echo '</pre>'; // var_dump($res); // die; } public static function arrayRecursive(&$array, $function, $apply_to_keys_also = false){ foreach ($array as $key => $value) { $array[$key] = $function($value); } } protected function getRequestMessage() { self :: arrayRecursive($this->order, "urlencode", false); self :: arrayRecursive($this->request, "urlencode", false); $js = '"Order":' . (json_encode(($this->order))); $js = substr($js, 0, -1); $js = $js . ',"OrderItems":['; $count = count($this->orderitems, COUNT_NORMAL); for ($i = 0; $i < $count; $i++) { self :: arrayRecursive($this->orderitems[$i], "urlencode", false); $js = $js . json_encode($this->orderitems[$i]); if ($i < $count -1) { $js = $js . ','; } } $js = $js . ']}}'; $tMessage = json_encode($this->request); $tMessage = substr($tMessage, 0, -1); $tMessage = $tMessage . ',' . $js; $tMessage = urldecode($tMessage); return $tMessage; } private function composeRequestMessage($aMerchantNo,$aMessage) { $tMessage = "{"Version":"V3.0.0","Format":"JSON","Merchant":" . "{"ECMerchantType":"" . "EBUS" . "","MerchantID":"" . self::MERCHANTID . ""}," . ""TrxRequest":" . $aMessage . "}"; return $tMessage; } private function signMessage($aMerchantNo, $aMessage) { // public function signMessageOp() { //1、读取证书 // $tTrustPayCertFile = dirname(__FILE__).'/TrustPay.cer'; $tTrustPayCertFile = "fuwuqi.pfx"; // $iTrustpayCertificate = openssl_x509_read(self :: der2pem(file_get_contents($tTrustPayCertFile))); // var_dump($tTrustPayCertFile); // var_dump(self::MERCHANTCERTPASSWORD); // die; openssl_pkcs12_read(file_get_contents($tTrustPayCertFile), $tCertificate, self::MERCHANTCERTPASSWORD); // var_dump($tCertificate); // die; //2、验证证书是否在有效期内 $cer = openssl_x509_parse($tCertificate['cert']); // var_dump($cer); //3、取得密钥 $pkey = openssl_pkey_get_private($tCertificate['pkey']); // var_dump($pkey); $key = $pkey; // $key = self :: $iMerchantKeys[$aMerchantNo -1]; $signature = ''; $data = strval($aMessage); if (!openssl_sign($data, $signature, $key, OPENSSL_ALGO_SHA1)) { return null; } $signature = base64_encode($signature); $tMessage = "{"Message":$data" . "," . '"Signature-Algorithm":' . '"' . self :: SIGNATURE_ALGORITHM . '","Signature":"' . $signature . '"}'; return $tMessage; // return $pkey; // var_dump($iTrustpayCertificate); } private function sendMessage($aMerchantNo, $aMessage) { //组成<MSG>段 $tMessage = strval($aMessage); $tURL = self::GATEWAY; $opts = array( 'http' => array( 'method' => 'POST', 'user_agent' => 'TrustPayClient V3.0.0', 'protocol_version' => 1.0, 'header' => array('Content-Type: text/html', 'Accept: */*'), 'content' => $tMessage ), 'ssl' => array( 'verify_peer' => false ) ); $context = stream_context_create($opts); $tResponseMessage = file_get_contents($tURL, false, $context); // $tTrxResponse = self::init($tResponseMessage); return $tResponseMessage; } private static function der2pem($der_data) { $pem = chunk_split(base64_encode($der_data), 64, " "); $pem = "-----BEGIN CERTIFICATE----- " . $pem . "-----END CERTIFICATE----- "; return $pem; } public static function verifySign($aMessage) { $TrustPayFile = "TrustPay.cer"; $iTrustpayCertificate = openssl_x509_read(self :: der2pem(file_get_contents($TrustPayFile))); $tTrxResponse = self::GetValue($aMessage,'Message') ; $tSignBase64 = self::GetValue($aMessage,'Signature') ; $tSign = base64_decode($tSignBase64); $key = openssl_pkey_get_public($iTrustpayCertificate); $data = strval($tTrxResponse); return openssl_verify($data, $tSign, $key, OPENSSL_ALGO_SHA1); } public function GetValue($json,$aTag) { $json = $json; $index = 0; $length = 0; $index = strpos($json, $aTag, 0); if ($index === false) return ""; do { if($json[$index-1] === """ && $json[$index+strlen($aTag)] === """) { break; } else { $index = strpos($json, $aTag, $index+1); if ($index === false) return ""; } } while (true); $index = $index + strlen($aTag) + 2; $c = $json[$index]; if ($c === '{') { $output = self::GetObjectValue($index, $json); } if ($c === '"') { $output = self::GetStringValue($index, $json); } return $output; } private function GetObjectValue($index, $json) { $count = 0; $_output = ""; do { $c = $json[$index]; if ($c === '{') { $count++; } if ($c === '}') $count--; if ($count !== 0) { $_output =$_output.$c; } else { $_output = $_output.$c; return $_output; } $index++; } while (true); } private function GetStringValue($index, $json) { $index++; $_output = ""; do { $c = $json[$index++]; if ($c !== '"') { $_output = $_output.$c; } else { return $_output; } } while (true); } /** * 返回地址验证(同步) * * @param * @return boolean */ public function return_verify(){ $this->order["PayTypeID"] = 'ImmediatePay'; //设定交易类型 $this->order["OrderNo"] = $this->order_info['pay_sn']; //设定订单编号 自己传参数 $this->order["OrderAmount"] = $this->order_info['api_pay_amount']; //设定交易金额 自己传参数 // $this->order["OrderAmount"] = '0.01'; //设定交易金额 自己传参数 测试使用 $this->order["CurrencyCode"] = 156; //设定交易币种 $this->order["InstallmentMark"] = 0; //分期标识 $this->order["OrderDate"] = date('Y/m/d'); //设定订单日期 (必要信息 - YYYY/MM/DD) $this->order["OrderTime"] = date('H:i:s'); //设定订单时间 (必要信息 - HH:MM:SS) $this->order["CommodityType"] = '0202'; //设置商品种类 //2、订单明细 $orderitem = array (); $orderitem["ProductName"] = "GG"; //商品名称 自己写随意 $this->orderitems[0] = $orderitem; //3、生成支付请求对象 $this->request["TrxType"] = self::TRX_TYPE_PAY_REQ; //设定交易类型 $this->request["PaymentType"] = 'A'; //设定支付类型 $this->request["PaymentLinkType"] = 1; //设定支付接入方式 $this->request["NotifyType"] = 1; //设定通知方式 $this->request["ResultNotifyURL"] = SHOP_SITE_URL."/api/payment/abchina/notify_url.php"; //设定通知URL地址 自己设定 $this->request["IsBreakAccount"] = 0; //设定交易是否分账 $aMerchantNo =1; //取得交易报文 $tRequestMessage = $this->getRequestMessage(); //组成完整交易报文 $tRequestMessage = $this->composeRequestMessage($aMerchantNo,$tRequestMessage); //对交易报文进行签名 $tRequestMessage = $this->signMessage($aMerchantNo, $tRequestMessage); //发送交易报文至网上支付平台 $tResponseMessage = $this->sendMessage($aMerchantNo,$tRequestMessage); //验证网上支付平台响应报文的签名 $this->res = $this->verifySign($tResponseMessage); $PaymentURL = self::GetValue($tResponseMessage,'PaymentURL') ; $ReturnCode = self::GetValue($tResponseMessage,'ReturnCode') ; //验证报文签名正确而却返回码是0000,就可以跳转支付页面 if($this->res == 1){ return true; }else{ return false; } } public function getPayResult($param){ return $this->res; } }
abchina.php
notify.php
<?php error_reporting(7); function der2pem($der_data) { $pem = chunk_split(base64_encode($der_data), 64, " "); $pem = "-----BEGIN CERTIFICATE----- " . $pem . "-----END CERTIFICATE----- "; return $pem; } //$tt = json_decode(json_encode((array) simplexml_load_string(base64_decode($_POST['MSG']))), true); function verifySignXML($aMessage) { include dirname(__FILE__)."/XMLDocument.php"; $TrustPayFile = dirname(__FILE__)."/TrustPay.cer"; $iTrustpayCertificate = openssl_x509_read(der2pem(file_get_contents($TrustPayFile))); $aMessage = new XMLDocument($aMessage); $tTrxResponse = $aMessage->getValue('Message'); $tSignBase64 = $aMessage->getValue('Signature'); $tSign = base64_decode($tSignBase64); $key = openssl_pkey_get_public($iTrustpayCertificate); $data = strval($tTrxResponse); $result['res'] = openssl_verify($data, $tSign, $key, OPENSSL_ALGO_SHA1); $result['iRspRef'] =$aMessage->getValue('iRspRef'); //交易流水号 $result['OrderNo'] =$aMessage->getValue('OrderNo'); //网站交易订单号 $result['Amount'] =$aMessage->getValue('Amount'); //订单金额 $result['VoucherNo'] =$aMessage->getValue('VoucherNo'); return $result; } $rr = verifySignXML(base64_decode($_POST['MSG'])); //var_dump($rr); //die; if ($rr['res'] == 1) { $_GET['act'] = 'payment'; $_GET['op'] = 'return'; $_GET['payment_code'] = 'abchina'; $_GET['trade_no'] = $rr['iRspRef']; $_GET['out_trade_no'] = $rr['OrderNo']; $_GET['bank_total'] = $rr['Amount']; $_GET['extra_common_param'] = 'real_order'; require_once(dirname(__FILE__).'/../../../index.php'); } else { die('abchina notify check error'); }
XMLDocument.php
<?php class XMLDocument { private $iXMLString = ''; public function getFirstTagName() { $tTagName = null; $tStartIndex = strpos($this->iXMLString, '<'); $tEndIndex = strpos($this->iXMLString, '>'); if ($tEndIndex > $tStartIndex) { $tTagName = substr($this->iXMLString, $tStartIndex + 1, $tEndIndex - ($tStartIndex + 1)); } return $tTagName; } public function __construct($aXMLString='') { $this->init($aXMLString); } public function init($aXMLString) { $this->iXMLString = $aXMLString; return $this; } public function __toString() { return $this->iXMLString; } public function getValue($aTag) { $tXMLDocument = null; $tStartIndex = strpos($this->iXMLString, '<'.trim($aTag).'>'); $tEndIndex = strpos($this->iXMLString, '</'.trim($aTag).'>'); if (($tStartIndex !== FALSE) && ($tEndIndex !== FALSE) && ($tStartIndex < $tEndIndex)) { $tXMLDocument = substr($this->iXMLString, $tStartIndex + strlen($aTag) + 2, $tEndIndex - ($tStartIndex + strlen($aTag) + 2)); } return $tXMLDocument; } public function getValueNoNull($aTag) { $tValue = ""; $tXML = $this->getValue($aTag); if ($tXML !== null) { $tValue = $tXML; } return $tValue; } public function getValueArray($aTag) { $tValues = array(); $offset = 0; while(TRUE) { $tStartIndex = strpos($this->iXMLString, '<'.trim($aTag).'>', $offset); $tEndIndex = strpos($this->iXMLString, '</'.trim($aTag).'>', $offset); if (($tStartIndex === FALSE) || ($tEndIndex === FALSE) || ($tStartIndex > $tEndIndex)) { break; } array_push($tValues, new XMLDocument(substr($this->iXMLString, $tStartIndex + strlen($aTag) + 2, $tEndIndex - ($tStartIndex + strlen($aTag) + 2)))); $offset = $tEndIndex + 1; } return $tValues; } public function getValueArrayList($aTag) { return $this->getValueArray($aTag); } public function getDocuments($aTag) { return $this->getValueArray($aTag); } public function getFormatDocument($aSpace) { return $this->getFormatDocumentLevel(0, $aSpace); } private function getFormatDocumentLevel($aLevel, $aSpace) { $tSpace1 = str_repeat($aSpace, $aLevel + 1); $tTagName = $this->getFirstTagName(); if ($tTagName === null) { return $this; } $tXMLString = " "; $tXMLDocument = new XMLDocument($this->iXMLString); while (($tTagName = $tXMLDocument->getFirstTagName()) !== null) { $tTemp = $tXMLDocument->getValue($tTagName); $tSpace = ""; if ($tTemp->getFirstTagName() !== null) { $tSpace = $tSpace1; } $tXMLString = "$tXMLString$tSpace1<$tTagName>".$tTemp->getFormatDocumentLevel($aLevel + 1, $aSpace)."$tSpace</$tTagName> "; $tXMLDocument = $tXMLDocument->deleteFirstTagDocument(); } return new XMLDocument($tXMLString); } public function deleteFirstTagDocument() { $tTagName = $this->getFirstTagName(); $tStartIndex = strpos($this->iXMLString, "<$tTagName>"); $tEndIndex = strpos($this->iXMLString, "</$tTagName>"); if ($tEndIndex > $tStartIndex) { $this->iXMLString = substr($this->iXMLString, $tEndIndex + strlen($tTagName) + 3); if ($this->iXMLString === FALSE) { $this->iXMLString = ""; } } return $this; } } ?>
代码包和开发文档说明下载地址 :http://download.csdn.net/detail/zh7314/9517627
便宜没好货你懂的,或者你可以直接复制代码也是可以使用的