0%

微信接入的点点滴滴

工作需要,来总结一下如何快速的接入微信。

公众号接入

通常来说,官方推荐的架构如下:

@startuml GZ
!include C4_Container.puml

System_Boundary(sys,"内部系统") {
Container(proxy1,"API PROXY","Java/Python/Go/NodeJS","专一与微信API对接, 不同的服务器可以负责对接不同的业务逻辑, 更可进行调用频率、权限限制。")
Container(proxy2,"API PROXY","Java/Python/Go/NodeJS","专一与微信API对接, 不同的服务器可以负责对接不同的业务逻辑, 更可进行调用频率、权限限制。")
Container(logic1, "业务逻辑服务器","Java/Python/Go/NodeJS")
Container(logic2, "业务逻辑服务器","Java/Python/Go/NodeJS")
Container(h5, "H5", "Vue/Uni APP")
Container(web, "Web", "Vue")
Container(ctrl, "AccessToken中控服务器", "Java/Python/Go/NodeJS","提供主动刷新和被动刷新机制来刷新accessToken并存储 (为了防止并发刷新,注意加并发锁), 提供给业务逻辑有效的accessToken")

Rel(h5, logic1, "use")
Rel(web, logic2, "use")
Rel(logic1, proxy1, "call")
Rel(logic2, proxy2, "call")
Rel(logic1, ctrl, "获取")
Rel(logic2, ctrl, "获取")
Rel(ctrl, proxy1, "刷新")
Rel(ctrl, proxy2, "刷新")
}
System_Ext(wxapi,"微信API")
Rel(proxy1, wxapi, "call")
Rel(proxy2, wxapi, "call")
@enduml

GZ

为什么会这么复杂?理论上不是直接调用 微信的 API 就行了么。那当然是因为微信要进行各种控制了,提供接口能力给你,要做限制,说不定还想要收费呢。

也就是说,所有的接口调用都需要带上 access_token 来作为参数,否则就不能进行调用。

access_token 的获取

curl https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

网页开发

网页授权

当用户在微信客户端中访问第三方网页的时候,可以通过授权机制来获取用户的信息。事实上,这个授权的目的,是为了让我们能在我们自己的网页中获取到微信用户的一些信息,这些信息一样需要前往微信的 API 进行获取。

与我们调用微信的开放能力不同,获取用户的信息需要得到用户的授权。我们需要调用一些额外的 API 来让微信提醒用户进行授权,并回调到我们的系统中来。

提醒用户进行授权

curl https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

引导用户进入这个链接,微信会弹出框来提示用户进行授权(snsapi_base) 则是静默授权。
用户授权后就会进入到我们指定的回调地址 redirect_uri,这个必须和我们在公众号设置的一致。授权之后,会加上一个code 参数,就表示用户进行授权了,我们可以在我们的网页中获取到这个 code

获取网页授权 access_token

这个是 token 区别于我们主动获取的 token,这个 token 应该是代表与用户授权我们访问其信息相关的东西。

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

拉取用户信息(需 scope 为 snsapi_userinfo)

这样我们就可以根据拿到的 token 和 Openid 去获取用户的信息了。

http:GET(请使用 https 协议) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

jssdk

JSSDK 是微信本身的一些功能,以 JS 绑定的形式开放来给我们调用。

但是,一个网页想要使用 JSSDK 也需要得到微信的许可和授权。

所有需要使用 JS-SDK 的页面必须先注入配置信息,否则将无法调用(同一个 url 仅需调用一次,对于变化 url 的 SPA 的 web app 可在每次 url 变化时进行调用,目前 Android 微信客户端不支持 pushState 的 H5 新特性,所以使用 pushState 来实现 web app 的页面会导致签名失败,此问题会在 Android6.2 中修复)。

所以一般分成几大步:

  1. 绑定域名
  2. 引入 jssdk 文件
  3. 注入配置信息
  4. 处理配置信息的验证结果(成功或失败)
  5. 调用接口。

关于在于第二步,官方文档说得语焉不详,因为配置信息需要将配置的信息(使用权限信息)进行签名,而签名这个东西又需要微信的票据。因此这一步是需要在服务端完成的。

权限签名步骤及算法

签名逻辑必须在服务端完成。

  1. 获取 access_token
  2. 获取 jsapi_ticket https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
  3. 签名逻辑:

    sha1(jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value)

    其中, url 必须是完整的 url,noncestr 是随机字符串, timestamp 是时间戳。

  4. 签名逻辑必须在服务端完成,将这些信息返回来,给到客户端,客户端才能调用 config 注入配置信息,获得使用权限。

有一些非常棒的库来帮我们做了这些事情,如 wxjava