微信开放文档 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.addTemplate.html
至于样式效果取决于模板选择
可能大概也许流程是这样子
我这里是这样新建的,当然也可以使用Visual Studio中的可视化新建。
dotnet new webapi --name AspNetCoreWeChatSubscribeMessage
编辑.csproj
文件。
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.4" />
</ItemGroup>
</Project>
新建WeChat.cs文件,根据上一篇Asp .NetCore 微信小程序授权登录、获取用户信息进行改进。
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
namespace AspNetCoreWeChatSubscribeMessage
{
public class WeChat
{
/// <summary>
/// 小程序 appId
/// </summary>
public string appid {
get; set; }
/// <summary>
/// 小程序 appSecret
/// </summary>
public string secret {
get; set; }
public class Code2SessionResult
{
/// <summary>
/// 用户唯一标识
/// </summary>
public string? openid {
get; set; }
/// <summary>
/// 会话密钥
/// </summary>
public string? session_key {
get; set; }
/// <summary>
/// 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明。
/// </summary>
public string? unionid {
get; set; }
/// <summary>
/// 错误码
/// </summary>
public int errcode {
get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? errmsg {
get; set; }
}
public enum Gender
{
unkown = 0,
man = 1,
woman = 2
}
public class UserInfo
{
public string? openId {
get; set; }
/// <summary>
/// 用户昵称
/// </summary>
public string? nickName {
get; set; }
/// <summary>
/// 用户性别
/// </summary>
public Gender? gender {
get; set; }
/// <summary>
/// 用户所在国家
/// </summary>
public string? country {
get; set; }
/// <summary>
/// 用户所在省份。
/// </summary>
public string? province {
get; set; }
/// <summary>
/// 用户所在城市。
/// </summary>
public string? city {
get; set; }
/// <summary>
/// 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明。
/// </summary>
public string? unionId {
get; set; }
/// <summary>
/// 用户头像图片的 URL。URL 最后一个数值代表正方形头像大小(有 0、46、64、96、132 数值可选,0 代表 640x640 的正方形头像,46 表示 46x46 的正方形头像,剩余数值以此类推。默认132),用户没有头像时该项为空。若用户更换头像,原有头像 URL 将失效。
/// </summary>
public string? avatarUrl {
get; set; }
/// <summary>
///
/// </summary>
public Watermark? watermark {
get; set; }
}
public class Watermark
{
/// <summary>
/// 敏感数据归属 appId,开发者可校验此参数与自身 appId 是否一致
/// </summary>
public string? appid {
get; set; }
/// <summary>
/// 敏感数据获取的时间戳, 开发者可以用于数据时效性校验
/// </summary>
public string? timestamp {
get; set; }
}
/// <summary>
/// 小程序类别
/// </summary>
public class GetAccessTokenResult
{
/// <summary>
/// 获取到的凭证
/// </summary>
public string? access_token {
get; set; }
/// <summary>
/// 凭证有效时间,单位:秒。目前是7200秒之内的值。
/// </summary>
public long expires_in {
get; set; }
/// <summary>
/// 错误码
/// </summary>
public long errcode {
get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? errmsg {
get; set; }
}
public class GetCategoryDataResult
{
/// <summary>
/// 类目id,查询公共库模版时需要
/// </summary>
public long id {
get; set; }
/// <summary>
/// 类目的中文名
/// </summary>
public string? name {
get; set; }
}
public class GetCategoryResult
{
/// <summary>
/// 错误码
/// </summary>
public long errcode {
get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? errmsg {
get; set; }
/// <summary>
/// 类目列表
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<GetCategoryDataResult>? data {
get; set; }
}
public class GetTemplateListResult
{
/// <summary>
/// 错误码
/// </summary>
public long errcode {
get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? errmsg {
get; set; }
/// <summary>
/// 个人模板列表
/// </summary>
public List<GetTemplateListDataResult>? data {
get; set; }
}
public class GetTemplateListDataResult
{
/// <summary>
/// 添加至帐号下的模板 id,发送小程序订阅消息时所需
/// </summary>
public string? priTmplId {
get; set; }
/// <summary>
/// 模版标题
/// </summary>
public string? title {
get; set; }
/// <summary>
/// 模版内容
/// </summary>
public string? content {
get; set; }
/// <summary>
/// 模板内容示例
/// </summary>
public string? example {
get; set; }
/// <summary>
/// 模版类型,2 为一次性订阅,3 为长期订阅
/// </summary>
public long type {
get; set; }
/// <summary>
/// 枚举参数值范围
/// </summary>
public List<KeywordEnumValueResult>? keywordEnumValueList {
get; set; }
}
public class KeywordEnumValueResult
{
/// <summary>
/// 枚举参数的 key
/// </summary>
public string? keywordCode {
get; set; }
/// <summary>
/// 枚举参数值范围列表
/// </summary>
public List<string>? enumValueList {
get; set; }
}
public class GetPubTemplateTitleListDataResult
{
/// <summary>
/// 模版标题 id
/// </summary>
public long tid {
get; set; }
/// <summary>
/// 模版标题
/// </summary>
public string? title {
get; set; }
/// <summary>
/// 模版类型,2 为一次性订阅,3 为长期订阅
/// </summary>
public long type {
get; set; }
/// <summary>
/// 模版所属类目 id
/// </summary>
public long categoryId {
get; set; }
}
public class GetPubTemplateTitleListResult
{
/// <summary>
/// 错误码
/// </summary>
public long errcode {
get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? errmsg {
get; set; }
/// <summary>
/// 模版标题列表总数
/// </summary>
public long count {
get; set; }
/// <summary>
/// 模板标题列表
/// </summary>
public List<GetPubTemplateTitleListDataResult>? data {
get; set; }
}
public class GetPubTemplateKeyWordsByIdDataResult
{
/// <summary>
/// 关键词 id,选用模板时需要
/// </summary>
public long kid {
get; set; }
/// <summary>
/// 关键词内容
/// </summary>
public string? name {
get; set; }
/// <summary>
/// 关键词内容对应的示例
/// </summary>
public string? example {
get; set; }
/// <summary>
/// 参数类型
/// </summary>
public string? rule {
get; set; }
}
public class GetPubTemplateKeyWordsByIdResult
{
/// <summary>
/// 错误码
/// </summary>
public long errCode {
get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? errMsg {
get; set; }
/// <summary>
/// 模版标题列表总数
/// </summary>
public long count {
get; set; }
/// <summary>
/// 关键词列表
/// </summary>
public List<GetPubTemplateKeyWordsByIdDataResult>? data {
get; set; }
}
public class AddTemplateParamter
{
/// <summary>
/// 模板标题 id,可通过接口获取,也可登录小程序后台查看获取
/// </summary>
public string? tid {
get; set; }
/// <summary>
/// 开发者自行组合好的模板关键词列表,关键词顺序可以自由搭配(例如[3, 5, 4] 或[4, 5, 3]),最多支持5个,最少2个关键词组合
/// </summary>
public List<long>? kidList {
get; set; }
/// <summary>
/// 服务场景描述,15个字以内
/// </summary>
public string? sceneDesc {
get; set; }
}
public class AddTemplateResult
{
/// <summary>
/// 错误码
/// 200014 模版 tid 参数错误
/// 200020 关键词列表 kidList 参数错误
/// 200021 场景描述 sceneDesc 参数错误
/// 200011 此账号已被封禁,无法操作
/// 200013 此模版已被封禁,无法选用
/// 200012 个人模版数已达上限,上限25个
/// </summary>
public long errCode {
get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? errMsg {
get; set; }
}
public class DeleteTemplateResult
{
/// <summary>
/// 错误码
/// </summary>
public long errCode {
get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? errMsg {
get; set; }
}
public class DeleteTemplateParamter
{
/// <summary>
/// 要删除的模板id
/// </summary>
public string priTmplId {
get; set; }
public DeleteTemplateParamter(string priTmplId)
{
this.priTmplId = priTmplId;
}
}
public class SubscribeMessageSendParamter
{
/// <summary>
/// 接收者(用户)的 openid
/// </summary>
public string? touser {
get; set; }
/// <summary>
/// 所需下发的订阅模板id
/// </summary>
public string? template_id {
get; set; }
/// <summary>
/// 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index? foo = bar)。该字段不填则模板无跳转。
/// </summary>
public string? page {
get; set; }
/// <summary>
/// 模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } }
/// </summary>
public object? data {
get; set; }
/// <summary>
/// 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
/// </summary>
public string? miniprogram_state {
get; set; }
/// <summary>
/// 进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN
/// </summary>
public string? lang {
get; set; }
}
public class SubscribeMessageSendResult
{
/// <summary>
/// 错误码
/// </summary>
public long errCode {
get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? errMsg {
get; set; }
}
public WeChat(string appid, string secret)
{
this.appid = appid;
this.secret = secret;
}
/// <summary>
/// 登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。更多使用方法详见 小程序登录。
/// https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
/// </summary>
/// <param name="js_code">登录时获取的 code</param>
/// <param name="grant_type">授权类型,此处只需填写 authorization_code</param>
/// <returns></returns>
public async Task<Code2SessionResult?> GetCode2Session(string js_code, string? grant_type = "authorization_code")
{
var result = await Get($"https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={js_code}&grant_type={grant_type}");
return JsonConvert.DeserializeObject<Code2SessionResult>(result);
}
/// <summary>
/// 解密获取用户信息 (不验证签名)
/// </summary>
/// <param name="iv">加密算法的初始向量</param>
/// <param name="encryptedData">包括敏感数据在内的完整用户信息的加密数据</param>
/// <param name="session_key">会话密钥</param>
/// <returns></returns>
public UserInfo? GetUserInfo(string iv, string encryptedData, string session_key)
{
return JsonConvert.DeserializeObject<UserInfo>(AESDecrypt(encryptedData, session_key, iv));
}
/// <summary>
/// 解密获取用户信息 (验证签名)
/// </summary>
/// <param name="iv">加密算法的初始向量</param>
/// <param name="encryptedData">包括敏感数据在内的完整用户信息的加密数据</param>
/// <param name="session_key">会话密钥</param>
/// <param name="rawData">不包括敏感信息的原始数据字符串,用于计算签名</param>
/// <param name="signature">使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息</param>
/// <returns></returns>
public UserInfo? GetUserInfo(string iv, string encryptedData, string session_key, string rawData, string signature)
{
CheckSignature(rawData, session_key, signature);
return GetUserInfo(iv, encryptedData, session_key);
}
/// <summary>
/// 获取小程序全局唯一后台接口调用凭据(access_token)。调用绝大多数后台接口时都需使用 access_token,开发者需要进行妥善保存。 如使用云开发,可通过云调用免维护 access_token 调用。
/// </summary>
/// <param name="grant_type">填写 client_credential</param>
/// <returns></returns>
public async Task<GetAccessTokenResult?> GetAccessToken(string grant_type = "client_credential")
{
var result = await Get($"https://api.weixin.qq.com/cgi-bin/token?grant_type={grant_type}&appid={appid}&secret={secret}");
return JsonConvert.DeserializeObject<GetAccessTokenResult>(result);
}
/// <summary>
/// 获取小程序账号的类目
/// </summary>
/// <param name="access_token">接口调用凭证</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public async Task<GetCategoryResult?> GetCategory(string access_token)
{
var result = await Get($"https://api.weixin.qq.com/wxaapi/newtmpl/getcategory?access_token={access_token}");
return JsonConvert.DeserializeObject<GetCategoryResult>(result);
}
/// <summary>
/// 获取帐号所属类目下的公共模板标题
/// </summary>
/// <param name="access_token">接口调用凭证</param>
/// <param name="ids">类目 id,多个用逗号隔开</param>
/// <param name="start">用于分页,表示从 start 开始。从 0 开始计数。</param>
/// <param name="limit">用于分页,表示拉取 limit 条记录。最大为 30</param>
/// <returns></returns>
public async Task<GetPubTemplateTitleListResult?> GetPubTemplateTitleList(string access_token, string ids, long start = 0, long limit = 30)
{
var result = await Get($"https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatetitles?access_token={access_token}&ids={ids}&start={start}&limit={limit}");
return JsonConvert.DeserializeObject<GetPubTemplateTitleListResult>(result);
}
/// <summary>
/// 获取模板标题下的关键词列表
/// </summary>
/// <param name="access_token">接口调用凭证</param>
/// <param name="tid">模板标题 id,可通过接口获取</param>
/// <returns></returns>
public async Task<GetPubTemplateKeyWordsByIdResult?> GetPubTemplateKeyWordsById(string access_token, string tid)
{
var result = await Get($"https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords?access_token={access_token}&tid={tid}");
return JsonConvert.DeserializeObject<GetPubTemplateKeyWordsByIdResult>(result);
}
/// <summary>
/// 获取当前帐号下的个人模板列表
/// </summary>
/// <param name="access_token">接口调用凭证</param>
/// <returns></returns>
public async Task<GetTemplateListResult?> GetTemplateList(string access_token)
{
var result = await Get($"https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token={access_token}");
return JsonConvert.DeserializeObject<GetTemplateListResult>(result);
}
/// <summary>
/// 组合模板并添加至帐号下的个人模板库
/// </summary>
/// <param name="access_token">接口调用凭证</param>
/// <param name="addTemplateParamter"></param>
/// <returns></returns>
public async Task<AddTemplateResult?> AddTemplate(string access_token, AddTemplateParamter addTemplateParamter)
{
var result = await Post($"https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate?access_token={access_token}", addTemplateParamter);
Console.WriteLine(result);
return JsonConvert.DeserializeObject<AddTemplateResult>(result);
}
/// <summary>
/// 删除帐号下的个人模板
/// </summary>
/// <param name="access_token">接口调用凭证</param>
/// <param name="priTmplId">要删除的模板id</param>
/// <returns></returns>
public async Task<DeleteTemplateResult?> DeleteTemplate(string access_token, string priTmplId)
{
var result = await Post($"https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate?access_token={access_token}", new DeleteTemplateParamter(priTmplId));
return JsonConvert.DeserializeObject<DeleteTemplateResult>(result);
}
/// <summary>
/// 发送订阅消息
/// </summary>
/// <param name="access_token"></param>
/// <param name="subscribeMessageSendParamter"></param>
/// <returns></returns>
public async Task<SubscribeMessageSendResult?> Send(string access_token, SubscribeMessageSendParamter subscribeMessageSendParamter)
{
var result = await Post($"https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={access_token}", subscribeMessageSendParamter);
return JsonConvert.DeserializeObject<SubscribeMessageSendResult>(result);
}
/// <summary>
/// Get 请求
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
static async Task<string> Get(string url)
{
var httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync(url);
return await response.Content.ReadAsStringAsync(); ;
}
/// <summary>
/// Post 请求
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
static async Task<string> Post(string url, object? body = null)
{
var httpClient = new HttpClient();
Console.WriteLine(JsonConvert.SerializeObject(body));
var content = new StringContent(JsonConvert.SerializeObject(body));
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await httpClient.PostAsync(url, content);
return await response.Content.ReadAsStringAsync();
}
/// <summary>
/// 检查签名
/// </summary>
/// <param name="rawData">不包括敏感信息的原始数据字符串,用于计算签名</param>
/// <param name="session_key"></param>
/// <param name="signature">使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息</param>
/// <exception cref="Exception"></exception>
static void CheckSignature(string rawData, string session_key, string signature)
{
Console.WriteLine(SHA1Encryption(rawData + session_key));
Console.WriteLine(signature);
if (SHA1Encryption(rawData + session_key).ToUpper() != signature.ToUpper())
{
throw new Exception("CheckSignature 签名校验失败,数据可能损坏。");
}
}
/// <summary>
/// SHA1 加密,返回大写字符串
/// </summary>
/// <param name="content">需要加密字符串</param>
/// <param name="encode">指定加密编码</param>
/// <returns>返回40位大写字符串</returns>
static string SHA1Encryption(string content, Encoding? encode = null)
{
try
{
if (encode == null) encode = Encoding.UTF8;
SHA1 sha1 = SHA1.Create();
byte[] bytes_in = encode.GetBytes(content);
byte[] bytes_out = sha1.ComputeHash(bytes_in);
sha1.Dispose();
string result = BitConverter.ToString(bytes_out);
result = result.Replace("-", "");
return result;
}
catch (Exception ex)
{
throw new Exception("SHA1Encryption加密出错:" + ex.Message);
}
}
/// <summary>
/// Aes 解密
/// </summary>
/// <param name="encryptedData"></param>
/// <param name="sessionKey"></param>
/// <param name="iv"></param>
/// <returns></returns>
static string AESDecrypt(string encryptedData, string sessionKey, string iv)
{
try
{
var encryptedDataByte = Convert.FromBase64String(encryptedData);
var aes = Aes.Create();
aes.Key = Convert.FromBase64String(sessionKey);
aes.IV = Convert.FromBase64String(iv);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
var transform = aes.CreateDecryptor();
var plainText = transform.TransformFinalBlock(encryptedDataByte, 0, encryptedDataByte.Length);
var result = Encoding.Default.GetString(plainText);
return result;
}
catch (Exception ex)
{
throw new Exception("AESDecrypt解密出错:" + ex.Message);
}
}
}
}
修改Program.cs文件。
using AspNetCoreWeChatSubscribeMessage;
var builder = WebApplication.CreateBuilder(args);
//对接口返回的json对象进行全局的处理
builder.Services.AddControllers().AddNewtonsoftJson(options =>
{
// 忽略循环引用
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
// 为空忽略
options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});
builder.Services.AddSingleton<WeChat>(new WeChat("appid", "secret"));
var app = builder.Build();
//app.UseCors();
app.UseAuthorization();
app.MapControllers();
app.Run();
进入微信公众平台 https://mp.weixin.qq.com/ 。
进入开发设置中获取。
左侧菜单点进去很容易就找到了。
当然在这里面定义模板是最好的选择~
新建SubscribeMessageController.cs文件放在Controllers文件夹中。
using Microsoft.AspNetCore.Mvc;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace AspNetCoreWeChatSubscribeMessage.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class SubscribeMessageController : ControllerBase
{
readonly WeChat _weChat;
static string access_token = "";
public SubscribeMessageController(WeChat weChat)
{
_weChat = weChat;
}
[HttpGet("{code}")]
public async Task<IActionResult> GetOpenId(string code)
{
var res = await _weChat.GetCode2Session(code);
// 注意: 这里是为了方便演示,开发的时候不应该去传给前端。
// 为了数据不被篡改,开发者不应该把 session_key 传到小程序客户端等服务器外的环境。
return new JsonResult(res);
}
[HttpGet]
public async Task<IActionResult> GetAccessToken()
{
var result = await _weChat.GetAccessToken();
// 注意: 这里是为了方便演示,开发的时候不应该去传给前端。
// 建议使用redis,将access_token存储起来
access_token = result?.access_token ?? "";
return new JsonResult(result);
}
[HttpGet]
public async Task<IActionResult> GetCategory()
{
return new JsonResult(await _weChat.GetCategory(access_token));
}
[HttpGet]
public async Task<IActionResult> GetTemplateList()
{
return new JsonResult(await _weChat.GetTemplateList(access_token));
}
[HttpGet]
public async Task<IActionResult> GetPubTemplateTitleList([FromQuery] string ids, [FromQuery] long start)
{
return new JsonResult(await _weChat.GetPubTemplateTitleList(access_token, ids, start));
}
[HttpGet]
public async Task<IActionResult> GetPubTemplateKeyWordsById([FromQuery] string tid)
{
return new JsonResult(await _weChat.GetPubTemplateKeyWordsById(access_token, tid));
}
[HttpPost]
public async Task<IActionResult> AddTemplate([FromBody] WeChat.AddTemplateParamter paramter)
{
return new JsonResult(await _weChat.AddTemplate(access_token, paramter));
}
[HttpDelete]
public async Task<IActionResult> DeleteTemplate([FromQuery] string priTmplId)
{
return new JsonResult(await _weChat.DeleteTemplate(access_token, priTmplId));
}
[HttpPost]
public async Task<IActionResult> Send([FromBody] WeChat.SubscribeMessageSendParamter paramter)
{
return new JsonResult(await _weChat.Send(access_token, paramter));
}
}
}
样式简陋还请见谅(●’◡’●)~
index.wxml
新建n个点击事件,用于触发事件于后端接口或者微信小程序api。
<view bindtap="getOpenId">getOpenId</view>
<view bindtap="getAccessToken">getAccessToken</view>
<view bindtap="getCategory">getCategory</view>
<view bindtap="getTemplateList">getTemplateList</view>
<view bindtap="getPubTemplateTitleList">getPubTemplateTitleList</view>
<view bindtap="getPubTemplateKeyWordsById">getPubTemplateKeyWordsById</view>
<view bindtap="addtemplate">addtemplate</view>
<view bindtap="requestSubscribeMessage">requestSubscribeMessage</view>
<view bindtap="send">send</view>
<view bindtap="deleteTemplate">deleteTemplate</view>
index.ts
Page({
getOpenId() {
wx.login({
success: (res) => {
wx.request({
url: `http://localhost:5000/api/SubscribeMessage/GetOpenId/${
res.code}`,
method: "GET",
success: (res) => {
console.log(res);
}
})
}
})
},
getAccessToken() {
wx.request({
url: `http://localhost:5000/api/SubscribeMessage/GetAccessToken`,
method: "GET",
success: (res) => {
console.log(res);
}
})
},
getCategory() {
wx.request({
url: `http://localhost:5000/api/SubscribeMessage/GetCategory`,
method: "GET",
success: (res) => {
console.log(res);
}
})
},
getTemplateList() {
wx.request({
url: `http://localhost:5000/api/SubscribeMessage/GetTemplateList`,
method: "GET",
success: (res) => {
console.log(res);
}
})
},
getPubTemplateTitleList() {
let ids = '612'
let start = 600;
wx.request({
url: `http://localhost:5000/api/SubscribeMessage/GetPubTemplateTitleList?ids=${
ids}&start=${
start}`,
method: "GET",
success: (res) => {
console.log(res);
}
})
},
getPubTemplateKeyWordsById() {
let tid = '27400'
wx.request({
url: `http://localhost:5000/api/SubscribeMessage/GetPubTemplateKeyWordsById?tid=${
tid}`,
method: "GET",
success: (res) => {
console.log(res);
}
})
},
addtemplate() {
wx.request({
url: `http://localhost:5000/api/SubscribeMessage/AddTemplate`,
method: "POST",
data: {
tid: "27400",
kidList: [1, 3, 2],
sceneDesc: "点赞"
},
success: (res) => {
console.log(res);
}
})
},
requestSubscribeMessage() {
wx.requestSubscribeMessage({
tmplIds: ['lTSwnFx6q6_H3d12xUir9lzhlC5NAI_2PVUmQ8_kaf0'],
success: (res) => {
console.log(res)
}
})
},
send() {
wx.request({
url: `http://localhost:5000/api/SubscribeMessage/Send`,
method: "POST",
data: {
touser: "o9TsK49Nuvub76UvhGw-eEsGCLV4",
template_id: "lTSwnFx6q6_H3d12xUir9lzhlC5NAI_2PVUmQ8_kaf0",
page: "/pages/test/index",
data: {
"thing1": {
"value": "啦啦啦啦"
},
"thing3": {
"value": "林一怂儿"
},
"time2": {
"value": "2022年4月25日"
}
},
miniprogram_state: "developer"
},
success: (res) => {
console.log(res);
}
})
},
deleteTemplate() {
let priTmplId = "lTSwnFx6q6_H3d12xUir9lzhlC5NAI_2PVUmQ8_kaf0";
wx.request({
url: `http://localhost:5000/api/SubscribeMessage/DeleteTemplate?priTmplId=${
priTmplId}`,
method: "DELETE",
success: (res) => {
console.log(res);
}
})
}
})
只是检查一下接口,返回以及订阅消息有没有发送成功,直接看调试器中的Network啦~
操作步骤就是改代码,哈哈哈哈。
其实一般项目中用到的比较多的就是
requestSubscribeMessage
send
记录一下为之后做小程序打一个基础~
文章浏览阅读3.8k次。1、将下载好的萤石js插件,添加到SoringBoot项目中。位置可参考下图所示。(容易出错的地方,在将js插件在html页面引入时,发生路径错误的问题)所以如果对页面中引入js的路径不清楚,可参考下图所示存放路径。2、将ezuikit.js引入到demo-live.html中。(可直接将如下代码复制到你创建的html页面中)<!DOCTYPE html><html lan..._ezuikit 测试的url
文章浏览阅读322次。第二步,在弹出的对话框选择,设备驱动—>PLC—>莫迪康—>ModbusRTU—>COM,根据配置软件选择的协议选期期,这里以此为例,然后点击“下一步”。第四步,把使用虚拟串口打勾(GPRS设备),根据需要选择要生成虚拟口,这里以选择KVCOM1为例,然后点击“下一步”设备ID即Modbus地址(1-255) 使用DTU时,为下485接口上的设备地址。第六步,Modbus的从机地址,与配置软件相同,这里以1为例,点击“下一步“第五步,Modbus的从机地址,与配置软件相同,这里以1为例,点击“下一步“_组态王ua
文章浏览阅读9.4k次,点赞22次,收藏19次。安装npm相当于安装node.js,Node.js已自带npm,安装Node.js时会一起安装,npm的作用就是对Node.js依赖的包进行管理,也可以理解为用来安装/卸载Node.js需要装的东西_npm安装配置
文章浏览阅读748次,点赞21次,收藏26次。大家好,小编来为大家解答以下问题,python基础训练100题,python入门100例题,现在让我们一起来看看吧!宝子们还在新手村练级的时候,不单要吸入基础知识,夯实自己的理论基础,还要去实际操作练练手啊!由于文章篇幅限制,不可能将100道题全部呈现在此除了这些,下面还有我整理好的基础入门学习资料,视频和讲解文案都很齐全,用来入门绝对靠谱,需要的自提。保证100%免费这不,贴心的我爆肝给大家整理了这份今天给大家分享100道Python练习题。大家一定要给我三连啊~
文章浏览阅读1k次。 为了在 Linux ( Ubuntu) 上安装sublime,一般大家都会选择常见的教程或是 sublime 官网教程,然而在国内这种方法可能失效。为此,需要用安装包安装。以下就是使用官网安装包安装的教程。打开 sublime 官网后,点击右上角 download, 或是直接访问点击打开链接,即可看到各个平台上的安装包。选择 Linux 64 位版并下载。下载后,打开终端,进入安装..._ubuntu 安装sumlime text打不开
文章浏览阅读563次,点赞13次,收藏6次。CrossOver24是一款类虚拟机软件,专为macOS和Linux用户设计。它的核心技术是Wine,这是一种在Linux和macOS等非Windows操作系统上运行Windows应用程序的开源软件。通过CrossOver24,用户可以在不购买Windows授权或使用传统虚拟机的情况下,直接在Mac或Linux系统上运行Windows软件和游戏。该软件还提供了丰富的功能,如自动配置、无缝集成和实时传输等,以实现高效的跨平台操作体验。
文章浏览阅读1.7k次。一个用聊天的方式让ChatGPT帮我写的线程安全的环形List_为什么gpt一写list就卡
文章浏览阅读336次。我们在前面的文章里曾写过Web应用中乱码产生的原因和处理方式,旧文回顾:深度揭秘乱码问题背后的原因及解决方式其中我们提到可以通过Filter的方式来设置请求和响应的encoding,来解..._filterconfig selectencoding
文章浏览阅读651次。转自:http://www.jb51.net/article/36480.htmencodeURI和decodeURI是成对来使用的,因为浏览器的地址栏有中文字符的话,可以会出现不可预期的错误,所以可以encodeURI把非英文字符转化为英文编码,decodeURI可以用来把字符还原回来_js encodeur decodeurl
文章浏览阅读1.9w次,点赞6次,收藏3次。前言在日常的Android开发当中,我们肯定要打包apk。但是今天我打包的时候遇到一个很奇怪的问题Android The destination folder does not exist or is not writeable,大意是目标文件夹不存在或不可写。出现问题的原因以及解决办法上面有说报错的中文大意是:目标文件夹不存在或不可写。其实问题就在我们的打包界面当中图中标红的Desti..._the destination folder does not exist or is not writeable
文章浏览阅读94次。一、配置代码编辑区的样式 <1>打开Eclipse,Help —> Install NewSoftware,界面如下: <2>点击add...,按下图所示操作: name:随意填写,Location:http://eclipse-color-th..._ecplise高大上设置
文章浏览阅读2.8k次。一,下载mysql:http://dev.mysql.com/downloads/mysql/; 打开页面之后,在Select Platform:下选择linux Generic,如果没有出现Linux的选项,请换一个浏览器试试。我用的谷歌版本不可以,换一个别的浏览器就行了,如果还是不行,需要换一个翻墙的浏览器。 二,下载完后解压缩并放到安装文件夹下: 1、MySQL-client-5.6.2_linux mysql 安装 mysql-5.6.24-1.linux_glibc2.5.x86_64.rpm-bundle