Heim  >  Artikel  >  Backend-Entwicklung  >  Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

小云云
小云云Original
2018-03-01 13:48:1212165Durchsuche

In diesem Artikel werden hauptsächlich Entwicklungsbeispiele für die Online-Zahlungsschnittstelle von PHP UnionPay vorgestellt, in der Hoffnung, allen zu helfen.

1. Melden Sie sich bei der UnionPay-Self-Service-Testplattform an (Anmeldeadresse: open.unionpay.com). Klicken Sie nach der Anmeldung wie folgt auf die zu testende Schnittstelle Richtig: In diesem Beispiel erfolgt die Zahlung exemplarisch auf der mobilen Webseite (WAP-Zahlung).

Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay
2. Klicken Sie auf die Testparameter im linken Menü, um die für den Testvorgang erforderlichen Parameter anzuzeigen, wie unten gezeigt: Klicken Sie auf das Testzertifikat, um es herunterzuladen zwei Zertifikate. Eines ist ein privates Schlüsselzertifikat mit dem Suffix .pfx und das andere ist ein öffentliches Schlüsselzertifikat mit dem Suffix .cer. Nach dem Herunterladen wird der Name der privaten Schlüsselzertifikatsdatei in acp_test_sign.pfx geändert. Wenn Sie es nicht herunterladen, können Sie dieses Beispiel auch direkt verwenden. Im TP3.2-Beispiel befinden sich alle Zertifikatsdateien in Public/cer.
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

3. Das TP3.2-Beispiel enthält relevanten Code, der zum Testen verwendet werden kann. Der Code enthält Kommentare. Bevor Sie beginnen, stellen Sie sicher, dass die PHP-Version Ihrer Umgebung auf 5.3 basiert. Sie müssen die Funktionen „curl“ und „openssl“ aktivieren und der Test muss online durchgeführt werden. Wenn Sie auf Probleme stoßen, können Sie sich auf die offiziellen Anweisungen in diesem Ordner beziehen. Das darin enthaltene Beispiel konnte nicht ausgeführt werden Ich weiß nicht, was passiert ist.
4. Wechseln Sie zur Produktionsumgebung und achten Sie auf die folgenden Probleme:
4.1 Besuchen Sie zunächst die Website http://cs.cfca.com.cn gemäß den Anweisungen in der Händleraktivierungs-E-Mail /
Laden Sie die Produktionszertifikatdatei herunter:
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay
Nachdem Sie auf „Herunterladen“ geklickt haben und der Downloadvorgang abgeschlossen ist, wird auf der Seite eine Aufforderung zum erfolgreichen Download angezeigt. Das heruntergeladene Zertifikat wird automatisch im IE gespeichert. Der nächste Schritt besteht darin, das Zertifikat zu exportieren.
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay
4.2 Zertifikatdatei exportieren: Öffnen Sie den IE-Browser, klicken Sie auf das Zahnrad in der oberen rechten Ecke, öffnen Sie Extras=》Internetoptionen=》Inhalt=》Zertifikat, wie im Bild gezeigt:
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

Nachdem Sie auf das Zertifikat geklickt haben, finden Sie das Zertifikat, das Sie gerade heruntergeladen haben. Sie können es anhand seines Namens identifizieren. Es ist in der E-Mail des Händlers markiert:
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay
Der Name ist markiert Rot im Bild oben sollte mit dem Namen übereinstimmen, den Sie heruntergeladen haben.
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay
Suchen Sie es und klicken Sie auf Exportieren: Im nächsten Schritt müssen Sie die folgenden Schritte beachten

Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

Das obige Passwort ist das Passwort, das in der Produktionsumgebung in config.php festgelegt werden soll. Bitte legen Sie es auf sechs Ziffern fest (nur Zahlen, bitte keine Buchstaben und Symbole festlegen).

Geben Sie den Dateinamen des exportierten Zertifikats an: acp_prod_sign und wählen Sie ein Verzeichnis zum Speichern des Zertifikats aus. Klicken Sie auf „Weiter“, um den Export auf den Desktop festzulegen. Nach Abschluss wird eine Datei „acp_prod_sign.pfx“ angezeigt Der Desktop. Dies ist die private Schlüsseldatei, die in der Produktionsumgebung verwendet werden soll. Kopieren Sie sie in das Zertifikatsverzeichnis /Public/cer. Der nächste Schritt besteht darin, dieses Zertifikat auf die Website des Händlerservices hochzuladen.

