1. 需求

最近在做一款拼课类小程序,大概需求就是分享课程页面给好友,好友参与达到一定数量后则拼课成功。

好友参与后会给分享者发送一条模板消息

参与人数满足后(拼课成功)会给分享者发送一条模板消息

管理后台可以群发模板消息(给所有用户发消息)

按理说很平常的需求,微信公众号里边应该很容易实现,但是想在小程序里边实现这么个功能却有点蛋疼了。

2. 分析

为什么小程序实现起来比较费劲呢,那就要说下小程序发送模板消息的机制了,先看文档怎么说:

划重点,本人、交互,也就是说这个模板消息,必须由用户手动来触发,你想后台定时给用户推个消息,洗洗睡吧你。

再来看下面:

这个重点你们自己划吧,发模板消息必须满足这两种情况中的一种,支付就不说了,用户付款后可以推送几条消息,重点是这个表单提交。

意思就是我想给用户发个模板消息,第一要搞个表单,第二要让用户来提交这个表单(获取formId),而且这个模板消息还只能发给提交表单的用户本人,你想发给别的用户,呵呵。

献给我们伟大的TX

3. 原理

好了,说多了都是气,既然这样设计,也是有一定道理,但是道理都是讲给守规矩的人听的,至于不守规矩的,喂!说的就是你。

通过上面的分析我们知道,想发送一个基本的模板消息需要以下步骤:

构建一个form表单

设置表单的report-submit属性为true(用来获取formId发送模板消息)

用户提交表单,把openid和formId一块提交给后台(其实真正开发中一般不会提交openid,因为在用户登录或者访问小程序时候通常会把openid和当前用户在数据库中做个同步)

后台调用POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN来发送模板消息

模板消息接口 POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN有这么几个参数 :

其中touser(openid)和form_id是重点,这两个参数的结合是用来确认和效验模板接收者的,因为用户提交表单微信会生成一个专属的formId,这个formId标识着用户的一个操作。所以可以这样来理解,要想发送一个模板消息给特定用户,那么必须要有该用户的有效formId(7天内有效)和openid,一旦我们有了用户大量的formId,你说我发个模板消息那还不跟玩的一样。

所以问题就来了

1. 我如何来收集用户的formId?

这个还没有什么特别有效的办法,因为微信不会给提供相关api,而且只有提交表单才能得到formId,所以只能让用户去主动的触发表单来生成formId,我们要做的就是修改原有的页面,把页面上高强度的交互都用form和button组件来替换,只是在外层套一个form组件而已,里边用button来触发操作(记得修改样式),比如:

像这些交互元素都可以外层套上form组件,用户点击后触发表单提交事件,得到formId,我们把formId和用户openid发送给后台特定接口,后台要做的就是把formId和openid存储下来,至于存数据库、文件、缓存、redis都行,主要是要把openid和formId关系对应好,而且每个formId都有一个过期时间。我是用laravel的redis缓存来存储,毕竟这块是一个高频的io操作。具体实现方式在后面。

2. 搞了一堆用户的formId后,我该怎么来用呢?

其实这个问题是多余的,就像给你了一个女朋友,你却不知道该干啥一样。当然是上...

前面已经说的很清楚了,想要给目标用户发模板消息需要formId和openid,当后台有一个发送模板消息事件被触发时,只需要获取目标用户的openid(这个你们自己数据库肯定有对应的啦),然后根据openid从数据库(或其他存储引擎)拉取一个有效的formId,请求POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN即可,完事了,记得删掉这个formId奥。

4. 实现

前面扯了一堆概念,下面我们来把这个功能具体的实现一遍吧,我这里后台用的是php laravel,原理都一样。

小程序端业务

我这只写一个例子,一看就明白

// wxml

// reprt-submit属性记得写上

这里边才是我们正常的界面代码

// js

// 这块都可以封装的,毕竟很多交互的地方都需要

clickFormView(event) {

let formId = event.detail.formId;

// 忽略开发者工具里边的formId

if (formId && formId !== 'the formId is a mock one') {

wx.request({

method: 'POST',

url: '/api/collectFormId', // 该接口只用来收集formId

data: { formId: formId } // 只传了一个formId,因为openid和当前用户通常会事先在后台做一个关联,看具体业务了

});

}

// 然后可以干其他事了,比如跳转页面,其他业务逻辑

// TODO

}

