微信小程序发送模板消息

根据微信官方文档,发送模板消息的时候要带上对应的 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)
	}
}

最后,根据微信的文档,发送模板消息即可。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据