关于百度智能小程序支付的重新编写封装探讨

why 646 2024-06-26

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

关于百度智能小程序支付的重新编写封装探讨

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

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

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

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

1

2

3

4

5

6

7

$config = array(

    'deal_id'       => '', // 百度收银台的财务结算凭证

    'app_key'       => '', // 表示应用身份的唯一ID

    'private_key'   => '', // 私钥原始字符串

    'public_key'    => '', // 平台公钥

    'notify_url'    => '', // 支付回调地址

);

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

1

2

3

4

5

6

7

8

9

10

11

12

<?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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

/**

 * [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

1

2

3

4

5

6

<view class="wrap">

    <view class="card-area">

        <button bind:tap="requestPolymerPayment" type="primary" hover-stop-propagation="true">支付0.01元</button>

    </view>

</view>

HTML

JS

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

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);

            }

        });

    }

});

四、支付回调

1

2

3

4

5

6

7

8

9

10

11

12

<?php

include &#39;./BaiduPay.php&#39;;

$baidupay = new \feng\BaiduPay($config);

$re = $baidupay->notify();

if ($re) {

    // 这里回调处理订单操作

    // 以验证返回支付成功后的信息,可直接对订单进行操作,已通知微信支付成功

    $baidupay->success(); // 支付返还成功,通知结果

} else {

    // 支付失败

    $baidupay->error(); // 支付失败,返回状态(无论支付成功与否都需要通知百度)

}

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

<?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;

    }

}

以上就是重新对百度支付进行编写封装(百度智能小程序支付)的详细内容。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:小程序内实现搜索功能的详细方法深入剖析
下一篇:微信支付API v3回调通知乱码问题的解决办法详述
相关文章

 发表评论

暂时没有评论,来抢沙发吧~