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. 时间篇之linux系统时间和RTC时间

    一.linux系统下包含两个时间:系统时间(刚启动时读取的是rtc时间)和RTC时间. 一般情况下都会选择芯片上最高精度的定时器作为系统时间的定时基准,以避免在系统运行较长时间后出现大的时间偏移.特点 ...

  2. eclipse项目导入工作空间提示已存在问题

    项目直接放在 workspace 目录下,必须项目名和项目文件夹名相同,主要找的是eclipse 项目文件夹下的 .project 文件中的 <name> ... </name> ...

  3. gin框架使用【3.路由参数】

    GET url: http://127.0.0.1:8080/users/{id} http://127.0.0.1:8080/users/1   对于id值的获取 package main impo ...

  4. 2021.11.02 eleveni的水省选题的记录

    2021.11.02 eleveni的水省选题的记录 因为eleveni比较菜,所以eleveni决定从绿题开始水 --实际上菜菜的eleveni连绿题都不一定能水过/忍不住哭了 [P2217 HAO ...

  5. docker入门_image、container相关命令

    docker入门_image.container相关命令 镜像仓库服务.镜像仓库.镜像相关概念 镜像仓库服务:docker镜像仓库服务.阿里云镜像服务 镜像仓库:docker镜像仓库服务中会有很多仓库 ...

  6. switch 和 if else if else 有什么区别

    1.  一般情况下,它们两个语句可以相互替换 2.  switch..case语句通常处理case为比较确定值的情况,而if...else...语句更加灵活,常用于范围判断(大于.等于某个范围) 3. ...

  7. PyTorch 广播机制

    PyTorch 广播机制 定义 PyTorch的tensor参数可以自动扩展其大小.一般的是小一点的会变大,来满足运算需求. 规则 满足一下情况的tensor是可以广播的. 至少有一个维度 两个ten ...

  8. Halo 开源项目学习(一):项目启动

    项目简介 Halo 是一个优秀的开源博客发布应用,在 GitHub 上广受好评,正好最近在练习写博客,借此记录一下学习 Halo 的过程. 项目下载 从 GitHub 上拉取项目源码,Halo 从 1 ...

  9. 了解磁盘IO的那些事

    了解磁盘IO的那些事 我们作为一名开发,经常耳熟能详的一句话,就是提高程序的性能.对于一个应用程序存在问题的直观体现:页面打开很慢,需要等待.造成这样的问题的主要原因有以下几种:1.网络问题.带宽和网 ...

  10. 弃用!Github 上用了 Git.io 缩址服务的都注意了

    GitHub 是面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名 GitHub.对程序员来说,GitHub 可以说是开源精神之所系.在 GitHub 任何职业程 ...