微信小程序--订阅消息

更新:

关于小程序订阅消息之一次性订阅:
一次性订阅是指授权一次方可接收一次消息;这个最好的应用场景就是自己给自己发送消息,比如订单,当自己下单成功时,调用此接口,会在微信服务消息收到下单成功通知等具体详情。 如果是给别人发,一次性订阅就不适合,类似你想给某个人发送消息,那你还得提前跟他说你进小程序授权一下消息模板,不然就收不到消息.....WTF....这样就很鸡肋! 一次性消息订阅就是一对一模式,授权一次才能接收到一次消息,如果你发送了两条消息,但对方只授权一次,那他也只能接收一次消息。

微信小程序之订阅消息(一次性订阅示例)

在这里插入图片描述

第一步. 订阅消息模板

在这里插入图片描述

可选公共模板,如果不满足可以自己申请;
记住模板Id,之后需要用到。

第二步. 调用微信订阅消息服务:

登录成功时调用微信订阅消息服务(也可以用在发送方法里边,我想的是登录成功后提示一次就行):

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

第三步 获取用户OpenId

openId:微信编码,唯一标识,消息发送给谁就填谁的openId。
我的思路是登录成功之后就调用接口获取到用户openid,之后存到数据库对应用户,用的时候直接取;

要获取openid就得先获取授权code,微信有接口:
1.前端:
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后端:
@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;
}
我的做法:

在用户登录时,就主动获取code和用户id发送到后台获取到openid,根据用户id将openid存到对应数据库,用的时候取出来。

第四步 发送消息

1.前端:
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) {
    
    
		  	//成功
		  }
		})

其中,data对应模板:
在这里插入图片描述

2.java后端:
@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("消息推送失败");

	}

}

其中getToken方法:

 /**
     * @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;
        }
    }

至此,消息发送成功!


注:java后台用到的工具类

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;
	}
}

猜你喜欢

转载自blog.csdn.net/sanmuO/article/details/119185854