最近開發的一個小程序項目需要通過服務號來推送通知。但是在最開始開發小程序的時候並沒有考慮到這個功能。
我在做小程序與服務號用戶關聯的過程中也是踩了無數坑,所以我會在這篇文章中給出自己摸索出的解決方案。
二、準備條件
預備知識:
小程序openid:小程序用戶的唯一id
公衆號openid:公衆號用戶的唯一id
unionid:同一用戶,對同一個微信開放平臺下的不同應用,unionid是相同的
準備:
1.將小程序與公衆號綁定(綁定後纔可獲取unionid),官方文檔:小程序與公衆號綁定獲取unionid
2.接入微信公衆平臺開發,也就是給服務號配置一下開發者服務器。當有用戶關注/取消服務號時,微信服務器會推送關注/取消的事件給我們的服務器。官方文檔:接入微信公衆平臺開發
3.獲取公衆號用戶列表,即所有用戶的公衆號openid。官方文檔:獲取公衆號用戶列表
4.通過公衆號openid獲取用戶的unionid。官方文檔:通過公衆號openid獲取unionid
5.推送服務號消息。官方文檔:公衆號發送模版消息
注意:
1.在上述的一些接口中,需要獲取access_token。小程序和公衆號的access_token是不同的,需要用各自的appid和secret去獲取。
2.access_token每天只能獲取200次,有效期是7200秒。所以應該把它加入緩存,而不是每次都去獲取新的access_token。
三、開始開發
將小程序用戶與公衆號用戶關聯:
小程序用戶openid→unionid←公衆號用戶openid
要想將小程序與公衆號用戶關聯,第一件事就是獲取用戶的unionid。
我們可以在兩種情況下獲取用戶的unionid:
一、如果用戶已經關注了公衆號,那麼在用戶登錄的時候,就可以獲取到unionid
二、如果用戶沒有關注公衆號,那麼得讓前端調用wx.getUserInfo,把加密數據給後端解密拿到unionid。
解密需要session_key,而session_key又有有效期,得注意它過期的情況。
當用戶關注公衆號時,微信會推送事件給我們(本文準備條件的第2條)。
通過關注事件,我們可以拿到用戶的公衆號openid,再獲取unionid(本文準備條件的第4條)。拿到unionid後,去數據庫查詢這個unionid的用戶,並把公衆號openid保存。
但是,還有兩個情況沒有考慮到:
一、在我們開發之前,已經關注了公衆號的用戶沒有去關聯
解決方案:
獲取微信公衆號的用戶列表,再依次獲取用戶unionid(本文準備條件的第3、4條)。注意,此操作非常耗時。
二、用戶先關注了公衆號,但是從來沒用過小程序(數據庫裏沒有unionid,導致無法關聯)
解決方案:
新建一張表,把這個公衆號用戶先記錄下來。當小程序用戶登錄時,先檢查一遍這張表嘗試關聯。
至此,小程序用戶與公衆號用戶就已經完成了關聯。
發送模版消息:
這個就很簡單了,照着官方文檔(本文準備條件的第5條)做就行了。
需要注意的是,參數別寫錯了,我就是把miniprogram放到data裏面去了,搞的不能跳轉小程序,害得我找了半天問題T T
最後附上發送模版消息的python代碼:
- def send_oa_msg(oa_openid, template_id, jump_param, param):
- """
- 發送模版消息
- """
- oa_token = get_oa_access_token()
- url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={oa_token}'.format(oa_token=oa_token)
- post_data = {
- "touser": oa_openid,
- "template_id": template_id,
- "miniprogram": jump_param,
- "data": param
- }
-
- res = requests.post(url, json=post_data)
- result = res.json()
-
- if result['errcode'] == 0:
- return True
- else:
- return False