1、java發(fā)送服務(wù)通知模板消息到指定用戶
準(zhǔn)備:
- 獲取當(dāng)前微信小程序appId(小程序appId)獲取當(dāng)前小程序的秘鑰secret
- 新建模板消息
選用后勾選需要的字段并提交
一次訂閱:
指用戶訂閱一次,服務(wù)號可不限時間地下發(fā)一條對應(yīng)的訂閱通知;
長期訂閱:
指用戶訂閱一次,服務(wù)號可長期多次下發(fā)通知,長期訂閱通知僅向政務(wù)民生、醫(yī)療,交通,金融等公共服務(wù)領(lǐng)域開放,比較難申請;
服務(wù)通知:
微信默認(rèn)開啟服務(wù)通知功能,在用戶聊天列表中會出現(xiàn)橙色的服務(wù)通知
后端代碼實(shí)現(xiàn):
微信發(fā)送服務(wù)通知工具類
import com.alibaba.fastjson.JSONObject;
import com.shop.cereshop.commons.utils.third.IdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @ClassName WechatUtil
* @Version 1.0
*/
@Slf4j(topic = "WxchatSendUtil")
@Component
public class WxchatSendUtil {
@Value("${bussiness.appId}")
private static String appId;
@Value("${bussiness.secret}")
private static String secret;
@Value("${bussiness.orderPlacementNoticeTemplateId}")
private static String orderPlacementNoticeTemplateId;
/**
* 獲取小程序token
*
* @return
*/
public static String getAccessToken() {
String url = "https://api.weixin.qq.com/cgi-bin/token?" +
"appid=" + appId + "&secret=" + secret + "&grant_type=client_credential";
PrintWriter out = null;
BufferedReader in = null;
String line;
StringBuffer stringBuffer = new StringBuffer();
try {
URL realUrl = new URL(url);
// 打開和URL之間的連接
URLConnection conn = realUrl.openConnection();
// 設(shè)置通用的請求屬性 設(shè)置請求格式
//設(shè)置返回類型
conn.setRequestProperty("contentType", "text/plain");
//設(shè)置請求類型
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
//設(shè)置超時時間
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
conn.setDoOutput(true);
conn.connect();
// 獲取URLConnection對象對應(yīng)的輸出流
out = new PrintWriter(conn.getOutputStream());
// flush輸出流的緩沖
out.flush();
// 定義BufferedReader輸入流來讀取URL的響應(yīng) 設(shè)置接收格式
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
while ((line = in.readLine()) != null) {
stringBuffer.append(line);
}
JSONObject jsonObject = JSONObject.parseObject(stringBuffer.toString());
return jsonObject.getString("access_token");
} catch (Exception e) {
e.printStackTrace();
}
//使用finally塊來關(guān)閉輸出流、輸入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
public static final String SEND_INFO_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";
public static void main(String[] args) throws IOException {
// 1、獲取 接口調(diào)用憑證
RestTemplate restTemplate = new RestTemplate();
String url = SEND_INFO_URL + WxchatSendUtil.getAccessToken();
//拼接推送的模版
WxMssVO wxMssVo = new WxMssVO();
//用戶的openId
wxMssVo.setTouser("oa4u44ukI8wbYO3it-ysAm_yNJSo");
//訂閱消息模板id
wxMssVo.setTemplate_id(orderPlacementNoticeTemplateId);
// wxMssVo.setPage("pages/appointment/line_up?"+"shopId="+info.getShopId());
Map<String, TemplateData> m = new HashMap<>(4);
m.put("character_string36", new TemplateData(IdWorker.generSequeId()));
m.put("thing2", new TemplateData("用戶下單通知啊"));
m.put("phrase28", new TemplateData("待付款"));
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
m.put("time10", new TemplateData(simpleDateFormat.format(new Date())));
wxMssVo.setData(m);
ResponseEntity<String> responseEntity =
restTemplate.postForEntity(url, wxMssVo, String.class);
System.out.println(responseEntity.getBody());
}
}
WxMssVO
import lombok.Data;
import java.util.Map;
/**
* @author ys
*/
@Data
public class WxMssVO {
/**
* 用戶openid
*/
private String touser;
/**
* 訂閱消息模版id
*/
private String template_id;
/**
* 默認(rèn)跳到小程序首頁
*/
private String page;
/**
* 推送文字
*/
private Map<String, TemplateData> data;
}
TemplateData
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author ys
*/
@AllArgsConstructor
@Data
public class TemplateData {
private String value;
}
前端代碼實(shí)現(xiàn):
用戶在在開發(fā)者提供的 H5 頁面中,通過 JSSDK 拉起訂閱按鈕
wx.requestSubscribeMessage
<button bindtap="getAuthority" type='primary'>獲取訂閱消息授權(quán)</button>
//獲取授權(quán)的點(diǎn)擊事件
getAuthority() {
wx.requestSubscribeMessage({
//這里填入我們生成的模板id
tmplIds: ['CFeSWarQL*************8V8bFLkBzTU'],
success(res) {
console.log('授權(quán)成功', res)
}, fail(res) {
console.log('授權(quán)失敗', res) }
}
)
}
2、java發(fā)送微信公眾號模板消息到指定用戶
這里和發(fā)送服務(wù)通知的不同
1> 要多一步配置并驗(yàn)證token(token需要驗(yàn)簽)
2> 需要配置ip白名單
3> 發(fā)送消息的https接口不同
配置模板消息
這里最好是公眾號關(guān)聯(lián)小程序,綁定后雖然每個小主體的用戶openid不同但是用戶的unionid都是相同的
獲取公眾號需要用到的信息
獲取公鑰私鑰,設(shè)置白名單ip(也就是你部署項目的服務(wù)器ip或者你本地的公網(wǎng)ip不設(shè)置獲取不到access_token)
后端代碼實(shí)現(xiàn)
微信發(fā)送公眾號消息工具類
import com.alibaba.fastjson.JSONObject;
import com.shop.cereshop.app.param.shop.WxSendParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
/**
* @author ys
* @ClassName WechatUtil
* @Version 1.0
*/
@Slf4j(topic = "WxChatSendUtil")
@Component
public class WxChatSendUtil {
// @Value("${bussiness.appId}")
// private static String appId;
// @Value("${bussiness.secret}")
// private static String secret;
// @Value("${bussiness.orderPlacementNoticeTemplateId}")
// private static String orderPlacementNoticeTemplateId;
private static final String appId="微信公眾號appID";
private static final String secret="微信公眾號secret密鑰";
private static final String orderPlacementNoticeTemplateId="微信公眾號模板消息id";
/**
* 獲取小程序token
* @return
*/
public static String getAccessToken() {
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + secret + "&grant_type=client_credential";
PrintWriter out = null;
BufferedReader in = null;
String line;
StringBuffer stringBuffer = new StringBuffer();
try {
URL realUrl = new URL(url);
// 打開和URL之間的連接
URLConnection conn = realUrl.openConnection();
// 設(shè)置通用的請求屬性 設(shè)置請求格式
//設(shè)置返回類型
conn.setRequestProperty("contentType", "text/plain");
//設(shè)置請求類型
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
//設(shè)置超時時間
conn.setConnectTimeout(1000);
conn.setReadTimeout(1000);
conn.setDoOutput(true);
conn.connect();
// 獲取URLConnection對象對應(yīng)的輸出流
out = new PrintWriter(conn.getOutputStream());
// flush輸出流的緩沖
out.flush();
// 定義BufferedReader輸入流來讀取URL的響應(yīng) 設(shè)置接收格式
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
while ((line = in.readLine()) != null) {
stringBuffer.append(line);
}
JSONObject jsonObject = JSONObject.parseObject(stringBuffer.toString());
return jsonObject.getString("access_token");
} catch (Exception e) {
e.printStackTrace();
}
//使用finally塊來關(guān)閉輸出流、輸入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
/**
* 發(fā)送微信小程序訂閱消息
*
* @param wxSendParam
* @return
*/
public static String WxChatSendOrderNotice(WxSendParam wxSendParam) {
// 1、獲取 接口調(diào)用憑證
RestTemplate restTemplate = new RestTemplate();
String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + WxChatSendUtil.getAccessToken();
//拼接推送的模版
WxMssVO wxMssVo = new WxMssVO();
//用戶的openId
wxMssVo.setTouser(wxSendParam.getBusinessOpenId());
//訂閱消息模板id
wxMssVo.setTemplate_id(orderPlacementNoticeTemplateId);
wxMssVo.setPage("pages/order/order");
wxMssVo.setData(wxSendParam.getOrderMap());
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, wxMssVo, String.class);
return responseEntity.getBody();
}
public static void main(String[] args) {
WxSendParam wxSendParam = new WxSendParam();
Map<String, TemplateData> orderSendWxSend = new HashMap<>(5);
orderSendWxSend.put("first", new TemplateData("下單成功通知"));
orderSendWxSend.put("keyword1", new TemplateData("113e23432432"));
orderSendWxSend.put("keyword2", new TemplateData("已付款"));
orderSendWxSend.put("keyword3", new TemplateData("320.18元"));
orderSendWxSend.put("keyword4", new TemplateData("2021-08-19"));
wxSendParam.setOrderMap(orderSendWxSend);
wxSendParam.setBusinessOpenId("xxxxx");
WxChatSendUtil.WxChatSendOrderNotice(wxSendParam);
}
}
通過前端授權(quán)公眾號獲取的code解析用戶在公眾號中的openid
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
/**
* 通過前端授權(quán)公眾號獲取的code解析用戶在公眾號中的openid
* @param code
* @param response
* @return
*/
public static String getopenid(String code, HttpServletResponse response){
String appid= "微信公眾號appID";
String secret = "微信公眾號secret密鑰";
response.setHeader("Access-Control-Allow-Origin", "*");
/*星號表示所有的域都可以接受,*/
response.setHeader("Access-Control-Allow-Methods", "GET,POST");
String wxLoginUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
String param = "appid="+appid+"&secret="+secret+"&code="+code+"&grant_type=authorization_code";
String jsonString = GetPostUntil.sendGet(wxLoginUrl, param);
JSONObject json = JSONObject.parseObject(jsonString);
String openid = json.getString("openid");
log.info("###############"+openid);
return openid;
}
授權(quán)公眾號controller
/**
* 授權(quán)公眾號
* @param param
* AuthorizedOfficialAccountParam 這個里面只有一個code屬性
* CoBusinessException 改成你的自定義異常
* @return
*/
@PostMapping(value = "authorizedOfficialAccount")
@ApiOperation(value = "授權(quán)公眾號")
public Result authorizedOfficialAccount(@RequestBody AuthorizedOfficialAccountParam param, HttpServletResponse response) throws CoBusinessException {
String openid = WxChatSendUtil.getopenid(param.getCode(),response);
if(StringUtils.isNotBlank(openid)){
log.info("==========================================:"+openid);
//todo 對公眾號openid做數(shù)據(jù)庫操作
}
//根據(jù)自己的項目返回 主要是通過接口調(diào)用后返回給前端的值
return new Result(CoReturnFormat.SUCCESS);
}
Token驗(yàn)證
import com.shop.cereshop.app.utils.wxSendUtils.SignUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* 訂單模塊
*/
@RestController
@RequestMapping("/wxSend")
@Slf4j(topic = "wxSendController")
@Api(value = "服務(wù)號發(fā)送消息", tags = "服務(wù)號發(fā)送消息")
public class wxSendController {
/**
* 這個token要與公眾平臺服務(wù)器配置填寫的token一致
*/
private final static String TOKEN = "xxxxxx";
@GetMapping("/checkSignature")
public String checkSignature(HttpServletRequest request) {
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
log.info("接收來自微信服務(wù)器的認(rèn)證信息。signature={},timestamp={},nonce={},echostr={}",
signature, timestamp, nonce, echostr);
if(StringUtils.isAnyBlank(signature,timestamp,nonce,echostr)){
log.info("請求參數(shù)非法");
return null;
}
//加密后的mySignature與微信公眾平臺的signature一致
boolean check = SignUtil.checkSignature(TOKEN, signature, timestamp, nonce);
if (check) {
return echostr;
}
return null;
}
}
驗(yàn)簽工具SignUtil類
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class SignUtil {
/**
* 校驗(yàn)簽名
*
* @param token 服務(wù)器配置里寫的TOKEN
* @param signature 簽名
* @param timestamp 時間戳
* @param nonce 隨機(jī)數(shù)
* @return true 成功,false 失敗
*/
public static boolean checkSignature(String token, String signature, String timestamp, String nonce) {
String checkText = null;
if (null != signature) {
//對Token,timestamp nonce 按字典排序
String[] paramArr = new String[]{token, timestamp, nonce};
Arrays.sort(paramArr);
//將排序后的結(jié)果拼成一個字符串
String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
//對接后的字符串進(jìn)行sha1加密
byte[] digest = md.digest(content.getBytes());
checkText = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
//將加密后的字符串與signature進(jìn)行對比
return checkText != null && checkText.equals(signature.toUpperCase());
}
/**
* 將字節(jié)數(shù)組轉(zhuǎn)化為16進(jìn)制字符串
*
* @param byteArrays 字符數(shù)組
* @return 字符串
*/
private static String byteToStr(byte[] byteArrays) {
StringBuilder str = new StringBuilder();
for (byte byteArray : byteArrays) {
str.append(byteToHexStr(byteArray));
}
return str.toString();
}
/**
* 將字節(jié)轉(zhuǎn)化為十六進(jìn)制字符串
*
* @param myByte 字節(jié)
* @return 字符串
*/
private static String byteToHexStr(byte myByte) {
char[] digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char[] tempArr = new char[2];
tempArr[0] = digit[(myByte >>> 4) & 0X0F];
tempArr[1] = digit[myByte & 0x0F];
return new String(tempArr);
}
}
WxMssVO
import lombok.Data;
import java.util.Map;
/**
* @author ys
*/
@Data
public class WxMssVO {
/**
* 用戶openid
*/
private String touser;
/**
* 訂閱消息模版id
*/
private String template_id;
/**
* 默認(rèn)跳到小程序首頁
*/
private String page;
/**
* 推送文字
*/
private Map<String, TemplateData> data;
}
TemplateData
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author ys
*/
@AllArgsConstructor
@Data
public class TemplateData {
private String value;
}
WxSendParam
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
/**
* 微信訂閱發(fā)送商家訂單消息
*/
@Data
public class WxSendParam {
@ApiModelProperty(value = "商家openId")
private String businessOpenId;
@ApiModelProperty(value = "小程序跳轉(zhuǎn)路徑")
private String pageUrl;
@ApiModelProperty(value = "模板內(nèi)容")
private Map<String, TemplateDatas> orderMap;
}
注:前端需要授權(quán)公眾號
補(bǔ)充:
獲取公眾號所有的關(guān)注用戶openid
https://api.weixin.qq.com/cgi-bin/user/get?access_token=
“openid”: [
“oNg5r5w54H4ZVfIWvOstPkY1WPDw”,
“oNg5r55r_nxPP8J0iY3gapn__rkw”,
“oNg5r5xCxn_dmErxcHzBCujnhhko”,
“oNg5r55Slu3Qt8-jlUxhdeQHrwTA”,
“oNg5r57SwfV-I5w1ccWjypTfyC_Q”,
“oNg5r53lQSBGeoJNdTiqGqQThhSk”,
“oNg5r5_vTiEXP5IArZHmAf1G0a64”,
“oNg5r59mPCOnnEzkNkTXpbRZ3zFw”,
“oNg5r5xYuHAPuZMLVjFlmely78Ig”,
“oNg5r565AHcksPhcYUwfgnSMAo24”,
“oNg5r5z6gKpe1mPqDkReb067IMgI”
]
獲取公眾號所有的標(biāo)簽信息
https://api.weixin.qq.com/cgi-bin/tags/get?access_token=
{
“id”: 2,
“name”: “星標(biāo)組”,
“count”: 0
},
{
“id”: 100,
“name”: “11”,
“count”: 1
},
{
“id”: 101,
“name”: “22”,
“count”: 1
},
{
“id”: 102,
“name”: “33”,
“count”: 1
}
通過openid獲取用戶分組等信息
https://api.weixin.qq.com/cgi-bin/user/info?access_token=&openid=文章來源:http://www.zghlxwxcb.cn/news/detail-495505.html
微信公眾號推送消息文章來源地址http://www.zghlxwxcb.cn/news/detail-495505.html
到了這里,關(guān)于java發(fā)送公眾號/服務(wù)通知模板消息到指定用戶(完整流程|親測可用)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!