微信公眾平臺-微信服務號開發(fā)

@[TOC]

背景:

近期接到了涉及微信開放平臺和微信公眾平臺相關的開發(fā)需求,開發(fā)過程中踩了許多坑,把相關問題整理記錄下來以便鞏固記憶,并把總結的經驗分享出來,本篇分享微信服務號開發(fā),希望可以給大家提供幫助

一、微信各個平臺介紹

1、微信開放平臺:面向開發(fā)人員,為網站、App提供微信第三方登錄功能,為App提供支付功能。

2、微信公眾平臺:對應的是公眾號,包括訂閱號、服務號、企業(yè)號,面向運營人員和開發(fā)人員,運營可以直接登錄公眾號管理后臺查看公眾號的整體情況,開發(fā)人員則是通過調用微信提供的各種接口來增強公眾號的功能;

3、微信商戶平臺,用戶通過微信支付的錢,最終到達商戶賬號。無論是開放平臺還是公眾平臺,涉及到支付,都需要商戶平臺賬號

解釋一下什么是服務號什么是訂閱號

訂閱號圖解.png

通過官方提供的圖片可以了解到,訂閱號的優(yōu)勢就是進行消息推送,而服務號的優(yōu)勢是能夠提供個性化的服務

二、公眾平臺介紹

公眾平臺只能通過管理員掃碼登錄,當運營、開發(fā)人員較多時,可以進行綁定運營/開發(fā)者微信號進行自行掃碼登錄(http://kf.qq.com/faq/120911VrYVrA141211FbEnq2.html)

登錄后可以在管理后臺進行一系列操作,例如:

  • 創(chuàng)作管理:圖文素材、多媒體素材上傳

  • 公眾號設置:設置公眾號關注回復內容,收到關鍵詞回復規(guī)則和內容,設置收到消息自動回復內容,自定義公眾號菜單

    (注意:如果在開發(fā)者中心開啟回調URL和Token進行公眾號二次開發(fā)后,官方提供的公眾號設置功能將被關閉,后面我會針對這個場景做介紹)

  • 管理功能:查看關注該公眾號的用戶、接收的用戶消息,可以通過管理后臺對關注的用戶進行消息回復、消息群發(fā)

  • 統(tǒng)計功能:用戶分析、內容分析、菜單分析、圖文分析、消息分析等

三、開發(fā)前準備

  • 公眾號開發(fā)切記保存好AppID和AppSecret信息(請求獲取AccessToken時用到),其中AppSecret在管理后臺不顯示,且無法查看,忘記只能重置,因此AppSecret一定要進行備份并注意防止泄露。

    (官方對AccessToken進行了詳細說明https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

  • 設置開發(fā)環(huán)境、測試環(huán)境、正式環(huán)境的服務器 IP為白名單,白名單以外的ip請求access_token接口會報40164錯誤,有了 access_token 才能調用微信的各種接口

四、服務器配置

開啟服務器配置,開啟以后服務號的推送信息將會傳送到所配置的服務器中,包括關注事件、事件回復、關鍵詞回復、用戶消息接收、自定義菜單等功能都將被服務器接管,并且在公眾平臺配置的一切推送規(guī)則都將被停用,需要注意。

(PS:在配置服務器URL時,由于微信會發(fā)送請求進行簽名校驗,填寫的URL必須是可以外網訪問的,開發(fā)時建議使用ngrok進行內網穿透方便調試 附上網址: https://ngrok.com/

其他詳情可以參考服務器配置接入指南(https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html

五、服務器驗證

開發(fā)者提交信息后,微信服務器將發(fā)送GET請求到填寫的服務器地址URL上,GET請求攜帶參數(shù)如下表所示:

參數(shù) 描述
signature 微信加密簽名,signature結合了開發(fā)者填寫的token參數(shù)和請求中的timestamp參數(shù)、nonce參數(shù)。
timestamp 時間戳
nonce 隨機數(shù)
echostr 隨機字符串

開發(fā)者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信服務器,請原樣返回echostr參數(shù)內容,則接入生效,成為開發(fā)者成功,否則接入失敗。加密/校驗流程如下:

1)將token、timestamp、nonce三個參數(shù)進行字典序排序

2)將三個參數(shù)字符串拼接成一個字符串進行sha1加密

3)開發(fā)者獲得加密后的字符串可與signature對比,標識該請求來源于微信

代碼示例:

代碼示例:
//解析
@GetMapping("/weChatParseXml")
public String parseXmlGet(@RequestParam("signature") String signature,
@RequestParam("timestamp") String timestamp,
@RequestParam("nonce") String nonce,
@RequestParam("echostr") String echostr) {
logger.info("signature: " + signature);
logger.info("timestamp: " + timestamp);
logger.info("nonce: " + nonce);
logger.info("echostr: " + echostr);
//排序
String[] strArray = {TOKEN, timestamp, nonce}; //TOKEN為公眾平臺填寫的Token
Arrays.sort(strArray);
StringBuilder sb = new StringBuilder();
for (String str : strArray) {
sb.append(str);
}
String sortString = sb.toString();
logger.info("sortString: " + sortString);
//加密  這里主要是進行sha1加密 可以使用 SecurityUtil工具類進行加密
String myString = weChatAppletBiz.weChatParseXmlSha1(sortString);
logger.info("myString: " + myString);
//校驗
if (myString != null && myString != "" && myString.equals(signature)) {
logger.info("簽名校驗通過");
//如果檢驗成功原樣返回echostr,微信服務器接收到此輸出,才會確認檢驗完成。
return echostr;
} else {
logger.info("簽名校驗失敗");
return "";
}
}

六、消息接收

當普通微信用戶向公眾賬號發(fā)消息時,微信服務器將POST消息的XML數(shù)據(jù)包到開發(fā)者填寫的URL上。

(PS:官方提供了對文本、圖片、語音、視頻、地理位置等消息接收的方法,一般對文本的解析足以滿足大部分需求,因此下面只針對文本解析進行說明,其他詳情可以查閱上面的服務器接入指南)

請注意:

  1. 關于重試的消息排重,推薦使用msgid排重。
  2. 微信服務器在五秒內收不到響應會斷掉連接,并且重新發(fā)起請求,總共重試三次。假如服務器無法保證在五秒內處理并回復,可以直接回復空串,微信服務器不會對此作任何處理,并且不會發(fā)起重試。詳情請見“發(fā)送消息-被動回復消息”。
  3. 如果開發(fā)者需要對用戶消息在5秒內立即做出回應,即使用“發(fā)送消息-被動回復消息”接口向用戶被動回復消息時,可以在

公眾平臺官網的開發(fā)者中心處設置消息加密。開啟加密后,用戶發(fā)來的消息和開發(fā)者回復的消息都會被加密(但開發(fā)者通過客服接口等API調用形式向用戶發(fā)送消息,則不受影響)。關于消息加解密的詳細說明,請見“發(fā)送消息-被動回復消息加解密說明”。 關于文本消息的推送XML數(shù)據(jù)包結構如下:

文本消息

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>1348831860</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[this is a test]]></Content>
  <MsgId>1234567890123456</MsgId>
