欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java實現微信公眾平臺發(fā)送模板消息的示例代碼

 更新時間:2019年09月06日 09:04:21   作者:Jello  
這篇文章主要介紹了java實現微信公眾平臺發(fā)送模板消息的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

最近開發(fā)公眾號項目,前端采用vue開發(fā),后臺使用java開發(fā),由于業(yè)務需求,需要實現公眾號向用戶發(fā)送重要的服務通知,提醒工作人員進行業(yè)務審核。這時候就需要用到微信平臺的模板消息,為了保證用戶不受到騷擾,在開發(fā)者出現需要主動提醒、通知用戶時,才允許開發(fā)者在公眾平臺網站中模板消息庫中選擇模板,選擇后獲得模板ID,再根據模板ID向用戶主動推送提醒、通知消息。常用的服務場景,如信用卡刷卡通知,商品下單成功、購買成功通知等。

獲取template_id(注意:僅微信開放平臺同事可獲?。?/p>

通過向微信公眾平臺申請模板,來獲取模板id,模板消息調用時主要需要模板ID和模板中各參數的賦值內容。請注意:
1.模板中參數內容必須以".DATA"結尾,否則視為保留字;
2.模板保留符號"{{ }}"

下圖是在微信測試公眾號申請模板

請求模板消息接口

1)微信網頁授權

 //前端發(fā)請請求
 this.axios.get('/wx/get_code_num').then((res) => {
  window.location.href = res.data;
 }).catch((error) => {
  console.log(error)
 });

 /**
  * 1.用戶同意授權,獲取code
  */
  @RequestMapping(value = "/get_code_num", method = RequestMethod.GET)
  public String getCode() throws UnsupportedEncodingException {
    return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + Constants.APPID + "&redirect_uri="
        + URLEncoder.encode("http://192.168.0.152:8085/wx/send_wx_msg", "UTF-8") + "&response_type=code&scope="
        + Constants.GRANTSCOPE + "&state=STATE#wechat_redirect";
  }  


2)獲取用戶openid

/**
 * 2.通過code換取網頁授權access_token及openid
 */
@RequestMapping(value = "/send_wx_msg", method = RequestMethod.GET)
public String sendWxMsg(String code) {
  String access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token";
  String accessTokenObj = HttpClientUtil.sendGet(access_token_url, "appid=" + Constants.APPID + "&secret="
      + Constants.APPSECRET + "&code=" + code + "&grant_type=authorization_code");
  JSONObject jsonToken = JSONObject.fromObject(accessTokenObj);

  String openId = null;
  if (StringUtils.isNotBlank(String.valueOf(jsonToken))) {
    openId = jsonToken.getString("openid");
  }
  logger.info("獲取openid,微信平臺接口返回{}", openId);
  return openId;
}

3)組裝、發(fā)送模板消息

import java.util.TreeMap;

public class WechatTemplate {

  private String touser;//用戶openid

  private String template_id;//模板ID

  private String url;//URL置空,則在發(fā)送后,點擊模板消息會進入一個空白頁面(ios),或無法點擊(android)

  private TreeMap<String, TreeMap<String, String>> data; //data數據

  public static TreeMap<String, String> item(String value, String color) {
    TreeMap<String, String> params = new TreeMap<String, String>();
    params.put("value", value);
    params.put("color", color);
    return params;
  }

  public TreeMap<String, TreeMap<String, String>> getData() {
    return data;
  }

  public void setData(TreeMap<String, TreeMap<String, String>> data) {
    this.data = data;
  }

  public String getTouser() {
    return touser;
  }

  public void setTouser(String touser) {
    this.touser = touser;
  }

  public String getTemplate_id() {
    return template_id;
  }

  public void setTemplate_id(String template_id) {
    this.template_id = template_id;
  }

  public String getUrl() {
    return url;
  }

  public void setUrl(String url) {
    this.url = url;
  }

  @Override
  public String toString() {
    return "WechatTemplate{" +
        "touser='" + touser + '\'' +
        ", template_id='" + template_id + '\'' +
        ", url='" + url + '\'' +
        ", data=" + data +
        '}';
  }
}
//微信模板接口
private final String SEND_TEMPLATE_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send";
//模板消息詳情跳轉URL
private static String url = "https://www.baidu.com/";

