From 10f9323c7341326813f73d4db5b8a00d4ee2123f Mon Sep 17 00:00:00 2001 From: wangsq Date: Thu, 18 Dec 2025 11:45:15 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=89=8B=E5=8A=A8=E9=80=80=E8=B4=B9=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E4=BD=8D=E7=BD=AE=E8=B0=83=E6=95=B4=202.=E5=8C=BB?= =?UTF-8?q?=E5=85=B1=E4=BD=93=E8=AE=A4=E8=AF=81=E5=8A=9F=E8=83=BD=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=AE=8C=E6=88=90.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ynxbd/common/TestA.java | 34 +---- .../ynxbd/common/action/test/TestAction.java | 13 +- .../com/ynxbd/wx/wxfactory/AesWxHelper.java | 6 + .../com/ynxbd/wx/wxfactory/WxAuthHelper.java | 125 ++++++++++++------ 4 files changed, 102 insertions(+), 76 deletions(-) diff --git a/src/main/java/com/ynxbd/common/TestA.java b/src/main/java/com/ynxbd/common/TestA.java index 599f4a0..d4f0998 100644 --- a/src/main/java/com/ynxbd/common/TestA.java +++ b/src/main/java/com/ynxbd/common/TestA.java @@ -1,28 +1,17 @@ package com.ynxbd.common; -import com.alibaba.fastjson.JSONObject; -import com.ynxbd.common.bean.pay.PEISOrderInfo; -import com.ynxbd.common.helper.common.Base64Helper; -import com.ynxbd.common.helper.common.JsonHelper; -import com.ynxbd.common.helper.http.OkHttpHelper; -import com.ynxbd.common.result.JsonResult; -import com.ynxbd.common.result.Result; -import com.ynxbd.wx.config.WeChatConfig; -import com.ynxbd.wx.utils.DesEncryptHelper; import lombok.extern.slf4j.Slf4j; -import okhttp3.FormBody; -import okhttp3.RequestBody; import org.apache.commons.lang3.ObjectUtils; import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Map; @Slf4j public class TestA { public static void main(String[] args) throws UnsupportedEncodingException { - // String a = ""; // String s = DesEncryptHelper.deCode(a); // System.out.println(s); @@ -36,25 +25,6 @@ public class TestA { // .build(); // log.info("[认证请求转发] resp:[{}]", requestBody); // log.info("[认证请求转发] resp:[{}]", JsonHelper.toJsonString(requestBody)); - - -// String data = OkHttpHelper.postFormStr("http://slxlfwsy.slxrmyy.cn/wx/wx_auth/is_auth", map -> { -// map.put("token", null); -// map.put("state", "aHR0cCUzQSUyRiUyRnNseGxmd3N5LnNseHJteXkuY24lMkZ3eCUyRndlYiUyRnJlZy1yZXNlcnZlLmh0bWwlMjMlMkY="); -// map.put("isUserInfo", false); -// map.put("enuId", false); -// map.put("protocolState", 0); -// }, null); - -// String data = OkHttpHelper.post("http://www.slxrmyy.cn/wx/wx_auth/is_auth", requestBody); -// JSONObject jsonObject = JsonHelper.parseObject(data); -// System.out.println(JsonHelper.toJsonString(jsonObject)); - -// -// String state = "aHR0cCUzQSUyRiUyRnNseGxmd3N5LnNseHJteXkuY24lMkZ3eCUyRndlYiUyRnJlZy1yZXNlcnZlLmh0bWwlMjMlMkY="; -// String decode = URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); -// System.out.println(decode); - } diff --git a/src/main/java/com/ynxbd/common/action/test/TestAction.java b/src/main/java/com/ynxbd/common/action/test/TestAction.java index c965d09..5391d21 100644 --- a/src/main/java/com/ynxbd/common/action/test/TestAction.java +++ b/src/main/java/com/ynxbd/common/action/test/TestAction.java @@ -2,12 +2,16 @@ package com.ynxbd.common.action.test; import com.ynxbd.common.action.base.BaseAction; import com.ynxbd.common.helper.common.DateHelper; +import com.ynxbd.common.helper.http.OkHttpHelper; import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ServiceException; +import com.ynxbd.wx.config.WeChatConfig; +import com.ynxbd.wx.wxfactory.AesWxHelper; import com.ynxbd.wx.wxfactory.WxPayHelper; import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Namespace; @@ -28,12 +32,16 @@ public class TestAction extends BaseAction { private static int i = 0; - @Action("refund_test") - public Result refund_test() throws ServiceException { + public synchronized void refund_handle() { if (i == 0) { i++; // WxPayHelper.refund("", "", new BigDecimal("0.900"), new BigDecimal("0.900"), "手动退费"); } + } + + @Action("refund_test") + public Result refund_test() throws ServiceException { + refund_handle(); return Result.success(); } @@ -98,7 +106,6 @@ public class TestAction extends BaseAction { } - // @Action("lock") // public String lock() { // return Result.success(update()); diff --git a/src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java index 2da8998..9f70158 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java @@ -15,6 +15,12 @@ public class AesWxHelper extends AesHelper { return encryptHex(data, KEY, IV); } + /** + * + * @param data 加密的数据 + * @param isDataNotNull 加密数据是否不允许为空 + * @return + */ public static String encode(String data, boolean isDataNotNull) { if (isDataNotNull && ObjectUtils.isEmpty(data)) { return null; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java index 2de9e73..44c1ae0 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java @@ -19,36 +19,43 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.net.URLDecoder; import java.net.URLEncoder; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @Slf4j public class WxAuthHelper { private static final int SESSION_MAX_INACTIVE_INTERVAL = 60 * 60; // session最大存活时间 1H + private static final String P_PREFIX = "_@"; // 前缀 + private static final String P_SUFFIX = ":"; // 后缀 + + private static final String AUTH_SESSION_ID_NAME = "SID"; + private static final String UNION_ID_NAME = "UID"; + + public static String auth(HttpServletRequest request, HttpServletResponse response, boolean isUserInfo) { String code = request.getParameter("code"); String state = request.getParameter("state"); // base64 - String params = request.getParameter("params"); + Map paramsMap = getParamsMap(request.getParameter("p")); - log.info("[授权] code={}, state={}, params={}", code, state, params); + log.info("[授权] code={}, state={}, paramsMap={}", code, state, JsonHelper.toJsonString(paramsMap)); try { state = state == null ? "" : URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); - String enUnionId = null; - String authSessionId = null; - - if (!ObjectUtils.isEmpty(params)) { - int index = params.indexOf("@SID="); - if (index == -1) index = params.indexOf("%40SID="); // 防止数据转义失败 - if (index != -1) { - enUnionId = params.substring(0, index); - authSessionId = params.substring(index); - authSessionId = AesWxHelper.decode(authSessionId); - } - } - log.info("[授权-解码] enUnionId={}, authSessionId={}, state={}", enUnionId, authSessionId, state); + String enUnionId = paramsMap.get(UNION_ID_NAME); + String enAuthSessionId = paramsMap.get(AUTH_SESSION_ID_NAME); + String authSessionId = AesWxHelper.decode(enAuthSessionId); + + paramsMap.get(AUTH_SESSION_ID_NAME); + +// if (!ObjectUtils.isEmpty(params)) { +// int index = params.indexOf("@" + AUTH_SESSION_ID_NAME + ":"); +// if (index == -1) index = params.indexOf("%40" + AUTH_SESSION_ID_NAME + ":"); // 防止数据转义失败 +// if (index != -1) { +// enUnionId = params.substring(0, index); +// authSessionId = params.substring(index); +// authSessionId = AesWxHelper.decode(authSessionId); +// } +// } + log.info("[授权-解码] enUnionId={}, enAuthSessionId={}, authSessionId={}, state={}", enUnionId, enAuthSessionId, authSessionId, state); SnsOath2AccessToken snsToken = WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code); log.info("[授权-用户]snsToken={}", JsonHelper.toJsonString(snsToken)); @@ -127,15 +134,15 @@ public class WxAuthHelper { String token = request.getParameter("token"); // 前端缓存 String state = request.getParameter("state"); String isUserInfo = request.getParameter("isUserInfo"); -// String protocolState = request.getParameter("protocolState"); - String enUID = ParamHelper.filterParamNull(request.getParameter("enUID"), ""); + String UID = ParamHelper.filterParamNull(request.getParameter(UNION_ID_NAME), ""); String deState = URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); + String authSessionId = null; if (WeChatConfig.IS_ENABLE_GMC && WeChatConfig.IS_GMC_SERVER && !isPayOAuth) { // 开启医共体开关 & 是医共体主服务器 & 不是支付授权 - authSessionId = AesWxHelper.decode(request.getHeader("AID")); + authSessionId = AesWxHelper.decode(request.getHeader(AUTH_SESSION_ID_NAME)); } - log.info("[is_auth]token={}, state={}, isUserInfo={}, authSessionId={}, enUID={}, deState={}", token, state, isUserInfo, authSessionId, enUID, deState); + log.warn("[授权is_auth] token={}, state={}, isUserInfo={}, authSessionId={}, UID={}, deState={}", token, state, isUserInfo, authSessionId, UID, deState); if (WeChatConfig.IS_ENABLE_GMC && !WeChatConfig.IS_GMC_SERVER && !isPayOAuth) { // 开启医共体开关 & 不是医共体主服务器 & 不是支付授权 try { // 请求转发 String serverDomain = WeChatConfig.getDomain(false, false); @@ -151,11 +158,10 @@ public class WxAuthHelper { params.put("token", token); params.put("state", state); params.put("isUserInfo", isUserInfo); - params.put("enuId", enUID); -// params.put("protocolState", protocolState); + params.put(UNION_ID_NAME, UID); }, headers -> { if (!ObjectUtils.isEmpty(sessionId)) { - headers.add("AID", AesWxHelper.encode(sessionId)); + headers.add(AUTH_SESSION_ID_NAME, AesWxHelper.encode(WeChatConfig.APP_ID + ":" + sessionId)); } }); Result result = Result.dataToResult(data, true); @@ -206,17 +212,17 @@ public class WxAuthHelper { Object sessionOpenId = session.getAttribute("openid"); String openid = sessionOpenId == null ? null : sessionOpenId.toString(); - log.info("[微信认证]获取 openid={}, authSessionId={}", openid, authSessionId); + log.info("[微信认证] openid={}, authSessionId={}", openid, authSessionId); if (!ObjectUtils.isEmpty(authSessionId) && ObjectUtils.isEmpty(openid)) { openid = WxCacheHelper.getOpenIdByAIDCache(authSessionId); - log.info("[微信AID认证]openid={}", openid); + log.warn("[微信AID认证]openid={}", openid); } if (openid != null) { log.info("[微信认证]openid={}", openid); User user = WxCacheHelper.getCacheUser(openid); if (user == null) { - return Result.success(getAuthUrl(request, state, isFindUserInfo, enUID, authSessionId)); + return Result.success(getAuthUrl(request, state, isFindUserInfo, UID, authSessionId)); } else { if (ObjectUtils.isEmpty(openid)) { openid = user.getOpenid(); // sessionId认证openid补充 @@ -225,7 +231,7 @@ public class WxAuthHelper { if (isFindUserInfo) { // 更换授权模式,需更新信息 if (user.getNickName() == null || user.getAvatar() == null) { - return Result.success(getAuthUrl(request, state, true, enUID, authSessionId)); + return Result.success(getAuthUrl(request, state, true, UID, authSessionId)); } } @@ -242,12 +248,12 @@ public class WxAuthHelper { return Result.success(map); } - return Result.success(getAuthUrl(request, state, isFindUserInfo, enUID, authSessionId)); + return Result.success(getAuthUrl(request, state, isFindUserInfo, UID, authSessionId)); } private static final String OAUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig.APP_ID + "&redirect_uri="; - private static String getAuthUrl(HttpServletRequest request, String state, boolean isFindUserInfo, String enUID, String SID) { + private static String getAuthUrl(HttpServletRequest request, String state, boolean isFindUserInfo, String UID, String SID) { // StringBuffer url = request.getRequestURL(); // String baseUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getServletContext().getContextPath()).append("/").toString(); if (state == null) { @@ -257,23 +263,25 @@ public class WxAuthHelper { String api = isFindUserInfo ? "u_auth" : "b_auth"; String scope = isFindUserInfo ? "snsapi_userinfo" : "snsapi_base"; - String enSID = ""; + UID = toURLParam(UNION_ID_NAME, UID); + String enSID = toURLParam(AUTH_SESSION_ID_NAME, AesWxHelper.encode(SID, true)); + + String params = enSID + UID; try { - enSID = (SID == null ? "" : ("%40SID=" + URLEncoder.encode(AesWxHelper.encode(SID), "UTF-8"))); + params = ObjectUtils.isEmpty(params) ? "" : URLEncoder.encode(params, "UTF-8"); + log.warn("[认证链接参数] params={}", params); } catch (Exception e) { log.error(e.getMessage()); } - - log.info("[认证链接] enSID={}, SID={}", enSID, SID); - state = OAUTH_URL + WeChatConfig.getBaseURL(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)) + "wx_auth/" + api + - "?state=" + state + + "?p=" + params + "&response_type=code" + - "&scope=" + scope + "&forcePopup=true" + - "¶ms=" + (enUID == null ? "" : enUID) + - enSID + + "&scope=" + scope + + "&forcePopup=true" + + "&state=" + state + // state位置固定 "#wechat_redirect"; + log.warn("[认证授权链接]state={}", state); return Base64Helper.encode(state); } @@ -289,6 +297,41 @@ public class WxAuthHelper { return request.isSecure(); } + public static String toURLParam(String key, String val) { + if (ObjectUtils.isEmpty(val)) return ""; + return P_PREFIX + key + P_SUFFIX + val; + } + + public static Map getParamsMap(String params) { + Map paramsMap = new HashMap<>(); + try { + if (ObjectUtils.isEmpty(params)) { + return paramsMap; + } + params = URLDecoder.decode(params, "UTF-8"); + String[] paramsArr = params.split(P_PREFIX); + String key, val; + String[] keyValueArr; + for (String paramItem : paramsArr) { + if (paramItem.isEmpty()) { + continue; + } + keyValueArr = paramItem.split(P_SUFFIX, 2); // 分割成最多两部分 + if (keyValueArr.length == 2) { + key = keyValueArr[0]; + val = keyValueArr[1]; + val = ParamHelper.filterParamNull(val, null); + if (val != null) { + paramsMap.put(key, val); + } + } + } + } catch (Exception e) { + log.error(e.getMessage()); + } + return paramsMap; + } + // // 医共体开启 & 不是支付授权 // private static boolean isAuthGMC(boolean isPayOAuth) {