微信小程序消息订阅Java

前言

编写日期 : 2022-11-04

写这篇文章原因

公司给政府做一个订餐系统,需要在员工在小程序上发起订餐后经过部门领导和书记的审批后,再由食堂确认订餐结果。在订餐审批单在各个节点流转的过程中,需要给每一个节点的审批人发送微信订阅消息手机短信,通知订餐流程所在节点的人有新的订餐审批单需要审批,最终将订餐结果通过微信订阅消息手机短信反馈给订餐人员。手机短信那块后端很好整,没啥问题,但是这个微信小程序发送订阅消息这个没有整过,有点懵,但不慌。本来这个微信的消息订阅前端已经做好了,但是架构师说这块的逻辑后端做,所以我就来搞这个了。

官方文档说明

链接 :>>>微信小程序发送订阅消息官方文档 <<<

调用方式 HTTPS 调用
POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN

请求参数

属性 类型 类型 说明
access_token String 需要用小程序的appid和密钥secret去调用 官方 接口获取
template_id String 所需下发的订阅模板id
page String 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
touser String 接收者(用户)的 openid,
data String 模板内容,格式形如 { “key1”: { “value”: any }, “key2”: { “value”: any } }的object
miniprogram_state String 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
lang String 进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN

申请的微信订阅消息模板

在这里插入图片描述

访问接口传参示例

{
    
    
  "touser": "OPENID",
  "template_id": "TEMPLATE_ID",
  "page": "index",
  "miniprogram_state":"developer",
  "lang":"zh_CN",
  "data": {
    
    
      "thing1": {
    
    
          "value": "金先生"
      },
      "time2": {
    
    
          "value": "2020-05-01"
      },
      "phrase13": {
    
    
          "value": "成功"
      } ,
      "thing17": {
    
    
          "value": "xx地方"
      }
  }
}

代码

需要用到的当前小程序的参数

  • appid 小程序的appid
  • secret 小程序密钥
  • TempId 申请的订阅消息模板id

获取access_token


	@Value("${wx.xiaochengxu.appid}")
    private String appid;
    @Value("${wx.xiaochengxu.secret}")
    private String secret;

 /**
  *	@param appid secret
  */
  	@Override
	public String getAccessToken() {
    
    
	        HttpResponse response = HttpRequest.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret + "").execute();
	        JSONObject tokenJson = JSON.parseObject(response.body());
	        String accessToken =  tokenJson.get("access_token").toString();
	        return accessToken;
	    }

发送订阅消息

请求参数

public class SendMsgBody {
    
    

    /*接收者(用户)的 openid*/
    private String touser;

    /*所需下发的订阅模板id*/
    private String template_id;

    /*点击消息后跳转的页面*/
    private String page;

    /*跳转小程序类型:developer 为开发版;trial 为体验版;formal 为正式版;默认为正式版*/
    private String miniprogram_state="developer";

    /*进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN返回值*/
    private String lang="zh_CN";

    /*模板数据,这里定义为object是希望所有的模板都能使用这个消息配置*/
    private Object data;


    public String getTouser() {
    
    
        return touser;
    }
    public void setTouser(String touser) {
    
    
        this.touser = touser;
    }
	//template_id、page、data ==>getset
}

请求参数中的data

public class MsgSuccess {
    
    

    /*姓  名*/
    private Map<String, String> thing1;

    /*预约时间*/
    private Map<String, String> time2;

    /*预约状态*/
    private Map<String, String> phrase13;

    /*预约地点*/
    private Map<String, String> thing17;

    public Map<String, String> getThing1() {
    
    
        return thing1;
    }

    public Map<String, String> getTime2() {
    
    
        return time2;
    }

    public Map<String, String> getPhrase13() {
    
    
        return phrase13;
    }

    public Map<String, String> getThing17() {
    
    
        return thing17;
    }

    public void setThing1(String thing1) {
    
    
        this.thing1 = getFormat(thing1);
    }

    public void setTime2(String time2) {
    
    
        this.time2 = getFormat(time2);
    }

    public void setPhrase13(String phrase13) {
    
    
        this.phrase13 = getFormat(phrase13);
    }

    public void setThing17(String thing17) {
    
    
        this.thing17 = getFormat(thing17);
    }

    public HashMap<String, String> getFormat(String str) {
    
    
        return new HashMap<String, String>() {
    
    {
    
    
            put("value", str);
        }};
    }

    @Override
    public String toString() {
    
    
        return "DCSuccess{" +
                "thing1=" + thing1 +
                ", time2=" + time2 +
                ", phrase13=" + phrase13 +
                ", thing17=" + thing17 +
                '}';
    }
}

发送消息

	@Value("${wx.xiaochengxu.sendMsg.successTempId}")
    private String tempId;//模板id

	@Override
	public void wxSendMsgSuccess(String openId, Map<String, String> node) {
    
    
	        String accessToken = getAccessToken() ;
	
	        //先填充请求体中data的数据
	        MsgSuccess msgSuccess = new MsgSuccess ();
	        msgSuccess .setThing1(node.get("thing1"));
	        msgSuccess .setTime2(node.get("time2"));
	        msgSuccess .setPhrase13("成功");
	        msgSuccess .setThing17(node.get("thing17"));
	
			//请求参数数据填充
	        SendMsgBody sendMsgBody = new SendMsgBody();
	        sendMsgBody.setTouser(openId);
	        sendMsgBody.setTemplate_id(tempId);
	        sendMsgBody.setData(msgSuccess);
	
	        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
	
	        //发送请求
	        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
	        HttpHeaders headers = new HttpHeaders();
	        headers.setContentType(type);
	        HttpEntity<SendMsgBody> httpEntity = new HttpEntity<>(sendMsgBody, headers);
	        JSONObject jsonResult = restTemplate.postForObject(url, httpEntity, JSONObject.class);
	        JSONObject responseData = jsonResult ;
	
	        Integer errorCode = responseData.getInteger("errcode");
	        String errorMessage = responseData.getString("errmsg");
	        if (errorCode == 0) {
    
    
	            log.info("订餐通知消息发送成功");
	        } else {
    
    
	            log.info("订餐通知消息发送失败,errcode:{},errorMessage:{}", errorCode, errorMessage);
	        }
	    }

调用

    @GetMapping("wxSendSuccess")
    @ApiOperation(value = "微信小程序发送订阅消息通知")
    public boolean wxSendSuccess(){
    
    
        String openId = "oks*******************Gk";
        HashMap<String, String> map = new HashMap<>();
        map.put("thing1","***");
        map.put("time2","2022-11-03 12:13");
        map.put("thing17","405");
        return wxService.wxSendMsgSuccess(openId,map);
    }

结果

在这里插入图片描述

总结

咱们这个消息的订阅前端授权一次后,咱们也就只能发送成功一次,在接收订阅消息的用户没有同意接收订阅信息的时候,我们调用接口给用户发送订阅消息基本都会被拒绝。请求结果如下:

errcode:43101,errorMessage:user refuse to accept the msg rid: 6363495-2267c4de-7aa0fab1

如果你的小程序没有进行政府 医疗等认证,那你就不能长期订阅,所以每一次订阅消息的发送都需要接收方的一次授权,并且接收放的授权次数是可以累加的,比如说这次订阅了你没发订阅消息,下次再继续订阅,你就可以连续发两条订阅成功。但是在特殊情况下小程序方也会清楚所有的授权次数。

猜你喜欢

转载自blog.csdn.net/m0_46636892/article/details/127709917