.netcore 3.1 C# 微信小程序发送订阅消息
一、appsettings.json定义小程序配置信息
- "WX": {
- "AppId": "wx88822730803edd44",
- "AppSecret": "75b269042e8b5026e6ed14aa24ba9353",
- "Templates": {
- "Audit": {
- "TemplateId": "aBaIjTsPBluYtj2tzotzpowsDDBGLhXQkwrScupnQsM",
- "PageUrl": "/pages/index/formAudit?formId={0}&tableId={1}",
- "MiniprogramState": "developer",
- "Lang": "zh_TW",
- "Data": {
- "Title": "thing6",
- "Content": "thing19",
- "Date": "date9"
- }
- }
- },
- "SignatureToken": "aaaaaa",
- "MessageSendUrl": "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={0}",
- "AccessTokenUrl": "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}"
- }
二、编写通用类加载配置
- using System;
- using System.Text;
- using System.Security.Cryptography;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.Configuration.Json;
- namespace WXERP.Services
- {
- /// <summary>
- /// 项目公有静态类
- /// </summary>
- public class Common
- {
- /// <summary>
- /// 獲取根目錄
- /// </summary>
- public static string AppRoot => Environment.CurrentDirectory;// AppContext.BaseDirectory;
- /// <summary>
- /// 獲取項目配置
- /// </summary>
- public static IConfiguration Configuration { get; set; }
- /// <summary>
- /// 加載項目配置
- /// </summary>
- static Common()
- {
- Configuration = new ConfigurationBuilder()
- .Add(new JsonConfigurationSource
- {
- Path = "appsettings.json",
- ReloadOnChange = true //当appsettings.json被修改时重新加载
- })
- .Build();
- }
- /// <summary>
- /// SHA1加密
- /// </summary>
- /// <param name="content">需要加密的字符串</param>
- /// <returns>返回40位大寫字符串</returns>
- public static string SHA1(string content)
- {
- try
- {
- SHA1 sha1 = new SHA1CryptoServiceProvider();
- byte[] bytes_in = Encoding.UTF8.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("Error in SHA1: " + ex.Message);
- }
- }
- }
- }
三、编写HttpHelper请求类
- using System;
- using System.Text;
- using System.Net.Http;
- using System.Net.Http.Headers;
- using System.Threading.Tasks;
- using System.Collections.Generic;
- namespace WXERP.Services
- {
- /// <summary>
- /// HTTP請求輔助類
- /// </summary>
- public class HttpHelper
- {
- /// <summary>
- /// post同步請求
- /// </summary>
- /// <param name="url">地址</param>
- /// <param name="postData">數據</param>
- /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
- /// <param name="headers">請求頭</param>
- /// <returns></returns>
- public static string HttpPost(string url, string postData = null, string contentType = null, Dictionary<string, string> headers = null)
- {
- using HttpClient client = new HttpClient();
- if (headers != null)
- {
- foreach (var header in headers)
- client.DefaultRequestHeaders.Add(header.Key, header.Value);
- }
- postData ??= "";
- using HttpContent httpContent = new StringContent(postData, Encoding.UTF8);
- if (contentType != null)
- httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
- HttpResponseMessage response = client.PostAsync(url, httpContent).Result;
- return response.Content.ReadAsStringAsync().Result;
- }
- /// <summary>
- /// post異步請求
- /// </summary>
- /// <param name="url">地址</param>
- /// <param name="postData">數據</param>
- /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
- /// <param name="timeOut">請求超時時間</param>
- /// <param name="headers">請求頭</param>
- /// <returns></returns>
- public static async Task<string> HttpPostAsync(string url, string postData = null, string contentType = null, int timeOut = 30, Dictionary<string, string> headers = null)
- {
- using HttpClient client = new HttpClient();
- client.Timeout = new TimeSpan(0, 0, timeOut);
- if (headers != null)
- {
- foreach (var header in headers)
- client.DefaultRequestHeaders.Add(header.Key, header.Value);
- }
- postData ??= "";
- using HttpContent httpContent = new StringContent(postData, Encoding.UTF8);
- if (contentType != null)
- httpContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);
- HttpResponseMessage response = await client.PostAsync(url, httpContent);
- return await response.Content.ReadAsStringAsync();
- }
- /// <summary>
- /// get同步請求
- /// </summary>
- /// <param name="url">地址</param>
- /// <param name="headers">請求頭</param>
- /// <returns></returns>
- public static string HttpGet(string url, Dictionary<string, string> headers = null)
- {
- using HttpClient client = new HttpClient();
- if (headers != null)
- {
- foreach (var header in headers)
- client.DefaultRequestHeaders.Add(header.Key, header.Value);
- }
- HttpResponseMessage response = client.GetAsync(url).Result;
- return response.Content.ReadAsStringAsync().Result;
- }
- /// <summary>
- /// get異步請求
- /// </summary>
- /// <param name="url"></param>
- /// <param name="headers"></param>
- /// <returns></returns>
- public static async Task<string> HttpGetAsync(string url, Dictionary<string, string> headers = null)
- {
- using HttpClient client = new HttpClient();
- if (headers != null)
- {
- foreach (var header in headers)
- client.DefaultRequestHeaders.Add(header.Key, header.Value);
- }
- HttpResponseMessage response = await client.GetAsync(url);
- return await response.Content.ReadAsStringAsync();
- }
- }
- }
四、在sqlserver下存储并获取openid,这个主要是因为提交消息并不是在微信小程序端,如果是在微信小程序上发起订阅消息,可以忽略这个步骤
- // 创建数据库表
- create table TBSF_Conmmunicate_WXUser
- (
- ID int identity(1,1) primary key,
- Staff_ID varchar(10),
- OpenId varchar(50),
- SessionKey varchar(50),
- UnionId varchar(50),
- IsValid bit,
- )
- // SqlHelper数据库辅助类来自于CommunicationOperateDBUtility,可以自己编写
- using System.Data;
- using System.Text;
- using CommunicationOperateDBUtility;
- namespace WXERP.Services.CommunicationOperateDAL
- {
- /// <summary>
- /// 微信信息
- /// </summary>
- public class WXInforDeal
- {
- private SqlHelper sqlHelper = null;
- /// <summary>
- /// 初始化數據庫輔助對象
- /// </summary>
- /// <param name="con"></param>
- public WXInforDeal(object con)
- {
- sqlHelper = new SqlHelper(con);
- }
- /// <summary>
- /// 獲取微信登陸用戶信息
- /// </summary>
- /// <param name="staffIdList">工號</param>
- /// <returns></returns>
- public DataSet GetLoginUserInfo(string staffIdList)
- {
- DataSet ds = new DataSet();
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.Append(" SELECT distinct OpenId FROM ");
- stringBuilder.Append(" TBSF_Conmmunicate_WXUser WHERE Staff_ID IN (");
- stringBuilder.Append(staffIdList);
- stringBuilder.Append(")");
- string strSql = stringBuilder.ToString();
- sqlHelper.DBRunSql(strSql, ref ds);
- return ds;
- }
- }
- }
五、编写订阅消息基类模型
- using System;
- using System.Data;
- using Newtonsoft.Json;
- using System.Collections.Generic;
- using WXERP.Services.CommunicationOperateDAL;
- namespace WXERP.Models
- {
- /// <summary>
- /// 訂閲消息請求模型
- /// </summary>
- public class SubscribeMessageModel
- {
- /// <summary>
- /// 初始化審核訂閲消息
- /// </summary>
- /// <param name="dbTransOrCnn">數據庫事務</param>
- /// <param name="nextAuditStaffId">下一個審核通知用戶工號</param>
- public SubscribeMessageModel(object dbTransOrCnn, string nextAuditStaffId)
- {
- WXInforDeal wxInfoDeal = new WXInforDeal(dbTransOrCnn);
- DataSet wxUserInfo = wxInfoDeal.GetLoginUserInfo(nextAuditStaffId);
- if (wxUserInfo != null && wxUserInfo.Tables.Count > 0 && wxUserInfo.Tables[0].Rows.Count > 0)
- {
- Touser = wxUserInfo.Tables[0].Rows[0]["OpenId"].ToString();
- }
- }
- /// <summary>
- /// 消息接收者的openid
- /// </summary>
- [JsonProperty("touser")]
- public string Touser { get; set; }
- /// <summary>
- /// 消息模板ID
- /// </summary>
- [JsonProperty("template_id")]
- public string TemplateId { get; set; }
- /// <summary>
- /// 點擊模板卡片后的跳轉頁面,僅限本小程序内的頁面,支持帶參數(示例index?foo=bar),該字段不填則不跳轉
- /// </summary>
- [JsonProperty("page")]
- public string Page { get; set; }
- /// <summary>
- /// 跳轉小程序類型:developer開發版、trial體驗版、formal正式版,默认为正式版
- /// </summary>
- [JsonProperty("miniprogram_state")]
- public string MiniprogramState { get; set; }
- /// <summary>
- /// 進入小程序查看的語言類型,支持zh_CN(簡體中文)、en_US(英文)、zh_HK(繁體中文)、zh_TW(繁體中文),默認為zh_CN
- /// </summary>
- [JsonProperty("lang")]
- public string Lang { get; set; }
- /// <summary>
- /// 模板内容
- /// </summary>
- [JsonProperty("data")]
- public Dictionary<string, DataValue> Data { get; set; }
- }
- /// <summary>
- /// 模板内容關鍵字
- /// </summary>
- public class DataValue
- {
- /// <summary>
- /// 訂閲消息參數值
- /// </summary>
- [JsonProperty("value")]
- public string Value { get; set; }
- }
- /// <summary>
- /// 小程序訂閲消息響應模型
- /// </summary>
- public class SubscribeMsgResponseModel
- {
- /// <summary>
- /// 錯誤代碼
- /// </summary>
- public int Errcode { get; set; }
- /// <summary>
- /// 錯誤信息
- /// </summary>
- public string Errmsg { get; set; }
- }
- /// <summary>
- /// 小程序獲取token響應模型
- /// </summary>
- public class AccessTokenResponseModel
- {
- /// <summary>
- /// 小程序訪問token
- /// </summary>
- public string Access_token { get; set; }
- /// <summary>
- /// Token過期時間,單位秒
- /// </summary>
- public int Expires_id { get; set; }
- /// <summary>
- /// Token創建時間
- /// </summary>
- public DateTime Create_time { get; set; }
- /// <summary>
- /// 刷新以後的Token
- /// </summary>
- public string Refresh_token { get; set; }
- /// <summary>
- /// 小程序用戶唯一標識,如果用戶未關注公衆號,訪問公衆號網頁也會產生
- /// </summary>
- public string Openid { get; set; }
- /// <summary>
- /// 用戶授權的作用域,使用逗號分隔
- /// </summary>
- public string Scope { get; set; }
- }
- }
六、实现消息订阅基类,下面的SetTemplateData方法根据自己的情况设置需要推送消息的内容,如果以后有其他订阅消息模板,新增一个类实现SubscribeMessageModel
- using System;
- using System.Collections.Generic;
- using Newtonsoft.Json;
- using BestSoft.Common.Resources;
- using BSFWorkFlow.Common.GeneralUtility;
- using WXERP.Models;
- namespace WXERP.Services.SubscribeMessage
- {
- /// <summary>
- /// 審核訂閲消息
- /// </summary>
- public class AuditSubscribeMessage : SubscribeMessageModel
- {
- private string page;
- private string lang;
- private Dictionary<string, DataValue> data;
- /// <summary>
- /// 設置小程序OpenId
- /// </summary>
- /// <param name="dbTransOrCnn">數據庫事務</param>
- /// <param name="nextAuditStaffId">下一個審核通知用戶工號</param>
- public AuditSubscribeMessage(object dbTransOrCnn, string nextAuditStaffId)
- : base(dbTransOrCnn, nextAuditStaffId)
- {
- }
- /// <summary>
- /// 消息模板ID
- /// </summary>
- [JsonProperty("template_id")]
- public new string TemplateId => Common.Configuration["WX:Templates:Audit:TemplateId"];
- /// <summary>
- /// 設置小程序訂閲消息跳轉頁面
- /// </summary>
- /// <param name="formId"></param>
- /// <param name="tableId"></param>
- public void SetPageUrl(string formId, string tableId)
- {
- Page = string.Format(Common.Configuration["WX:Templates:Audit:PageUrl"],
- formId, tableId);
- }
- /// <summary>
- /// 點擊模板卡片后的跳轉頁面
- /// </summary>
- [JsonProperty("page")]
- public new string Page
- {
- get
- {
- return page;
- }
- set
- {
- page = value;
- return;
- }
- }
- /// <summary>
- /// 跳轉小程序類型
- /// </summary>
- [JsonProperty("miniprogram_state")]
- public new string MiniprogramState => Common.Configuration["WX:Templates:Audit:MiniprogramState"];
- /// <summary>
- /// 進入小程序查看的語言類型,支持zh_CN(簡體中文)、en_US(英文)、zh_HK(繁體中文)、zh_TW(繁體中文),默認為zh_CN
- /// </summary>
- [JsonProperty("lang")]
- public new string Lang
- {
- get
- {
- lang = Common.Configuration["WX:Templates:Audit:Lang"];
- if (!string.IsNullOrEmpty(MyHttpContext.Current.Request.Headers["bsLanKind"]))
- lang = MyHttpContext.Current.Request.Headers["bsLanKind"];
- return lang;
- }
- set
- {
- lang = value;
- return;
- }
- }
- /// <summary>
- /// 設置審核訂閲消息數據
- /// </summary>
- /// <param name="operation">審核動作:通過、否決、作廢、退回</param>
- /// <param name="itemAuditStatus">審核狀態:1代表審核完畢</param>
- /// <param name="currentWorkflowName">審核標題</param>
- public void SetTemplateData(WFAuditOperation operation, WFAuditItemStatus itemAuditStatus, string currentWorkflowName)
- {
- string tip_msg = "";
- switch (operation)
- {
- case WFAuditOperation.AuditPassAndAgree:
- if (itemAuditStatus == WFAuditItemStatus.SuccessfulToFinishAllAudits)
- tip_msg = GeneralFunction.ReplaceNullOrEmptyStr(SourcesWarehouse.GetStringSources("WFEngine_FinishAuditTip"), "您的單據已審核完成!");
- else
- tip_msg = GeneralFunction.ReplaceNullOrEmptyStr(SourcesWarehouse.GetStringSources("WFEngine_AuditAgreeTip"), "您有一筆新單據待審核!");
- break;
- case WFAuditOperation.AuditPassButDegree:
- tip_msg = GeneralFunction.ReplaceNullOrEmptyStr(SourcesWarehouse.GetStringSources("WFEngine_AuditDegreeTip"), "您提交的單據等待異議!");
- break;
- case WFAuditOperation.AuditAbort:
- tip_msg = GeneralFunction.ReplaceNullOrEmptyStr(SourcesWarehouse.GetStringSources("WFEngine_AuditAbortTip"), "您提交的單據已被作廢!");
- break;
- case WFAuditOperation.AuditBack:
- tip_msg = GeneralFunction.ReplaceNullOrEmptyStr(SourcesWarehouse.GetStringSources("WFEngine_AuditBackTip"), "您提交的單據已被退回修正!");
- break;
- }
- string title = Common.Configuration["WX:Templates:Audit:Data:Title"];
- string content = Common.Configuration["WX:Templates:Audit:Data:Content"];
- string date = Common.Configuration["WX:Templates:Audit:Data:Date"];
- Dictionary<string, DataValue> data = new Dictionary<string, DataValue>()
- {
- {title, new DataValue{ Value= currentWorkflowName }},
- {content, new DataValue{ Value= tip_msg }},
- {date, new DataValue{ Value= DateTime.Now.ToShortDateString() }}
- };
- Data = data;
- }
- /// <summary>
- /// 審核訂閲消息數據
- /// </summary>
- [JsonProperty("data")]
- public new Dictionary<string, DataValue> Data
- {
- get
- {
- return data;
- }
- set
- {
- data = value;
- return;
- }
- }
- }
- }
七、编写发送订阅消息,消息推送配置签名认证
- using System;
- using System.Threading.Tasks;
- using System.Collections.Generic;
- using Newtonsoft.Json;
- using WXERP.Models;
- namespace WXERP.Services
- {
- /// <summary>
- /// 系統消息上下文
- /// </summary>
- public class MessageContext
- {
- /// <summary>
- /// 獲取AccessToken的全局鎖
- /// </summary>
- private readonly static object SyncLock = new object();
- private static Dictionary<string, AccessTokenResponseModel> tokenCache = new Dictionary<string, AccessTokenResponseModel>();
- /// <summary>
- /// 發送訂閲消息
- /// </summary>
- /// <param name="msg">消息内容</param>
- /// <param name="errMsg">可能由於獲取的token錯誤</param>
- /// <returns></returns>
- public static bool SendSubscribeMsg(SubscribeMessageModel msg, out string errMsg)
- {
- errMsg = "";
- try
- {
- string token = GetAccessToken();
- if (token.Length < 20)
- {
- errMsg = "Failed to send subscription message, Access token error!";
- return false;
- }
- string url = string.Format(Common.Configuration["WX:MessageSendUrl"], token);
- string requestJson = JsonConvert.SerializeObject(msg);
- string responseJson = HttpHelper.HttpPost(url, requestJson, "application/json", null);
- var msgResponse = JsonConvert.DeserializeObject<SubscribeMsgResponseModel>(responseJson);
- if (msgResponse.Errcode != 0)
- {
- errMsg = string.Format("Failed to send subscription message, {0}", msgResponse.Errmsg);
- return false;
- }
- }
- catch (Exception exp)
- {
- throw new Exception("SendSubscribeMsg: " + exp.Message);
- }
- return true;
- }
- /// <summary>
- /// 獲取小程序訪問token
- /// </summary>
- /// <returns></returns>
- private static string GetAccessToken()
- {
- lock (SyncLock)
- {
- string appid = Common.Configuration["WX:AppId"];
- string appsecret = Common.Configuration["WX:AppSecret"];
- string accessTokenUrl = string.Format(Common.Configuration["WX:AccessTokenUrl"], appid, appsecret);
- AccessTokenResponseModel result = null;
- if (tokenCache.ContainsKey(appid))
- result = tokenCache[appid];
- if (result == null)
- {
- string responseJson = HttpHelper.HttpGet(accessTokenUrl, null);
- result = JsonConvert.DeserializeObject<AccessTokenResponseModel>(responseJson);
- result.Create_time = DateTime.Now;
- tokenCache.Add(appid, result);
- }
- else if (DateTime.Compare(result.Create_time.AddSeconds(result.Expires_id), DateTime.Now) < 1)
- {
- string responseJson = HttpHelper.HttpGet(accessTokenUrl, null);
- result = JsonConvert.DeserializeObject<AccessTokenResponseModel>(responseJson);
- result.Create_time = DateTime.Now;
- tokenCache[appid] = result;
- }
- return result.Access_token;
- }
- }
- /// <summary>
- /// 驗證消息來自於微信服務器
- /// </summary>
- /// <param name="signature">微信加密簽名,signature結合了開發者填寫的token、timestamp、nonce</param>
- /// <param name="timestamp">時間戳</param>
- /// <param name="nonce">隨機數</param>
- /// <returns></returns>
- public async Task<bool> CheckSignature(string signature, string timestamp, string nonce)
- {
- string token = Common.Configuration["WX:SignatureToken"];
- string[] tmpArr = { token, timestamp, nonce };
- Array.Sort(tmpArr);
- string tmpStr = string.Join("", tmpArr);
- tmpStr = Common.SHA1(tmpStr);
- if (!tmpStr.Equals(signature, StringComparison.OrdinalIgnoreCase))
- return false;
- await Task.CompletedTask;
- return true;
- }
- }
- }
八、编写消息推送配置签名认证控制器
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using WXERP.Services;
- namespace WXERP.Controllers
- {
- /// <summary>
- /// 消息控制器
- /// </summary>
- [Route("api/[controller]")]
- [ApiController]
- public class MessageController : ControllerBase
- {
- private readonly MessageContext _context;
- /// <summary>
- /// 初始化消息
- /// </summary>
- public MessageController()
- {
- _context = new MessageContext();
- }
- /// <summary>微信消息</summary>
- /// <remarks>驗證消息來自於微信服務器</remarks>
- /// <param name="signature">微信加密簽名,signature結合了開發者填寫的token、timestamp、nonce</param>
- /// <param name="timestamp">時間戳</param>
- /// <param name="nonce">隨機數</param>
- /// <param name="echostr">隨機字符串</param>
- /// <returns></returns>
- [HttpGet("checkSignature")]
- [AllowAnonymous]
- public async void CheckSignature(string signature,string timestamp,string nonce,string echostr)
- {
- bool result = await _context.CheckSignature(signature, timestamp, nonce);
- if (result)
- {
- HttpContext.Response.ContentType = "text/plain; charset=utf-8";
- await HttpContext.Response.WriteAsync(echostr);
- }
- else
- {
- HttpContext.Response.StatusCode = 409;
- HttpContext.Response.ContentType = "text/plain; charset=utf-8";
- await HttpContext.Response.WriteAsync("error");
- }
- }
- }
- }
九、调用小程序订阅消息,需要自己实现其他逻辑
- //@iFormSaveDAL.GetTran 数据库链接事务,如果发送消息失败,应该回滚提交的表单数据
- //@wFControl.NextAuditNotifyStaffIDStr 下一个审核用户的工号
- //@auditPageData.FormID 表单编号
- //@auditPageData.MainRecordID 表单数据ID
- //@operationByCode 一个枚举类型,前端传递的:审核通过、作废、退回等
- //@wFControl.ItemAuditStatus 一个枚举类型,如果全部审核完毕为1,否则为0
- //@wFControl.CurrentWorkflowName 当前流程的名称,例如:请假单审核
- //@SaveAfterInfo 全局字符变量,用于保存结果信息
- AuditSubscribeMessage auditMsg = new AuditSubscribeMessage(iFormSaveDAL.GetTran, wFControl.NextAuditNotifyStaffIDStr);
- auditMsg.SetPageUrl(auditPageData.FormID, auditPageData.MainRecordID);
- auditMsg.SetTemplateData(operationByCode, wFControl.ItemAuditStatus, wFControl.CurrentWorkflowName);
- if (!string.IsNullOrEmpty(auditMsg.Touser))
- {
- if (!MessageContext.SendSubscribeMsg(auditMsg, out messageStr))
- {
- SaveAfterInfo = messageStr;
- return false;
- }
- }
有不懂或需要改正的欢迎留言!
.netcore 3.1 C# 微信小程序发送订阅消息的更多相关文章
- 微信小程序发送订阅消息(之前是模板消息)
之前的模板消息已经废弃,现在改为订阅消息,订阅消息发布前,需要用户确认后才能接收订阅消息. 小程序端 index.wxml <button bindtap="send"> ...
- 微信小程序发送模板消息
微信小程序发送模板消息 标签(空格分隔): php 看小程序文档 [模板消息文档总览]:https://developers.weixin.qq.com/miniprogram/dev/framewo ...
- 微信小程序 发送模版消息
微信小程序开发之发送模板消息 1,小程序wxml页面form表单添加 report-submit="true" <form bindsubmit="sub" ...
- 微信小程序 发送模板消息的功能实现
背景 - 小程序开发的过程中,绝大多数会满足微信支付 - 那么,作为友好交互的体现,自然就会考虑到支付后的消息通知咯 - 所以,我的小程序项目也要求完成这个效果,so.分享一下自己的实现步骤,以方便道 ...
- 微信小程序-发送模板消息
1 添加一个小程序的消息模板,获取到模板id,存储到数据库中,方便以后修改调用 2. https://developers.weixin.qq.com/miniprogram/dev/api-back ...
- 微信小程序-发送模板消息(C#)
步骤一:获取模板ID 有两个方法可以获取模版ID 通过模版消息管理接口获取模版ID 在微信公众平台手动配置获取模版ID 步骤二:页面的 <form/> 组件,属性report-submit ...
- Q:微信小程序一次性订阅消息(前台收集)
说明:官方文档(https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.ht ...
- 微信小程序发送短信验证码完整实例
微信小程序注册完整实例,发送短信验证码,带60秒倒计时功能,无需服务器端.效果图: 代码: index.wxml <!--index.wxml--> <view class=&quo ...
- 微信小程序发送ajax
微信小程序通过 wx.request发送ajax请求 1. GET wx.request({ url: app.globalData.pubSiteUrl + 'user-information/ge ...
随机推荐
- Sqlalchemy 事件监听与初始化
sqlalchemy不仅仅能自动创建数据库,更提供了其他更强大的功能,今天要介绍的就是sqlalchemy中的事件监听,并将其应用到数据库的初始化中. 需求:当插入设置password字段时,自动加密 ...
- Python2.7.8 setuptools 下载及安装方法
Python2.7.8 setuptools 下载及安装方法 电脑配置:联想笔记本电脑 windows8系统 Python版本:2.7.8 本文章撰写时间:2014.12.11 作者:陈东陈 阅读说 ...
- 微信商户H5支付申请不通过被驳回解法,拒绝提示:网站有不实内容或不安全信息
H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付.主要用于触屏版的手机浏览器请求微信支付的场景.可以方便从外部浏览器唤起 ...
- 洛谷 P4343 [SHOI2015]自动刷题机
思路 二分答案 显然的二分答案,但是因为二分判定条件 \(\text{wa}\) 了好几遍-- 可以发现,\(n\) 越大,\(k\) 就越小,所以答案是有单调性的,因此可以用两个二分,一次求最大值, ...
- 理解Word2Vec
一.简介 Word2vec 是 Word Embedding 的方法之一,属于NLP 领域.它是将词转化为「可计算」「结构化」的向量的过程.它是 2013 年由谷歌的 Mikolov 提出了一套新的词 ...
- 【HttpRunner v3.x】笔记—8.用例引用、变量传递
看到这里,对于httprunner已经有了一个大概的了解,现在想对于一些比较重要或者常用的功能,进行一些实践操作. 毕竟那谁说过,"纸上得来终觉浅,绝知此事要躬行." 上一篇提到了 ...
- MySQL 数据库 查 续
MySQL 增删查改 必知必会 4.1.13 使用 like 关键字进行模糊查询 -- 说明:模糊查询,使用查询关键字like,like意思是类似于,像...的意思 -- 模糊查询,支持两种字符匹配符 ...
- centos7 RPM MySQL5.5
一.安装MYSQL 把下载好的rpm版的mysql上传到centos7中,目前公司中最爱用的是5.5版本和5.7版本,推荐用5.5. 先安装服务端 rpm -ivh MySQL-server-5.5. ...
- Oracle重做日志和日志挖掘
重做日志-Redo log 首先给出参考资料: 1.Oracle官网-Managing the Redo Log 为什么需要redo log 内存中数据修改后,不必立即更新到磁盘---效率 由日志完成 ...
- Python学习—Anaconda详细 下载、安装与使用,以及如何创建虚拟环境,不仅仅只有安装步骤哦
上一期我们介绍了Python.Pycharm.Anaconda三者之间的关系以及使用,这一期主要详细介绍如何在Windows上下载和安装工具Anaconda,然后使用其自带的conda管理不同项目的虚 ...