尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

C#实现微信小程序订阅消息推送

C#实现微信小程序订阅消息推送
📅 发布时间:2026/7/2 12:26:34

一、背景介绍

微信小程序的订阅消息是服务端向用户推送通知的重要能力,广泛应用于订单状态变更、预约提醒、物流进度等场景。

重要提示:微信官方已于2023年10月1日起全面下线了旧的「模板消息」接口,现在只能使用「订阅消息」(subscribeMessage.send)能力,请勿沿用旧接口文档。

订阅消息的核心机制是:用户主动授权一次,开发者可发送一条消息,授权次数与发送次数一一对应。

本文将详细介绍如何使用C#(.NET Core)实现微信小程序订阅消息的推送。

二、准备工作

1. 获取小程序配置信息

登录微信公众平台,在「开发-开发管理」中获取:
AppId:小程序唯一标识
AppSecret:小程序密钥(妥善保管)

2. 配置订阅消息模板

进入「功能-订阅消息」,从公共模板库选择或申请新模板,审核通过后记录模板ID。模板中的参数(如thing1、date2等)需与代码中的data字段对应。

3. 配置服务器域名

在「开发-开发设置-服务器域名」中配置request合法域名,用于后端服务调用微信API。

三、核心流程

小程序端用户点击按钮
↓
wx.requestSubscribeMessage 弹出授权窗
↓
用户同意授权(一次授权=一条消息额度)
↓
服务端调用 subscribeMessage.send
↓
微信服务器向用户推送订阅消息

四、代码实现

1. 配置文件(appsettings.json)

{ "Wechat": { "AppId": "你的小程序AppId", "AppSecret": "你的小程序AppSecret", "TemplateId": "你的订阅消息模板ID", "AccessTokenUrl": "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", "SendMessageUrl": "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={0}" } }

2. 获取AccessToken

AccessToken有效期7200秒(2小时),必须缓存并定时刷新,避免频繁请求。