@RequestMapping(value = "/send_wx_msg", method = RequestMethod.GET)
public String sendWxMsg(String code) {
  String access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token";
  String accessTokenObj = HttpClientUtil.sendGet(access_token_url, "appid=" + Constants.APPID + "&secret="
      + Constants.APPSECRET + "&code=" + code + "&grant_type=authorization_code");
  JSONObject jsonToken = JSONObject.fromObject(accessTokenObj);

  String openId = null;
  if (StringUtils.isNotBlank(String.valueOf(jsonToken))) {
    openId = jsonToken.getString("openid");
  }
  logger.info("獲取openid,微信平臺接口返回{}", openId);

  String urlToken = "https://api.weixin.qq.com/cgi-bin/token";
  String tokenObj = HttpClientUtil.sendGet(urlToken, "grant_type=client_credential" + "&secret=" + Constants.APPSECRET + "&appid=" + Constants.APPID);
  JSONObject retToken = JSONObject.fromObject(tokenObj);
  String accessToken = String.valueOf(retToken.get("access_token"));
  logger.info("獲取access_token,微信平臺接口返回{}", accessToken);

  TreeMap<String, TreeMap<String, String>> params = new TreeMap<String, TreeMap<String, String>>();
  //根據具體模板參數組裝
  params.put("first", WechatTemplate.item("您的戶外旅行活動訂單已經支付完成,可在我的個人中心中查看", "#000000"));
  params.put("keyword1", WechatTemplate.item("發(fā)現尼泊爾—人文與自然的旅行圣地", "#000000"));
  params.put("keyword2", WechatTemplate.item("5000元", "#000000"));
  params.put("keyword3", WechatTemplate.item("2019.09.04", "#000000"));
  params.put("keyword4", WechatTemplate.item("5", "#000000"));
  params.put("remark", WechatTemplate.item("請屆時攜帶好身份證件準時到達集合地點,若臨時退改將產生相應損失,敬請諒解,謝謝!", "#000000"));
  WechatTemplate wechatTemplate = new WechatTemplate();
  wechatTemplate.setTemplate_id(Constants.TEMPLATEID);
  wechatTemplate.setTouser(openId);
  wechatTemplate.setUrl(url);
  wechatTemplate.setData(params);
  JSONObject json = JSONObject.fromObject(wechatTemplate);//將java對象轉換為json對象
  String sendData = json.toString();//將json對象轉換為字符串
  logger.info("板參數組裝{}", sendData);

  TreeMap<String, String> treeMap = new TreeMap<String, String>();
  treeMap.put("access_token", accessToken);
  String retInfo = HttpUtil.doPost(SEND_TEMPLATE_MESSAGE_URL, treeMap, sendData);
  logger.info("消息模板返回{}", retInfo);
  return retInfo;
}

請求的數據格式

{
  "data": {
    "first": {
      "color": "#000000",
      "value": "您的戶外旅行活動訂單已經支付完成,可在我的個人中心中查看"
    },
    "keyword1": {
      "color": "#000000",
      "value": "發(fā)現尼泊爾—人文與自然的旅行圣地"
    },
    "keyword2": {
      "color": "#000000",
      "value": "5000元"
    },
    "keyword3": {
      "color": "#000000",
      "value": "2019.09.04"
    },
    "keyword4": {
      "color": "#000000",
      "value": "5"
    },
    "remark": {
      "color": "#000000",
      "value": "請屆時攜帶好身份證件準時到達集合地點,若臨時退改將產生相應損失,敬請諒解,謝謝!"
    }
  },
  "template_id": "ZUMTnYtG0O4vZSv4bPTtWTOFZ2zirOjaM50GYywRRnA",
  "touser": "olv_asx8nmggCQEmAFNbQstx3xd0",
  "url": "https://www.baidu.com/"
}

微信平臺返回的結果:


微信公眾號通知消息


工具類:

 
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