有些时候用户操作频繁,可能会导致服务器收到大量请求,所以可以优化下,把formId先存到一个全局变量里边(数组),当达到一定数量后统一发给后台来保存。这块可以灵活运用。

服务端实现

服务端的实现也就两个功能,收集和发送。

假设我们现在有这么一个类FormIdCollection,可以收集(save)和获取(get)某个openid的formId,那我们给前台暴露的api只需要简单的调用下就可以了,至于发消息,也只需要get一个formId,即可。

// 实例化一个对象

// $openid为目标用户openid

// $config是一个数组,微信小程序相关配置[app_id, secret]

$collection = new FormIdCollection($openid, $config);

// 收集一个formId

$collecton->save($formId);

//获取一个可用formId

$collection->get();

// 发送模板消息

// $data为模板消息相关参数 template_id等

$collecton->send($data);

下面是FormIdCollection类的一个具体实现,基于laravel(说实话,挺好用的),另外引入了一个微信开发包overtrue/wechat(这里主要是用来发模板消息、有点大材小用了),https://www.easywechat.com/

use Illuminate\Support\Facades\Cache;

use EasyWeChat\Factory;

class FormIdCollection

{

private $openid;

private $config;

private $cache;

private $cacheKey;

public function __construct($openid, $config = [])

{

$this->openid = $openid;

$this->config = $config;

$this->cache = Cache::store('redis'); // 用redis作为缓存驱动,记得要配置redis环境奥

$this->cacheKey = $this->getCacheKey(); // 每个openid对应一个key

}

/**

* 获取缓存key

*

*/

public function getCacheKey()

{

return 'mini_program_form_id_'.$this->openid;

}

/**

* 发送模板消息

*

* @param $data 模板消息参数

*/

public function send($data)

{

$mina = Factory::miniProgram([

'app_id' => $this->config['app_id'],

'secret' => $this->config['secret'],

]);

// 获取一个可用的formId,然后删除掉

$formId = $this->get(true);

if (!$formId) {

throw new \Exception('no formId');

} else {

$data['touser'] = $this->openid;

$data['form_id'] = $formId;

// 用overtrue/wechat包来发送模板消息

$res = $mina->template_message->send($data);

return $res;

}

}

/**

* 存储formId

*

* @param $formId

*/

public function save($formId)

{

$formIds = $this->gets();

$formIds->push([

'form_id' => $formId,

'expire' => time() + 60 * 7 * 24 // formId过期时间

]);

// 存储到redis缓存中

$this->cache->forever($this->cacheKey, $formIds->toArray());

}

/**

* 获取某个未过期的formId

*

* @param $delete 获取之后是否立即删除

*/

public function get($delete = false)

{

$formIds = $this->gets();

if (!$formIds->count()) {

return false;

}

// 筛选一个有效的formId,优先获取快过期的

$formId = $formIds->where('expire', '>=', time())->sortBy('expire')->first()['form_id'];

if ($delete && $formId) {

$this->delete($formId);

}

return $formId;

}

/**

* 获取formId集合

*

* @return \Illuminate\Support\Collection

*/

public function gets()

{

$formIds = $this->cache->get($this->cacheKey);

return collect($formIds ? $formIds : []);

}

/**

* 删除某个formId

*

* @param $formId

*/

public function delete($formId)

{

$formIds = $this->gets();

$formIds = $formIds->filter(function($item) use($formId) {

return $item['form_id'] != $formId;

});

$this->cache->forever($this->cacheKey, $formIds->toArray());

}

/**

* 清理所有已过期的formId

*

*/

public function clearExpireFormIds()

{

$formIds = $this->gets();

$time = time();

$formIds = $formIds->filter(function($item) use($time) {

return $item['expire'] > $time;

});

$this->cache->forever($this->cacheKey, $formIds->toArray());

}

}

我已经封装了一个laravel扩展包,感兴趣的朋友可以上github上看下https://github.com/laravuel/laravel-wfc。

至于非框架的php实现,小伙伴可以帮忙弄下。

觉得讲的不错的小伙伴可以点波关注奥~

