一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

分享我們團(tuán)隊最近開發(fā)的微信公眾號運(yùn)營助手,可以在手機(jī)上回復(fù)粉絲留言

 深度視訊 2016-09-09

由于公司旗下有好幾個微信公眾號,經(jīng)常來回切換登錄很麻煩,粉絲留言咨詢的時候常常不能及時回復(fù),導(dǎo)致訂單流失。于是我們團(tuán)隊開發(fā)了一個公眾號小助手,可以把多個公眾號綁定進(jìn)來,只要有粉絲留言,馬上管理員就收到通知了,然后還可以在手機(jī)上進(jìn)行回復(fù)。

實(shí)現(xiàn)的功能如下:

  1. 粉絲留言自動微信通知
  2. 在微信中回復(fù)粉絲留言,文字 圖片
  3. 粉絲關(guān)注自動微信通知
  4. 粉絲關(guān)注自動推送多圖文消息或者歷史消息
  5. 更強(qiáng)大的自定義菜單管理
  6. 自定義客服消息模板
  7. 支持綁定多個管理員
  8. 支持關(guān)鍵詞自動回復(fù)
  9. 支持二次開發(fā)

雖然這個小助手很小,但是里面用到的技術(shù)我覺得還是有一定分享價值。本文就向大家分享一下這個小助手中核心的技術(shù)方案,包括:公眾號綁定、粉絲信息獲取、給粉絲發(fā)送消息、微信圖片上傳與下載、公眾號自定義菜單接口、公眾號臨時二維碼的妙用等等。

免費(fèi)在線體驗(yàn):

核心技術(shù)1:多個公眾號的綁定

想要調(diào)用微信公眾號的API,首先要通過AppId和AppSecret獲取AccessToken,而AccessToken過一段時間就會過期。為了提高AccessToken的利用率并且實(shí)現(xiàn)自動刷新,我們專門寫了一個AccessTokenContext來管理多個公眾號的AccessToken,這個類也是完成多個公眾號綁定最重要的一步。

請看源碼:

1 public class AccessTokenContext 2 { 3 public static AccessTokenContext Instance { get; } 4 5 static AccessTokenContext 6 { 7 Instance = new AccessTokenContext; 8 } 9 10 private readonly Dictionary<Guid, AccountAccessTokenDto> _keyValues; 11 12 public AccessTokenContext 13 { 14 _keyValues = new Dictionary<Guid, AccountAccessTokenDto>; 15 } 16 17 public string GetDabenAccessToken 18 { 19 return GetAccessToken(AppContext.DabenMpAccountId); 20 } 21 22 public string GetAccessToken(Guid accountId) 23 { 24 if (_keyValues.ContainsKey(accountId)) 25 { 26 var dto = _keyValues[accountId]; 27 if (dto.IsExpired == false) 28 { 29 return dto.AccessToken; 30 } 31 } 32 var account = Ioc.Get<IAccountService>.Get(accountId); 33 var apidto = GetByApi(account); 34 _keyValues[account.Id] = apidto; 35 return apidto.AccessToken; 36 } 37 38 public string GetAccessToken(MpAccount account) 39 { 40 if (_keyValues.ContainsKey(account.Id)) 41 { 42 var dto = _keyValues[account.Id]; 43 if (dto.IsExpired) 44 { 45 dto = GetByApi(account); 46 } 47 return dto.AccessToken; 48 } 49 else 50 { 51 var dto = GetByApi(account); 52 _keyValues[account.Id] = dto; 53 return dto.AccessToken; 54 } 55 } 56 57 private AccountAccessTokenDto GetByApi(MpAccount account) 58 { 59 var token = WeixinApi.GetAccessToken(account.AppId, account.AppSecret); 60 if (token == null || token.IsSuccess == false) 61 { 62 throw new KnownException('Mp.GetAccessToken:' account.Name); 63 } 64 return new AccountAccessTokenDto(account.Id, token); 65 } 66 }

一旦拿到了某個公眾號的AccessToken,就可以調(diào)用絕大部分接口了。

核心技術(shù)2:拉取粉絲基本信息

不同的微信公眾號下面的粉絲擁有不同的OpenId,而OpenId是微信對于用于的唯一標(biāo)識。

微信提供了幾個事件發(fā)生的時候,程序可以獲取用戶的OpenId,而用OpenId就可以跟用戶互動。我們僅用了2個事件獲取OpenId:粉絲關(guān)注時和粉絲留言時。

下面的代碼展示了如何通過OpenId和AccessToken獲取粉絲基本信息。

public class WeixinApi { public static UserDto GetUserInfo(string openId, string accessToken = null) { return HttpHelper.GetApiDto<UserDto>(WeixinConfigs.Urls.GetUserInfo(openId, accessToken)); } }
internal class HttpHelper { public static T GetApiDto<T>(string url) where T : ApiDtoBase { var html = DownloadString(url); try { var dto = Serializer.FromJson<T>(html); if (dto.IsSuccess == false) { Logger.Error('GetApiDto.' typeof(T).FullName '.NotSuccess', dto.GetFullError); } return dto; } catch (Exception ex) { Logger.Error('GetApiDto.' typeof(T).FullName '.Exception', ex); Logger.Error('GetApiDto.' typeof(T).FullName '.Exception', html); } return null; } }
核心技術(shù)3:給粉絲發(fā)送消息

