微信小程序中的 联系客服 最基本的使用方法
微信官方文档:
https://developers.weixin.qq.com/miniprogram/dev/server/API/kf-mgnt/kf-message/api_sendcustommessage.html
https://developers.weixin.qq.com/miniprogram/dev/component/button.html
1.在小程序页面中添加一个连续客服的按钮:
<button open-type="contact" bindcontact="handleContact" session-from="来源标识"> 联系客服 </button>
Page({ handleContact(e) { console.log(e.detail.path) // 用户点击的消息路径 console.log(e.detail.query) // 携带的参数 } })
用户点击后进入微信内置的客服聊天界面。
或者使用:
wx.openCustomerServiceConversation({ sessionFrom: '你的会话来源标识', showMessageCard: true, sendMessageTitle: '您好,有什么可以帮您?', sendMessagePath: '/pages/index/index', sendMessageImg: 'https://example.com/image.png', success(res) { console.log('打开客服会话成功', res); }, fail(err) { console.error('打开客服会话失败', err); } });
官方文档:https://developers.weixin.qq.com/minigame/dev/api/open-api/customer-message/wx.openCustomerServiceConversation.html
2、进入小程序的管理平台进行设置开启消息推送,
管理 -> 开发管理 -> 开发设置 -> 消息推送 -> 开启,注意消息的格式要设置成 JSON格式,默认的是 XML 格式,我的代码中全都使用的是json格式解析的。
Token和EncodingAESKey主要是用于设置 消息推送URL(服务器地址) 时候校验地址是否正确的,下面的代码中 WeChatCustomerService方法的get方法就是校验使用的。

3、我用的后台处理是用netCore,
/// <summary> /// 客服消息处理 /// </summary> /// <returns></returns> //[HttpPost] public async Task<IActionResult> WeChatCustomerService() { // GET 请求 = 微信服务器配置 URL 时的签名验证 if (Request.Method.ToUpper() == "GET") { var signature = Request.Query["signature"].ToString(); var timestamp = Request.Query["timestamp"].ToString(); var nonce = Request.Query["nonce"].ToString(); var echostr = Request.Query["echostr"].ToString(); return Ok(echostr); //ValidSignature(); } // POST 请求 = 接收用户消息 string _postBody = await GDCUtility.GetRequestBody(); string resultInfoModel=await GDCWeChatCustomerServiceHelper.HandleMessageAsync(_postBody); return Ok(resultInfoModel); }
/// <summary> /// 微信客服的帮助类 /// </summary> public class GDCWeChatCustomerServiceHelper { private readonly static IMemoryCache _cache=new MemoryCache(new MemoryCacheOptions()); #region 一个简单的接受客户的消息并处理的过程,以后都可以参考这个来扩展 public static async Task<String> HandleMessageAsync(string postBody) { try { // using var reader = new StreamReader(Request.Body, Encoding.UTF8); var body = postBody; // await reader.ReadToEndAsync(); //_logger.LogDebug("收到微信消息: {Body}", body); GDCLogHelper.AddLog($"收到微信消息: {body}", "HandleMessageAsync",Modules.AccessData); if (string.IsNullOrWhiteSpace(body)) { return "success"; } var msg = JsonSerializer.Deserialize<WxMessageModel>(body); if (msg == null) { return "success"; } // 排重:防止微信重试导致重复处理 var msgKey = $"wx_msg_{msg.FromUserName}_{msg.CreateTime}_{ (msg.MsgId==null ? msg.EventKey : msg.MsgId.ToString()) }"; if (_cache.TryGetValue(msgKey, out _)) { //_logger.LogInformation("消息已处理,跳过重复推送: {Key}", msgKey); return "success"; } _cache.Set(msgKey, true, TimeSpan.FromMinutes(5)); // GDCLogHelper.AddLog($"收到微信消息MsgType: {msg.MsgType?.ToLower()}", "HandleMessageAsync", Modules.AccessData); // 根据消息类型分发处理 switch (msg.MsgType?.ToLower()) { case "text": await HandleTextMessageAsync(msg); break; case "image": await HandleImageMessageAsync(msg); break; case "event": await HandleEventMessageAsync(msg); break; default: //_logger.LogInformation("收到未处理的消息类型: {MsgType}", msg.MsgType); break; } } catch (Exception ex) { //_logger.LogError(ex, "处理微信消息异常"); } // 必须返回 success,否则微信会重试3次 return "success"; } /// <summary> /// 处理文字消息 /// </summary> private static async Task HandleTextMessageAsync(WxMessageModel msg) { // _logger.LogInformation("用户[{Openid}]发送文字: {Content}", msg.FromUserName, msg.Content); //GDCLogHelper.AddLog($"用户[{msg.FromUserName}]发送文字: {msg.Content}", "HandleMessageAsync", Modules.AccessData); // 简单关键词回复,实际可接入 NLP/AI var reply = msg.Content switch { "1" => "【订单查询】请输入您的订单号", "2" => "【售后服务】请描述您遇到的问题", "帮助" or "help" => "回复数字选择服务:\n1. 订单查询\n2. 售后服务\n3. 联系人工客服", _ => $"收到您的消息:{msg.Content}\n客服正在处理中..." }; await SendCustomerMessageAsync(msg.FromUserName, reply); } /// <summary> /// 处理图片消息 /// </summary> private static async Task HandleImageMessageAsync(WxMessageModel msg) { // _logger.LogInformation("用户[{Openid}]发送图片: {PicUrl}", msg.FromUserName, msg.PicUrl); await SendCustomerMessageAsync(msg.FromUserName, "收到图片,客服正在查看,请稍候..."); } /// <summary> /// 处理事件消息(用户进入客服会话等),第一次点 联系客服 之类 的进入 /// </summary> private static async Task HandleEventMessageAsync(WxMessageModel msg) { if (msg.Event == "user_enter_tempsession") { // _logger.LogInformation("用户[{Openid}]进入客服会话", msg.FromUserName); // 发送欢迎语 + 菜单 var welcome = "👋 您好!欢迎来到客服中心\n\n" + "回复数字选择服务:\n" + "1️⃣ 订单查询\n" + "2️⃣ 售后服务\n" + "3️⃣ 联系人工客服\n\n" + "或输入您的问题,智能客服为您解答"; await SendCustomerMessageAsync(msg.FromUserName, welcome); } } #endregion #region 基本的给用户发送消息方法 /// <summary> /// 发送文本客服消息 /// </summary> public static async Task<bool> SendCustomerMessageAsync(string openid, string content) { var accessToken = GDCWeChatAppHelper.GetAccessToken(); var url = $"https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={accessToken}"; var payload = new { touser = openid, msgtype = "text", text = new { content } }; //这个会对 导致 👋 被转成了 \uD83D\uDC4B //var json = JsonSerializer.Serialize(payload, new JsonSerializerOptions //{ // PropertyNamingPolicy = JsonNamingPolicy.CamelCase, // Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping //防止转义 //}); var json = Newtonsoft.Json.JsonConvert.SerializeObject(payload); Console.WriteLine(json); var response =GDCHttpRequestHelper.HttpPostString(url,json,"", "application/json", "application/json").Result; //var result = await response.Content.ReadAsStringAsync(); //_logger.LogDebug("发送客服消息结果: {Result}", result); //GDCLogHelper.AddLog($"发送客服消息结果: {response}", "HandleMessageAsync", Modules.AccessData); var wxRes = JsonSerializer.Deserialize<WxResponseModel>(response); if (wxRes?.ErrCode != 0) { // _logger.LogError("发送客服消息失败: {ErrCode} {ErrMsg}", wxRes?.ErrCode, wxRes?.ErrMsg); //GDCLogHelper.AddLog($"发送客服消息失败: {wxRes?.ErrCode} {wxRes?.ErrMsg}", "HandleMessageAsync", Modules.AccessData); return false; } return true; } /// <summary> /// 发送小程序卡片(引导用户跳转页面) /// </summary> public static async Task<bool> SendMiniProgramCardAsync(string openid, string title, string pagePath, string thumbMediaId) { var accessToken = GDCWeChatAppHelper.GetAccessToken(); var url = $"https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={accessToken}"; var payload = new { touser = openid, msgtype = "miniprogrampage", miniprogrampage = new { title, pagepath = pagePath, thumb_media_id = thumbMediaId } }; //这个会对 导致 👋 被转成了 \uD83D\uDC4B //var json = JsonSerializer.Serialize(payload, new JsonSerializerOptions //{ // PropertyNamingPolicy = JsonNamingPolicy.CamelCase, // Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping //防止转义 //}); var json = Newtonsoft.Json.JsonConvert.SerializeObject(payload); var response = GDCHttpRequestHelper.HttpPostString(url,json,"", "application/json", "application/json").Result; //var result = await response.Content.ReadAsStringAsync(); var wxRes = JsonSerializer.Deserialize<WxResponseModel>(response); return wxRes?.ErrCode == 0; } #endregion } /// <summary> /// 微信推送的消息结构 /// </summary> public class WxMessageModel { [JsonPropertyName("ToUserName")] public string ToUserName { get; set; } [JsonPropertyName("FromUserName")] public string FromUserName { get; set; } [JsonPropertyName("CreateTime")] public long CreateTime { get; set; } [JsonPropertyName("MsgType")] public string MsgType { get; set; } [JsonPropertyName("MsgId")] public long? MsgId { get; set; } [JsonPropertyName("Content")] public string Content { get; set; } [JsonPropertyName("PicUrl")] public string PicUrl { get; set; } [JsonPropertyName("MediaId")] public string MediaId { get; set; } [JsonPropertyName("Event")] public string Event { get; set; } [JsonPropertyName("EventKey")] public string EventKey { get; set; } [JsonPropertyName("SessionFrom")] public string SessionFrom { get; set; } } /// <summary> /// 微信接口通用响应 /// </summary> public class WxResponseModel { [JsonPropertyName("errcode")] public int ErrCode { get; set; } [JsonPropertyName("errmsg")] public string ErrMsg { get; set; } }
4、运行的效果
![]()


重要说明:
如果小程序后台配置了多名客服,消息会由系统根据在线情况分配给相应客服,
- 消息会由微信的客服系统自动根据在线状态和接待能力等规则分配给具体某个在线客服。
- 开发者和小程序端无法控制或指定具体将用户消息分配给哪位客服。
- 系统会优先分配给在线且空闲的客服,保证用户能尽快获得响应。
这个自动分配机制是微信官方托管的,目的是均衡客服工作量和提升用户体验。
如果还想更多的要求,就自己动手仔细研究。。。
浙公网安备 33010602011771号