>  기사  >  백엔드 개발  >  PHP UnionPay 온라인 결제 인터페이스 개발 사례

PHP UnionPay 온라인 결제 인터페이스 개발 사례

小云云
小云云원래의
2018-03-01 13:48:1212182검색

이 기사에서는 모든 사람에게 도움이 되기를 바라며 주로 PHP UnionPay 온라인 결제 인터페이스의 개발 사례를 공유합니다.

1. UnionPay 셀프 서비스 테스트 플랫폼(로그인 주소: open.unionpay.com)에 로그인합니다. 로그인 후 다음과 같이 내 제품을 클릭합니다. 오른쪽에서 테스트할 인터페이스를 클릭합니다. 예를 들어, 모바일 웹 결제(WAP 결제)가 예시입니다.

PHP UnionPay 온라인 결제 인터페이스 개발 사례
PHP UnionPay 온라인 결제 인터페이스 개발 사례
2 왼쪽 메뉴에서 테스트 매개변수를 클릭하면 아래와 같이 테스트 프로세스에 필요한 매개변수가 표시됩니다. 테스트 인증서를 클릭하고 두 개의 인증서를 다운로드합니다. 하나는 접미사가 붙은 개인 키 인증서입니다. .pfx, 기타 확장자가 .cer인 공개키 인증서입니다. 다운로드 후 개인키 인증서 파일 이름이 acp_test_sign.pfx로 변경됩니다. 또는 다운로드하지 않은 경우 이 예제를 직접 사용할 수도 있습니다. TP3.2 예에서는 Public/cer에 모든 인증서 파일이 있습니다.
PHP UnionPay 온라인 결제 인터페이스 개발 사례

3. TP3.2 예제에는 테스트에 사용할 수 있는 관련 코드가 있습니다. 테스트할 때 테스트 환경의 매개변수를 사용하세요. 시작하기 전에 환경의 PHP 버전이 5.3을 기반으로 하는지 확인하십시오. 컬 및 openssl 기능을 활성화해야 하며 테스트는 온라인으로 수행되어야 합니다. 문제가 발생하면 공식 문서인 PHP 버전 SDK를 참조하세요. 테스트할 때 해당 예제가 실행되지 않습니다. 무슨 일이 일어났는지 모르겠어요.
4. 프로덕션 환경으로 전환하고 다음 문제에 주의하세요.
4.1 먼저 받은 판매자 활성화 이메일의 지침에 따라 웹사이트 http://cs.cfca.com.cn/을 방문하세요.
다운로드 생산 인증서 파일:
PHP UnionPay 온라인 결제 인터페이스 개발 사례
다운로드를 클릭한 후 다운로드 작업이 완료되면 페이지에 다운로드 성공 메시지가 나타납니다. 다운로드한 인증서는 IE에 자동으로 저장됩니다. 다음 단계는 인증서를 내보내는 것입니다.
PHP UnionPay 온라인 결제 인터페이스 개발 사례
4.2 인증서 파일 내보내기: IE 브라우저를 열고 오른쪽 상단의 기어를 클릭한 후 도구 = "인터넷 옵션 =" ​​Content = "인증서를 엽니다. 그림과 같이:
PHP UnionPay 온라인 결제 인터페이스 개발 사례

를 클릭한 후 인증서, 방금 다운로드한 인증서를 찾으세요. 판매자 이메일에 표시된 이름으로 식별할 수 있습니다.
PHP UnionPay 온라인 결제 인터페이스 개발 사례
위 사진에서 빨간색으로 표시된 이름은 다운로드한 인증서와 동일해야 합니다.
PHP UnionPay 온라인 결제 인터페이스 개발 사례
찾아서 내보내기 클릭: 다음 단계에서는 다음 단계에 주의해야 합니다

PHP UnionPay 온라인 결제 인터페이스 개발 사례

PHP UnionPay 온라인 결제 인터페이스 개발 사례

PHP UnionPay 온라인 결제 인터페이스 개발 사례

위 비밀번호는 프로덕션 환경에서 설정하는 비밀번호입니다. config.php를 6자리로 설정하세요(숫자만, 문자 및 기호는 설정하지 마세요)

내보낸 인증서의 파일 이름을 지정하세요. 이름은 acp_prod_sign으로 설정되고 인증서를 저장할 디렉터리를 선택하세요. 다음을 클릭하여 설정을 바탕 화면으로 내보냅니다. 완료되면 바탕 화면에 acp_prod_sign.pfx 파일이 표시됩니다. 프로덕션 환경에서 사용할 개인 키 파일을 인증서 디렉터리 /Public/cer에 복사합니다. 다음 단계는 이 인증서를 판매자 서비스 웹사이트에 업로드하는 것입니다.

4.2 가맹점 서비스 홈페이지에 인증서를 업로드하세요. 로그인 https://merchant.unionpay.com/portal/login.jsp
PHP UnionPay 온라인 결제 인터페이스 개발 사례
방금 내보낸 acp_prod_sign.pfx 파일을 업로드하고 업로드를 클릭합니다.

다음 단계에서는 인증서를 활성화하고 보안 인증서 관리를 클릭한 후 활성화하세요.
PHP UnionPay 온라인 결제 인터페이스 개발 사례

다음 단계에서는 UnionPay 공개 키를 다운로드합니다.
PHP UnionPay 온라인 결제 인터페이스 개발 사례
파일의 압축을 풀고 두 개의 인증서를 /Public/cer에 넣습니다. 그런 다음 config.php로 이동하여 파일 설명에 따라 프로덕션 환경으로 전환합니다.

PHP UnionPay 온라인 결제 인터페이스 개발 사례

다음은 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', //交易币种
        ),
);?>

컨트롤러 코드는 다음과 같습니다.

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

뷰 파일의 내용은 다음과 같습니다.

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

인증서 파일은 여기에 업로드할 수 없습니다. 다음은 스크린샷입니다. 직접 다운로드할 수 있습니다.
PHP UnionPay 온라인 결제 인터페이스 개발 사례

관련 권장 사항:

Bank of Communications 온라인 뱅킹 온라인 결제 인터페이스 ECSHOP 플러그인 및 PHP로 구현된 사용 예

위 내용은 PHP UnionPay 온라인 결제 인터페이스 개발 사례의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.