4.2 Laden Sie das Zertifikat auf die Händlerservice-Website hoch. Melden Sie sich an: https://merchant.unionpay.com/portal/login.jsp
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay
Laden Sie die Datei acp_prod_sign.pfx hoch, die Sie gerade exportiert haben, und klicken Sie auf Hochladen.

Aktivieren Sie im nächsten Schritt das Zertifikat, klicken Sie auf „Sicherheitszertifikatverwaltung“ und aktivieren Sie es.
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

Im nächsten Schritt laden Sie den öffentlichen UnionPay-Schlüssel herunter
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay
Entpacken Sie die Datei und legen Sie die beiden darin enthaltenen Zertifikate in /Public/cer ab. Gehen Sie dann zu config.php und wechseln Sie gemäß den Dateikommentaren in die Produktionsumgebung.

Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

Das Folgende sind die Codeinformationen von TP3.2:
/App/Home/Conf/config.php

<?phpreturn  array(    //&#39;配置项&#39;=>'配置值'

    'UNIONPAY' => array(// 银联配置
                //测试环境参数
                'frontUrl' => 'https://101.231.204.80:5000/gateway/api/frontTransReq.do', //测试环境前台交易请求地址
                //'frontUrl' => 'https://gateway.95516.com/gateway/api/frontTransReq.do', //生产环境前台交易请求地址

                'singleQueryUrl' => 'https://101.231.204.80:5000/gateway/api/backTransReq.do', //测试环境单笔查询请求地址
                //'singleQueryUrl' => 'https://gateway.95516.com/gateway/api/queryTrans.do', //生产环境单笔查询请求地址

                'signCertPath' =>getcwd().'/Public/cer/acp_test_sign.pfx', //签名证书路径 这个证书就是你在https://open.unionpay.com/ajweb/account/testPara 上面下载的那个商户私钥证书 供你测试使用 
                //'signCertPath' =>getcwd().'/Public/cer/acp_prod_sign.pfx', //签名证书路径 这个证书就是你在 商户开通邮件里面叫你去 http://cs.cfca.com.cn/ 下载并把私钥上传至商户服务网站并启用的那个私钥文件

                'signCertPwd' => '000000', //测试环境签名证书密码
                //'signCertPwd' => '135246', //生产环境证书签名证书密码 这个密码是你在IE导出上述私钥文件时候你自己定义的6位数字密码 

                //'verifyCertPath' => getcwd().'/Public/cer/verify_sign_acp.cer', //测试环境验签证书路径
                'verifyCertPath' => getcwd().'/Public/cer/acp_prod_verify_sign.cer', //验签证书路径

                'merId' => '777290058138754', //测试商户代码
                //'merId' => '8024400481****', //生产环境商户代码 从你的商户开通邮件里面有


        ),        'UNIONPAY_CONFIG'=>array(// 银联配置
                'version' => '5.0.0', //版本号
                'encoding' => 'GBK', //编码方式
                'signMethod' => '01', //签名方式
                'txnType' => '01', //交易类型
                'txnSubType' => '01', //交易子类
                'bizType' => '000201', //产品类型
                'channelType' => '07',//渠道类型
                'frontUrl' => "http://win2.qbt8.com/ase_admin/index.php/Home/ypay/pay_success", //前台通知地址
                'backUrl' => "http://win2.qbt8.com/ase_admin/index.php/Home/ypay/notify", //后台通知地址
                'frontFailUrl' => "http://win2.qbt8.com/ase_admin/index.php/Home/ypay/pay_fail", //失败交易前台跳转地址
                'accessType' => '0', //接入类型
                'merId' => '777290058138754', //测试商户代码
                //'merId' => '8024400481*****', //生产环境商户代码
                'txnTime' => date('YmdHis'), //订单发送时间
                'currencyCode' => '156', //交易币种
        ),
);?>

Der Controller Der Code lautet wie folgt:

