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. npm 和 Yarn 镜像站配置

    Node.js 作为近年来非常受欢迎的 Web 开发运行环境,由于开发者众多,贡献开源代码的人也很多,所有这些凝结成了 npm 这个世界上最大的软件包仓库,但是受限于 npm 软件包的服务器在国外,国 ...

  2. springboot jar包方式部署

    打好jar包后上传到 linux 执行命令 java -jar /root/vhr-web-0.0.1-SNAPSHOT.jar > /root/log.txt & 1.java -ja ...

  3. 2021.12.06 P2511 [HAOI2008]木棍分割(动态规划)

    2021.12.06 P2511 [HAOI2008]木棍分割(动态规划) https://www.luogu.com.cn/problem/P2511 题意: 有n根木棍, 第i根木棍的长度为 \( ...

  4. 将python脚本打包为exe可执行文件

    技术背景 在很多情况下,编程人员是在Linux环境下完成的编程任务,但是更多的使用人员是在Windows环境下的,比方说,在参考链接1的文章中提到: 那么我们就不得不考虑一个环境转化的问题.pytho ...

  5. 字节跳动构建Data Catalog数据目录系统的实践(上)

    作为数据目录产品,Data Catalog 通过汇总技术和业务元数据,解决大数据生产者组织梳理数据.数据消费者找数和理解数的业务场景,并服务于数据开发和数据治理的产品体系.本文介绍了字节跳动 Data ...

  6. 数据交换格式 JSON

    1. 什么是 JSON 概念 : JSON 的英文全称是 JavaScript ObjEct Notation, 即 "JavaScript 对象表示法" . 简单来讲 : JSO ...

  7. burp通过条件竞争上传文件

    一·何为条件竞争 现代框架更能抵御此类攻击.他们通常不会将文件直接上传到文件系统上的预期目的地.相反,他们采取了预防措施,例如首先上传到临时的沙盒目录并随机命名以避免覆盖现有文件.然后,他们对这个临时 ...

  8. Windows与Linux如何实现相互远程桌面连接?

    今天跟大家一起讨论下,利用Windows自带的远程桌面连接工具,实现远程Linux桌面及在Linux系统中远程Windows桌面 一.Windows远程Linux桌面 1)本次实验以CentOS 7. ...

  9. Docker中级篇,看这篇就对了

    点击上方"开源Linux",选择"设为星标"回复"学习"获取独家整理的学习资料! 姊妹篇: Docker容器网络-基础篇 十分钟看懂Dock ...

  10. BootstrapBlazor实战 Markdown 编辑器使用

    基础工程使用工程: B08. BootstrapBlazor实战 Menu 导航菜单使用 实战BootstrapBlazorMenu Markdown 编辑器使用, 以及整合Freesql orm快速 ...