农业银行快捷支付php版说明和实例代码

北城余情 提交于 2020-02-26 04:20:05
接入的是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, "\n");
		$pem = "-----BEGIN CERTIFICATE-----\n" . $pem . "-----END CERTIFICATE-----\n";
		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, "\n");
		$pem = "-----BEGIN CERTIFICATE-----\n" . $pem . "-----END CERTIFICATE-----\n";
		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 = "\n";
        $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>\n";
            $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

便宜没好货你懂的,或者你可以直接复制代码也是可以使用的

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!