1.搭建回调服务器

  可参考:https://www.cnblogs.com/zspwf/p/16381643.html进行搭建

2.编写代码

2.1接口定义

应用可以发送模板卡片消息,发送之后可再通过接口更新可回调的用户任务卡片消息的替换文案信息(仅原卡片为 按钮交互型、投票选择型、多项选择型的卡片以及填写了action_menu字段的文本通知型、图文展示型可以调用本接口更新)。

请注意,当应用调用发送模版卡片消息后,接口会返回一个response_code,通过response_code用户可以调用本接口一次。后续如果有用户点击任务卡片,回调接口也会带上response_code,开发者通过该code也可以调用本接口一次,注意response_code的有效期是24小时,超过24小时后将无法使用。

请求方式:POST(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/update_template_card?access_token=ACCESS_TOKEN

参数说明:

access_token:接口授权

2.2 appsettings配置

  根据实际情况填写、

corpid 企业ID

corpsecret 应用密钥,

CallBackToken 企业微信后台,开发者设置的Token,

EncodingAESKey企业微信后台,开发者设置的EncodingAESKey。

 "Wx": {
"Baseurl": "https://qyapi.weixin.qq.com/cgi-bin/",
"PushUrl": "message/send?access_token={0}",
"PushCardUrl": "message/update_template_card?access_token={0}",
"PushTokenUrl": "gettoken?corpid=&corpsecret=",
"CallBackToken": "",
"EncodingAESKey": "",
"corpid": ""
}

2.3 Startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient("WxClient", config =>
{
config.BaseAddress = new Uri(Configuration["Wx:baseurl"]);
config.DefaultRequestHeaders.Add("Accept", "application/json");
});
} public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
GlobalContext.httpClientFactory = app.ApplicationServices.GetService<IHttpClientFactory>();
}

2.4 GlobalContext.cs

  提供了Token,推送等方法。

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text; namespace Wx
{
public class GlobalContext
{
public static IHttpClientFactory httpClientFactory { get; set; } /// <summary>
/// Wx 过期时间
/// </summary>
public static DateTime TimeOutDate { get; set; } /// <summary>
/// Wx Token
/// </summary>
public static string Token { get; set; } /// <summary>
/// 获取Token
/// </summary>
/// <returns>Item1 Token;Item2 是否成功</returns>
public static Tuple<string, bool> GetPushToken()
{
//判断Token是否存在 以及Token是否在有效期内
if (string.IsNullOrEmpty(Token) || TimeOutDate > DateTime.Now)
{
//构造请求链接
var requestBuild = AppSetting.Configuration["Wx:PushTokenUrl"];
using (var wxClient = httpClientFactory.CreateClient("WxClient"))
{
var httpResponse = wxClient.GetAsync(requestBuild).Result;
var dynamic = JsonConvert.DeserializeObject<GetTokenResult>(
httpResponse.Content.ReadAsStringAsync().Result
); if (dynamic.errcode == 0)
{
Token = dynamic.access_token;
//过期5分钟前刷新Token
var expires_in = Convert.ToDouble(dynamic.expires_in - 5 * 60);
TimeOutDate = DateTime.Now.AddSeconds(expires_in);
return Tuple.Create(Token, true);
}
else
{
return Tuple.Create($"获取Token失败,错误:{ dynamic.errmsg}", false);
}
}
}
else
{
return Tuple.Create(Token, true);
}
} /// <summary>
/// 推送MES
/// </summary>
/// <returns>Item1 Token;Item2 是否成功</returns>
public static string WxPush(string content)
{
//构造请求链接
var requestBuild = AppSetting.Configuration["Wx:PushUrl"];
var (token, issuccess) = GetPushToken();
if (!issuccess)
throw new Exception(token);
requestBuild = string.Format(requestBuild, token);
//建立HttpClient
using (var wxClient = httpClientFactory.CreateClient("WxClient"))
{
byte[] data = Encoding.UTF8.GetBytes(content);
var bytearray = new ByteArrayContent(data);
var httpResponse = wxClient.PostAsync(requestBuild, bytearray).Result;
var dynamic = JsonConvert.DeserializeObject<dynamic>(
httpResponse.Content.ReadAsStringAsync().Result
);
bytearray.Dispose();
if (dynamic.errcode == 0)
return "推送成功!";
if (dynamic.errcode == 82001)
throw new Exception("推送失败,原因:未配置员工手机号或者员工手机号不在应用可见范围!");
else
throw new Exception($"推送失败,原因:{JsonConvert.SerializeObject(dynamic) }");
}
} /// <summary>
/// 获取发送内容
/// </summary>
/// <param name="userId"></param>
/// <param name="Msg"></param>
/// <returns></returns>
public static string GetTextContent(string userId, string msg, int agentid)
{
var objText = new { content = msg };
string text = JsonConvert.SerializeObject(objText);
var obj = new
{
touser = userId,
toparty = "",
totag = "",
msgtype = "text",
agentid = agentid,
text = objText,
safe = 0,
enable_id_trans = 0,
enable_duplicate_check = 0,
duplicate_check_interval = 1800
};
string strJson = JsonConvert.SerializeObject(obj);
return strJson;
} /// <summary>
/// 更新微信推送消息内容
/// </summary>
/// <param name="userId"></param>
/// <param name="responsecode"></param>
/// <param name="replacename"></param>
/// <param name="agentid"></param>
/// <returns></returns>
public static string UpdateTextCardContent(string[] userId, string responsecode, string replacename, int agentid)
{
var obj = new
{
userids = userId,
atall = 0,
agentid = agentid,
response_code = responsecode,
button = new
{
replace_name = replacename
}
}; string strJson = JsonConvert.SerializeObject(obj);
return strJson;
} /// <summary>
/// 更新卡片消息
/// </summary>
/// <returns>Item1 Token;Item2 是否成功</returns>
public static string UpdateCard(string content)
{
//构造请求链接
var requestBuild = AppSetting.Configuration["Wx:PushCardUrl"];
var (token, issuccess) = GetPushToken();
if (!issuccess)
throw new Exception(token);
requestBuild = string.Format(requestBuild, token);
//建立HttpClient
using (var wxClient = httpClientFactory.CreateClient("WxClient"))
{
byte[] data = Encoding.UTF8.GetBytes(content);
var bytearray = new ByteArrayContent(data);
var httpResponse = wxClient.PostAsync(requestBuild, bytearray).Result;
var dynamic = JsonConvert.DeserializeObject<dynamic>(
httpResponse.Content.ReadAsStringAsync().Result
);
bytearray.Dispose();
if (dynamic.errcode == 0)
return "推送成功!";
if (dynamic.errcode == 82001)
throw new Exception("推送失败,原因:未配置员工手机号或者员工手机号不在应用可见范围!");
else
throw new Exception($"推送失败,原因:{JsonConvert.SerializeObject(dynamic) }");
}
} }
}

