.Net Core 企业微信更新模版卡片消息
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
参数说明:
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 企业微信更新模版卡片消息的更多相关文章
- .NET Core 企业微信消息推送
接口定义 应用支持推送文本.图片.视频.文件.图文等类型.请求方式:POST(HTTPS)请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send? ...
- .NET Core 企业微信回调配置
1.配置API接收 2.下载加密解密库 地址:https://developer.work.weixin.qq.com/devtool/introduce?id=36388,也可以复制下面的代码 2. ...
- 【原创】在 ASP.NET Core 3.1 中使用 Senparc.Weixin.Work 企业微信 SDK —— 发送文本消息
下面在 Web 空应用里展示一个简单的例子来实现发送文本消息. 本文目录: 创建 Web 空应用 命令行方式创建 添加SDK引用 命令行方式 进入项目目录 添加包引用 配置和使用SDK 添加appse ...
- 【原创】在 .NET Core 3.1 中使用 Senparc.Weixin.Work 企业微信 SDK —— 发送文本消息
下面在控制台应用里展示一个简单的例子来实现发送文本消息. 本文目录: 创建控制台应用 添加SDK引用 命令行方式 进入项目目录 添加包引用 配置和使用SDK 添加appsettings.json文件 ...
- 通过企业微信API接口发送消息
最近给公司测试组内部开发一个记账小工具,当账目出现问题的时候需要发送消息通知大家,前期主要采用的QQ发送通知消息,但是有一天突然无法连接到QQ服务器,运维的同学建议采用微信的方式对接然后进行告警,所以 ...
- Java企业微信开发_01_接收消息服务器配置
一.准备阶段 需要准备事项: 1.一个能在公网上访问的项目: 见:Java微信公众平台开发_01_本地服务器映射外网 2.一个企业微信账号: 去注册:(https://work.weixin.qq.c ...
- .NET Core企业微信网页授权登录
1.开发前准备 参数获取 corpid 每个企业都拥有唯一的corpid,获取此信息可在管理后台"我的企业"-"企业信息"下查看"企业ID" ...
- Asp.Net Core 企业微信静默授权
企业微信接口文档 1.构造授权网页链接 2.回调获取到 Code 通过code+access_token去请求用户信息 3.获取access_token 调试准备工作 -->内网穿透+域名 推荐 ...
- Java企业微信开发_05_消息推送之被动回复消息
一.本节要点 1.消息的加解密 微信加解密包 下载地址:http://qydev.weixin.qq.com/java.zip ,此包中封装好了AES加解密方法,直接调用方法即可. 其中,解 ...
随机推荐
- SLF4J (The Simple Logging Facade for Java)使用记录
SLF4J (The Simple Logging Facade for Java)使用记录 官网 http://www.slf4j.org/ 参考资料 官方文档 什么是 SLF4J? 官网: The ...
- Sql递归查询,Sqlserver、Oracle、PG、Mysql
递归分两种:一种由父项向下级递归,另一种是由子项向上级递归.下面就这两种情况做个简单的处理. 假设有一个表treeview,包含字段 id,parentid,text 分别代表id,上级id,描述字段 ...
- git设置忽略提交文件
直接在idea进行操作 1.找到想要忽略提交的文件,点击右键,然后如下操作: 2.然后就会发现被忽略的文件名变成了灰色,在项目最下方会生成ignore文件夹 3.文件夹内可以看到我们忽略的文件 4.注 ...
- STL空间分配器源码分析(二)mt_allocator
一.简介 mt allocator 是一种以2的幂次方字节大小为分配单位的空间配置器,支持多线程和单线程.该配置器灵活可调,性能高. 分配器有三个通用组件:一个描述内存池特性的数据,一个包含该池的策略 ...
- ArcGIS使用技巧(七)——批量导出
新手,若有错误还请指正! 在ArcGIS中如何将栅格数据批量导出?用到"复制栅格这个工具",这里我用的例子是:将ArcGIS默认输出的DEM文件夹批量导出为tif格式.(如果是文件 ...
- struts2绕过waf读写文件及另类方式执行命令
之前碰到过好几次Struts2,还都是016,项目.众测都遇到过,每次都只是证明了一下存在,由于waf的存在,没有深入去利用,这里简单的记录下. 0x01 背景 xray或者Struts2漏扫可以扫到 ...
- Python学习笔记: 用pprint更漂亮的打印数据
pprint是一个标准库,它提供了pprint()函数 ,用来打印复杂数据时更漂亮 >>> from pprint import pprint >>> data = ...
- VUE 日期组件(包括年选择)
封装vant 日期组件实现可以选择年份 <template> <div class="yearMonMain"> <div class="l ...
- Swift字符串操作-持续更新-2022
Swift字符串追加 var str = "OC" str.append(" Swfit") print(str) // 输出结果: OC Swift 输出结果 ...
- 分享一个为Linux创建的任务管理器,看起来就像Windows的任务管理器
关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ 链接:https://www.linuxmi.com/sysmontask-linux-tas ...