diff --git a/pjcloud-common/pjcloud-common-core/src/main/java/com/bsd/pjcloud/common/core/util/R.java b/pjcloud-common/pjcloud-common-core/src/main/java/com/bsd/pjcloud/common/core/util/R.java index e728b7029..b743ed9da 100644 --- a/pjcloud-common/pjcloud-common-core/src/main/java/com/bsd/pjcloud/common/core/util/R.java +++ b/pjcloud-common/pjcloud-common-core/src/main/java/com/bsd/pjcloud/common/core/util/R.java @@ -81,6 +81,13 @@ public class R implements Serializable { return restResult(null, CommonConstants.FAIL, msg); } + /** + * 失败并指定业务码(非 0),便于前端区分提示(如浙政钉绑定后无系统用户)。 + */ + public static R failed(int code, String msg) { + return restResult(null, code, msg); + } + public static R failed(T data) { return restResult(data, CommonConstants.FAIL, null); } diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppMenuOpenController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppMenuOpenController.java index 5148dbadd..68bcd0586 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppMenuOpenController.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppMenuOpenController.java @@ -32,6 +32,7 @@ import java.util.List; public class AppMenuOpenController { private final ExternalAppConfig externalAppConfig; + private final RemoteAppMenuService remoteAppMenuService; /** diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/constant/ThirdPartyZzdBizCodes.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/constant/ThirdPartyZzdBizCodes.java new file mode 100644 index 000000000..fdee32a99 --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/constant/ThirdPartyZzdBizCodes.java @@ -0,0 +1,13 @@ +package com.bsd.pjcloud.thirdparty.constant; + +/** + * 浙政钉单点 / 短信绑定相关前端可识别业务码(与 {@link com.bsd.pjcloud.common.core.util.R#code} 一致)。 + */ +public final class ThirdPartyZzdBizCodes { + + private ThirdPartyZzdBizCodes() { + } + + /** 短信核验通过,但 sys_user 中不存在该手机号用户 */ + public static final int SYS_USER_NOT_FOUND_FOR_ZZD_BIND = 46001; +} diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java index aca574839..6dec3e9fb 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/ThirdPartyOAth2Cotroller.java @@ -19,6 +19,8 @@ import com.bsd.pjcloud.thirdparty.dto.*; import com.bsd.pjcloud.thirdparty.service.SmsService; import com.bsd.pjcloud.thirdparty.exception.ThirdPartyException; import com.bsd.pjcloud.thirdparty.vo.ZzdJsapiConfigVO; +import com.bsd.pjcloud.thirdparty.constant.ThirdPartyZzdBizCodes; +import com.bsd.pjcloud.thirdparty.entity.ThirdPartyZzdPhoneBindEntity; import com.bsd.pjcloud.thirdparty.service.ThirdPartyOAuth2Service; import com.bsd.pjcloud.thirdparty.service.ThirdPartyUserService; import com.bsd.pjcloud.thirdparty.service.ThirdPartyZzdSmsBindService; @@ -111,20 +113,22 @@ public class ThirdPartyOAth2Cotroller { log.warn("[zzdsso][ZZDUserDTO_JSON] 浙政钉开放平台映射后的对象,可整段复制做本地写死调试(含姓名手机号等敏感信息,调试完建议关日志或删此行) body={}", JSON.toJSONString(zzdUserDTO)); ZZDUserDTO.Ext ext = zzdUserDTO.getExt(); String employeeCode = ext != null ? ext.getEmployeeCode() : null; + String zzdOpenId = ext != null ? ext.getOpenid() : null; String mobile = zzdUserDTO.getMobile(); if (thirdPartyZzdSmsBindService.isEnabled()) { - if (StringUtils.isBlank(employeeCode)) { - return R.failed("浙政钉未返回员工编码,无法登录"); - } - var boundOpt = thirdPartyZzdSmsBindService.findByEmployeeCode(employeeCode); + var boundOpt = thirdPartyZzdSmsBindService.findBound(employeeCode, zzdOpenId); if (boundOpt.isPresent()) { - return buildZzdSsoTokenResult(employeeCode, boundOpt.get().getVerifiedPhone()); + ThirdPartyZzdPhoneBindEntity bound = boundOpt.get(); + return buildZzdSsoTokenResult(bound.getEmployeeCode(), bound.getVerifiedPhone()); } try { ZzdUserSnapshot snap = ThirdPartyZzdSmsBindService.snapshotOf(zzdUserDTO); + if (StringUtils.isBlank(snap.getEmployeeCode()) && StringUtils.isBlank(snap.getOpenid())) { + return R.failed("浙政钉未返回员工编码或 openid,无法绑定登录"); + } if (StringUtils.isBlank(snap.getEmployeeCode())) { - return R.failed("浙政钉未返回员工编码,无法登录"); + return R.failed("浙政钉未返回员工编码,无法完成首次手机号绑定,请在开放平台核对应用权限或联系管理员。"); } String bindSessionId = thirdPartyZzdSmsBindService.createBindSession(snap); HashMap need = new HashMap<>(); @@ -171,10 +175,12 @@ public class ThirdPartyOAth2Cotroller { R> byPhone = remoteUserService.getUserByMobile(dto.getMobilePhone()); List users = byPhone.getData(); if (CollectionUtils.isEmpty(users)) { - return R.failed("本系统不存在该手机号用户"); + return R.failed(ThirdPartyZzdBizCodes.SYS_USER_NOT_FOUND_FOR_ZZD_BIND, + "本系统暂无该手机号对应的用户,请联系管理员申请开通账号后再完成绑定。"); } SysUser sysUser = users.get(0); if (StringUtils.isNotBlank(sysUser.getDingtalkEmployeeCode()) + && StringUtils.isNotBlank(snap.getEmployeeCode()) && !sysUser.getDingtalkEmployeeCode().equals(snap.getEmployeeCode())) { return R.failed("浙政钉账号与本系统用户不一致"); } diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/ThirdPartyZzdSmsBindService.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/ThirdPartyZzdSmsBindService.java index 016bb158d..2bc14be94 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/ThirdPartyZzdSmsBindService.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/ThirdPartyZzdSmsBindService.java @@ -46,6 +46,28 @@ public class ThirdPartyZzdSmsBindService { return Optional.ofNullable(one); } + public Optional findByOpenId(String openId) { + if (StringUtils.isBlank(openId)) { + return Optional.empty(); + } + ThirdPartyZzdPhoneBindEntity one = thirdPartyZzdPhoneBindMapper.selectOne(Wrappers.lambdaQuery() + .eq(ThirdPartyZzdPhoneBindEntity::getOpenId, openId) + .eq(ThirdPartyZzdPhoneBindEntity::getDelFlag, "0") + .last("limit 1")); + return Optional.ofNullable(one); + } + + /** + * 已绑定记录:优先员工编码(与库 uk 一致),再按 openid(浙政钉侧稳定标识)。 + */ + public Optional findBound(String employeeCode, String openId) { + Optional byEmp = findByEmployeeCode(employeeCode); + if (byEmp.isPresent()) { + return byEmp; + } + return findByOpenId(openId); + } + public String createBindSession(ZzdUserSnapshot snapshot) throws JsonProcessingException { String id = UUID.randomUUID().toString().replace("-", ""); String key = REDIS_BIND_SESSION_PREFIX + id;