根据文档描述,发送图片需要临时素材的form_id,所以首先得完成临时素材的上传获取到form_id
/**
* 微信小程序临时素材上传
*
* @param file
* @return
* @author 13
* @throws Exception
*/
public String uploadFile(MultipartFile file) throws Exception {
String url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=" + ACCESS_TOKEN + "&type=image";
String result = null;
String fileName = file.getOriginalFilename();
URL urlObj = new URL(url);
HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
// 设置请求头信息
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Charset", "UTF-8");
// 设置边界
String BOUNDARY = "----------" + System.currentTimeMillis();
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
// 请求正文信息
// 第一部分:
StringBuilder sb = new StringBuilder();
sb.append("--"); // 必须多两道线
sb.append(BOUNDARY);
sb.append("\r\n");
sb.append("Content-Disposition: form-data;name=\"media\";filename=\"" + fileName + "\"\r\n");
sb.append("Content-Type:application/octet-stream\r\n\r\n");
byte[] head = sb.toString().getBytes("utf-8");
// 获得输出流
OutputStream out = new DataOutputStream(con.getOutputStream());
// 输出表头
out.write(head);
// 文件正文部分
// 把文件已流文件的方式 推入到url中
DataInputStream in = new DataInputStream(file.getInputStream());
int bytes = 0;
byte[] bufferOut = new byte[1024];
while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
in.close();
// 结尾部分
byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线
out.write(foot);
out.flush();
out.close();
StringBuffer buffer = new StringBuffer();
BufferedReader reader = null;
try {
// 定义BufferedReader输入流来读取URL的响应
reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
if (result == null) {
result = buffer.toString();
}
} catch (IOException e) {
System.out.println("发送POST请求出现异常! {}");
e.printStackTrace();
throw new IOException("数据读取异常");
} finally {
if (reader != null) {
reader.close();
}
}
// 获取到返回HTTP结果
Map<String, Object> map = JSONObject.parseObject(result, Map.class);
if (map.containsKey("media_id")) {
return map.get("media_id").toString();
}
System.out.println("小程序上传临时素材出错,返回信息为: " + result);
return null;
}
拿到form_id以后就可以进行客服消息自动回复了
同一个接口,设置服务器地址微信会进行get请求校验服务器地址的可用性,而post接口则进行客服消息自动回复
// 开启时填写的秘钥
private static final String token="XXXXXXXX";
/**
* 微信小程序消息验证和配置
*
* @author 13
* @return
* @throws Exception
*/
@RequestMapping(value = "/message", method = RequestMethod.GET)
public String getProcess(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 微信加密签名
String signature = request.getParameter("signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if (this.checkSignature(signature, timestamp, nonce)) {
return echostr;
}
return null;
}
/**
* 微信小程序客服消息自动回复
*
* @author 13
* @return
* @throws Exception
*/
@RequestMapping(value = "/message", method = RequestMethod.POST)
public String replyMessage(@RequestBody Map<String, Object> msg, HttpServletRequest request, HttpServletResponse response) throws Exception {
return appletCommonService.replyMessage(msg);
}
private 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 (Exception e) {
e.printStackTrace();
}
content = null;
// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
}
/**
* 将字节数组转换为十六进制字符串
* @author 13
* @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;
}
/**
* 将字节转换为十六进制字符串
* @author 13
* @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;
}
@Service
public class AppletCommonService {
public static final String[] keyWord = {"你好", "您好", "请问", "在"};
public static final List<String> keyList = Arrays.asList(keyWord);
// 小程序的access_token
public static final String ACCESS_TOKEN = "";
/**
* 小程序客服自动回复功能
* @author 13
* @param msg 微信传递的参数集合
* @return "SUCCEE"告知微信处理成功
* @throws Exception
*/
public String replyMessage(Map<String, Object> msg) throws Exception {
System.out.println("客服消息自动回复 ====> start");
String opendId = msg.get("FromUserName").toString();
Map<String, String> contenMap = new HashMap<String, String>();
// 发送结果
String result = "";
String conten = msg.get("Content") == null ? "" : msg.get("Content").toString();
// 判断文字中是否包含关键词,若包含则提前自动回复
boolean flag = false;
for (String string : keyList) {
if (conten.startsWith(string)) {
flag = true;
break;
}
}
// 若用户消息包含关键字则自动回复
if (flag) {
contenMap.put("content", "你好!正在赶来的路上,可以先留下你的问题");
result = sendMessage(opendId, "text", contenMap);
System.out.println("客服自动回复结果:" + result);
// 此处将消息转发至人工客服,不然人工客服窗会没有消息
Map<String, Object> tranMap = new HashMap<String, Object>();
tranMap.put("ToUserName", msg.get("FromUserName"));
tranMap.put("FromUserName", msg.get("ToUserName"));
tranMap.put("CreateTime", msg.get("CreateTime"));
tranMap.put("MsgType", "transfer_customer_service");
String messageJson = JSONObject.toJSONString(tranMap);
System.out.println("消息转发至人工客服");
return messageJson;
}
// TODO 此处根据自己的业务逻辑获取微信临时素材id
String mediaId = "xxxxxxxx";
// 若没有活动临时素材则不进项操作
if (StringUtils.isBlank(mediaId)) {
// 此处将消息转发至人工客服,不然人工客服窗会没有消息
Map<String, Object> tranMap = new HashMap<String, Object>();
tranMap.put("ToUserName", msg.get("FromUserName"));
tranMap.put("FromUserName", msg.get("ToUserName"));
tranMap.put("CreateTime", msg.get("CreateTime"));
tranMap.put("MsgType", "transfer_customer_service");
String messageJson = JSONObject.toJSONString(tranMap);
System.out.println("消息转发至人工客服");
return messageJson;
}
// 有临时素材照片则自动回复临时素材图片media_id【 活动二维码或推广二维码等】
contenMap.put("media_id", mediaId);
result = sendMessage(opendId, "image", contenMap);
System.out.println("客服自动回复结果:" + result);
return "SUCCESS";
}
/**
* 客服消息自动回复
* @author 13
* @param opendId 接收者openId
* @param msgtype 消息格式:text 文本;image 图片; link 图文链接
* @param contentMap 正文map
* @return
* @throws UnsupportedEncodingException
*/
private String sendMessage(String opendId, String msgtype, Map<String, String> contentMap) throws UnsupportedEncodingException {
Map<String, Object> replyMessageMap = new HashMap<String, Object>();
replyMessageMap.put("touser", opendId);
replyMessageMap.put("msgtype", msgtype);
replyMessageMap.put(msgtype, contentMap);
String messageJson = JSONObject.toJSONString(replyMessageMap);
messageJson = new String(messageJson.getBytes(), "UTF-8");
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + ACCESS_TOKEN;
// 发送结果
return HttpUtils.sendPost(url, messageJson);
}
}
代码中用到的HttpUtils是自己写的,可以网上随便搜下怎么发post请求即可