PHP小程序支付功能完整版【基于thinkPHP】

2025-05-29 0 74

本文实例讲述了PHP小程序支付功能。分享给大家供大家参考,具体如下:

环境: tp3.2 + 小程序 微信支付功能开通

Step1: 下载PHP 支付SDK(下载地址) 放到Library\\Vendor下,取名Wxpay

修改WxPay.Config.php 里的appid appsecret key MCHID

Step2: 小程序 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

40

41

42

43

44

45

46

47

48

49

50
var url = getApp().globalData.httpServer + 'api/buy/pay';

var userId = getApp().globalData.userId;

var totalMoney = this.data.totalMoney;

var cart = this.data.goods;

var param = {

cart: JSON.stringify(cart),

cartamount: totalMoney,

userid: userId,

payment: this.data.payment,

addressid: defaultAddress.id

};

var that = this;

util.http(url, param, function (ret) {

if (ret.data.code == 1) {

if (that.data.payment == 'balance') { // 余额支付

that.afterPaySuccess(ret.data.data);

} else { // 微信支付

wx.requestPayment({

timeStamp: ret.data.data.timeStamp,

nonceStr: ret.data.data.nonceStr,

package: ret.data.data.package,

signType: ret.data.data.signType,

paySign: ret.data.data.paySign,

'success': function (res) {

that.afterPaySuccess(ret.data.data.orderid);

},

'fail': function (res) {

console.log(res);

}

})

}

} else {

util.showTip(ret.data.msg, '提交订单失败');

}

});

/**

* 网络请求

*/

function http(url, params, callback) {

wx.request({

url: url,

data: params,

success: function (res) {

callback(res);

},

fail: function (err) {

console.log(err);

}

});

}

Step3: 接口代码:

?

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
public function pay()

{

$cart = I('cart', '', 'trim');

$cartAmount = I('cartamount');

$addressId = I('addressid', 0, 'intval');

$payment = I('payment', '', 'trim');

$userId = $this->userid;

$cart = json_decode($cart, true);

if (empty($cart)) {

$result['msg'] = '购物车获取失败';

$result['code'] = 0;

$this->ajaxReturn($result);

}

$totalMoney = 0;

foreach ($cart as $goods) {

$money = $goods['price']; // price

$selectCount = $goods['selectcount']; // price

$itemAmount = number_format($money * $selectCount, 2, '.', '');

$totalMoney += $itemAmount;

}

// 检查总金额是否一致

if ($totalMoney != $cartAmount) {

$result['msg'] = '总金额不匹配:' . $totalMoney;

$result['code'] = 0;

$this->ajaxReturn($result);

}

// 获取用户地址

$address = M('MemberAddress')->where('userid=' . $userId . " and id=" . $addressId)->find();

if (empty($address)) {

$result['msg'] = '用户地址不存在';

$result['code'] = 0;

$this->ajaxReturn($result);

}

// 用户信息

$user = M('Member')->where("id=" . $userId)->find();

if ($payment == 'balance') {

if ($user['amount'] < $cartAmount) {

$result['msg'] = '余额不足';

$result['code'] = 0;

$this->ajaxReturn($result);

}

}

// 生成订单

$order['ordersn'] = $this->genOrdersn($user['id']);

$order['price'] = $cartAmount;

$order['addressid'] = $address['id'];

$order['addressinfo'] = serialize($address); //json_encode($address);

$order['longitude'] = $address['longitude'];

$order['latitude'] = $address['latitude'];

$order['addtime'] = time();

$order['status'] = 0;

$order['userid'] = $user['id'];

$order['paytype'] = $payment;

$order['paysn'] = '';

$order['paytime'] = time();

$orderId = M("Order")->add($order);

if ($orderId == 0) {

$result['msg'] = '创建订单失败';

$result['code'] = 0;

$this->ajaxReturn($result);

}

foreach ($cart as $goods) {

$orderGoods['orderid'] = $orderId;

$orderGoods['goodsid'] = $goods['id'];

$orderGoods['title'] = $goods['title'];

$orderGoods['price'] = $goods['price'];

$orderGoods['attr'] = $goods['attr'];

$orderGoods['pic'] = $goods['pic'];

$orderGoods['num'] = $goods['selectcount'];

M("OrderGoods")->add($orderGoods);

}

if ($payment == 'balance') {

// 余额支付

$this->balancePay($cartAmount, $user['wxopenid'], $orderId);

} else if ($payment == 'weixin') {

// 微信支付

$this->weixinPay($cartAmount, $user['wxopenid'], $orderId, $order['ordersn']);

}

}

