|
@@ -1,9 +1,9 @@
|
|
|
package com.jpsoft.weixin.controller;
|
|
|
|
|
|
import cn.hutool.core.date.DateTime;
|
|
|
-import cn.hutool.json.JSON;
|
|
|
import cn.hutool.json.JSONObject;
|
|
|
-import cn.hutool.json.JSONUtil;
|
|
|
+import com.jpsoft.weixin.callback.EventCallback;
|
|
|
+import com.jpsoft.weixin.config.PICCEntScanConfig;
|
|
|
import com.jpsoft.weixin.config.WeixinConfig;
|
|
|
import com.jpsoft.weixin.util.WeixinUtil;
|
|
|
import io.swagger.annotations.Api;
|
|
@@ -18,30 +18,21 @@ import org.apache.http.HttpStatus;
|
|
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
|
import org.apache.http.client.methods.HttpGet;
|
|
|
import org.apache.http.client.methods.HttpPost;
|
|
|
-import org.apache.http.client.utils.URIBuilder;
|
|
|
import org.apache.http.entity.StringEntity;
|
|
|
import org.apache.http.impl.client.CloseableHttpClient;
|
|
|
import org.apache.http.impl.client.HttpClientBuilder;
|
|
|
import org.apache.http.util.EntityUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.data.redis.core.ValueOperations;
|
|
|
import org.springframework.stereotype.Controller;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
-import org.xml.sax.Attributes;
|
|
|
-import org.xml.sax.SAXException;
|
|
|
-import org.xml.sax.helpers.DefaultHandler;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
-import javax.xml.parsers.ParserConfigurationException;
|
|
|
-import javax.xml.parsers.SAXParser;
|
|
|
-import javax.xml.parsers.SAXParserFactory;
|
|
|
-import java.io.InputStream;
|
|
|
+import java.io.IOException;
|
|
|
import java.net.URLEncoder;
|
|
|
-import java.nio.charset.Charset;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.Map;
|
|
|
+import java.util.*;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
@Api(description = "微信中控")
|
|
@@ -51,9 +42,15 @@ public class WeixinController {
|
|
|
@Autowired
|
|
|
private WeixinConfig weixinConfig;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private PICCEntScanConfig piccEntScanConfig;
|
|
|
+
|
|
|
@Autowired
|
|
|
private ValueOperations<String,Object> valueOperations;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private RedisTemplate<String, Object> redisTemplate;
|
|
|
+
|
|
|
@ApiOperation(value="验证服务器地址的有效性")
|
|
|
@GetMapping("/")
|
|
|
@ResponseBody
|
|
@@ -77,9 +74,10 @@ public class WeixinController {
|
|
|
@ApiOperation(value = "基础支持中获取普通access_token")
|
|
|
@GetMapping("/token")
|
|
|
@ResponseBody
|
|
|
- public JSONObject getToken(@RequestParam(defaultValue = "client_credential") String grant_type,
|
|
|
- @RequestParam(defaultValue = "") String appid,
|
|
|
- @RequestParam(defaultValue = "") String secret){
|
|
|
+ public JSONObject getToken(
|
|
|
+ @RequestParam(defaultValue = "client_credential") String grant_type,
|
|
|
+ @RequestParam(defaultValue = "") String appid,
|
|
|
+ @RequestParam(defaultValue = "") String secret){
|
|
|
String suffix = "_common_token";
|
|
|
JSONObject json = (JSONObject)valueOperations.get(appid + suffix);
|
|
|
|
|
@@ -117,10 +115,18 @@ public class WeixinController {
|
|
|
return json;
|
|
|
}
|
|
|
|
|
|
+ @ApiOperation(value = "刷新基础支持token")
|
|
|
+ @GetMapping("/refreshToken")
|
|
|
+ @ResponseBody
|
|
|
+ public Boolean refreshToken(@RequestParam(defaultValue = "") String appid){
|
|
|
+ String suffix = "_common_token";
|
|
|
+
|
|
|
+ return redisTemplate.delete(appid + suffix);
|
|
|
+ }
|
|
|
+
|
|
|
@ApiOperation(value = "处理消息事件")
|
|
|
@PostMapping("/")
|
|
|
public void processEvent(HttpServletRequest request, HttpServletResponse response){
|
|
|
-
|
|
|
try{
|
|
|
Map<String,Object> dataMap = WeixinUtil.xmlToMap(request.getInputStream());
|
|
|
|
|
@@ -131,29 +137,42 @@ public class WeixinController {
|
|
|
response.setContentType("text/html; charset=UTF-8");
|
|
|
response.setCharacterEncoding("UTF-8");
|
|
|
|
|
|
- String responseText = "success";
|
|
|
+ String eventKey = (String)dataMap.get("EventKey");
|
|
|
+ String toUserName = (String)dataMap.get("ToUserName");
|
|
|
+ String fromUserName = (String)dataMap.get("FromUserName");
|
|
|
+
|
|
|
+ List<EventCallback> callbackList = registerCallbackList();
|
|
|
+
|
|
|
+ boolean processed = false;
|
|
|
|
|
|
- responseText = replyTextMessage(dataMap);
|
|
|
+ //开发者在5秒内未回复任何内容
|
|
|
+ for (EventCallback callback: callbackList) {
|
|
|
+ if (eventKey.startsWith(callback.getCode())){
|
|
|
+ callback.process(fromUserName,toUserName,eventKey);
|
|
|
+ WeixinUtil.replyTextMessage(response,toUserName,fromUserName,callback.getMessage());
|
|
|
+
|
|
|
+ processed = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- response.getWriter().print(responseText);
|
|
|
+ if(!processed) {
|
|
|
+ String responseText = "success";
|
|
|
+ response.getWriter().print(responseText);
|
|
|
+ }
|
|
|
}
|
|
|
catch (Exception ex){
|
|
|
log.error(ex.getMessage(),ex);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private String replyTextMessage(Map dataMap){
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
+ private List<EventCallback> registerCallbackList() {
|
|
|
+ List<EventCallback> list = new ArrayList<>();
|
|
|
|
|
|
- sb.append("<xml>");
|
|
|
- sb.append("<ToUserName><![CDATA[" + dataMap.get("FromUserName") + "]]></ToUserName>");
|
|
|
- sb.append("<FromUserName><![CDATA["+ dataMap.get("ToUserName") + "]]></FromUserName>");
|
|
|
- sb.append("<CreateTime>" + DateTime.now().getTime() + "</CreateTime>");
|
|
|
- sb.append("<MsgType><![CDATA[text]]></MsgType>");
|
|
|
- sb.append("<Content><![CDATA[你好]]></Content>");
|
|
|
- sb.append("</xml>");
|
|
|
+ list.add(new EventCallback(piccEntScanConfig.getLoginCode(),piccEntScanConfig.getLoginCallbackUrl()));
|
|
|
+ list.add(new EventCallback(piccEntScanConfig.getBindingCode(),piccEntScanConfig.getBindingCallbackUrl()));
|
|
|
|
|
|
- return sb.toString();
|
|
|
+ return list;
|
|
|
}
|
|
|
|
|
|
@ResponseBody
|
|
@@ -166,9 +185,9 @@ public class WeixinController {
|
|
|
@ApiImplicitParam(name="scene_id", paramType="query", value="场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)"),
|
|
|
@ApiImplicitParam(name="scene_str", paramType="query", value="场景值ID(字符串形式的ID),字符串类型,长度限制为1到64")
|
|
|
})
|
|
|
- public JSONObject createQrCode(@RequestParam(name = "access_token") String accessToken,
|
|
|
+ public JSONObject createQrcode(@RequestParam(name = "access_token") String accessToken,
|
|
|
@RequestParam(name = "expire_seconds",defaultValue = "300") long expireSeconds,
|
|
|
- @RequestParam(name = "action_name",defaultValue = "QR_SCENE") String actionName,
|
|
|
+ @RequestParam(name = "action_name",defaultValue = "QR_STR_SCENE") String actionName,
|
|
|
@RequestParam(name = "scene_id",required = false) String sceneId,
|
|
|
@RequestParam(name = "scene_str",required = false) String sceneStr){
|
|
|
JSONObject resultObj = new JSONObject();
|
|
@@ -180,10 +199,6 @@ public class WeixinController {
|
|
|
.append("?access_token=")
|
|
|
.append(URLEncoder.encode(accessToken,"UTF-8"));
|
|
|
|
|
|
- HttpPost httpPost = new HttpPost(urlBuilder.toString());
|
|
|
-
|
|
|
- CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
|
|
-
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
jsonObject.put("expire_seconds", expireSeconds);
|
|
|
jsonObject.put("action_name", actionName);
|
|
@@ -191,41 +206,65 @@ public class WeixinController {
|
|
|
JSONObject actionInfo = new JSONObject();
|
|
|
JSONObject scene = new JSONObject();
|
|
|
|
|
|
+ StringBuilder keyBuilder = new StringBuilder();
|
|
|
+
|
|
|
+ keyBuilder.append(accessToken);
|
|
|
+
|
|
|
if(StringUtils.isNotEmpty(sceneId)) {
|
|
|
scene.put("scene_id", sceneId);
|
|
|
+ keyBuilder.append(sceneId);
|
|
|
}
|
|
|
|
|
|
if(StringUtils.isNotEmpty(sceneStr)) {
|
|
|
scene.put("scene_str", sceneStr);
|
|
|
+ keyBuilder.append(sceneStr);
|
|
|
+ }
|
|
|
+
|
|
|
+ String qrcodeUrl = (String)valueOperations.get("QRCODE_" + keyBuilder.toString());
|
|
|
+
|
|
|
+ if (StringUtils.isNotEmpty(qrcodeUrl)){
|
|
|
+ resultObj.put("data",qrcodeUrl);
|
|
|
+ resultObj.put("result", true);
|
|
|
}
|
|
|
+ else{
|
|
|
+ actionInfo.put("scene",scene);
|
|
|
+
|
|
|
+ jsonObject.put("action_info", actionInfo);
|
|
|
|
|
|
- actionInfo.put("scene",scene);
|
|
|
+ StringEntity entity = new StringEntity(jsonObject.toString(), "utf-8");
|
|
|
|
|
|
- jsonObject.put("action_info", actionInfo);
|
|
|
+ entity.setContentType("application/json");//发送json数据需要设置contentType
|
|
|
|
|
|
- StringEntity entity = new StringEntity(jsonObject.toString(), "utf-8");
|
|
|
+ HttpPost httpPost = new HttpPost(urlBuilder.toString());
|
|
|
+ CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
|
|
|
|
|
- entity.setContentEncoding("UTF-8");
|
|
|
- entity.setContentType("application/json");//发送json数据需要设置contentType
|
|
|
- httpPost.setEntity(entity);
|
|
|
+ httpPost.setEntity(entity);
|
|
|
|
|
|
- HttpResponse res = httpClient.execute(httpPost);
|
|
|
+ HttpResponse res = httpClient.execute(httpPost);
|
|
|
|
|
|
- if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
|
|
- String content = EntityUtils.toString(res.getEntity());// 返回json格式:
|
|
|
- JSONObject ret = new JSONObject(content);
|
|
|
+ if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
|
|
+ String content = EntityUtils.toString(res.getEntity());// 返回json格式:
|
|
|
+ JSONObject ret = new JSONObject(content);
|
|
|
|
|
|
- if (ret.containsKey("errcode")) {
|
|
|
- resultObj.put("result",false);
|
|
|
- resultObj.put("message",ret.getStr("errmsg"));
|
|
|
- resultObj.put("code",ret.getInt("errcode"));
|
|
|
- }
|
|
|
- else {
|
|
|
- String ticket = ret.getStr("ticket");
|
|
|
- long expire_seconds = ret.getLong("expire_seconds");
|
|
|
+ if (ret.containsKey("errcode")) {
|
|
|
+ resultObj.put("result", false);
|
|
|
+ resultObj.put("message", ret.getStr("errmsg"));
|
|
|
+ resultObj.put("code", ret.getInt("errcode"));
|
|
|
+ } else {
|
|
|
+ String ticket = ret.getStr("ticket");
|
|
|
+ long expire_seconds = ret.getLong("expire_seconds");
|
|
|
|
|
|
- resultObj.put("data", weixinConfig.getShowQrCodeUrl() + "?ticket=" + URLEncoder.encode(ticket, "UTF-8"));
|
|
|
- resultObj.put("result", true);
|
|
|
+ qrcodeUrl = weixinConfig.getShowQrCodeUrl() + "?ticket=" + URLEncoder.encode(ticket, "UTF-8");
|
|
|
+
|
|
|
+ valueOperations.set("QRCODE_" + keyBuilder, qrcodeUrl, expire_seconds - 5, TimeUnit.SECONDS);
|
|
|
+
|
|
|
+ resultObj.put("data", qrcodeUrl);
|
|
|
+ resultObj.put("result", true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ resultObj.put("result", false);
|
|
|
+ resultObj.put("message", "weixin服务器未正常返回!");
|
|
|
}
|
|
|
}
|
|
|
}
|