微信小程序 客服消息 接口接入分享

由于公司业务需要,在小程序上开发客服功能
先浏览微信提供的接口文档https://developers.weixin.qq.com/miniprogram/dev/framework/server-ability/message-push.html
浏览完后,我们开始配置
1、先开发一个接口,用于验证需要填写的“URL服务器地址”,此接口用GET请求

     @IgnoreToken
	@GetMapping("/XXXXXXX")
	public void weixinProcessGetMethod(@RequestParam(required = false) Map params,HttpServletResponse response) {
		// 微信加密签名
		String msgSignature = (String) params.get("signature");
		// 时间戳
		String timeStamp = (String) params.get("timestamp");
		// 随机数
		String nonce = (String) params.get("nonce");
		// 随机字符串
		String echoStr = (String) params.get("echostr");
		log.info("客服消息验证url参数:{}", JSONObject.toJSONString(params));
		String result = "";
		if (SignUtil.checkSignature(msgSignature, timeStamp, nonce)) {
			result = echoStr;
		}

		log.info("客服消息验证url验证结果:{}",result);
		
		WXCommonUtils.responeOutputResult(response,result);
	}

再附一个工具类

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import cn.dankal.jb.core.util.ComponetWX;

import java.io.BufferedReader;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;

/**
 * ClassName: SignUtil 
* Function: 此工具类用于验证微信小程序消息接收接口url验证使用
* date: Jun 19, 2019 10:14:54 AM
* * @version * @since JDK 1.7 */ public class SignUtil { // 与接口配置信息中的Token要一致 //private static String token = "xxxx"; /** * 验证签名 * @ sc * @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; } @SuppressWarnings("unchecked") public static String getBodyFromRequest(HttpServletRequest request) { BufferedReader br = null; StringBuilder sb = new StringBuilder(""); try { br = request.getReader(); String str; while ((str = br.readLine()) != null) { sb.append(str); } br.close(); } catch (IOException e) { e.printStackTrace(); } finally { if (null != br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } }

注:小程序后台中的 url服务器地址可以先不填,先设置好 token 令牌,消息加密密钥
微信小程序 客服消息 接口接入分享_第1张图片
就此验证部分写完,如果消息加密方式选择了加密方式,验证接口不变!!!因为微信验证没有加密,只是验证接口可用

2、再写一个方法,接收用户发送的消息(用户发送消息,小程序调用配置的“URL服务器地址”),如图2效果
微信小程序 客服消息 接口接入分享_第2张图片
不多说,上代码

    @IgnoreToken
	@PostMapping("/XXXXXXX")
	@ResponseBody
	public void receiveMessage(HttpServletRequest request, HttpServletResponse response) {
		String result = "fail";
		try {
			String postData = SignUtil.getBodyFromRequest(request);

			log.info("接收小程序客户消息开始:{},postData:{}", request.getQueryString(), postData);
			Map xmlToMap = WXPayUtil.xmlToMap(postData);
			JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(xmlToMap));

			if (jsonObject.containsKey("MsgType") && jsonObject.getString("MsgType").equals("text")) { //收到的是文本消息
				//customerServerService.handleCustomerMessageText(jsonObject); 这里处理消息,我是放到了kafka里面
				result = "success";
			} else { //其他消息
				log.info("非文本消息不予处理");
				//也回复一个图片消息
				result = "success";
			}
		} catch (Exception e) {
			log.error("接收消息出现异常", e);
		}
		
		WXCommonUtils.responeOutputResult(response,result);
	}

WXCommonUtils.responeOutputResult 内容如下

public static void responeOutputResult(HttpServletResponse response, String result) {
		try (ServletOutputStream outputStream = response.getOutputStream()) {
			//此处需要用repsone,返回不能带引号
			outputStream.print(result);
		} catch (IOException e) {
			log.error("response 输出结果出现异常", e);
		}
	}

特别在这里提醒,响应微信要用response输出方式,因为其他方式都会返回时带引号,而微信接收时,是不能带引号的,这个微信接口没有提到,一定要注意

3、发送回应消息的内容,稍后补上。。。

这里借鉴到了https://blog.csdn.net/syj921029/article/details/81301548 这位兄台的内容,这是找到的比较详细的,在此多谢!

你可能感兴趣的:(微信)