Teach you step by step how to implement a WeChat applet to push one-time subscription messages to specific users

Mini program and public account preparation

Currently there is aWeChat certifiedsubscription account Type public account, a WeChat authentication applet, the applet and the public account are related to each other. It is unclear whether WeChat authentication or a specific type is required, because no type mismatch or related problems have been encountered so far, and there are fewer restrictions on sending one-time subscription messages to WeChat mini programs

Insert image description here
Insert image description here
Insert image description here

What is mini program subscription message?

1. Function introduction

  • Subscription message push location: Service notification
    Insert image description here

  • Subscription message delivery conditions: Users subscribe independently
    Insert image description here

  • Subscription message card jump ability: Click to view details to jump to the page of the mini program
    Insert image description here

2. Message type

  • One-time subscription message (Message type implemented in this article)
    One-time subscription message is used to solve After the user uses the mini program, there will be notification issues in subsequent service sessions. After the user subscribes, the developer can send a corresponding service message without time limit; each message can be subscribed or unsubscribed separately.

  • Long-term subscription messages
    One-time subscription messages can meet the needs of most service scenarios of mini programs, but there are scenarios in the offline public service field that one-time subscriptions cannot meet, such as flight delays. , message reminders need to be sent multiple times based on real-time flight dynamics. To facilitate service, we provide long-term subscription messages. After a user subscribes once, developers can send multiple messages over a long period of time.

    Currently, long-term subscription information is only open to offline public services such as government affairs and people's livelihood, medical care, transportation, finance, education, etc., and will gradually support other offline public services in the future.

  • Device subscription message
    Device subscription message is a special type of subscription message. It is a long-term subscription message type and requires "device access" to be completed before it can be used.

    Device subscription messages are used to send message notifications to users when the device triggers certain events that require manual intervention (such as device failure, insufficient device supplies, etc.). See the device subscription message documentation for details.

For detailed introduction, please read the official documents yourself:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html

Implementation process

1. Selection of subscription message template

  • Log in to the WeChat public platform of the mini program and click on the function - Subscribe to messages

    Insert image description here

  • Click on the public template library to search and select the template you need.

    Insert image description here

  • Only 5 keywords can be selected. Enter the scene description and click Submit.

    Insert image description here

  • If you do not have the keywords you want, click点击申请 on the page to apply for the keywords you need. Note that there are 5 application opportunities every month. The keywords you apply for are the keywords you want to add. Do not apply again if there are some in the original template. After the application is approved, click "Select Template" to use the original keywords and Keywords for your application to be approved

    Insert image description here

Insert image description here

  • After selecting the template keywords and confirming submission, it will be available under我的模板
    Insert image description here
  • Click Details to see what parameters are required to send subscription messages using this template.
    Insert image description here

2. The docking brings up the mini program login pop-up window, parses to obtain the user's openId, saves the openId to the database, and associates it with user information or adds a field to the user table.

  • Mini program partially implemented

Official documentation:https://uniapp.dcloud.net.cn/api/plugins/login.html

uni.login({
    
    
  success: (result) => {
    
    
  	//保存获取到的code
    this.jsCode = result.code; 
    request({
    
    
      url: '后台接口地址',
      method: "POST",
      data: {
    
     code: result.code },
    })
      .then((res) => {
    
    
        this.openid = res.data.openid;
        this.session_key = res.data.session_key;
      })
      .catch((err) => {
    
    });
  },
  fail: (error) => {
    
    },
});
  • Backend partial implementation

Official documentation:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html

// 对传入code进行解密获取openid
LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("appid",appid);
params.add("secret",secret);
// 小程序调接口传的code
params.add("js_code",code);
params.add("grant_type","authorization_code");

String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&js_code="+code+"&grant_type=authorization_code";
String result = restTemplate.getForObject(url, String.class);
JSONObject jsonObject = JSON.parseObject(result);

Map<String, String> map = new HashMap<>();
try {
    
    
    map.put("openid", jsonObject.get("openid").toString());
    map.put("session_key", jsonObject.get("session_key").toString());
    log.info("code解密成功");
} catch (Exception e){
    
    
    log.error("code解析失败,"+jsonObject.getString("errmsg"));
    throw new RuntimeException("code解析失败,"+jsonObject.getString("errmsg"));
}
return map;

