知识点

相关文章

更多

最近更新

更多

微信公共服务平台开发(.Net 的实现)11-------客服消息(定项消息推送 重要的OPENID)

2019-03-02 00:59|来源: 网路

   这次我们来一起研究一下“客服消息”,首先明确一下“客服消息”的概念。这不同于之前的“被动响应消息”,也就是说并不是之前“你一言我一语的即时响应”,可能在某种情况下你需要给不同的人主动发送消息,例如你的餐馆推出了新的川菜,那么你需要给喜欢川菜的人发送消息,而并不是等着被人发送“有什么新菜”后,然后反馈给客户,我推出了什么什么的。

 

       说道这里可能有人会问,那不是群发吗?微信不是每天只能发一条吗?服务号每个月发一条吗?答案很明确微信说的是“客服消息”,也不是群发,它跟群发的区别就在于只要关注了我,那么我就可以群发给你消息,而为了不让用户感到讨厌,微信作了严格的群发条数限制。而“客服消息”则是只有关注你的人向你发送了消息,你才能主动推送。就像打电话只有人家问过你问题了,你才能回答,并且继续跟进回答。再举一个例子:你通过被人知道了我的手机号,存下来了,你突然给我打电话,我肯定是抵触的。但是如果我给你打过电话,你通过来电显示知道了我的号码,以后再给我打电话,说明我们是认识的,我最少不会抵触。这就使群发/被动响应/客服消息的本质区别。

 

       就像我们可以通过收集电话号码,手机自己的客户信息一样,一旦他们的信息被我们收录。那么我们就可以突破群发条数的限制了,按照微信的限制群发一个月只能一条(服务号),但是“客服消息”则可以一天50000条,足够用了。

 

       下面的问题就是如何手机客户的“手机号”了,微信里面有一个OPENID,这就使手机号了,这个是关注你的用户的唯一标识,这个标识是不会变的,但是同一个用户关注不同的微信号,那么他在不同微信号中的ID是不一样的。如何取得OPENID呢?

 

       网上找了些资料,有的说的的确是错误的,有的还说要通过OAuth 2.0授权才可以,这个的确可以,但是太复杂了吧,通过我的测试得出了这样的结论“只要用户和你的公共微信好发生交互”就可以取得他的OPENID了。就如同打电话一样,只要用户给你打了电话,你一定知道他的电话了。在微信里是这样的:用户只要发信息给你,或者点了某个菜单,发过来的信息都会有一个“FromUserName”,这个就使OPENID了。我们可以建立一个数据库来收集这些宝贵的用户身份信息,也就是记录他的“电话号码”,有了电话号码,我们就可以以后经常与客户主动打电话了。我做这样的一个实验:

 

       首先记录用户的OPENID在OnLoad函数第二行里面加上一个 WriteLog(wx.FromUserName);把它记录在一个文本文件中

protected void Page_Load(object sender, EventArgs e)
{
wxmessage wx = GetWxMessage();
WriteLog(wx.FromUserName);
string res = "";


if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "subscribe")
{
string content = "";
if (!wx.EventKey.Contains("qrscene_"))
{
content = "/:rose欢迎北京永杰友信科技有限公司/:rose\n直接回复“你好”";
res = sendTextMessage(wx, content);
}
else
{
content = "二维码参数:\n" + wx.EventKey.Replace("qrscene_", "");
res = sendTextMessage(wx, content);
}
}

else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.ToLower() == "scan")
{
string str = "二维码参数:\n" + wx.EventKey;
res = sendTextMessage(wx, str);
}
else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "CLICK")
{
if(wx.EventKey=="HELLO")
res = sendTextMessage(wx, "你好,欢迎使用北京永杰友信科技有限公司公共微信平台!");
}
else if (!string.IsNullOrEmpty(wx.EventName) && wx.EventName.Trim() == "LOCATION")
{
res = sendTextMessage(wx, "您的位置是经度:" + wx.Latitude + ",维度是:" + wx.Longitude+",地理经度为:"+wx.Precision);
}
else
{
if (wx.MsgType == "text" && wx.Content == "你好")
{

res = sendTextMessage(wx, "你好,欢迎使用北京永杰友信科技有限公司公共微信平台!");
}
else if (wx.MsgType == "voice")
{
res = sendTextMessage(wx, wx.Recognition);
}
else if (wx.MsgType == "location")
{
res = sendTextMessage(wx, "您发送的位置是:" + wx.Label + ";纬度是:" + wx.Location_X + ";经度是:" + wx.Location_Y + ";缩放比例为:" + wx.Scale);
}
else
{
res = sendTextMessage(wx, "你好,未能识别消息!");
}
}

 

