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.     if(!is_array($order) || count($order) < 3) 
  13.         die("数组数据信息缺失!"); 
  14.  
  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.  
  52.     $bdOrder = array( 
  53.         'dealId'        => $config['deal_id'], 
  54.         'appKey'        => $config['app_key'], 
  55.         'totalAmount'   => $order['total_amount'], 
  56.         'tpOrderId'     => $order['order_sn'], 
  57.         'dealTitle'     => $order['body'], 
  58.         'signFieldsRange' => 1, 
  59.         'rsaSign'       => $rsaSign, 
  60.         'bizInfo'       => json_encode($bizInfo), 
  61.     ); 
  62.     return $bdOrder; 


三、百度智能小程序端的使用
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(); // 支付失败,返回状态(无论支付成功与否都需要通知百度) 

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

 

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

支付宝扫一扫打赏

微信扫一扫打赏

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

文章点评

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

添加微信好友

添加微信好友

微信小程序

百度小程序