您好,欢迎访问一九零五行业门户网

PHP银联在线支付接口的开发实例

本文主要和大家分享php银联在线支付接口的开发实例,希望能帮助到大家。
1、 登录银联自助化测试平台(登陆地址:open.unionpay.com),登录后,点击我的产品,如下:点击右方需要测试的接口,本例以 手机网页支付(wap支付)为例。
2、 点击左侧菜单 测试参数,即可看到测试过程所需要的参数,如下图:点击测试证书,下载两个证书,一个是以后缀 .pfx 的私钥证书,一个是后缀 .cer 的公钥证书,将其下载后,私钥证书文件名称修改为 acp_test_sign.pfx 。或者你不下载的话,直接用本例子的也可以。tp3.2例子 里面 public/cer 里面已有所有证书文件。
3、 tp3.2例子里面已有相关代码可以用来测试,测试的时候请使用测试环境的参数,代码中均有注释。在开始之前要确保你的环境php版本基于5.3,需开启curl、openssl功能,还有测试要放在线上测试,本地的虚拟域名是不行的。如遇到什么问题,可以参考官方的说明,本文件夹里面有个 php version sdk 是官方的文档,参考里面的说明就好了,他们那个例子我测试的时候也跑不起来,不知道什么鬼原因。 
4、 切换到生产环境,注意以下问题: 
4.1 首先根据你收到的商户开通邮件里面的指示,访问网站 http://cs.cfca.com.cn/ 
下载生产证书文件:
点击下载后,完成下载操作后,页面会出现下载成功的提示。下载的证书自动存放在ie中,下一步就要进行证书的导出。
4.2 导出证书文件:打开ie浏览器,点击右上角的齿轮,打开工具=》internet选项=》内容=》证书,如图:
点击证书后,找到刚刚下载的那个证书,你可以根据名称去辨别,商户邮件中有标注:
上图中红色标注的名称应该跟你下载的那个名称一样。
找到它,然后点击导出:一路的下一步,在以下几步需要注意
以上密码就是 config.php 里面生产环境要设置的那个密码,请设置为六位数字(仅限数字,请勿设置字母及符号)
指定导出证书的文件名,名称就设置为:acp_prod_sign,并选择目录存放证书,点击下一步,设置导出到桌面,完成后将在桌面看到一个 acp_prod_sign.pfx 的文件。这个就是生产环境要用到的私钥文件,将它复制一份到证书目录 /public/cer 。下一步就要上传这个证书到商户服务网站。
4.2 上传证书到商户服务网站。登录 https://merchant.unionpay.com/portal/login.jsp
上传刚刚导出的那个 acp_prod_sign.pfx 文件,点击上传。
下一步,启用证书,点击安全证书管理,启用即可。
下一步,下载银联公钥
解压文件,把里面的两个证书同样放到 /public/cer 里面。然后就去 config.php 里面根据文件注释切换到生产环境即可。
以下是tp3.2的代码资料: 
/app/home/conf/config.php
<?phpreturn array( //'配置项'=>'配置值'     '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', //交易币种         ), );?>
控制器代码如下:
<?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>         <html>         <head>                 <meta charset="utf-8">                 <title>支付</title>         </head>         <body>                 <p style="text-align:center">跳转中...</p>                 <form id="pay_form" name="pay_form" action="%s" method="post">                         %s                 </form>                 <script type="text/javascript">                         document.onreadystatechange = function(){                                if(document.readystate == complete) {                                         document.pay_form.submit();                                 }                         };                 </script>         </body>         </html> html;     public function index(){         //前台表单        $this->display();     }     /*支付成功后 前台通知地址*/     public function pay_success(){        echo <h1>支付成功!</h1>;     }     /*失败交易前台跳转地址*/     public function pay_fail(){        echo <h1>支付失败!</h1>;     }     /*生产支付参数 提交支付 */     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'] < 2 ) { $where1['udb_user.user_id'] = array('eq', session('id')); $userinfo1 = json_decode(req_api("api_key", c("api_key"), c('user_api') ."user/api/getsomeuser/", array('where' => 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<input type=\"hidden\" name=\"{$key}\" value=\"{$item}\">\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']);           } }
视图文件内容如下:
<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head>     <meta http-equiv="content-type" content="text/html;charset=utf-8" />     <title>银联支付测试</title></head><body>     <h1>银联支付测试</h1>     <form action="{:u('ypay/usespay')}" method="post">         支付金额:<input type="text" name="money" value="0.1" />         <input type="submit" value="确定支付" />     </form></body></html>
证书文件这里上传不了,放个截图好了,都可以自己去下载的:
相关推荐:
php实现的交通银行网银在线支付接口ecshop插件和使用例子
以上就是php银联在线支付接口的开发实例的详细内容。
其它类似信息

推荐信息