PHP 微信公众号和html5接入微信支付

最近公司项目需要接入微信支付购买道具,本人负责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 );
     $url "https://api.weixin.qq.com/cgi-bin/token?" . $bizString ;
     //初始化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 );
     $url "https://api.weixin.qq.com/cgi-bin/user/info?" . $bizString ;
     //初始化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

原文地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值