根据微信官方文档,发送模板消息的时候要带上对应的 form_id
,然而并不是在所有情况下都能满足一次表单发送一次模板消息的需求,因而需要通过不断采集可用的 form_id
来为后续模板消息的发送做准备。
又根据这篇文档,可知带有 report-submit
属性的 form 可获取一个有效的 form_id
,所以我们可以子类化一个 button
来不断地采集可用的 form_id
。
我们将这个类命名为 sbutton
,小程序端代码如下:
<!--sbutton.wxml--> <form bindsubmit="btnClick" report-submit> <button formType="submit"><slot></slot></button> </form>
{ "component": true, "usingComponents": {} }
/* sbutton.wxss */
// sbutton.js Component({ /** * 组件的属性列表 */ properties: { }, /** * 组件的初始数据 */ data: { requested: false, }, /** * 组件的方法列表 */ methods: { btnClick: function (e) { let formId = e.detail.formId if ('the formId is a mock one' !== formId && false ===this.data.requested) { // TODO: 发送formId到后端 // 如果成功则让 this.data.requested 为 true } this.triggerEvent('Tap', e, {}) } }, })
这样之后,可以无缝替换标准 button
组件为我们定义的 sbutton
,比如
<button bindtap="onConfirm">Confirm</button>
可以直接替换为
<sbutton bindtap="onConfirm">Confirm</sbutton>
在对应页面的 json
中,添加 usingComponents
字段指向 sbutton 所在位置
{ "usingComponents": { "sbutton": "path/to/your/sbutton" } }
而在服务器端,需要实现一个可以记录并自动清理过期 form_id
的功能,Golang 的例子如下
package wechat import ( "errors" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" "model/db" "strconv" "time" ) /* WeChat Mini Program Template Message FormId */ type WxTempMsgFormId struct { WxOpenId string FormId string Timestamp int64 } var conn *gorm.DB func init() { var err error conn, err = gorm.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", "db_username", "db_password", "db_host", "db_port", "db_name")) if err != nil { panic(err.Error()) } conn.AutoMigrate(&WxTempMsgFormId{}) go clean_worker() } func FormIdSave(wxOpenId string, formId string) { conn.Save(WxTempMsgFormId{ WxOpenId: wxOpenId, FormId: formId, Timestamp: time.Now().Unix(), }) } func FormIdConsume(wxOpenId string) (string, error) { record := WxTempMsgFormId{WxOpenId: wxOpenId} conn.Where(record).First(&record) if "" != record.FormId { db.Conn.Delete(&record) return record.FormId, nil } else { return "", errors.New("No more available form_id for user " + wxOpenId) } } func clean_worker() { for { threshold := time.Now().Unix() - 3600*24*6 // 6 days ago db.Conn.Where("timestamp < " + strconv.FormatInt(threshold, 10)).Delete(&WxTempMsgFormId{}) time.Sleep(time.Hour * 1) } }
最后,根据微信的文档,发送模板消息即可。