Maison  >  Article  >  développement back-end  >  Exemple de développement de l'interface de paiement en ligne PHP UnionPay

Exemple de développement de l'interface de paiement en ligne PHP UnionPay

小云云
小云云original
2018-03-01 13:48:1212182parcourir

Cet article partage principalement avec vous les exemples de développement de l'interface de paiement en ligne PHP UnionPay, en espérant aider tout le monde.

1. Connectez-vous à la plateforme de test en libre-service UnionPay (adresse de connexion : open.unionpay.com) Après vous être connecté, cliquez sur Mes produits, comme suit : Cliquez sur l'interface à tester sur le site. à droite Dans cet exemple, le paiement s'effectue sur la page web mobile (paiement WAP) à titre d'exemple.

Exemple de développement de linterface de paiement en ligne PHP UnionPay
Exemple de développement de linterface de paiement en ligne PHP UnionPay
2. Cliquez sur les paramètres de test dans le menu de gauche pour voir les paramètres requis pour le processus de test, comme indiqué ci-dessous : Cliquez sur le certificat de test pour télécharger deux certificats. L'un est un certificat de clé privée avec le suffixe .pfx et l'autre est un certificat de clé publique avec le suffixe .cer. Après les avoir téléchargés, le nom du fichier de certificat de clé privée est modifié en acp_test_sign.pfx. Ou si vous ne le téléchargez pas, vous pouvez simplement utiliser cet exemple directement. Dans l'exemple TP3.2, il y a tous les fichiers de certificat dans Public/cer.
Exemple de développement de linterface de paiement en ligne PHP UnionPay

3. L'exemple TP3.2 contient un code pertinent qui peut être utilisé pour les tests. Veuillez utiliser les paramètres de l'environnement de test lors des tests. Il y a des commentaires dans le code. Avant de commencer, assurez-vous que la version PHP de votre environnement est basée sur 5.3. Vous devez activer les fonctions curl et openssl, et le test doit être effectué en ligne. Les noms de domaines virtuels locaux ne fonctionneront pas. Si vous rencontrez des problèmes, vous pouvez vous référer aux instructions officielles. Il y a un SDK de version PHP dans ce dossier, qui est un document officiel. Reportez-vous simplement aux instructions à l'intérieur. Leur exemple n'a pas pu s'exécuter lorsque je l'ai testé. Je ne sais pas ce qui s'est passé.
4. Passez à l'environnement de production et faites attention aux problèmes suivants :
4.1 Tout d'abord, selon les instructions contenues dans l'e-mail d'activation du commerçant que vous avez reçu, visitez le site Web http://cs.cfca.com.cn. /
Téléchargez le fichier du certificat de production :
Exemple de développement de linterface de paiement en ligne PHP UnionPay
Après avoir cliqué sur télécharger, après avoir terminé l'opération de téléchargement, une invite de téléchargement réussi apparaîtra sur la page. Le certificat téléchargé est automatiquement stocké dans IE. L'étape suivante consiste à exporter le certificat.
Exemple de développement de linterface de paiement en ligne PHP UnionPay
4.2 Exporter le fichier de certificat : ouvrez le navigateur IE, cliquez sur l'engrenage dans le coin supérieur droit, ouvrez Tools=》Internet Options=》Content=》Certificate, comme indiqué dans l'image :
Exemple de développement de linterface de paiement en ligne PHP UnionPay

Après avoir cliqué sur le certificat, retrouvez le certificat que vous venez de télécharger. Vous pouvez l'identifier par son nom. Il est marqué dans l'email du commerçant :
Exemple de développement de linterface de paiement en ligne PHP UnionPay
Le nom marqué dedans. Le rouge dans l'image ci-dessus doit être le même que le nom que vous avez téléchargé.
Exemple de développement de linterface de paiement en ligne PHP UnionPay
Trouvez-le et cliquez sur Exporter : la prochaine étape du processus, vous devez faire attention aux étapes suivantes

Exemple de développement de linterface de paiement en ligne PHP UnionPay

Exemple de développement de linterface de paiement en ligne PHP UnionPay

Exemple de développement de linterface de paiement en ligne PHP UnionPay

Le mot de passe ci-dessus est le mot de passe à définir dans l'environnement de production dans config.php. Veuillez le définir sur six chiffres (uniquement des chiffres, veuillez ne pas définir de lettres ni de symboles).

Spécifiez Définissez le nom de fichier du certificat exporté sur : acp_prod_sign et sélectionnez un répertoire pour stocker le certificat. Cliquez sur Suivant pour définir l'exportation sur le bureau. Une fois terminé, vous verrez un fichier acp_prod_sign.pfx sur. le bureau. Il s'agit du fichier de clé privée à utiliser dans l'environnement de production. Copiez-le dans le répertoire du certificat /Public/cer. L'étape suivante consiste à télécharger ce certificat sur le site Web du service marchand.

4.2 Téléchargez le certificat sur le site Web du service marchand. Connectez-vous https://merchant.unionpay.com/portal/login.jsp
Exemple de développement de linterface de paiement en ligne PHP UnionPay
Téléchargez le fichier acp_prod_sign.pfx que vous venez d'exporter et cliquez sur Télécharger.

Étape suivante, activez le certificat, cliquez sur Gestion des certificats de sécurité et activez-le.
Exemple de développement de linterface de paiement en ligne PHP UnionPay

Étape suivante, téléchargez la clé publique UnionPay
Exemple de développement de linterface de paiement en ligne PHP UnionPay
Décompressez le fichier et placez les deux certificats à l'intérieur dans /Public/cer. Allez ensuite dans config.php et passez à l'environnement de production en fonction des commentaires du fichier.

Exemple de développement de linterface de paiement en ligne PHP UnionPay

Voici les informations de code de 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', //交易币种
        ),
);?>

Le contrôleur le code est le suivant :

<?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']);           } }

Le contenu du fichier de vue est le suivant :

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>
    
        支付金额:              

Le fichier de certificat ne peut pas être téléchargé ici. Mettez simplement une capture d'écran et vous pouvez le télécharger. vous-même :
Exemple de développement de linterface de paiement en ligne PHP UnionPay

Recommandations associées :

Interface de paiement en ligne bancaire en ligne de Bank of Communications Plug-in ECSHOP et exemples d'utilisation implémentés en PHP

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn