第一步:用户同意授权,获取code
在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下
服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
给用户推送消息的时候,把点击的url设为上面那个,把需要用户真正进入的个人网页地址放在REDIRECT_URI处,这样,当用户点击了该链接,会从微信获取对应的CODE值,并传递和跳转到自己定义的跳转地址REDIRECT_URI.
不过,该跳转地址似乎需要微信授权,引用-这个网页授权需要登录微信公众平台,点击左侧菜单“开发者中心”,在右侧“权限列表”中找到“网页账号”,点击最右侧的修改,把测试的网址写进去,注意不要加http。填好后,这个坑就趟过去了。参见http://blog.csdn.net/molaifeng/article/details/42968673
你需要在跳转地址的页面里如php,jsp等里获取到对应的CODE值。
需要给上面那个url传递的参数,分别为appid-公众号,redirect_uri-你想要用户看到和支付的个人网页地址,
response_type-code返回类型,这里填code
Scope-snsapi_base 只可以获取用户端的openid
Scope-snsapi_userinfo 可以获取用户的个人信息,微信会弹出提醒用户是否授权的界面,用户自行选择,默认会获取openid
State重定向后微信会将该产生传递给你自己的页面,会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect 必须带
第二步:通过code换取网页授权access_token
上面微信处理完后,会跳转到你自定义的页面,并向你传递code和state参数
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
这时候,你要通过ajax(http:GET(请使用https协议)向上面这个地址发送四个数据,并请求json数据,appid为公众号,secret为公众号的appsecret,code为微信传递给你的,
Grant_type为授予类型 填为authorization_code
那么怎么获取appsecret呢,见百度经验 http://jingyan.baidu.com/album/6525d4b12af618ac7c2e9468.html
appid和appsecret是微信公众平台服务号才有的,如果自己的公众平台不是服务号,需要升级为服务号。
首先登录服务号,登录“服务”条目,“服务中心”,看到自定义菜单一栏,选择开发模式,下翻页面,就可以看到自己公众平台帐号的appid和appsecret,其中appsecret,自己可以重新设置
好了这样,你准备好了向微信传递的四个参数,发送ajax请求,如果正确响应时获得对应的返回值如下:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
这时候,我们最后支付传递给微信或者传递给后台(不必需)所需要的openid已经在里面了,
access_token主要用来在scope为snsapi_userinfo 时,用来获取用户个人资料。
Openid是用户的标识,用来识别是具体哪个用户在使用微信支付,access_token,网页授权接口调用凭证
错误时会返回如下
{"errcode":40029,"errmsg":"invalid code"}
各种错误码对应的含义,可以参见 http://mp.weixin.qq.com/wiki/17/fa4e1434e57290788bde25603fa2fcbd.html
第三步:拉取用户信息(需scope为 snsapi_userinfo)
如果第一步scope填写的snsapi_userinfo, 并且用户在微信弹出的授权页面里授予你获取个人信息的权限
那么通过第二步获得的access_token和openid,还可以获取用户的个人信息
当然,考虑支付的话,只需要openid和access_token就够了,如果需要根据用户信息个性化支付界面和后续的支付完成失败等页面,
则需要通过ajax get方法传递第二步获得的openid和access_token请求下面的链接,并获得相应的json数据进行处理:
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
正确时获得的json数据如下:
{
"openid":" OPENID",
" nickname": NICKNAME, //用户昵称
"sex":"1", //性别
"province":"PROVINCE" //省份
"city":"CITY", //所在城市
"country":"COUNTRY", //所在国家
"headimgurl": //用户头像 "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege":[
"PRIVILEGE1"
"PRIVILEGE2"
],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" //多平台,手机,ios, android公用的唯一id
}
第一步到第三步请参考 http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
第四步:获取用户购买商品信息,通知后台拉起统一支付,获取相应的prepay_id和签名, 随机串, 时间戳
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
折腾了这么久,终于要进入支付的主题了。
前面三个步骤,我们已经获得了openid和access_token, 然后等待用户选择相应的商品。
等我们的用户选择了想要购买的商品,我们获得相应的商品名字,金额,
在正式的微信支付交互前,我们还需要先传递到服务器后台获得一个prepay_id 和 签名。
那么我们需要向后台要求一个请求prepay_id和签名的网络地址,这个地址个人服务器提供,并通过ajax get 或者Post向后台请求
那么后台怎么得到这个prepay_id和签名呢,后台需要向微信通过https://api.mch.weixin.qq.com/pay/unifiedorder这个地址发起请求,发送的数据如下,不明白为什么是xml而不是json
<xml>
<appid>wx2421b1c4370ec43b</appid>
<attach>支付测试</attach>
<body>JSAPI支付测试</body>
<mch_id>10000100</mch_id>
<nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
<notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>
<openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
<out_trade_no>1415659990</out_trade_no>
<spbill_create_ip>14.23.150.211</spbill_create_ip>
<total_fee>1</total_fee>
<trade_type>JSAPI</trade_type>
<sign>0CB01533B8C1EF103065174F50BCA001</sign>
</xml>
我们发现后台需要前台传递的数据有 appid(公众号id), mch_id(商户号) openid(第二步获取的)body(商品描述) total_fee(个人定义支付页面里用户选择购买的商品金额) spbill_create_ip(用户终端ip) trad_type() JSAPI
很奇怪的是openid竟然不是后台统一支付必须要传递给微信的参数,那么我们获取了openid干嘛
而后台拉起统一支付后获得的prepay_id 和sign, code_url和微信返回的随机字符串nonce_str则可以传递给前台进行使用
Code_url为前台显示给用户商品要进行的扫一扫支付需要的二维码
后台需要在notify_url参数里填写用户在前台点击支付,并在微信支付成功后通知后台成功的网页地址,便于进一步处理
这时我们发现,尽管后台在生成预支付prepaid_id请求的过程中并不必须传递openid,但是在支付成功回调里会收到openid的返回值,用来确定是哪个用户付款成功,这说明微信支付的思路是:对于某个具体商品,在用户支付成功前,后台并不需要知道对方是谁。
相应的错误码和原始页面见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
这时候在统一支付成功之后,后台向前端返回请求的prepay_id,签名或者code_url
这个时候,前端就获取了进行支付所需要的信息,可以进行下一步了
第五步:h5页面前端和微信达成支付功能
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7
当用户点击支付,我们发现利用下面的方法就可以进行支付了,所需要的数据是appid(公众号)
Package就是后台传回的prepay_id,paySign签名,后台传递,nonceStr随机串后台传递
function onBridgeReady(){
WeixinJSBridge.invoke(
‘getBrandWCPayRequest‘, {
"appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入
"timeStamp":" 1395712654", //时间戳,自1970年以来的秒数
"nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串
"package" : "prepay_id=u802345jgfjsdfgsdg888",
"signType" : "MD5", //微信签名方式:
"paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
}
);
}
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener(‘WeixinJSBridgeReady‘, onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent(‘WeixinJSBridgeReady‘, onBridgeReady);
document.attachEvent(‘onWeixinJSBridgeReady‘, onBridgeReady);
}
}else{
onBridgeReady();
}