首页 / JAVA / 微信公众号JAVA后台对接最全面
微信公众号JAVA后台对接最全面
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了微信公众号JAVA后台对接最全面,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含11555字,纯文字阅读大概需要17分钟。
内容图文
![微信公众号JAVA后台对接最全面](/upload/InfoBanner/zyjiaocheng/601/0d21f8bca6d34e909c9bf737be59a1ba.jpg)
微信公众号JAVA后台对接最全面
微信公众号JAVA后台对接步骤
1.环境搭建
(1)接口测试号申请
拿到appid和appsecret,配置在后台配置文件!
https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
2.代码编写
公众号接口配置信息的填写,必须直接填写到指定的方法中,填写完,微信服务器会立即请求到填写服务器的地址,进行验证。
在微信公众号中,不管是验证服务器安全性还是微信消息推送,都只会走这个接口。一般情况下,验证安全性是get请求,而消息推送等都是POST请求,并且数据格式为XML,所以这个方法,就大有来头.
(1)获取消息推送
POM插件
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
@RequestMapping(value = "/get")
public void msgIn(HttpServletResponse response, HttpServletRequest request) throws ServletException, IOException {
if ("GET".equals(request.getMethod())) {
bindMsg(response, request);
} else if ("POST".equals(request.getMethod())) {
System.out.println("走的是post");
doPost(request, response);
}
}
/**
* 微信公共号get请求,服务器安全性校验。
* @param response
* @param request
*/
public void bindMsg(HttpServletResponse response, HttpServletRequest request) {
String echostr = request.getParameter("echostr");
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
try {
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
PrintWriter out = response.getWriter();
out.print(echostr);
out.close();
} else {
logger.info("这里存在非法请求!");
}
} catch (Exception e) {
logger.error(e.toString());
}
}
/**
* 接收并处理微信客户端发送的请求
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/xml;charset=utf-8");
PrintWriter out = response.getWriter();
try {
// 拿到微信客户端发来的请求并通过工具类解析为map格式
Map<String, String> map = XmlUtilMap.xmlToMap(request);
String toUserName = map.get("ToUserName");
String fromUserName = map.get("FromUserName"); //openid
String msgType = map.get("MsgType");
String content = map.get("Content");
String event = map.get("event");
System.out.println(fromUserName);
if (event.equals("subscribe")) {
System.out.println("用户关注了微信公众号, 这里写自己的业务逻辑.....");
}
if (event.equals("unsubscribe")) {
logger.info("用户取消关注公众号, 这里写自己的业务逻辑......");
System.out.println("用户取消关注公众号, 这里写自己的业务逻辑......");
}
} catch (Exception E) {
E.getMessage();
}
}
工具类***********
public class SignUtil {
// 与接口配置信息中的 Token 要一致
private static String token = "gede";
/**
* 验证签名
* @param signature
* @param timestamp
* @param nonce
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String[] arr = new String[] { token, timestamp, nonce };
// 将 token、timestamp、nonce 三个参数进行字典序排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 将三个参数字符串拼接成一个字符串进行 sha1 加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
content = null;
// 将 sha1 加密后的字符串可与 signature 对比,标识该请求来源于微信
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
}
/**
* 将字节数组转换为十六进制字符串
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
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[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
}
/**
* 实现消息的格式转换(Map类型和XML的互转)
*/
public class XmlUtilMap {
/**
* 将XML转换成Map集合
*/
public static Map<String, String> xmlToMap(HttpServletRequest request)
throws IOException, DocumentException {
Map<String, String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader(); // 使用dom4j解析xml
InputStream is= request.getInputStream(); // 从request中获取输入流
Document doc = reader.read(is);
Element root = doc.getRootElement(); // 获取根元素
List<Element> list = root.elements(); // 获取所有节点
for (Element e : list) {
map.put(e.getName(), e.getText());
System.out.println(e.getName() + "--->" + e.getText());
}
is.close();
return map;
}
/**
* 将文本消息对象转换成XML
*/
public static String textMessageToXML(WechatNotifyRequestVO textMessage) {
XStream xstream = new XStream(); // 使用XStream将实体类的实例转换成xml格式
System.out.println(",,,,,,,,,,");
xstream.alias("xml", textMessage.getClass()); // 将xml的默认根节点替换成“xml”
System.out.println("......");
return xstream.toXML(textMessage);
}
}
实体类,封装微信传递的参数。
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class WechatNotifyRequestVO {
@ApiModelProperty("开发者微信号")
private String toUserName;
@ApiModelProperty("发送方帐号(一个OpenID)")
private String fromUserName;
@ApiModelProperty("消息创建时间 (整型)")
private Integer createTime;
@ApiModelProperty("消息类型,event")
private String messageType;
@ApiModelProperty("事件类型,subscribe(订阅)、unsubscribe(取消订阅)")
private String event;
}
(2)发送模板消息
要给用户发送模板消息,最最主要的是拿到opeind!!!!
步揍:a:在微信公众号创建消息模板,拿到模板id。请注意每个字段后面必须有DATA
如下:尊敬的【{{fist.DATA}}】,您的计量仪器检校异常,请您及时处理。
仪器名称: {{keyword1.DATA}}
规格型号:{{keyword2.DATA}}
出厂编号:{{keyword3.DATA}}
业务员:{{keyword4.DATA}}
备注:{{keyword5.DATA}}
b:获取TOKEN,token有效期为2个小时。本示列代码使用的redis,存储时间为119分钟。在需要使用token的时候,可以从rendis中获取,若redis中没有,可调用下列方法生成新的redis。
/**
* 获取token
*
* @return token
*/
public String getToken() {
// 授予形式
String grant_type = "client_credential";
// 接口地址拼接参数
String getTokenApi = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" + grant_type + "&appid=" + appid
+ "&secret=" + secret;
String tokenJsonStr = sendGet(getTokenApi);
JSONObject tokenJson = JSONObject.parseObject(tokenJsonStr);
String token = tokenJson.get("access_token").toString();
redisTemplate.opsForValue().set("token", token, 119, TimeUnit.MINUTES);
System.out.println("获取到的TOKEN : " + token);
return token;
}
工具类:
/**
* HTTP/get
* @param requestUrl
* @return
*/
public static String sendGet(String requestUrl) {
StringBuffer buffer = null;
try {
// 建立连接
URL url = new URL(requestUrl);
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoInput(true);
httpUrlConn.setRequestMethod("GET");
// 获取输入流
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// 读取返回结果
buffer = new StringBuffer();
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return buffer.toString();
}
c: 消息推送
(因为一次只能调用方法推送一次,所以可以传多个手机号,循环调用推送方法)
/**
* 推送测试
* http://localhost:8082/api/subscription/a
*/
@RequestMapping("/a")
@ResponseBody
public void test(){
List<String> phone = new ArrayList<>();
phone.add("18792460893"); //此条数据对应的openid已经维护进wechat_fan表
//仪器校验测试
CompleteParam completeParam = new CompleteParam();
completeParam.setCustomerName("西安测试公司");
completeParam.setOrderSerila("111111-9898");
completeParam.setPrice("100");
completeParam.setNumber("11");
completeParam.setCompletedata("2020-3-15");
completeParam.setPhone(phone);
complete(completeParam);
}
/**
*仪器校验完成消息推送
* @param completeParam
*/
public void complete(CompleteParam completeParam) {
Map<String, Object> dataMap = new HashMap<String, Object>();
//根据自己的模板定义内容和颜色
DataWx dataWx1 = new DataWx();
dataWx1.setValue(completeParam.getCustomerName());
dataWx1.setColor("#173177");
DataWx dataWx2 = new DataWx();
dataWx2.setValue(completeParam.getOrderSerila());
dataWx2.setColor("#173177");
DataWx dataWx3 = new DataWx();
dataWx3.setValue(completeParam.getPrice());
dataWx3.setColor("#173177");
DataWx dataWx4 = new DataWx();
dataWx4.setValue(completeParam.getNumber());
dataWx4.setColor("#173177");
DataWx dataWx5 = new DataWx();
dataWx5.setValue(completeParam.getCompletedata());
dataWx5.setColor("#173177");
dataMap.put("fist",dataWx1);
dataMap.put("keyword1",dataWx2);
dataMap.put("keyword2",dataWx3);
dataMap.put("keyword3",dataWx4);
dataMap.put("keyword4",dataWx5);
List<String> phone = completeParam.getPhone();
if (StringUtils.isNotEmpty(phone)){
//整体参数map
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("template_id", templateId_complete);
paramMap.put("data", dataMap);
paramMap.put("url", "https://www.baidu.com"); //跳转其他路径
if (phone.size()==1){
WeChartFan weChartFan = weChartFanService.findUniqueByProperty("phone", phone.get(0));
if (StringUtils.isNotEmpty(weChartFan)){
paramMap.put("touser", weChartFan.getOpenId());
SendWeChatMsg(paramMap);
}
}else {
for (String s : phone) {
WeChartFan weChartFan = weChartFanService.findByPhone(phone.get(0));
if (StringUtils.isNotEmpty(weChartFan)){
paramMap.put("touser", weChartFan.getOpenId());
SendWeChatMsg(paramMap);
}
}
}
}
}
/**
* 公众号消息推送请求公共api
* @param map
*/
public void SendWeChatMsg(Map<String, Object> map) {
String token;
Object token1 = redisTemplate.opsForValue().get("token");
if (StringUtils.isNotEmpty(token1)){
token = token1.toString();
System.out.println("从redis中拿取的:"+token);
}else {
token = wxConfig.getToken();
System.out.println("重新生成的token:"+token);
}
// 接口地址
String sendMsgApi = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+token;
System.out.println(WxConfig.sendpost(sendMsgApi,map));
}
/**
* 调用接口 http/POST
* @param apiPath
*/
public static String sendpost(String apiPath,Map<String,Object> paramMap){
OutputStreamWriter out = null;
InputStream is = null;
String result = null;
try{
URL url = new URL(apiPath);// 创建连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod("POST") ; // 设置请求方式
connection.setRequestProperty("Charset", "UTF-8"); // 设置接收数据的格式
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // 设置发送数据的格式
connection.connect();
out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8"); // utf-8编码
out.append(JSON.toJSONString(paramMap));
out.flush();
out.close();
// 读取响应
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));
String line;
String responseStr="";
while ((line = reader.readLine()) != null){
responseStr+=line;
}
System.out.println(responseStr);
reader.close();
connection.disconnect();
}catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
内容总结
以上是互联网集市为您收集整理的微信公众号JAVA后台对接最全面全部内容,希望文章能够帮你解决微信公众号JAVA后台对接最全面所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。