2023年11月28日发(作者:)

C#版本】微信公众号模板消息对接(⼆)(图⽂详解)

本篇⽂章承接上⼀篇⽂章内容,

特此说明:本篇⽂章为个⼈原创⽂章,创作不易,未经作者本⼈同意、许可等条件,不得以任何形式搬运、转载、抄袭(等包括但不限于上述⼿段)本⽂

章,否则保留追究有关侵权⼈责任的权利。

⼀、⽹页授权业务设计

可能会有⼩伙伴要说了,咱不是讲解微信模板消息的开发嘛?怎么⼜扯到⽹页授权开发了?你这不是跑题了吗?然⽽事实并⾮如此,且听我慢慢细细道来。

1步:

当我们(消息推送者)要给某位公众号关注者(消息接收者消息被推送者)推送⼀条消息时,我们必须要先知道这位公众号关注者的唯⼀且正确的信息OpenID

或者

UnionID后才能推送消息(例如:就像你给某⼈打电话时必须先知道TA的正确的电话号码,不然你怎么确定你输⼊的号码就是你想打给电话的那个⼈,是⼀样的道理),

防⽌消息推送给错误的公众号关注者。即该消息的消息接收者正是我们要推送的消息的消息被推送者。

2步:

假设我们已经获取到公众号关注者的唯⼀且正确的信息,然⽽获取到的上述信息不包含公众号关注者的特征信息,实际上就是⼀串⽆任何含义的字符串,⽆法知道这条

唯⼀且正确的信息对应我们业务系统中的哪位⽤户,也有可能这位公众号关注者还未在我们业务系统中注册过账号。

3步:

我们需要在微信公众号中设计⼀个信息双向绑定的业务需求。在这个页⾯中,我们不仅要获取到公众号关注者的唯⼀且正确的信息,还需要公众号关注者主动提供并填

在我们业务系统中⽤户主动填写的⾃⾝的具有唯⼀区分性的信息(例如:⼿机号、邮箱号等信息)。这样⼀来,通过中间桥梁信息(⼿机号、邮箱号等信息)就能把公众号关

注者的唯⼀且正确的信息与我们业务系统中⽤户表⾥的唯⼀信息(假设是uid)进⾏绑定。即:我们就能把⽤户在我们公众号的唯⼀且正确的信息与我们业务系统中⽤户表⾥的唯

⼀信息进⾏⼀⼀对应,形成信息双向绑定关系。如果公众号关注者主动提供的信息在我们业务系统的⽤户表⾥不存在,还需要设计⽤户注册等业务需求,注册成功后再进⾏信息

双向绑定。

4步:

当我们业务系统中的某个功能触发时,需要给公众号关注者推送提醒消息,我们便可通过第3步中建⽴的⼀⼀对应双向绑定关系,拿我们业务系统中⽤户的唯⼀信息

(假设是uid)查询到公众号关注者的唯⼀且正确的信息。当获取到公众号关注者的唯⼀且正确的信息后,便可以给其推送微信公众号消息啦。

5步:

我们业务系统的⽤户唯⼀信息获取⾮常容易,可公众号关注者的唯⼀且正确的信息怎么获取呢?这就是我们下⼀部分要讲解的内容——“⽹页授权获取OpenID”

下图⼤致总结了上述步骤内容,供⼩伙伴参考:

⼆、⽹页授权获取OpenID的前提准备及说明

如果⽤户在微信客户端中访问第三⽅⽹页,公众号可以通过微信机制,来获取⽤户基本信息,进⽽实现业务逻辑。

1、关于⽹页授权回调域名的说明

在微信公众号请求⽤户⽹页授权之前,开发者需要先到公众平台官⽹中的开发 -> 接⼝权限 -> ⽹页服务 -> ⽹页帐号 -> ⽹页授权获取⽤户基本信息的配置选项中,修改授

权回调域名。请注意,这⾥填写的是域名(是⼀个字符串),⽽不是URL,因此请勿加 等协议头。

微信公众平台测试号可以在中的【体验接⼝权限表】⼀栏,在⽹页服务->⽹页账号->⽹页授权获取⽤户基本信息的操作选项中,点击修改按钮,弹出【OAuth2.0⽹页授

权】对话框,并在中填写域名信息,见下⾯两张图所⽰。

授权回调页⾯域名输⼊框

授权回调域名配置规范为全域名,⽐如需要⽹页授权的域名为:,配置以后此域名下⾯的页⾯/ /

都可以进⾏OAuth2.0鉴权。但 ⽆法进⾏OAuth2.0鉴权。

如果公众号登录授权给了第三⽅开发者来进⾏管理,则不必做任何设置,由第三⽅代替公众号实现⽹页授权即可。

2、关于⽹页授权的两种scope的区别说明

snsapi_basescope发起的⽹页授权,是⽤来获取进⼊页⾯的⽤户的openid的,并且是静默授权并⾃动跳转到回调页的。⽤户感知的就是直接进⼊了回调页(往往是业

务页⾯)

snsapi_userinfoscope发起的⽹页授权,是⽤来获取⽤户的基本信息的。但这种授权需要⽤户⼿动同意,并且由于⽤户同意过,所以⽆须关注,就可在授权后获取该⽤

