最近公司项目需要接入微信支付购买道具,本人负责h5和微信公众号支付这一块。app支付由另一同事负责,在这里就不说了。
关于公众号支付,腾讯官方有提供demo。下载地址:官方Demo
吐嘈一下,官方Demo的好像有点问题,在WxPay.Api.php line 537 538这两个代码会导致错误码60
1
2
|
curl_setopt(
$ch
,CURLOPT_SSL_VERIFYPEER,TRUE);
curl_setopt(
$ch
,CURLOPT_SSL_VERIFYHOST,2);
//严格校验
|
修改为
1
2
|
curl_setopt(
$ch
,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt(
$ch
,CURLOPT_SSL_VERIFYHOST,FALSE);
|
就好了
使用公众号支付时,需要先获取用户的openId(需要设置微信js接口安全域名/网页授权域名(在公众号设置-功能设置))。这个授权在官方给出的demo中使用的是静默授权
关于网页授权的两种scope的区别说明
1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
3、用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。
经过测试,静默授权跳转回到页面需要花费2秒左右。所以我使用ajax去请求授权
首先在业务页面获取code
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
|
<?php
error_reporting
(E_ERROR);
ini_set
(
'date.timezone'
,
'Asia/Shanghai'
);
header(
"Content-Type: text/html; charset=UTF-8"
);
require_once
"JsApiPay.php"
;
//是否是微信打开 h5和微信内是同一个网页,所以加上这个判断
function
is_weixin(){
if
(
strpos
(
$_SERVER
[
'HTTP_USER_AGENT'
],
'MicroMessenger'
) !== false ) {
return
true;
}
return
false;
}
if
(is_weixin()){
$tools
=
new
JsApiPay();
//触发微信返回code码
if
(!isset(
$_GET
[
'code'
])){
$baseUrl
= urlencode(
'http://'
.
$_SERVER
[
'HTTP_HOST'
].
$_SERVER
[
'REQUEST_URI'
].
$_SERVER
[
'QUERY_STRING'
]);
$url
=
$tools
->__CreateOauthUrlForCode(
$baseUrl
);
Header(
"Location: $url"
);
exit
();
}
//获取共享收货地址js函数参数
$editAddress
=
$tools
->GetEditAddressParameters();
}
?>
|
前端ajax请求用户信息
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
|
//显示loading 建议内容不超出六个汉字
function
showLoading(msg){
var
$loadingToast = $(
'#loadingToast'
);
if
($loadingToast.css(
'display'
) !=
'none'
)
return
;
$(
'.weui-toast__content'
).html(msg)
$loadingToast.fadeIn(100);
}
function
closeLoading()
{
var
$loadingToast = $(
'#loadingToast'
);
$loadingToast.fadeOut(100);
}
//是否是微信打开
function
is_weixin(){
var
ua = navigator.userAgent.toLowerCase();
if
(ua.match(/MicroMessenger/i)==
"micromessenger"
) {
return
true
;
}
else
{
return
false
;
}
}
$(
function
(){
var
userInfo;
if
(is_weixin()){
showLoading(
"获取授权中"
);
//请求过程中显示一个loading
var
userInfo
$.get(
'get_user_info.php?<?php echo $_SERVER['
QUERY_STRING
'] ?>'
,
function
(data, st){
closeLoading();
userInfo = JSON.parse(data);
$(
'.page__title'
).html(userInfo.nick);
$(
'.page__desc'
).html(
"UID:"
+userInfo.uid);
if
(userInfo.uid == -1){
$(
'.page__desc'
).html(
"UID:null"
);
showMessage(
"您还未使用过当前微信号登陆过游戏,请确认"
);
}
});
}
else
{
userInfo = {
"unionid"
:
"0"
,
"nick"
:
"未登录用户"
,
"uid"
:
"-1"
,
"openId"
:
"0"
};
$(
'.page__title'
).html(userInfo.nick);
$(
'.page__desc'
).html(
"UID:"
+userInfo.uid);
}
|
get_user_info.php代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?php
ini_set
(
'date.timezone'
,
'Asia/Shanghai'
);
header(
"Content-Type: text/html; charset=UTF-8"
);
require_once
"JsApiPay.php"
;
//①、获取用户openid
$tools
=
new
JsApiPay();
$openId
=
$tools
->GetOpenid();
$usInfo
=
$tools
->GetUserInfo();
$unionid
=
$usInfo
[
"unionid"
];
$ret_data
=
function
()
//跟后台确认用户信息<span>,建议后台用户标识使用开放平台的unionid,可以在平台绑定该公众号。
//这样获取的用户信息就带有unionid字段了。而且公众平台和开放平台下其它应用是一致的unionid
$nick
=
"尚未登录游戏"
;
$uid
= -1;
if
(
$ret_data
->ret == 1){
$nick
=
$ret_data
->data->nick;
$uid
=
$ret_data
->data->uid;
}
//'{"ret":1,"data":'.$jsApiParameters.'}';
echo
'{"unionid":"'
.
$unionid
.
'","nick":"'
.
$nick
.
'","uid":"'
.
$uid
.
'","openId":"'
.
$openId
.
'"}'
;
?></span>
|
JsApiPay(Demo中的WxPay.JsApiPay.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
|
/**
*
* 获取access_token
*
*/
private
function
GetAccessToken()
{
$urlObj
[
"grant_type"
] =
"client_credential"
;
$urlObj
[
"appid"
] = WxPayConfig::APPID;
$urlObj
[
"secret"
] = WxPayConfig::APPSECRET;
$bizString
=
$this
->ToUrlParams(
$urlObj
);
//初始化curl
$ch
= curl_init();
//设置超时
curl_setopt(
$ch
, CURLOPT_TIMEOUT,
$this
->curl_timeout);
curl_setopt(
$ch
, CURLOPT_URL,
$url
);
curl_setopt(
$ch
, CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt(
$ch
, CURLOPT_SSL_VERIFYHOST,FALSE);
curl_setopt(
$ch
, CURLOPT_HEADER, FALSE);
curl_setopt(
$ch
, CURLOPT_RETURNTRANSFER, TRUE);
if
(WxPayConfig::CURL_PROXY_HOST !=
"0.0.0.0"
&& WxPayConfig::CURL_PROXY_PORT != 0){
curl_setopt(
$ch
,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
curl_setopt(
$ch
,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
}
//运行curl,结果以jason形式返回
$res
= curl_exec(
$ch
);
curl_close(
$ch
);
//取出accessToken
$data
= json_decode(
$res
,true);
$accessToken
=
$data
[
'access_token'
];
$this
->accessToken =
$accessToken
;
return
$accessToken
;
}
/**
*
* 获取用户信息
*
*/
public
function
GetUserInfo()
{
$access_token
=
$this
->GetAccessToken();
$getData
=
$this
->data;
$urlObj
[
"access_token"
] =
$access_token
;
//$getData["access_token"];//this->GetAccessToken();
$urlObj
[
"openid"
] =
$getData
[
"openid"
];
$urlObj
[
"lang"
] =
"zh_CN"
;
$bizString
=
$this
->ToUrlParams(
$urlObj
);
//初始化curl
$ch
= curl_init();
//设置超时
curl_setopt(
$ch
, CURLOPT_TIMEOUT,
$this
->curl_timeout);
curl_setopt(
$ch
, CURLOPT_URL,
$url
);
curl_setopt(
$ch
, CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt(
$ch
, CURLOPT_SSL_VERIFYHOST,FALSE);
curl_setopt(
$ch
, CURLOPT_HEADER, FALSE);
curl_setopt(
$ch
, CURLOPT_RETURNTRANSFER, TRUE);
if
(WxPayConfig::CURL_PROXY_HOST !=
"0.0.0.0"
&& WxPayConfig::CURL_PROXY_PORT != 0){
curl_setopt(
$ch
,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
curl_setopt(
$ch
,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
}
//运行curl,结果以jason形式返回
$res
= curl_exec(
$ch
);
curl_close(
$ch
);
//取出openid
$userInfo
= json_decode(
$res
,true);
$this
->userInfo =
$userInfo
;
return
$userInfo
;
}
|
效果如下:
下单付款:
这个官方给出的Demo有,就不多说了。
以下为微信内和h5页面的对比:
再来说说h5的微信支付,其它和微信内的支付差不了多少。对比图如下:
点击立即付款按钮时动作分别是
微信内
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
|
var
PayApiArgs;
//调用微信JS api 支付
function
jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest'
,
PayApiArgs,
function
(res){
WeixinJSBridge.log(res.err_msg);
if
(res.err_msg ==
"get_brand_wcpay_request:cancel"
)
{
showMessage(
"用户取消支付"
);
}
else
if
(res.err_msg ==
"get_brand_wcpay_request:ok"
)
{
showMessage(
"支付成功"
,
function
()
{
WeixinJSBridge.call(
'closeWindow'
);
});
}
else
if
(res.err_msg ==
"get_brand_wcpay_request:fail"
)
{
showMessage(
"支付失败"
,
function
(){
writeLog(
"err_code:"
+res.err_code+
",err_desc:"
+res.err_desc+
", err_msg:"
+res.err_msg, 1);
});
}
}
);
}
$.get(
'CreatOrder.php'
,
function
(data, status){
var
dtatObj = JSON.parse(data);
if
(dtatObj.ret == 1){
PayApiArgs = dtatObj.data;
callpay();
}
else
{
showMessage(dtatObj.msg)
}
});
|
h5页面
1
2
3
4
5
6
7
8
9
10
|
showLoading(
"创建订单中"
);
$.get(
'CreatOrder.php'
,
function
(data){
closeLoading();
var
dtatObj = JSON.parse(data);
if
(dtatObj.ret == 1){
window.location.href=dtatObj.mweb_url;
//跳转到中间页面自动拉起微信客户端
}
else
{
showMessage(dtatObj.msg)
}
})
|
上面页面中使用的样式均为weui