我姓焦 發表於 2023-4-3 18:06:00

微信小程序订阅消息开发指南(java)

<h1 id="微信小程序订阅消息开发指南java">微信小程序订阅消息开发指南(java)</h1>
<h2 id="第一步-准备阶段">第一步 准备阶段</h2>
<p>1、<strong>你得有一个小程序</strong>,<strong>并且认证了</strong>,<strong>个人的也行</strong></p>
<p>2、<strong>开通订阅消息</strong></p>
<blockquote>
<p><code>小程序后台</code>-&gt;<code>功能</code>-&gt;<code>订阅消息</code></p>
</blockquote>
<p><img src="https://img2023.cnblogs.com/blog/1473548/202304/1473548-20230403180329928-2092365160.png"></p>
<p>3、<strong>公共模板库选择一个模板</strong></p>
<blockquote>
<p>选择的时候,选择你需要的字段,因为字段有限制</p>
</blockquote>
<p><img src="https://img2023.cnblogs.com/blog/1473548/202304/1473548-20230403180251992-1269264079.png"></p>
<p><strong>4、我的模板点击详情</strong></p>
<blockquote>
<p>详情内容,模板 id 都是需要提供个服务端开发人员的</p>
</blockquote>
<p><img src="https://img2023.cnblogs.com/blog/1473548/202304/1473548-20230403180301152-1244374.png"></p>
<h2 id="第二步-编码阶段">第二步 编码阶段</h2>
<h3 id="小程序端">小程序端</h3>
<blockquote>
<p>小程序消息订阅,需要用户确认</p>
</blockquote>
<p>1、首先小程序授权登陆获取 <code>code</code></p>
<blockquote>
<p>官网示例:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html</p>
</blockquote>
<pre><code class="language-javascript">wx.login({
success (res) {
    if (res.code) {
      //发起网络请求
      wx.request({
      url: 'https://example.com/onLogin',
      data: {
          code: res.code
      }
      })
    } else {
      console.log('登录失败!' + res.errMsg)
    }
}
})
// 结果 {errMsg: "login:ok", code: "0a3kK4Ga10Gk3F0oBAHa1mGyRl3kK4Gd"}
</code></pre>
<blockquote>
<p>uni-App 示例:https://uniapp.dcloud.net.cn/api/plugins/login.html#login</p>
</blockquote>
<pre><code class="language-javascript">uni.login({
    provider: 'weixin', //使用微信登录
    success: function (loginRes) {
      console.log(loginRes)
    }
});
// 结果 {errMsg: "login:ok", code: "0a3kK4Ga10Gk3F0oBAHa1mGyRl3kK4Gd"}
</code></pre>
<p>2、将 <code>code</code> 传给服务端 获取用户唯一标识 <code>openId</code></p>
<p>3、通过代码起小程序消息订阅界面、用户点击确定ok,小程序工作结束</p>
<p>官方示例:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/subscribe-message/wx.requestSubscribeMessage.html</p>
<p><code>tmplIds</code> 填写模板 id 即可,最多三个</p>
<pre><code class="language-javascript">wx.requestSubscribeMessage({
tmplIds: [''],
success (res) {
      console.log(res)
}
})
</code></pre>
<p>4、注意事项:</p>
<blockquote>
<p>避免重复拉起用户订阅通知,可以通过微信提供的 <code>getSetting</code> 判断用户是否订阅了,如果没有就拉起。</p>
<p>注意下面是用<code>uniapp</code>写的,方法前缀是<code>uni</code> 如果你小程序代码记得修改 <code>wx</code> 以及提示组件</p>
<p>到此小程序工作结束</p>
</blockquote>
<pre><code class="language-javascript">getSetting() {
    uni.getSetting({
      withSubscriptions: true, // 获取用户订阅状态
      success(res) {
            // false 表示用户未订阅改消息
            if (!res.subscriptionsSetting.mainSwitch) {
                this.subscribeMessage();
            } else {
                uni.showToast({
                  title: '已订阅',
                  icon: 'none'
                })
            }
      }
    })
},
subscribeMessage() {
    uni.requestSubscribeMessage({
      tmplIds: ['模板id'],
      success(res) {
            if (res.errMsg === 'requestSubscribeMessage:ok') {
                uni.showToast({
                  title: '订阅成功',
                  icon: 'none'
                })
            }
      }
    })
}   
</code></pre>
<h4 id="服务端">服务端</h4>
<blockquote>
<p>微信小程序的 <code>appid</code> 和<code>secret</code> <code>小程序后台</code>-&gt;<code>开发</code>-&gt;<code>开发管理</code>-&gt;<code>开发设置</code>-&gt;<code>开发者 ID</code></p>
</blockquote>
<p><strong>注意事项</strong>:</p>
<ol>
<li><code>http</code> 请求这里使用 apache 的工具类,你也可以使用别的</li>
<li>微信消息模板字段 <code>thing</code> 字段有长度限制20,超过会失败</li>
<li>以下演示代码,生产环境还需进行优化</li>
</ol>
<p>1、通过 code 获取用户 open id 官网文档</p>
<pre><code class="language-java"> public String getOpenId(String code) throws IOException {
      CloseableHttpClient httpClient = HttpClientBuilder.create().build();
      Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();
      params.put("appid", Constants.APPLET_APP_ID);
      params.put("secret", Constants.APPLET_SECRET);
      params.put("js_code", code);
      params.put("grant_type", "authorization_code");

      String url = handleParams("https://api.weixin.qq.com/sns/jscode2session", params);
      HttpGet httpGet = new HttpGet(url);

      CloseableHttpResponse response = httpClient.execute(httpGet);
      HttpEntity entity = response.getEntity(); // 响应结果
      return EntityUtils.toString(entity, CharSetType.UTF8.getType());
}

