• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

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

php 搞代码 3年前 (2022-01-22) 31次浏览 已收录 0个评论

本文主要和大家分享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>        &l<strong style="color:transparent">来2源gaodaima#com搞(代@码&网</strong><label>搞gaodaima代码</label>t;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银联在线支付接口的开发实例的详细内容,更多请关注搞代码gaodaima其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:PHP银联在线支付接口的开发实例

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址