微信开发技术文档
网页授权——登陆
获取用户信息,需要获取来自微信的授权access_token。获取access_token的方式有两种.
一种是服务器通过调用微信开放接口全局获取
适用于:用户关注的时候获取到用户信息,自动返回用户名称 + 欢迎信息
//调用接口
'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET'
//微信返回
{
"access_token": 'token'//如"NU7Kr6v9L9TQaqm5NE3OTPctTZx797Wxw4Snd2WL2HHBqLCiXlDVOw2l-Se0I-WmOLLniAYLAwzhbYhXNjbLc_KAA092cxkmpj5FpuqNO0IL7bB0Exz5s5qC9Umypy-rz2y441W9qgfnmNtIZWSjSQ",
"expires_in": 7200
}
在根据tokenh和用户的openid(用户和公众号产生交互均可获得)去获取更详细的用户信息
//接口调用
"https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID"
//微信返回
{
"subscribe": 1,
"openid": "oLVPpjqs2BhvzwPj5A-vTYAX4GLc",
"nickname": "刺猬宝宝",
"sex": 1,
"language": "zh_CN",
"city": "深圳",
"province": "广东",
"country": "中国",
"headimgurl": "http://wx.qlogo.cn/mmopen/JcDicrZBlREhnNXZRudod9PmibRkIs5K2f1tUQ7lFjC63pYHaXGxNDgMzjGDEuvzYZbFOqtUXaxSdoZG6iane5ko9H30krIbzGv/0",
"subscribe_time": 1386160805
}
另一种是通过OAuth2.0方式弹出授权页面获得用户基本信息
适用于:
- 网页获取用户信息
- 朋友圈中获取用户信息
- 在自定义菜单中获取用户信息
这里简单介绍下什么是OAuth授权:
OAuth2.0网页授权
OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、移动或桌面应用上存储的私密的资源(如用户个人信息、照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用
微信公众平台OAuth2.0授权
微信公众平台OAuth2.0授权详细步骤如下:
- 用户关注微信公众账号。
- 微信公众账号提供用户请求授权页面URL。
- 用户点击授权页面URL,将向服务器发起请求
- 服务器询问用户是否同意授权给微信公众账号(scope为snsapi_base时无此步骤)
- 用户同意(scope为snsapi_base时无此步骤)
- 服务器将CODE通过回调传给微信公众账号
- 微信公众账号获得CODE
- 微信公众账号通过CODE向服务器请求Access Token
- 服务器返回Access Token和OpenID给微信公众账号
- 微信公众账号通过Access Token向服务器请求用户信息(scope为snsapi_base时无此步骤)
- 服务器将用户信息回送给微信公众账号(scope为snsapi_base时无此步骤)
我们的应用场景一个公众号网页,所以选择OAuth授权方式。
根据以上授权步骤,用户进入我们页面后,若这是一个未登陆用户,那么我们会跳转到一个授权页面,用户访问授权页面,授权后登陆成功,并前往回调地址。
授权页面构造地址如下:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx8888888888888888&redirect_uri=http://mascot.duapp.com/oauth2.php&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
参数说明:
参数 | 是否必须 | 说明 |
---|---|---|
appid | y | 公众号的唯一标识 |
redirect_uri | y | 授权后重定向的回调链接地址(注意使用encodeURIComponent()转码) |
response_type | y | 返回类型,这里直接填写code,微信会返回我们需要的code |
scope | y | 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息) |
state | n | 重定向后会带上state参数,开发者可以填写任意参数值 |
#wechat_redirect | n | 直接在微信打开链接,可以不填此参数。做页面302重定向时候,必须带此参数 |
用户在授权页面点击授权后,跳转redirect_uri
后会带一个code参数,服务器使用这个code即可去向微信服务器请求用户的信息(7,8,9,10,11步骤)
access_token这种信息最好在服务端请求,不要传给客户端,所以在前端将code传给后端之后,所有的操作都需要在服务端操作,前端只需要在服务端请求完成后获取用户的信息即可。
更多关于服务端请求微信的步骤可以参考官方文档,也可以参考这篇文章,讲的可以说非常清晰了微信网页授权登录实践总结
微信支付
微信JS-JDK开发文档
JS调用微信API实现微信支付
接下去到了支付的环节。
作为一个前端这部分要做的事情并不复杂,微信提供了强大的JDK
官方文档给出的代码是这样
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();
}
名称 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
---|---|---|---|---|---|
公众号id | appId | 是 | String(16) | wx8888888888888888 | 商户注册具有支付权限的公众号成功后即可获得 |
时间戳 | timeStamp | 是 | String(32) | 1414561699 | 当前的时间,其他详见时间戳规则 |
随机字符串 | nonceStr | 是 | String(32) | 5K8264ILTKCH16CQ2502SI8ZNMTM67VS | 随机字符串,不长于32位。推荐随机数生成算法 |
订单详情扩展字符串 | package | 是 | String(128) | prepay_id=123456789 | 统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=*** |
签名方式 | signType | 是 | String(32) | MD5 | 签名类型,默认为MD5,支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致 |
签名 | paySign | 是 | String(64) | C380BEC2BFD727A4B6845133519F3AD6 | 签名,详见签名生成算法 |
至此,微信内调用微信支付完成
趟过的各种坑
1. 授权登陆 —— 回调地址错误
这里注意redirect_uri需要使用encodeURIComponent()进行转码,比如vue的hash模式会带有一个#号,如果回调地址中含有#而没有做转义,会报response_type
错误。不要问我是怎么知道的
history路由模式可以去掉#号,但是直接访问test.swarma.org/courseList
会一片白屏,其实是没有找到有这个路由。这就需要服务端进行配置,在路由未找到静态资源时自动加载index.html(这个index.html就是项目依赖的文件)。
需要将url转义,可以使用浏览器自带方法encodeURIComponent()
,转义#,=等(encodeURL()
用于转义中文字符)
2. 支付失败
支付失败有很多原因,前端代码保证正确的情况下,关注传参是否正确
最后定位后台给出的参数并不是json格式,JSON.parse()
之后,就显示支付成功
//在支付代码中可以看到第二个参数是一个json对象
{
"appId":"wx2421b1c4370ec43b", //公众号名称,由商户传入
"timeStamp":"1395712654", //时间戳,自1970年以来的秒数
"nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串
"package":"prepay_id=u802345jgfjsdfgsdg888",
"signType":"MD5", //微信签名方式:
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
},