分享微信公众号运营助手,可以在手机上回复粉丝留言

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分享微信公众号运营助手,可以在手机上回复粉丝留言相关的知识,希望对你有一定的参考价值。

由于公司旗下有好几个微信公众号,经常来回切换登录很麻烦,粉丝留言咨询的时候常常不能及时回复,导致订单流失。于是我们团队开发了一个公众号小助手,可以把多个公众号绑定进来,只要有粉丝留言,马上管理员就收到通知了,然后还可以在手机上进行回复。

 

实现的功能如下:

  1. 粉丝留言自动微信通知

  2. 在微信中回复粉丝留言,文字+图片

  3. 粉丝关注自动微信通知

  4. 粉丝关注自动推送多图文消息或者历史消息

  5. 更强大的自定义菜单管理

  6. 自定义客服消息模板

  7. 支持绑定多个管理员

  8. 支持关键词自动回复

  9. 支持二次开发

 

虽然这个小助手很小,但是里面用到的技术我觉得还是有一定分享价值。本文就向大家分享一下这个小助手中核心的技术方案,包括:公众号绑定、粉丝信息获取、给粉丝发送消息、微信图片上传与下载、公众号自定义菜单接口、公众号临时二维码的妙用等等。

 

核心技术1:多个公众号的绑定

想要调用微信公众号的API,首先要通过AppId和AppSecret获取AccessToken,而AccessToken过一段时间就会过期。为了提高AccessToken的利用率并且实现自动刷新,我们专门写了一个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         else50         {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,就可以调用绝大部分接口了。

 

核心技术2:拉取粉丝基本信息

 不同的微信公众号下面的粉丝拥有不同的OpenId,而OpenId是微信对于用于的唯一标识。

 

微信提供了几个事件发生的时候,程序可以获取用户的OpenId,而用OpenId就可以跟用户互动。我们仅用了2个事件获取OpenId:粉丝关注时和粉丝留言时。

 

下面的代码下载 展示了如何通过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;
    }
}


 

核心技术3:给粉丝发送消息

注意这里仅仅是发送的客服消息,也就是粉丝与公众号互动之后的48小时内可以随意给粉丝发送的消息,包括文字和图片下载 

 


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             new15             {16                 touser = this.ToUserOpenId,17                 msgtype = "text",18                 text = new19                 {20                     content = this.Text21                 }22             });23     }24 }


 

如果推送的是图片消息,则需要先上传图片到微信服务器拿到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             new15             {16                 touser = this.ToUserOpenId,17                 msgtype = "image",18                 image = new19                 {20                     media_id = this.MediaId21                 }22             });23     }24 }


 

核心技术4:微信图片上传与下载

微信图片的上传与下载都是通过media_id进行的。上传一个图片文件之后,微信服务器返回media_id;如果要下载某张图片,也需要提供media_id。

 

关于图片上传这块,我们封装了一个非常方便的微信图片上传控件下载 ,等以后有时间再给大家详解这个控件,绝对超cool的,现在你可以先体验下。

 

图片上传之前,需要先将用户上传的图片保存到服务器,然后再将服务器的图片上传到微信服务器:


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         try12         {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}";
}

 


以上是关于分享微信公众号运营助手,可以在手机上回复粉丝留言的主要内容,如果未能解决你的问题,请参考以下文章

微信公众号营销用鱼塘微营销系统怎么样?

公众号留言功能怎么开通?微信公众号没有留言功能怎么办?

为什么代运营越来越火

分享利用微信公众号做淘宝客返利机器人系统的3个技巧

微信公众号代注册运营去哪里找?

小程序公众号数据助手升级为公众平台助手,增加消息留言赞赏通知四个功能