注意這里僅僅是發(fā)送的客服消息,也就是粉絲與公眾號互動之后的48小時內(nèi)可以隨意給粉絲發(fā)送的消息,包括文字和圖片。

public class WeixinApi { public static ApiDtoBase TrySendMessage(MessageBase message, string accessToken = null) { try { return HttpHelper.PostApiDto<ApiDtoBase>(WeixinConfigs.Urls.SendMessage(message is TemplateMessageBase, accessToken), message.ToJson); } catch (Exception ex) { Logger.Error('WeixinApi TrySendMessage', ex); } return null; } }
internal class HttpHelper { public static T PostApiDto<T>(string url, string json) where T : ApiDtoBase { string html; using (var client = new WebClient) { var result = client.UploadData(url, 'POST', Encoding.UTF8.GetBytes(json ?? string.Empty)); html = Encoding.UTF8.GetString(result); } try { var dto = Serializer.FromJson<T>(html); if (dto.IsSuccess == false) { Logger.Error('PostApiDto.' typeof(T).FullName '.NotSuccess', dto.GetFullError); } return dto; } catch (Exception ex) { Logger.Error('PostApiDto.' typeof(T).FullName '.Exception', ex); return null; } } }

如果推送的是文本消息:

1 public class TextMessage : MessageBase 2 { 3 public string Text { get; set; } 4 5 public TextMessage(string openId, string text) 6 { 7 this.ToUserOpenId = openId; 8 this.Text = text; 9 } 10 11 public override string ToJson 12 { 13 return Serializer.ToJson( 14 new 15 { 16 touser = this.ToUserOpenId, 17 msgtype = 'text', 18 text = new 19 { 20 content = this.Text 21 } 22 }); 23 } 24 }

如果推送的是圖片消息,則需要先上傳圖片到微信服務(wù)器拿到media_Id(本文后面會展示):

1 public class ImageMessage : MessageBase 2 { 3 public string MediaId { get; set; } 4 5 public ImageMessage(string openId, string mediaId) 6 { 7 this.ToUserOpenId = openId; 8 this.MediaId = mediaId; 9 } 10 11 public override string ToJson 12 { 13 return Serializer.ToJson( 14 new 15 { 16 touser = this.ToUserOpenId, 17 msgtype = 'image', 18 image = new 19 { 20 media_id = this.MediaId 21 } 22 }); 23 } 24 }
核心技術(shù)4:微信圖片上傳與下載

微信圖片的上傳與下載都是通過media_id進(jìn)行的。上傳一個圖片文件之后,微信服務(wù)器返回media_id;如果要下載某張圖片,也需要提供media_id。

關(guān)于圖片上傳這塊,我們封裝了一個非常方便的微信圖片上傳控件,等以后有時間再給大家詳解這個控件,絕對超cool的,現(xiàn)在你可以先體驗(yàn)下。

圖片上傳之前,需要先將用戶上傳的圖片保存到服務(wù)器,然后再將服務(wù)器的圖片上傳到微信服務(wù)器:

public class WeixinApi { public static UploadFileDto UploadFile(string localFilePath, ResourceType type, string accessToken = null) { return HttpHelper.PostFile<UploadFileDto>(WeixinConfigs.Urls.UploadFile(type, accessToken), localFilePath); } }
1 internal class HttpHelper 2 { 3 public static T PostFile<T>(string url, string filePath) where T : ApiDtoBase 4 { 5 string html; 6 using (var client = new WebClient) 7 { 8 var result = client.UploadFile(url, 'POST', filePath); 9 html = Encoding.UTF8.GetString(result); 10 } 11 try 12 { 13 var dto = Serializer.FromJson<T>(html); 14 if (dto.IsSuccess == false) 15 { 16 Logger.Error('PostFile.' typeof(T).FullName '.NotSuccess', dto.GetFullError); 17 } 18 return dto; 19 } 20 catch (Exception ex) 21 { 22 Logger.Error('PostFile.' typeof(T).FullName '.Exception', ex); 23 return null; 24 } 25 } 26 }

下載圖片就非常簡單了,只需要通過media_id獲取下載圖片的URL即可:

public static string GetMediaDownloadUrl(string mediaId, string accessToken = null) { return 'http://file.api.weixin.qq.com/cgi-bin/media/get' $'?access_token={accessToken ?? WeixinKeyManager.Instance.GetAccessToken}&media_id={mediaId}'; }
核心技術(shù)5:自定義菜單的實(shí)現(xiàn)

由于微信定義的接口可以接受JSON格式的自定義菜單項,所以我們就用JS在瀏覽器中編輯菜單,然后最終提交的時候,將整個菜單序列化成JSON,一起提交到微信服務(wù)器。

