diff --git a/src/main/java/com/budwk/app/base/sms/impl/SmsServiceImpl.java b/src/main/java/com/budwk/app/base/sms/impl/SmsServiceImpl.java index 184a58d..ef467b5 100644 --- a/src/main/java/com/budwk/app/base/sms/impl/SmsServiceImpl.java +++ b/src/main/java/com/budwk/app/base/sms/impl/SmsServiceImpl.java @@ -50,6 +50,8 @@ public class SmsServiceImpl implements SmsService { @Inject private PropertiesProxy conf; + @Inject + private ZjnuMsgService zjnuMsgService; /** * 发送短信消息。 @@ -59,6 +61,9 @@ public class SmsServiceImpl implements SmsService { */ @Override public MsgPlatformResponse sendSms(MsgPlatformSmsRequest request) { + if ("prd".equalsIgnoreCase(conf.get("nutz.profiles.active"))) { + return zjnuMsgService.send(request, "SMS"); + } validateCommonRequest(request); JSONObject payload = buildCommonPayload(request, true); return doPost(SMS_API_PATH, payload); @@ -107,6 +112,9 @@ public class SmsServiceImpl implements SmsService { */ @Override public MsgPlatformResponse sendWechat(MsgPlatformWechatRequest request) { + if ("prd".equalsIgnoreCase(conf.get("nutz.profiles.active"))) { + return zjnuMsgService.send(request, "WeChat"); + } validateCommonRequest(request); if (Strings.isBlank(request.getWechatType())) { request.setWechatType("text"); @@ -342,6 +350,9 @@ public class SmsServiceImpl implements SmsService { * @param request 平台请求参数 */ private void fillDefaultSenderInfo(MsgPlatformBaseRequest request) { + if ("prd".equalsIgnoreCase(conf.get("nutz.profiles.active"))) { + return; + } request.setSendUserId(getRequiredConfig("msg.platform.default-send-user-id", "请先配置 msg.platform.default-send-user-id")); request.setSendUserName(getRequiredConfig("msg.platform.default-send-user-name", "请先配置 msg.platform.default-send-user-name")); request.setSendUnitId(conf.get("msg.platform.default-send-unit-id", "")); diff --git a/src/main/java/com/budwk/app/base/sms/impl/ZjnuMsgService.java b/src/main/java/com/budwk/app/base/sms/impl/ZjnuMsgService.java new file mode 100644 index 0000000..7c42daa --- /dev/null +++ b/src/main/java/com/budwk/app/base/sms/impl/ZjnuMsgService.java @@ -0,0 +1,146 @@ +package com.budwk.app.base.sms.impl; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.exception.BaseException; +import com.budwk.app.base.sms.model.*; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.web.commons.base.Globals; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.integration.jedis.RedisService; +import org.nutz.ioc.impl.PropertiesProxy; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.log.Log; +import org.nutz.log.Logs; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@IocBean +public class ZjnuMsgService { + private static final Log log = Logs.get(); + @Inject + private PropertiesProxy conf; + @Inject + private RedisService redisService; + @Inject + private Dao dao; + + public MsgPlatformResponse send(MsgPlatformBaseRequest request, String channel) { + MsgPlatformResponse result = new MsgPlatformResponse(); + if (!conf.getBoolean("msg.platform.enabled", false) + || !Globals.MyConfig.getBoolean("SendMsg", Globals.MyConfig.getBoolean("AppSms", false))) { + result.setCode(0); + result.setResult(true); + result.setMsg("通讯平台未启用,已跳过实际发送"); + return result; + } + if (request == null || Strings.isBlank(request.getInfo())) { + throw new BaseException("浙师大消息内容不能为空"); + } + List recipients = request.getRecipients(); + if (Strings.isNotBlank(request.getPersonInfo())) { + recipients = new ArrayList<>(); + for (String line : request.getPersonInfo().split("\\^@\\^")) { + String[] fields = line.split("\\|", -1); + MsgPlatformRecipient recipient = new MsgPlatformRecipient(); + recipient.setName(fields[0]); + recipient.setAccount(fields.length > 1 ? fields[1] : ""); + recipient.setMobile(fields.length > 4 ? fields[4] : ""); + recipients.add(recipient); + } + } + if (recipients == null || recipients.isEmpty()) { + throw new BaseException("接收人列表不能为空"); + } + List> receivers = new ArrayList<>(); + for (MsgPlatformRecipient recipient : recipients) { + if (recipient == null) { + throw new BaseException("接收人信息不能为空"); + } + String account = recipient.getAccount(); + String mobile = recipient.getMobile(); + if (Strings.isBlank(mobile) && Strings.isNotBlank(account) && account.matches("^\\d{11}$")) { + mobile = account; + account = null; + } + if (Strings.isBlank(account) && Strings.isNotBlank(mobile)) { + List users = dao.query(Sys_user.class, Cnd.where("mobile", "=", mobile)); + if (users.size() != 1) { + throw new BaseException("无法通过手机号唯一确定浙师大消息接收人工号"); + } + account = users.get(0).getLoginname(); + } + if (Strings.isBlank(account)) { + throw new BaseException("浙师大消息接收人工号不能为空"); + } + receivers.add(Map.of("type", "User", "userId", account, "name", Strings.sNull(recipient.getName()))); + } + try { + Map payload = new LinkedHashMap<>(); + payload.put("token", getToken()); + payload.put("msgtitle", Globals.AppName); + payload.put("msgContent", request.getInfo().replace("<", "<").replace(">", ">")); + payload.put("msgType", "0"); + payload.put("sendStatus", "1"); + payload.put("sendChannel", channel); + payload.put("sendMode", "normal"); + payload.put("receivers", JSONUtil.toJsonStr(receivers)); + payload.put("summary", ""); + payload.put("sendTime", Strings.sNull(request.getSendTime())); + payload.put("isReply", "0"); + payload.put("sendMsgType", "1"); + try (HttpResponse response = HttpRequest.post(baseUrl() + "/message/sendMessageApi") + .form(payload).timeout(conf.getInt("msg.platform.read-timeout", 10000)).execute()) { + JSONObject body = JSONUtil.parseObj(response.body()); + Integer code = body.getInt("rspCode"); + result.setHttpStatus(response.getStatus()); + result.setCode(code); + result.setResult(response.getStatus() == 200 && Integer.valueOf(0).equals(code)); + result.setMsg(body.getStr("rspMsg")); + if (!Boolean.TRUE.equals(result.getResult())) { + log.warn("浙师大消息发送失败,状态码:" + response.getStatus() + ",业务码:" + code); + } + return result; + } + } catch (Exception e) { + log.warn("浙师大消息接口调用失败:" + e.getClass().getSimpleName()); + result.setCode(-1); + result.setResult(false); + result.setMsg("浙师大消息接口调用失败"); + return result; + } + } + + private String getToken() { + String appId = conf.get("custom.msg.platform.app-id"); + String cacheKey = "zjnu:msg:token:" + appId; + String token = redisService.get(cacheKey); + if (Strings.isNotBlank(token)) { + return token; + } + try (HttpResponse response = HttpRequest.get(baseUrl() + "/msg/getThirdAPIToken") + .form("appId", appId, "appPassword", conf.get("custom.msg.platform.app-password")) + .timeout(conf.getInt("msg.platform.read-timeout", 10000)).execute()) { + JSONObject body = JSONUtil.parseObj(response.body()); + JSONObject data = body.getJSONObject("resultData"); + token = data == null ? null : data.getStr("token"); + if (response.getStatus() != 200 || Strings.isBlank(token)) { + throw new BaseException("获取浙师大消息平台token失败"); + } + redisService.setex(cacheKey, 1200, token); + return token; + } + } + + private String baseUrl() { + return conf.get("msg.platform.base-url").replaceAll("/+$", ""); + } +} diff --git a/src/main/java/com/budwk/app/sys/controller/SysLoginController.java b/src/main/java/com/budwk/app/sys/controller/SysLoginController.java index 4d16fd3..97dd728 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysLoginController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysLoginController.java @@ -190,23 +190,72 @@ public class SysLoginController { return ">>:" + sysUserService.loginPlus(sysUser, LoginType.CAS, request); } - @At(value = "/platform/wxwork/oauth2/callback", top = true) + @At(value = {"/platform/qywechat/oauth", "/platform/qywechat"}, top = true) + @Ok("re") + public String qywechatOauth(@Param("redirect") String redirect, HttpServletRequest request) { + if (!"prd".equalsIgnoreCase(conf.get("nutz.profiles.active")) || !conf.getBoolean("wxwork.enable", false)) { + return ">>:/platform/home"; + } + String state = UUID.randomUUID().toString(); + request.getSession().setAttribute("zjnuWxworkState", state); + String callback = Globals.AppDomain + conf.get("wxwork.redirectUri"); + if (StrUtil.isNotBlank(redirect)) { + callback += "?redirect=" + URLEncoder.encode(redirect, StandardCharsets.UTF_8); + } + return ">>:https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + conf.get("wxwork.corpId") + + "&redirect_uri=" + URLEncoder.encode(callback, StandardCharsets.UTF_8) + + "&response_type=code&scope=snsapi_base&state=" + state + "#wechat_redirect"; + } + + private String getZjnuWxworkToken() { + String cacheKey = RedisConstant.REDIS_KEY_WX_WORK_TOKEN + conf.get("wxwork.corpId"); + String token = redisService.get(cacheKey); + if (StrUtil.isNotBlank(token)) { + return token; + } + String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + conf.get("wxwork.corpId") + + "&corpsecret=" + conf.get("wxwork.corpSecret"); + JSONObject result = JSONUtil.parseObj(HttpUtil.get(url)); + token = result.getStr("access_token"); + if (!Integer.valueOf(0).equals(result.getInt("errcode")) || StrUtil.isBlank(token)) { + throw new BaseException("????????????"); + } + redisService.setex(cacheKey, Math.max(1, result.getInt("expires_in", 7200) - 200), token); + return token; + } + + @At(value = {"/platform/wxwork/oauth2/callback", "/platform/qywechat/getCode"}, top = true) @Ok("re") @ApiOperation("企业微信登录回调") public String wxworkOAuth2(@Param("code") String code, @Param("redirect") String redirect, HttpServletRequest request) { if (StrUtil.isBlank(code)) { return ">>:/platform/home"; } - String token = redisService.get(RedisConstant.REDIS_KEY_WX_WORK_TOKEN); + boolean zjnu = "prd".equalsIgnoreCase(conf.get("nutz.profiles.active")); + if (zjnu) { + Object expectedState = request.getSession().getAttribute("zjnuWxworkState"); + request.getSession().removeAttribute("zjnuWxworkState"); + if (!conf.getBoolean("wxwork.enable", false) || expectedState == null + || !expectedState.equals(request.getParameter("state"))) { + return ">>:/platform/home/500"; + } + } + String token = zjnu ? getZjnuWxworkToken() : redisService.get(RedisConstant.REDIS_KEY_WX_WORK_TOKEN); if (StrUtil.isBlank(token)) { return ">>:/platform/home"; } String url = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=ACCESS_TOKEN&code=CODE"; + if (zjnu) { + url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE"; + } url = url.replace("ACCESS_TOKEN", token).replace("CODE", code); String response = HttpUtil.get(url); JSONObject jsonObject = JSONUtil.parseObj(response); if (jsonObject.getInt("errcode") == 0) { - String loginName = jsonObject.getStr("userid"); + String loginName = jsonObject.getStr(zjnu ? "UserId" : "userid"); + if (StrUtil.isBlank(loginName)) { + return ">>:/platform/home/500"; + } sysUserService.checkThirdPlatformLoginName(loginName); Sys_user sysUser = sysUserService.loginByLoginName(loginName); return ">>:" + sysUserService.loginPlus(sysUser, LoginType.QI_YE_WECHAT, request); diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java index 44121b0..55c166a 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java @@ -496,6 +496,11 @@ public class SysUserServiceImpl extends BaseServiceImpl implements Sys String redirect = request.getParameter("redirect"); if (StrUtil.isNotBlank(redirect)) { + if ("prd".equalsIgnoreCase(conf.get("nutz.profiles.active")) + && (redirect.equals(Globals.AppDomain) || redirect.startsWith(Globals.AppDomain + "/") + || redirect.startsWith(Globals.AppDomain + "?") || redirect.startsWith(Globals.AppDomain + "#"))) { + return redirect; + } return Globals.AppDomain + redirect; } else { return Globals.AppDomain + "/platform/home"; diff --git a/src/main/java/com/budwk/app/web/commons/base/Globals.java b/src/main/java/com/budwk/app/web/commons/base/Globals.java index 20535a3..791a317 100644 --- a/src/main/java/com/budwk/app/web/commons/base/Globals.java +++ b/src/main/java/com/budwk/app/web/commons/base/Globals.java @@ -59,8 +59,12 @@ public class Globals { private SysTaskService sysTaskService; @Inject private PropertiesProxy conf; + private static String productionAppDomain; public void init() { + if ("prd".equalsIgnoreCase(conf.get("nutz.profiles.active"))) { + productionAppDomain = conf.get("custom.app-domain"); + } initSysConfig(sysConfigService); initRoute(sysRouteService); initTask(sysTaskService); @@ -95,6 +99,9 @@ public class Globals { default -> Globals.MyConfig.put(sysConfig.getConfigKey(), sysConfig.getConfigValue()); } } + if (Strings.isNotBlank(productionAppDomain)) { + Globals.AppDomain = productionAppDomain; + } } public static void initRoute(SysRouteService sysRouteService) { diff --git a/src/main/java/com/budwk/app/web/commons/proc/WkFailProcessor.java b/src/main/java/com/budwk/app/web/commons/proc/WkFailProcessor.java index 5fa871d..18731e7 100644 --- a/src/main/java/com/budwk/app/web/commons/proc/WkFailProcessor.java +++ b/src/main/java/com/budwk/app/web/commons/proc/WkFailProcessor.java @@ -188,7 +188,10 @@ public class WkFailProcessor extends ViewProcessor { if (Globals.sso) { //1.判断是否为企业微信浏览器并且对接了企业微信 - if (browserPlatform == BrowserPlatform.QI_YE_WEI_XIN && propertiesProxy.getBoolean("wxwork.enable", false)) { + if (browserPlatform == BrowserPlatform.QI_YE_WEI_XIN && propertiesProxy.getBoolean("wxwork.enable", false) + && "prd".equalsIgnoreCase(propertiesProxy.get("nutz.profiles.active"))) { + new ServerRedirectView("/platform/qywechat/oauth?redirect=" + redirect).render(request, response, null); + } else if (browserPlatform == BrowserPlatform.QI_YE_WEI_XIN && propertiesProxy.getBoolean("wxwork.enable", false)) { //进行企业微信授权 // String token = getWxWorkToken(); // if (StrUtil.isNotBlank(token)) { diff --git a/src/main/resources/application-prd.yaml b/src/main/resources/application-prd.yaml index 09e1b5b..b71b3e8 100644 --- a/src/main/resources/application-prd.yaml +++ b/src/main/resources/application-prd.yaml @@ -23,21 +23,21 @@ sdk: wxwork: - enable: false - corpId: wwaca81b3016b9a58c - corpSecret: Auc7919Su1Uds5ZErfZybBrt-8FkP5NA-dldZyQuOrM - agentId: 1000131 - redirectUri: /platform/wxwork/oauth2/callback + enable: true + corpId: 'ww5386df99fd3b6b0f' + corpSecret: 'HpSptE9wKZRq_c_kemAPJc0AfXkNSevpfYCJd1TTgrI' + agentId: '' + redirectUri: /platform/qywechat/getCode wx: enable: false - appID: wx4f65ff5f1b72e99d - appSecret: a65cec4fb69980bd88258fc8433a3eef + appID: 'MOCK_ZJNU_WX_APP_ID' + appSecret: 'MOCK_ZJNU_WX_APP_SECRET' redirectUri: /platform/wx/oauth2/callback cas: enable: true server-url-prefix: https://authserver.zjnu.edu.cn/authserver server-login-url: https://authserver.zjnu.edu.cn/authserver/login - qi-wx-server-login-url: httos:/cas.whcp.eou.cn/lyuapServer/wechatauz/wxAuthRedirect + qi-wx-server-login-url: https://authserver.zjnu.edu.cn/authserver/login client-host-url: https://lxy.zjnu.edu.cn client-call-back-url: /sso/login validation-type: cas @@ -48,6 +48,7 @@ sdk: bucket: zjnu custom: + app-domain: https://lxy.zjnu.edu.cn spdb: bab7: url: http://localhost:8888/supplierOpenApi/pointOrder/queryOrderInfo @@ -55,26 +56,28 @@ custom: keyHex: 00112233445566778899aabbccddeeff ivHex: 0102030405060708090a0b0c0d0e0f10 data-center: - grant_type: password - scope: read - username: 3848A3C738EFBB2C2E76E0D59B419DACA16A80F3AB0354CD - password: 3848A3C738EFBB2C2E76E0D59B419DACA16A80F3AB0354CD - token-url: https://bd.whcp.edu.cn/sjjkfwpt/api/bd-api/oauth/token + grant_type: '' + scope: '' + username: '' + password: '' + token-url: '' urls: teacher: http://mdm.zjnu.edu.cn/do/api/call/lxyxt_jzgjbxx unit: http://mdm.zjnu.edu.cn/do/api/call/lxyxt_dwxx msg: platform: - enabled: false - base-url: https://msg.cug.edu.cn - tp-name: nwszl.cug.edu.cn - default-send-user-id: 790036 - default-send-user-name: 周斐霏 - default-send-unit-id: 421 - default-send-unit-name: 工会 + enabled: true + app-id: 'MSG45363193' + app-password: 'OGQxNzVmOTJkZjM5NzJhZDg1MDNiZGM0MDQ5ZTJlNDY' + base-url: http://xxt.zjnu.edu.cn + tp-name: '' + default-send-user-id: '' + default-send-user-name: '' + default-send-unit-id: '' + default-send-unit-name: '' default-send-user-sign: '' - default-template-id: 1978744168869937153 - raw-secret-key: Z21kbDlwYWJ4c2Vtbnk4NjlxeQ== + default-template-id: '' + raw-secret-key: '' encrypted-secret-key: '' connect-timeout: 5000 read-timeout: 10000