微信小程序服务通知

 官方接口链接

发送订阅消息 | 微信开放文档

一、流程

 1、准备号小程序

2、小程序在订阅消息端创建消息模板拿到TemplateID

3、 前端需要配置消息ID,订阅服务通知

4、后端调接口发送通知到用户openId

二、使用

1、小程序创建消息模板

在微信小程序添加订阅消息模板

小程序后台链接:小程序

1、注意消息模板的ID,前端和后端都需要

2、点击详情下面有对应的字段内容,后端需要返回对应字段JSON格式数据

2、 小程序后台配置

        封装成工具类使用

        直接调用sendTemplateMsg()方法即可。

需要参数

        a、用户的openId、

        b、消息模板ID

        c、消息主体的JSON字段数据

注意:注意JSON格式,参照官网

如果JSON格式不对:(时间格式不能包含字母或无关符号)

result:{"errcode":47003,"errmsg":"argument invalid! data.character_string22.value rid: 66012b9d-00baed03-2e813aea"

1、构建工具类

/**
 * 微信消息通知
 */
public class WxMessageConfig {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 发送模板消息 注意格式
     */
    public static boolean sendTemplateMsg(String openId,  String templateId,WxMessageDto wxMessageDto) {
        String access_token = getAccessToken();

        Map<String, Object> paramMap = wxMessageMap(wxMessageDto);
        paramMap.put("touser", openId);
        // 模版
        paramMap.put("template_id", templateId);
        // 跳转小程序(不加微信界面没有跳转那一行)
        paramMap.put("page", "index");

        String url = WxConstants.POST_MESSAGE_URL;
        String jsonStr = null;
        try {
            // 转JSON
            ObjectMapper objectMapper = new ObjectMapper();
            jsonStr = objectMapper.writeValueAsString(paramMap);
        } catch (JsonProcessingException e) {
            log.error("消息通知转JSON格式异常");
            e.printStackTrace();
        }
        try {
            jsonStr = HttpUtil.post(url, access_token, jsonStr);
        } catch (Exception e) {
            log.error("小程序服务通知异常-转化异常", e);
        }
        JSONObject jsonObj = JSONObject.parseObject(jsonStr);
        String errcode = jsonObj.get("errcode").toString();
        Object errmsg = jsonObj.get("errmsg");
        if (!errcode.equals("0")) {
            log.error("微信通知消息发送失败:code=" + errcode + "msg=" + errmsg);
            return false;
        }
        return true;
    }

    /**
     * 获取access_Token(发送消息需要)
     * @return
     */
    private static String getAccessToken() {
        /**
        * 非spring环境获取bean(注入redis工具类) 工具类  redis获取缓存的的token
        */
        RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
        /**
         *  public static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
         */
        String access_token = redisCache.getCacheObject("wx_access_token");
        if (access_token == null) {
            String url = WxConstants.GET_ACCESS_TOKEN_URL.replace("APPID", WxConstants.APPID)
                    .replace("APPSECRET", WxConstants.SECRET);
            String jsonStr = HttpUtil.httpGet(url);
            JSONObject jsonObj = JSONObject.parseObject(jsonStr);
            access_token = jsonObj.getString("access_token");
            int expires_in = Integer.parseInt(jsonObj.getString("expires_in"));
            redisCache.setCacheObject("wx_access_token", access_token, expires_in, TimeUnit.SECONDS);
        }
        return access_token;
    }

    /**
     * 构建消息主体JSON数据
     * @param wxMessageDto
     * @return
     */
    public static  Map<String, Object> wxMessageMap(WxMessageDto wxMessageDto){
        // 时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 格式化时间
        String formattedDateTime = wxMessageDto.getTime().format(formatter);

        HashMap<String, Object> paramMap = new HashMap<>();
        // 创建消息内容的 Map 对象
        Map<String, Object> messageContent = new HashMap<>();
        messageContent.put("thing13", new HashMap<String, Object>() {{
            put("value", wxMessageDto.getProductName());
        }});
        messageContent.put("amount4", new HashMap<String, Object>() {{
            put("value", wxMessageDto.getPrice());
        }});
        messageContent.put("character_string22", new HashMap<String, Object>() {{
            put("value", wxMessageDto.getOrderNo());
        }});
        messageContent.put("thing24", new HashMap<String, Object>() {{
            put("value", wxMessageDto.getAddress());
        }});
        messageContent.put("time23", new HashMap<String, Object>() {{
            put("value", formattedDateTime);
        }});
        paramMap.put("data", messageContent);

        return paramMap;
    }
}

2、微信相关链接、消息模板ID常量

/**
 * 微信相关参数
 */
public class WxConstants {

    public static final String APPID = "wxexxxxxxxxxxx"; 
    public static final String SECRET = "b9bc54xxxxxxxxxxxxxxxxxxxxxx"; 
    //    public static final String GET_ACK_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; // 网页
    public static final String GET_ACK_URL2 = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_cod"; // 小程序

    public static final String GET_USER_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID"; // 网页
//    public static final String POST_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN";

    // 小程序消息通知 
   public static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    public static final String POST_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send";
    public static final String WX_TEMPLATE_ID_ORDER1 = "8u_2j-thz_6TDIiEZUXOWqwNNbwDoVbdXIwlWB5K91k";
}

3、消息主体的dto

/**
 * 消息模类主体数据
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class WxMessageDto implements Serializable {
    private String productName;
    private String price;
    private String orderNo;
    private String address;
    private LocalDateTime time;
}

4.3 前端配置

        用微信开发工具做前端测试:

        前端uni-app只需要发送对应请求订阅消息即可(官方规定不能页面加载触发订阅请求,只能点击某个事件触发订阅)

<template>
  <view class="content">
    <image class="logo" src="/static/logo.png"></image>
    <view class="text-area">
      <text class="title">{{title}}</text>
    </view>
    <view >
      <text class="title">{{title}}</text>
    </view>

    <view class="content">
      <button @click="requestSubscription">点击订阅消息</button>
    </view>
  </view>
</template>

<script>
  export default {
    data() {
      return {
        title: 'Hello2',
      }
    },
    onLoad() {
      const that = this; // 保存组件实例的引用
      wx.login({
        success (res) {
          console.log('登录ok!' + res.code);
          that.title = res.code;
        }
      });
    },
    methods: {
      requestSubscription() {
        console.log('点击了订阅1')
        wx.requestSubscribeMessage({
          tmplIds: ['8u_2j-thz_6TDIiEZUXOWqwNNbwDoVbdXIwlWB5K91k'], // 数组,最多3个订阅
          success (res) {
            console.log('订阅消息结果', res);
            // 处理订阅消息的结果
          },
          error(){
            console.error(222)
          }
        });
      }
    }
  }
</script>

<style>
	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
		user-select: text;
	}
</style>

        点击订阅即可,每次最多订阅3个(手机端是下面弹出订阅,同时可以选择订阅!此处用模拟器测试前端订阅)

4.4 后端发送消息推送测试

1、springboot测试

@SpringBootTest
@RunWith(SpringRunner.class)
public class AppTest {

    @Test
    public void shouldAnswerWithTrue() throws Exception {
        String openId = "otvf_5HrOcky90_sqST2kvKTvr1k"; // 用户的openId
        String templateId = WxConstants.WX_TEMPLATE_ID_ORDER1; // 模板消息Id

        WxMessageDto wxMessageDto = new WxMessageDto(); // 消息主体
        wxMessageDto.setProductName("黄铜");
        wxMessageDto.setPrice("36.8元");
        wxMessageDto.setOrderNo("2024032516282222hs9999");
        wxMessageDto.setAddress("四川省成都市双流区龙桥地铁站");
        wxMessageDto.setTime(LocalDateTime.now());

        boolean boo = WxMessageConfig.sendTemplateMsg(openId, templateId, wxMessageDto);
        System.out.println("=====================================");
        System.out.println(boo);
    }

2、控制台输出:

注意:报错就参考官方错误码。注意用户是否订阅,不然报错:

用户为订阅报错:

或者代码配置参数问题:

        result:{"errcode":47003,"errmsg":"argument invalid! data.character_string22.value rid: 66012b9d-00baed03-2e813aea"

发送成功字样 errcode:0 errmsg:ok

3、微信的服务通知提醒

要使用`RestTemplate`来实现微信小程序服务通知,你需要先获取access_token,然后使用该access_token发送模板消息。 下面是一个使用`RestTemplate`发送微信小程序服务通知的示例代码: ```java RestTemplate restTemplate = new RestTemplate(); // 获取access_token String appId = "YOUR_APP_ID"; String appSecret = "YOUR_APP_SECRET"; String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret; ResponseEntity<AccessTokenResponse> accessTokenResponse = restTemplate.getForEntity(accessTokenUrl, AccessTokenResponse.class); String accessToken = accessTokenResponse.getBody().getAccess_token(); // 发送模板消息 String sendUrl = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=" + accessToken; WxOpenTemplateMessageRequest request = new WxOpenTemplateMessageRequest(); request.setTouser("OPENID"); request.setTemplate_id("TEMPLATE_ID"); // 设置模板消息参数 // request.addData("keyword1", "VALUE1"); // request.addData("keyword2", "VALUE2"); // ... HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<WxOpenTemplateMessageRequest> entity = new HttpEntity<>(request, headers); ResponseEntity<SendTemplateMessageResponse> sendResponse = restTemplate.postForEntity(sendUrl, entity, SendTemplateMessageResponse.class); if (sendResponse.getStatusCode() == HttpStatus.OK) { SendTemplateMessageResponse sendResult = sendResponse.getBody(); if (sendResult.getErrcode() == 0) { // 发送成功 } else { // 发送失败 } } else { // 请求失败 } ``` 在上面的代码中,首先使用`RestTemplate`获取access_token,然后构建模板消息请求`WxOpenTemplateMessageRequest`,设置相应的参数,包括touser(接收用户的openid)、template_id(模板ID)和模板消息的具体参数。 然后,通过`RestTemplate`发送POST请求,将模板消息请求作为请求体发送到指定的URL。最后,根据响应结果判断发送是否成功。 请根据你的实际情况替换相应的参数,例如`YOUR_APP_ID`、`YOUR_APP_SECRET`、`OPENID`和`TEMPLATE_ID`。 希望对你有所帮助!如果还有其他问题,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值