public class HttpUtil {
  private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);
  protected static final String POST_METHOD = "POST";
  private static final String GET_METHOD = "GET";

  static {
    TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
      @Override
      public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        logger.debug("ClientTrusted");
      }

      @Override
      public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        logger.debug("ServerTrusted");
      }

      @Override
      public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[]{};
      }
    }};

    HostnameVerifier doNotVerify = (s, sslSession) -> true;

    try {
      SSLContext sc = SSLContext.getInstance("SSL", "SunJSSE");
      sc.init(null, trustAllCerts, new SecureRandom());
      HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
      HttpsURLConnection.setDefaultHostnameVerifier(doNotVerify);
    } catch (Exception e) {
      logger.error("Initialization https impl occur exception : {}", e);
    }
  }


  /**
   * 默認的http請求執(zhí)行方法
   *
   * @param url  url 路徑
   * @param method 請求的方法 POST/GET
   * @param map  請求參數集合
   * @param data  輸入的數據 允許為空
   * @return result
   */
  private static String HttpDefaultExecute(String url, String method, Map<String, String> map, String data) {
    String result = "";
    try {
      url = setParmas(url, map, null);
      result = defaultConnection(url, method, data);
    } catch (Exception e) {
      logger.error("出錯參數 {}", map);
    }
    return result;
  }

  public static String httpGet(String url, Map<String, String> map) {
    return HttpDefaultExecute(url, GET_METHOD, map, null);
  }

  public static String httpPost(String url, Map<String, String> map, String data) {
    return HttpDefaultExecute(url, POST_METHOD, map, data);
  }

  /**
   * 默認的https執(zhí)行方法,返回
   *
   * @param url  url 路徑
   * @param method 請求的方法 POST/GET
   * @param map  請求參數集合
   * @param data  輸入的數據 允許為空
   * @return result
   */
  private static String HttpsDefaultExecute(String url, String method, Map<String, String> map, String data) {
    try {
      url = setParmas(url, map, null);
      logger.info(data);
      return defaultConnection(url, method, data);
    } catch (Exception e) {
      logger.error("出錯參數 {}", map);
    }
    return "";
  }

  public static String doGet(String url, Map<String, String> map) {
    return HttpsDefaultExecute(url, GET_METHOD, map, null);
  }

  public static String doPost(String url, Map<String, String> map, String data) {
    return HttpsDefaultExecute(url, POST_METHOD, map, data);
  }

  /**
   * @param path  請求路徑
   * @param method 方法
   * @param data  輸入的數據 允許為空
   * @return
   * @throws Exception
   */
  private static String defaultConnection(String path, String method, String data) throws Exception {
    if (StringUtils.isBlank(path)) {
      throw new IOException("url can not be null");
    }
    String result = null;
    URL url = new URL(path);
    HttpURLConnection conn = getConnection(url, method);
    if (StringUtils.isNotEmpty(data)) {
      OutputStream output = conn.getOutputStream();
      output.write(data.getBytes(StandardCharsets.UTF_8));
      output.flush();
      output.close();
    }
    if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
      InputStream input = conn.getInputStream();
      result = IOUtils.toString(input, StandardCharsets.UTF_8);
      input.close();
      conn.disconnect();
    }
//    log.info(result);
    return result;
  }

  /**
   * 根據url的協議選擇對應的請求方式
   *
   * @param url  請求路徑
   * @param method 方法
   * @return conn
   * @throws IOException 異常
   */
  //待改進
  protected static HttpURLConnection getConnection(URL url, String method) throws IOException {
    HttpURLConnection conn;
    if (StringUtils.equals("https", url.getProtocol())) {
      conn = (HttpsURLConnection) url.openConnection();
    } else {
      conn = (HttpURLConnection) url.openConnection();
    }
    if (conn == null) {
      throw new IOException("connection can not be null");
    }
    conn.setRequestProperty("Pragma", "no-cache");// 設置不適用緩存
    conn.setRequestProperty("Cache-Control", "no-cache");
    conn.setRequestProperty("Connection", "Close");// 不支持Keep-Alive
    conn.setUseCaches(false);
    conn.setDoOutput(true);
    conn.setDoInput(true);
    conn.setInstanceFollowRedirects(true);
    conn.setRequestMethod(method);
    conn.setConnectTimeout(8000);
    conn.setReadTimeout(8000);

    return conn;
  }


  /**
   * 根據url
   *
   * @param url 請求路徑
   * @return isFile
   * @throws IOException 異常
   */
  //待改進
  protected static HttpURLConnection getConnection(URL url, boolean isFile) throws IOException {
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    if (conn == null) {
      throw new IOException("connection can not be null");
    }
    //設置從httpUrlConnection讀入
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.setUseCaches(false);
    //如果是上傳文件,則設為POST
    if (isFile) {
      conn.setRequestMethod(POST_METHOD); //GET和 POST都可以 文件略大改成POST
    }
    // 設置請求頭信息
    conn.setRequestProperty("Connection", "Keep-Alive");
    conn.setRequestProperty("Charset", String.valueOf(StandardCharsets.UTF_8));
    conn.setConnectTimeout(8000);
    conn.setReadTimeout(8000);
    return conn;
  }


  /**
   * 拼接參數
   *
   * @param url   需要拼接參數的url
   * @param map   參數
   * @param charset 編碼格式
   * @return 拼接完成后的url
   */
  public static String setParmas(String url, Map<String, String> map, String charset) throws Exception {
    String result = StringUtils.EMPTY;
    boolean hasParams = false;
    if (StringUtils.isNotEmpty(url) && MapUtils.isNotEmpty(map)) {
      StringBuilder builder = new StringBuilder();
      for (Map.Entry<String, String> entry : map.entrySet()) {
        String key = entry.getKey().trim();
        String value = entry.getValue().trim();
        if (hasParams) {
          builder.append("&");
        } else {
          hasParams = true;
        }
        if (StringUtils.isNotEmpty(charset)) {
          builder.append(key).append("=").append(URLEncoder.encode(value, charset));
        } else {
          builder.append(key).append("=").append(value);
        }
      }
      result = builder.toString();
    }

    URL u = new URL(url);
    if (StringUtils.isEmpty(u.getQuery())) {
      if (url.endsWith("?")) {
        url += result;
      } else {
        url = url + "?" + result;
      }
    } else {
      if (url.endsWith("&")) {
        url += result;
      } else {
        url = url + "&" + result;
      }
    }
    logger.debug("request url is {}", url);
    return url;
  }
}

