fanli/src/main/java/com/yeshi/fanli/aspect/RequestSerializableAspect.java
@@ -1,6 +1,5 @@ package com.yeshi.fanli.aspect; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Method; import java.util.HashMap; @@ -63,7 +62,7 @@ } @Around("execution(public * com.yeshi.fanli.controller.client.*.*.*(..))") public Object requestSerializable(ProceedingJoinPoint joinPoint) throws IOException { public Object requestSerializable(ProceedingJoinPoint joinPoint) throws Throwable { Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method targetMethod = methodSignature.getMethod(); @@ -125,9 +124,6 @@ if (!StringUtil.isNullOrEmpty(result)) { try { return joinPoint.proceed(); } catch (Throwable e) { e.printStackTrace(); LogHelper.errorDetailInfo(e); } finally { jedis.del(cacheKey); Constant.waitingThreadSet.remove(Thread.currentThread().getId()); @@ -138,12 +134,7 @@ } } } catch (Exception e) {// 原子性保护出错 try { return joinPoint.proceed(); } catch (Throwable e1) { e.printStackTrace(); LogHelper.errorDetailInfo(e1); } } } fanli/src/main/java/com/yeshi/fanli/aspect/RequestSerializableServiceAspect.java
@@ -17,7 +17,6 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.stereotype.Component; import com.yeshi.fanli.log.LogHelper; import com.yeshi.fanli.util.Constant; import com.yeshi.fanli.util.StringUtil; import com.yeshi.fanli.util.annotation.RequestSerializableByKeyService; @@ -92,9 +91,6 @@ if (!StringUtil.isNullOrEmpty(result)) { try { return joinPoint.proceed(); } catch (Throwable e) { e.printStackTrace(); LogHelper.errorDetailInfo(e); } finally { jedis.del(cacheKey); Constant.waitingThreadSet.remove(Thread.currentThread().getId()); @@ -105,12 +101,7 @@ } } } catch (Exception e) {// 原子性保护出错 try { return joinPoint.proceed(); } catch (Throwable e1) { e.printStackTrace(); LogHelper.errorDetailInfo(e1); } } } } catch (NoSuchMethodException e) { fanli/src/main/java/com/yeshi/fanli/aspect/WXMPSignValidateAspect.java
New file @@ -0,0 +1,200 @@ package com.yeshi.fanli.aspect; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.yeshi.utils.JsonUtil; import com.yeshi.fanli.dto.WXMPAcceptData; import com.yeshi.fanli.entity.accept.AcceptData; import com.yeshi.fanli.log.LogHelper; import com.yeshi.fanli.util.Constant; import com.yeshi.fanli.util.StringUtil; import com.yeshi.fanli.util.ThreadUtil; import net.sf.json.JSONObject; /** * 微信小程序接口签名验证 * * @author Administrator * */ @Component @Aspect @Order(2) public class WXMPSignValidateAspect { public static final String EDP = "execution(* com.yeshi.fanli.controller.wxmp.*.*.*(..))"; public static String KEY = ""; static { KEY = Constant.systemCommonConfig.getSignKey(); } @Around(EDP) public Object testAround(ProceedingJoinPoint joinPoint) throws IOException { Object[] args = joinPoint.getArgs(); PrintWriter out = null; ServletRequestAttributes servletContainer = (ServletRequestAttributes) RequestContextHolder .getRequestAttributes(); out = servletContainer.getResponse().getWriter(); HttpServletRequest request = servletContainer.getRequest(); WXMPAcceptData acceptData = null; for (Object obj : args) { if (obj instanceof WXMPAcceptData) { acceptData = (WXMPAcceptData) obj; } else if (obj instanceof HttpServletRequest) { request = (HttpServletRequest) obj; } } boolean isRight = true; if (acceptData == null) { out.print(JsonUtil.loadFalseResult(-1, "签名错误")); return null; } isRight = signIsRight(request); // 签名是否正确 if (isRight) { // 判断签名超时 if (Math.abs((acceptData.getTimeStamp()) - System.currentTimeMillis()) > 1000 * 60 * 10) { JSONObject data = new JSONObject(); data.put("code", -2); data.put("msg", "时间错误"); out.print(data); out.close(); return null; } final String url = request.getRequestURI(); @SuppressWarnings("unchecked") final Map<String, Object> params = request.getParameterMap(); ThreadUtil.run(new Runnable() { @Override public void run() { // 记录请求日志 LogHelper.requestInfo(url, params); } }); // 设置device if (!StringUtil.isNullOrEmpty(acceptData.getOpenId())) { acceptData.setDevice(acceptData.getAppId() + "-" + acceptData.getOpenId()); } Object obj = null; try { long startTime = System.currentTimeMillis(); obj = joinPoint.proceed(args); final long responseTime = System.currentTimeMillis() - startTime; // 记录大于2s的请求 if (responseTime >= 2000) { ThreadUtil.run(new Runnable() { @Override public void run() { LogHelper.requestTime(url, params, responseTime); } }); } } catch (Throwable e) { LogHelper.errorDetailInfo(e, getHttpServletParams(request), request.getRequestURI().toString()); out.print(JsonUtil.loadFalseResult(90009, "服务器内部错误")); } return obj; } else { JSONObject data = new JSONObject(); data.put("code", -1); data.put("msg", "签名错误"); out.print(data); out.close(); LogHelper.error("签名错误:" + request.getRequestURI() + "-" + getHttpServletParams(request)); return null; } } /** * * * @param request * @return */ @SuppressWarnings("unchecked") private boolean signIsRight(HttpServletRequest request) { Map<String, Object> map = request.getParameterMap(); Iterator<String> its = map.keySet().iterator(); List<String> list = new ArrayList<>(); while (its.hasNext()) { String key = its.next(); if (key.equalsIgnoreCase("sign")) { continue; } Object value = map.get(key); Object[] values = (Object[]) value; list.add(key + "=" + values[0].toString()); } Collections.sort(list); String str = ""; for (String st : list) { str += st + "&"; } String sign = null; sign = StringUtil.Md5(str + Constant.WXMP_SIGN_KEY); if (sign.equalsIgnoreCase(request.getParameter("sign") + "")) { return true; } else { return false; } } /** * 获取请求参数信息 * * @param request * @return */ private String getHttpServletParams(HttpServletRequest request) { if (request == null) { return ""; } Map map = request.getParameterMap(); if (map != null) { Iterator<String> its = map.keySet().iterator(); JSONObject json = new JSONObject(); while (its.hasNext()) { String next = its.next(); if (map.get(next) != null) { Object[] objects = (Object[]) map.get(next); if (objects != null && objects.length > 0) { json.put(next, objects[0].toString()); } } } return json.toString(); } return ""; } } fanli/src/main/java/com/yeshi/fanli/controller/wxmp/ConfigController.java
New file @@ -0,0 +1,88 @@ package com.yeshi.fanli.controller.wxmp; import java.io.PrintWriter; import java.util.List; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.yeshi.utils.IPUtil; import org.yeshi.utils.JsonUtil; import com.yeshi.fanli.dto.WXMPAcceptData; import com.yeshi.fanli.entity.push.DeviceActive; import com.yeshi.fanli.entity.system.BusinessSystem; import com.yeshi.fanli.entity.system.SystemClientParams; import com.yeshi.fanli.service.inter.config.BusinessSystemService; import com.yeshi.fanli.service.inter.config.SystemClientParamsService; import com.yeshi.fanli.service.inter.push.DeviceActiveService; import com.yeshi.fanli.util.StringUtil; import com.yeshi.fanli.util.ThreadUtil; import net.sf.json.JSONArray; import net.sf.json.JSONObject; @Controller @RequestMapping("/wxmp/api/v1/config") public class ConfigController { @Resource private SystemClientParamsService systemClientParamsService; @Resource private BusinessSystemService businessSystemService; @Resource private DeviceActiveService deviceActiveService; /** * 获取系统配置信息 * * @param acceptData * @param code * @param out */ @RequestMapping("getSystemClientConfig") public void getOpenId(WXMPAcceptData acceptData, HttpServletRequest request, PrintWriter out) { BusinessSystem system = businessSystemService.getBusinessSystemCache(acceptData.getPlatform(), acceptData.getAppId()); if (system == null) { out.print("系统不存在"); return; } List<SystemClientParams> systemClientParamsList = systemClientParamsService .getSystemClientParamsBySystemId(system.getId(), Integer.parseInt(acceptData.getVersion())); if (systemClientParamsList == null || systemClientParamsList.size() == 0) { out.print(JsonUtil.loadFalseResult("暂无数据")); return; } JSONArray array = new JSONArray(); for (SystemClientParams params : systemClientParamsList) { JSONObject item = new JSONObject(); item.put(params.getKey(), params.getValue()); } out.print(JsonUtil.loadTrueResult(array)); String ipInfo = IPUtil.getRemotIP(request) + ":" + request.getRemotePort(); ThreadUtil.run(new Runnable() { @Override public void run() { if (!StringUtil.isNullOrEmpty(acceptData.getDevice())) { // 安卓平台添加设备活跃记录 DeviceActive da = new DeviceActive(); da.setDevice(acceptData.getDevice()); da.setPlatform(DeviceActive.PLATFORM_WXMP); da.setVersionCode(Integer.parseInt(acceptData.getVersion())); da.setIpInfo(ipInfo); da.setChannel("wxmp"); da.setMac(null); deviceActiveService.addDeviceActive(da); } } }); } } fanli/src/main/java/com/yeshi/fanli/controller/wxmp/UserController.java
New file @@ -0,0 +1,36 @@ package com.yeshi.fanli.controller.wxmp; import java.io.PrintWriter; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.yeshi.utils.JsonUtil; import org.yeshi.utils.wx.WXXCXUtil; import com.yeshi.fanli.dto.WXMPAcceptData; import com.yeshi.fanli.util.Constant; import com.yeshi.fanli.util.StringUtil; import net.sf.json.JSONObject; @Controller @RequestMapping("/wxmp/api/v1/user") public class UserController { @RequestMapping("getOpenId") public void getOpenId(WXMPAcceptData acceptData, String code, PrintWriter out) { if (StringUtil.isNullOrEmpty(code)) { out.print(JsonUtil.loadFalseResult("code为空")); return; } String openId = WXXCXUtil.getOpenId(Constant.WXMP_APP_INFO, code); if (!StringUtil.isNullOrEmpty(openId)) { JSONObject data = new JSONObject(); data.put("openId", openId); out.print(JsonUtil.loadTrueResult(data)); } else { out.print(JsonUtil.loadFalseResult("openId获取失败")); } } } fanli/src/main/java/com/yeshi/fanli/dto/WXMPAcceptData.java
New file @@ -0,0 +1,83 @@ package com.yeshi.fanli.dto; /** * 微信接口数据接收 * * @author Administrator * */ public class WXMPAcceptData { private long timeStamp;// 时间戳 private String sign;// 签名 private String platform;// 客户端平台 private String wxVersion;// 微信版本号 private String version;// 小程序版本 private String appId;// private String openId; private String device; public String getDevice() { return device; } public void setDevice(String device) { this.device = device; } public long getTimeStamp() { return timeStamp; } public void setTimeStamp(long timeStamp) { this.timeStamp = timeStamp; } public String getSign() { return sign; } public void setSign(String sign) { this.sign = sign; } public String getPlatform() { return platform; } public void setPlatform(String platform) { this.platform = platform; } public String getWxVersion() { return wxVersion; } public void setWxVersion(String wxVersion) { this.wxVersion = wxVersion; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getAppId() { return appId; } public void setAppId(String appId) { this.appId = appId; } public String getOpenId() { return openId; } public void setOpenId(String openId) { this.openId = openId; } } fanli/src/main/java/com/yeshi/fanli/entity/common/JumpDetailV2.java
@@ -61,6 +61,17 @@ private Integer minAndroidAppVersion;// 最小Android版本 @org.yeshi.utils.mybatis.Column(name = "jp_min_ios_version") private Integer minIOSAppVersion;// 最小ios版本 @org.yeshi.utils.mybatis.Column(name = "jp_path") private String path;//小程序路径 public String getPath() { return path; } public void setPath(String path) { this.path = path; } public Integer getMinAndroidAppVersion() { return minAndroidAppVersion; fanli/src/main/java/com/yeshi/fanli/entity/push/DeviceActive.java
@@ -10,6 +10,7 @@ public static final int PLATFORM_ANDROID = 1; public static final int PLATFORM_IOS = 2; public static final int PLATFORM_WXMP = 4;//微信小程序 @Column(name = "da_id") private Long id; fanli/src/main/java/com/yeshi/fanli/entity/system/BusinessSystem.java
@@ -27,8 +27,6 @@ @org.yeshi.utils.mybatis.Column(name="id") private Long id; @org.yeshi.utils.mybatis.Column(name="name") @Column(name = "`name`", length = 50) private String name; fanli/src/main/java/com/yeshi/fanli/service/inter/config/BusinessSystemService.java
@@ -8,13 +8,13 @@ public BusinessSystem getBusinessSystem(String platform, String packages); public BusinessSystem getBusinessSystemCache(String platform, String packages); public List<BusinessSystem> getBusinessSystems(); /** * 通过id查询 * * @param id * @return */ fanli/src/main/java/com/yeshi/fanli/util/Constant.java
@@ -6,6 +6,7 @@ import java.util.Set; import org.yeshi.utils.annotation.MapUtil; import org.yeshi.utils.entity.wx.WXAPPInfo; import com.yeshi.fanli.dto.wx.WXAccountInfoDTO; import com.yeshi.fanli.entity.config.AlipayConfig; @@ -120,7 +121,6 @@ // 金币有效天数 public static final int GOLD_COIN_VALID_DAYS = 30; // 微信自动提现金额 public static final int AUTO_EXTRACT_MONEY = 1; // 微信自动提现最低余额 @@ -181,7 +181,6 @@ // 专属邀请码申请直接粉丝限制 public static final int INVITE_CODRE_TAILOR_LIMIT = 2; public static WXGZConfig wxGZConfig; @@ -246,6 +245,12 @@ public static final String WXHEADURL = "wx/headImg/"; public static final String WEBPAGE_SIGN_KEY = "@?,223Hbb88lll"; public static final String WXMP_SIGN_KEY="xyJBaNliK&*!uAIShEn8g@@"; public static final WXAPPInfo WXMP_APP_INFO=new WXAPPInfo("wxc22f3bd53cb25012", "4c7b166fecb6d9f53837e993f2214673", "", ""); // 新人抽奖-最大次数 public static final int MAX_COUNT_LOTTERY_NEWBIES = 5; @@ -329,8 +334,10 @@ return 1; else if ("ios".equalsIgnoreCase(platform)) return 2; else if ("wxmp".equalsIgnoreCase(platform)) return 4;// 未知 else return 0;// 未知 return 0; } public static String getAppName(String platform, String version) { fanli/src/main/java/com/yeshi/fanli/util/JumpDetailUtil.java
New file @@ -0,0 +1,40 @@ package com.yeshi.fanli.util; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Iterator; import com.yeshi.fanli.entity.common.JumpDetailV2; import net.sf.json.JSONObject; public class JumpDetailUtil { /** * 过滤小程序跳转参数 * * @param detail * @param params * @return */ public static JumpDetailV2 getWXMPJumDetail(JumpDetailV2 detail, JSONObject params) { String path = detail.getPath(); if (params != null) { path += "?"; for (Iterator<String> its = params.keys(); its.hasNext();) { String key = its.next(); try { path += (key + "=" + URLEncoder.encode(params.optString(key), "UTF-8") + "&"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } if (path.endsWith("&")) path = path.substring(0, path.length() - 1); JumpDetailV2 v2 = new JumpDetailV2(); v2.setPath(path); v2.setType(detail.getType()); return v2; } } fanli/src/test/java/org/fanli/elastic/Test_Query.java
@@ -49,7 +49,7 @@ public void detele() { try { ESOrderDao dao = BeanUtil.getBean(ESOrderDao.class); dao.delete("1_102205518158-42030576999"); // dao.delete("1_102205518158-42030576999"); System.out.println("-------------结束-------------"); } catch (Exception e) { e.printStackTrace(); utils/src/main/java/org/yeshi/utils/exception/WXMPException.java
New file @@ -0,0 +1,33 @@ package org.yeshi.utils.exception; /** * 微信小程序异常 * @author Administrator * */ public class WXMPException extends Exception { private static final long serialVersionUID = 1L; private int code; private String msg; public int getCode() { return code; } public String getMsg() { return msg; } public WXMPException(int code, String msg) { this.code = code; this.msg = msg; } public WXMPException() { } @Override public String getMessage() { return this.msg; } } utils/src/main/java/org/yeshi/utils/wx/WXXCXUtil.java
@@ -3,6 +3,9 @@ import java.io.InputStream; import org.yeshi.utils.HttpUtil; import org.yeshi.utils.entity.wx.WXAPPInfo; import com.aliyun.openservices.shade.io.netty.util.internal.StringUtil; import net.sf.json.JSONObject; @@ -34,4 +37,20 @@ return HttpUtil.postForInputstream(url, data.toString()); } public static String getOpenId(WXAPPInfo app, String code) { try { String url = String.format( "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", app.getAppId(), app.getAppSecret(), code); String result = HttpUtil.get(url); JSONObject json = JSONObject.fromObject(result); String openId = json.optString("openid"); if (!StringUtil.isNullOrEmpty(openId)) { return openId; } } catch (Exception e) { } return null; } }