GlobalContext.cs

2.5 回调中编写内容

  下图中是按钮交互性的按钮,点击确认会触发回调服务器的方法,在回调服务中根据返回的FromUserName和ResponseCode调用更新模板方法,把按钮改为已推送。

 

  下面代码为回调服务中的Post方法,在1中搭建回调服务器中的方法。业务逻辑,失主请求获取联系方式,拾取人点击确认,推送联系方式至失主企业微信。将确认更新成已发送。可根据自己的实际业务替换内容,其中UpdateCard方法为更新模板已推送方法。

[HttpPost, Route("callback/interAspect")]
public ContentResult AcceptMessage(string msg_signature,string timestamp,string nonce)
{
//获取被动响应包
string encrypt = "";
using (StreamReader sr = new StreamReader(Request.Body, Encoding.UTF8))
{
encrypt = sr.ReadToEndAsync().Result; }
//验证
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(AppSetting.Configuration["Wx:CallBackToken"]
, AppSetting.Configuration["Wx:EncodingAESKey"]
, AppSetting.Configuration["Wx:corpid"]); string sMsg = ""; // 解析之后的明文
int ret = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, encrypt, ref sMsg);
if (ret != 0)
{
throw new Exception();
}
// ret==0表示解密成功,sMsg表示解密之后的明文xml串
XmlDocument doc = new XmlDocument();
doc.LoadXml(sMsg);
XmlNode root = doc.FirstChild; string userName = root["FromUserName"].InnerText;
string eventKey = root["EventKey"].InnerText;
string responseCode = root["ResponseCode"].InnerText; //业务逻辑 eventKey是我保存的请求人推送UserID。
var content = GlobalContext.GetTextContent(eventKey, $"我的联系方式:" + userName, 1);
var message = GlobalContext.WxPush(content);
if (message == "推送成功!")
{
try
{
var responseContent = GlobalContext.UpdateTextCardContent(new string[] { userName }, responseCode, "已推送", 1);
            var updateMessage = GlobalContext.UpdateCard(responseContent);
if (updateMessage == "推送成功!")
{
return Content("成功");
}
else
{throw new Exception();
}
}
catch(Exception ex)
{throw new Exception();
} }
else
{
throw new Exception();
}
}

3.测试

4.链接

  更新模板卡片:https://developer.work.weixin.qq.com/document/path/94888

