• TP3.2.3 接入银联支付


    TP3.2.3 接入银联支付

        项目接入银联支付的过程, 在此记录下,希望能帮助开发盆友平坑。

        银联SKD链接:https://open.unionpay.com/ajweb/product/newProDetail?proId=1&cataId=14

        首先我们先下载官方提供的SDK  ,下载好了解压选择版本 ,里面有PHP  java  .net  这里我们自然是选择PHP版本的,接入前我们先配环境,它要我们PHP

      的版本 在5.3以上,并且需开启环境的curl、openssl功能。

       然后就是它提供的测试证书了,默认在window系统是放在D:/certs ,意思是在你的电脑的D创建一个名为certs 的文件夹,然后将4个证书放进去,测试的名为

      acp_test_enc.cer  acp_test_middle.cer  acp_test_root.cer  acp_test_sign.pfx ,在创建一个名为logs文件夹D:/logs/  放支付生成的日志文件,linux中请

     修改成Linux中的路径。

      如图:

      

        你可以在assets文件夹中找到你要的证书,测试环境官方提供四个证书,生产环境官方提供三个,还个签名证书就是后缀为.pfx 的需要你去你的银联那里申请

      下载对应的你还需要可以需要解签名证书的密码 和商户号 , 这些后面都会提到的。

        在然后我们将名为SDK文件夹中的六个文件放到我们项目放到 ThinkPHPLibraryVendorYunpay 的文件夹中

        

         写逻辑代码前你还得前配置好你的acp_sdk.ini 文件 ,文件里面都写的很清楚,这里就不一一解释了,这里是我的支付代码

        

    //银联充值操作
        public function pay()
        {
            header ( 'Content-type:text/html;charset=utf-8' );
            Vendor('Yunpay.acp_service');
    
            //前台通知地址
            $frontUrl = "http://".I("server.HTTP_HOST")."/Assets/rechargedetail";
            //后台通知地址
            $backUrl = "http://".I("server.HTTP_HOST");
            $params = array(
                //以下信息非特殊情况不需要改动
                'version' => comunionpayacpsdkSDKConfig::getSDKConfig()->version,          //版本号
                'encoding' => 'utf-8',                                                              //编码方式
                'txnType' => '01',                                                                  //交易类型
                'txnSubType' => '01',                                                              //交易子类
                'bizType' => '000201',                                                              //业务类型
                'frontUrl' =>  $frontUrl,                                                          //前台通知地址
                'backUrl' =>   $backUrl,                                                          //后台通知地址
                'signMethod' => comunionpayacpsdkSDKConfig::getSDKConfig()->signMethod,    //签名方法
                'channelType' => '08',                                                             //渠道类型,07-PC,08-手机
                'accessType' => '0',                                                                //接入类型
                'currencyCode' => '156',    
                 // 超过超时时间调查询接口应答origRespCode不是A6或者00的就可以判断为失败。
                   'payTimeout' => date('YmdHis', strtotime('+15 minutes'))                         //订单发送时间
            );
            $txnAmt = I('post.txnAmt');    //交易金额
            $orderId = I('post.orderId');  //商户订单号
    
            //加入商户参数
            $params['txnAmt'] = $txnAmt*100;
            $params['merId'] = C('Yunpay.merId');    //商户号
            $params['orderId'] = $orderId;
            $params['txnTime'] = date('YmdHis');
    
            //商品描述,可空
            $body = trim(I('post.WIDbody'));
            $ud = session('users.uid');
            $data = array(
                    'uid'=>$ud,                                  //用户id
                    'win_code'=>$orderId,                     //商户订单号
                    'winsubject'=>I('post.WIDsubject'),          //订单名称
                    'wintotal_amount'=>$txnAmt,                //付款金额
                    'winbody'=>I('post.WIDbody'),             //商品描述
                    'state'=>'yl',                              //支付方式
                    'status'=>'0',                              //是否支付
                    'ordertime'=>time()                          //交易时间
                );
            M("pay_record")->add($data); // 保存交易信息
            comunionpayacpsdkAcpService::sign ( $params );
            $uri = comunionpayacpsdkSDKConfig::getSDKConfig()->frontTransUrl;
            $html_form = comunionpayacpsdkAcpService::createAutoFormHtml( $params, $uri );
            echo $html_form;
        
        }

        这里我曾试过删除里面的命名空间用 new的方式去写,这样可以简洁代码,但是后面异步的时候报错,客服说不能删除命名空间,这样会导致方法名重复,所以还是乖乖的用demo

      中提供的方法。

        异步方法--------

        

      1     //银联充值异步
      2     public function xxx()
      3     {    
      4         Vendor('Yunpay.acp_service');
      5         $logger = comunionpayacpsdkLogUtil::getLogger();
      6         $logger->LogInfo("receive back notify: " . comunionpayacpsdkcreateLinkString ( $_POST, false, true ));
      7         if (isset ( $_POST ['signature'] )) {
      8                 // echo comunionpayacpsdkAcpService::validate ( $_POST ) ? '验签成功' : '验签失败';
      9                 $respCode = I('post.respCode');
     10                 $orderId = I('post.orderId');         // 商户订单号
     11                 $total_amount = I('post.settleAmt'); //订单金额
     12                 $trade_no = I('post.queryId');         // queryId 银联唯一标识一笔交易
     13 
     14                 //判断respCode=00、A6后,对涉及资金类的交易,请再发起查询接口查询,确定交易成功后更新数据库。
     15                 if( $respCode=='00' ){
     16                      $this->unionpay($orderId,$total_amount,$trade_no);
     17                 }else{
     18                      $res = $this->confirmpay($orderId,'1');
     19                         if( $res == 'Successful' ){
     20                             $this->unionpay($orderId,$total_amount,$trade_no);
     21                      } else {
     22                             echo '交易失败';
     23                      }
     24                 }
     25 
     26         } else {
     27             echo '签名为空';
     28         }
     29 
     30 
     31     }
     32 
     33 
     34     //银联充值
     35     public function unionpay($orderId,$total_amount,$trade_no)
     36     {
     37         $per = M("pay_record")->where('win_code='.$orderId)->find(); //查找该订单
     38         if( $per['status']=='1' ){
     39             echo '已充值';
     40             return;
     41         }
     42         $Pay = M("pay");
     43         // 在Pay模型中启动事务
     44         $Pay->startTrans();            
     45         // 进行相关的业务逻辑操作
     46         $res = $Pay->where('uid='.$per['uid'])->setInc('money',$total_amount/100);
     47         //数据组合
     48         $data = array(
     49                 'alipay_number'=>$trade_no,                  //银联唯一标识
     50                 'status'=>'1',                              //交易状态
     51                 'paytime'=>time()                          //交易时间
     52             );
     53         M("pay_record")->where('win_code='.$orderId)->save($data); // 修改交易信息
     54 
     55         if (!empty($res)){
     56           // 提交事务
     57           $Pay->commit();
     58         }else{
     59           // 事务回滚
     60           $Pay->rollback();
     61         }
     62     }
     63 
     64 
     65     //确定是否充值操作
     66     public function confirmpay($orderId,$L)
     67     {
     68         header ( 'Content-type:text/html;charset=utf-8' );
     69          Vendor('Yunpay.acp_service');
     70          $params = array(
     71             //以下信息非特殊情况不需要改动
     72             'version' => comunionpayacpsdkSDKConfig::getSDKConfig()->version,          //版本号
     73             'encoding' => 'utf-8',          //编码方式
     74             'signMethod' => comunionpayacpsdkSDKConfig::getSDKConfig()->signMethod,          //签名方法
     75             'txnType' => '00',              //交易类型
     76             'txnSubType' => '00',          //交易子类
     77             'bizType' => '000000',          //业务类型
     78             'accessType' => '0',          //接入类型
     79             'channelType' => '07',          //渠道类型
     80         );
     81         if($L == '0'){
     82             $time = M("order_pay")->where('win_code = "'.$orderId.'"')->find()['addtime'];
     83         }else{
     84             $time = M("pay_record")->where('win_code = "'.$orderId.'"')->find()['ordertime'];
     85         }
     86         $params['merId'] = C('Yunpay.merId');       //商户号
     87         $params['orderId'] = $orderId;               //交易的订单号
     88         $params['txnTime'] = date('YmdHis',$time); //订单发送时间
     89 
     90         comunionpayacpsdkAcpService::sign ( $params ); // 签名
     91         $url = comunionpayacpsdkSDKConfig::getSDKConfig()->singleQueryUrl;
     92 
     93         $result_arr = comunionpayacpsdkAcpService::post ( $params, $url);
     94         if(count($result_arr)<=0) { //没收到200应答的情况
     95             return 'No200';
     96         }
     97         if (!comunionpayacpsdkAcpService::validate ($result_arr) ){
     98             return "应答报文验签失败";
     99         }
    100         if ($result_arr["respCode"] == "00"){
    101             if ($result_arr["origRespCode"] == "00"){
    102                 //交易成功
    103                 //TODO
    104                 return "Successful";
    105             } else if ($result_arr["origRespCode"] == "03"
    106                     || $result_arr["origRespCode"] == "04"
    107                     || $result_arr["origRespCode"] == "05"){
    108                 //后续需发起交易状态查询交易确定交易状态
    109                 //TODO
    110                 return "交易处理中,请稍微查询";
    111             } else {
    112                 //其他应答码做以失败处理
    113                 //TODO
    114                 return "交易失败:" . $result_arr["origRespMsg"];
    115             }
    116         } else if ($result_arr["respCode"] == "03"
    117                 || $result_arr["respCode"] == "04"
    118                 || $result_arr["respCode"] == "05" ){
    119             //后续需发起交易状态查询交易确定交易状态
    120             //TODO
    121             return "处理超时,请稍微查询";
    122         } else {
    123             //其他应答码做以失败处理
    124             //TODO
    125             return "失败:" . $result_arr["respMsg"];
    126         }
    127 
    128     }

        这里第一个方法xxx 中的respCode等于00 就是支付成功 ,如果没有需要根据你生成的订单号在次查询在结果。这里客服说这种失败不好模拟,就不说了,但是这操作方法还是

      建议写下,以防万一 。

        最后说明下几个参数 queryId  银联唯一标识,需要保存, 还有银联支付是按 '分' 做单位的 所以支付跳转前  假如是1元,你得乘以100,它才可以识别为1元,要不然就是0.01元

      然后异步到你的时候,如果你是元的单位在除于100,如果是分就不用了。

        搞定收工 , 祝大家早日成为大牛

      

        

        

      

      

      

  • 相关阅读:
    关于 控制反转与依赖注入 对初学者的一点帮助
    转载--文章(感谢米粒儿博主分享) 关于 Json.net序列化时间问题
    转载--文章(感谢陈晨博主分享) 关于 Json.net
    B-JUI框架使用探究
    什么是Entity Framework(ORM)
    字典
    Docker部署Linux+Nginx+Mariadb+PHP环境
    Docker部署Django+nginx+uwsgi环境
    Docker部署Django+apache+mod_wsgi环境
    Docker容器技术
  • 原文地址:https://www.cnblogs.com/liubaoqing/p/8004176.html
Copyright © 2020-2023  润新知