重新对百度支付进行编写封装(百度智能小程序支付)

 4662

最近因为项目重构的原因,对百度支付重新进行了编写封装,本次重写,添加了对签名的处理、添加用户退款,方便之后开发的使用。


因为百度电商开放平台的升级,支付功能已移至智能小程序内部。

具体申请流程:百度收银台支付开通指引,(https://smartprogram.baidu.com/docs/operations/transform/pay/)

(注:在支付服务中,服务电话应填写银行预留手机号,如填写错误报【银行预留手机号码格式校验不通过】)

百度支付文档:百度收银台接口2.0(https://smartprogram.baidu.com/docs/develop/function/tune_up_2.0/)


一、申请通过后,填写百度支付相关配置:

  1. $config = array(
  2.     'deal_id'       => '', // 百度收银台的财务结算凭证
  3.     'app_key'       => '', // 表示应用身份的唯一ID
  4.     'private_key'   => '', // 私钥原始字符串
  5.     'public_key'    => '', // 平台公钥
  6.     'notify_url'    => '', // 支付回调地址
  7. );


二、调用封装的支付方法,将返回信息,传递到百度小程序

  1. <?php
  2. include './BaiduPay.php';
  3. $baidupay = new \feng\BaiduPay($config);
  4. $order_sn = time().rand(1000,9999);
  5. $order = array(
  6.     'body'          => '测试商品', // 产品描述
  7.     'total_amount'  => '1', // 订单金额(分)
  8.     'order_sn'      => $order_sn, // 订单编号
  9. );
  10. $re = $baidupay->xcxPay($order);
  11. die(json_encode($re)); // JSON化直接返回小程序客户端


小程序支付类 xcxPay:

  1. /**
  2.  * [xcxPay 百度小程序支付]
  3.  * @param  [type]  $order [订单信息数组]
  4.  * @return [type]         [description]
  5.  * $order = array(
  6.  *      'body'          => '', // 产品描述
  7.  *      'total_amount'  => '', // 订单金额(分)
  8.  *      'order_sn'      => '', // 订单编号
  9.  * );
  10.  */
  11. public static function xcxPay($order)
  12. {
  13.     if(!is_array($order) || count($order) < 3)
  14.         die("数组数据信息缺失!");
  15.     $config = self::$config;
  16.     $requestParamsArr = array(
  17.         'appKey'    => $config['app_key'],
  18.         'dealId'    => $config['deal_id'],
  19.         'tpOrderId' => $order['order_sn'],
  20.         'totalAmount' => $order['total_amount'],
  21.     );
  22.     $rsaSign = self::makeSign($requestParamsArr, $config['private_key']);  // 声称百度支付签名
  23.     $bizInfo = array(
  24.         'tpData' => array(
  25.             "appKey"        => $config['app_key'],
  26.             "dealId"        => $config['deal_id'],
  27.             "tpOrderId"     => $order['order_sn'],
  28.             "rsaSign"       => $rsaSign,
  29.             "totalAmount"   => $order['total_amount'],
  30.             "returnData"    => '',
  31.             "displayData"   => array(
  32.                 "cashierTopBlock" => array(
  33.                     array(
  34.                         [ "leftCol" => "订单名称", "rightCol"   => $order['body'] ],
  35.                         [ "leftCol" => "数量", "rightCol" => "1" ],
  36.                         [ "leftCol" => "订单金额", "rightCol"   => $order['total_amount'] ]
  37.                     ),
  38.                     array(
  39.                         [ "leftCol" => "服务地址", "rightCol" => "北京市海淀区上地十街10号百度大厦" ],
  40.                         [ "leftCol" => "服务时间", "rightCol" => "2018/10/29 14:51" ],
  41.                         [ "leftCol" => "服务人员", "rightCol" => "百度App" ]
  42.                     )
  43.                 )
  44.             ),
  45.             "dealTitle"     => $order['body'],
  46.             "dealSubTitle"  => $order['body'],
  47.             "dealThumbView" => "https://b.bdstatic.com/searchbox/icms/searchbox/img/swan-logo.png",
  48.         ),
  49.         "orderDetailData"   => ''
  50.     );
  51.     $bdOrder = array(
  52.         'dealId'        => $config['deal_id'],
  53.         'appKey'        => $config['app_key'],
  54.         'totalAmount'   => $order['total_amount'],
  55.         'tpOrderId'     => $order['order_sn'],
  56.         'dealTitle'     => $order['body'],
  57.         'signFieldsRange' => 1,
  58.         'rsaSign'       => $rsaSign,
  59.         'bizInfo'       => json_encode($bizInfo),
  60.     );
  61.     return $bdOrder;
  62. }


三、百度智能小程序端的使用

SWAN

  1. <view class="wrap">
  2.     <view class="card-area">
  3.         <button bind:tap="requestPolymerPayment" type="primary" hover-stop-propagation="true">支付0.01元</button>
  4.     </view>
  5. </view>

JS

  1. Page({
  2.     requestPolymerPayment(e) {
  3.         swan.request({
  4.             url: 'https://mbd.baidu.com/xxx', // 仅为示例,并非真实的接口地址,开发者从真实接口获取orderInfo的值
  5.             success: res => {
  6.                 res.data.data.dealTitle = '百度小程序Demo支付测试';
  7.                 let data = res.data;
  8.                 if (data.errno !== 0) {
  9.                     console.log('create order err', data);
  10.                     return;
  11.                 }
  12.                 swan.requestPolymerPayment({
  13.                     orderInfo: data.data,
  14.                     success: res => {
  15.                         swan.showToast({
  16.                             title: '支付成功',
  17.                             icon: 'success'
  18.                         });
  19.                         console.log('pay success', res);
  20.                     },
  21.                     fail: err => {
  22.                         swan.showToast({
  23.                             title: err.errMsg,
  24.                             icon: 'none'
  25.                         });
  26.                         console.log('pay fail', err);
  27.                     }
  28.                 });
  29.             },
  30.             fail: err => {
  31.                 swan.showToast({
  32.                     title: '订单创建失败',
  33.                     icon: 'none'
  34.                 });
  35.                 console.log('create order fail', err);
  36.             }
  37.         });
  38.     }
  39. });


四、支付回调

  1. <?php
  2. include './BaiduPay.php';
  3. $baidupay = new \feng\BaiduPay($config);
  4. $re = $baidupay->notify();
  5. if ($re) {
  6.     // 这里回调处理订单操作
  7.     // 以验证返回支付成功后的信息,可直接对订单进行操作,已通知微信支付成功
  8.     $baidupay->success(); // 支付返还成功,通知结果
  9. } else {
  10.     // 支付失败
  11.     $baidupay->error(); // 支付失败,返回状态(无论支付成功与否都需要通知百度)
  12. }

百度完整支付类(BaiduPay.php),包含小程序支付、验签、回调、退款:

  1. <?php
  2. /**
  3.  * @Author: [FENG] <1161634940@qq.com>
  4.  * @Date:   2020-09-27T16:28:31+08:00
  5.  * @Last Modified by:   [FENG] <1161634940@qq.com>
  6.  * @Last Modified time: 2020-10-15T10:23:07+08:00
  7.  */
  8. namespace feng;
  9. class BaiduPay
  10. {
  11.     private static $config = array(
  12.         'deal_id'       => '', // 百度收银台的财务结算凭证
  13.         'app_key'       => '', // 表示应用身份的唯一ID
  14.         'private_key'   => '', // 私钥原始字符串
  15.         'public_key'    => '', // 平台公钥
  16.         'notify_url'    => '', // 支付回调地址
  17.     );
  18.     /**
  19.      * [__construct 构造函数]
  20.      * @param [type] $config [传递支付相关配置]
  21.      */
  22.     public function __construct($config=NULL){
  23.         $config && self::$config = $config;
  24.     }
  25.     /**
  26.      * [xcxPay 百度小程序支付]
  27.      * @param  [type]  $order [订单信息数组]
  28.      * @return [type]         [description]
  29.      * $order = array(
  30.      *      'body'          => '', // 产品描述
  31.      *      'total_amount'  => '', // 订单金额(分)
  32.      *      'order_sn'      => '', // 订单编号
  33.      * );
  34.      */
  35.     public static function xcxPay($order)
  36.     {
  37.         if(!is_array($order) || count($order) < 3)
  38.             die("数组数据信息缺失!");
  39.         $config = self::$config;
  40.         $requestParamsArr = array(
  41.             'appKey'    => $config['app_key'],
  42.             'dealId'    => $config['deal_id'],
  43.             'tpOrderId' => $order['order_sn'],
  44.             'totalAmount' => $order['total_amount'],
  45.         );
  46.         $rsaSign = self::makeSign($requestParamsArr, $config['private_key']);  // 声称百度支付签名
  47.         $bizInfo = array(
  48.             'tpData' => array(
  49.                 "appKey"        => $config['app_key'],
  50.                 "dealId"        => $config['deal_id'],
  51.                 "tpOrderId"     => $order['order_sn'],
  52.                 "rsaSign"       => $rsaSign,
  53.                 "totalAmount"   => $order['total_amount'],
  54.                 "returnData"    => '',
  55.                 "displayData"   => array(
  56.                     "cashierTopBlock" => array(
  57.                         array(
  58.                             [ "leftCol" => "订单名称", "rightCol"   => $order['body'] ],
  59.                             [ "leftCol" => "数量", "rightCol" => "1" ],
  60.                             [ "leftCol" => "订单金额", "rightCol"   => $order['total_amount'] ]
  61.                         ),
  62.                         array(
  63.                             [ "leftCol" => "服务地址", "rightCol" => "北京市海淀区上地十街10号百度大厦" ],
  64.                             [ "leftCol" => "服务时间", "rightCol" => "2018/10/29 14:51" ],
  65.                             [ "leftCol" => "服务人员", "rightCol" => "百度App" ]
  66.                         )
  67.                     )
  68.                 ),
  69.                 "dealTitle"     => $order['body'],
  70.                 "dealSubTitle"  => $order['body'],
  71.                 "dealThumbView" => "https://b.bdstatic.com/searchbox/icms/searchbox/img/swan-logo.png",
  72.             ),
  73.             "orderDetailData"   => ''
  74.         );
  75.         $bdOrder = array(
  76.             'dealId'        => $config['deal_id'],
  77.             'appKey'        => $config['app_key'],
  78.             'totalAmount'   => $order['total_amount'],
  79.             'tpOrderId'     => $order['order_sn'],
  80.             'dealTitle'     => $order['body'],
  81.             'signFieldsRange' => 1,
  82.             'rsaSign'       => $rsaSign,
  83.             'bizInfo'       => json_encode($bizInfo),
  84.         );
  85.         return $bdOrder;
  86.     }
  87.     /**
  88.      * [refund baidu支付退款]
  89.      * @param  [type] $order [订单信息]
  90.      * @param  [type] $type  [退款类型]
  91.      * $order = array(
  92.      *      'body'          => '', // 退款原因
  93.      *      'total_amount'  => '', // 退款金额(分)
  94.      *      'order_sn'      => '', // 订单编号
  95.      *      'access_token'  => '', // 获取开发者服务权限说明
  96.      *      'order_id'      => '', // 百度收银台订单 ID
  97.      *      'user_id'       => '', // 百度收银台用户 id
  98.      * );
  99.      */
  100.     public static function refund($order=[], $type=1)
  101.     {
  102.         $config = self::$config;
  103.         $data = array(
  104.             'access_token'      => $order['access_token'], // 获取开发者服务权限说明
  105.             'applyRefundMoney'  => $order['total_amount'], // 退款金额,单位:分。
  106.             'bizRefundBatchId'  => $order['order_sn'], // 开发者退款批次
  107.             'isSkipAudit'       => 1, // 是否跳过审核,不需要百度请求开发者退款审核请传 1,默认为0; 0:不跳过开发者业务方审核;1:跳过开发者业务方审核。
  108.             'orderId'           => $order['order_id'], // 百度收银台订单 ID
  109.             'refundReason'      => $order['body'], // 退款原因
  110.             'refundType'        => $type, // 退款类型 1:用户发起退款;2:开发者业务方客服退款;3:开发者服务异常退款。
  111.             'tpOrderId'         => $order['order_sn'], // 开发者订单 ID
  112.             'userId'            => $order['user_id'], // 百度收银台用户 id
  113.         );
  114.         $array = ['errno'=>0, 'msg'=>'success', 'data'=> ['isConsumed'=>2] ];
  115.         $url = 'https://openapi.baidu.com/rest/2.0/smartapp/pay/paymentservice/applyOrderRefund';
  116.         $response = self::post_curl($url, $data);
  117.         $result = json_decode($response, true);
  118.         // // 显示错误信息
  119.         // if ($result['msg']!='success') {
  120.         //     return false;
  121.         //     // die($result['msg']);
  122.         // }
  123.         return $result;
  124.     }
  125.     /**
  126.      * [notify 回调验证]
  127.      * @return [array] [返回数组格式的notify数据]
  128.      */
  129.     public static function notify()
  130.     {
  131.         $data = $_POST; // 获取xml
  132.         $config = self::$config;
  133.         if (!$data || empty($data['rsaSign']))
  134.             die('暂无回调信息');
  135.         $result = self::checkSign($data, $config['public_key']); // 进行签名验证
  136.         // 判断签名是否正确  判断支付状态
  137.         if ($result && $data['status']==2) {
  138.             return $data;
  139.         } else {
  140.             return false;
  141.         }
  142.     }
  143.     /**
  144.      * [success 通知支付状态]
  145.      */
  146.     public static function success()
  147.     {
  148.         $array = ['errno'=>0, 'msg'=>'success', 'data'=> ['isConsumed'=>2] ];
  149.         die(json_encode($array));
  150.     }
  151.     /**
  152.      * [error 通知支付状态]
  153.      */
  154.     public static function error()
  155.     {
  156.         $array = ['errno'=>0, 'msg'=>'success', 'data'=> ['isErrorOrder'=>1, 'isConsumed'=>2] ];
  157.         die(json_encode($array));
  158.     }
  159.     /**
  160.      * [makeSign 使用私钥生成签名字符串]
  161.      * @param  array  $assocArr     [入参数组]
  162.      * @param  [type] $rsaPriKeyStr [私钥原始字符串,不含PEM格式前后缀]
  163.      * @return [type]               [签名结果字符串]
  164.      */
  165.     public static function makeSign(array $assocArr, $rsaPriKeyStr)
  166.     {
  167.         $sign = '';
  168.         if (empty($rsaPriKeyStr) || empty($assocArr)) {
  169.             return $sign;
  170.         }
  171.         if (!function_exists('openssl_pkey_get_private') || !function_exists('openssl_sign')) {
  172.             throw new Exception("openssl扩展不存在");
  173.         }
  174.         $rsaPriKeyPem = self::convertRSAKeyStr2Pem($rsaPriKeyStr, 1);
  175.         $priKey = openssl_pkey_get_private($rsaPriKeyPem);
  176.         if (isset($assocArr['sign'])) {
  177.             unset($assocArr['sign']);
  178.         }
  179.         ksort($assocArr); // 参数按字典顺序排序
  180.         $parts = array();
  181.         foreach ($assocArr as $k => $v) {
  182.             $parts[] = $k . '=' . $v;
  183.         }
  184.         $str = implode('&', $parts);
  185.         openssl_sign($str, $sign, $priKey);
  186.         openssl_free_key($priKey);
  187.         return base64_encode($sign);
  188.     }
  189.     /**
  190.      * [checkSign 使用公钥校验签名]
  191.      * @param  array  $assocArr     [入参数据,签名属性名固定为rsaSign]
  192.      * @param  [type] $rsaPubKeyStr [公钥原始字符串,不含PEM格式前后缀]
  193.      * @return [type]               [验签通过|false 验签不通过]
  194.      */
  195.     public static function checkSign(array $assocArr, $rsaPubKeyStr)
  196.     {
  197.         if (!isset($assocArr['rsaSign']) || empty($assocArr) || empty($rsaPubKeyStr)) {
  198.             return false;
  199.         }
  200.         if (!function_exists('openssl_pkey_get_public') || !function_exists('openssl_verify')) {
  201.             throw new Exception("openssl扩展不存在");
  202.         }
  203.         $sign = $assocArr['rsaSign'];
  204.         unset($assocArr['rsaSign']);
  205.         if (empty($assocArr)) {
  206.             return false;
  207.         }
  208.         ksort($assocArr); // 参数按字典顺序排序
  209.         $parts = array();
  210.         foreach ($assocArr as $k => $v) {
  211.             $parts[] = $k . '=' . $v;
  212.         }
  213.         $str = implode('&', $parts);
  214.         $sign = base64_decode($sign);
  215.         $rsaPubKeyPem = self::convertRSAKeyStr2Pem($rsaPubKeyStr);
  216.         $pubKey = openssl_pkey_get_public($rsaPubKeyPem);
  217.         $result = (bool)openssl_verify($str, $sign, $pubKey);
  218.         openssl_free_key($pubKey);
  219.         return $result;
  220.     }
  221.     /**
  222.      * [convertRSAKeyStr2Pem 将密钥由字符串(不换行)转为PEM格式]
  223.      * @param  [type]  $rsaKeyStr [原始密钥字符串]
  224.      * @param  integer $keyType   [0 公钥|1 私钥,默认0]
  225.      * @return [type]             [PEM格式密钥]
  226.      */
  227.     public static function convertRSAKeyStr2Pem($rsaKeyStr, $keyType = 0)
  228.     {
  229.         $pemWidth = 64;
  230.         $rsaKeyPem = '';
  231.         $begin = '-----BEGIN ';
  232.         $end = '-----END ';
  233.         $key = ' KEY-----';
  234.         $type = $keyType ? 'RSA PRIVATE' : 'PUBLIC';
  235.         $keyPrefix = $begin . $type . $key;
  236.         $keySuffix = $end . $type . $key;
  237.         $rsaKeyPem .= $keyPrefix . "\n";
  238.         $rsaKeyPem .= wordwrap($rsaKeyStr, $pemWidth, "\n", true) . "\n";
  239.         $rsaKeyPem .= $keySuffix;
  240.         if (!function_exists('openssl_pkey_get_public') || !function_exists('openssl_pkey_get_private')) {
  241.             return false;
  242.         }
  243.         if ($keyType == 0 && false == openssl_pkey_get_public($rsaKeyPem)) {
  244.             return false;
  245.         }
  246.         if ($keyType == 1 && false == openssl_pkey_get_private($rsaKeyPem)) {
  247.             return false;
  248.         }
  249.         return $rsaKeyPem;
  250.     }
  251.     /**
  252.      * curl post请求
  253.      * @param string $url 地址
  254.      * @param string $postData 数据
  255.      * @param array $header 头部
  256.      * @return bool|string
  257.      * @Date 2020/9/17 17:12
  258.      * @Author wzb
  259.      */
  260.     public static function post_curl($url='',$postData='',$header=[]){
  261.         $ch = curl_init($url);
  262.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  263.         curl_setopt($ch, CURLOPT_POST, 1);
  264.         curl_setopt($ch, CURLOPT_HEADER, false);
  265.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  266.         curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5000);
  267.         curl_setopt($ch, CURLOPT_TIMEOUT, 5000);
  268.         if($header){
  269.             curl_setopt($ch, CURLOPT_HTTPHEADER,$header);
  270.         }
  271.         curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
  272.         $result = curl_exec($ch);
  273.         $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  274.         $curlErrNo = curl_errno($ch);
  275.         $curlErr = curl_error($ch);
  276.         curl_close($ch);
  277.         return $result;
  278.     }
  279. }


本文网址:https://www.zztuku.com/index.php/detail-9018.html
站长图库 - 重新对百度支付进行编写封装(百度智能小程序支付)
申明:如有侵犯,请 联系我们 删除。

评论(0)条

您还没有登录,请 登录 后发表评论!

提示:请勿发布广告垃圾评论,否则封号处理!!

    编辑推荐