Skip to content
On this page

小程序 - 发送模版消息

概述

没有经验的开发者在初次尝试时会遇到很多坑,本文围绕的业务逻辑是B点击按钮进行某项操作后更新了记录的状态,发消息给记录创建人A。

主要内容

  • 模版消息的发送实现
  • 获取用户信息、获取form_id与转发分享button冲突及回调处理

模版消息的发送实现

api为

/**
 * 发送模版消息 
 */
wx.sendTemplateMessage({
    // 链接上的access_token一定要带上
    url: 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=',
    // 不要认为链接上带了这里就可以省略,或者这里带了,链接上的就省略
    access_token: accessToken,
    // openid,产生form_id人的openid,也就是说openid要与form_id来源一致
    touser: params.openId,
    // 消息模版id,可以直接登陆后台,从模版库中选择模版然后复制。新建模版审核比较慢
    template_id: params.templateId || templateId,
    // 该字段必填,文档上写的以为可以省略
    form_id: params.formId,
    // 小程序页面path
    page: params.page,
    // 文档上写的string类型,实际不是,为选择模版勾选字段的顺序,填充value即可
    data: {
      keyword1: {
        value: params.value1
      },
      keyword2: {
        value: params.value2
      },
      keyword3: {
        value: params.value3
      }
    }
    // 需要在消息中放大展示的字段,固定的值
    emphasis_keyword: 'keyword1.DATA'
  })

form_id的获取

依赖<form/><button/>组件

<form
    report-submit="true"
    @submit="submit"
  >
  <button form-type="submit"></button>
</form>

submit事件会接收到e.detail.form_id,form_id只能被使用一次,有效期为7天。那些可以发送7天后提醒的小程序肯定不是用的这个方法,而是用的公众号里的方法来发送提醒。

点击按钮只能获取一个form_id且只能被使用一次,那如果想发送多条消息怎么办?我们可以嵌套form实现

<form
    report-submit="true"
    @submit="submit"
  >
  <button form-type="submit">
    <form
        report-submit="true"
        @submit="submit"
      >
      <button form-type="submit"></button>
    </form>
  </button>
</form>

这样就可以获取2个form_id了,用3个字段分别去标记form_id、有效期和该登陆人的openid,在使用时根据登陆时获取的openid做筛选即可。

也就是说,在小程序中基本上你看到页面的按钮都是埋了很多点的,按钮要慎点,一不小心就会给你推送消息。

获取用户信息、获取form_id与转发分享

我们会发现,获取用户信息也是<button/>组件

<button
  open-type="getUserInfo"
  @getuserinfo="callback"
/>

其实这2种事件是可以并存的,只不过没有先后顺序

<form
    report-submit="true"
    @submit="submit"
  >
  <button
    form-type="submit"
    open-type="getUserInfo"
    @getuserinfo="callback"
  >
  </button>
</form>

文档上没有说明是否有顺序,但在实际的操作过程中,会发现submit事件永远先于callback,但在一种情况下不是,但快速点击这个button时,就不会触发getUserInfo,似乎是一种缓存机制。

当然,正常情况下你可以先在submit事件中保存得到的form_id,再在getUserInfo后使用,但是为了保险起见,还是用setInterval比较稳妥

// 页面隐藏时要清除掉timer
onHide() {
  this.timer && clearInterval(this.timer)
  this.timer = null
  console.log('clear timer.')
}

beforeHandle () {
  if (!this.timer) {
    this.timer = setInterval(() => {
      // 在获取到userInfo和formId后再做其它操作
      if (this.userInfo && this.formId) {
        clearInterval(this.timer)
        this.timer = null
        console.log('timer is stopped')     
      } else {
        console.log('timer is circling...')
      }
    }, 10)  // 不允许为0
  } else {
    console.log('timer is exist!')
  }
}

那如何做到用户B在操作后,将操作结果发消息给用户A呢?

发消息给用户A肯定需要用户A的form_id而不是点击按钮时用户B获取的。

我们只能在用户A做转发操作分享给B时,获取form_id存在表里,这样就可以了。

这里又会有一个问题,转发时

<button
  open-type="share"
/>

并且不会触发@click事件,如果这个按钮想在做这3件事情后还能触发点击事件怎么办?

<form
    report-submit="true"
    @submit="submit"
  >
  <button
    form-type="submit"
    :open-type="condition ? 'share' : 'getUserInfo'"
    @getuserinfo="e => callback(e, 'optionName')"
  >
  </button>
</form>

...

{
  callback(fnName) {
    store.commit('setUser', Object.assign(res.mp.detail.userInfo))      
    this.beforeHandle(fn)
  }
}

只能动态bind属性open-type,然后将需要做的操作传递给getuserinfo回调,在回调中再调用上面定义的timer函数beforeHandle