需求:在后台开启活动后为活跃用户发送服务消息,并连接到小程序上。
这个需求其实主要的问题点就是form_id
form_id 的生成由小程序前端表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id
本文中的form_id 为一次性id ,且有效性是7天。
下面是前端的代码
<form bindsubmit="submit" report-submit='true' class='formid'>
<button form-type="submit" ></button>
</form>
可以在button上添加。我们是在小程序的多个常用button上添加了。
下面是前端请求代码
//生成formId
submit: function (e) {
console.log(e.detail.formId, "我是formID");
wx.request({
url: app.globalData.domain + 'saveFormId',
method: 'POST',
header: {
"content-type": "application/x-www-form-urlencoded"
},
data: {
formId: e.detail.formId,
orgId: app.globalData.orgId,
userId: wx.getStorageSync("shareId")
},
success: function (res) {
}
})
}
需要注意一点:在传参时,使用POST方法的话,必须加上下面的header。否则后台接受的都是null
header: {
"content-type": "application/x-www-form-urlencoded"
},
下面是存储到redis的代码
public void saveFormId(String userId, String formId,String orgId) {
logger.info("开始保存formId"+formId);
Date date = new Date();
long longtime = 60*60*24*7;
String createDate = DateUtil.getDatetime(date);
List<FormIdBo> forms = (List<FormIdBo>)redisHandle.get("formId:"+orgId);
logger.info("-----------forms-----"+forms);
//当前机构存在数据
int result = 0;
if (forms!=null&&forms.size()>0){
//遍历所有人
for (FormIdBo formBo :forms){
//存在当前用户
if (userId.equals(formBo.getUserId())){
List<Form> forms1 = formBo.getForms();
List<Integer> delForm = new ArrayList<>();
//删除失效的
if (forms1!=null&&forms1.size()>0){
for (int i = 0;i<forms1.size();i++){
Form form = forms1.get(i);
String create = form.getCreateDate();
Date dateFromString = DateUtil.getDateFromString(create);
boolean latestWeek = DateUtil.isLatestWeek(dateFromString, date);
if (!latestWeek){
delForm.add(i);
}
}
}else {
forms1 = new ArrayList<>();
}
//删除
for (Integer del : delForm){
forms1.remove(del);
}
Form form = new Form();
form.setCreateDate(createDate);
form.setFormId(formId);
forms1.add(form);
formBo.setForms(forms1);
//更新
redisHandle.set("formId:"+orgId,forms,longtime);
logger.info("----------更新的保存成功:{}-----"+forms);
result = 1;
}
}
//新增加的用户
if (result==0){
FormIdBo formIdBo = new FormIdBo();
formIdBo.setUserId(userId);
Form form = new Form();
form.setFormId(formId);
form.setCreateDate(createDate);
List<Form> formList = new ArrayList<>();
formList.add(form);
formIdBo.setForms(formList);
forms.add(formIdBo);
redisHandle.set("formId:"+orgId,forms,longtime);
logger.info("----------新增的保存成功:{}-----"+forms);
}
}else {
//该机构不存在
List<FormIdBo> fromBoList = new ArrayList<>();
FormIdBo formIdBo = new FormIdBo();
formIdBo.setUserId(userId);
Form form = new Form();
form.setFormId(formId);
form.setCreateDate(createDate);
List<Form> formList = new ArrayList<>();
formList.add(form);
formIdBo.setForms(formList);
fromBoList.add(formIdBo);
redisHandle.set("formId:"+orgId,fromBoList,longtime);
logger.info("----------新增机构的保存成功:{}-----"+forms);
}
}
数据结构:{(formId:orgId):{userId:{[formId,createdate]....}}.....}
@Data
public class FormIdBo {
private String userId;
private List<Form> forms;
}
@Data
public class Form{
private String createDate;
private String formId;
}
发送就是利用api 了
其中template_id 获取temShortId 其实就是登陆后台到模板管理中,模板库中自己去查(或者你获取模板库自己去匹配)。我是自己找的。
public Map<String,Object> getSmallTemplateId(String accessToken, String temShortId ,ArrayList<Integer> keywordIdList){
String url = "https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get?access_token"+accessToken;
Map<String,Object> paramMap = new HashMap<>();
paramMap.put("id",temShortId);
paramMap.put("keyword_id_list",keywordIdList);
String param = JSON.toJSONString(paramMap);
String result = PostUtils.postToUrl(param,url);
Map<String,Object> resultMap = JSONObject.parseObject(result,Map.class);
return resultMap;
}
发送
private String sendOpenActivityMessage(User user,String activityName,String date, String formId,String page){
ArrayList<Integer> arrayList = new ArrayList<>();
//添加的消息模板中的关键词所在的value
arrayList.add(21);
arrayList.add(121);
Response<String> templateResult = orgWeixinTemplateService.findSmallByOrgIdAndShortId(user.getOrgId(),ModelMessageNumber.SHOP_OPEN_ACTIVITY.getCode(),arrayList);
Response<String> userResult= userManager.getShopAccessToken(user.getOrgId());
if(!userResult.isSuccess()){
log.info("--------获取accessToken失败:{}------------",userResult.getErrorMessage());
return userResult.getErrorMessage();
}
String accessToken = userResult.getData();
if(!templateResult.isSuccess()){
log.info("------templateId获取失败:{}-----------",templateResult.getErrorMessage());
return templateResult.getErrorMessage();
}
log.info("------t数据初始化成功:{}-----------");
String templateId = templateResult.getData();
String openId = user.getWxUnionid();
Map<String,Object> data = new HashMap<>();
Map<String,Object> activityNameMap = new HashMap<>();
activityNameMap.put("value",activityName);
Map<String,Object> dateMap = new HashMap<>();
dateMap.put("value",date);
data.put("keyword1",activityNameMap);
data.put("keyword2",dateMap);
Map<String,Object> paramMap = new HashMap<>();
paramMap.put("touser",openId);
paramMap.put("template_id",templateId);
paramMap.put("form_id",formId);
paramMap.put("data",data);
if (StringUtils.isNotEmpty(page)){
log.info("------跳跳跳跳跳转+++++:{}--------------",page);
paramMap.put("page",page);
}
//字体变大 变大后最多七个字, 超了不显示
paramMap.put("emphasis_keyword","keyword1.DATA");
String param = JSON.toJSONString(paramMap);
String result = PostUtils.postToUrl(param,"https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token="+accessToken);
log.info("------小程序订单推送结果:{}--------------",result);
return result;
}
坑还是比较多的。慢慢填吧。
首先:form_id 微信限制的。跟人一一对应的,而且是一次性的有效期还是7天。(优化是增加签到功能,在每天签到的方法中加入存储form_id的方法。这样能够更有效的维护活跃用户。而且也保证了form_id 的时效性。)
再有:就是template_id 看代码的时候,那个OPEN开头的和 AT 开头的id 的出处有些蒙,但是也是很快就找到了出处。
在上面的代码中,我觉得比较low ,而且代码没有优化,一两天弄出来的。form_id 就忙了一天。还是记录一下。有不清楚的人可以给我留言。