3. Guide users to actively authorize subscription messages to be sent

  • Create a new file in the mini programappletAuthorize.jsFile

Official documentation:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/subscribe-message/wx.requestSubscribeMessage.html

import Vue from 'vue'

const templateIds = [
	// 审批结果通知
	'审批结果通知模板id',
	// 领用单领用通知
	'领用单领用通知模板id',
	// 待审核通知
	'待审核通知模板id',
	// 数据报表生成通知
	'数据报表生成通知模板id',
	// 工单完成提醒
	'工单完成提醒模板id'
]

const appletAuthorize = () => {
    
    
	let tmplIds = []
	uni.getStorage({
    
    
		key: "currAuthorizeStep",
		success: ({
     
     
			data
		}) => {
    
    
			console.log("currAuthorizeStep", data);
			let temp = data
			for (var i = 0; i < 3; i++) {
    
    
				if (temp === templateIds.length) {
    
    
					temp = 0
				}
				tmplIds.push(templateIds[temp])
				temp++
			}
			uni.setStorage({
    
    
		 	key: "currAuthorizeStep",
				data: temp,
				success: (result) => {
    
    },
				fail: (error) => {
    
    },
			});
			if (tmplIds.length === 0) {
    
    
				return
			}

			wx.requestSubscribeMessage({
    
    
				tmplIds: tmplIds,
				success(res) {
    
    
					console.log("订阅消息唤起成功 =====>", res)
				},
				fail(err) {
    
    
					console.log("订阅消息唤起失败 =====>", err)
				}
			})
		},
		fail: (error) => {
    
    },
	});
};

Vue.prototype.$appletAuthorize = appletAuthorize

export default appletAuthorize;

Notice:

(1) setStorage when logging in

uni.setStorage({
    
    
  key: "currAuthorizeStep",
  data: 0,
  success: (result) => {
    
    },
  fail: (error) => {
    
    },
});

(2) Use templateIds to define the template IDs, and obtain three authorizations each time. This is because the ID of the message template subscribed to by wx.requestSubscribeMessage can only be passed at most three at a time, otherwise the subscription will fail.

  • Add this.$appletAuthorize()
    can only be
    in the @click method on the mini program page. Note:
    (1) The user must authorize the subscription message before the subscription can be sent to the user. Message
    (2) The subscription message interface can be called up only after the user clicks or initiates a payment callback. That is to say, the subscription authorization method cannot be called as soon as you enter the page. It needs to be used together with click event binding

4. The subscription message template is available, the user openId is available, and the user subscription message authorization is available. The next step is to send the subscription message.

官方文档:
(1)https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-message-management/subscribe-message/sendMessage.html
(2)https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

Parameter splicing tool class

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;

/**
 * 发送订阅消息参数整合
 *
 * @author Administrator
 */
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Slf4j
public class AppletParamUtil {
    
    

    /**
     * 待审核通知参数
     * @param thing1Value
     * @param thing11Value
     * @param thing12Value
     * @param time4Value
     * @param thing10Value
     * @return
     */
    public static Map<String, Object> getNeedConfirmParam (String thing1Value,
                                                           String thing11Value,
                                                           String thing12Value,
                                                           String time4Value,
                                                           String thing10Value) {
    
    

        Map<String, Object> objMap = new HashMap<>(5);
        Map<String, String> map = new HashMap<>(1);
        // 申请人
        map.put("value", thing1Value);
        objMap.put("thing1", map);
        // 申请人部门
        map = new HashMap<>(1);
        map.put("value", thing11Value);
        objMap.put("thing11", map);
        // 申请人工种
        map = new HashMap<>(1);
        map.put("value", thing12Value);
        objMap.put("thing12", map);
        // 申请时间
        map = new HashMap<>(1);
        map.put("value", time4Value);
        objMap.put("time4", map);
        // 申请物品
        map = new HashMap<>(1);
        map.put("value", thing10Value);
        objMap.put("thing10", map);

        return objMap;
    }
    
    /**
     * 数据报表生成通知
     * @param thing1Value
     * @param thing2Value
     * @return
     */
    public static Map<String, Object> getDataReportParam (String thing1Value, String thing2Value) {
    
    

        Map<String, Object> objMap = new HashMap<>(2);
        Map<String, String> map = new HashMap<>(1);
        // 报表名称
        map.put("value", thing1Value);
        objMap.put("thing1", map);
        // 数据统计周期
        map = new HashMap<>(1);
        map.put("value", thing2Value);
        objMap.put("thing2", map);

        return objMap;
    }
}

