c#winForm向微信小程序订阅者发送消息
历时三天经过了许多弯路winform向微信小程序订阅者发送消息终于调试成功主要是在openId的获取上浪费了好多时间。将代码记录一下免的将来再同样犯傻。。。。openId获取流程小程序发送userId到winform--winform发送userId到腾讯api获取openId并记录关键点为获得小程序发过来的数据winform需要内置http服务器并有公网IP本人做了公网端口映射用HttpListener接收小程序数据。userId转openId的APIhttps://api.weixin.qq.com/sns/jscode2session?appid{0}secret{1}js_code{2}grant_typeauthorization_codejs_code为提交的userId,appid和secret在小程序后台找到其中secret仅申请或重置时显示一定记下来)获取tokenAPIhttps://api.weixin.qq.com/cgi-bin/token?grant_typeclient_credentialappid{0}secret{1}发送消息API https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token{0};小程序端获取userIdapp.js// 登录wx.login({success: res {if (res.code) {//发起网络请求const app getApp();app.globalData { userId: res.code }}}})获取openId并订阅// 订阅消息subscribeMessage() {const templateId 模板Id小程序后台查看const app getApp();wx.requestSubscribeMessage({tmplIds: [templateId],success: (res) {var appidappid小程序后台查看;var userIdapp.globalData.userId;var openId;var secret小程序后台第一次申请时可查看后面忘记只能重置;wx.request({url: http://公网IP:端口号/, //winform的web服务必须映射到公网IP需要接收小程序数据method:POST,data: {code: userId},success(data){openiddata.data;console.log(openid: openid)},fail(data){//获取失败的处理}});console.log(订阅成功app.globalData.userId, res)if (res[templateId] accept) {wx.showToast({title: 订阅成功app.globalData.userId,icon: success})}},fail: (err) {console.log(订阅失败, err)}})}})C#Winform端使用HttpListener接收小程序发过来的数据做好端口映射界面主程序代码public partial class frmMain : Form { private static string appId 小程序appid小程序后台查杳看; private static string appSecret 小程序后台第一次申请可见; private string session_key ; WeChatMessageService weChatMessageService new WeChatMessageService(appId, appSecret); HttpListener _server null; string openId ,userId; public frmMain() { InitializeComponent(); } private void btnSend_Click(object sender, EventArgs e) { var data new Dictionarystring, DataValue {//根据消息模板的数据结构填数据 [thing2] new DataValue { value 1号设备 }, [time3] new DataValue { value DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss) }, [character_string4] new DataValue { value I类警报 }, [time6] new DataValue { value DateTime.Now.ToString(yyyy-MM-dd HH:mm:ss) }, }; var result weChatMessageService.SendSubscribeMessageAsync( openId: openId, templateId: 模板Id, data: data, page: pages/index/index//详情跳转到小程序的哪个页面 ); txtMessage.Text result.ToString() Environment.NewLine; } private void btnListen_Click(object sender, EventArgs e) { string serverurl string.Format(http://10.50.203.249:{0}/, txtPort.Text); _server new HttpListener(); _server.Prefixes.Add(serverurl); _server.Start(); _server.BeginGetContext(new AsyncCallback(GetContextCallBack), _server); txtMessage.Text serverurl 开始监听...... Environment.NewLine; } private void GetContextCallBack(IAsyncResult ar) { HttpListener listnener ar.AsyncState as HttpListener; HttpListenerContext context listnener.EndGetContext(ar); listnener.BeginGetContext(new AsyncCallback(GetContextCallBack), listnener); try { var request context.Request; var response context.Response; // 设置跨域和响应头 response.AppendHeader(Access-Control-Allow-Origin, *); response.ContentType application/json; charsetUTF-8; if (request.HttpMethod POST) { using (var reader new StreamReader(request.InputStream, Encoding.UTF8)) { string json reader.ReadToEnd(); if (this.InvokeRequired) { this.Invoke(new Action(() { txtMessage.Text $Received POST data: {json} Environment.NewLine; })); } else { txtMessage.Text $Received POST data: {json} Environment.NewLine; } userIdJsonConvert.DeserializeObjectopenIdData(json).code; using (HttpClient client new HttpClient()) { string openIdUrl string.Format(https://api.weixin.qq.com/sns/jscode2session?appid{0}secret{1}js_code{2}grant_typeauthorization_code, appId, appSecret, userId); var content new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, application/json); var resp client.PostAsync(openIdUrl, content).Result; var result resp.Content.ReadAsStringAsync().Result; if (this.InvokeRequired) { this.Invoke(new Action(() { txtMessage.Text $Received POST data: {result} Environment.NewLine; })); } else { txtMessage.Text $Received POST data: {result} Environment.NewLine; } var json1 JsonConvert.DeserializeObjectDictionarystring, string(result); if (json1.ContainsKey(openid) !string.IsNullOrEmpty(json1[openid])) { openId json1[openid]; session_key json1[session_key]; } } // 返回接收到的数据作为响应 /* string responseString JsonConvert.SerializeObject(new { status success, receivedData json });*/ string responseString openId.ToString(); byte[] buffer Encoding.UTF8.GetBytes(responseString); response.ContentLength64 buffer.Length; response.OutputStream.Write(buffer, 0, buffer.Length); } } else { response.StatusCode 405; byte[] buffer Encoding.UTF8.GetBytes({\error\:\Method Not Allowed\}); response.ContentLength64 buffer.Length; response.OutputStream.Write(buffer, 0, buffer.Length); } response.Close(); } catch (Exception ex) { Console.WriteLine($Error: {ex.Message}); } } } public class openIdData { public string code { get; set; } } weChatMessageService类代码 using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading.Tasks; public class WeChatMessageService { private readonly string _appId; private readonly string _appSecret; private readonly string _accessTokenUrl; private readonly string _subscribeMessageUrl; private readonly string _openidUrl; public WeChatMessageService(string appId, string appSecret) { _appId appId; _appSecret appSecret; _accessTokenUrl https://api.weixin.qq.com/cgi-bin/token?grant_typeclient_credentialappid{0}secret{1}; _subscribeMessageUrl https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token{0}; _openidUrl https://api.weixin.qq.com/sns/jscode2session?appid{0}secret{1}js_code{2}grant_typeauthorization_code; } // 获取 access_token建议缓存有效期7200秒 public string GetAccessTokenAsync() { var url string.Format(_accessTokenUrl, _appId, _appSecret); using (var client new HttpClient()) { var response client.GetStringAsync(url).Result; var tokenResult JsonConvert.DeserializeObjectAccessTokenResponse(response); return tokenResult.access_token; } } // 发送订阅消息 public string SendSubscribeMessageAsync(string openId, string templateId, Dictionarystring, DataValue data, string page ) { var accessToken GetAccessTokenAsync(); var url string.Format(_subscribeMessageUrl, accessToken); var request new SubscribeMessageRequest { touser openId, template_id templateId, page page, data data, miniprogram_state formal // 正式版可选developer开发版、trial体验版 }; var json JsonConvert.SerializeObject(request); using (var client new HttpClient()) { var content new StringContent(json, Encoding.UTF8, application/json); var response client.PostAsync(url, content).Result; return response.Content.ReadAsStringAsync().Result;// .Content.ReadAsStringAsync(); } } // 请求模型 public class SubscribeMessageRequest { public string touser { get; set; } public string template_id { get; set; } public string page { get; set; } public Dictionarystring, DataValue data { get; set; } public string miniprogram_state { get; set; } formal; } public class DataValue { public string value { get; set; } public string color { get; set; } #173177; } public class AccessTokenResponse { public string access_token { get; set; } public int expires_in { get; set; } } }