</xml>
參數(shù) 描述
ToUserName 開發(fā)者微信號
FromUserName 發(fā)送方帳號(一個OpenID)
CreateTime 消息創(chuàng)建時間 (整型)
MsgType 消息類型,文本為text
Content 文本消息內容
MsgId 消息id,64位整型

代碼示例:

@PostMapping("/weChatParseXml")
public Object parseXmlPost(HttpServletRequest request) throws Exception {
logger.info("==================接收到微信消息==================");
//解析xml
// Map<String, String> stringStringMap = weChatAppletBiz.parseXml(request);


Map<String, String> messageMap = new HashMap<>();

// 從request中取得輸入流
InputStream inputStream = request.getInputStream();
// 讀取輸入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
String asXML = document.asXML();
logger.info(asXML);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子節(jié)點
List<Element> elementList = root.elements();

// 遍歷所有子節(jié)點
for (Element e : elementList) {
messageMap.put(e.getName(), e.getText());
}

// 釋放資源
inputStream.close();

logger.info("獲取到的信息:\n" + messageMap);

weChatAppletBiz.dealWithInfo(messageMap);//該方法內根據(jù)用戶行為做對應的消息推送

logger.info("==================接收微信消息結束==================");
return "";
}

實際效果:

發(fā)送消息.png
消息接收文件.png

用戶事件:

當服務器后臺獲取到用戶發(fā)送的信息后,可以根據(jù)Event參數(shù)獲取事件類型,針對不用的事件進行對應處理

事件.png

事件類型分為subscribe(訂閱)、unsubscribe(取消訂閱)、 SCAN(掃描二維碼)、 CLICK(菜單點擊)、 LOCATION(地理位置)、 VIEW(菜單跳轉)

不同事件相關參數(shù)也不同,具體還請到上面分享的配置接入指南頁面,"消息管理模塊-接收事件推送"進行參考

七、客服消息

接口調用請求說明

http請求方式:

POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN

消息類型分為多種,包含文本、圖片、語音、視頻、音頻、視頻、圖文、菜單,這里舉例幾個常用JSON數(shù)據(jù)包如下:

發(fā)送文本消息

{
    "touser":"OPENID",
    "msgtype":"text",
    "text":
    {
         "content":"Hello World"
    }
}

發(fā)送圖片消息

{
    "touser":"OPENID",
    "msgtype":"image",
    "image":
    {
      "media_id":"MEDIA_ID"
    }
}

發(fā)送視頻消息

{
    "touser":"OPENID",
    "msgtype":"video",
    "video":
    {
      "media_id":"MEDIA_ID",
      "thumb_media_id":"MEDIA_ID",
      "title":"TITLE",
      "description":"DESCRIPTION"
    }
}

發(fā)送圖文消息(有兩種方式,這里舉例一種) 注意!!圖文消息條數(shù)限制在1條以內,如果圖文數(shù)超過1,則將會返回錯誤碼45008。 這里非常坑!

{
    "touser":"OPENID",
    "msgtype":"mpnews",
    "mpnews":
    {
         "media_id":"MEDIA_ID"
    }
}

