According to the WeChat Development document, a field form_id
should be presented when requesting a template message to be sent to the user. But the problem is that one template message for one corresponding form can’t meet all the needs. So we need to keep collecting available form_id
s for future template message sending.
And according to this document, form with filed report-submit
can provide a valid form_id
. Thus we can create a subclass for button
to collecting available form_id
s.
We name this class sbutton
, codes on the mini-program side read:
<!--sbutton.wxml--> <form bindsubmit="btnClick" report-submit> <button formType="submit"><slot></slot></button> </form>
{ "component": true, "usingComponents": {} }
/* sbutton.wxss */
// sbutton.js Component({ /** * List of component properties */ properties: { }, /** * Initial data of the component */ data: { requested: false, }, /** * List of component methods */ methods: { btnClick: function (e) { let formId = e.detail.formId if ('the formId is a mock one' !== formId && false ===this.data.requested) { // TODO: send formId to the backend // Set this.data.requested to be true when success } this.triggerEvent('Tap', e, {}) } }, })
After then, we can replace button
with sbutton
safely. For example,
<button bindtap="onConfirm">Confirm</button>
could be replaced with
<sbutton bindtap="onConfirm">Confirm</sbutton>
In the corresponding json
file of the component, add usingComponents
record pointing to the sbutton
.
{ "usingComponents": { "sbutton": "path/to/your/sbutton" } }
On the server side, we need to keep and clean out-dated form_id
s. The example for Golang reads
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) } }
The last step is to send template message with valid form_id
from our pool.