using System.Net.Http; using System.Text.Json; using Microsoft.Extensions.Options; public class WechatTokenService { private readonly HttpClient _httpClient; private readonly IOptions<WechatOptions> _options; private string _cachedToken; private DateTime _tokenExpireTime; public WechatTokenService(HttpClient httpClient, IOptions<WechatOptions> options) { _httpClient = httpClient; _options = options; } public async Task<string> GetAccessTokenAsync() { // 检查缓存是否有效(提前5分钟刷新) if (!string.IsNullOrEmpty(_cachedToken) && DateTime.Now < _tokenExpireTime) { return _cachedToken; } string url = string.Format(_options.Value.AccessTokenUrl, _options.Value.AppId, _options.Value.AppSecret); var response = await _httpClient.GetAsync(url); var json = await response.Content.ReadAsStringAsync(); using var doc = JsonDocument.Parse(json); _cachedToken = doc.RootElement.GetProperty("access_token").GetString(); int expiresIn = doc.RootElement.GetProperty("expires_in").GetInt32(); _tokenExpireTime = DateTime.Now.AddSeconds(expiresIn - 300); // 提前5分钟刷新 return _cachedToken; } }

3. 发送订阅消息

public class SubscribeMessageService { private readonly HttpClient _httpClient; private readonly WechatTokenService _tokenService; private readonly IOptions<WechatOptions> _options; public SubscribeMessageService(HttpClient httpClient, WechatTokenService tokenService, IOptions<WechatOptions> options) { _httpClient = httpClient; _tokenService = tokenService; _options = options; } /// <summary> /// 发送订阅消息 /// </summary> /// <param name="openId">用户的OpenId</param> /// <param name="page">点击消息跳转的页面路径</param> /// <param name="data">模板数据,key为模板字段名</param> public async Task<SendResult> SendSubscribeMessageAsync( string openId, string page, Dictionary<string, string> data) { var token = await _tokenService.GetAccessTokenAsync(); var url = string.Format(_options.Value.SendMessageUrl, token); // 构造模板数据 var msgData = new Dictionary<string, object>(); foreach (var item in data) { msgData[item.Key] = new { value = item.Value }; } var requestBody = new { touser = openId, template_id = _options.Value.TemplateId, page = page, data = msgData, miniprogram_state = "formal" // 正式版 }; var json = JsonSerializer.Serialize(requestBody); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await _httpClient.PostAsync(url, content); var resultJson = await response.Content.ReadAsStringAsync(); using var doc = JsonDocument.Parse(resultJson); var errcode = doc.RootElement.GetProperty("errcode").GetInt32(); var errmsg = doc.RootElement.GetProperty("errmsg").GetString(); return new SendResult { Success = errcode == 0, ErrCode = errcode, ErrMsg = errmsg }; } } public class SendResult { public bool Success { get; set; } public int ErrCode { get; set; } public string ErrMsg { get; set; } } public class WechatOptions { public string AppId { get; set; } public string AppSecret { get; set; } public string TemplateId { get; set; } public string AccessTokenUrl { get; set; } public string SendMessageUrl { get; set; } }

4. 服务注册(Program.cs / Startup.cs)

builder.Services.Configure<WechatOptions>(builder.Configuration.GetSection("Wechat")); builder.Services.AddHttpClient(); builder.Services.AddScoped<WechatTokenService>(); builder.Services.AddScoped<SubscribeMessageService>();

5. 调用示例(Controller)

[ApiController] [Route("api/[controller]")] public class MessageController : ControllerBase { private readonly SubscribeMessageService _msgService; public MessageController(SubscribeMessageService msgService) { _msgService = msgService; } [HttpPost("send")] public async Task<IActionResult> Send([FromBody] SendRequest request) { var data = new Dictionary<string, string> { ["thing1"] = "您的订单已发货", // 对应模板中的thing1 ["time2"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm"), // 对应time2 ["thing3"] = "请注意查收" // 对应thing3 }; var result = await _msgService.SendSubscribeMessageAsync( request.OpenId, "pages/order/detail?id=123", data ); if (result.Success) { return Ok(new { code = 0, msg = "发送成功" }); } // 43101表示用户未授权或拒绝授权 if (result.ErrCode == 43101) { return BadRequest(new { code = 43101, msg = "用户未授权订阅" }); } return BadRequest(result); } } public class SendRequest { public string OpenId { get; set; } }

五、小程序端代码

前端需要在用户的点击事件中调用wx.requestSubscribeMessage拉起授权弹窗:

// 页面js Page({ onSubscribe() { wx.requestSubscribeMessage({ tmplIds: ['你的模板ID'], // 最多3个 success(res) { // res[templateId] 可能为 'accept'、'reject'、'ban'、'filter' if (res['你的模板ID'] === 'accept') { // 用户同意,可调用后端接口发送消息 wx.request({ url: 'https://你的域名/api/message/send', method: 'POST', data: { openId: '用户的openid' } }); } }, fail(err) { console.error('订阅失败', err); } }); } });

注意:wx.requestSubscribeMessage必须在用户的点击事件(如bindtap)中调用,不能放在onLoad或onShow中。

六、常见错误码

错误码含义解决方案
0成功-
40001access_token无效重新获取token
42001access_token过期刷新token后重试
43101用户未授权订阅引导用户重新订阅
20037模板参数不合法检查字段类型和字数限制

七、注意事项

  1. 一次性订阅 vs 长期订阅:大部分小程序使用一次性订阅,用户每次授权发一条;长期订阅仅对特定类目(医疗、民生、交通等)开放。

  2. 用户勾选"总是保持选择"后,弹窗不再出现,但订阅状态会保持,代码中直接调用发送接口即可。

  3. 发送上限:开通支付能力的小程序每日3千万条,未开通的1千万条。

  4. 推荐使用SDK:社区有成熟的C# SDK,如Senparc.Weixin.WxOpen、DH.SKIT.FlurlHttpClient.Wechat.Api,封装了订阅消息等微信API,可减少重复造轮子。

八、总结

微信小程序订阅消息的核心是用户主动授权 + 服务端按授权发送。本文通过配置管理、Token缓存、消息发送、前端授权等环节,完整展示了C#服务端的实现方案。关键在于:

  • 模板ID必须与微信公众平台配置一致

  • AccessToken必须缓存刷新

  • 用户未授权(43101)需引导重新订阅

接入过程中建议优先使用成熟的微信SDK,可大幅提升开发效率。

相关新闻

  • Docker - 04 - 连接postgres容器并迁移
  • LP5812与MKV58实现RGB灯光控制方案详解
  • Display Driver Uninstaller:彻底解决显卡驱动问题的专业工具

最新新闻

  • ICM-42605与PIC18LF4515实现运动追踪系统设计
  • 2026海南省黄金回收白银回收铂金回收旧料回收怎么选?五家高实价铂金白银线下门店测评清单 + 联系方式
  • PIC18F86J16实现DC-DC降压电源设计与优化
  • 5分钟掌握B站视频转换技巧:m4s-converter完全指南
  • DroidRun:基于AI视觉大模型的Android自动化测试与RPA实践
  • hAL-TIM

日新闻

  • Python Playwright录制功能:从零到一构建自动化测试脚本
  • 如何用开源工具永久保存你心爱的小说:novel-downloader全攻略
  • In-Context Learning不是教知识,而是模式对齐:从5个示例到100个工业级样本的真相

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号