当前位置:   article > 正文

微信小程序--订阅消息_微信小程序订阅消息

微信小程序订阅消息

更新:

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

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

在这里插入图片描述

第一步. 订阅消息模板

在这里插入图片描述

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

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

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

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

第三步 获取用户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)
    }
  }
})

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
我的做法:

在用户登录时,就主动获取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) {
		  	//成功
		  }
		})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

其中,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("消息推送失败");

	}

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

其中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;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

至此,消息发送成功!


注: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;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号