.Net Core 企业微信更新模版卡片消息的更多相关文章

  1. .NET Core 企业微信消息推送

    接口定义 应用支持推送文本.图片.视频.文件.图文等类型.请求方式:POST(HTTPS)请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send? ...

  2. .NET Core 企业微信回调配置

    1.配置API接收 2.下载加密解密库 地址:https://developer.work.weixin.qq.com/devtool/introduce?id=36388,也可以复制下面的代码 2. ...

  3. 【原创】在 ASP.NET Core 3.1 中使用 Senparc.Weixin.Work 企业微信 SDK —— 发送文本消息

    下面在 Web 空应用里展示一个简单的例子来实现发送文本消息. 本文目录: 创建 Web 空应用 命令行方式创建 添加SDK引用 命令行方式 进入项目目录 添加包引用 配置和使用SDK 添加appse ...

  4. 【原创】在 .NET Core 3.1 中使用 Senparc.Weixin.Work 企业微信 SDK —— 发送文本消息

    下面在控制台应用里展示一个简单的例子来实现发送文本消息. 本文目录: 创建控制台应用 添加SDK引用 命令行方式 进入项目目录 添加包引用 配置和使用SDK 添加appsettings.json文件 ...

  5. 通过企业微信API接口发送消息

    最近给公司测试组内部开发一个记账小工具,当账目出现问题的时候需要发送消息通知大家,前期主要采用的QQ发送通知消息,但是有一天突然无法连接到QQ服务器,运维的同学建议采用微信的方式对接然后进行告警,所以 ...

  6. Java企业微信开发_01_接收消息服务器配置

    一.准备阶段 需要准备事项: 1.一个能在公网上访问的项目: 见:Java微信公众平台开发_01_本地服务器映射外网 2.一个企业微信账号: 去注册:(https://work.weixin.qq.c ...

  7. .NET Core企业微信网页授权登录

    1.开发前准备 参数获取 corpid 每个企业都拥有唯一的corpid,获取此信息可在管理后台"我的企业"-"企业信息"下查看"企业ID" ...

  8. Asp.Net Core 企业微信静默授权

    企业微信接口文档 1.构造授权网页链接 2.回调获取到 Code 通过code+access_token去请求用户信息 3.获取access_token 调试准备工作 -->内网穿透+域名 推荐 ...

  9. Java企业微信开发_05_消息推送之被动回复消息

    一.本节要点 1.消息的加解密 微信加解密包 下载地址:http://qydev.weixin.qq.com/java.zip      ,此包中封装好了AES加解密方法,直接调用方法即可. 其中,解 ...

随机推荐

  1. MySQL高级以及锁机制

    MySQL高级 推荐阅读: 锁:https://www.cnblogs.com/zwtblog/tag/锁/ 数据库:https://www.cnblogs.com/zwtblog/tag/数据库/ ...

  2. Java 8 学习记录

    Java 8 学习记录 官方文档 https://docs.oracle.com/javase/8/ https://docs.oracle.com/javase/8/docs/index.html ...

  3. 深入理解Kafka核心设计及原理(三):消费者

    转载请注明出处:https://www.cnblogs.com/zjdxr-up/p/16114877.html 深入理解Kafka核心设计及原理(一):初识Kafka 深入理解Kafka核心设计及原 ...

  4. GRPC-go版本

    GRPC-go版本 1.安装GO,protobuf 只适合有梯子的 GO的安装没必要说了 protobuf :https://github.com/protocolbuffers/protobuf/r ...

  5. 使用加强堆结构解决topK问题

    作者:Grey 原文地址: 使用加强堆结构解决topK问题 题目描述 LintCode 550 · Top K Frequent Words II 思路 由于要统计每个字符串的次数,以及字典序,所以, ...

  6. Python 康德乐大药房网站爬虫,使用bs4获取json,导入mysql

    自学两天,写个low点的爬虫代码.自己获取商品价格接口的过程,使用软件 Fiddler 进行抓包进行分析.调用接口进行异常判断

  7. Spring Retry 在SpringBoot 中的应用

    Spring Boot中使用Spring-Retry重试框架 Spring Retry提供了自动重新调用失败的操作的功能.这在错误可能是暂时的(例如瞬时网络故障)的情况下很有用. 从2.2.0版本开始 ...

  8. [AcWing 862] 三元组排序

    点击查看代码 #include <iostream> #include <algorithm> using namespace std; const int N = 1e5 + ...

  9. js 如何判断变量类型

    自定义一些类型 const boolean = true const string = '这是一个字符串' const number = 1 const array = [] const object ...

  10. 干货 | LVM快照学习

    一个执着于技术的公众号 前言 在上一章节,我们学习了LVM逻辑卷管理技术,知道了LVM能够通过增减PE的数量来弹性调整文件系统的大小.除此之外,LVM还有另一个重要功能「LVM快照技术」,也就是可以给 ...