微信小程序結合微信公眾號進行消息發送
由於小程序的模板消息已經廢棄了,官方讓使用訂閱消息功能。而訂閱消息的使用限制比較大,用戶必須得訂閱、需要獲取用戶同意接收消息的權限、用戶必須得和小程序有交互的時候才能發送且只能發送一次。而我們的需求有可能是不限時間不限“次數”的發送消息。那么就可以使用官方提供的統一服務消息。
統一服務消息
該功能還是有一點的使用限制的。
第一:小程序和公眾號的主體必須是同一個。
第二:用戶必須關注公眾號。
第三:我們得有消息模板,小程序消息模板和公眾號消息模板都可以。
結合文檔,使用Java對發送消息的功能進行簡單的封裝
第一:使用httpClient請求地址,獲取access_token
GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
根據官方接口的返回值,我們封裝返回值對象
@Data
public class AccessToken {
/** 接口調用憑證 */
private String access_token;
/** 過期時間 */
private Long expires_in;
/** 錯誤信息代碼 */
private String errcode;
/** 錯誤信息 */
private String errmsg;
}
使用httpClient發送請求
AccessToken accessToken = new AccessToken();
String url = WxMessageConstant.GET_XCX_ACCESS_TOKEN_URL + "&appid=" + WxMessageConstant.APP_ID + "&secret=" + WxMessageConstant.SECRET;
String result = HttpClientUtils.doGet(url);
accessToken = JSON.parseObject(result, AccessToken.class);
注意:獲得的token結果可以放在redis里面,設置上過期時間,防止應用重復獲取access_token!
第二:構造請求
構造請求url
根據官方提供的接口再加上我們的獲取的access_token進行構造
POST https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN
構造請求參數
根據官方文檔,我們一步一步來構造請求參數對象,我們用的是公眾號的消息模板,所以這里沒有weapp_template_msg參數
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReqSendMessageData {
/**
* 消息接收者
*/
private String touser;
/**
* 公眾號模板消息信息
*/
private MpTemplateMsg mp_template_msg;
}
構造mp_template_msg對象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MpTemplateMsg {
/** 公眾號openId */
private String appid;
/** 公眾號模板id */
private String template_id;
/** 跳轉到公眾號的地址,文檔上寫的必填,我沒填,沒有報錯 */
private String url;
/** 公眾號綁定的小程序信息 */
private Miniprogram miniprogram;
/** 數據 */
private Map<String,Object> data;
}
構造小程序信息
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Miniprogram {
/** 小程序appid */
private String appid;
/** 要跳轉到小程序的頁面 */
private String page;
}
貼出httpClient發送post請求的方式
public static String postSendJsonParam(String url, String param) {
CloseableHttpClient httpClient = HttpClients.createDefault();
String result = null;
// 請求方式
HttpPost httpPost = null;
// 響應
CloseableHttpResponse httpResponse = null;
httpPost = new HttpPost(url);
httpPost.setHeader("Connection", REQUEST_HEADER_CONNECTION);
httpPost.setHeader("User-Agent", REQUEST_HEADER_USER_AGENT);
httpPost.addHeader("content-type", "application/json;charset=utf-8");
httpPost.addHeader("accept", "application/json");
httpPost.setEntity(new StringEntity(param, "UTF-8"));
try {
httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
構造返回值對象,我們根據錯誤代碼進行擴展操作
@Data
public class ResSendMessageDTO {
/** 錯誤代碼 */
private String errcode;
/** 錯誤信息 */
private String errmsg;
}
最后我們可以把這些封裝成一個service交給spring管理。
public interface MessageService {
/**
* @author: taoym
* @date: 2020/7/2 9:08
* @desc: 推送消息
*/
ResSendMessageDTO sendMessage(ReqSendMessageData data);
}
具體實現不展示了。
封裝消息發送者
@Component
public class MessageSender {
@Autowired
private MessageService messageService;
/**
* @param first 消息標題
* @param keywordMap 消息內容
* @param page 要跳轉到小程序的頁面
* @param templateId 模板消息編號
* @param touser 消息接收者openId
* @author: taoym
* @date: 2020/9/28 11:25
* @desc: 消息發送者
*/
public ResSendMessageDTO sendMessage(String first, Map<String, Keyword> keywordMap, String touser, String page, String templateId) {
// 消息模板上的數據
Map<String, Object> messageData = Maps.newHashMap();
// first,可以理解為 標題
messageData.put("first", new First(first));
// keywordMap 可以理解為內容
messageData.putAll(keywordMap);
ReqSendMessageData reqSendMessageData = new ReqSendMessageData();
reqSendMessageData.setTouser(PasswordUtils.decrypt(touser));
MpTemplateMsg mpTemplateMsg = new MpTemplateMsg();
Miniprogram miniprogram = new Miniprogram();
miniprogram.setPage(page);
mpTemplateMsg.setMiniprogram(miniprogram);
mpTemplateMsg.setData(messageData);
mpTemplateMsg.setTemplate_id(templateId);
reqSendMessageData.setMp_template_msg(mpTemplateMsg);
ResSendMessageDTO resSendMessageDTO = messageService.sendMessage(reqSendMessageData);
// 0為成功的標志
if (!resSendMessageDTO.getErrcode().equals("0")) {
throw new ExceptionCore(resSendMessageDTO.getErrcode(), resSendMessageDTO.getErrmsg());
}
return resSendMessageDTO;
}
}
最后我們只需要根據模板消息的內容構造合理的參數,然后調用該方法即可發送消息。
