微信有4種類型的服務(wù):
- 訂閱號祟印,針對媒體和個人,偏向于向用戶傳達咨詢即發(fā)消息(一般是推文)粟害,每天可以群發(fā)一條消息蕴忆,消息被放在“訂閱號消息”欄中。
- 服務(wù)號悲幅,針對企業(yè)和組織套鹅,偏向于交互服務(wù),因為偏向于服務(wù)汰具,所以每月只能發(fā)4次推文卓鹿。
- 企業(yè)號,所有功能都支持
- 小程序
訂閱號和服務(wù)號在開發(fā)者接口權(quán)限上有所不同郁副,服務(wù)號更全面滋尉。不過對于一些基本的接口權(quán)限律歼,訂閱號都能滿足,具體可以參考權(quán)限接口說明。
對于有支付需求的應(yīng)用和蚪,不管是服務(wù)號還是訂閱號都需要做支付申請,但是盡量選擇服務(wù)號遭铺。
出于用戶體驗和安全性方面的考慮搀绣,微信公眾號的注冊有一定門檻,某些高級接口的權(quán)限需要微信認證后才可以獲取恰聘。所以句各,為了幫助開發(fā)者快速了解和上手微信公眾號開發(fā)吸占,熟悉各個接口的調(diào)用,微信推出了微信公眾帳號測試號凿宾,通過手機微信掃描二維碼即可獲得測試號矾屯。
接入微信公眾平臺
環(huán)境準(zhǔn)備:
- 公眾平臺測試賬號(參考上一節(jié))
- 內(nèi)網(wǎng)映射,在接入公眾平臺時初厚,需要提供服務(wù)器的URL地址件蚕,這里使用Natapp做內(nèi)網(wǎng)映射
natapp隧道搭建
微信公眾平臺開發(fā)者模式需要提供服務(wù)器的URL地址,這里使用NATAPP做內(nèi)網(wǎng)穿透产禾。
打開NATAPP官網(wǎng)排作,注冊登錄后,點擊購買隧道亚情,可以使用免費隧道妄痪,也可購買付費隧道。免費隧道與付費隧道不同的是楞件,付費隧道支持固定的二級域名(當(dāng)然衫生,這個二級域名也是需要你購買的),這樣我們每次啟動natapp做內(nèi)網(wǎng)穿透時履因,域名不會改變的障簿,方便調(diào)試。
購買隧道后栅迄,我們做客戶端的配置站故,這里我是Mac環(huán)境,其他環(huán)境參考官網(wǎng)毅舆。
下載natapp客戶端西篓,添加執(zhí)行權(quán)限
# 解壓
? Desktop unzip natapp_darwin_amd64_2_3_9.zip
Archive: natapp_darwin_amd64_2_3_9.zip
inflating: natapp
# 移動natapp到natapp目錄下
? Desktop mkdir ~/natapp && mv natapp ~/natapp/
? Desktop cd ~/natapp
? natapp chmod +x natapp
運行natapp
./natapp -authtoken=xxxxxxxxxx
authtoken的值在我的隧道列表中可以查看。至此憋活,natapp隧道搭建完成岂津,總的流程如下:
- 購買隧道(可以使用免費的隧道),設(shè)置域名和本地應(yīng)用端口
- 在本地啟動natapp客戶端做穿透
配置后臺服務(wù)器信息
微信服務(wù)器使用應(yīng)用服務(wù)器配置信息來與其做交互悦即,配置信息主要包括URL地址吮成、token和EncodingAESKey,其中:
- URL 是應(yīng)用服務(wù)器的地址辜梳,它是微信服務(wù)器與應(yīng)用服務(wù)器的交互入口粱甫,公眾號產(chǎn)生的任何消息(如用戶關(guān)注該公眾號,或用戶向公眾號發(fā)送消息等)作瞄,都會調(diào)用該地址通知應(yīng)用服務(wù)器茶宵。
- token 表示令牌,在填寫了URL地址后宗挥,微信服務(wù)器需要驗證該地址是否有效乌庶,這是就需要用到這個token
- EncodingAESKey 消息加密密鑰种蝶,用戶在公眾號上產(chǎn)生的所有事件,都會以消息的形式發(fā)送了上面的URL地址瞒大,這個消息可以選擇加密螃征,這個EncodingAESKey就是消息加密的密鑰。
編寫服務(wù)器驗證接口
微信會驗證我們提供的服務(wù)器URL是否有效糠赦,具體流程如下:
- 微信服務(wù)器向URL發(fā)送GET請求
- 服務(wù)器驗證該請求会傲,并返回指定的值
GET請求附帶了一些參數(shù),包括:
- signature 簽名拙泽,作為我們驗證結(jié)果的比對
- timestamp 時間戳,驗證參數(shù)之一
- nonce 隨機數(shù)裸燎,驗證參數(shù)之一
- echostr 如果成功返回該參數(shù)
具體的驗證算法偽代碼如下:
if(sha1(token+timestamp+nonce) == signature){
return echostr;
}
return "";
將token顾瞻、timestamp和nonce按順序組成一個字符串,使用sha1加密德绿。如果加密后的字符串與signature相同荷荤,則返回echostr。微信服務(wù)器在收到echostr后移稳,表示該開發(fā)服務(wù)器已經(jīng)接入了微信服務(wù)器蕴纳。
@RestController
@RequestMapping("/auth/wechat")
public class WeChatMakeController {
@GetMapping("/mkserver")
public String makeServer(String signature,
String timestamp,
String nonce,
String echostr){
return echostr;
}
}
這里為了方面,我直接返回了echostr个粱。
獲取access_token
調(diào)用各微信接口時都需使用access_token古毛,access_token的有效期目前為2個小時,需定時刷新都许,每天只能刷新2000次稻薇,接口為GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
。一般的處理方式是胶征,將access_token存儲在內(nèi)存的某一個地方(實例或redis中)統(tǒng)一管理塞椎。向外提供獲取access_token的方法,方法內(nèi)部需要考慮token過期與多線程的情況睛低。參考me.chanjar.weixin.mp.api.impl.WxMpServiceHttpClientImpl#getAccessToken
public String getAccessToken(boolean forceRefresh) throws WxErrorException {
// 微信配置存儲器
final WxMpConfigStorage config = this.getWxMpConfigStorage();
// 是否獲取 或 強制刷新
if (!config.isAccessTokenExpired() && !forceRefresh) {
// 未過期直接返回數(shù)據(jù)
return config.getAccessToken();
}
// 多線程情況
Lock lock = config.getAccessTokenLock();
lock.lock();
try {
if (!config.isAccessTokenExpired() && !forceRefresh) {
return config.getAccessToken();
}
// 調(diào)用微信接口獲取access_token
// 更新存儲器中的token
// 返回token
} finally {
lock.unlock();
}
}
配置菜單
公眾號下的菜單欄最多包括3個一級菜單案狠,每個一級菜單最多包含5個二級菜單。菜單有多種類型
- click 點擊事件
- view 跳轉(zhuǎn)url
- miniprogram 跳轉(zhuǎn)到小程序
- scancode_push 掃碼推事件
- scancode_waitmsg 掃碼推事件且彈出“消息接收中”提示框.
- pic_sysphoto 彈出系統(tǒng)拍照發(fā)圖
- pic_photo_or_album 彈出拍照或者相冊發(fā)圖
- pic_weixin 彈出微信相冊發(fā)圖器
- location_select 彈出地理位置選擇器
- location_select 彈出地理位置選擇器
- media_id 下發(fā)消息(除文本消息)
- view_limited 跳轉(zhuǎn)圖文消息URL
其中最常用的是click钱雷、view和miniprogram骂铁。不同的菜單類型需要加的不同的參數(shù),比如急波,view類型的菜單是跳轉(zhuǎn)url的从铲,所以,我們需要附加url項澄暮。而click類型的菜單名段,我們需要附加一個key阱扬,以標(biāo)識該菜單。
{
// button代表的是菜單欄伸辟,是一個數(shù)組麻惶,里面的元素表示菜單
"button":[
// click類型的菜單,使用key標(biāo)識該菜單信夫,方便后臺處理對應(yīng)的業(yè)務(wù)
{
"type":"click",
"name":"今日歌曲",
"key":"V1001_TODAY_MUSIC"
},
// view類型的菜單窃蹋,url表示要跳轉(zhuǎn)的地址
{
"type":"view",
"name":"搜索",
"url":"http://www.soso.com/"
},
// 使用子菜單,sub_button是一個數(shù)組静稻,里面的元素是其子菜單
{
"name":"其他",
"sub_button": []
}
]
}
生成菜單時警没,需要向以下地址發(fā)送post請求
https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
獲取用戶信息
公眾號獲取用戶信息有兩種方式,通過openid獲取以及通過OAuth2獲取振湾。
通過OpenID獲取用戶信息
當(dāng)用戶關(guān)注公眾號后杀迹,微信服務(wù)器會為該用戶對于公眾號產(chǎn)生一個openid,這個openid是唯一的押搪,同一個用戶在不同的公眾號中openid是不同的树酪。后臺可根據(jù)該openid來獲取用戶信息。
GET https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
access_token是我們上面章節(jié)介紹獲取的大州。openid是微信服務(wù)器向后臺配置的URL發(fā)送的請求參數(shù)续语,比如,當(dāng)用戶關(guān)注了公眾號厦画,微信服務(wù)器會調(diào)用后臺的url地址疮茄,其中FromUserName就是該用戶的OpenID。
通過OAuth2獲取用戶信息
1 訂閱號不能使用該接口苛白,服務(wù)號需要認證后才能使用該接口
2 必須使用微信內(nèi)置瀏覽器
關(guān)于OAuth2.0 授權(quán)可以參考阮一峰的理解OAuth 2.0娃豹,因為這里采用的是OAuth2.0的授權(quán)碼模式,所以這里簡要的說一下使用授權(quán)碼模式的步驟购裙。
- 獲取授權(quán)碼(code)
- 使用code換access_token
- 獲取用戶信息
獲取授權(quán)碼
獲取授權(quán)碼的地址如下:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID
&redirect_uri=REDIRECT_URI
&response_type=code
&scope=SCOPE
&state=STATE#wechat_redirect
appid為公眾號的appid
-
redirect_uri 為微信授權(quán)后的回調(diào)頁懂版,該回調(diào)頁的域名部分需要在公眾號的后臺設(shè)置(接口權(quán)限/網(wǎng)頁授權(quán))
注意:在公眾號后臺設(shè)置的回調(diào)地址時,填寫的是域名躏率,而不是URL躯畴,因此請勿加 http:// 等協(xié)議頭。
response_type 授權(quán)類型薇芝,這里填固定值code蓬抄,因為微信采用的是OAuth2.0的授權(quán)碼模式
-
scope 授權(quán)的作用域,有兩種取值
snsapi_base snsapi_userinfo 用戶信息 用戶的OpenID 用戶基本信息(昵稱夯到、頭像等) 感知度 用戶無感知嚷缭,直接進入回調(diào)頁 1 用戶未關(guān)注公眾號,彈出授權(quán)頁面,用戶手動授權(quán)<br />2 用戶已關(guān)注公眾號阅爽,且通過點擊公眾號的菜單進入路幸,無需授權(quán)頁,即無感知 由上可以看出付翁,用戶即使未關(guān)注公眾號(已認證的服務(wù)號)简肴,也可以獲取用戶信息。
state 表示客戶端的狀態(tài)百侧,微信服務(wù)器會原封不動的返回該值
獲取access_token
注意這里的網(wǎng)頁授權(quán)access_token與前面所講的access_token是不同的砰识,這里的access_token只適合在OAuth2.0授權(quán)流程中使用。
通過第一步后佣渴,微信服務(wù)器會調(diào)用回調(diào)也的地址辫狼,并附帶code和state兩個參數(shù)
redirect_uri/?code=CODE&state=STATE。
回調(diào)頁使用這個code從微信服務(wù)器上獲取access_token辛润。這一步是后臺服務(wù)器和微信服務(wù)器做交互予借,可以認為是安全的通信。
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID
&secret=SECRET
&code=CODE
&grant_type=authorization_code
- appid 公眾號的appid
- secret 公眾號的appsecret
- code 第一步獲取的code
- grant_type 授權(quán)類型频蛔,授權(quán)碼模式,所以這里是固定值authorization_code
返回如下信息
{
"access_token":"訪問token",
"expires_in":7200,
"refresh_token":"刷新token",
"openid":"OPENID",
"scope":"SCOPE"
}
當(dāng)用戶未關(guān)注公眾號時秦叛,訪問公眾號的網(wǎng)頁晦溪,也會產(chǎn)生OpenID,且這個OpenID與關(guān)注后的OpenID相同挣跋。
獲取用戶信息
使用以下地址獲取用戶信息
https://api.weixin.qq.com/sns/userinfo?
access_token=ACCESS_TOKEN
&openid=OPENID
&lang=zh_CN
- access_token 訪問令牌三圆,上一步得到
- openid 用戶的唯一標(biāo)識,上一步得到
返回的用戶信息
{
"openid":" OPENID",
"nickname": "NICKNAME",
"sex":"1男避咆,2女舟肉,0未知",
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "headimgurl",
"privilege":[ "PRIVILEGE1" "PRIVILEGE2" ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
前后端分離獲取用戶信息
先后端分離時,微信登錄的解決辦法:
- 前端請求微信的code
- 收到code后查库,將code發(fā)送給后端
- 后端通過code換取access-token
- 通過access-token路媚,獲取當(dāng)前登錄的用戶信息,返回給前端