<?php /*
|-------------------------------------------------------------|
|                       银联在线支付控制器
|author:shuguang  date:2016-11-16 |-------------------------------------------------------------|
*/

namespace Home\Controller;
use Think\Controller;

class YpayController extends Controller
{
    /**
     * 支付配置
     * @var array
     */
    public $config = array();
    /**
     * 支付参数,提交到银联对应接口的所有参数
     * @var array
     */
    public $params = array();
    /**
     * 自动提交表单模板
     * @var string
     */
    private $formTemplate = <<<HTML
        <!DOCTYPE HTML>
        
        
                <meta>
                <title>支付</title>
        
        
                <p>跳转中...</p>
                
                        %s                 
                <script> document.onreadystatechange = function(){ if(document.readyState == "complete") { document.pay_form.submit(); } }; </script>                   HTML;     public function index(){         //前台表单        $this->display();     }     /*支付成功后 前台通知地址*/     public function pay_success(){        echo "

支付成功!

";     }     /*失败交易前台跳转地址*/     public function pay_fail(){        echo "

支付失败!

";     }     /*生产支付参数 提交支付 */     function usespay(){        $this->config = C('UNIONPAY');//从配置里读取          $config = C('UNIONPAY_CONFIG');        $config['certId']  = $this->getSignCertId(); //证书ID        $config['orderId'] = mt_rand(111111111,999999999);//订单号 自定义          $config['txnAmt']  = I("post.money")*100; //交易金额,单位分        $this->params = $config;                 // $_SESSION['ceshi']=$config;         /* 以下是自己的业务逻辑操作 生产支付记录到本地数据库          $money = I("post.money");;        $user_id = $this->user_id;        $OrderId = $config['orderId'];//生成随机订单号        $pay_type = "银联";//支付方式 1余额 2支付宝        $pay_fee = M('handfee')->find(2);        if ($pay_fee['type'] == 1){            $fee=$pay_fee['rate']*$money;         }else {            $fee=$pay_fee['fee'];         }         //订单表数据        $order = array(                "order_id"=>$OrderId,                "uid"=>$user_id,                "pay_mode"=>1,                "pay_channels"=>2,                "fee"=>$fee,                "status"=>0,//待审核                "beizhu"=>"银联在线充值",                "ent_money"=>$money-$fee,                "time"=>time(),                "sub_time"=>time(),                "pay_money"=>$money,                "pay_type"=>$pay_type,//1余额支付 2支付宝支付                 //"type"=>2         );*/         //$Ord=M('pay');         //$Ord->add($order);        $html = $this->createPostForm();//构建自动提交HTML表单        echo $html;     }     function ceshi(){         dump($_SESSION);     }     function usernotify(){// 付款后返回商家     }     function notify(){//后台通知路径         /*付款后业务逻辑代码  */        $orderId = $_POST ['orderId']; //其他字段也可用类似方式获取        $respCode = $_POST ['respCode']; //判断respCode=00或A6即可认为交易成功        if ($respCode=='00'||$respCode=='A6'){             /*通过写入文件的方式记录返回的订单号等 */            $str = "--------- ".date('Y-m-d H:i:s')." ---------";            $str .= "orderId:".$orderId."\r\n";            $str .= "respCode:".$respCode."\r\n";            $str .= "--------- END -----------"."\r\n";             file_put_contents('unionpay_notify_log.log', $str);             /* 以下是支付成功后的数据库操作 请根据需要自行操作              $order['status']=1;            $order['check_time']=time();             M('pay')->where(array('order_id'=>$orderId))->save($order);              $order_info = M('pay')->where(array('order_id'=>$orderId))->find();               $log['user_id']=$order_info['uid'];            $log['user_money']=$order_info['pay_money'];            $log['change_time']=time();            $log['desc']="银联在线充值";             M('account_log')->add($log);             M('users')->where('user_id='.$order_info['uid'])->setInc('user_money',$order_info['ent_money']);             */         }     }     function unionpayfail(){     }    /*  function orderPay($orderinfo,$state){        $filename = 'Log/yapy';                 file_put_contents($filename.'/'.$orderinfo['orderId'].'.txt', json_encode($_POST), FILE_APPEND);         //$order = D('order');         //$payment = D('payment');         //$where['order_sn'] = array('in', array($orderinfo['orderId']));         //$orinfo = $order->where($where)->find();        $rs = $payment->where($where)->find();        if (empty($rs) && $orinfo['order_state']  json_encode($where1))), true);            $data1['order_state'] = (int) $state;             //$orderwhere['order_sn'] = array('in', array($orderinfo['orderId']));             //$order->where($orderwhere)->save($data1);            if($orinfo['balance'] >0 && $orinfo['isblance'] == 1){                if($userinfo1[0]['balance']-$orinfo['balance']>=0){                    $total1 = $total1-$data['balance'];                    $istrue = req_api("api_key", C("API_KEY"), C('USER_API') . "user/api/removeBalance/", array('user' =>session('id'),'count'=>$orinfo['balance'],'type'=>'d'));                     //$this->BanlanceRecord(2,$orinfo['balance'],'购物消费',session('id'));                 }             }            if ($orinfo['jindou'] >0 && $orinfo['isjindou'] == 1) {                if($userinfo1[0]['user_wealth']-$orinfo['jindou']>=0){                    $istrue = req_api("api_key", C("API_KEY"), C('USER_API') . "user/api/AddJindou/", array('user' =>session('id'),'count'=>$orinfo['jindou'],'type'=>'d'));                    $this->ChangeRecord(2,$orinfo['jindou'],'购物抵消',session('id'));                    $total1 = $total1-($orinfo['jindou']/100);                 }             }            $data['order_sn'] = $orderinfo['orderId'];            $data['buyer_id'] = $orderinfo['certId'];            $data['buyer_user'] = '银联支付';            $data['is_success'] = 'T';            $data['notify_time'] = substr($orderinfo['txnTime'],0,4)."-".substr($orderinfo['txnTime'],4,2).'-'.substr($orderinfo['txnTime'],6,2).' '.substr($orderinfo['txnTime'],8,2).':'.substr($orderinfo['txnTime'],10,2).':'.substr($orderinfo['txnTime'],12,2);            $data['trade_no'] = $orderinfo['queryId'];            $data['seller_id'] = $orderinfo['merId'];            $data['total_fee'] = $orderinfo['txnAmt']*100;            $data['sign'] = $orderinfo['signature'];            $data['user_id'] = $orinfo['user_id'];            $data['order_state'] = (int) $state;            $data['status'] = 0;            $payment->data($data)->filter('strip_tags')->add();         }        $record = A('Shop/Orderrecord');        $shuju['order_state'] = (string) $state;        $shuju['action_user_id'] = session('id');        $shuju['action_descrption'] = $type.'支付宝付款' . $orinfo['payable_total'];        $record->ChangeOrderRecords($orinfo['_id'], $shuju);        $orderrecord = A('Shop/Order');        $orderrecord->CashMoneyRecord(2, $orinfo['payable_total'], '购物消费--订单(' . $orderinfo['out_trade_no'] . ')', session('id'));         layout(false);        $this->assign('orderinfo', $orinfo);        $this->display('Order:PaySuccess6');     } */     /**     * 构建自动提交HTML表单     * @return string     */     public function createPostForm()     {        $this->params['signature'] = $this->sign();        $input = '';         foreach($this->params as $key => $item) {                $input .= "\t\t\n";         }        return sprintf($this->formTemplate, $this->config['frontUrl'], $input);     }     /**     * 验证签名     * 验签规则:     * 除signature域之外的所有项目都必须参加验签     * 根据key值按照字典排序,然后用&拼接key=value形式待验签字符串;     * 然后对待验签字符串使用sha1算法做摘要;     * 用银联公钥对摘要和签名信息做验签操作     *     * @throws \Exception     * @return bool     */     public function verifySign()     {        $publicKey = $this->getVerifyPublicKey();        $verifyArr = $this->filterBeforSign();         ksort($verifyArr);        $verifyStr = $this->arrayToString($verifyArr);        $verifySha1 = sha1($verifyStr);        $signature = base64_decode($this->params['signature']);        $result = openssl_verify($verifySha1, $signature, $publicKey);        if($result === -1) {                // throw new \Exception('Verify Error:'.openssl_error_string());            echo 'Verify Error:'.openssl_error_string();         }        return $result === 1 ? true : false;     }     /**     * 取签名证书ID(SN)     * @return string     */     public function getSignCertId()     {            return $this->getCertIdPfx($this->config['signCertPath']);     }       /**     * 签名数据     * 签名规则:     * 除signature域之外的所有项目都必须参加签名     * 根据key值按照字典排序,然后用&拼接key=value形式待签名字符串;     * 然后对待签名字符串使用sha1算法做摘要;     * 用银联颁发的私钥对摘要做RSA签名操作     * 签名结果用base64编码后放在signature域     *     * @throws \InvalidArgumentException     * @return multitype|string     */     private function sign() {        $signData = $this->filterBeforSign();         ksort($signData);        $signQueryString = $this->arrayToString($signData);        if($this->params['signMethod'] == 01) {                 //签名之前先用sha1处理                 //echo $signQueryString;exit;                $datasha1 = sha1($signQueryString);                $signed = $this->rsaSign($datasha1);         } else {                 //throw new \InvalidArgumentException('Nonsupport Sign Method');            echo 'Nonsupport Sign Method';         }        return $signed;     }     /**     * 数组转换成字符串     * @param array $arr     * @return string     */     private function arrayToString($arr)     {        $str = '';         foreach($arr as $key => $value) {                $str .= $key.'='.$value.'&';         }        return substr($str, 0, strlen($str) - 1);     }     /**     * 过滤待签名数据     * signature域不参加签名     *     * @return array     */     private function filterBeforSign()     {        $tmp = $this->params;        unset($tmp['signature']);        return $tmp;     }     /**     * RSA签名数据,并base64编码     * @param string $data 待签名数据     * @return mixed     */     private function rsaSign($data)     {        $privatekey = $this->getSignPrivateKey();        $result = openssl_sign($data, $signature, $privatekey);        if($result) {                return base64_encode($signature);         }        return false;     }     /**     * 取.pfx格式证书ID(SN)     * @return string     */     private function getCertIdPfx($path)     {        $data = fopen($path);        $pkcs12certdata = file_get_contents($path);         openssl_pkcs12_read($pkcs12certdata, $certs, $this->config['signCertPwd']);        $x509data = $certs['cert'];         openssl_x509_read($x509data);        $certdata = openssl_x509_parse($x509data);        return $certdata['serialNumber'];     }     /**     * 取.cer格式证书ID(SN)     * @return string     */     private function getCertIdCer($path)     {        $x509data = file_get_contents($path);         openssl_x509_read($x509data);        $certdata = openssl_x509_parse($x509data);        return $certdata['serialNumber'];     }     /**     * 取签名证书私钥     * @return resource     */     private function getSignPrivateKey()     {        $pkcs12 = file_get_contents($this->config['signCertPath']);         openssl_pkcs12_read($pkcs12, $certs, $this->config['signCertPwd']);        return $certs['pkey'];     }     /**     * 取验证签名证书     * @throws \InvalidArgumentException     * @return string     */     private function getVerifyPublicKey()     {         //先判断配置的验签证书是否银联返回指定的证书是否一致        if($this->getCertIdCer($this->config['verifyCertPath']) != $this->params['certId']) {                // throw new \InvalidArgumentException('Verify sign cert is incorrect');            echo 'Verify sign cert is incorrect';         }        return file_get_contents($this->config['verifyCertPath']);           } }

Der Inhalt der Ansichtsdatei lautet wie folgt:

nbsp;html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <meta>
    <title>银联支付测试</title>
    <h1>银联支付测试</h1>
    
        支付金额:              

Die Zertifikatsdatei kann hier nicht hochgeladen werden. Fügen Sie einfach einen Screenshot ein und Sie können ihn herunterladen selbst:
Entwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay

Verwandte Empfehlungen:

Bank of Communications Online-Banking Online-Zahlungsschnittstelle ECSHOP-Plug-in und in PHP implementierte Anwendungsbeispiele

Das obige ist der detaillierte Inhalt vonEntwicklungsbeispiel der Online-Zahlungsschnittstelle PHP UnionPay. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn