微信-小程序模板消息升级订阅消息难点记录
说明
小程序接口升级由模板消息升级为订阅消息,期间遇到了很多的坑,把自己的问题以及源码贴出来记录一下
前提
公司之前有在用一套模板消息,包括咨询回复通知、拼团成功通知、拼团失败通知、支付成功通知、支付失败通知、订单确认通知、发货提醒通知、收益到账通知 ,我需要做的就是要将这些消息模板改为订阅消息模板。
在不更改前人逻辑的前提下,只对核心发送接口和自动添加模板接口做更改。
模板消息发送升级为订阅消息发送
模板消息发送接口更改为订阅消息发送接口除url外有两个地方需要更改。
1.订阅消息发送接口不需要form_id
2.订阅消息发送数据格式跟模板消息不一样
我就把我写的升级接口给大家贴一下:
//代码做了删减,保留大家有用的部分
//订阅消息推送接口,相当于接收的参数还是模板消息的格式,这里做处理后改为发送订阅消息
public static function sendTemplateSubMsg($data,$beid){
$accessToken = self::getAccessToken($beid);
$url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=".$accessToken;
//获取模板键值代码
$keyArray=WeixinService::upMsgInterface($data['template_id'],$beid);
//升级模板消息内容为订阅消息
$subDataArray=[];
unset($data['form_id']); //去除form_id
foreach (array_values($data['data']) as $key => $value ){
$subDataArray[$keyArray[$key]]['value']=$value['value'];
}
$data['data']=$subDataArray;
Log::info($url);
$output = Curl::post($url,json_encode($data));
$obj = json_decode($output);
Log::info('output:'.print_r(json_decode($output, true), true));
if(!empty($obj->errcode)){
Log::info(print_r($data,true));
}
return true;
}
//数据转化接口,将模板消息的数据格式转为订阅消息的格式
public static function upMsgInterface($temId,$beid){
//匹配模板id,获取模板标题id
$accessToken = self::getAccessToken($beid);
$url="https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token=".$accessToken;
//获取模板详情
$response = json_decode(Curl::get($url),true);
if(!$response){
return false;
}
//获取模板内容字符串
$conStr='';
foreach ($response['data'] as $key => $value) {
if($value['priTmplId']==$temId){
$conStr=$value['content'];
break;
}
}
unset($response);
//获取模板key值数组
$conArray=explode(PHP_EOL,$conStr);
$conKeyArray=[];
foreach($conArray as $value){
if(!$value){
continue;
}
$conKeyArray[]=ltrim(Util::getNeedBetween($value,'{','.'),'{');
}
return $conKeyArray;
}
模板消息添加升级为订阅消息添加
订阅消息添加有一个需要注意的地方,接口文档示例上传递参数是json格式,实际上应该用x-www-from-urlencoded格式
x-www-form-urlencoded就是application/x-www-from-urlencoded,会将表单内的数据转换为键值对,&分隔。
当form的action为get时,浏览器用x-www-form-urlencoded的编码方式,将表单数据编码为
(name1=value1&name2=value2…),然后把这个字符串append到url后面,用?分隔,跳转到这个新的url。
当form的action为post时,浏览器将form数据封装到http body中,然后发送到server。
postman发送示例截图:
<h5>代码示例</h5>
保留了基础代码,核心就是参数的配置与拼接。
public static function generateSubTemplateId($type,$beid){
$params = [
'tid=6271',
'kidList[0]=4',
'kidList[1]=3',
'kidList[2]=2',
'kidList[3]=1',
'sceneDesc=订单支付成功后进行通知',
];
$paramStr = implode("&", $params);
$accessToken = WeixinService::getAccessToken($beid);
$url="https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate?access_token=".$accessToken;
$response = Curl::post($url,$paramStr);
$returnArray=json_decode($response,true);
var_dump($returnArray);
}
其他知识点
1.目前小程序开发版与体验版已经关闭了form_id的获取,但线上还可以获取,所以线上的模板消息还可以用,但截至日期不太清楚,小道消息是1/4。
2.订阅消息发送字段的长度不可超过20个字符,长消息需要做处理,例:收货地址
3.目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。
https://developers.weixin.qq.com/community/develop/doc/00008a8a7d8310b6bf4975b635a401?blockType=1
4.一次性订阅的意思是订阅了一次,就是你用完了这一次下次还需要订阅,一次性订阅消息推送次数跟时间没有关系,只跟订阅次数有关。
5.一次性订阅选择时,如果勾选了总是保持以上选择,那么订阅消息框将不再弹起,目前就是这样的一个场景,所以需要谨慎引导客户选择。
6.订阅消息发送接口要用x-www-from-urlencoded格式,将参数放到body体中。
结尾
酒入豪肠,七分化作月光;剩下的三分,啸成了剑气,绣口一吐,就是半个盛唐。