遇到的問題

1)"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest hint: [Ua2IXa0080sz47!]"
獲取的access_token不對,這邊的token不是授權的token,是公眾號調用各接口時使用的access_token

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • JAVA觀察者模式的的講解及代碼實現

    JAVA觀察者模式的的講解及代碼實現

    這篇文章主要為大家詳細介紹了JAVA的觀察者模式,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 詳解Spring Boot 屬性配置和使用

    詳解Spring Boot 屬性配置和使用

    本篇文章主要介紹了詳解Spring Boot 屬性配置和使用,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • 30w+數據使用RedisTemplate?pipeline空指針NullPointerException異常分析

    30w+數據使用RedisTemplate?pipeline空指針NullPointerException異常分析

    這篇文章主要為大家介紹了30w+數據使用RedisTemplate?pipeline空指針NullPointerException異常分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • Java GUI圖形界面開發(fā)實現小型計算器流程詳解

    Java GUI圖形界面開發(fā)實現小型計算器流程詳解

    本文章向大家介紹Java GUI圖形界面開發(fā)實現小型計算器,主要包括布局管理器使用實例、應用技巧、基本知識點總結和需要注意事項,具有一定的參考價值,需要的朋友可以參考一下
    2022-08-08
  • 教你如何寫springboot接口?

    教你如何寫springboot接口?

    這篇文章主要介紹了教你如何寫springboot接口,Spring?Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發(fā)過程。該框架使用了特定的方式來進行配置,從而使開發(fā)人員不再需要定義樣板化的配置,需要的朋友可以參考y一下
    2022-01-01
  • Java實習打卡8道面試題

    Java實習打卡8道面試題

    臨近秋招,備戰(zhàn)暑期實習,祝大家每天進步億點點!本篇文章準備了十道java的常用面試題,希望能夠給大家提供幫助,最后祝大家面試成功,進入自己心儀的大廠
    2021-06-06
  • java中字符串如何計算字節(jié)長度

    java中字符串如何計算字節(jié)長度

    這篇文章主要介紹了java中字符串如何計算字節(jié)長度,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • java.io.EOFException產生原因及解決方法(附代碼)

    java.io.EOFException產生原因及解決方法(附代碼)

    java.io.EOFException表示在讀取數據時突然遇到了文件或流的末尾,也就是說客戶端或服務器已經關閉了連接,但是你還在嘗試讀取數據,這篇文章主要給大家介紹了關于java.io.EOFException產生原因及解決的相關資料,需要的朋友可以參考下
    2023-09-09
  • spring boot打包成war包的頁面如何存放

    spring boot打包成war包的頁面如何存放

    這篇文章主要介紹了spring boot打包成war包的頁面該放到哪里,很多朋友對這個問題都很疑惑,今天小編給大家分享一篇教程,需要的朋友可以參考下
    2019-11-11
  • Kotlin中常見的List使用示例教程

    Kotlin中常見的List使用示例教程

    filter 就像其本意一樣,可以通過 filter 對 Kotlin list 進行過濾,本文重點給大家介紹Kotlin中常見的List使用,感興趣的朋友一起看看吧
    2023-11-11

最新評論