WeChat Mini Program--Subscribe to Messages

renew:

Regarding one-time subscription of mini program subscription messages:
One-time subscription refers to authorizing one time to receive a message; the best application scenario is to send messages to yourself, such as orders. When you place an order successfully, call this interface, and you will receive the order success message in the WeChat service Notifications and other specific details. If you are sending it to others, a one-time subscription is not suitable. Similar to if you want to send a message to someone, you have to tell him in advance that you have to enter the mini program to authorize the message template, otherwise you will not receive the message... WTF....This is so useless! One-time message subscription is a one-to-one model. You can only receive one message once if you authorize it once. If you send two messages, but the other party only authorizes it once, then he can only receive the message once.

Subscription messages for WeChat mini program (one-time subscription example)

Insert image description here

Step 1. Subscribe to the message template

Insert image description here

Public templates are optional. If you are not satisfied, you can apply for it yourself;
Remember the template ID, you will need it later.

Step 2. Call the WeChat subscription message service:

When the login is successful, the WeChat subscription message service is called (it can also be used in the sending method. What I want is to prompt once after the login is successful):

uni.requestSubscribeMessage({
    
     //获取下发权限
	tmplIds: ['fWxR5XXXXXXXXXXXX'], //模板ID
	success(res) {
    
    
		console.log('已授权接收订阅消息')
 	}
  }); 
  //这里的tmplIds是消息模板集合,可放多个如:
 // tmplIds: ['fWxR5XXXXXXXXXXXXXXXXX','xxxxxxxxxxxxx'.....],

Step 3: Obtain user OpenId

openId: WeChat code, unique identifier, fill in the openId of whomever the message is sent to.
My idea is to call the interface to obtain the user's openid after successful login, and then save it to the database corresponding to the user, and retrieve it directly when using;

To obtain openid, you must first obtain the authorization code. WeChat has an interface:
1. Front end:
wx.login({
    
    
  success (res) {
    
    
    if (res.code) {
    
    
      //发起网络请求
      //使用 code 换取 openid 和 session_key 等信息
      //将code传到后台服务器获取openId
		wx.request({
    
    
		  url: 'https://test.com/getOpenId', //仅为示例,并非真实的接口地址
		  data: {
    
    
	          code: res.code
	        },
		  header: {
    
    
		    'content-type': 'application/json' // 默认值
		  },
		  success (res) {
    
    
		  	//成功获取到openid
		    console.log(res.data)
		  }
		})
    } else {
    
    
      console.log('登录失败!' + res.errMsg)
    }
  }
})

2.java backend:
@PostMapping(value="/getOpenId")
public String getOpenId(String code) throws Exception{
    
    
	String appId = "你的小程序AppId";
	String appSecret ="你的小程序AppSecret ";
	//微信小程序固定接口
	String WX_URL = "https://api.weixin.qq.com/sns/jscode2session?appid="+appId +"&secret="+appSecret+"&js_code="+code+"&grant_type=authorization_code";
	if(StringUtil.isEmpty(code)){
    
    
		//缺少参数code
		return null;
	}else {
    
    
		String requestUrl = WX_URL;
		// 发起GET请求获取凭证
		JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
		if (jsonObject != null) {
    
    
			try {
    
    
				//获取成功
				String openid = jsonObject.getString("openid");
				String sessionKey = jsonObject.getString("session_key");
			return openid;
			} catch (JSONException e) {
    
    
				//失败
				return null;
			}
		}else {
    
    
			//失败
			return null;
		}
	}
	return null;
}
My approach:

When the user logs in, the code and user ID are actively obtained and sent to the background to obtain the openid. The openid is stored in the corresponding database according to the user ID and taken out when used.

Step 4 Send message

1. Front end:
var Obj = {
    
    
	 "touser": openId,//接收人的openId
	  "template_id": "fWxR5XXXXXXXXXXX",//订阅消息模板ID
	  "page":"pages/business/business-audit/business-audit",//微信端收到消息时,点击进入的页面
	  "miniprogram_state":"trial",//这是代表体验版,上线需该为正式版(默认为正式版)
	  "lang":"zh_CN",//语言
	  "data": {
    
    
		  "thing6": {
    
    
			  "value": "外出报备审核"
		  },
		  "thing18": {
    
    
			  "value": "您有1条新的待审核数据"
		  },
		  "thing37": {
    
    
			  "value": myself.tools.getUserInfo().name //人名
		  } ,
		  "time38": {
    
    
			  "value": myself.tools.dateFormate(new Date(), "YYYY-MM-DD HH:mm:ss")//时间
		  }
	  }
	}
	var jsonData = JSON.stringify(Obj );
	wx.request({
    
    
		  url: 'https://test.com/gsendWxTempleMsg', //仅为示例,并非真实的接口地址
		 data:{
    
    
			jsonData:jsonData
			},
		  header: {
    
    
		    'content-type': 'application/json' // 默认值
		  },
		  success (res) {
    
    
		  	//成功
		  }
		})

Meanwhile,dataPicture board:
Insert image description here

