• 技术文章 >微信小程序 >小程序开发

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

    藏色散人藏色散人2021-07-29 17:58:20转载199
    最近因为项目重构的原因,对百度支付重新进行了编写封装,本次重写,添加了对签名的处理、添加用户退款,方便之后开发的使用。

    因为百度电商开放平台的升级,支付功能已移至智能小程序内部,具体申请流程:百度收银台支付开通指引,(https://smartprogram.baidu.com/docs/operations/transform/pay/)

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

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

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

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

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

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

    小程序支付类 xcxPay:

    /**
     * [xcxPay 百度小程序支付]
     * @param  [type]  $order [订单信息数组]
     * @return [type]         [description]
     * $order = array(
     *      'body'          => '', // 产品描述
     *      'total_amount'  => '', // 订单金额(分)
     *      'order_sn'      => '', // 订单编号
     * );
     */
    public static function xcxPay($order)
    {
        if(!is_array($order) || count($order) < 3)
            die("数组数据信息缺失!");
        $config = self::$config;
        $requestParamsArr = array(
            'appKey'    => $config['app_key'],
            'dealId'    => $config['deal_id'],
            'tpOrderId' => $order['order_sn'],
            'totalAmount' => $order['total_amount'],
        );
        $rsaSign = self::makeSign($requestParamsArr, $config['private_key']);  // 声称百度支付签名
        $bizInfo = array(
            'tpData' => array(
                "appKey"        => $config['app_key'],
                "dealId"        => $config['deal_id'],
                "tpOrderId"     => $order['order_sn'],
                "rsaSign"       => $rsaSign,
                "totalAmount"   => $order['total_amount'],
                "returnData"    => '',
                "displayData"   => array(
                    "cashierTopBlock" => array(
                        array(
                            [ "leftCol" => "订单名称", "rightCol"   => $order['body'] ],
                            [ "leftCol" => "数量", "rightCol" => "1" ],
                            [ "leftCol" => "订单金额", "rightCol"   => $order['total_amount'] ]
                        ),
                        array(
                            [ "leftCol" => "服务地址", "rightCol" => "北京市海淀区上地十街10号百度大厦" ],
                            [ "leftCol" => "服务时间", "rightCol" => "2018/10/29 14:51" ],
                            [ "leftCol" => "服务人员", "rightCol" => "百度App" ]
                        )
                    )
                ),
                "dealTitle"     => $order['body'],
                "dealSubTitle"  => $order['body'],
                "dealThumbView" => "https://b.bdstatic.com/searchbox/icms/searchbox/img/swan-logo.png",
            ),
            "orderDetailData"   => ''
        );
        $bdOrder = array(
            'dealId'        => $config['deal_id'],
            'appKey'        => $config['app_key'],
            'totalAmount'   => $order['total_amount'],
            'tpOrderId'     => $order['order_sn'],
            'dealTitle'     => $order['body'],
            'signFieldsRange' => 1,
            'rsaSign'       => $rsaSign,
            'bizInfo'       => json_encode($bizInfo),
        );
        return $bdOrder;
    }

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

    SWAN

    <view class="wrap">
        <view class="card-area">
            <button bind:tap="requestPolymerPayment" type="primary" hover-stop-propagation="true">支付0.01元</button>
        </view>
    </view>
    HTML

    JS

    Page({
        requestPolymerPayment(e) {
            swan.request({
                url: 'https://mbd.baidu.com/xxx', // 仅为示例,并非真实的接口地址,开发者从真实接口获取orderInfo的值
                success: res => {
                    res.data.data.dealTitle = '百度小程序Demo支付测试';
                    let data = res.data;
                    if (data.errno !== 0) {
                        console.log('create order err', data);
                        return;
                    }
                    swan.requestPolymerPayment({
                        orderInfo: data.data,
                        success: res => {
                            swan.showToast({
                                title: '支付成功',
                                icon: 'success'
                            });
                            console.log('pay success', res);
                        },
                        fail: err => {
                            swan.showToast({
                                title: err.errMsg,
                                icon: 'none'
                            });
                            console.log('pay fail', err);
                        }
                    });
                },
                fail: err => {
                    swan.showToast({
                        title: '订单创建失败',
                        icon: 'none'
                    });
                    console.log('create order fail', err);
                }
            });
        }
    });

    四、支付回调

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

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

    <?php
    /**
     * @Author: [FENG] <1161634940@qq.com>
     * @Date:   2020-09-27T16:28:31+08:00
     * @Last Modified by:   [FENG] <1161634940@qq.com>
     * @Last Modified time: 2020-10-15T10:23:07+08:00
     */
    namespace feng;
    class BaiduPay
    {
        private static $config = array(
            'deal_id'       => '', // 百度收银台的财务结算凭证
            'app_key'       => '', // 表示应用身份的唯一ID
            'private_key'   => '', // 私钥原始字符串
            'public_key'    => '', // 平台公钥
            'notify_url'    => '', // 支付回调地址
        );
        /**
         * [__construct 构造函数]
         * @param [type] $config [传递支付相关配置]
         */
        public function __construct($config=NULL){
            $config && self::$config = $config;
        }
        /**
         * [xcxPay 百度小程序支付]
         * @param  [type]  $order [订单信息数组]
         * @return [type]         [description]
         * $order = array(
         *      'body'          => '', // 产品描述
         *      'total_amount'  => '', // 订单金额(分)
         *      'order_sn'      => '', // 订单编号
         * );
         */
        public static function xcxPay($order)
        {
            if(!is_array($order) || count($order) < 3)
                die("数组数据信息缺失!");
            $config = self::$config;
            $requestParamsArr = array(
                'appKey'    => $config['app_key'],
                'dealId'    => $config['deal_id'],
                'tpOrderId' => $order['order_sn'],
                'totalAmount' => $order['total_amount'],
            );
            $rsaSign = self::makeSign($requestParamsArr, $config['private_key']);  // 声称百度支付签名
            $bizInfo = array(
                'tpData' => array(
                    "appKey"        => $config['app_key'],
                    "dealId"        => $config['deal_id'],
                    "tpOrderId"     => $order['order_sn'],
                    "rsaSign"       => $rsaSign,
                    "totalAmount"   => $order['total_amount'],
                    "returnData"    => '',
                    "displayData"   => array(
                        "cashierTopBlock" => array(
                            array(
                                [ "leftCol" => "订单名称", "rightCol"   => $order['body'] ],
                                [ "leftCol" => "数量", "rightCol" => "1" ],
                                [ "leftCol" => "订单金额", "rightCol"   => $order['total_amount'] ]
                            ),
                            array(
                                [ "leftCol" => "服务地址", "rightCol" => "北京市海淀区上地十街10号百度大厦" ],
                                [ "leftCol" => "服务时间", "rightCol" => "2018/10/29 14:51" ],
                                [ "leftCol" => "服务人员", "rightCol" => "百度App" ]
                            )
                        )
                    ),
                    "dealTitle"     => $order['body'],
                    "dealSubTitle"  => $order['body'],
                    "dealThumbView" => "https://b.bdstatic.com/searchbox/icms/searchbox/img/swan-logo.png",
                ),
                "orderDetailData"   => ''
            );
            $bdOrder = array(
                'dealId'        => $config['deal_id'],
                'appKey'        => $config['app_key'],
                'totalAmount'   => $order['total_amount'],
                'tpOrderId'     => $order['order_sn'],
                'dealTitle'     => $order['body'],
                'signFieldsRange' => 1,
                'rsaSign'       => $rsaSign,
                'bizInfo'       => json_encode($bizInfo),
            );
            return $bdOrder;
        }
        /**
         * [refund baidu支付退款]
         * @param  [type] $order [订单信息]
         * @param  [type] $type  [退款类型]
         * $order = array(
         *      'body'          => '', // 退款原因
         *      'total_amount'  => '', // 退款金额(分)
         *      'order_sn'      => '', // 订单编号
         *      'access_token'  => '', // 获取开发者服务权限说明
         *      'order_id'      => '', // 百度收银台订单 ID
         *      'user_id'       => '', // 百度收银台用户 id
         * );
         */
        public static function refund($order=[], $type=1)
        {
            $config = self::$config;
            $data = array(
                'access_token'      => $order['access_token'], // 获取开发者服务权限说明
                'applyRefundMoney'  => $order['total_amount'], // 退款金额,单位:分。
                'bizRefundBatchId'  => $order['order_sn'], // 开发者退款批次
                'isSkipAudit'       => 1, // 是否跳过审核,不需要百度请求开发者退款审核请传 1,默认为0; 0:不跳过开发者业务方审核;1:跳过开发者业务方审核。
                'orderId'           => $order['order_id'], // 百度收银台订单 ID
                'refundReason'      => $order['body'], // 退款原因
                'refundType'        => $type, // 退款类型 1:用户发起退款;2:开发者业务方客服退款;3:开发者服务异常退款。
                'tpOrderId'         => $order['order_sn'], // 开发者订单 ID
                'userId'            => $order['user_id'], // 百度收银台用户 id
            );
            $array = ['errno'=>0, 'msg'=>'success', 'data'=> ['isConsumed'=>2] ];
            $url = 'https://openapi.baidu.com/rest/2.0/smartapp/pay/paymentservice/applyOrderRefund';
            $response = self::post_curl($url, $data);
            $result = json_decode($response, true);
            // // 显示错误信息
            // if ($result['msg']!='success') {
            //     return false;
            //     // die($result['msg']);
            // }
            return $result;
        }
        /**
         * [notify 回调验证]
         * @return [array] [返回数组格式的notify数据]
         */
        public static function notify()
        {
            $data = $_POST; // 获取xml
            $config = self::$config;
            if (!$data || empty($data['rsaSign']))
                die('暂无回调信息');
            $result = self::checkSign($data, $config['public_key']); // 进行签名验证
            // 判断签名是否正确  判断支付状态
            if ($result && $data['status']==2) {
                return $data;
            } else {
                return false;
            }
        }
        /**
         * [success 通知支付状态]
         */
        public static function success()
        {
            $array = ['errno'=>0, 'msg'=>'success', 'data'=> ['isConsumed'=>2] ];
            die(json_encode($array));
        }
        /**
         * [error 通知支付状态]
         */
        public static function error()
        {
            $array = ['errno'=>0, 'msg'=>'success', 'data'=> ['isErrorOrder'=>1, 'isConsumed'=>2] ];
            die(json_encode($array));
        }
        /**
         * [makeSign 使用私钥生成签名字符串]
         * @param  array  $assocArr     [入参数组]
         * @param  [type] $rsaPriKeyStr [私钥原始字符串,不含PEM格式前后缀]
         * @return [type]               [签名结果字符串]
         */
        public static function makeSign(array $assocArr, $rsaPriKeyStr)
        {
            $sign = '';
            if (empty($rsaPriKeyStr) || empty($assocArr)) {
                return $sign;
            }
            if (!function_exists('openssl_pkey_get_private') || !function_exists('openssl_sign')) {
                throw new Exception("openssl扩展不存在");
            }
            $rsaPriKeyPem = self::convertRSAKeyStr2Pem($rsaPriKeyStr, 1);
            $priKey = openssl_pkey_get_private($rsaPriKeyPem);
            if (isset($assocArr['sign'])) {
                unset($assocArr['sign']);
            }
            ksort($assocArr); // 参数按字典顺序排序
            $parts = array();
            foreach ($assocArr as $k => $v) {
                $parts[] = $k . '=' . $v;
            }
            $str = implode('&', $parts);
            openssl_sign($str, $sign, $priKey);
            openssl_free_key($priKey);
            return base64_encode($sign);
        }
        /**
         * [checkSign 使用公钥校验签名]
         * @param  array  $assocArr     [入参数据,签名属性名固定为rsaSign]
         * @param  [type] $rsaPubKeyStr [公钥原始字符串,不含PEM格式前后缀]
         * @return [type]               [验签通过|false 验签不通过]
         */
        public static function checkSign(array $assocArr, $rsaPubKeyStr)
        {
            if (!isset($assocArr['rsaSign']) || empty($assocArr) || empty($rsaPubKeyStr)) {
                return false;
            }
            if (!function_exists('openssl_pkey_get_public') || !function_exists('openssl_verify')) {
                throw new Exception("openssl扩展不存在");
            }
            $sign = $assocArr['rsaSign'];
            unset($assocArr['rsaSign']);
            if (empty($assocArr)) {
                return false;
            }
            ksort($assocArr); // 参数按字典顺序排序
            $parts = array();
            foreach ($assocArr as $k => $v) {
                $parts[] = $k . '=' . $v;
            }
            $str = implode('&', $parts);
            $sign = base64_decode($sign);
            $rsaPubKeyPem = self::convertRSAKeyStr2Pem($rsaPubKeyStr);
            $pubKey = openssl_pkey_get_public($rsaPubKeyPem);
            $result = (bool)openssl_verify($str, $sign, $pubKey);
            openssl_free_key($pubKey);
            return $result;
        }
        /**
         * [convertRSAKeyStr2Pem 将密钥由字符串(不换行)转为PEM格式]
         * @param  [type]  $rsaKeyStr [原始密钥字符串]
         * @param  integer $keyType   [0 公钥|1 私钥,默认0]
         * @return [type]             [PEM格式密钥]
         */
        public static function convertRSAKeyStr2Pem($rsaKeyStr, $keyType = 0)
        {
            $pemWidth = 64;
            $rsaKeyPem = '';
            $begin = '-----BEGIN ';
            $end = '-----END ';
            $key = ' KEY-----';
            $type = $keyType ? 'RSA PRIVATE' : 'PUBLIC';
            $keyPrefix = $begin . $type . $key;
            $keySuffix = $end . $type . $key;
            $rsaKeyPem .= $keyPrefix . "\n";
            $rsaKeyPem .= wordwrap($rsaKeyStr, $pemWidth, "\n", true) . "\n";
            $rsaKeyPem .= $keySuffix;
            if (!function_exists('openssl_pkey_get_public') || !function_exists('openssl_pkey_get_private')) {
                return false;
            }
            if ($keyType == 0 && false == openssl_pkey_get_public($rsaKeyPem)) {
                return false;
            }
            if ($keyType == 1 && false == openssl_pkey_get_private($rsaKeyPem)) {
                return false;
            }
            return $rsaKeyPem;
        }
        /**
         * curl post请求
         * @param string $url 地址
         * @param string $postData 数据
         * @param array $header 头部
         * @return bool|string
         * @Date 2020/9/17 17:12
         * @Author wzb
         */
        public static function post_curl($url='',$postData='',$header=[]){
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5000);
            curl_setopt($ch, CURLOPT_TIMEOUT, 5000);
            if($header){
                curl_setopt($ch, CURLOPT_HTTPHEADER,$header);
            }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
            $result = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $curlErrNo = curl_errno($ch);
            $curlErr = curl_error($ch);
            curl_close($ch);
            return $result;
        }
    }

    以上就是重新对百度支付进行编写封装(百度智能小程序支付)的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:fengkui.net,如有侵犯,请联系admin@php.cn删除
    专题推荐:百度智能小程序
    上一篇:百度小程序富文本解析工具bdParse的使用 下一篇:浅谈小程序如何授权登录,获取信息和手机号
    VIP会员

    相关文章推荐

    • 关于微信支付小程序v3【附PHP完整后端代码】• 分享封装的一个PHP微信支付的类库(扫码、H5、小程序)• 小程序如何获取到openid和session_key• 随着更新潮流,把PHP字节小程序担保支付类也更新了!

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网