【C#版本】微信公众号模板消息对接(二)(图文详解)
本篇文章承接上一篇文章内容,点击此段文字传送至上一篇文章。
特此说明:本篇文章为个人原创文章,创作不易,未经作者本人同意、许可等条件,不得以任何形式搬运、转载、抄袭(等包括但不限于上述手段)本文章,否则保留追究有关侵权人责任的权利。
一、网页授权业务设计
可能会有小伙伴要说了,咱不是讲解微信模板消息的开发嘛?怎么又扯到网页授权开发了?你这不是跑题了吗?然而事实并非如此,且听我慢慢细细道来。
第1步:当我们(“消息推送者”)要给某位公众号关注者(“消息接收者”、“消息被推送者”)推送一条消息时,我们必须要先知道这位公众号关注者的唯一且正确的信息(OpenID或者UnionID)后才能推送消息(例如:就像你给某人打电话时必须先知道TA的正确的电话号码,不然你怎么确定你输入的号码就是你想打给电话的那个人,是一样的道理),防止消息推送给错误的公众号关注者。即该消息的消息接收者正是我们要推送的消息的消息被推送者。
第2步:假设我们已经获取到公众号关注者的唯一且正确的信息,然而获取到的上述信息不包含公众号关注者的特征信息,实际上就是一串无任何含义的字符串,无法知道这条唯一且正确的信息对应我们业务系统中的哪位用户,也有可能这位公众号关注者还未在我们业务系统中注册过账号。
第3步:我们需要在微信公众号中设计一个信息双向绑定的业务需求。在这个页面中,我们不仅要获取到公众号关注者的唯一且正确的信息,还需要公众号关注者主动提供并填写在我们业务系统中用户主动填写的自身的具有唯一区分性的信息(例如:手机号、邮箱号等信息)。这样一来,通过中间桥梁信息(手机号、邮箱号等信息)就能把公众号关注者的唯一且正确的信息与我们业务系统中用户表里的唯一信息(假设是uid)进行绑定。即:我们就能把用户在我们公众号的唯一且正确的信息与我们业务系统中用户表里的唯一信息进行一一对应,形成信息双向绑定关系。如果公众号关注者主动提供的信息在我们业务系统的用户表里不存在,还需要设计用户注册等业务需求,注册成功后再进行信息双向绑定。
第4步:当我们业务系统中的某个功能触发时,需要给公众号关注者推送提醒消息,我们便可通过第3步中建立的一一对应双向绑定关系,拿我们业务系统中用户的唯一信息(假设是uid)查询到公众号关注者的唯一且正确的信息。当获取到公众号关注者的唯一且正确的信息后,便可以给其推送微信公众号消息啦。
第5步:我们业务系统的用户唯一信息获取非常容易,可公众号关注者的唯一且正确的信息怎么获取呢?这就是我们下一部分要讲解的内容——“网页授权获取OpenID”。
下图大致总结了上述步骤内容,供小伙伴参考:
文章图片
二、网页授权获取OpenID的前提准备及说明
如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。
1、关于网页授权回调域名的说明
- 在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 -> 接口权限 -> 网页服务 -> 网页帐号 -> 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头。
- 微信公众平台测试号可以在测试号管理页面中的【体验接口权限表】一栏,在“网页服务->网页账号->网页授权获取用户基本信息”的操作选项中,点击修改按钮,弹出【OAuth2.0网页授权】对话框,并在授权回调页面域名输入框中填写域名信息,见下面两张图所示。
- 授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com 无法进行OAuth2.0鉴权。
- 如果公众号登录授权给了第三方开发者来进行管理,则不必做任何设置,由第三方代替公众号实现网页授权即可。
文章图片
文章图片
2、关于网页授权的两种scope的区别说明
- 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)
- 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
- 用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。
- 微信网页授权是通过OAuth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭证(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息;
- 其他微信接口,需要通过基础支持中的“获取access_token”接口来获取到的普通access_token调用。
4、UnionID机制,以及UnionID与OpenID的区别和联系 微信公众号开发文档中已有多处关于该方面信息的详细介绍,本人在此就不再赘述,有兴趣的小伙伴可以自行上网查阅相关资料进行了解。
5、网页授权流程 具体而言,网页授权流程分为以下四步,我们目前暂时只用到前面两步即可满足业务需求:
- 引导用户进入授权页面->用户同意授权->获取code
- 通过code换取网页授权access_token(与基础支持中的access_token不同)
- 如果需要,开发者可以刷新网页授权access_token,避免过期
- 通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
尤其注意:由于授权操作安全等级较高,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页面将无法正常访问
此处提供微信官方给予的参考链接(请在微信客户端中打开此链接体验):
- scope为snsapi_base
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect
- scope为snsapi_userinfo
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
尤其注意:跳转回调redirect_uri,应当使用https链接来确保授权code的安全性。
下面讲解参数说明:
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | 公众号的唯一标识 |
redirect_uri | 是 | 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理 |
response_type | 是 | 返回类型,请填写code |
scope | 是 | 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 ) |
state | 否 | 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 |
#wechat_redirect | 是 | 无论直接打开还是做页面302重定向时候,必须带此参数 |
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx70d54bbda1ef76b8&redirect_uri=http%3A%2F%2Fhuaweiit.kmdns.net%3A8031%2Fweb%2Findex.html&response_type=code&scope=snsapi_base&state=iZOHC#wechat_redirect
以下为本人测试时跳转后的HTML页面代码,仅供参考使用:
- 锐客网 微信公众号关注用户网页授权后,跳转的页面
测试号的公众号如何找到并关注呢?在第一篇文章中已有详细介绍,此处将一笔带过(在测试号管理页面中找到“测试号二维码”一栏,在此栏下方有一张二维码,此二维码便是测试号的公众号二维码,用微信APP扫一扫功能扫描此码即可进入测试号的公众号)。
把上述测试url链接发送到测试号的公众号会话框中,如下图所示:
文章图片
点击会话框中的链接打开它,如果用户同意授权,页面将跳转至:
redirect_uri/?code=CODE&state=STATE
跳转后的页面显示如下图,小伙伴们需要特别关注下图片中红色框框出来的内容,正好符合redirect_uri/?code=CODE&state=STATE格式。redirect_uri后面附带的state参数的值“iZOHC”正是链接中我们赋予的值,被原封不动的返回了;code参数的值正是第二步通过code换取网页授权access_token中所需要的code值,此时我们已经获取到了。
文章图片
code说明:code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
用户同意授权后,跳转页面时可能会发生的错误返回码说明如下:
返回码 | 说明 |
10003 | redirect_uri域名与后台配置不一致 |
10004 | 此公众号被封禁 |
10005 | 此公众号并没有这些scope的权限 |
10006 | 必须关注此测试号 |
10009 | 操作太频繁了,请稍后重试 |
10010 | scope不能为空 |
10011 | redirect_uri不能为空 |
10012 | appid不能为空 |
10013 | state不能为空 |
10015 | 公众号未授权第三方平台,请检查授权状态 |
10016 | 不支持微信开放平台的Appid,请使用公众号Appid |
尤其注意:由于公众号的secret和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。
在第一步中我们已经获取到code的值了,接下来请求以下链接获取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明:
参数 | 是否必须 | 说明 |
appid | 是 | 公众号的唯一标识 |
secret | 是 | 公众号的appsecret |
code | 是 | 填写第一步获取的code参数 |
grant_type | 是 | 填写为authorization_code |
secret
参数的值不能外泄,故部分值使用星号(*)替换:【【C#版本】微信公众号模板消息对接(二)(图文详解)】
https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx70d54bbda1ef76b8&secret=2******d&code=061gBaml2rcFK84KWQll2QA2ha0gBamU&grant_type=authorization_code
接口响应正确时返回的JSON数据包如下:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
返回参数说明:
参数 | 描述 |
---|---|
access_token | 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 |
expires_in | access_token接口调用凭证超时时间,单位(秒) |
refresh_token | 用户刷新access_token |
openid | 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID |
scope | 用户授权的作用域,使用逗号(,)分隔 |
{
"access_token": "54_wCp2aHueMlMUTuoPHr9fg0SY8P0O3m3czggVXvWoBcHCij7i744JigKOyN72LInpsBcp5YpdXELMk2A1ejyi29s4CsGplmjKhiiNvZXqmes",
"expires_in": 7200,
"refresh_token": "54_EOTFhoLvuPLb-YnkbLeTSAm_uQqR8ARkfPS58yBtvrSoxjuDGvubOOC3Ri_S41AvmdxssHFMri-GjRq8pu-DcseZU__e5yrD2Y-RLKZAlgg",
"openid": "oLrmn5rh9480z38etS-YMCDD-cwc",
"scope": "snsapi_base"
}
以下为本人测试时微信服务器某次响应的错误数据:(示例为Code无效错误):
{
"errcode":40029,
"errmsg":"invalid code, rid: 62246a80-00401253-0f5aa6b3"
}
本篇文章到此结束,但本系列文章还未结束。
敬请期待下一篇文章内容,将真正步入主题“模板消息”,
先前文章都是为下一篇文章做铺垫。
点击此段文字传送至本系列文章上一篇文章。
喜欢本人文章的小伙伴记得点个关注哟!!!
顺带顶一下本文,让更多的小伙伴看到本文并受益!!!
推荐阅读
- COMP3811
- 每日leetcode——92. 反转链表 II
- CMP5327 游戏编程
- 仿淘宝固定侧边栏 2020/11/26
- 听说(分布式ID不能全局递增())
- 对于 PHP 框架,我们真的需要使用 LTS 版本吗()
- EEE125 分析
- 历史上的今天|【历史上的今天】12 月 31 日(千年虫问题;DNA 计算之父出生;微机先驱 Cromemco 成立)
- 历史上的今天|【历史上的今天】3 月 6 日(Unix 版权争夺战;豆瓣网上线;谷歌推出了 Google Play)
- c语言socket面试题,【C++工程师面试宝典】学习说明_互联网校招面试真题面经汇总_牛客网...