/**

* 微信支付

* @author 大脸猫脸大

* @param $cart

* @param $cartAmount

* @param $address

* @param $user

*/

private function weixinPay($cartAmount, $openId, $orderId, $orderSn)

{

import("Vendor.Wxpay.lib.WxPay#Api", "", ".php");

//订单号

$money = $cartAmount * 100;

$openid = $openId;

$input = new \\WxPayUnifiedOrder();

$input->SetBody("迪克-商品");

$input->SetOut_trade_no("$orderSn");

$input->SetTotal_fee("$money");

$input->SetNotify_url("https://" . $_SERVER['HTTP_HOST'] . "/api/buy/payNotify");

$input->SetTrade_type("JSAPI");

$input->SetOpenid($openid);

$unifiedOrder = \\WxPayApi::unifiedOrder($input);

if ($unifiedOrder['result_code'] == 'SUCCESS' && $unifiedOrder['return_code'] == 'SUCCESS') {

$time = time();

$data['timeStamp'] = "$time"; //时间戳

$data['nonceStr'] = $unifiedOrder['nonce_str']; //随机字符串

$data['signType'] = 'MD5'; //签名算法,暂支持 MD5

$data['package'] = 'prepay_id=' . $unifiedOrder['prepay_id']; //统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*

$data['paySign'] = $this->genPaySign($unifiedOrder, $time);// 之前以为是$unifiedOrder['sign']; 后来发现是调用的这种方法. 签名方案参见微信公众号支付帮助文档;

$data['out_trade_no'] = $orderSn;

$data['orderid'] = $orderId;

$return['code'] = 1;

$return['data'] = $data;

} else {

Log::write(var_export($unifiedOrder, true), Log::ERR, '', C('LOG_PATH')."wx_pay_".date('y_m_d').'.log');

$return['code'] = 0;

$return['msg'] = '微信支付失败';// $unifiedOrder['RETURN_MSG'];

}

$this->ajaxReturn($return);

}

/* 生成支付签名*/

private function genPaySign($unifiedOrder, $time)

{

$appId = \\WxPayConfig::APPID;

$nonceStr = $unifiedOrder['nonce_str'];

$package = 'prepay_id=' . $unifiedOrder['prepay_id'];

$signType = "MD5";

$timeStamp = $time;

$key = \\WxPayConfig::KEY;

$sign = md5(sprintf("appId=%s&nonceStr=%s&package=%s&signType=%s&timeStamp=%s&key=%s", $appId, $nonceStr, $package, $signType, $timeStamp, $key));

return $sign;

}

/**

* 支付回调

* @author:大脸猫脸大

*/

public function payNotify()

{

import("Vendor.Wxpay.lib.WxPay#Data", "", ".php");

$xml = $GLOBALS['HTTP_RAW_POST_DATA'];

$val = \\WxPayResults::Init($xml);

if ($val['result_code'] == 'SUCCESS' && $val['return_code'] == 'SUCCESS') {

$orderSn = $val['out_trade_no'];

$transactionId = $val['transaction_id'];

$data = array('paytype' => 'weixin', 'status' => '1', 'paytime' => time(), 'paysn' => $transactionId);

M("Order")->where("ordersn='$orderSn'")->setField($data);

exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');

}else {

Log::write(var_export($val, true), Log::ERR, '', C('LOG_PATH')."wx_pay_notify_".date('y_m_d').'.log');

exit('<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');

}

}

payNotify 回调方法里一定要注意返回

<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>

如果不处理,你会发现payNotify 会被执行很多次参见:官方文档

总结一下: 注意二点, 1.签名的问题 2. 回调方法的返回处理。

欢迎大家指正。

希望本文所述对大家PHP程序设计有所帮助。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 PHP小程序支付功能完整版【基于thinkPHP】 https://www.kuaiidc.com/93469.html

相关文章

发表评论
暂无评论