首页 微信小程序 小程序开发 重新对百度支付进行编写封装(百度智能小程序支付)

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

Jul 17, 2021 pm 03:38 PM

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

因为百度电商开放平台的升级,支付功能已移至智能小程序内部,具体申请流程:百度收银台支付开通指引,(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 &#39;./BaiduPay.php&#39;;
$baidupay = new \feng\BaiduPay($config);
$order_sn = time().rand(1000,9999);
$order = array(
    &#39;body&#39;          => &#39;测试商品&#39;, // 产品描述
    &#39;total_amount&#39;  => &#39;1&#39;, // 订单金额(分)
    &#39;order_sn&#39;      => $order_sn, // 订单编号
);
$re = $baidupay->xcxPay($order);
die(json_encode($re)); // JSON化直接返回小程序客户端
PHP
登录后复制

小程序支付类 xcxPay:

/**
 * [xcxPay 百度小程序支付]
 * @param  [type]  $order [订单信息数组]
 * @return [type]         [description]
 * $order = array(
 *      &#39;body&#39;          => &#39;&#39;, // 产品描述
 *      &#39;total_amount&#39;  => &#39;&#39;, // 订单金额(分)
 *      &#39;order_sn&#39;      => &#39;&#39;, // 订单编号
 * );
 */
public static function xcxPay($order)
{
    if(!is_array($order) || count($order) < 3)
        die("数组数据信息缺失!");
    $config = self::$config;
    $requestParamsArr = array(
        &#39;appKey&#39;    => $config[&#39;app_key&#39;],
        &#39;dealId&#39;    => $config[&#39;deal_id&#39;],
        &#39;tpOrderId&#39; => $order[&#39;order_sn&#39;],
        &#39;totalAmount&#39; => $order[&#39;total_amount&#39;],
    );
    $rsaSign = self::makeSign($requestParamsArr, $config[&#39;private_key&#39;]);  // 声称百度支付签名
    $bizInfo = array(
        &#39;tpData&#39; => array(
            "appKey"        => $config[&#39;app_key&#39;],
            "dealId"        => $config[&#39;deal_id&#39;],
            "tpOrderId"     => $order[&#39;order_sn&#39;],
            "rsaSign"       => $rsaSign,
            "totalAmount"   => $order[&#39;total_amount&#39;],
            "returnData"    => &#39;&#39;,
            "displayData"   => array(
                "cashierTopBlock" => array(
                    array(
                        [ "leftCol" => "订单名称", "rightCol"   => $order[&#39;body&#39;] ],
                        [ "leftCol" => "数量", "rightCol" => "1" ],
                        [ "leftCol" => "订单金额", "rightCol"   => $order[&#39;total_amount&#39;] ]
                    ),
                    array(
                        [ "leftCol" => "服务地址", "rightCol" => "北京市海淀区上地十街10号百度大厦" ],
                        [ "leftCol" => "服务时间", "rightCol" => "2018/10/29 14:51" ],
                        [ "leftCol" => "服务人员", "rightCol" => "百度App" ]
                    )
                )
            ),
            "dealTitle"     => $order[&#39;body&#39;],
            "dealSubTitle"  => $order[&#39;body&#39;],
            "dealThumbView" => "https://b.bdstatic.com/searchbox/icms/searchbox/img/swan-logo.png",
        ),
        "orderDetailData"   => &#39;&#39;
    );
    $bdOrder = array(
        &#39;dealId&#39;        => $config[&#39;deal_id&#39;],
        &#39;appKey&#39;        => $config[&#39;app_key&#39;],
        &#39;totalAmount&#39;   => $order[&#39;total_amount&#39;],
        &#39;tpOrderId&#39;     => $order[&#39;order_sn&#39;],
        &#39;dealTitle&#39;     => $order[&#39;body&#39;],
        &#39;signFieldsRange&#39; => 1,
        &#39;rsaSign&#39;       => $rsaSign,
        &#39;bizInfo&#39;       => 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: &#39;https://mbd.baidu.com/xxx&#39;, // 仅为示例,并非真实的接口地址,开发者从真实接口获取orderInfo的值
            success: res => {
                res.data.data.dealTitle = &#39;百度小程序Demo支付测试&#39;;
                let data = res.data;
                if (data.errno !== 0) {
                    console.log(&#39;create order err&#39;, data);
                    return;
                }
                swan.requestPolymerPayment({
                    orderInfo: data.data,
                    success: res => {
                        swan.showToast({
                            title: &#39;支付成功&#39;,
                            icon: &#39;success&#39;
                        });
                        console.log(&#39;pay success&#39;, res);
                    },
                    fail: err => {
                        swan.showToast({
                            title: err.errMsg,
                            icon: &#39;none&#39;
                        });
                        console.log(&#39;pay fail&#39;, err);
                    }
                });
            },
            fail: err => {
                swan.showToast({
                    title: &#39;订单创建失败&#39;,
                    icon: &#39;none&#39;
                });
                console.log(&#39;create order fail&#39;, err);
            }
        });
    }
});
登录后复制

四、支付回调

<?php
include &#39;./BaiduPay.php&#39;;
$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(
        &#39;deal_id&#39;       => &#39;&#39;, // 百度收银台的财务结算凭证
        &#39;app_key&#39;       => &#39;&#39;, // 表示应用身份的唯一ID
        &#39;private_key&#39;   => &#39;&#39;, // 私钥原始字符串
        &#39;public_key&#39;    => &#39;&#39;, // 平台公钥
        &#39;notify_url&#39;    => &#39;&#39;, // 支付回调地址
    );
    /**
     * [__construct 构造函数]
     * @param [type] $config [传递支付相关配置]
     */
    public function __construct($config=NULL){
        $config && self::$config = $config;
    }
    /**
     * [xcxPay 百度小程序支付]
     * @param  [type]  $order [订单信息数组]
     * @return [type]         [description]
     * $order = array(
     *      &#39;body&#39;          => &#39;&#39;, // 产品描述
     *      &#39;total_amount&#39;  => &#39;&#39;, // 订单金额(分)
     *      &#39;order_sn&#39;      => &#39;&#39;, // 订单编号
     * );
     */
    public static function xcxPay($order)
    {
        if(!is_array($order) || count($order) < 3)
            die("数组数据信息缺失!");
        $config = self::$config;
        $requestParamsArr = array(
            &#39;appKey&#39;    => $config[&#39;app_key&#39;],
            &#39;dealId&#39;    => $config[&#39;deal_id&#39;],
            &#39;tpOrderId&#39; => $order[&#39;order_sn&#39;],
            &#39;totalAmount&#39; => $order[&#39;total_amount&#39;],
        );
        $rsaSign = self::makeSign($requestParamsArr, $config[&#39;private_key&#39;]);  // 声称百度支付签名
        $bizInfo = array(
            &#39;tpData&#39; => array(
                "appKey"        => $config[&#39;app_key&#39;],
                "dealId"        => $config[&#39;deal_id&#39;],
                "tpOrderId"     => $order[&#39;order_sn&#39;],
                "rsaSign"       => $rsaSign,
                "totalAmount"   => $order[&#39;total_amount&#39;],
                "returnData"    => &#39;&#39;,
                "displayData"   => array(
                    "cashierTopBlock" => array(
                        array(
                            [ "leftCol" => "订单名称", "rightCol"   => $order[&#39;body&#39;] ],
                            [ "leftCol" => "数量", "rightCol" => "1" ],
                            [ "leftCol" => "订单金额", "rightCol"   => $order[&#39;total_amount&#39;] ]
                        ),
                        array(
                            [ "leftCol" => "服务地址", "rightCol" => "北京市海淀区上地十街10号百度大厦" ],
                            [ "leftCol" => "服务时间", "rightCol" => "2018/10/29 14:51" ],
                            [ "leftCol" => "服务人员", "rightCol" => "百度App" ]
                        )
                    )
                ),
                "dealTitle"     => $order[&#39;body&#39;],
                "dealSubTitle"  => $order[&#39;body&#39;],
                "dealThumbView" => "https://b.bdstatic.com/searchbox/icms/searchbox/img/swan-logo.png",
            ),
            "orderDetailData"   => &#39;&#39;
        );
        $bdOrder = array(
            &#39;dealId&#39;        => $config[&#39;deal_id&#39;],
            &#39;appKey&#39;        => $config[&#39;app_key&#39;],
            &#39;totalAmount&#39;   => $order[&#39;total_amount&#39;],
            &#39;tpOrderId&#39;     => $order[&#39;order_sn&#39;],
            &#39;dealTitle&#39;     => $order[&#39;body&#39;],
            &#39;signFieldsRange&#39; => 1,
            &#39;rsaSign&#39;       => $rsaSign,
            &#39;bizInfo&#39;       => json_encode($bizInfo),
        );
        return $bdOrder;
    }
    /**
     * [refund baidu支付退款]
     * @param  [type] $order [订单信息]
     * @param  [type] $type  [退款类型]
     * $order = array(
     *      &#39;body&#39;          => &#39;&#39;, // 退款原因
     *      &#39;total_amount&#39;  => &#39;&#39;, // 退款金额(分)
     *      &#39;order_sn&#39;      => &#39;&#39;, // 订单编号
     *      &#39;access_token&#39;  => &#39;&#39;, // 获取开发者服务权限说明
     *      &#39;order_id&#39;      => &#39;&#39;, // 百度收银台订单 ID
     *      &#39;user_id&#39;       => &#39;&#39;, // 百度收银台用户 id
     * );
     */
    public static function refund($order=[], $type=1)
    {
        $config = self::$config;
        $data = array(
            &#39;access_token&#39;      => $order[&#39;access_token&#39;], // 获取开发者服务权限说明
            &#39;applyRefundMoney&#39;  => $order[&#39;total_amount&#39;], // 退款金额,单位:分。
            &#39;bizRefundBatchId&#39;  => $order[&#39;order_sn&#39;], // 开发者退款批次
            &#39;isSkipAudit&#39;       => 1, // 是否跳过审核,不需要百度请求开发者退款审核请传 1,默认为0; 0:不跳过开发者业务方审核;1:跳过开发者业务方审核。
            &#39;orderId&#39;           => $order[&#39;order_id&#39;], // 百度收银台订单 ID
            &#39;refundReason&#39;      => $order[&#39;body&#39;], // 退款原因
            &#39;refundType&#39;        => $type, // 退款类型 1:用户发起退款;2:开发者业务方客服退款;3:开发者服务异常退款。
            &#39;tpOrderId&#39;         => $order[&#39;order_sn&#39;], // 开发者订单 ID
            &#39;userId&#39;            => $order[&#39;user_id&#39;], // 百度收银台用户 id
        );
        $array = [&#39;errno&#39;=>0, &#39;msg&#39;=>&#39;success&#39;, &#39;data&#39;=> [&#39;isConsumed&#39;=>2] ];
        $url = &#39;https://openapi.baidu.com/rest/2.0/smartapp/pay/paymentservice/applyOrderRefund&#39;;
        $response = self::post_curl($url, $data);
        $result = json_decode($response, true);
        // // 显示错误信息
        // if ($result[&#39;msg&#39;]!=&#39;success&#39;) {
        //     return false;
        //     // die($result[&#39;msg&#39;]);
        // }
        return $result;
    }
    /**
     * [notify 回调验证]
     * @return [array] [返回数组格式的notify数据]
     */
    public static function notify()
    {
        $data = $_POST; // 获取xml
        $config = self::$config;
        if (!$data || empty($data[&#39;rsaSign&#39;]))
            die(&#39;暂无回调信息&#39;);
        $result = self::checkSign($data, $config[&#39;public_key&#39;]); // 进行签名验证
        // 判断签名是否正确  判断支付状态
        if ($result && $data[&#39;status&#39;]==2) {
            return $data;
        } else {
            return false;
        }
    }
    /**
     * [success 通知支付状态]
     */
    public static function success()
    {
        $array = [&#39;errno&#39;=>0, &#39;msg&#39;=>&#39;success&#39;, &#39;data&#39;=> [&#39;isConsumed&#39;=>2] ];
        die(json_encode($array));
    }
    /**
     * [error 通知支付状态]
     */
    public static function error()
    {
        $array = [&#39;errno&#39;=>0, &#39;msg&#39;=>&#39;success&#39;, &#39;data&#39;=> [&#39;isErrorOrder&#39;=>1, &#39;isConsumed&#39;=>2] ];
        die(json_encode($array));
    }
    /**
     * [makeSign 使用私钥生成签名字符串]
     * @param  array  $assocArr     [入参数组]
     * @param  [type] $rsaPriKeyStr [私钥原始字符串,不含PEM格式前后缀]
     * @return [type]               [签名结果字符串]
     */
    public static function makeSign(array $assocArr, $rsaPriKeyStr)
    {
        $sign = &#39;&#39;;
        if (empty($rsaPriKeyStr) || empty($assocArr)) {
            return $sign;
        }
        if (!function_exists(&#39;openssl_pkey_get_private&#39;) || !function_exists(&#39;openssl_sign&#39;)) {
            throw new Exception("openssl扩展不存在");
        }
        $rsaPriKeyPem = self::convertRSAKeyStr2Pem($rsaPriKeyStr, 1);
        $priKey = openssl_pkey_get_private($rsaPriKeyPem);
        if (isset($assocArr[&#39;sign&#39;])) {
            unset($assocArr[&#39;sign&#39;]);
        }
        ksort($assocArr); // 参数按字典顺序排序
        $parts = array();
        foreach ($assocArr as $k => $v) {
            $parts[] = $k . &#39;=&#39; . $v;
        }
        $str = implode(&#39;&&#39;, $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[&#39;rsaSign&#39;]) || empty($assocArr) || empty($rsaPubKeyStr)) {
            return false;
        }
        if (!function_exists(&#39;openssl_pkey_get_public&#39;) || !function_exists(&#39;openssl_verify&#39;)) {
            throw new Exception("openssl扩展不存在");
        }
        $sign = $assocArr[&#39;rsaSign&#39;];
        unset($assocArr[&#39;rsaSign&#39;]);
        if (empty($assocArr)) {
            return false;
        }
        ksort($assocArr); // 参数按字典顺序排序
        $parts = array();
        foreach ($assocArr as $k => $v) {
            $parts[] = $k . &#39;=&#39; . $v;
        }
        $str = implode(&#39;&&#39;, $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 = &#39;&#39;;
        $begin = &#39;-----BEGIN &#39;;
        $end = &#39;-----END &#39;;
        $key = &#39; KEY-----&#39;;
        $type = $keyType ? &#39;RSA PRIVATE&#39; : &#39;PUBLIC&#39;;
        $keyPrefix = $begin . $type . $key;
        $keySuffix = $end . $type . $key;
        $rsaKeyPem .= $keyPrefix . "\n";
        $rsaKeyPem .= wordwrap($rsaKeyStr, $pemWidth, "\n", true) . "\n";
        $rsaKeyPem .= $keySuffix;
        if (!function_exists(&#39;openssl_pkey_get_public&#39;) || !function_exists(&#39;openssl_pkey_get_private&#39;)) {
            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=&#39;&#39;,$postData=&#39;&#39;,$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中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)