先看下我們的自定義菜單編輯器吧,純JS打造的,有機(jī)會也給大家分享下:

分享我們團(tuán)隊最近開發(fā)的微信公眾號運(yùn)營助手,可以在手機(jī)上回復(fù)粉絲留言

調(diào)用這個JS的菜單編輯器非常簡單,只需要傳入一個容器和accesstoken即可:

(function { $(document).ready(function { var manager = new WeixinMenuAppManager($('#hfAccessToken').val, $('.content')); manager.init; $('#hfAccessToken').remove; }); });

而傳到我們服務(wù)器之后,調(diào)用微信接口的代碼就非常簡單了:

1 public class WeixinApi 2 { 3 public static string GetMenuJson(string accessToken = null) 4 { 5 return HttpHelper.DownloadString(WeixinConfigs.Urls.GetMenu(accessToken)); 6 } 7 8 public static ApiDtoBase SaveMenu(string json, string accessToken = null) 9 { 10 return HttpHelper.PostApiDto<ApiDtoBase>(WeixinConfigs.Urls.SaveMenu(accessToken), json); 11 } 12 13 public static ApiDtoBase DeleteMenu(string accessToken = null) 14 { 15 return HttpHelper.PostApiDto<ApiDtoBase>(WeixinConfigs.Urls.DeleteMenu(accessToken), null); 16 } 17 }
核心技術(shù)6:帶參數(shù)的臨時二維碼

首先說一下這個臨時二維碼是由微信服務(wù)器生成的。用戶掃碼之后,首先是關(guān)注公眾號,同時我們服務(wù)器還接收到了這個二維碼額外的一個參數(shù)(系統(tǒng)唯一標(biāo)識),我們利用這個參數(shù)就可以很方便的完成多管理員掃碼自動綁定的功能了。

業(yè)務(wù)流程:公眾號所有者點(diǎn)擊【添加管理員】,我們系統(tǒng)就彈出一個有效期5分鐘的臨時二維碼,另一個管理員掃碼關(guān)注公眾號之后,自動將他綁定到該公眾號,再給用戶推送一條客服消息,告訴他綁定成功。

這個體驗(yàn)是相當(dāng)?shù)膸洶。?/p>

生成臨時二維碼的代碼:

public static string GetTempQrCodeUrl(int autoId, int expireMinutes, string accessToken = null) { var data = Serializer.ToJson(new { expire_seconds = expireMinutes*60, action_name = 'QR_SCENE', action_info = new { scene = new { scene_id = autoId } } }); var result = HttpHelper.PostApiDto<GetQrCodeDto>(WeixinConfigs.Urls.GenerateQrCode(accessToken), data); if (result.IsSuccess == false) { throw new KnownException(result.GetFullError); } return WeixinConfigs.Urls.ShowQrCode(result.Ticket); }

用戶掃碼關(guān)注后,服務(wù)器完成自動綁定的代碼就不貼了,太多了,并且夾雜著我們系統(tǒng)其他的業(yè)務(wù)邏輯,不容易理解。

結(jié)語

這個公眾號小助手雖然很小,但幾乎完全包含了我們團(tuán)隊在微信公眾號開發(fā)方面積累的經(jīng)驗(yàn),以及我們自己封裝的很多控件、類庫。如果大家感興趣的話,后面我再專門把這些積累開源。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    成人午夜视频精品一区| 麻豆剧果冻传媒一二三区| 国产精品欧美激情在线播放| 久久婷婷综合色拍亚洲| 日本不卡片一区二区三区| 久久精品国产亚洲av麻豆| 色好吊视频这里只有精| 丁香七月啪啪激情综合| 熟女免费视频一区二区| 欧美日韩一区二区午夜| 色丁香一区二区黑人巨大| 亚洲国产欧美久久精品| 日韩精品免费一区三区| 少妇被粗大进猛进出处故事| 色婷婷视频国产一区视频| 翘臀少妇成人一区二区| 自拍偷女厕所拍偷区亚洲综合| 欧美一级片日韩一级片 | 国产午夜免费在线视频| 熟女免费视频一区二区| 午夜视频成人在线免费| 国产乱久久亚洲国产精品| 在线懂色一区二区三区精品| 免费在线播放一区二区| 国产精品久久香蕉国产线| 亚洲少妇一区二区三区懂色| 日韩一区二区三区四区乱码视频| 亚洲国产欧美精品久久| 丁香六月啪啪激情综合区| 欧美一级黄片欧美精品| 开心久久综合激情五月天| 精品日韩视频在线观看| 好吊日在线观看免费视频| 九九热精品视频在线观看| 国产又粗又猛又黄又爽视频免费| 激情国产白嫩美女在线观看| 丰满人妻少妇精品一区二区三区| 亚洲国产成人精品福利| 中文精品人妻一区二区| 国产精品激情对白一区二区| 日韩一区中文免费视频|