Response.Write(res);
}

WriteLog的方法是这样的:

/// <summary>
/// 写日志(用于跟踪)
/// </summary>
private void WriteLog(string strMemo)
{
string filename = Server.MapPath("/logs/log.txt");
if (!Directory.Exists(Server.MapPath("//logs//")))
Directory.CreateDirectory("//logs//");
StreamWriter sr = null;
try
{
if (!File.Exists(filename))
{
sr = File.CreateText(filename);
}
else
{
sr = File.AppendText(filename);
}
sr.WriteLine(strMemo);
}
catch
{

}
finally
{
if (sr != null)
sr.Close();
}
}

      这样当客户发送任何一种信息给微信公共号,我们的log.txt文件中就会记录这个OPENID,我先打开Log.txt这个文件看看OPENID号,我的事这样的“oV93gjl5slD3p29yS1dOijy-pqZ8”,有了这个OPENID很多事情就都好办了,以后我们还会介绍如何获取客户的信息。这里先说“客户消息”吧。

 

        下面我们建立一个新的ASPX页面,在这个页面里面我就可以给这些用户发信息了。这个页面(SendMessage.aspx.cs)很简单就使两个文本框和一个按钮:

 

string MyOpenID;
string MyContent;
protected void Page_Load(object sender, EventArgs e)
{
MyOpenID = "oV93gjl5slD3p29yS1dOijy-pqZ8";
MyContent = "这是一个客服消息";
UserName.Text = MyOpenID;
Content.Text = MyContent;
}
protected void Button1_Click(object sender, EventArgs e)
{
string res = "";
string Access_Token = IsExistAccess_Token();

string posturl = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + Access_Token;
string postData = "{\"touser\":\"" + UserName.Text + "\",\"msgtype\":\"text\",\"text\":{\"content\":\"" + Content.Text + "\"}}";
res = GetPage(posturl, postData);

Response.Write(res);
}

 

    中间还用到了之前提到的3个函数:

public string GetPage(string posturl, string postData)
{
Stream outstream = null;
Stream instream = null;
StreamReader sr = null;
HttpWebResponse response = null;
HttpWebRequest request = null;
Encoding encoding = Encoding.UTF8;
byte[] data = encoding.GetBytes(postData);
// 准备请求...
try
{
// 设置参数
request = WebRequest.Create(posturl) as HttpWebRequest;
CookieContainer cookieContainer = new CookieContainer();
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = true;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
outstream = request.GetRequestStream();
outstream.Write(data, 0, data.Length);
outstream.Close();
//发送请求并获取相应回应数据
response = request.GetResponse() as HttpWebResponse;
//直到request.GetResponse()程序才开始向目标网页发送Post请求
instream = response.GetResponseStream();
sr = new StreamReader(instream, encoding);
//返回结果网页(html)代码
string content = sr.ReadToEnd();
string err = string.Empty;
return content;
}
catch (Exception ex)
{
string err = ex.Message;
Response.Write(err);
return string.Empty;
}
}

/// <summary>
/// 根据当前日期 判断Access_Token 是否超期 如果超期返回新的Access_Token 否则返回之前的Access_Token
/// </summary>
/// <param name="datetime"></param>
/// <returns></returns>
public static string IsExistAccess_Token()
{

string Token = string.Empty;
DateTime YouXRQ;
// 读取XML文件中的数据,并显示出来 ,注意文件路径
string filepath = HttpContext.Current.Server.MapPath("XMLFile.xml");

StreamReader str = new StreamReader(filepath, System.Text.Encoding.UTF8);
XmlDocument xml = new XmlDocument();
xml.Load(str);
str.Close();
str.Dispose();
Token = xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText;
YouXRQ = Convert.ToDateTime(xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText);

if (DateTime.Now > YouXRQ)
{
DateTime _youxrq = DateTime.Now;
Access_token mode = GetAccess_token();
xml.SelectSingleNode("xml").SelectSingleNode("Access_Token").InnerText = mode.access_token;
_youxrq = _youxrq.AddSeconds(int.Parse(mode.expires_in));
xml.SelectSingleNode("xml").SelectSingleNode("Access_YouXRQ").InnerText = _youxrq.ToString();
xml.Save(filepath);
Token = mode.access_token;
}
return Token;
}

 