php怎么实现发送给指定用户,微信小程序 实现模板消息群发、发送给指定用户...相关推荐

  1. 微信小程序之模板消息

    在移动应用中,APP经常通过推送的方式将一些消息发送到用户的手机上.小程序基于微信内,为我们提供了一整套的模板消息,使微信和小程序这个体系达到服务闭环的效果. 一.消息模板在微信中显示 1.服务通知: ...

  2. Spring Boot 实现微信小程序订阅模板消息

    导语   有很多场景下,需要要对接微信小程序的开发,在使用的过程中,会出现各种各样的问题,本人总结了关于如何调用微信小程序模板订阅消息的相关实现总结如下 微信订阅消息官网   首先要求系统,在不同的场 ...

  3. 【微信小程序】模板消息推送(测试成功)。

    note: 这几天想做微信小程序消息推送的功能,然后在网上找了好多教程,都没解决问题,官方文档写的教程由不够详细,所以走了好多弯路. 现在问题解决了,记录一下. 我在网上找的好多教程都不详细,虽然是贴 ...

  4. 【Springboot】整合wxjava实现 微信小程序:模板消息

    文章目录 一.模板消息是什么? 二.整合步骤: 1.微信小程序后台配置模板消息 2. 发送模板消息 后端逻辑代码 controller service impl 前端逻辑代码 测试: 提示:以下是本篇 ...

  5. 微信小程序API 模板消息

    模板推送位置:服务通知 模板下发条件:用户本人在微信体系内与页面有交互行为后触发 模板跳转能力:点击查看详情仅能跳转下发模板的该帐号的各个页面 使用说明 步骤一:获取模板ID 有两个方法可以获取模版I ...

  6. 微信小程序的模板消息与小程序订阅消息

    小程序订阅消息功能介绍消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验. 订阅消息推送位置:服务通知订阅消息下发条件:用户自主订阅订阅消息卡片跳转能力: ...

  7. 微信小程序(模板消息)

    formid用过一次,立即失效,如果formid不使用,7天内天可以用 步骤: 1.获取用户openid (api) 2.获取access_token(api) 3.提交时获取formid 4.发送模 ...

  8. 微信小程序订阅模板消息

    1.登录管理员后台,订阅消息,选择模板或者申请模板 2. 开发管理,开发设置,开启消息推送,并验证服务器 3. 开发获取获取模板列表接口,和 测试消息发送接口 4. 前端根据接口配置授权弹窗页,获取用 ...

  9. uni-app 微信小程序客服聊天和发送页面卡片功能

    微信小程序客服聊天和发送页面卡片功能实现步骤如下: (一):首先登录微信公众平台 :https://mp.weixin.qq.com/ 登录成功后找到----->功能-----> 客服-- ...

最新文章

  1. 闽台“物联网+”产业融合方兴未艾
  2. React Native学习笔记-1:JSC profiler is not supported.(转载)
  3. .net中6个重要的基础概念:Stack, heap, Value types, reference types, boxing and Unboxing.
  4. zabbix监控 openstack 的实例的资源使用情况
  5. python 使用期物处理并发
  6. tc35 终端 cnmi=2,2即时模式下收不到短信的问题
  7. 3.8 Spark 用户日志分析
  8. 实现多楼层,每个楼层多房间,上下拖动切换楼层,左右拖动查看其他房间
  9. c语言数组转指针,(转)c语言指针数组
  10. html判断安装没安装qq,QQ提示安装路径无效您没有权限怎么办 QQ2015提示安装路径无效您没有权限的解决方法...
  11. python自动刷网课_基于python和selenium的刷网课的代码。
  12. 闲时看看, 比较有益的文章地址
  13. VMware安装CentOS7以及CentOS官网下载自选镜像
  14. c语言单片机程序int,单片机睡眠-外中断INT0 INT1唤醒(汇编+C语言程序)
  15. OC dyld750调用分析
  16. alc662声卡注入id_ALC662声卡Linux提取文件.doc
  17. 软件工程—团队作业1(三人行)
  18. 微信营销社群营销推广方案--精华版
  19. 思维模型丨看先辈是如何学习的?
  20. xmanager调出图形安装oracle,Xmanager快速连接Linux图形界面教程

热门文章

  1. Win10电脑如何查看电脑配置
  2. win11语言输入没反应怎么办 windows11语音输入没反应的解决方法
  3. CubeMX创建stm32项目及遇到的问题
  4. 多线程下载Android
  5. 未预期的符号 `( 附近有语法错误_苹果iOS 14.2现在提供117种新的表情符号和新的壁纸...
  6. java10个整数反向输出_输入一个整数,实现反转输出,如输入123,输出321。
  7. android dao设计模式,DAO设计模式
  8. e站app里站hosts_硬核干货区 | E站的国际站运营知识星球上线啦
  9. 比较版本号大小c语言,比较两个版本字符串version1和version2
  10. 计算机是怎样跑起来的