QQ咨询 官方微信

添加微信好友

官方小程序

百度小程序

微信小程序

头条小程序

关于我们

小程序

首页 > 小程序 >

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

 admin  2022-02-13 13:06:09

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

因为百度电商开放平台的升级,
支付功能已移至智能小程序内部,
具体申请流程:百度收银台支付开通指引,
(注:在支付服务中,服务电话应填写银行预留手机号,如填写错误报【银行预留手机号码格式校验不通过】)
百度支付文档:百度收银台接口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.  
  4. $baidupay = new \feng\BaiduPay($config); 
  5. $order_sn = time().rand(1000,9999); 
  6.  
  7. $order = array( 
  8.     'body'          => '测试商品', // 产品描述 
  9.     'total_amount'  => '1', // 订单金额(分) 
  10.     'order_sn'      => $order_sn, // 订单编号 
  11. ); 
  12.  
  13. $re = $baidupay->xcxPay($order); 
  14. die(json_encode($re)); // JSON化直接返回小程序客户端 


PHP
小程序支付类 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.  
  16.     $config = self::$config; 
  17.     $requestParamsArr = array( 
  18.         'appKey'    => $config['app_key'], 
  19.         'dealId'    => $config['deal_id'], 
  20.         'tpOrderId' => $order['order_sn'], 
  21.         'totalAmount' => $order['total_amount'], 
  22.     ); 
  23.     $rsaSign = self::makeSign($requestParamsArr, $config['private_key']);  // 声称百度支付签名 
  24.     $bizInfo = array( 
  25.         'tpData' => array( 
  26.             "appKey"        => $config['app_key'], 
  27.             "dealId"        => $config['deal_id'], 
  28.             "tpOrderId"     => $order['order_sn'], 
  29.             "rsaSign"       => $rsaSign, 
  30.             "totalAmount"   => $order['total_amount'], 
  31.             "returnData"    => '', 
  32.             "displayData"   => array( 
  33.                 "cashierTopBlock" => array( 
  34.                     array( 
  35.                         [ "leftCol" => "订单名称", "rightCol"   => $order['body'] ], 
  36.                         [ "leftCol" => "数量", "rightCol" => "1" ], 
  37.                         [ "leftCol" => "订单金额", "rightCol"   => $order['total_amount'] ] 
  38.                     ), 
  39.                     array( 
  40.                         [ "leftCol" => "服务地址", "rightCol" => "北京市海淀区上地十街10号百度大厦" ], 
  41.                         [ "leftCol" => "服务时间", "rightCol" => "2018/10/29 14:51" ], 
  42.                         [ "leftCol" => "服务人员", "rightCol" => "百度App" ] 
  43.                     ) 
  44.                 ) 
  45.             ), 
  46.             "dealTitle"     => $order['body'], 
  47.             "dealSubTitle"  => $order['body'], 
  48.             "dealThumbView" => "https://b.bdstatic.com/searchbox/icms/searchbox/img/swan-logo.png", 
  49.         ), 
  50.         "orderDetailData"   => '' 
  51.     ); 
  52.  
  53.     $bdOrder = array( 
  54.         'dealId'        => $config['deal_id'], 
  55.         'appKey'        => $config['app_key'], 
  56.         'totalAmount'   => $order['total_amount'], 
  57.         'tpOrderId'     => $order['order_sn'], 
  58.         'dealTitle'     => $order['body'], 
  59.         'signFieldsRange' => 1, 
  60.         'rsaSign'       => $rsaSign, 
  61.         'bizInfo'       => json_encode($bizInfo), 
  62.     ); 
  63.     return $bdOrder; 
  64. } 


三、百度智能小程序端的使用
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.  
  13.                 swan.requestPolymerPayment({ 
  14.                     orderInfo: data.data, 
  15.                     success: res => { 
  16.                         swan.showToast({ 
  17.                             title: '支付成功', 
  18.                             icon: 'success' 
  19.                         }); 
  20.                         console.log('pay success', res); 
  21.                     }, 
  22.                     fail: err => { 
  23.                         swan.showToast({ 
  24.                             title: err.errMsg, 
  25.                             icon: 'none' 
  26.                         }); 
  27.                         console.log('pay fail', err); 
  28.                     } 
  29.                 }); 
  30.             }, 
  31.             fail: err => { 
  32.                 swan.showToast({ 
  33.                     title: '订单创建失败', 
  34.                     icon: 'none' 
  35.                 }); 
  36.                 console.log('create order fail', err); 
  37.             } 
  38.         }); 
  39.     } 
  40. }); 

四、支付回调

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

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

 

¥ 打赏
×
如果您觉得文章帮助了您就打赏一下吧
非常感谢你的打赏,我们将继续分享更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

本文《重新对百度支付进行编写封装(百度智能小程序支付)》发布于石头博客文章,作者:admin,如若转载,请注明出处:https://www.pweb123.com/xiaocheng/837.html,否则禁止转载,谢谢配合!

文章点评

我来说两句 已有0条评论
点击图片更换

添加微信好友

添加微信好友

微信小程序

百度小程序