Subscription message sending tool class

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.ruoyi.RemoteSysConfigService;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.SysUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 发送小程序信息
 *
 * @author Administrator
 */
@Component
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Slf4j
public class AppletMsgSendUtil {
    
    

    private final RestTemplate restTemplate;

    private final StringRedisTemplate redisTemplate;


    /**
     * 发送小程序订阅信息
     * @param templateId    所需下发的订阅模板id
     * @param page          点击模板卡片后的跳转页面
     * @param data          模板内容
     * @return
     */
    public void msgSend(String templateId, String page, Map<String, Object> data) {
    
    
        try {
    
    
            
            //region 获取access_token
            String accessToken = getAppletToken();
            //endregion

            //region 推送小程序信息
            String msgUrl = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
            // 参数处理
            Map<String, Object> params = new HashMap<>(6);
            params.put("touser", openId);
            params.put("template_id", templateId);
            params.put("page", page);
            params.put("lang", "zh_CN");
            params.put("miniprogram_state", "formal");
            params.put("data", data);
            String jsonData = JSONUtils.toJSONString(params);
            HttpEntity<String> request = new HttpEntity<>(jsonData);
            String msgResult = restTemplate.postForObject(msgUrl, request, String.class);
            JSONObject msgResultObject = JSONUtil.parseObj(msgResult);

            if (!"0".equals(msgResultObject.get("errcode").toString())) {
    
    
                throw new RuntimeException("发送订阅消息失败," + msgResultObject.get("errmsg"));
            }
            //endregion
        } catch (Exception e) {
    
    
            throw new RuntimeException("发送订阅消息失败," + e);
        }
        //endregion
    }

    /**
     * 获取小程序token
     * @return
     */
    public String getAppletToken () {
    
    
        // 先从缓存查看有没有
        String appletToken = redisTemplate.opsForValue().get("AppletToken");
        if (!StringUtil.isBlank(appletToken)) {
    
    
            return appletToken;
        }
        
        //设置查询参数与请求url
        MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
        queryParams.add("appid", appid);
        queryParams.add("secret", secret);
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
        UriComponentsBuilder tokenBuilder = UriComponentsBuilder.fromHttpUrl(tokenUrl).queryParams(queryParams);
        //获取token
        String tokenResult = restTemplate.getForObject(tokenBuilder.toUriString(), String.class);
        JSONObject tokenObject = JSONUtil.parseObj(tokenResult);
        appletToken = tokenObject.getStr("access_token");
        if (StringUtil.isBlank(appletToken)) {
    
    
            throw new RuntimeException("小程序token获取失败," + tokenObject.getStr("errmsg"));
        }
        //将token存到redis,有效期100分钟。官方接口返回的token有效期120分钟
        redisTemplate.opsForValue().set("AppletToken", appletToken);
        redisTemplate.expire("AppletToken", 100, TimeUnit.MINUTES);

        return appletToken;
    }

}

usage

// 发送消息通知领取人已领取物品
Map<String, Object> objMap = AppletParamUtil.getDataReportParam(thing1Value,thing2Value);

msgSendUtil.msgSend(模板id, 需要跳转的小程序页面, objMap);

Note: Each parameter of the method in the parameter splicing tool class is determined based on the template. The tool class method has as many parameters as the template has.
Insert image description here

This is the effect of successfully sending the subscription message in the end.
Insert image description here

In addition, attach the APIPost subscription message sending calling method. Please refer to the official document posted above for the meaning of the parameters.

url:https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=你的token
method:POST
body:
{ “touser”: “”,
“template_id”: “”,
“page”: “”,
“lang”:“zh_CN”,
“miniprogram_state”: “formal”,
“data”: {} }

Insert image description here

If you don’t understand anything, go to the WeChat open community and ask or post. https://developers.weixin.qq.com/community/develop/mixflow

参考:
(1)https://developers.weixin.qq.com/community/develop/doc/0008aa1fd40ec80b4710e9b2260000
(2)https://developers.weixin.qq.com/community/develop/doc/000ce8a9298950338310bc75966800

おすすめ

転載: blog.csdn.net/weixin_46099269/article/details/132033003
おすすめ