發(fā)送文本消息時,還支持插入跳小程序的文字鏈

文本內容<a href="[http://www.qq.com](http://www.qq.com/)" data-miniprogram-appid="appid" data-miniprogram-path="pages/index/index">點擊跳小程序</a>

說明:

1.data-miniprogram-appid 項,填寫小程序appid,則表示該鏈接跳小程序;

2.data-miniprogram-path項,填寫小程序路徑,路徑與app.json中保持一致,可帶參數(shù);

3.對于不支持data-miniprogram-appid 項的客戶端版本,如果有herf項,則仍然保持跳href中的網頁鏈接;

4.data-miniprogram-appid對應的小程序必須與公眾號有綁定關系。

JSON數(shù)據(jù)包發(fā)送時需要注意以下幾點

1、OPENID可以通過接收參數(shù)中fromUserName字段獲得

2、msgtype一定要遵從規(guī)范,否則會出錯

3、media_id是管理員自行上傳的相關資源,上傳成功后會成為微信素材同時生成唯一的media_id,上傳方式可以從公眾平臺頁面上傳或使用curl命令進行上傳

(PS:這里我curl用的很少,大多數(shù)資源都是通過公眾平臺進行上傳,而且上傳的都是永久素材)

新增永久視頻素材的調用示例(慎用):

curl "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE" -F media=@media.file -F description='{"title":VIDEO_TITLE, "introduction":INTRODUCTION}'

參數(shù)說明

參數(shù) 是否必須 說明
title 視頻素材的標題
introduction 視頻素材的描述

返回說明

{
  "media_id":MEDIA_ID,
  "url":URL
}

返回參數(shù)說明

參數(shù) 描述
media_id 新增的永久素材的media_id
url 新增的圖片素材的圖片URL(僅新增圖片素材時會返回該字段)

八、獲取素材

調用微信系統(tǒng)的素材接口可以獲取對應的資源列表,注意!!獲取資源接口調用時有每日次數(shù)限制,不建議實時查詢,我這里是通過設計表,找恰當?shù)臅r機將數(shù)據(jù)同步到我們自己服務器中。

接口說明:

1、獲取永久素材的列表,也包含公眾號在公眾平臺官網素材管理模塊中新建的圖文消息、語音、視頻等素材

2、臨時素材無法通過本接口獲取

3、調用該接口需https協(xié)議

接口調用請求說明

http請求方式:

POST https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN

調用示例

{
    "type":TYPE,
    "offset":OFFSET,
    "count":COUNT
}

參數(shù)說明

參數(shù) 是否必須 說明
type 素材的類型,圖片(image)、視頻(video)、語音 (voice)、圖文(news)
offset 從全部素材的該偏移位置開始返回,0表示從第一個素材 返回
count 返回素材的數(shù)量,取值在1到20之間

返回說明

永久圖文消息素材列表的響應如下:

{
   "total_count": TOTAL_COUNT,
   "item_count": ITEM_COUNT,
   "item": [{
       "media_id": MEDIA_ID,
       "content": {
           "news_item": [{
               "title": TITLE,
               "thumb_media_id": THUMB_MEDIA_ID,
               "show_cover_pic": SHOW_COVER_PIC(0 / 1),
               "author": AUTHOR,
               "digest": DIGEST,
               "content": CONTENT,
               "url": URL,
               "content_source_url": CONTETN_SOURCE_URL
           },
           //多圖文消息會在此處有多篇文章
           ]
        },
        "update_time": UPDATE_TIME
    },
    //可能有多個圖文消息item結構
  ]
}

其他類型(圖片、語音、視頻)的返回如下:

{
   "total_count": TOTAL_COUNT,
   "item_count": ITEM_COUNT,
   "item": [{
       "media_id": MEDIA_ID,
       "name": NAME,
       "update_time": UPDATE_TIME,
       "url":URL
   },
   //可能會有多個素材
   ]
}

返回參數(shù)說明

參數(shù) 描述
total_count 該類型的素材的總數(shù)
item_count 本次調用獲取的素材的數(shù)量
title 圖文消息的標題
thumb_media_id 圖文消息的封面圖片素材id(必須是永久mediaID)
show_cover_pic 是否顯示封面,0為false,即不顯示,1為true,即顯示
author 作者
digest 圖文消息的摘要,僅有單圖文消息才有摘要,多圖文此處為空
content 圖文消息的具體內容,支持HTML標簽,必須少于2萬字符,小于1M,且此處會去除JS
url 圖文頁的URL,或者,當獲取的列表是圖片素材列表時,該字段是圖片的URL
content_source_url 圖文消息的原文地址,即點擊“閱讀原文”后的URL
update_time 這篇圖文消息素材的最后更新時間
name 文件名稱

九、相關工具

十、最終效果展示

關鍵詞列表.png

收到消息回復.png

關鍵詞界面.png

關鍵詞半回復界面.png

最終效果.png

總結

微信開發(fā)過程中很容易踩坑,遇到問題建議仔細閱讀官方文檔或通過微信開放社區(qū)尋找?guī)椭?/p>

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,616評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內容