


Develop automatic message replies and custom menus for WeChat public accounts
Feb 24, 2017 pm 04:48 PMMessage reply
Process the request and respond
1) Follow
and also refer to the official website documentation: https ://mp.weixin.qq.com/wiki
When WeChat users follow public accounts, they can be given appropriate prompts. It can be a welcome message or a help tip. The sample code is as follows:
?class?EventHandler?:?IHandler ????{????????///?<summary> ????????///?請(qǐng)求的xml????????///?</summary> ????????private?string?RequestXml?{?get;?set;?}????????///?<summary> ????????///?構(gòu)造函數(shù)????????///?</summary> ????????///?<param name="requestXml"></param> ????????public?EventHandler(string?requestXml) ????????{????????????this.RequestXml?=?requestXml; ????????}????????///?<summary> ????????///?處理請(qǐng)求????????///?</summary> ????????///?<returns></returns> ????????public?string?HandleRequest() ????????{????????????string?response?=?string.Empty; ????????????EventMessage?em?=?EventMessage.LoadFromXml(RequestXml);????????????if?(em.Event.Equals("subscribe",StringComparison.OrdinalIgnoreCase)) ????????????{????????????????//回復(fù)歡迎消息 ????????????????TextMessage?tm?=?new?TextMessage(); ????????????????tm.ToUserName?=?em.FromUserName; ????????????????tm.FromUserName?=?em.ToUserName; ????????????????tm.CreateTime?=?Common.GetNowTime(); ????????????????tm.Content?=?"歡迎您關(guān)注我們,我是服務(wù)小二,有事您開(kāi)口~\n\n"; ????????????????response?=?tm.GenerateContent(); ????????????}????????????return?response; ????????} ????}
The official introduction is as follows
Follow/Unfollow events
Users are in When following or unfollowing a public account, WeChat will push this event to the URL filled in by the developer. It is convenient for developers to send welcome messages to users or unbind accounts.
If the WeChat server does not receive a response within five seconds, it will disconnect and re-initiate the request, retrying three times in total.
Regarding retry message duplication, it is recommended to use FromUserName + CreateTime to deduplicate messages.
If the server cannot guarantee to process and reply within five seconds, you can directly reply with an empty string. The WeChat server will not do anything with this and will not initiate a retry.
Push XML packet example:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[subscribe]]></Event> </xml> |
Parameter description:
Parameters | Description |
---|---|
ToUserName | Developer WeChat ID |
FromUserName | Sender account (an OpenID) |
CreateTime | Message creation time (integer) |
MsgType | Message type, event |
Event | Event type, subscribe(subscription), unsubscribe(cancel subscription) |
也可使用微信在線接口調(diào)試工具測(cè)試是否正常:取消/關(guān)注事件接口在線調(diào)試
2)問(wèn)候
簡(jiǎn)單的交流問(wèn)候,比如你好、幫助等等,跟我們使用微信聊天一樣,不過(guò)回應(yīng)是由我們的程序響應(yīng)。具體功能,可以根據(jù)自己的需要進(jìn)行添加。
微信本來(lái)就是溝通的平臺(tái)。這個(gè)案例,可以用于在線服務(wù)機(jī)器人,類似于淘寶的客服機(jī)器人,可是我們這個(gè)是微信版的。
其實(shí),很簡(jiǎn)單,獲取請(qǐng)求消息,根據(jù)關(guān)鍵字來(lái)匹配回應(yīng)。當(dāng)然這里可能要做的工作很多,如何支持智能匹配,如何支持模糊匹配等。
/// <summary> /// 文本信息處理類 /// </summary> public class TextHandler : IHandler { /// <summary> /// 請(qǐng)求的XML /// </summary> private string RequestXml { get; set; } /// <summary> /// 構(gòu)造函數(shù) /// </summary> /// <param name="requestXml">請(qǐng)求的xml</param> public TextHandler(string requestXml) { this.RequestXml = requestXml; } /// <summary> /// 處理請(qǐng)求 /// </summary> /// <returns></returns> public string HandleRequest() { string response = string.Empty; TextMessage tm = TextMessage.LoadFromXml(RequestXml); string content = tm.Content.Trim(); if (string.IsNullOrEmpty(content)) { response = "您什么都沒(méi)輸入,沒(méi)法幫您啊,%>_<%。"; } else { if (content.StartsWith("tq", StringComparison.OrdinalIgnoreCase)) { string cityName = content.Substring(2).Trim(); response = WeatherHelper.GetWeather(cityName); } else { response = HandleOther(content); } } tm.Content = response; //進(jìn)行發(fā)送者、接收者轉(zhuǎn)換 string temp = tm.ToUserName; tm.ToUserName = tm.FromUserName; tm.FromUserName = temp; response = tm.GenerateContent(); return response; } /// <summary> /// 處理其他消息 /// </summary> /// <param name="tm"></param> /// <returns></returns> private string HandleOther(string requestContent) { string response = string.Empty; if (requestContent.Contains("你好") || requestContent.Contains("您好")) { response = "您也好~"; } else if (requestContent.Contains("傻")) { response = "我不傻!哼~ "; } else if (requestContent.Contains("shit") || requestContent.Contains("小王八蛋")) { response = "哼,你說(shuō)臟話! "; } else if (requestContent.Contains("是誰(shuí)")) { response = "我是大哥大,有什么能幫您的嗎?~"; } else if (requestContent.Contains("再見(jiàn)")) { response = "再見(jiàn)!"; } else if (requestContent.Contains("bye")) { response = "Bye!"; } else if (requestContent.Contains("謝謝")) { response = "不客氣!嘿嘿"; } else if (requestContent == "h" || requestContent == "H" || requestContent.Contains("幫助")) { response = @"有事找警察"; } else { response = "您說(shuō)的,可惜,我沒(méi)明白啊,試試其他關(guān)鍵字吧。"; } return response; } }
實(shí)現(xiàn)效果如圖所示:
自定義菜單
首先呢,我們要了解下微信公眾號(hào)開(kāi)發(fā)里面菜單有哪些類型呢?
自定義菜單接口可實(shí)現(xiàn)多種類型按鈕,如下:
請(qǐng)注意,3到8的所有事件,僅支持微信iPhone5.4.1以上版本,和Android5.4以上版本的微信用戶,舊版本微信用戶點(diǎn)擊后將沒(méi)有回應(yīng),開(kāi)發(fā)者也不能正常接收到事件推送。9和10,是專門給第三方平臺(tái)旗下未微信認(rèn)證(具體而言,是資質(zhì)認(rèn)證未通過(guò))的訂閱號(hào)準(zhǔn)備的事件類型,它們是沒(méi)有事件推送的,能力相對(duì)受限,其他類型的公眾號(hào)不必使用。
接口調(diào)用請(qǐng)求說(shuō)明
http請(qǐng)求方式:POST(請(qǐng)使用https協(xié)議) http://m.miracleart.cn/
click和view的請(qǐng)求示例
{ "button":[ { "type":"click", "name":"今日歌曲", "key":"V1001_TODAY_MUSIC" }, { "name":"菜單", "sub_button":[ { "type":"view", "name":"搜索", "url":"http://m.miracleart.cn/" }, { "type":"view", "name":"視頻", "url":"http://m.miracleart.cn/" }, { "type":"click", "name":"贊一下我們", "key":"V1001_GOOD" }] }] }
參數(shù)說(shuō)明
參數(shù) | 是否必須 | 說(shuō)明 |
---|---|---|
button | 是 | 一級(jí)菜單數(shù)組,個(gè)數(shù)應(yīng)為1~3個(gè) |
sub_button | 否 | 二級(jí)菜單數(shù)組,個(gè)數(shù)應(yīng)為1~5個(gè) |
type | 是 | 菜單的響應(yīng)動(dòng)作類型 |
name | 是 | 菜單標(biāo)題,不超過(guò)16個(gè)字節(jié),子菜單不超過(guò)60個(gè)字節(jié) |
key | click等點(diǎn)擊類型必須 | 菜單KEY值,用于消息接口推送,不超過(guò)128字節(jié) |
url | view類型必須 | 網(wǎng)頁(yè)鏈接,用戶點(diǎn)擊菜單可打開(kāi)鏈接,不超過(guò)1024字節(jié) |
media_id | media_id類型和view_limited類型必須 | 調(diào)用新增永久素材接口返回的合法media_id |
當(dāng)然也可以使用在線調(diào)試接口調(diào)試菜單是否設(shè)置正確:我要在線調(diào)試菜單接口
詳細(xì)步驟
1、首先獲取access_token
access_token是公眾號(hào)的全局唯一票據(jù),公眾號(hào)調(diào)用各接口時(shí)都需使用access_token。正常情況下access_token有效期為7200秒,重復(fù)獲取將導(dǎo)致上次獲取的access_token失效。
公眾號(hào)可以使用AppID和AppSecret調(diào)用本接口來(lái)獲取access_token。AppID和AppSecret可在開(kāi)發(fā)模式中獲得(需要已經(jīng)成為開(kāi)發(fā)者,且?guī)ぬ?hào)沒(méi)有異常狀態(tài))。注意調(diào)用所有微信接口時(shí)均需使用https協(xié)議。
接口調(diào)用請(qǐng)求說(shuō)明
http請(qǐng)求方式: GET https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
參數(shù)說(shuō)明
參數(shù) | 是否必須 | 說(shuō)明 |
---|---|---|
grant_type | 是 | 獲取access_token填寫(xiě)client_credential |
appid | 是 | 第三方用戶唯一憑證 |
secret | 是 | 第三方用戶唯一憑證密鑰,既appsecret |
返回說(shuō)明
正常情況下,微信會(huì)返回下述JSON數(shù)據(jù)包給公眾號(hào):
{"access_token":"ACCESS_TOKEN","expires_in":7200}
參數(shù) | 說(shuō)明 |
---|---|
access_token | 獲取到的憑證 |
expires_in | 憑證有效時(shí)間,單位:秒 |
錯(cuò)誤時(shí)微信會(huì)返回錯(cuò)誤碼等信息,JSON數(shù)據(jù)包示例如下(該示例為AppID無(wú)效錯(cuò)誤):
{"errcode":40013,"errmsg":"invalid appid"}
創(chuàng)建自定義菜單
自定義菜單能夠幫助公眾號(hào)豐富界面,讓用戶更好更快地理解公眾號(hào)的功能。
目前自定義菜單最多包括3個(gè)一級(jí)菜單,每個(gè)一級(jí)菜單最多包含5個(gè)二級(jí)菜單。一級(jí)菜單最多4個(gè)漢字,二級(jí)菜單最多7個(gè)漢字,多出來(lái)的部分將會(huì)以“...”代替。請(qǐng)注意,創(chuàng)建自定義菜單后,由于微信客戶端緩存,需要24小時(shí)微信客戶端才會(huì)展現(xiàn)出來(lái)。建議測(cè)試時(shí)可以嘗試取消關(guān)注公眾賬號(hào)后再次關(guān)注,則可以看到創(chuàng)建后的效果。
3、查詢菜單
使用接口創(chuàng)建自定義菜單后,開(kāi)發(fā)者還可使用接口查詢自定義菜單的結(jié)構(gòu)。
請(qǐng)求說(shuō)明
http請(qǐng)求方式:GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
返回說(shuō)明
對(duì)應(yīng)創(chuàng)建接口,正確的Json返回結(jié)果: {"menu":{"button":[{"type":"click","name":"今日歌曲","key":"V1001_TODAY_MUSIC","sub_button":[]},{"type":"click","name":"歌手簡(jiǎn)介","key":"V1001_TODAY_SINGER","sub_button":[]},{"name":"菜單","sub_button":[{"type":"view","name":"搜索","url":"http://www.soso.com/","sub_button":[]},{"type":"view","name":"視頻","url":"http://v.qq.com/","sub_button":[]},{"type":"click","name":"贊一下我們","key":"V1001_GOOD","sub_button":[]}]}]}}
4、刪除菜單
使用接口創(chuàng)建自定義菜單后,開(kāi)發(fā)者還可使用接口刪除當(dāng)前使用的自定義菜單。
請(qǐng)求說(shuō)明
http請(qǐng)求方式:GET https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
返回說(shuō)明
對(duì)應(yīng)創(chuàng)建接口,正確的Json返回結(jié)果: {"errcode":0,"errmsg":"ok"}
5、事件處理
用戶點(diǎn)擊自定義菜單后,如果菜單按鈕設(shè)置為click類型,則微信會(huì)把此次點(diǎn)擊事件推送給開(kāi)發(fā)者,注意view類型(跳轉(zhuǎn)到URL)的菜單點(diǎn)擊不會(huì)上報(bào)。
推送XML數(shù)據(jù)包示例:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[FromUser]]></FromUserName> <CreateTime>123456789</CreateTime> <MsgType><![CDATA[event]]></MsgType> <Event><![CDATA[CLICK]]></Event> <EventKey><![CDATA[EVENTKEY]]></EventKey> </xml>
參數(shù)說(shuō)明:
參數(shù) | 描述 |
---|---|
ToUserName | 開(kāi)發(fā)者微信號(hào) |
FromUserName | 發(fā)送方帳號(hào)(一個(gè)OpenID) |
CreateTime | 消息創(chuàng)建時(shí)間 (整型) |
MsgType | 消息類型,event |
Event | 事件類型,CLICK |
EventKey | 事件KEY值,與自定義菜單接口中KEY值對(duì)應(yīng) |
實(shí)例講解
我們將會(huì)在上一篇的基礎(chǔ)上,添加自定義菜單的功能
1、獲取access_token
首先需要得到AppId和AppSecret
當(dāng)你成為開(kāi)發(fā)者后,自然能夠在,開(kāi)發(fā)者模式,便可看到這兩個(gè)值,可以重置。
然后調(diào)用按照二.1中所示,進(jìn)行操作。
注意:access_token有過(guò)期時(shí)間,如果過(guò)期,需要重新獲取。
private static DateTime GetAccessToken_Time; /// <summary> /// 過(guò)期時(shí)間為7200秒 /// </summary> private static int Expires_Period = 7200; /// <summary> /// /// </summary> private static string mAccessToken; /// <summary> /// /// </summary> public static string AccessToken { get { //如果為空,或者過(guò)期,需要重新獲取 if (string.IsNullOrEmpty(mAccessToken) || HasExpired()) { //獲取 mAccessToken = GetAccessToken(AppID, AppSecret); } return mAccessToken; } } /// <summary> /// /// </summary> /// <param name="appId"></param> /// <param name="appSecret"></param> /// <returns></returns> private static string GetAccessToken(string appId, string appSecret) { string url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appId, appSecret); string result = HttpUtility.GetData(url); XDocument doc = XmlUtility.ParseJson(result, "root"); XElement root = doc.Root; if (root != null) { XElement access_token = root.Element("access_token"); if (access_token != null) { GetAccessToken_Time = DateTime.Now; if (root.Element("expires_in")!=null) { Expires_Period = int.Parse(root.Element("expires_in").Value); } return access_token.Value; } else { GetAccessToken_Time = DateTime.MinValue; } } return null; } /// <summary> /// 判斷Access_token是否過(guò)期 /// </summary> /// <returns>bool</returns> private static bool HasExpired() { if (GetAccessToken_Time != null) { //過(guò)期時(shí)間,允許有一定的誤差,一分鐘。獲取時(shí)間消耗 if (DateTime.Now > GetAccessToken_Time.AddSeconds(Expires_Period).AddSeconds(-60)) { return true; } } return false; }
2、設(shè)置菜單
菜單需根據(jù)需要,按照實(shí)際要求進(jìn)行設(shè)定。
這里我們只做簡(jiǎn)單的演示。
然后還提供了友情鏈接,這里提供了view類型的菜單,直接可以跳轉(zhuǎn)至URL頁(yè)面,為跳轉(zhuǎn)做個(gè)好的演示。
具體菜單如下:
{ "button": [ { "name": "測(cè)試跳轉(zhuǎn)", "sub_button": [ { "type": "view", "name": "搜索", "url": "http://www.baidu.com/" }, { "type": "view", "name": "視頻", "url": "http://v.qq.com/" }, { "type": "click", "name": "贊一下我們", "key": "BTN_GOOD" } ] }, { "type": "view", "name": "設(shè)備狀態(tài)", "url": "http://vanrui.com/weixin" }, { "type": "click", "name": "幫助", "key": "BTN_HELP" } ] }
3、管理菜單
因?yàn)椴藛蔚淖兏鼪](méi)有那么頻繁,因此通過(guò)txt文件來(lái)設(shè)置菜單,并通過(guò)管理界面來(lái)管理菜單。
主要的管理功能:
1)從文件加載菜單
2)創(chuàng)建菜單。即將菜單通知微信服務(wù)端,并更新至微信客戶端
3)查詢菜單。獲取當(dāng)前系統(tǒng)的菜單。
4)刪除菜單。從微信服務(wù)器刪除菜單,也可以刪除后再創(chuàng)建。
實(shí)現(xiàn)代碼如下:
public class MenuManager { /// <summary> /// 菜單文件路徑 /// </summary> private static readonly string Menu_Data_Path = System.AppDomain.CurrentDomain.BaseDirectory + "/Data/menu.txt"; /// <summary> /// 獲取菜單 /// </summary> public static string GetMenu() { string url = string.Format("http://m.miracleart.cn/{0}", Context.AccessToken); return HttpUtility.GetData(url); } /// <summary> /// 創(chuàng)建菜單 /// </summary> public static void CreateMenu(string menu) { string url = string.Format("http://m.miracleart.cn/{0}", Context.AccessToken); //string menu = FileUtility.Read(Menu_Data_Path); HttpUtility.SendHttpRequest(url, menu); } /// <summary> /// 刪除菜單 /// </summary> public static void DeleteMenu() { string url = string.Format("http://m.miracleart.cn/{0}", Context.AccessToken); HttpUtility.GetData(url); } /// <summary> /// 加載菜單 /// </summary> /// <returns></returns> public static string LoadMenu() { return FileUtility.Read(Menu_Data_Path); } }
4、基本方法
上面的代碼,其實(shí)我們對(duì)一些公共功能做了封裝。如進(jìn)行g(shù)et請(qǐng)求、POST提交等操作,讀取文件等。
這里我們提供進(jìn)行g(shù)et、Post提交的方法案例代碼,如果使用,建議優(yōu)化。
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;using System.Text;using System.Threading.Tasks;namespace WeChat.Utility { /// <summary> /// 幫助類 /// </summary> class HttpUtility { /// <summary> /// 發(fā)送請(qǐng)求 /// </summary> /// <param name="url">Url地址</param> /// <param name="data">數(shù)據(jù)</param> public static string SendHttpRequest(string url, string data) { return SendPostHttpRequest(url, "application/x-www-form-urlencoded", data); } /// <summary> /// /// </summary> /// <param name="url"></param> /// <returns></returns> public static string GetData(string url) { return SendGetHttpRequest(url, "application/x-www-form-urlencoded"); } /// <summary> /// 發(fā)送請(qǐng)求 /// </summary> /// <param name="url">Url地址</param> /// <param name="method">方法(post或get)</param> /// <param name="method">數(shù)據(jù)類型</param> /// <param name="requestData">數(shù)據(jù)</param> public static string SendPostHttpRequest(string url, string contentType, string requestData) { WebRequest request = (WebRequest)HttpWebRequest.Create(url); request.Method = "POST"; byte[] postBytes = null; request.ContentType = contentType; postBytes = Encoding.UTF8.GetBytes(requestData); request.ContentLength = postBytes.Length; using (Stream outstream = request.GetRequestStream()) { outstream.Write(postBytes, 0, postBytes.Length); } string result = string.Empty; using (WebResponse response = request.GetResponse()) { if (response != null) { using (Stream stream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { result = reader.ReadToEnd(); } } } } return result; } /// <summary> /// 發(fā)送請(qǐng)求 /// </summary> /// <param name="url">Url地址</param> /// <param name="method">方法(post或get)</param> /// <param name="method">數(shù)據(jù)類型</param> /// <param name="requestData">數(shù)據(jù)</param> public static string SendGetHttpRequest(string url, string contentType) { WebRequest request = (WebRequest)HttpWebRequest.Create(url); request.Method = "GET"; request.ContentType = contentType; string result = string.Empty; using (WebResponse response = request.GetResponse()) { if (response != null) { using (Stream stream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { result = reader.ReadToEnd(); } } } } return result; } } }
class XmlUtility { /// <summary> /// /// </summary> /// <param name="json"></param> /// <param name="rootName"></param> /// <returns></returns> public static XDocument ParseJson(string json,string rootName) { return JsonConvert.DeserializeXNode(json, rootName); } }
5、事件處理
設(shè)置了菜單,這下需要處理事件了。跟我們之前設(shè)計(jì)ASPX或者WinForm一樣,都要綁定按鈕的事件。這里只是通過(guò)XML消息將請(qǐng)求傳遞過(guò)來(lái)。
通過(guò)“2、設(shè)置菜單"中具體的菜單內(nèi)容,我們便已經(jīng)知道需要進(jìn)行哪些事件處理了。對(duì)于按鈕類型為view的,無(wú)須處理,它會(huì)自動(dòng)跳轉(zhuǎn)至指定url.
需要處理的點(diǎn)擊事件:
1)贊一下
2)幫助
這個(gè)還要沿用上章中的事件處理器EventHandler來(lái)擴(kuò)展處理。
具體的實(shí)現(xiàn)代碼吧:
class EventHandler : IHandler { /// <summary> /// 請(qǐng)求的xml /// </summary> private string RequestXml { get; set; } /// <summary> /// 構(gòu)造函數(shù) /// </summary> /// <param name="requestXml"></param> public EventHandler(string requestXml) { this.RequestXml = requestXml; } /// <summary> /// 處理請(qǐng)求 /// </summary> /// <returns></returns> public string HandleRequest() { string response = string.Empty; EventMessage em = EventMessage.LoadFromXml(RequestXml); if (em != null) { switch (em.Event.ToLower()) { case ("subscribe"): response = SubscribeEventHandler(em); break; case "click": response = ClickEventHandler(em); break; } } return response; } /// <summary> /// 關(guān)注 /// </summary> /// <param name="em"></param> /// <returns></returns> private string SubscribeEventHandler(EventMessage em) { //回復(fù)歡迎消息 TextMessage tm = new TextMessage(); tm.ToUserName = em.FromUserName; tm.FromUserName = em.ToUserName; tm.CreateTime = Common.GetNowTime(); tm.Content = "歡迎您關(guān)注我們,我是服務(wù)小二,有事您說(shuō)話~\n\n"; return tm.GenerateContent(); } /// <summary> /// 處理點(diǎn)擊事件 /// </summary> /// <param name="em"></param> /// <returns></returns> private string ClickEventHandler(EventMessage em) { string result = string.Empty; if (em != null && em.EventKey != null) { switch (em.EventKey.ToUpper()) { case "BTN_GOOD": result = btnGoodClick(em); break; case "BTN_HELP": result = btnHelpClick(em); break; } } return result; } /// <summary> /// 贊一下 /// </summary> /// <param name="em"></param> /// <returns></returns> private string btnGoodClick(EventMessage em) { //回復(fù)歡迎消息 TextMessage tm = new TextMessage(); tm.ToUserName = em.FromUserName; tm.FromUserName = em.ToUserName; tm.CreateTime = Common.GetNowTime(); tm.Content = @"謝謝您的支持!"; return tm.GenerateContent(); } /// <summary> /// 幫助 /// </summary> /// <param name="em"></param> /// <returns></returns> private string btnHelpClick(EventMessage em) { //回復(fù)歡迎消息 TextMessage tm = new TextMessage(); tm.ToUserName = em.FromUserName; tm.FromUserName = em.ToUserName; tm.CreateTime = Common.GetNowTime(); tm.Content = @"有事找警察~"; return tm.GenerateContent(); }
調(diào)試效果
圖中點(diǎn)擊的幫助菜單,如果大家仔細(xì)觀察,會(huì)發(fā)現(xiàn)后面斷點(diǎn)進(jìn)入第二次了,這是因?yàn)榍懊嫣岬降?,微信服?wù)器5秒未回復(fù),就會(huì)重復(fù)嘗試發(fā)3次請(qǐng)求,所以就會(huì)有多次進(jìn)入斷點(diǎn)的效果。
最終效果
Demo下載
鏈接:點(diǎn)我下載? 密碼:41dt
Git地址:https://github.com/XiaoYong666/-Demo
?
更多微信公眾號(hào)開(kāi)發(fā)自動(dòng)消息回復(fù)和自定義菜單?相關(guān)文章請(qǐng)關(guān)注PHP中文網(wǎng)!
?

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)