2.java backend:
@PostMapping(value = "/wx/sendMessage")
public AjaxJson sendWxTempleMsg(String jsonData) throws Exception {
    
    
	if(StringUtil.isBlank(jsonData)){
    
    
		return error("消息推送失败,缺少消息模板信息");
	}
	String appId = "你的小程序AppId";
	String appSecret ="你的小程序AppSecret ";
	String ACCESS_TOKEN = getToken(appId, appSecret);//这里需要获取access_token

    String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="+ACCESS_TOKEN;
	
	// 发起请求,返回JSON字符串
	JSONObject jsonObject = CommonUtil.httpsRequest(url , "POST", jsonData);//官方文档指定POST方式发送

	if(jsonObject.get("errcode").equals("0")||jsonObject.get("errmsg").equals("ok")){
    
    
			return success("消息推送成功");
	}else{
    
    
			return error("消息推送失败");

	}

}

Among them getToken method:

 /**
     * @param appId
     * @param appSecret
     * @return
     */
    public static String getToken(String appId, String appSecret) {
    
    
         String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret+"";
        // logger.info(requestUrl);
        // 发起GET请求获取凭证
        JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
        if (jsonObject != null) {
    
    
            if (jsonObject.getString("errcode") == null) {
    
    
                return jsonObject.getString("access_token");
            } else {
    
    
                return null;
            }
        } else {
    
    
            return null;
        }
    }

At this point, the message was sent successfully!


Note: Tool classes used in java background

CommonUtil:

/**
 * 类名: CommonUtil.java</br> 
 * 描述: http请求工具类</br> 
 */
public class CommonUtil {
    
    

    private static Logger log = LoggerFactory.getLogger(CommonUtil.class);//日志类(可删除)

    /**
     * 发送https请求
     * @param requestUrl 请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr 提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
    
    
        JSONObject jsonObject = null;
        try {
    
    
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = {
    
     new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);

            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
    
    
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
    
    
                buffer.append(str);
            }

            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject = JSONObject.parseObject(buffer.toString());
        } catch (ConnectException ce) {
    
    
            log.error("连接超时:{}", ce);
        } catch (Exception e) {
    
    
            log.error("https请求异常:{}", e);
        }
        return jsonObject;
    }
    
    /**
	 * 发送https请求
	 * 
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式(GET、POST)
	 * @param outputStr
	 *            提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static AjaxJson httpsRequestStream(String requestUrl, String requestMethod, String outputStr,
			String basePath, Long id) {
    
    
		AjaxJson aj = new AjaxJson();
		try {
    
    
			// 创建SSLContext对象,并使用我们指定的信任管理器初始化
			TrustManager[] tm = {
    
     new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
			conn.setSSLSocketFactory(ssf);

			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			// 设置请求方式(GET/POST)
			conn.setRequestMethod(requestMethod);

			// 当outputStr不为null时向输出流写数据
			if (null != outputStr) {
    
    
				OutputStream outputStream = conn.getOutputStream();
				// 注意编码格式
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}
			InputStream inputStream = conn.getInputStream();
			
			String fileUrl = File.separator + "images" + File.separator + "standaqrcode" + File.separator + "stand" + id + ".jpg";
			String savePath = basePath + fileUrl;
			// System.out.println(savePath);
			aj = inputStreamToImage(inputStream, savePath, "jpg");
			inputStream.close();
			inputStream = null;
			conn.disconnect();
			// 从输入流读取返回内容
			aj.setSuccess(true);
			aj.put("data", fileUrl);
			return aj;
		} catch (ConnectException ce) {
    
    
			log.error("连接超时:{}", ce);
			aj.setSuccess(false);
			aj.setMsg("链接超时:" + ce);
			return aj;
		} catch (Exception e) {
    
    
			log.error("https请求异常:{}", e);
			aj.setSuccess(false);
			aj.setMsg("https请求异常:" + e);
			return aj;
		}
	}

	/**
	 * 将字符流转换为图片文件
	 * @param input 字符流
	 * @param savePath 图片需要保存的路径
	 * @param 类型  jpg/png等
	 * @return
	 */
	private static AjaxJson inputStreamToImage(InputStream input, String savePath, String type) {
    
    
		AjaxJson aj = new AjaxJson();
		try {
    
    
			File file = null;
			file = new File(savePath);
			String paramPath = file.getParent(); // 路径
			String fileName = file.getName(); //
			String newName = fileName.substring(0, fileName.lastIndexOf(".")) + "." + type;// 根据实际返回的文件类型后缀
			savePath = paramPath + File.separator + newName;
			if (!file.exists()) {
    
    
				File dirFile = new File(paramPath);
				dirFile.mkdirs();
			}
			file = new File(savePath);
			FileOutputStream output = new FileOutputStream(file);
			int len = 0;
			byte[] array = new byte[1024];
			while ((len = input.read(array)) != -1) {
    
    
				output.write(array, 0, len);
			}
			output.flush();
			output.close();
			aj.setSuccess(true);
			aj.setMsg("save success!");
		} catch (FileNotFoundException e) {
    
    
			e.printStackTrace();
			aj.setSuccess(false);
			aj.setMsg(e.getMessage());
		} catch (IOException e) {
    
    
			e.printStackTrace();
			aj.setSuccess(false);
			aj.setMsg(e.getMessage());
		}
		return aj;
	}
}

Guess you like

Origin blog.csdn.net/sanmuO/article/details/119185854