public static void main(String[] args) throws IOException {
      HttpUtils httpUtils = new HttpUtils();
      String token = httpUtils.getToken();
      System.out.println(token);
}


</code></pre>
<p>响应结果:</p>
<pre><code class="language-json">{"access_token":"67_u22CQaWq22222222Q4griDE6kiT5hwg7jVxedn8J9te17Az1oWGGxPgB22222229Y4Wm6h_Yzci7-FSDjeH8YG6DsCOYrQXJCWsPXhT6nWbKIWCXfABACID","expires_in":7200}
</code></pre>
<p>2、通过 <code>appid</code> 和<code>secret</code> 获取 token 超时 7200 秒 可 redis 缓存 官方文档</p>
<pre><code class="language-java">public String getToken() throws IOException {
      CloseableHttpClient httpClient = HttpClientBuilder.create().build();
      Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();
      params.put("appid", Constants.APPLET_APP_ID);
      params.put("secret", Constants.APPLET_SECRET);
      params.put("grant_type", "client_credential");

      String url = handleParams("https://api.weixin.qq.com/cgi-bin/token", params);
      HttpGet httpGet = new HttpGet(url);

      CloseableHttpResponse response = httpClient.execute(httpGet);
      HttpEntity entity = response.getEntity(); // 响应结果

      return EntityUtils.toString(entity, CharSetType.UTF8.getType());
}
</code></pre>
<p>3、指定用户推送消息结束 官方文档</p>
<pre><code class="language-java">public String pushMsg(String token) throws IOException {

      CloseableHttpClient httpClient = HttpClientBuilder.create().build();
      Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();

      // 处理微信推送数据结构
      JSONObject mapData = new JSONObject();
      Map&lt;String, Object&gt; map1 = new HashMap&lt;&gt;();
      map1.put("value", "任务名称");
      mapData.put("thing2", map1);

      Map&lt;String, Object&gt; map2 = new HashMap&lt;&gt;();
      map2.put("value", "2022-04-03 10:00:00");
      mapData.put("time3", map2);

      Map&lt;String, Object&gt; map3 = new HashMap&lt;&gt;();
      map3.put("value", "描述信息");
      mapData.put("thing4", map3);

      Map&lt;String, Object&gt; map4 = new HashMap&lt;&gt;();
      map4.put("value", "备注信息");
      mapData.put("thing10", map4);

      Map&lt;String, Object&gt; map5 = new HashMap&lt;&gt;();
      map5.put("value", "任务来源");
      mapData.put("thing11", map5);

      params.put("template_id", "templateId");// 模板 id
      params.put("touser", "openId"); // open id
      params.put("data", mapData); // 数据
      params.put("page", "page"); // 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
      params.put("miniprogram_state", "trial"); //developer为开发版;trial为体验版;formal为正式版;默认为正式版
      params.put("lang", "zh_CN"); //

      HttpPost httpPost = new HttpPost("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + token);
      httpPost.addHeader("ContentTyp", "application/json");

      // 参数转 JSON 格式
      String json = objToStr(params);
      StringEntity stringEntity = new StringEntity(json, CharSetType.UTF8.getType());
      stringEntity.setContentEncoding(CharSetType.UTF8.getType());
      httpPost.setEntity(stringEntity);

      CloseableHttpResponse response = httpClient.execute(httpPost);
      HttpEntity entity = response.getEntity(); // 响应结果
      return EntityUtils.toString(entity, CharSetType.UTF8.getType());
    }
</code></pre>
<p>4、完整代码</p>
<pre><code class="language-java">import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.chenlijia1111.utils.core.enums.CharSetType;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.jeecg.modules.video.utitls.Constants;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @description:
* @author: Mr.Fang
* @create: 2023-04-03 17:06
**/

public class HttpUtils {

    /**
   * description: 获取token,返回结果为 JSON 自行转 map
   * create by: Mr.Fang
   *
   * @return: java.lang.String
   * @date: 2023/4/3 17:46
   */
    public String getToken() throws IOException {
      CloseableHttpClient httpClient = HttpClientBuilder.create().build();
      Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();
      params.put("appid", Constants.APPLET_APP_ID);
      params.put("secret", Constants.APPLET_SECRET);
      params.put("grant_type", "client_credential");

      String url = handleParams("https://api.weixin.qq.com/cgi-bin/token", params);
      HttpGet httpGet = new HttpGet(url);

      CloseableHttpResponse response = httpClient.execute(httpGet);
      HttpEntity entity = response.getEntity(); // 响应结果

      return EntityUtils.toString(entity, CharSetType.UTF8.getType());
    }

    /**
   * description: 获取 open id,返回结果为 JSON 自行转 map
   * create by: Mr.Fang
   *
   * @param:
   * @return: java.lang.String
   * @date: 2023/4/3 17:46
   */
    public String getOpenId(String code) throws IOException {
      CloseableHttpClient httpClient = HttpClientBuilder.create().build();
      Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();
      params.put("appid", Constants.APPLET_APP_ID);
      params.put("secret", Constants.APPLET_SECRET);
      params.put("js_code", code);
      params.put("grant_type", "authorization_code");

      String url = handleParams("https://api.weixin.qq.com/sns/jscode2session", params);
      HttpGet httpGet = new HttpGet(url);

      CloseableHttpResponse response = httpClient.execute(httpGet);
      HttpEntity entity = response.getEntity(); // 响应结果
      return EntityUtils.toString(entity, CharSetType.UTF8.getType());
    }

    /**
   * description: 消息推送 返回结果为 JSON 自行转 map;token 调用 getToken获取
   * create by: Mr.Fang
   *
   * @param:
   * @return: java.lang.String
   * @date: 2023/4/3 17:46
   */
    public String pushMsg(String token) throws IOException {

      CloseableHttpClient httpClient = HttpClientBuilder.create().build();
      Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();

      // 处理微信推送数据结构
      JSONObject mapData = new JSONObject();
      Map&lt;String, Object&gt; map1 = new HashMap&lt;&gt;();
      map1.put("value", "任务名称");
      mapData.put("thing2", map1);

      Map&lt;String, Object&gt; map2 = new HashMap&lt;&gt;();
      map2.put("value", "2023-04-03 12:00:00");
      mapData.put("time3", map2);

      Map&lt;String, Object&gt; map3 = new HashMap&lt;&gt;();
      map3.put("value", "描述信息");
      mapData.put("thing4", map3);

      Map&lt;String, Object&gt; map4 = new HashMap&lt;&gt;();
      map4.put("value", "备注系信息");
      mapData.put("thing10", map4);

      Map&lt;String, Object&gt; map5 = new HashMap&lt;&gt;();
      map5.put("value", "抖音");
      mapData.put("thing11", map5);

      params.put("template_id", "templateId");// 模板 id
      params.put("touser", "openId"); // open id
      params.put("data", mapData); // 数据
      params.put("page", "page"); // 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转
      params.put("miniprogram_state", "trial"); //developer为开发版;trial为体验版;formal为正式版;默认为正式版
      params.put("lang", "zh_CN"); //

      HttpPost httpPost = new HttpPost("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + token);
      httpPost.addHeader("ContentTyp", "application/json");

      // 参数转 JSON 格式
      String json = objToStr(params);
      StringEntity stringEntity = new StringEntity(json, CharSetType.UTF8.getType());
      stringEntity.setContentEncoding(CharSetType.UTF8.getType());
      httpPost.setEntity(stringEntity);

      CloseableHttpResponse response = httpClient.execute(httpPost);
      HttpEntity entity = response.getEntity(); // 响应结果
      return EntityUtils.toString(entity, CharSetType.UTF8.getType());
    }


    /**
   * description: 对象转 字符串
   * create by: Mr.Fang
   *
   * @param:
   * @return: java.lang.String
   * @date: 2023/4/3 17:45
   */
    public static String objToStr(Object obj) {

      ObjectMapper objectMapper = new ObjectMapper();
      if (Objects.nonNull(obj)) {
            try {
                String jsonStr = objectMapper.writeValueAsString(obj);
                return jsonStr;
            } catch (JsonProcessingException var2) {
                var2.printStackTrace();
            }
      }

      return null;
    }

    /**
   * description: map 转 URL 地址拼接
   * create by: Mr.Fang
   *
   * @param:
   * @return: java.lang.String
   * @date: 2023/4/3 17:45
   */
    public String handleParams(String url, Map&lt;String, Object&gt; params) {
      if (params.size() != 0) {
            Set&lt;Map.Entry&lt;String, Object&gt;&gt; entries = params.entrySet();
            String paramsString = entries.stream().map((e) -&gt; {
                try {
                  StringBuilder sb = new StringBuilder();
                  sb.append(URLEncoder.encode(e.getKey(), CharSetType.UTF8.getType()));
                  sb.append("=");
                  if (Objects.nonNull(e.getValue())) {
                        sb.append(URLEncoder.encode(e.getValue().toString(), CharSetType.UTF8.getType()));
                  }

                  return sb.toString();
                } catch (UnsupportedEncodingException var2) {
                  var2.printStackTrace();
                  return null;
                }
            }).collect(Collectors.joining("&amp;"));
            return url + "?" + paramsString;
      }
      return url;
    }


}

</code></pre>


</div>
<div id="MySignature" role="contentinfo">
    哇!又赚了一天人民币<br><br>
来源:https://www.cnblogs.com/bxmm/p/17283908.html
頁: [1]
查看完整版本: 微信小程序订阅消息开发指南(java)