public static Access_token GetAccess_token()
{
string appid = "wx043225275885dafd";
string secret = "cb4425b24ab79ef875029cf0bf326ae9";
string strUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
Access_token mode = new Access_token();

HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(strUrl);

req.Method = "GET";
using (WebResponse wr = req.GetResponse())
{
HttpWebResponse myResponse = (HttpWebResponse)req.GetResponse();

StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);

string content = reader.ReadToEnd();
//Response.Write(content);
//在这里对Access_token 赋值
Access_token token = new Access_token();
token = JsonHelper.ParseFromJson<Access_token>(content);
mode.access_token = token.access_token;
mode.expires_in = token.expires_in;
}
return mode;
}

     这个页面就是这些了,打开这个页面然后发送消息试试?很不错吧,这样在配合上我们的数据库啦,什么循环了,就可以突破了微信群发的限制,做到定项的群发消息推送了!这里面能发很多种消息:文本,语音,视频,图文,图片等等。只是Json而已,聪明的你一定可以举一反三的。


转自:http://www.cnblogs.com/lyl6796910/p/3661158

相关问答

更多
  • 看看什么是stackoverflow提供。 https://stackoverflow.com/users/login 可悲的是不知道你必须使用什么网址,但有一些选择是目前流行的。 问候 take a look what stackoverflow is offering. https://stackoverflow.com/users/login sadly no idea what urls you have to use, but a little choice what is popular so ...
  • 我发现了我的错误。 问题在于使用太新的附加库。 为了正确的工作,请使用openid4java下载的库 I have found my error. Problem was in using too new additional libraries. For correct work use libraries which is you are downloading with openid4java
  • 看起来应用程序需要请求openid本身,因为似乎没有返回有关当前openid的会话信息 Looks like the application needs to request the openid itself since there appears to be no session information returned about the current openid
  • 是的,如果OpenID依赖方请求并且用户同意共享这些数据,OpenID提供商可以并且经常提供有关登录人员的“声明”或“属性”。 如果您使用DotNetOpenAuth作为ASP.NET OpenID库,它内置支持几种获取这些属性的方法,但无论提供者提供哪种方式,都可以让您轻松获取这些属性。 如果您下载该库,它会附带一个如何执行此操作的示例。 至于工作地址,以及特定于某些域(数据域 - 而不是Internet域)的某些其他属性,很少有提供商提供它们。 您可以做的最好的事情是获取“完整地址”并询问用户是否是他们 ...
  • 我看一下实际的omniauth-openid gem的源代码,看起来似乎没有添加这个功能。 尝试发出功能请求。 I take a look through the source-code of the actual omniauth-openid gem and it seems to be, that this functionality is not added. Try to make a feature-request.
  • 我遇到了完全相同的问题,发现问题在于这一行: OPENID_CREATE_USER = True 此设置缺少名称末尾的S 该行应为: OPENID_CREATE_USERS = True 更正此错误导致OpenID登录完美运行。 当OP说“已经完成了相同的settings.py粘贴在这个页面上,但它现在正在工作......”他们可能错过了这个非常小的差异。 I ran into the exact same issue and discovered that the problem was with t ...
  • 没有这样的系统,你正在寻找。 您可以使用openid请求许多属性,但不能依赖于它们的发送。 通常,OpenID的AX扩展非常适合您的需求,但是大多数提供商只提供少数AX属性 - 当然,用户可能只是拒绝提供它们。 There is no such system that you're looking for. You can request many attributes with openid, however you can't depend on them being sent. Generally, ...
  • 这可能没有关系,但看起来AOL的OpenID可能现在有问题,我不得不切换到另一个提供商登录到SO。 This may not be related, but it looks like AOL's OpenID may be having issues right now, I had to switch to another provider to log into SO.
  • OpenID 2.0中需要openid.claimed_id参数,但OpenID 1.1中不需要。 因此,您的OpenID提供程序(Zend)很可能只实现OpenID 1.1。 从这里我们可以得出几件事: 考虑将OpenID Provider升级到OpenID 2.0。 它更安全,更有能力。 您的Zend Provider发布的OpenID可能声称与OpenID 2.0兼容,因为它们只应声明1.1兼容性。 DotNetOpenAuth可以很好地对抗1.1和2.0,但不会对于假装为2.0而不是2.0的1.1。 ...
  • 问题在于获得个人资料。 我还是不知道出了什么问题。 所以我删除了询问个人资料并将网址“/ auth / openid / return”更改为GET请求。 所以代码现在工作正常。 The problem was in getting profile. I still don't know what is wrong. So I removed asking profile and changed url "/auth/openid/return" to GET request. So code is wor ...