微信扫码支付相对微信公众号支付来说,开发流程简单很多,不需要网页授权,不要调用微信内置WeixinJSBridge对象。只需要生成二维码,微信扫码即可直接调起微信支付。下面我们来讲解一下微信扫码的开发流程,包括简单的代码测试。
一、前期准备工作
1、申请一个认证服务号,并且开通支付功能
2、备案的域名+服务器(这个是必备的)
二、微信公众号支付开发流程

1、根据微信支付文档封装支付参数,调用微信支付统一下单接口向微信服务器发起请求,返回微信二维码链接。微信文档链接
2、将微信二维码链接生成二维码图片
三、代码开发流程
前面粗略讲解了微信扫码支付的开发流程,理解起来应该是相对简单。下面是示例代码(只是测试代码,不要用于生产环境):
1、调用微信统一下单接口,获取微信预支付交易会话标识和微信二维码链接。
调用统一下单接口类 wxpay.class.php1
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<?php
/**
* 微信支付
*/
class WxPay
{
private $apiUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
private $key;
private $mch_id;
private $appid;
private $openid;
private $nonce_str;
private $body;
private $out_trade_no;
private $total_fee;
private $spbill_create_ip;
private $notify_url;
private $trade_type;
function __construct($attributes)
{
$this->key = $attributes['key'];
$this->mch_id = $attributes['mch_id'];
$this->appid = $attributes['appid'];
$this->openid = $attributes['openid'];
$this->body = $attributes['body'];
$this->total_fee = $attributes['total_fee'];
$this->trade_type = $attributes['trade_type'];
$this->notify_url = $attributes['notify_url'];
}
//发送post请求
function http_post($url, $param) {
$header [] = "content-type: application/json; charset=UTF-8";
$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header );
curl_setopt ( $ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)' );
curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );
curl_setopt ( $ch, CURLOPT_AUTOREFERER, 1 );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $param );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
$res = curl_exec ( $ch );
curl_close ( $ch );
//$res = json_decode ( $res, true );
return $res;
}
//数组转换为xml格式
function arrayToXml($arr)
{
$xml = "<xml>";
foreach ($arr as $key=>$val)
{
if (is_numeric($val)){
$xml.="<".$key.">".$val."</".$key.">";
}else{
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
}
$xml.="</xml>";
return $xml;
}
//将XML转为数组
function xmlToArray($xml)
{
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $values;
}
//支付参数签名
function paySign($array, $key){
ksort($array);
$str = '';
foreach($array as $k => $value){
$str .= $k.'='.$value.'&';
}
$str .= "key=".$key;
$str = strtoupper(md5($str));
return $str;
}
//生成随机字符串
function get_rand_char($length = 6, $type = 1) {
$str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
$str2 = "0123456789";
$strLength1 = 61;
$strLength2 = 9;
$res = '';
if($type == 1){
for($i = 0; $i < $length; $i ++) {
$res .= $str1 [rand ( 0, $strLength1 )];
}
}else{
for($i = 0; $i < $length; $i ++) {
$res .= $str2 [rand ( 0, $strLength2 )];
}
}
return $res;
}
//获取IP
function get_client_ip() {
$ip = $_SERVER['REMOTE_ADDR'];
if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
foreach ($matches[0] AS $xip) {
if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
$ip = $xip;
break;
}
}
}
return $ip == '::1' ? '127.0.0.1' : $ip;
}
function prepare(){
$payConfig = [
'mch_id' => $this->mch_id,
'appid' => $this->appid,
'openid' => $this->openid,
'nonce_str' => $this->get_rand_char(32,2),
'body' => $this->body,
'out_trade_no' => date('YmdHis').$this->get_rand_char(6,1),
'total_fee' => $this->total_fee,
'spbill_create_ip' => $this->get_client_ip(),
'notify_url' => $this->notify_url,
'trade_type' => $this->trade_type,
];
$sign = $this->paySign($payConfig, $this->key);
$payConfig['sign'] = $sign;
$payXML = $this->arrayToXml($payConfig);
$result = $this->http_post($this->apiUrl, $payXML);
return $this->xmlToArray($result);
}
function qr_prepare(){
$payConfig = [
'mch_id' => $this->mch_id,
'appid' => $this->appid,
'nonce_str' => $this->get_rand_char(32,2),
'body' => $this->body,
'out_trade_no' => date('YmdHis').$this->get_rand_char(6,1),
'total_fee' => $this->total_fee,
'spbill_create_ip' => $this->get_client_ip(),
'notify_url' => $this->notify_url,
'trade_type' => $this->trade_type,
];
$sign = $this->paySign($payConfig, $this->key);
$payConfig['sign'] = $sign;
$payXML = $this->arrayToXml($payConfig);
$result = $this->http_post($this->apiUrl, $payXML);
return $this->xmlToArray($result);
}
function configForPayment($prepayId){
$jsPayConfig = [
'appId' => $this->appid,
'timeStamp' => strval(time()),
'nonceStr' => $this->get_rand_char(32,2),
'package' => "prepay_id=$prepayId",
'signType' => 'MD5',
];
$jsPayConfig['paySign'] = $this->paySign($jsPayConfig, $this->key);
return json_encode($jsPayConfig);
}
}
测试代码 test.php1
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<?php
//引入微信支付类
include 'wxpay.class.php';
//APPID
$appid = 'APPID';
//商户号
$mch_id = 'MCH_ID';
//API KEY
$key = 'KEY';
//支付回调地址
$notify_url = 'http://whatcode.cn/notify.php';
//商品描述
$body = '微信测试';
//商品价格
$total_fee = '100';
//微信支付类型
$trade_type = 'NATIVE';
//支付配置参数
$attributes = [
'mch_id' => $mch_id,
'key' => $key,
'appid' => $appid,
'body' => $body,
'total_fee' => $total_fee,
'notify_url' => $notify_url,
'trade_type' => $trade_type,
];
$wxpay = new WxPay($attributes);
$result = $wxpay->qr_prepare();
//打印输出$result
print_r($result);
?>
2、生成微信支付二维码
测试代码: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
35include 'wxpay.class.php';
//APPID
$appid = 'APPID';
//商户号
$mch_id = 'MCH_ID';
//API KEY
$key = 'KEY';
//支付回调地址
$notify_url = 'http://whatcode.cn/notify.php';
//商品描述
$body = '微信测试';
//商品价格
$total_fee = '1';
//微信支付类型
$trade_type = 'NATIVE';
//支付配置参数
$attributes = [
'mch_id' => $mch_id,
'key' => $key,
'appid' => $appid,
'body' => $body,
'total_fee' => $total_fee,
'notify_url' => $notify_url,
'trade_type' => $trade_type,
];
$wxpay = new WxPay($attributes);
$result = $wxpay->qr_prepare();
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
//利用微信提供的在线生成二维码功能
$wxpay_url = urlencode($result['code_url']);
echo '<img src="http://paysdk.weixin.qq.com/example/qrcode.php?data='.$wxpay_url.'" style="width:150px;height:150px;"/>';
}
这一步的生成二维码图片可以用第三方的类库,github上有很多,这里是为了方便测试就直接用微信提供的测试在线二维码接口。
四、总结
微信扫码支付开发流程相对公众号支付开发少了用户授权登录一步,后台配置了也少了两步,不需要配置授权域名,支付目录。注意支付参数不要弄错,trade_type=NATIVE。