户的基本信息。

⽤户管理类接⼝中的“”,是在⽤户和公众号产⽣消息交互或关注后事件推送后,才能根据⽤户OpenID来获取⽤户基本信息。这个接⼝,包括其他微信接⼝,都是需要该⽤

户(即openid)关注了公众号后,才能调⽤成功的。

3、关于⽹页授权access_token和普通access_token的区别

微信⽹页授权是通过OAuth2.0机制实现的,在⽤户授权给公众号后,公众号可以获取到⼀个⽹页授权特有的接⼝调⽤凭证(⽹页授权access_token),通过⽹页授权

access_token可以进⾏授权后接⼝调⽤,如获取⽤户基本信息;

其他微信接⼝,需要通过基础⽀持中的“”接⼝来获取到的普通access_token调⽤。

4UnionID机制,以及UnionIDOpenID的区别和联系

中已有多处关于该⽅⾯信息的详细介绍,本⼈在此就不再赘述,有兴趣的⼩伙伴可以⾃⾏上⽹查阅相关资料进⾏了解。

5、⽹页授权流程

具体⽽⾔,⽹页授权流程分为以下四步,我们⽬前暂时只⽤到前⾯两步即可满⾜业务需求:

1. 引导⽤户进⼊授权页⾯->⽤户同意授权->获取code

2. 通过code换取⽹页授权access_token(与基础⽀持中的access_token不同)

3. 如果需要,开发者可以刷新⽹页授权access_token,避免过期

4. 通过⽹页授权access_tokenopenid获取⽤户基本信息(⽀持UnionID机制)

三、⽹页授权获取OpenID

1步:⽤户同意授权,获取code

在确保微信公众账号拥有授权作⽤域(scope参数)的权限的前提下(服务号获得⾼级接⼝后,默认拥有scope参数中的snsapi_basesnsapi_userinfo),引导关注者打开如下

页⾯:

/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

若提⽰该链接⽆法访问,请检查参数是否填写错误,是否拥有scope参数对应的授权作⽤域权限。

尤其注意:由于授权操作安全等级较⾼,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页⾯将⽆法正常访问

此处提供微信官⽅给予的参考链接(请在微信客户端中打开此链接体验)

scopesnsapi_base

/connect/oauth2/authorize?

appid=wx520c15f417810387&redirect_uri=https%3A%2F%%2Fphp%%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope

scopesnsapi_userinfo

/connect/oauth2/authorize?

appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%%2Foauth_&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

尤其注意:跳转回调redirect_uri,应当使⽤https链接来确保授权code的安全性。

下⾯讲解参数说明:

参数是否必须说明

appid公众号的唯⼀标识

redirect_uri授权后重定向的回调链接地址, 请使⽤ urlEncode 对链接进⾏处理

response_type返回类型,请填写code

scope

state重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节

#wechat_redirect⽆论直接打开还是做页⾯302重定向时候,必须带此参数

应⽤授权作⽤域,snsapi_base (不弹出授权页⾯,直接跳转,只能获取⽤户openid),snsapi_userinfo

(弹出授权页⾯,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要⽤户授权,

也能获取其信息

以下为本⼈测试时所使⽤的url链接,仅供参考使⽤,特别注意redirect_uristate参数的赋值:

/connect/oauth2/authorize?

appid=wx70d54bbda1ef76b8&redirect_uri=http%3A%2F%%3A8031%2Fweb%&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分钟未被使⽤⾃动过期。

⽤户同意授权后,跳转页⾯时可能会发⽣的错误返回码说明如下:

返回码说明

10003redirect_uri域名与后台配置不⼀致

10004此公众号被封禁

10005此公众号并没有这些scope的权限

10006必须关注此测试号

10009操作太频繁了,请稍后重试

10010scope不能为空

10011redirect_uri不能为空

10012appid不能为空

10013state不能为空

10015公众号未授权第三⽅平台,请检查授权状态

10016不⽀持微信开放平台的Appid,请使⽤公众号Appid

2步:通过code换取⽹页授权access_token

⾸先请注意,这⾥通过code换取的是⼀个特殊的access_token,与基础⽀持中的(该access_token⽤于调⽤其他接⼝)不同。公众号可通过下述接⼝来获取⽹页授权

⽹页授权

access_token。如果⽹页授权的作⽤域为snsapi_base,则本步骤中获取到⽹页授权access_token的同时,也获取到了openidsnsapi_base式的⽹页授权流程即到此为⽌。

尤其注意:由于公众号的secret和获取到的access_token安全级别都⾮常⾼,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取⽤户信

息等步骤,也必须从服务器发起。

在第⼀步中我们已经获取到code的值了,接下来请求以下链接获取access_token

/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明:

参数是否必须说明

appid公众号的唯⼀标识

secret公众号的appsecret

code填写第⼀步获取的code参数

grant_type填写为authorization_code

以下为本⼈测试过成中所使⽤的url链接,因为参数的值不能外泄,故部分值使⽤星号(*)替换:

secret

/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_inaccess_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"

}

本篇⽂章到此结束,但本系列⽂章还未结束。