Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-user
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xingmin
yd-user
Commits
b62266e0
Commit
b62266e0
authored
Oct 15, 2026
by
zhangxingmin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
push
parent
0e51e2e8
Hide whitespace changes
Inline
Side-by-side
Showing
54 changed files
with
3482 additions
and
2 deletions
+3482
-2
yd-user-api/src/main/java/com/yd/user/api/controller/ApiProjectThirdPartyBindController.java
+42
-0
yd-user-api/src/main/java/com/yd/user/api/controller/ApiThirdPartyPlatformController.java
+60
-0
yd-user-api/src/main/java/com/yd/user/api/controller/ApiThirdPartyScanLoginController.java
+80
-0
yd-user-api/src/main/java/com/yd/user/api/controller/ApiUserThirdPartyBindController.java
+70
-0
yd-user-api/src/main/java/com/yd/user/api/service/ApiProjectThirdPartyBindService.java
+34
-0
yd-user-api/src/main/java/com/yd/user/api/service/ApiScanLoginService.java
+70
-0
yd-user-api/src/main/java/com/yd/user/api/service/ApiThirdPartyPlatformService.java
+58
-0
yd-user-api/src/main/java/com/yd/user/api/service/ApiThirdPartyScanLoginService.java
+50
-0
yd-user-api/src/main/java/com/yd/user/api/service/ApiUserThirdPartyBindService.java
+43
-0
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiProjectThirdPartyBindServiceImpl.java
+72
-0
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiScanLoginServiceImpl.java
+445
-0
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiThirdPartyPlatformServiceImpl.java
+115
-0
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiThirdPartyScanLoginServiceImpl.java
+106
-0
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiUserThirdPartyBindServiceImpl.java
+61
-0
yd-user-api/src/main/java/com/yd/user/api/utils/WeChatApiUtil.java
+223
-0
yd-user-feign/src/main/java/com/yd/user/feign/client/thirdpartyplatform/ApiProjectThirdPartyBindFeignClient.java
+43
-0
yd-user-feign/src/main/java/com/yd/user/feign/client/thirdpartyplatform/ApiThirdPartyPlatformFeignClient.java
+69
-0
yd-user-feign/src/main/java/com/yd/user/feign/client/thirdscanlogin/ApiThirdPartyScanLoginFeignClient.java
+61
-0
yd-user-feign/src/main/java/com/yd/user/feign/client/thirdscanlogin/ApiUserThirdPartyBindFeignClient.java
+54
-0
yd-user-feign/src/main/java/com/yd/user/feign/constants/ScanLoginConstants.java
+137
-0
yd-user-feign/src/main/java/com/yd/user/feign/fallback/thirdpartyplatform/ApiProjectThirdPartyBindFeignFallbackFactory.java
+41
-0
yd-user-feign/src/main/java/com/yd/user/feign/fallback/thirdpartyplatform/ApiThirdPartyPlatformFeignFallbackFactory.java
+56
-0
yd-user-feign/src/main/java/com/yd/user/feign/fallback/thirdscanlogin/ApiThirdPartyScanLoginFeignFallbackFactory.java
+51
-0
yd-user-feign/src/main/java/com/yd/user/feign/fallback/thirdscanlogin/ApiUserThirdPartyBindFeignFallbackFactory.java
+46
-0
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdpartyplatform/ApiProjectThirdPartyBindRequest.java
+46
-0
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdpartyplatform/ApiThirdPartyPlatformAddRequest.java
+68
-0
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdpartyplatform/ApiThirdPartyPlatformEditRequest.java
+70
-0
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdpartyplatform/ApiThirdPartyPlatformPageRequest.java
+43
-0
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdscanlogin/ApiGenerateLoginQrCodeRequest.java
+36
-0
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdscanlogin/ApiGenerateShareBindQrCodeRequest.java
+49
-0
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdscanlogin/ApiVerifyTicketRequest.java
+32
-0
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdpartyplatform/ApiProjectThirdPartyBindResponse.java
+54
-0
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdpartyplatform/ApiThirdPartyPlatformDetailResponse.java
+79
-0
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdpartyplatform/ApiThirdPartyPlatformPageResponse.java
+59
-0
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdscanlogin/ApiGenerateQrCodeResponse.java
+28
-0
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdscanlogin/ApiScanStatusResponse.java
+43
-0
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdscanlogin/ApiUserThirdPartyBindResponse.java
+74
-0
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdscanlogin/ApiVerifyTicketResponse.java
+33
-0
yd-user-service/src/main/java/com/yd/user/service/dao/ProjectThirdPartyBindMapper.java
+16
-0
yd-user-service/src/main/java/com/yd/user/service/dao/ThirdPartyPlatformMapper.java
+16
-0
yd-user-service/src/main/java/com/yd/user/service/dao/UserThirdPartyBindMapper.java
+16
-0
yd-user-service/src/main/java/com/yd/user/service/model/ProjectThirdPartyBind.java
+110
-0
yd-user-service/src/main/java/com/yd/user/service/model/ThirdPartyPlatform.java
+134
-0
yd-user-service/src/main/java/com/yd/user/service/model/UserThirdPartyBind.java
+146
-0
yd-user-service/src/main/java/com/yd/user/service/service/IProjectThirdPartyBindService.java
+19
-0
yd-user-service/src/main/java/com/yd/user/service/service/IThirdPartyPlatformService.java
+24
-0
yd-user-service/src/main/java/com/yd/user/service/service/IUserThirdPartyBindService.java
+52
-0
yd-user-service/src/main/java/com/yd/user/service/service/impl/ProjectThirdPartyBindServiceImpl.java
+25
-0
yd-user-service/src/main/java/com/yd/user/service/service/impl/ThirdPartyPlatformServiceImpl.java
+32
-0
yd-user-service/src/main/java/com/yd/user/service/service/impl/UserThirdPartyBindServiceImpl.java
+74
-0
yd-user-service/src/main/java/com/yd/user/service/utils/MyBatisPlusCodeGenerator.java
+2
-2
yd-user-service/src/main/resources/mappers/ProjectThirdPartyBindMapper.xml
+5
-0
yd-user-service/src/main/resources/mappers/ThirdPartyPlatformMapper.xml
+5
-0
yd-user-service/src/main/resources/mappers/UserThirdPartyBindMapper.xml
+5
-0
No files found.
yd-user-api/src/main/java/com/yd/user/api/controller/ApiProjectThirdPartyBindController.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
controller
;
import
com.yd.common.result.Result
;
import
com.yd.user.api.service.ApiProjectThirdPartyBindService
;
import
com.yd.user.feign.client.thirdpartyplatform.ApiProjectThirdPartyBindFeignClient
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiProjectThirdPartyBindRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiProjectThirdPartyBindResponse
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.List
;
/**
* 项目与第三方平台绑定
*
* @author zxm
* @since 2026-10-13
*/
@RestController
@RequestMapping
(
"/projectThirdPartyBind"
)
@Validated
public
class
ApiProjectThirdPartyBindController
implements
ApiProjectThirdPartyBindFeignClient
{
@Autowired
private
ApiProjectThirdPartyBindService
apiProjectThirdPartyBindService
;
@Override
public
Result
bind
(
ApiProjectThirdPartyBindRequest
request
)
{
return
apiProjectThirdPartyBindService
.
bind
(
request
);
}
@Override
public
Result
unbind
(
Long
id
)
{
return
apiProjectThirdPartyBindService
.
unbind
(
id
);
}
@Override
public
Result
<
List
<
ApiProjectThirdPartyBindResponse
>>
list
(
String
projectBizId
)
{
return
apiProjectThirdPartyBindService
.
list
(
projectBizId
);
}
}
yd-user-api/src/main/java/com/yd/user/api/controller/ApiThirdPartyPlatformController.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
controller
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.yd.common.result.Result
;
import
com.yd.user.api.service.ApiThirdPartyPlatformService
;
import
com.yd.user.feign.client.thirdpartyplatform.ApiThirdPartyPlatformFeignClient
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformAddRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformEditRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformPageRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformDetailResponse
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformPageResponse
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
javax.annotation.Resource
;
/**
* 第三方平台配置
*
* @author zxm
* @since 2026-10-13
*/
@RestController
@RequestMapping
(
"/thirdPartyPlatform"
)
@Validated
public
class
ApiThirdPartyPlatformController
implements
ApiThirdPartyPlatformFeignClient
{
@Resource
private
ApiThirdPartyPlatformService
apiThirdPartyPlatformService
;
@Override
public
Result
<
IPage
<
ApiThirdPartyPlatformPageResponse
>>
page
(
ApiThirdPartyPlatformPageRequest
request
)
{
return
apiThirdPartyPlatformService
.
page
(
request
);
}
@Override
public
Result
<
ApiThirdPartyPlatformDetailResponse
>
detail
(
Long
id
)
{
return
apiThirdPartyPlatformService
.
detail
(
id
);
}
@Override
public
Result
add
(
ApiThirdPartyPlatformAddRequest
request
)
{
return
apiThirdPartyPlatformService
.
add
(
request
);
}
@Override
public
Result
edit
(
ApiThirdPartyPlatformEditRequest
request
)
{
return
apiThirdPartyPlatformService
.
edit
(
request
);
}
@Override
public
Result
del
(
Long
id
)
{
return
apiThirdPartyPlatformService
.
del
(
id
);
}
@Override
public
Result
editStatus
(
Long
id
,
Integer
status
)
{
return
apiThirdPartyPlatformService
.
editStatus
(
id
,
status
);
}
}
yd-user-api/src/main/java/com/yd/user/api/controller/ApiThirdPartyScanLoginController.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
controller
;
import
com.yd.common.result.Result
;
import
com.yd.user.api.service.ApiThirdPartyScanLoginService
;
import
com.yd.user.feign.client.thirdscanlogin.ApiThirdPartyScanLoginFeignClient
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateLoginQrCodeRequest
;
import
com.yd.user.feign.request.thirdscanlogin.ApiVerifyTicketRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiScanStatusResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiVerifyTicketResponse
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* 第三方扫码登录信息
*
* @author zxm
* @since 2026-10-13
*/
@RestController
@RequestMapping
(
"/thirdPartyScanLogin"
)
@Validated
public
class
ApiThirdPartyScanLoginController
implements
ApiThirdPartyScanLoginFeignClient
{
@Autowired
private
ApiThirdPartyScanLoginService
apiThirdPartyScanLoginService
;
/**
* 生成登录二维码
* @param request 请求参数
* @return 二维码信息
*/
@Override
public
Result
<
ApiGenerateQrCodeResponse
>
generateLoginQrCode
(
ApiGenerateLoginQrCodeRequest
request
)
{
return
apiThirdPartyScanLoginService
.
generateLoginQrCode
(
request
);
}
/**
* 扫码回调(微信服务器调用,xml解析出来二维码业务类型,根据业务类型处理不同的业务逻辑,目前两种类型:分享绑定和扫码登录)
* @param appId 公众号appId
* @param xml 微信XML
* @return success
*/
@Override
public
String
loginWechatCallback
(
String
appId
,
String
xml
)
{
return
apiThirdPartyScanLoginService
.
handleLoginWechatCallback
(
appId
,
xml
);
}
/**
* 查询扫码状态
* @param qrId 二维码参数
* @return 扫码状态
*/
@Override
public
Result
<
ApiScanStatusResponse
>
queryScanStatus
(
String
qrId
)
{
return
apiThirdPartyScanLoginService
.
queryScanStatus
(
qrId
);
}
/**
* 校验 loginTicket
* @param request 校验参数
* @return 校验结果
*/
@Override
public
Result
<
ApiVerifyTicketResponse
>
verifyTicket
(
ApiVerifyTicketRequest
request
)
{
return
apiThirdPartyScanLoginService
.
verifyTicket
(
request
);
}
/**
* 消费 loginTicket
* @param request 消费参数
* @return 是否成功
*/
@Override
public
Result
<
Boolean
>
consumeTicket
(
ApiVerifyTicketRequest
request
)
{
return
apiThirdPartyScanLoginService
.
consumeTicket
(
request
);
}
}
yd-user-api/src/main/java/com/yd/user/api/controller/ApiUserThirdPartyBindController.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
controller
;
import
com.yd.common.result.Result
;
import
com.yd.user.api.service.ApiUserThirdPartyBindService
;
import
com.yd.user.feign.client.thirdscanlogin.ApiUserThirdPartyBindFeignClient
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateShareBindQrCodeRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiUserThirdPartyBindResponse
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.List
;
/**
* 用户与第三方绑定关系信息
*
* @author zxm
* @since 2026-10-13
*/
@RestController
@RequestMapping
(
"/userThirdPartyBind"
)
@Validated
public
class
ApiUserThirdPartyBindController
implements
ApiUserThirdPartyBindFeignClient
{
@Autowired
private
ApiUserThirdPartyBindService
apiUserThirdPartyBindService
;
/**
* 生成分享绑定二维码
* @param request 请求参数
* @return 二维码信息
*/
@Override
public
Result
<
ApiGenerateQrCodeResponse
>
generateShareBindQrCode
(
ApiGenerateShareBindQrCodeRequest
request
)
{
return
apiUserThirdPartyBindService
.
generateShareBindQrCode
(
request
);
}
// /**
// * 分享扫码关注回调(微信服务器调用)
// * @param appId 公众号appId
// * @param xml 微信XML
// * @return success
// */
// @Override
// public String shareWechatCallback(String appId, String xml) {
// return apiUserThirdPartyBindService.handleShareWechatCallback(appId, xml);
// }
/**
* 查询绑定关系
* @param unionid 微信unionid
* @param projectBizId 项目ID
* @return 绑定列表
*/
@Override
public
Result
<
List
<
ApiUserThirdPartyBindResponse
>>
queryBind
(
String
unionid
,
String
projectBizId
)
{
return
apiUserThirdPartyBindService
.
queryBind
(
unionid
,
projectBizId
);
}
/**
* 解绑
* @param id 主键
* @return 操作结果
*/
@Override
public
Result
unbind
(
Long
id
)
{
return
apiUserThirdPartyBindService
.
unbind
(
id
);
}
}
yd-user-api/src/main/java/com/yd/user/api/service/ApiProjectThirdPartyBindService.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiProjectThirdPartyBindRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiProjectThirdPartyBindResponse
;
import
java.util.List
;
/**
* 项目与第三方平台绑定 API Service
*/
public
interface
ApiProjectThirdPartyBindService
{
/**
* 绑定
* @param request 绑定参数
* @return 操作结果
*/
Result
bind
(
ApiProjectThirdPartyBindRequest
request
);
/**
* 解绑
* @param id 主键
* @return 操作结果
*/
Result
unbind
(
Long
id
);
/**
* 查询项目绑定列表
* @param projectBizId 项目ID
* @return 绑定列表
*/
Result
<
List
<
ApiProjectThirdPartyBindResponse
>>
list
(
String
projectBizId
);
}
yd-user-api/src/main/java/com/yd/user/api/service/ApiScanLoginService.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateLoginQrCodeRequest
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateShareBindQrCodeRequest
;
import
com.yd.user.feign.request.thirdscanlogin.ApiVerifyTicketRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiScanStatusResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiVerifyTicketResponse
;
/**
* 扫码登录核心服务
*/
public
interface
ApiScanLoginService
{
/**
* 生成分享绑定二维码
*
* @param request 请求参数
* @return 二维码信息
*/
ApiGenerateQrCodeResponse
generateShareBindQrCode
(
ApiGenerateShareBindQrCodeRequest
request
);
/**
* 处理分享扫码回调
*
* @param appId 公众号appId
* @param xml 微信XML
*/
void
handleShareWechatCallback
(
String
appId
,
String
xml
);
/**
* 生成登录二维码
*
* @param request 请求参数
* @return 二维码信息
*/
ApiGenerateQrCodeResponse
generateLoginQrCode
(
ApiGenerateLoginQrCodeRequest
request
);
/**
* 处理登录扫码回调
*
* @param appId 公众号appId
* @param xml 微信XML
*/
void
handleLoginWechatCallback
(
String
appId
,
String
xml
);
/**
* 查询扫码状态
*
* @param qrId 二维码参数
* @return 扫码状态
*/
ApiScanStatusResponse
queryScanStatus
(
String
qrId
);
/**
* 校验 loginTicket
*
* @param request 校验参数
* @return 校验结果
*/
ApiVerifyTicketResponse
verifyTicket
(
ApiVerifyTicketRequest
request
);
/**
* 消费 loginTicket
*
* @param request 消费参数
* @return 是否成功
*/
boolean
consumeTicket
(
ApiVerifyTicketRequest
request
);
}
yd-user-api/src/main/java/com/yd/user/api/service/ApiThirdPartyPlatformService.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformAddRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformEditRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformPageRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformDetailResponse
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformPageResponse
;
/**
* 第三方平台配置 API Service
*/
public
interface
ApiThirdPartyPlatformService
{
/**
* 分页查询
* @param request 查询条件
* @return 分页结果
*/
Result
<
IPage
<
ApiThirdPartyPlatformPageResponse
>>
page
(
ApiThirdPartyPlatformPageRequest
request
);
/**
* 详情
* @param id 主键
* @return 详情
*/
Result
<
ApiThirdPartyPlatformDetailResponse
>
detail
(
Long
id
);
/**
* 新增
* @param request 新增参数
* @return 操作结果
*/
Result
add
(
ApiThirdPartyPlatformAddRequest
request
);
/**
* 编辑
* @param request 编辑参数
* @return 操作结果
*/
Result
edit
(
ApiThirdPartyPlatformEditRequest
request
);
/**
* 删除
* @param id 主键
* @return 操作结果
*/
Result
del
(
Long
id
);
/**
* 启用/禁用
* @param id 主键
* @param status 状态
* @return 操作结果
*/
Result
editStatus
(
Long
id
,
Integer
status
);
}
yd-user-api/src/main/java/com/yd/user/api/service/ApiThirdPartyScanLoginService.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateLoginQrCodeRequest
;
import
com.yd.user.feign.request.thirdscanlogin.ApiVerifyTicketRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiScanStatusResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiVerifyTicketResponse
;
/**
* 第三方扫码登录 API Service
*/
public
interface
ApiThirdPartyScanLoginService
{
/**
* 生成登录二维码
* @param request 请求参数
* @return 二维码信息
*/
Result
<
ApiGenerateQrCodeResponse
>
generateLoginQrCode
(
ApiGenerateLoginQrCodeRequest
request
);
/**
* 扫码回调(微信服务器调用,xml解析出来二维码业务类型,根据业务类型处理不同的业务逻辑,目前两种类型:分享绑定和扫码登录)
* @param appId 公众号appId
* @param xml 微信XML
* @return success
*/
String
handleLoginWechatCallback
(
String
appId
,
String
xml
);
/**
* 查询扫码状态
* @param qrId 二维码参数
* @return 扫码状态
*/
Result
<
ApiScanStatusResponse
>
queryScanStatus
(
String
qrId
);
/**
* 校验 loginTicket
* @param request 校验参数
* @return 校验结果
*/
Result
<
ApiVerifyTicketResponse
>
verifyTicket
(
ApiVerifyTicketRequest
request
);
/**
* 消费 loginTicket
* @param request 消费参数
* @return 是否成功
*/
Result
<
Boolean
>
consumeTicket
(
ApiVerifyTicketRequest
request
);
}
yd-user-api/src/main/java/com/yd/user/api/service/ApiUserThirdPartyBindService.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateShareBindQrCodeRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiUserThirdPartyBindResponse
;
import
java.util.List
;
/**
* 用户与第三方绑定关系 API Service
*/
public
interface
ApiUserThirdPartyBindService
{
/**
* 生成分享绑定二维码
* @param request 请求参数
* @return 二维码信息
*/
Result
<
ApiGenerateQrCodeResponse
>
generateShareBindQrCode
(
ApiGenerateShareBindQrCodeRequest
request
);
/**
* 处理分享扫码回调
* @param appId 公众号appId
* @param xml 微信XML
* @return success
*/
String
handleShareWechatCallback
(
String
appId
,
String
xml
);
/**
* 查询绑定关系
* @param unionid 微信unionid
* @param projectBizId 项目ID
* @return 绑定列表
*/
Result
<
List
<
ApiUserThirdPartyBindResponse
>>
queryBind
(
String
unionid
,
String
projectBizId
);
/**
* 解绑
* @param id 主键
* @return 操作结果
*/
Result
unbind
(
Long
id
);
}
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiProjectThirdPartyBindServiceImpl.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.user.api.service.ApiProjectThirdPartyBindService
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiProjectThirdPartyBindRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiProjectThirdPartyBindResponse
;
import
com.yd.user.service.model.ProjectThirdPartyBind
;
import
com.yd.user.service.service.IProjectThirdPartyBindService
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.time.LocalDateTime
;
import
java.util.List
;
import
java.util.stream.Collectors
;
/**
* 项目与第三方平台绑定 API Service 实现
*/
@Service
public
class
ApiProjectThirdPartyBindServiceImpl
implements
ApiProjectThirdPartyBindService
{
@Autowired
private
IProjectThirdPartyBindService
iProjectThirdPartyBindService
;
@Override
public
Result
bind
(
ApiProjectThirdPartyBindRequest
request
)
{
// 校验是否已绑定
long
count
=
iProjectThirdPartyBindService
.
count
(
new
LambdaQueryWrapper
<
ProjectThirdPartyBind
>()
.
eq
(
ProjectThirdPartyBind:
:
getProjectBizId
,
request
.
getProjectBizId
())
.
eq
(
ProjectThirdPartyBind:
:
getPlatformCode
,
request
.
getPlatformCode
())
.
eq
(
ProjectThirdPartyBind:
:
getIsDeleted
,
0
));
if
(
count
>
0
)
{
throw
new
BusinessException
(
"该项目已绑定此平台"
);
}
ProjectThirdPartyBind
entity
=
new
ProjectThirdPartyBind
();
BeanUtils
.
copyProperties
(
request
,
entity
);
entity
.
setIsDeleted
(
0
);
entity
.
setCreateTime
(
LocalDateTime
.
now
());
entity
.
setUpdateTime
(
LocalDateTime
.
now
());
iProjectThirdPartyBindService
.
save
(
entity
);
return
Result
.
success
();
}
@Override
public
Result
unbind
(
Long
id
)
{
ProjectThirdPartyBind
entity
=
iProjectThirdPartyBindService
.
getById
(
id
);
if
(
entity
==
null
)
{
throw
new
BusinessException
(
"绑定关系不存在"
);
}
entity
.
setIsDeleted
(
1
);
entity
.
setUpdateTime
(
LocalDateTime
.
now
());
iProjectThirdPartyBindService
.
updateById
(
entity
);
return
Result
.
success
();
}
@Override
public
Result
<
List
<
ApiProjectThirdPartyBindResponse
>>
list
(
String
projectBizId
)
{
List
<
ProjectThirdPartyBind
>
list
=
iProjectThirdPartyBindService
.
list
(
new
LambdaQueryWrapper
<
ProjectThirdPartyBind
>()
.
eq
(
ProjectThirdPartyBind:
:
getProjectBizId
,
projectBizId
)
.
eq
(
ProjectThirdPartyBind:
:
getIsDeleted
,
0
));
List
<
ApiProjectThirdPartyBindResponse
>
responseList
=
list
.
stream
().
map
(
entity
->
{
ApiProjectThirdPartyBindResponse
response
=
new
ApiProjectThirdPartyBindResponse
();
BeanUtils
.
copyProperties
(
entity
,
response
);
return
response
;
}).
collect
(
Collectors
.
toList
());
return
Result
.
success
(
responseList
);
}
}
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiScanLoginServiceImpl.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
.
impl
;
import
com.yd.common.utils.RedisUtil
;
import
com.yd.user.api.service.ApiScanLoginService
;
import
com.yd.user.api.utils.WeChatApiUtil
;
import
com.yd.user.feign.constants.ScanLoginConstants
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateLoginQrCodeRequest
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateShareBindQrCodeRequest
;
import
com.yd.user.feign.request.thirdscanlogin.ApiVerifyTicketRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiScanStatusResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiVerifyTicketResponse
;
import
com.yd.user.service.model.ProjectThirdPartyBind
;
import
com.yd.user.service.model.ThirdPartyPlatform
;
import
com.yd.user.service.model.UserThirdPartyBind
;
import
com.yd.user.service.service.IProjectThirdPartyBindService
;
import
com.yd.user.service.service.IThirdPartyPlatformService
;
import
com.yd.user.service.service.IUserThirdPartyBindService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.time.LocalDateTime
;
import
java.util.UUID
;
import
java.util.concurrent.TimeUnit
;
/**
* 扫码登录核心服务实现
*/
@Slf4j
@Service
public
class
ApiScanLoginServiceImpl
implements
ApiScanLoginService
{
@Autowired
private
IThirdPartyPlatformService
thirdPartyPlatformService
;
@Autowired
private
IProjectThirdPartyBindService
projectThirdPartyBindService
;
@Autowired
private
IUserThirdPartyBindService
userThirdPartyBindService
;
@Autowired
private
RedisUtil
redisUtil
;
@Autowired
private
WeChatApiUtil
weChatApiUtil
;
/**
* 生成分享绑定二维码
*
* @param request 请求参数
* @return 二维码信息
*/
@Override
public
ApiGenerateQrCodeResponse
generateShareBindQrCode
(
ApiGenerateShareBindQrCodeRequest
request
)
{
// 1. 查询项目绑定的公众号配置
ProjectThirdPartyBind
projectBind
=
projectThirdPartyBindService
.
getByProjectAndType
(
request
.
getTenantBizId
(),
request
.
getProjectBizId
(),
request
.
getPlatformType
()
==
null
?
ScanLoginConstants
.
PLATFORM_TYPE_GZH
:
request
.
getPlatformType
());
if
(
projectBind
==
null
)
{
throw
new
RuntimeException
(
"租户项目未绑定公众号平台"
);
}
//查询第三方平台基础配置信息
ThirdPartyPlatform
platform
=
thirdPartyPlatformService
.
getByPlatformCode
(
projectBind
.
getPlatformCode
());
if
(
platform
==
null
)
{
throw
new
RuntimeException
(
"第三方平台配置信息不存在"
);
}
// 2. 生成 qrId
String
qrId
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
// 3. 构造 scene_str自定义参数,格式:bizType:qrId:tenantBizId:projectBizId:userId
String
sceneStr
=
ScanLoginConstants
.
BIZ_TYPE_SHARE_BIND
+
":"
+
qrId
+
":"
+
request
.
getTenantBizId
()
+
":"
+
request
.
getProjectBizId
()
+
":"
+
request
.
getUserId
();
// 4. 调用微信接口生成带参临时二维码
String
ticket
=
weChatApiUtil
.
createTemporaryQrCode
(
platform
.
getAppId
(),
platform
.
getAppSecret
(),
sceneStr
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
);
String
qrCodeUrl
=
"https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="
+
ticket
;
// 5. 缓存扫码会话,状态为待扫码
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
,
ScanLoginConstants
.
STATUS_WAIT_SCAN
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
// 6. 缓存分享绑定额外信息,以便回调时使用
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":projectBizId"
,
request
.
getProjectBizId
(),
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":userId"
,
request
.
getUserId
(),
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":bizType"
,
ScanLoginConstants
.
BIZ_TYPE_SHARE_BIND
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
// 7. 构建返回
ApiGenerateQrCodeResponse
response
=
new
ApiGenerateQrCodeResponse
();
response
.
setQrId
(
qrId
);
response
.
setQrCodeUrl
(
qrCodeUrl
);
response
.
setExpireSeconds
((
long
)
ScanLoginConstants
.
QR_EXPIRE_SECONDS
);
return
response
;
}
/**
* 处理分享扫码回调
*
* @param appId 公众号appId
* @param xml 微信XML
*/
@Override
public
void
handleShareWechatCallback
(
String
appId
,
String
xml
)
{
// 1. 解析微信XML,获取事件类型、openid、EventKey
String
eventType
=
weChatApiUtil
.
getEventType
(
xml
);
//公众号openid
String
openid
=
weChatApiUtil
.
getFromUserName
(
xml
);
String
eventKey
=
weChatApiUtil
.
getEventKey
(
xml
);
if
(
StringUtils
.
isBlank
(
openid
)
||
StringUtils
.
isBlank
(
eventKey
))
{
log
.
warn
(
"分享扫码回调参数缺失,openid={}, eventKey={}"
,
openid
,
eventKey
);
return
;
}
// 2. 解析 EventKey,格式:bizType:qrId:tenantBizId:projectBizId:userId
String
[]
parts
=
eventKey
.
split
(
":"
);
if
(
parts
.
length
<
5
)
{
log
.
warn
(
"分享扫码 EventKey 格式错误:{}"
,
eventKey
);
return
;
}
//二维码业务类型: 分享绑定
String
bizType
=
parts
[
0
];
//扫码唯一ID
String
qrId
=
parts
[
1
];
//租户ID
String
tenantBizId
=
parts
[
2
];
//项目ID
String
projectBizId
=
parts
[
3
];
//用户ID
String
userId
=
parts
[
4
];
if
(!
ScanLoginConstants
.
BIZ_TYPE_SHARE_BIND
.
equals
(
bizType
))
{
log
.
warn
(
"非分享绑定业务类型:{}"
,
bizType
);
return
;
}
// 3. 幂等处理:检查该事件是否已处理
String
idempotentKey
=
ScanLoginConstants
.
REDIS_KEY_IDEMPOTENT
+
openid
+
":"
+
eventType
+
":"
+
eventKey
;
Boolean
success
=
redisUtil
.
tryLock
(
idempotentKey
,
"1"
,
5
,
TimeUnit
.
MINUTES
);
if
(
Boolean
.
FALSE
.
equals
(
success
))
{
log
.
info
(
"分享扫码回调重复,已忽略,openid={}, eventKey={}"
,
openid
,
eventKey
);
return
;
}
// 4. 用 openid 换 unionid
String
unionid
=
weChatApiUtil
.
getUnionIdByOpenId
(
appId
,
openid
);
if
(
StringUtils
.
isBlank
(
unionid
))
{
log
.
warn
(
"无法获取 unionid,openid={}"
,
openid
);
return
;
}
// 5. 写入绑定关系表
// 先查询用户是否已存在绑定记录
UserThirdPartyBind
existBind
=
userThirdPartyBindService
.
queryBind
(
tenantBizId
,
projectBizId
,
unionid
,
openid
);
if
(
existBind
!=
null
)
{
log
.
info
(
"该微信已绑定,无需重复绑定,openid={}, projectBizId={}"
,
openid
,
projectBizId
);
}
else
{
UserThirdPartyBind
bind
=
new
UserThirdPartyBind
();
bind
.
setTenantBizId
(
tenantBizId
);
bind
.
setProjectBizId
(
projectBizId
);
bind
.
setUserId
(
userId
);
bind
.
setUnionid
(
unionid
);
bind
.
setGzhOpenid
(
openid
);
bind
.
setBindSource
(
ScanLoginConstants
.
BIND_SOURCE_SHARE
);
bind
.
setBindStatus
(
ScanLoginConstants
.
BIND_STATUS_BOUND
);
bind
.
setBindTime
(
LocalDateTime
.
now
());
bind
.
setIsDeleted
(
0
);
userThirdPartyBindService
.
bind
(
bind
);
log
.
info
(
"分享扫码绑定成功,openid={}, unionid={}, userId={}, projectBizId={}"
,
openid
,
unionid
,
userId
,
projectBizId
);
}
// 6. 更新二维码状态为已绑定(可选)
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
,
ScanLoginConstants
.
STATUS_CONFIRMED
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
}
/**
* 生成登录二维码
*
* @param request 请求参数
* @return 二维码信息
*/
@Override
public
ApiGenerateQrCodeResponse
generateLoginQrCode
(
ApiGenerateLoginQrCodeRequest
request
)
{
// 1. 查询项目绑定的公众号配置
ProjectThirdPartyBind
projectBind
=
projectThirdPartyBindService
.
getByProjectAndType
(
request
.
getTenantBizId
(),
request
.
getProjectBizId
(),
request
.
getPlatformType
()
==
null
?
ScanLoginConstants
.
PLATFORM_TYPE_GZH
:
request
.
getPlatformType
());
if
(
projectBind
==
null
)
{
throw
new
RuntimeException
(
"项目未绑定公众号平台"
);
}
ThirdPartyPlatform
platform
=
thirdPartyPlatformService
.
getByPlatformCode
(
projectBind
.
getPlatformCode
());
if
(
platform
==
null
)
{
throw
new
RuntimeException
(
"平台配置不存在"
);
}
// 2. 生成 qrId
String
qrId
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
// 3. 构造 scene_str,格式:bizType:qrId:tenantBizId:projectBizId
String
sceneStr
=
ScanLoginConstants
.
BIZ_TYPE_LOGIN
+
":"
+
qrId
+
":"
+
request
.
getTenantBizId
()
+
":"
+
request
.
getProjectBizId
();
// 4. 调用微信接口生成带参临时二维码
String
ticket
=
weChatApiUtil
.
createTemporaryQrCode
(
platform
.
getAppId
(),
platform
.
getAppSecret
(),
sceneStr
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
);
String
qrCodeUrl
=
"https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="
+
ticket
;
// 5. 缓存扫码会话,状态为待扫码
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
,
ScanLoginConstants
.
STATUS_WAIT_SCAN
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":projectBizId"
,
request
.
getProjectBizId
(),
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":bizType"
,
ScanLoginConstants
.
BIZ_TYPE_LOGIN
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
// 6. 构建返回
ApiGenerateQrCodeResponse
response
=
new
ApiGenerateQrCodeResponse
();
response
.
setQrId
(
qrId
);
response
.
setQrCodeUrl
(
qrCodeUrl
);
response
.
setExpireSeconds
((
long
)
ScanLoginConstants
.
QR_EXPIRE_SECONDS
);
return
response
;
}
/**
* 处理登录扫码回调
*
* @param appId 公众号appId
* @param xml 微信XML
*/
@Override
public
void
handleLoginWechatCallback
(
String
appId
,
String
xml
)
{
// 1. 解析微信XML
String
eventType
=
weChatApiUtil
.
getEventType
(
xml
);
String
openid
=
weChatApiUtil
.
getFromUserName
(
xml
);
String
eventKey
=
weChatApiUtil
.
getEventKey
(
xml
);
if
(
StringUtils
.
isBlank
(
openid
)
||
StringUtils
.
isBlank
(
eventKey
))
{
log
.
warn
(
"登录扫码回调参数缺失,openid={}, eventKey={}"
,
openid
,
eventKey
);
return
;
}
// 2. 解析 EventKey,格式:bizType:qrId:tenantBizId:projectBizId
String
[]
parts
=
eventKey
.
split
(
":"
);
if
(
parts
.
length
<
4
)
{
log
.
warn
(
"登录扫码 EventKey 格式错误:{}"
,
eventKey
);
return
;
}
String
bizType
=
parts
[
0
];
String
qrId
=
parts
[
1
];
String
tenantBizId
=
parts
[
2
];
String
projectBizId
=
parts
[
3
];
if
(!
ScanLoginConstants
.
BIZ_TYPE_LOGIN
.
equals
(
bizType
))
{
log
.
warn
(
"非登录业务类型:{}"
,
bizType
);
return
;
}
// 3. 幂等处理
String
idempotentKey
=
ScanLoginConstants
.
REDIS_KEY_IDEMPOTENT
+
openid
+
":"
+
eventType
+
":"
+
eventKey
;
Boolean
success
=
redisUtil
.
tryLock
(
idempotentKey
,
"1"
,
5
,
TimeUnit
.
MINUTES
);
if
(
Boolean
.
FALSE
.
equals
(
success
))
{
log
.
info
(
"登录扫码回调重复,已忽略,openid={}, eventKey={}"
,
openid
,
eventKey
);
return
;
}
// 4. 更新二维码状态为已扫码
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
,
ScanLoginConstants
.
STATUS_SCANNED
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
// 5. 用 openid 换 unionid
String
unionid
=
weChatApiUtil
.
getUnionIdByOpenId
(
appId
,
openid
);
if
(
StringUtils
.
isBlank
(
unionid
))
{
log
.
warn
(
"无法获取 unionid,openid={}"
,
openid
);
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
,
ScanLoginConstants
.
STATUS_UNBOUND
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
return
;
}
// 6. 查询绑定关系
UserThirdPartyBind
bind
=
userThirdPartyBindService
.
queryBind
(
tenantBizId
,
projectBizId
,
unionid
,
openid
);
if
(
bind
==
null
)
{
log
.
info
(
"未找到绑定关系,unionid={}, projectBizId={}"
,
unionid
,
projectBizId
);
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
,
ScanLoginConstants
.
STATUS_UNBOUND
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
return
;
}
// 7. 生成 loginTicket,写入 Redis
String
loginTicket
=
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
);
String
ticketValue
=
qrId
+
":"
+
bind
.
getUserId
()
+
":"
+
projectBizId
;
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_TICKET
+
loginTicket
,
ticketValue
,
ScanLoginConstants
.
TICKET_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
// 8. 更新二维码状态为已确认,并缓存 userId、projectBizId、ticket
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
,
ScanLoginConstants
.
STATUS_CONFIRMED
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":ticket"
,
loginTicket
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":userId"
,
bind
.
getUserId
(),
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":projectBizId"
,
projectBizId
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
log
.
info
(
"扫码登录确认成功,qrId={}, userId={}, projectBizId={}"
,
qrId
,
bind
.
getUserId
(),
projectBizId
);
}
/**
* 查询扫码状态
*
* @param qrId 二维码参数
* @return 扫码状态
*/
@Override
public
ApiScanStatusResponse
queryScanStatus
(
String
qrId
)
{
//缓存查询扫码状态
Object
statusObj
=
redisUtil
.
getCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
);
if
(
statusObj
==
null
)
{
ApiScanStatusResponse
response
=
new
ApiScanStatusResponse
();
response
.
setQrId
(
qrId
);
response
.
setStatus
(
ScanLoginConstants
.
STATUS_EXPIRED
);
response
.
setMessage
(
"二维码已过期"
);
return
response
;
}
String
status
=
statusObj
.
toString
();
ApiScanStatusResponse
response
=
new
ApiScanStatusResponse
();
response
.
setQrId
(
qrId
);
response
.
setStatus
(
status
);
if
(
ScanLoginConstants
.
STATUS_CONFIRMED
.
equals
(
status
))
{
String
ticket
=
redisUtil
.
getCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":ticket"
);
String
userId
=
redisUtil
.
getCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":userId"
);
String
projectBizId
=
redisUtil
.
getCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
qrId
+
":projectBizId"
);
response
.
setLoginTicket
(
ticket
);
response
.
setUserId
(
userId
);
response
.
setProjectBizId
(
projectBizId
);
}
else
if
(
ScanLoginConstants
.
STATUS_UNBOUND
.
equals
(
status
))
{
response
.
setMessage
(
"该微信号未绑定系统账号"
);
}
else
if
(
ScanLoginConstants
.
STATUS_SCANNED
.
equals
(
status
))
{
response
.
setMessage
(
"已扫码,校验中"
);
}
else
if
(
ScanLoginConstants
.
STATUS_WAIT_SCAN
.
equals
(
status
))
{
response
.
setMessage
(
"等待扫码"
);
}
return
response
;
}
/**
* 校验 loginTicket
*
* @param request 校验参数
* @return 校验结果
*/
@Override
public
ApiVerifyTicketResponse
verifyTicket
(
ApiVerifyTicketRequest
request
)
{
ApiVerifyTicketResponse
response
=
new
ApiVerifyTicketResponse
();
String
cacheTicket
=
redisUtil
.
getCacheObject
(
ScanLoginConstants
.
REDIS_KEY_TICKET
+
request
.
getLoginTicket
());
if
(
cacheTicket
==
null
)
{
response
.
setValid
(
false
);
response
.
setMessage
(
"ticket 不存在或已过期"
);
return
response
;
}
String
[]
parts
=
cacheTicket
.
split
(
":"
);
if
(
parts
.
length
<
3
)
{
response
.
setValid
(
false
);
response
.
setMessage
(
"ticket 数据异常"
);
return
response
;
}
String
qrId
=
parts
[
0
];
String
userId
=
parts
[
1
];
String
projectBizId
=
parts
[
2
];
if
(!
qrId
.
equals
(
request
.
getQrId
()))
{
response
.
setValid
(
false
);
response
.
setMessage
(
"qrId 不匹配"
);
return
response
;
}
if
(!
projectBizId
.
equals
(
request
.
getProjectBizId
()))
{
response
.
setValid
(
false
);
response
.
setMessage
(
"项目ID不匹配"
);
return
response
;
}
response
.
setValid
(
true
);
response
.
setUserId
(
userId
);
response
.
setProjectBizId
(
projectBizId
);
return
response
;
}
/**
* 消费 loginTicket
*
* @param request 消费参数
* @return 是否成功
*/
@Override
public
boolean
consumeTicket
(
ApiVerifyTicketRequest
request
)
{
String
key
=
ScanLoginConstants
.
REDIS_KEY_TICKET
+
request
.
getLoginTicket
();
boolean
deleted
=
redisUtil
.
deleteObject
(
key
);
// 同时更新二维码状态为已消费
redisUtil
.
setCacheObject
(
ScanLoginConstants
.
REDIS_KEY_QR
+
request
.
getQrId
(),
ScanLoginConstants
.
STATUS_CONSUMED
,
ScanLoginConstants
.
QR_EXPIRE_SECONDS
,
TimeUnit
.
SECONDS
);
return
deleted
;
}
}
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiThirdPartyPlatformServiceImpl.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.user.api.service.ApiThirdPartyPlatformService
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformAddRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformEditRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformPageRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformDetailResponse
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformPageResponse
;
import
com.yd.user.service.model.ThirdPartyPlatform
;
import
com.yd.user.service.service.IThirdPartyPlatformService
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.time.LocalDateTime
;
import
java.util.Objects
;
/**
* 第三方平台配置 API Service 实现
*/
@Service
public
class
ApiThirdPartyPlatformServiceImpl
implements
ApiThirdPartyPlatformService
{
@Autowired
private
IThirdPartyPlatformService
iThirdPartyPlatformService
;
@Override
public
Result
<
IPage
<
ApiThirdPartyPlatformPageResponse
>>
page
(
ApiThirdPartyPlatformPageRequest
request
)
{
Page
<
ThirdPartyPlatform
>
page
=
new
Page
<>(
request
.
getPageNo
(),
request
.
getPageSize
());
LambdaQueryWrapper
<
ThirdPartyPlatform
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
eq
(
StringUtils
.
isNotBlank
(
request
.
getPlatformCode
()),
ThirdPartyPlatform:
:
getPlatformCode
,
request
.
getPlatformCode
())
.
like
(
StringUtils
.
isNotBlank
(
request
.
getPlatformName
()),
ThirdPartyPlatform:
:
getPlatformName
,
request
.
getPlatformName
())
.
eq
(
Objects
.
nonNull
(
request
.
getPlatformType
()),
ThirdPartyPlatform:
:
getPlatformType
,
request
.
getPlatformType
())
.
eq
(
Objects
.
nonNull
(
request
.
getStatus
()),
ThirdPartyPlatform:
:
getStatus
,
request
.
getStatus
())
.
eq
(
ThirdPartyPlatform:
:
getIsDeleted
,
0
)
.
orderByDesc
(
ThirdPartyPlatform:
:
getCreateTime
);
IPage
<
ThirdPartyPlatform
>
entityPage
=
iThirdPartyPlatformService
.
page
(
page
,
wrapper
);
IPage
<
ApiThirdPartyPlatformPageResponse
>
responsePage
=
entityPage
.
convert
(
entity
->
{
ApiThirdPartyPlatformPageResponse
response
=
new
ApiThirdPartyPlatformPageResponse
();
BeanUtils
.
copyProperties
(
entity
,
response
);
return
response
;
});
return
Result
.
success
(
responsePage
);
}
@Override
public
Result
<
ApiThirdPartyPlatformDetailResponse
>
detail
(
Long
id
)
{
ThirdPartyPlatform
entity
=
iThirdPartyPlatformService
.
getById
(
id
);
if
(
entity
==
null
||
entity
.
getIsDeleted
()
==
1
)
{
throw
new
BusinessException
(
"平台配置不存在"
);
}
ApiThirdPartyPlatformDetailResponse
response
=
new
ApiThirdPartyPlatformDetailResponse
();
BeanUtils
.
copyProperties
(
entity
,
response
);
return
Result
.
success
(
response
);
}
@Override
public
Result
add
(
ApiThirdPartyPlatformAddRequest
request
)
{
long
count
=
iThirdPartyPlatformService
.
count
(
new
LambdaQueryWrapper
<
ThirdPartyPlatform
>()
.
eq
(
ThirdPartyPlatform:
:
getPlatformCode
,
request
.
getPlatformCode
())
.
eq
(
ThirdPartyPlatform:
:
getIsDeleted
,
0
));
if
(
count
>
0
)
{
throw
new
BusinessException
(
"平台编码已存在"
);
}
ThirdPartyPlatform
entity
=
new
ThirdPartyPlatform
();
BeanUtils
.
copyProperties
(
request
,
entity
);
entity
.
setIsDeleted
(
0
);
entity
.
setCreateTime
(
LocalDateTime
.
now
());
entity
.
setUpdateTime
(
LocalDateTime
.
now
());
iThirdPartyPlatformService
.
save
(
entity
);
return
Result
.
success
();
}
@Override
public
Result
edit
(
ApiThirdPartyPlatformEditRequest
request
)
{
ThirdPartyPlatform
entity
=
iThirdPartyPlatformService
.
getById
(
request
.
getId
());
if
(
entity
==
null
||
entity
.
getIsDeleted
()
==
1
)
{
throw
new
BusinessException
(
"平台配置不存在"
);
}
BeanUtils
.
copyProperties
(
request
,
entity
);
entity
.
setUpdateTime
(
LocalDateTime
.
now
());
iThirdPartyPlatformService
.
updateById
(
entity
);
return
Result
.
success
();
}
@Override
public
Result
del
(
Long
id
)
{
ThirdPartyPlatform
entity
=
iThirdPartyPlatformService
.
getById
(
id
);
if
(
entity
==
null
)
{
throw
new
BusinessException
(
"平台配置不存在"
);
}
entity
.
setIsDeleted
(
1
);
entity
.
setUpdateTime
(
LocalDateTime
.
now
());
iThirdPartyPlatformService
.
updateById
(
entity
);
return
Result
.
success
();
}
@Override
public
Result
editStatus
(
Long
id
,
Integer
status
)
{
ThirdPartyPlatform
entity
=
iThirdPartyPlatformService
.
getById
(
id
);
if
(
entity
==
null
)
{
throw
new
BusinessException
(
"平台配置不存在"
);
}
entity
.
setStatus
(
status
);
entity
.
setUpdateTime
(
LocalDateTime
.
now
());
iThirdPartyPlatformService
.
updateById
(
entity
);
return
Result
.
success
();
}
}
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiThirdPartyScanLoginServiceImpl.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
.
impl
;
import
com.yd.common.result.Result
;
import
com.yd.user.api.service.ApiScanLoginService
;
import
com.yd.user.api.service.ApiThirdPartyScanLoginService
;
import
com.yd.user.api.utils.WeChatApiUtil
;
import
com.yd.user.feign.constants.ScanLoginConstants
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateLoginQrCodeRequest
;
import
com.yd.user.feign.request.thirdscanlogin.ApiVerifyTicketRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiScanStatusResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiVerifyTicketResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
/**
* 第三方扫码登录 API Service 实现
*/
@Slf4j
@Service
public
class
ApiThirdPartyScanLoginServiceImpl
implements
ApiThirdPartyScanLoginService
{
@Autowired
private
ApiScanLoginService
scanLoginService
;
@Autowired
private
WeChatApiUtil
weChatApiUtil
;
/**
* 生成登录二维码
* @param request 请求参数
* @return 二维码信息
*/
@Override
public
Result
<
ApiGenerateQrCodeResponse
>
generateLoginQrCode
(
ApiGenerateLoginQrCodeRequest
request
)
{
ApiGenerateQrCodeResponse
response
=
scanLoginService
.
generateLoginQrCode
(
request
);
return
Result
.
success
(
response
);
}
/**
* 扫码回调(微信服务器调用,xml解析出来二维码业务类型,根据业务类型处理不同的业务逻辑,目前两种类型:分享绑定和扫码登录)
* @param appId 公众号appId
* @param xml 微信XML
* @return success
*/
@Override
public
String
handleLoginWechatCallback
(
String
appId
,
String
xml
)
{
//解析微信XML
String
eventKey
=
weChatApiUtil
.
getEventKey
(
xml
);
if
(
StringUtils
.
isBlank
(
eventKey
))
{
log
.
warn
(
"扫码回调参数缺失,eventKey={}"
,
eventKey
);
return
"fail"
;
}
//解析eventKey
String
[]
parts
=
eventKey
.
split
(
":"
);
if
(
parts
.
length
<
1
)
{
log
.
warn
(
"登录扫码 EventKey 格式错误:{}"
,
eventKey
);
return
"fail"
;
}
//二维码业务类型
String
bizType
=
parts
[
0
];
if
(
ScanLoginConstants
.
BIZ_TYPE_LOGIN
.
equals
(
bizType
))
{
//二维码业务类型:扫码登录
scanLoginService
.
handleLoginWechatCallback
(
appId
,
xml
);
}
else
if
(
ScanLoginConstants
.
BIZ_TYPE_SHARE_BIND
.
equals
(
bizType
))
{
//二维码业务类型:分享绑定
scanLoginService
.
handleShareWechatCallback
(
appId
,
xml
);
}
return
"success"
;
}
/**
* 查询扫码状态
* @param qrId 二维码参数
* @return 扫码状态
*/
@Override
public
Result
<
ApiScanStatusResponse
>
queryScanStatus
(
String
qrId
)
{
ApiScanStatusResponse
response
=
scanLoginService
.
queryScanStatus
(
qrId
);
return
Result
.
success
(
response
);
}
/**
* 校验 loginTicket
* @param request 校验参数
* @return 校验结果
*/
@Override
public
Result
<
ApiVerifyTicketResponse
>
verifyTicket
(
ApiVerifyTicketRequest
request
)
{
ApiVerifyTicketResponse
response
=
scanLoginService
.
verifyTicket
(
request
);
return
Result
.
success
(
response
);
}
/**
* 消费 loginTicket
* @param request 消费参数
* @return 是否成功
*/
@Override
public
Result
<
Boolean
>
consumeTicket
(
ApiVerifyTicketRequest
request
)
{
boolean
success
=
scanLoginService
.
consumeTicket
(
request
);
return
Result
.
success
(
success
);
}
}
yd-user-api/src/main/java/com/yd/user/api/service/impl/ApiUserThirdPartyBindServiceImpl.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
service
.
impl
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.user.api.service.ApiScanLoginService
;
import
com.yd.user.api.service.ApiUserThirdPartyBindService
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateShareBindQrCodeRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiUserThirdPartyBindResponse
;
import
com.yd.user.service.model.UserThirdPartyBind
;
import
com.yd.user.service.service.IUserThirdPartyBindService
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
import
java.util.stream.Collectors
;
/**
* 用户与第三方绑定关系 API Service 实现
*/
@Service
public
class
ApiUserThirdPartyBindServiceImpl
implements
ApiUserThirdPartyBindService
{
@Autowired
private
ApiScanLoginService
scanLoginService
;
@Autowired
private
IUserThirdPartyBindService
userThirdPartyBindService
;
@Override
public
Result
<
ApiGenerateQrCodeResponse
>
generateShareBindQrCode
(
ApiGenerateShareBindQrCodeRequest
request
)
{
ApiGenerateQrCodeResponse
response
=
scanLoginService
.
generateShareBindQrCode
(
request
);
return
Result
.
success
(
response
);
}
@Override
public
String
handleShareWechatCallback
(
String
appId
,
String
xml
)
{
scanLoginService
.
handleShareWechatCallback
(
appId
,
xml
);
return
"success"
;
}
@Override
public
Result
<
List
<
ApiUserThirdPartyBindResponse
>>
queryBind
(
String
unionid
,
String
projectBizId
)
{
List
<
UserThirdPartyBind
>
list
=
userThirdPartyBindService
.
queryByUnionidAndProject
(
unionid
,
projectBizId
);
List
<
ApiUserThirdPartyBindResponse
>
responseList
=
list
.
stream
().
map
(
entity
->
{
ApiUserThirdPartyBindResponse
response
=
new
ApiUserThirdPartyBindResponse
();
BeanUtils
.
copyProperties
(
entity
,
response
);
return
response
;
}).
collect
(
Collectors
.
toList
());
return
Result
.
success
(
responseList
);
}
@Override
public
Result
unbind
(
Long
id
)
{
boolean
success
=
userThirdPartyBindService
.
unbind
(
id
);
if
(!
success
)
{
throw
new
BusinessException
(
"解绑失败"
);
}
return
Result
.
success
();
}
}
yd-user-api/src/main/java/com/yd/user/api/utils/WeChatApiUtil.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
api
.
utils
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.yd.common.utils.RedisUtil
;
import
com.yd.user.service.model.ThirdPartyPlatform
;
import
com.yd.user.service.service.IThirdPartyPlatformService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.*
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.client.RestTemplate
;
import
org.w3c.dom.Document
;
import
org.w3c.dom.Element
;
import
org.w3c.dom.NodeList
;
import
javax.xml.parsers.DocumentBuilder
;
import
javax.xml.parsers.DocumentBuilderFactory
;
import
java.io.ByteArrayInputStream
;
import
java.nio.charset.StandardCharsets
;
import
java.util.concurrent.TimeUnit
;
/**
* 微信 API 工具类
* 提供 access_token 获取、临时二维码创建、openid 换 unionid、XML 解析等功能
*/
@Slf4j
@Component
public
class
WeChatApiUtil
{
/**
* 获取 access_token 的 URL 模板
*/
private
static
final
String
ACCESS_TOKEN_URL
=
"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
;
/**
* 创建二维码的 URL 模板
*/
private
static
final
String
QRCODE_CREATE_URL
=
"https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s"
;
/**
* 获取用户信息的 URL 模板
*/
private
static
final
String
USER_INFO_URL
=
"https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN"
;
/**
* Redis 缓存 access_token 的 key 前缀
*/
private
static
final
String
REDIS_KEY_ACCESS_TOKEN
=
"yd:wechat:access_token:"
;
/**
* HTTP 客户端
*/
private
final
RestTemplate
restTemplate
=
new
RestTemplate
();
/**
* JSON 解析器
*/
private
final
ObjectMapper
objectMapper
=
new
ObjectMapper
();
@Autowired
private
RedisUtil
redisUtil
;
@Autowired
private
IThirdPartyPlatformService
thirdPartyPlatformService
;
/**
* 获取微信 access_token,优先从 Redis 缓存中读取
*
* @param appId 公众号 appId
* @param appSecret 公众号 appSecret
* @return access_token
*/
public
String
getAccessToken
(
String
appId
,
String
appSecret
)
{
String
cacheKey
=
REDIS_KEY_ACCESS_TOKEN
+
appId
;
// 从 Redis 缓存中读取
String
cached
=
redisUtil
.
getCacheObject
(
cacheKey
);
if
(
cached
!=
null
)
{
return
cached
;
}
String
url
=
String
.
format
(
ACCESS_TOKEN_URL
,
appId
,
appSecret
);
String
response
=
restTemplate
.
getForObject
(
url
,
String
.
class
);
try
{
JsonNode
node
=
objectMapper
.
readTree
(
response
);
if
(
node
.
has
(
"access_token"
))
{
String
accessToken
=
node
.
get
(
"access_token"
).
asText
();
int
expiresIn
=
node
.
get
(
"expires_in"
).
asInt
();
// 提前 300 秒过期,避免临界时间失效
redisUtil
.
setCacheObject
(
cacheKey
,
accessToken
,
expiresIn
-
300
,
TimeUnit
.
SECONDS
);
return
accessToken
;
}
else
{
log
.
error
(
"获取微信 access_token 失败: {}"
,
response
);
throw
new
RuntimeException
(
"获取微信 access_token 失败: "
+
response
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"解析 access_token 响应异常"
,
e
);
throw
new
RuntimeException
(
"解析微信 access_token 异常"
,
e
);
}
}
/**
* 创建带参数的临时二维码
*
* @param appId 公众号 appId
* @param appSecret 公众号 appSecret
* @param sceneStr 自定义参数,放入 scene_str
* @param expireSeconds 二维码有效期(秒),最大 2592000
* @return 二维码 ticket
*/
public
String
createTemporaryQrCode
(
String
appId
,
String
appSecret
,
String
sceneStr
,
int
expireSeconds
)
{
String
accessToken
=
getAccessToken
(
appId
,
appSecret
);
String
url
=
String
.
format
(
QRCODE_CREATE_URL
,
accessToken
);
// 构造请求体
String
body
=
"{\"expire_seconds\":"
+
expireSeconds
+
",\"action_name\":\"QR_STR_SCENE\",\"action_info\":{\"scene\":{\"scene_str\":\""
+
sceneStr
+
"\"}}}"
;
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
APPLICATION_JSON
);
HttpEntity
<
String
>
request
=
new
HttpEntity
<>(
body
,
headers
);
ResponseEntity
<
String
>
responseEntity
=
restTemplate
.
postForEntity
(
url
,
request
,
String
.
class
);
String
response
=
responseEntity
.
getBody
();
try
{
JsonNode
node
=
objectMapper
.
readTree
(
response
);
if
(
node
.
has
(
"ticket"
))
{
return
node
.
get
(
"ticket"
).
asText
();
}
else
{
log
.
error
(
"创建微信二维码失败: {}"
,
response
);
throw
new
RuntimeException
(
"创建微信二维码失败: "
+
response
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"解析二维码响应异常"
,
e
);
throw
new
RuntimeException
(
"解析微信二维码响应异常"
,
e
);
}
}
/**
* 用 openid 换取 unionid
*
* @param appId 公众号 appId
* @param openid 用户 openid
* @return unionid,获取失败返回 null
*/
public
String
getUnionIdByOpenId
(
String
appId
,
String
openid
)
{
// 根据 appId 查询平台配置获取 appSecret
ThirdPartyPlatform
platform
=
thirdPartyPlatformService
.
getByAppId
(
appId
);
if
(
platform
==
null
||
platform
.
getAppSecret
()
==
null
)
{
log
.
error
(
"未找到 appId 对应的平台配置或 appSecret 为空: {}"
,
appId
);
return
null
;
}
String
appSecret
=
platform
.
getAppSecret
();
String
accessToken
=
getAccessToken
(
appId
,
appSecret
);
String
url
=
String
.
format
(
USER_INFO_URL
,
accessToken
,
openid
);
String
response
=
restTemplate
.
getForObject
(
url
,
String
.
class
);
try
{
JsonNode
node
=
objectMapper
.
readTree
(
response
);
if
(
node
.
has
(
"unionid"
))
{
return
node
.
get
(
"unionid"
).
asText
();
}
else
{
log
.
warn
(
"获取 unionid 失败,可能未绑定开放平台: {}"
,
response
);
return
null
;
}
}
catch
(
Exception
e
)
{
log
.
error
(
"解析用户信息响应异常"
,
e
);
return
null
;
}
}
/**
* 解析微信 XML 获取事件类型
*
* @param xml 微信回调 XML
* @return Event 字段值
*/
public
String
getEventType
(
String
xml
)
{
return
getXmlField
(
xml
,
"Event"
);
}
/**
* 解析微信 XML 获取 FromUserName(openid)
*
* @param xml 微信回调 XML
* @return FromUserName 字段值
*/
public
String
getFromUserName
(
String
xml
)
{
return
getXmlField
(
xml
,
"FromUserName"
);
}
/**
* 解析微信 XML 获取 EventKey
*
* @param xml 微信回调 XML
* @return EventKey 字段值
*/
public
String
getEventKey
(
String
xml
)
{
return
getXmlField
(
xml
,
"EventKey"
);
}
/**
* 通用解析微信 XML 字段
*
* @param xml 微信回调 XML
* @param fieldName 字段名称
* @return 字段值,解析失败返回 null
*/
private
String
getXmlField
(
String
xml
,
String
fieldName
)
{
try
{
DocumentBuilderFactory
factory
=
DocumentBuilderFactory
.
newInstance
();
// 防止 XXE 攻击
factory
.
setFeature
(
"http://apache.org/xml/features/disallow-doctype-decl"
,
true
);
factory
.
setFeature
(
"http://xml.org/sax/features/external-general-entities"
,
false
);
factory
.
setFeature
(
"http://xml.org/sax/features/external-parameter-entities"
,
false
);
factory
.
setExpandEntityReferences
(
false
);
DocumentBuilder
builder
=
factory
.
newDocumentBuilder
();
Document
document
=
builder
.
parse
(
new
ByteArrayInputStream
(
xml
.
getBytes
(
StandardCharsets
.
UTF_8
)));
NodeList
nodeList
=
document
.
getElementsByTagName
(
fieldName
);
if
(
nodeList
.
getLength
()
>
0
)
{
Element
element
=
(
Element
)
nodeList
.
item
(
0
);
return
element
.
getTextContent
();
}
}
catch
(
Exception
e
)
{
log
.
error
(
"解析微信 XML 失败,field={}, xml={}"
,
fieldName
,
xml
,
e
);
}
return
null
;
}
}
yd-user-feign/src/main/java/com/yd/user/feign/client/thirdpartyplatform/ApiProjectThirdPartyBindFeignClient.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
client
.
thirdpartyplatform
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.fallback.thirdpartyplatform.ApiProjectThirdPartyBindFeignFallbackFactory
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiProjectThirdPartyBindRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiProjectThirdPartyBindResponse
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
java.util.List
;
/**
* 项目与第三方平台绑定 Feign 客户端
*/
@FeignClient
(
name
=
"yd-user-api"
,
contextId
=
"apiProjectThirdPartyBindFeignClient"
,
fallbackFactory
=
ApiProjectThirdPartyBindFeignFallbackFactory
.
class
)
public
interface
ApiProjectThirdPartyBindFeignClient
{
/**
* 绑定
* @param request 绑定参数
* @return 操作结果
*/
@PostMapping
(
"/projectThirdPartyBind/bind"
)
Result
bind
(
@Validated
@RequestBody
ApiProjectThirdPartyBindRequest
request
);
/**
* 解绑
* @param id 主键
* @return 操作结果
*/
@DeleteMapping
(
"/projectThirdPartyBind/unbind"
)
Result
unbind
(
@RequestParam
(
"id"
)
Long
id
);
/**
* 查询项目绑定列表
* @param projectBizId 项目ID
* @return 绑定列表
*/
@GetMapping
(
"/projectThirdPartyBind/list"
)
Result
<
List
<
ApiProjectThirdPartyBindResponse
>>
list
(
@RequestParam
(
"projectBizId"
)
String
projectBizId
);
}
yd-user-feign/src/main/java/com/yd/user/feign/client/thirdpartyplatform/ApiThirdPartyPlatformFeignClient.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
client
.
thirdpartyplatform
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.fallback.thirdpartyplatform.ApiThirdPartyPlatformFeignFallbackFactory
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformAddRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformEditRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformPageRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformDetailResponse
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformPageResponse
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
/**
* 用户服务-第三方平台配置 Feign 客户端
*/
@FeignClient
(
name
=
"yd-user-api"
,
contextId
=
"apiThirdPartyPlatformFeignClient"
,
fallbackFactory
=
ApiThirdPartyPlatformFeignFallbackFactory
.
class
)
public
interface
ApiThirdPartyPlatformFeignClient
{
/**
* 分页查询
* @param request 查询条件
* @return 分页结果
*/
@PostMapping
(
"/thirdPartyPlatform/page"
)
Result
page
(
@RequestBody
ApiThirdPartyPlatformPageRequest
request
);
/**
* 详情
* @param id 主键
* @return 详情
*/
@GetMapping
(
"/thirdPartyPlatform/detail"
)
Result
<
ApiThirdPartyPlatformDetailResponse
>
detail
(
@RequestParam
(
"id"
)
Long
id
);
/**
* 新增
* @param request 新增参数
* @return 操作结果
*/
@PostMapping
(
"/thirdPartyPlatform/add"
)
Result
add
(
@Validated
@RequestBody
ApiThirdPartyPlatformAddRequest
request
);
/**
* 编辑
* @param request 编辑参数
* @return 操作结果
*/
@PutMapping
(
"/thirdPartyPlatform/edit"
)
Result
edit
(
@Validated
@RequestBody
ApiThirdPartyPlatformEditRequest
request
);
/**
* 删除
* @param id 主键
* @return 操作结果
*/
@DeleteMapping
(
"/thirdPartyPlatform/del"
)
Result
del
(
@RequestParam
(
"id"
)
Long
id
);
/**
* 启用/禁用
* @param id 主键
* @param status 状态
* @return 操作结果
*/
@PatchMapping
(
"/thirdPartyPlatform/edit/status"
)
Result
editStatus
(
@RequestParam
(
"id"
)
Long
id
,
@RequestParam
(
"status"
)
Integer
status
);
}
yd-user-feign/src/main/java/com/yd/user/feign/client/thirdscanlogin/ApiThirdPartyScanLoginFeignClient.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
client
.
thirdscanlogin
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.fallback.thirdscanlogin.ApiThirdPartyScanLoginFeignFallbackFactory
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateLoginQrCodeRequest
;
import
com.yd.user.feign.request.thirdscanlogin.ApiVerifyTicketRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiScanStatusResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiVerifyTicketResponse
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
/**
* 第三方扫码登录 Feign 客户端
*/
@FeignClient
(
name
=
"yd-user-api"
,
path
=
"/user/api/thirdPartyScanLogin"
,
fallbackFactory
=
ApiThirdPartyScanLoginFeignFallbackFactory
.
class
)
public
interface
ApiThirdPartyScanLoginFeignClient
{
/**
* 生成登录二维码
* @param request 请求参数
* @return 二维码信息
*/
@PostMapping
(
"/qrcode"
)
Result
<
ApiGenerateQrCodeResponse
>
generateLoginQrCode
(
@Validated
@RequestBody
ApiGenerateLoginQrCodeRequest
request
);
/**
* 扫码回调(微信服务器调用,xml解析出来二维码业务类型,根据业务类型处理不同的业务逻辑,目前两种类型:分享绑定和扫码登录)
* @param appId 公众号appId
* @param xml 微信XML
* @return success
*/
@PostMapping
(
"/wechat/callback/{appId}"
)
String
loginWechatCallback
(
@PathVariable
(
"appId"
)
String
appId
,
@RequestBody
String
xml
);
/**
* 查询扫码状态
* @param qrId 二维码参数
* @return 扫码状态
*/
@GetMapping
(
"/status"
)
Result
<
ApiScanStatusResponse
>
queryScanStatus
(
@RequestParam
(
"qrId"
)
String
qrId
);
/**
* 校验 loginTicket
* @param request 校验参数
* @return 校验结果
*/
@PostMapping
(
"/verifyTicket"
)
Result
<
ApiVerifyTicketResponse
>
verifyTicket
(
@Validated
@RequestBody
ApiVerifyTicketRequest
request
);
/**
* 消费 loginTicket
* @param request 消费参数
* @return 是否成功
*/
@PostMapping
(
"/consumeTicket"
)
Result
<
Boolean
>
consumeTicket
(
@Validated
@RequestBody
ApiVerifyTicketRequest
request
);
}
yd-user-feign/src/main/java/com/yd/user/feign/client/thirdscanlogin/ApiUserThirdPartyBindFeignClient.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
client
.
thirdscanlogin
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.fallback.thirdscanlogin.ApiUserThirdPartyBindFeignFallbackFactory
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateShareBindQrCodeRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiUserThirdPartyBindResponse
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
java.util.List
;
/**
* 用户与第三方绑定关系 Feign 客户端
*/
@FeignClient
(
name
=
"yd-user-api"
,
path
=
"/user/api/userThirdPartyBind"
,
fallbackFactory
=
ApiUserThirdPartyBindFeignFallbackFactory
.
class
)
public
interface
ApiUserThirdPartyBindFeignClient
{
/**
* 生成分享绑定二维码
* @param request 请求参数
* @return 二维码信息
*/
@PostMapping
(
"/share/qrcode"
)
Result
<
ApiGenerateQrCodeResponse
>
generateShareBindQrCode
(
@Validated
@RequestBody
ApiGenerateShareBindQrCodeRequest
request
);
// /**
// * 分享扫码关注回调(微信服务器调用)
// * @param appId 公众号appId
// * @param xml 微信XML
// * @return success
// */
// @PostMapping("/wechat/callback/{appId}")
// String shareWechatCallback(@PathVariable("appId") String appId, @RequestBody String xml);
/**
* 查询绑定关系
* @param unionid 微信unionid
* @param projectBizId 项目ID
* @return 绑定列表
*/
@GetMapping
(
"/query"
)
Result
<
List
<
ApiUserThirdPartyBindResponse
>>
queryBind
(
@RequestParam
(
"unionid"
)
String
unionid
,
@RequestParam
(
"projectBizId"
)
String
projectBizId
);
/**
* 解绑
* @param id 主键
* @return 操作结果
*/
@PostMapping
(
"/unbind"
)
Result
unbind
(
@RequestParam
(
"id"
)
Long
id
);
}
yd-user-feign/src/main/java/com/yd/user/feign/constants/ScanLoginConstants.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
constants
;
/**
* 扫码登录常量类
*/
public
class
ScanLoginConstants
{
/**
* 二维码业务类型:分享绑定
*/
public
static
final
String
BIZ_TYPE_SHARE_BIND
=
"share_bind"
;
/**
* 二维码业务类型:扫码登录
*/
public
static
final
String
BIZ_TYPE_LOGIN
=
"login"
;
/**
* 扫码状态:待扫码
*/
public
static
final
String
STATUS_WAIT_SCAN
=
"WAIT_SCAN"
;
/**
* 扫码状态:已扫码
*/
public
static
final
String
STATUS_SCANNED
=
"SCANNED"
;
/**
* 扫码状态:已确认
*/
public
static
final
String
STATUS_CONFIRMED
=
"CONFIRMED"
;
/**
* 扫码状态:已消费
*/
public
static
final
String
STATUS_CONSUMED
=
"CONSUMED"
;
/**
* 扫码状态:已过期
*/
public
static
final
String
STATUS_EXPIRED
=
"EXPIRED"
;
/**
* 扫码状态:已取消
*/
public
static
final
String
STATUS_CANCELLED
=
"CANCELLED"
;
/**
* 扫码状态:未绑定
*/
public
static
final
String
STATUS_UNBOUND
=
"UNBOUND"
;
/**
* 扫码状态:已禁用
*/
public
static
final
String
STATUS_DISABLED
=
"DISABLED"
;
/**
* 扫码状态:已离职
*/
public
static
final
String
STATUS_RESIGNED
=
"RESIGNED"
;
/**
* 扫码状态:无权限
*/
public
static
final
String
STATUS_NO_PERMISSION
=
"NO_PERMISSION"
;
/**
* Redis Key 前缀:二维码会话
*/
public
static
final
String
REDIS_KEY_QR
=
"yd:scan:login:qr:"
;
/**
* Redis Key 前缀:loginTicket
*/
public
static
final
String
REDIS_KEY_TICKET
=
"yd:scan:login:ticket:"
;
/**
* Redis Key 前缀:幂等控制
*/
public
static
final
String
REDIS_KEY_IDEMPOTENT
=
"yd:scan:login:idempotent:"
;
/**
* 二维码有效期(秒)
*/
public
static
final
int
QR_EXPIRE_SECONDS
=
120
;
/**
* loginTicket 有效期(秒)
*/
public
static
final
int
TICKET_EXPIRE_SECONDS
=
60
;
/**
* 平台类型:公众号
*/
public
static
final
int
PLATFORM_TYPE_GZH
=
1
;
/**
* 平台类型:小程序
*/
public
static
final
int
PLATFORM_TYPE_MINI
=
2
;
/**
* 平台类型:网站
*/
public
static
final
int
PLATFORM_TYPE_WEBSITE
=
3
;
/**
* 绑定状态:已绑定
*/
public
static
final
int
BIND_STATUS_BOUND
=
1
;
/**
* 绑定状态:已解绑
*/
public
static
final
int
BIND_STATUS_UNBOUND
=
0
;
/**
* 绑定来源:PC分享扫码绑定
*/
public
static
final
int
BIND_SOURCE_SHARE
=
1
;
/**
* 绑定来源:扫码登录绑定
*/
public
static
final
int
BIND_SOURCE_LOGIN
=
2
;
/**
* 绑定来源:个人中心绑定
*/
public
static
final
int
BIND_SOURCE_USER_CENTER
=
3
;
/**
* 绑定来源:公众号菜单绑定
*/
public
static
final
int
BIND_SOURCE_GZH_MENU
=
4
;
}
yd-user-feign/src/main/java/com/yd/user/feign/fallback/thirdpartyplatform/ApiProjectThirdPartyBindFeignFallbackFactory.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
fallback
.
thirdpartyplatform
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.client.thirdpartyplatform.ApiProjectThirdPartyBindFeignClient
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiProjectThirdPartyBindRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiProjectThirdPartyBindResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cloud.openfeign.FallbackFactory
;
import
org.springframework.stereotype.Component
;
import
java.util.Collections
;
import
java.util.List
;
/**
* 项目第三方绑定 Feign 降级
*/
@Slf4j
@Component
public
class
ApiProjectThirdPartyBindFeignFallbackFactory
implements
FallbackFactory
<
ApiProjectThirdPartyBindFeignClient
>
{
@Override
public
ApiProjectThirdPartyBindFeignClient
create
(
Throwable
cause
)
{
log
.
error
(
"项目第三方绑定服务降级"
,
cause
);
return
new
ApiProjectThirdPartyBindFeignClient
()
{
@Override
public
Result
bind
(
ApiProjectThirdPartyBindRequest
request
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
Result
unbind
(
Long
id
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
Result
<
List
<
ApiProjectThirdPartyBindResponse
>>
list
(
String
projectBizId
)
{
return
Result
.
success
(
Collections
.
emptyList
());
}
};
}
}
yd-user-feign/src/main/java/com/yd/user/feign/fallback/thirdpartyplatform/ApiThirdPartyPlatformFeignFallbackFactory.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
fallback
.
thirdpartyplatform
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.client.thirdpartyplatform.ApiThirdPartyPlatformFeignClient
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformAddRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformEditRequest
;
import
com.yd.user.feign.request.thirdpartyplatform.ApiThirdPartyPlatformPageRequest
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformDetailResponse
;
import
com.yd.user.feign.response.thirdpartyplatform.ApiThirdPartyPlatformPageResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cloud.openfeign.FallbackFactory
;
import
org.springframework.stereotype.Component
;
/**
* 第三方平台配置 Feign 降级
*/
@Slf4j
@Component
public
class
ApiThirdPartyPlatformFeignFallbackFactory
implements
FallbackFactory
<
ApiThirdPartyPlatformFeignClient
>
{
@Override
public
ApiThirdPartyPlatformFeignClient
create
(
Throwable
cause
)
{
log
.
error
(
"第三方平台配置服务降级"
,
cause
);
return
new
ApiThirdPartyPlatformFeignClient
()
{
@Override
public
Result
page
(
ApiThirdPartyPlatformPageRequest
request
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
Result
<
ApiThirdPartyPlatformDetailResponse
>
detail
(
Long
id
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
Result
add
(
ApiThirdPartyPlatformAddRequest
request
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
Result
edit
(
ApiThirdPartyPlatformEditRequest
request
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
Result
del
(
Long
id
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
Result
editStatus
(
Long
id
,
Integer
status
)
{
return
Result
.
fail
(
"服务降级"
);
}
};
}
}
yd-user-feign/src/main/java/com/yd/user/feign/fallback/thirdscanlogin/ApiThirdPartyScanLoginFeignFallbackFactory.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
fallback
.
thirdscanlogin
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.client.thirdscanlogin.ApiThirdPartyScanLoginFeignClient
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateLoginQrCodeRequest
;
import
com.yd.user.feign.request.thirdscanlogin.ApiVerifyTicketRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiScanStatusResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiVerifyTicketResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cloud.openfeign.FallbackFactory
;
import
org.springframework.stereotype.Component
;
/**
* 扫码登录 Feign 降级
*/
@Slf4j
@Component
public
class
ApiThirdPartyScanLoginFeignFallbackFactory
implements
FallbackFactory
<
ApiThirdPartyScanLoginFeignClient
>
{
@Override
public
ApiThirdPartyScanLoginFeignClient
create
(
Throwable
cause
)
{
log
.
error
(
"扫码登录服务降级"
,
cause
);
return
new
ApiThirdPartyScanLoginFeignClient
()
{
@Override
public
Result
<
ApiGenerateQrCodeResponse
>
generateLoginQrCode
(
ApiGenerateLoginQrCodeRequest
request
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
String
loginWechatCallback
(
String
appId
,
String
xml
)
{
return
"success"
;
}
@Override
public
Result
<
ApiScanStatusResponse
>
queryScanStatus
(
String
qrId
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
Result
<
ApiVerifyTicketResponse
>
verifyTicket
(
ApiVerifyTicketRequest
request
)
{
return
Result
.
fail
(
"服务降级"
);
}
@Override
public
Result
<
Boolean
>
consumeTicket
(
ApiVerifyTicketRequest
request
)
{
return
Result
.
fail
(
"服务降级"
);
}
};
}
}
yd-user-feign/src/main/java/com/yd/user/feign/fallback/thirdscanlogin/ApiUserThirdPartyBindFeignFallbackFactory.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
fallback
.
thirdscanlogin
;
import
com.yd.common.result.Result
;
import
com.yd.user.feign.client.thirdscanlogin.ApiUserThirdPartyBindFeignClient
;
import
com.yd.user.feign.request.thirdscanlogin.ApiGenerateShareBindQrCodeRequest
;
import
com.yd.user.feign.response.thirdscanlogin.ApiGenerateQrCodeResponse
;
import
com.yd.user.feign.response.thirdscanlogin.ApiUserThirdPartyBindResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cloud.openfeign.FallbackFactory
;
import
org.springframework.stereotype.Component
;
import
java.util.Collections
;
import
java.util.List
;
/**
* 用户第三方绑定 Feign 降级
*/
@Slf4j
@Component
public
class
ApiUserThirdPartyBindFeignFallbackFactory
implements
FallbackFactory
<
ApiUserThirdPartyBindFeignClient
>
{
@Override
public
ApiUserThirdPartyBindFeignClient
create
(
Throwable
cause
)
{
log
.
error
(
"用户第三方绑定服务降级"
,
cause
);
return
new
ApiUserThirdPartyBindFeignClient
()
{
@Override
public
Result
<
ApiGenerateQrCodeResponse
>
generateShareBindQrCode
(
ApiGenerateShareBindQrCodeRequest
request
)
{
return
Result
.
fail
(
"服务降级"
);
}
// @Override
// public String shareWechatCallback(String appId, String xml) {
// return "success";
// }
@Override
public
Result
<
List
<
ApiUserThirdPartyBindResponse
>>
queryBind
(
String
unionid
,
String
projectBizId
)
{
return
Result
.
success
(
Collections
.
emptyList
());
}
@Override
public
Result
unbind
(
Long
id
)
{
return
Result
.
fail
(
"服务降级"
);
}
};
}
}
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdpartyplatform/ApiProjectThirdPartyBindRequest.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
request
.
thirdpartyplatform
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
java.io.Serializable
;
/**
* 项目绑定第三方平台请求
*/
@Data
public
class
ApiProjectThirdPartyBindRequest
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 租户唯一业务ID
*/
private
String
tenantBizId
;
/**
* 项目唯一业务ID
*/
@NotBlank
(
message
=
"项目ID不能为空"
)
private
String
projectBizId
;
/**
* 项目名称
*/
private
String
projectName
;
/**
* 平台编码
*/
@NotBlank
(
message
=
"平台编码不能为空"
)
private
String
platformCode
;
/**
* 平台类型:1=公众号 2=小程序 3=网站
*/
private
Integer
platformType
;
/**
* 备注
*/
private
String
remark
;
}
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdpartyplatform/ApiThirdPartyPlatformAddRequest.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
request
.
thirdpartyplatform
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.NotNull
;
import
java.io.Serializable
;
/**
* 新增第三方平台配置请求
*/
@Data
public
class
ApiThirdPartyPlatformAddRequest
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 平台编码,如 YD_GZH
*/
@NotBlank
(
message
=
"平台编码不能为空"
)
private
String
platformCode
;
/**
* 平台名称
*/
@NotBlank
(
message
=
"平台名称不能为空"
)
private
String
platformName
;
/**
* 平台类型:1=公众号 2=小程序 3=网站
*/
@NotNull
(
message
=
"平台类型不能为空"
)
private
Integer
platformType
;
/**
* appId
*/
private
String
appId
;
/**
* appSecret
*/
private
String
appSecret
;
/**
* 微信服务器配置 Token
*/
private
String
token
;
/**
* 微信服务器配置 EncodingAESKey
*/
private
String
encodingAesKey
;
/**
* 固定公众号二维码地址
*/
private
String
gzhQrCodeUrl
;
/**
* 状态:1=启用 0=禁用
*/
private
Integer
status
=
1
;
/**
* 备注
*/
private
String
remark
;
}
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdpartyplatform/ApiThirdPartyPlatformEditRequest.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
request
.
thirdpartyplatform
;
import
lombok.Data
;
import
javax.validation.constraints.NotNull
;
import
java.io.Serializable
;
/**
* 编辑第三方平台配置请求
*/
@Data
public
class
ApiThirdPartyPlatformEditRequest
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
@NotNull
(
message
=
"id不能为空"
)
private
Long
id
;
/**
* 平台编码
*/
private
String
platformCode
;
/**
* 平台名称
*/
private
String
platformName
;
/**
* 平台类型
*/
private
Integer
platformType
;
/**
* appId
*/
private
String
appId
;
/**
* appSecret
*/
private
String
appSecret
;
/**
* Token
*/
private
String
token
;
/**
* EncodingAESKey
*/
private
String
encodingAesKey
;
/**
* 固定公众号二维码地址
*/
private
String
gzhQrCodeUrl
;
/**
* 状态
*/
private
Integer
status
;
/**
* 备注
*/
private
String
remark
;
}
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdpartyplatform/ApiThirdPartyPlatformPageRequest.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
request
.
thirdpartyplatform
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* 第三方平台配置分页查询请求
*/
@Data
public
class
ApiThirdPartyPlatformPageRequest
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 页码
*/
private
Integer
pageNo
=
1
;
/**
* 每页条数
*/
private
Integer
pageSize
=
10
;
/**
* 平台编码,如 YD_GZH
*/
private
String
platformCode
;
/**
* 平台名称,如 银盾公众号
*/
private
String
platformName
;
/**
* 平台类型:1=公众号 2=小程序 3=网站
*/
private
Integer
platformType
;
/**
* 状态:1=启用 0=禁用
*/
private
Integer
status
;
}
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdscanlogin/ApiGenerateLoginQrCodeRequest.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
request
.
thirdscanlogin
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
java.io.Serializable
;
/**
* 生成登录二维码请求
*/
@Data
public
class
ApiGenerateLoginQrCodeRequest
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 租户唯一业务ID
*/
@NotBlank
(
message
=
"租户唯一业务ID不能为空"
)
private
String
tenantBizId
;
/**
* 项目唯一业务ID
*/
@NotBlank
(
message
=
"项目ID不能为空"
)
private
String
projectBizId
;
/**
* 项目名称
*/
private
String
projectName
;
/**
* 平台类型:1=公众号 2=小程序 3=网站
*/
private
Integer
platformType
=
1
;
}
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdscanlogin/ApiGenerateShareBindQrCodeRequest.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
request
.
thirdscanlogin
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
javax.validation.constraints.NotNull
;
import
java.io.Serializable
;
/**
* 生成分享绑定二维码请求
*/
@Data
public
class
ApiGenerateShareBindQrCodeRequest
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 租户唯一业务ID
*/
@NotBlank
(
message
=
"租户ID不能为空"
)
private
String
tenantBizId
;
/**
* 项目唯一业务ID
*/
@NotBlank
(
message
=
"项目ID不能为空"
)
private
String
projectBizId
;
/**
* 项目名称
*/
private
String
projectName
;
/**
* 项目用户ID
*/
@NotBlank
(
message
=
"用户ID不能为空"
)
private
String
userId
;
/**
* 项目用户手机号
*/
private
String
mobile
;
/**
* 平台类型:1=公众号 2=小程序 3=网站
*/
@NotNull
(
message
=
"平台类型不能为空"
)
private
Integer
platformType
=
1
;
}
yd-user-feign/src/main/java/com/yd/user/feign/request/thirdscanlogin/ApiVerifyTicketRequest.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
request
.
thirdscanlogin
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
java.io.Serializable
;
/**
* 校验 loginTicket 请求
*/
@Data
public
class
ApiVerifyTicketRequest
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 二维码参数
*/
@NotBlank
(
message
=
"qrId不能为空"
)
private
String
qrId
;
/**
* 一次性登录凭证
*/
@NotBlank
(
message
=
"loginTicket不能为空"
)
private
String
loginTicket
;
/**
* 项目ID
*/
@NotBlank
(
message
=
"项目ID不能为空"
)
private
String
projectBizId
;
}
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdpartyplatform/ApiProjectThirdPartyBindResponse.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
response
.
thirdpartyplatform
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
/**
* 项目绑定第三方平台响应
*/
@Data
public
class
ApiProjectThirdPartyBindResponse
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
private
Long
id
;
/**
* 租户唯一业务ID
*/
private
String
tenantBizId
;
/**
* 项目唯一业务ID
*/
private
String
projectBizId
;
/**
* 项目名称
*/
private
String
projectName
;
/**
* 平台编码
*/
private
String
platformCode
;
/**
* 平台类型
*/
private
Integer
platformType
;
/**
* 平台名称
*/
private
String
platformName
;
/**
* 创建时间
*/
private
LocalDateTime
createTime
;
}
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdpartyplatform/ApiThirdPartyPlatformDetailResponse.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
response
.
thirdpartyplatform
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
/**
* 第三方平台配置详情响应
*/
@Data
public
class
ApiThirdPartyPlatformDetailResponse
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
private
Long
id
;
/**
* 平台编码
*/
private
String
platformCode
;
/**
* 平台名称
*/
private
String
platformName
;
/**
* 平台类型
*/
private
Integer
platformType
;
/**
* appId
*/
private
String
appId
;
/**
* appSecret
*/
private
String
appSecret
;
/**
* Token
*/
private
String
token
;
/**
* EncodingAESKey
*/
private
String
encodingAesKey
;
/**
* 固定公众号二维码地址
*/
private
String
gzhQrCodeUrl
;
/**
* 状态
*/
private
Integer
status
;
/**
* 备注
*/
private
String
remark
;
/**
* 创建时间
*/
private
LocalDateTime
createTime
;
/**
* 更新时间
*/
private
LocalDateTime
updateTime
;
}
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdpartyplatform/ApiThirdPartyPlatformPageResponse.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
response
.
thirdpartyplatform
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
/**
* 第三方平台配置分页响应
*/
@Data
public
class
ApiThirdPartyPlatformPageResponse
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
private
Long
id
;
/**
* 平台编码
*/
private
String
platformCode
;
/**
* 平台名称
*/
private
String
platformName
;
/**
* 平台类型
*/
private
Integer
platformType
;
/**
* appId
*/
private
String
appId
;
/**
* 状态
*/
private
Integer
status
;
/**
* 备注
*/
private
String
remark
;
/**
* 创建时间
*/
private
LocalDateTime
createTime
;
/**
* 更新时间
*/
private
LocalDateTime
updateTime
;
}
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdscanlogin/ApiGenerateQrCodeResponse.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
response
.
thirdscanlogin
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* 生成二维码响应
*/
@Data
public
class
ApiGenerateQrCodeResponse
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 二维码参数
*/
private
String
qrId
;
/**
* 二维码图片地址
*/
private
String
qrCodeUrl
;
/**
* 过期秒数
*/
private
Long
expireSeconds
;
}
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdscanlogin/ApiScanStatusResponse.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
response
.
thirdscanlogin
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* 扫码状态响应
*/
@Data
public
class
ApiScanStatusResponse
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 二维码参数
*/
private
String
qrId
;
/**
* 状态:待扫码/已扫码/已确认/已消费/已过期/已取消/未绑定/已禁用/已离职/无权限
*/
private
String
status
;
/**
* 一次性登录凭证
*/
private
String
loginTicket
;
/**
* 用户ID
*/
private
String
userId
;
/**
* 项目ID
*/
private
String
projectBizId
;
/**
* 提示信息
*/
private
String
message
;
}
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdscanlogin/ApiUserThirdPartyBindResponse.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
response
.
thirdscanlogin
;
import
lombok.Data
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
/**
* 用户第三方绑定关系响应
*/
@Data
public
class
ApiUserThirdPartyBindResponse
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
private
Long
id
;
/**
* 租户唯一业务ID
*/
private
String
tenantBizId
;
/**
* 项目唯一业务ID
*/
private
String
projectBizId
;
/**
* 项目名称
*/
private
String
projectName
;
/**
* 项目用户ID
*/
private
String
userId
;
/**
* 项目用户手机号
*/
private
String
mobile
;
/**
* 微信开放平台 unionid
*/
private
String
unionid
;
/**
* 公众号 openid
*/
private
String
gzhOpenid
;
/**
* 绑定来源
*/
private
Integer
bindSource
;
/**
* 绑定状态
*/
private
Integer
bindStatus
;
/**
* 绑定时间
*/
private
LocalDateTime
bindTime
;
/**
* 解绑时间
*/
private
LocalDateTime
unbindTime
;
}
yd-user-feign/src/main/java/com/yd/user/feign/response/thirdscanlogin/ApiVerifyTicketResponse.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
feign
.
response
.
thirdscanlogin
;
import
lombok.Data
;
import
java.io.Serializable
;
/**
* 校验 loginTicket 响应
*/
@Data
public
class
ApiVerifyTicketResponse
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 是否有效
*/
private
boolean
valid
;
/**
* 用户ID
*/
private
String
userId
;
/**
* 项目ID
*/
private
String
projectBizId
;
/**
* 提示信息
*/
private
String
message
;
}
yd-user-service/src/main/java/com/yd/user/service/dao/ProjectThirdPartyBindMapper.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
dao
;
import
com.yd.user.service.model.ProjectThirdPartyBind
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
/**
* <p>
* 项目和第三方平台绑定关系表 Mapper 接口
* </p>
*
* @author zxm
* @since 2026-10-13
*/
public
interface
ProjectThirdPartyBindMapper
extends
BaseMapper
<
ProjectThirdPartyBind
>
{
}
yd-user-service/src/main/java/com/yd/user/service/dao/ThirdPartyPlatformMapper.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
dao
;
import
com.yd.user.service.model.ThirdPartyPlatform
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
/**
* <p>
* 第三方平台基础配置表 Mapper 接口
* </p>
*
* @author zxm
* @since 2026-10-13
*/
public
interface
ThirdPartyPlatformMapper
extends
BaseMapper
<
ThirdPartyPlatform
>
{
}
yd-user-service/src/main/java/com/yd/user/service/dao/UserThirdPartyBindMapper.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
dao
;
import
com.yd.user.service.model.UserThirdPartyBind
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
/**
* <p>
* 用户与第三方绑定关系表 Mapper 接口
* </p>
*
* @author zxm
* @since 2026-10-13
*/
public
interface
UserThirdPartyBindMapper
extends
BaseMapper
<
UserThirdPartyBind
>
{
}
yd-user-service/src/main/java/com/yd/user/service/model/ProjectThirdPartyBind.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
import
lombok.Getter
;
import
lombok.Setter
;
/**
* <p>
* 项目和第三方平台绑定关系表
* </p>
*
* @author zxm
* @since 2026-10-13
*/
@Getter
@Setter
@TableName
(
"project_third_party_bind"
)
public
class
ProjectThirdPartyBind
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
@TableId
(
value
=
"id"
,
type
=
IdType
.
AUTO
)
private
Long
id
;
/**
* 租户唯一业务ID
*/
@TableField
(
"tenant_biz_id"
)
private
String
tenantBizId
;
/**
* 项目唯一业务ID
*/
@TableField
(
"project_biz_id"
)
private
String
projectBizId
;
/**
* 项目名称
*/
@TableField
(
"project_name"
)
private
String
projectName
;
/**
* 关联 third_party_platform.platform_code
*/
@TableField
(
"platform_code"
)
private
String
platformCode
;
/**
* 平台类型,冗余方便查询:1=公众号 2=小程序 3=网站
*/
@TableField
(
"platform_type"
)
private
Integer
platformType
;
/**
* 通用备注
*/
@TableField
(
"remark"
)
private
String
remark
;
/**
* 删除标识: 0-正常, 1-删除
*/
@TableField
(
"is_deleted"
)
private
Integer
isDeleted
;
/**
* 创建人ID
*/
@TableField
(
"creator_id"
)
private
String
creatorId
;
/**
* 创建人名称
*/
@TableField
(
"creator_name"
)
private
String
creatorName
;
/**
* 更新人ID
*/
@TableField
(
"updater_id"
)
private
String
updaterId
;
/**
* 更新人名称
*/
@TableField
(
"updater_name"
)
private
String
updaterName
;
/**
* 创建时间
*/
@TableField
(
"create_time"
)
private
LocalDateTime
createTime
;
/**
* 更新时间
*/
@TableField
(
"update_time"
)
private
LocalDateTime
updateTime
;
}
yd-user-service/src/main/java/com/yd/user/service/model/ThirdPartyPlatform.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
import
lombok.Getter
;
import
lombok.Setter
;
/**
* <p>
* 第三方平台基础配置表
* </p>
*
* @author zxm
* @since 2026-10-13
*/
@Getter
@Setter
@TableName
(
"third_party_platform"
)
public
class
ThirdPartyPlatform
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
@TableId
(
value
=
"id"
,
type
=
IdType
.
AUTO
)
private
Long
id
;
/**
* 平台编码,如 YD_GZH、YD_MALL_MINI、YD_WEBSITE
*/
@TableField
(
"platform_code"
)
private
String
platformCode
;
/**
* 平台名称,如 银盾公众号、银盾家办商城小程序、银盾网站
*/
@TableField
(
"platform_name"
)
private
String
platformName
;
/**
* 平台类型:1=公众号 2=小程序 3=网站
*/
@TableField
(
"platform_type"
)
private
Integer
platformType
;
/**
* 公众号/小程序/应用 appId
*/
@TableField
(
"app_id"
)
private
String
appId
;
/**
* appSecret(加密存储)
*/
@TableField
(
"app_secret"
)
private
String
appSecret
;
/**
* 微信服务器配置 Token
*/
@TableField
(
"token"
)
private
String
token
;
/**
* 微信服务器配置 EncodingAESKey
*/
@TableField
(
"encoding_aes_key"
)
private
String
encodingAesKey
;
/**
* 固定公众号二维码地址
*/
@TableField
(
"gzh_qr_code_url"
)
private
String
gzhQrCodeUrl
;
/**
* 1=启用 0=禁用
*/
@TableField
(
"status"
)
private
Integer
status
;
/**
* 通用备注
*/
@TableField
(
"remark"
)
private
String
remark
;
/**
* 删除标识: 0-正常, 1-删除
*/
@TableField
(
"is_deleted"
)
private
Integer
isDeleted
;
/**
* 创建人ID
*/
@TableField
(
"creator_id"
)
private
String
creatorId
;
/**
* 创建人名称
*/
@TableField
(
"creator_name"
)
private
String
creatorName
;
/**
* 更新人ID
*/
@TableField
(
"updater_id"
)
private
String
updaterId
;
/**
* 更新人名称
*/
@TableField
(
"updater_name"
)
private
String
updaterName
;
/**
* 创建时间
*/
@TableField
(
"create_time"
)
private
LocalDateTime
createTime
;
/**
* 更新时间
*/
@TableField
(
"update_time"
)
private
LocalDateTime
updateTime
;
}
yd-user-service/src/main/java/com/yd/user/service/model/UserThirdPartyBind.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
model
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
java.io.Serializable
;
import
java.time.LocalDateTime
;
import
lombok.Getter
;
import
lombok.Setter
;
/**
* <p>
* 用户与第三方绑定关系表
* </p>
*
* @author zxm
* @since 2026-10-13
*/
@Getter
@Setter
@TableName
(
"user_third_party_bind"
)
public
class
UserThirdPartyBind
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
/**
* 主键
*/
@TableId
(
value
=
"id"
,
type
=
IdType
.
AUTO
)
private
Long
id
;
/**
* 租户唯一业务ID
*/
@TableField
(
"tenant_biz_id"
)
private
String
tenantBizId
;
/**
* 项目唯一业务ID
*/
@TableField
(
"project_biz_id"
)
private
String
projectBizId
;
/**
* 项目名称
*/
@TableField
(
"project_name"
)
private
String
projectName
;
/**
* 项目用户ID
*/
@TableField
(
"user_id"
)
private
String
userId
;
/**
* 项目用户手机号
*/
@TableField
(
"mobile"
)
private
String
mobile
;
/**
* 微信开放平台 unionid
*/
@TableField
(
"unionid"
)
private
String
unionid
;
/**
* 公众号 openid
*/
@TableField
(
"gzh_openid"
)
private
String
gzhOpenid
;
/**
* 绑定来源 1-PC分享扫码绑定
*/
@TableField
(
"bind_source"
)
private
Integer
bindSource
;
/**
* 绑定状态 1=已绑定 0=已解绑
*/
@TableField
(
"bind_status"
)
private
Integer
bindStatus
;
/**
* 绑定时间
*/
@TableField
(
"bind_time"
)
private
LocalDateTime
bindTime
;
/**
* 解绑时间
*/
@TableField
(
"unbind_time"
)
private
LocalDateTime
unbindTime
;
/**
* 通用备注
*/
@TableField
(
"remark"
)
private
String
remark
;
/**
* 删除标识: 0-正常, 1-删除
*/
@TableField
(
"is_deleted"
)
private
Integer
isDeleted
;
/**
* 创建人ID
*/
@TableField
(
"creator_id"
)
private
String
creatorId
;
/**
* 创建人名称
*/
@TableField
(
"creator_name"
)
private
String
creatorName
;
/**
* 更新人ID
*/
@TableField
(
"updater_id"
)
private
String
updaterId
;
/**
* 更新人名称
*/
@TableField
(
"updater_name"
)
private
String
updaterName
;
/**
* 创建时间
*/
@TableField
(
"create_time"
)
private
LocalDateTime
createTime
;
/**
* 更新时间
*/
@TableField
(
"update_time"
)
private
LocalDateTime
updateTime
;
}
yd-user-service/src/main/java/com/yd/user/service/service/IProjectThirdPartyBindService.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
service
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yd.user.service.model.ProjectThirdPartyBind
;
/**
* 项目和第三方平台绑定关系表 服务类
*/
public
interface
IProjectThirdPartyBindService
extends
IService
<
ProjectThirdPartyBind
>
{
/**
* 根据项目ID和平台类型查询绑定关系
* @param tenantBizId 租户ID
* @param projectBizId 项目ID
* @param platformType 平台类型
* @return 绑定关系
*/
ProjectThirdPartyBind
getByProjectAndType
(
String
tenantBizId
,
String
projectBizId
,
Integer
platformType
);
}
yd-user-service/src/main/java/com/yd/user/service/service/IThirdPartyPlatformService.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
service
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yd.user.service.model.ThirdPartyPlatform
;
/**
* 第三方平台基础配置表 服务类
*/
public
interface
IThirdPartyPlatformService
extends
IService
<
ThirdPartyPlatform
>
{
/**
* 根据 appId 查询平台配置
* @param appId 应用ID
* @return 平台配置
*/
ThirdPartyPlatform
getByAppId
(
String
appId
);
/**
* 根据平台编码查询平台配置
* @param platformCode 平台编码
* @return 平台配置
*/
ThirdPartyPlatform
getByPlatformCode
(
String
platformCode
);
}
yd-user-service/src/main/java/com/yd/user/service/service/IUserThirdPartyBindService.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
service
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yd.user.service.model.UserThirdPartyBind
;
import
java.util.List
;
/**
* 用户与第三方绑定关系表 服务类
*/
public
interface
IUserThirdPartyBindService
extends
IService
<
UserThirdPartyBind
>
{
/**
* 根据 unionid 和项目ID查询绑定关系
* @param unionid 微信unionid
* @param projectBizId 项目ID
* @return 绑定列表
*/
List
<
UserThirdPartyBind
>
queryByUnionidAndProject
(
String
unionid
,
String
projectBizId
);
/**
* 根据 openid 和项目ID查询绑定关系
* @param openid 公众号openid
* @param projectBizId 项目ID
* @return 绑定关系
*/
UserThirdPartyBind
queryByOpenidAndProject
(
String
openid
,
String
projectBizId
);
/**
* 多条件查询绑定关系
* @param tenantBizId
* @param projectBizId
* @param unionid
* @param gzhOpenid
* @return
*/
UserThirdPartyBind
queryBind
(
String
tenantBizId
,
String
projectBizId
,
String
unionid
,
String
gzhOpenid
);
/**
* 绑定关系
* @param bind 绑定实体
* @return 是否成功
*/
boolean
bind
(
UserThirdPartyBind
bind
);
/**
* 解绑
* @param id 主键
* @return 是否成功
*/
boolean
unbind
(
Long
id
);
}
yd-user-service/src/main/java/com/yd/user/service/service/impl/ProjectThirdPartyBindServiceImpl.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yd.user.service.dao.ProjectThirdPartyBindMapper
;
import
com.yd.user.service.model.ProjectThirdPartyBind
;
import
com.yd.user.service.service.IProjectThirdPartyBindService
;
import
org.springframework.stereotype.Service
;
/**
* 项目和第三方平台绑定关系表 服务实现类
*/
@Service
public
class
ProjectThirdPartyBindServiceImpl
extends
ServiceImpl
<
ProjectThirdPartyBindMapper
,
ProjectThirdPartyBind
>
implements
IProjectThirdPartyBindService
{
@Override
public
ProjectThirdPartyBind
getByProjectAndType
(
String
tenantBizId
,
String
projectBizId
,
Integer
platformType
)
{
return
getOne
(
new
LambdaQueryWrapper
<
ProjectThirdPartyBind
>()
.
eq
(
ProjectThirdPartyBind:
:
getTenantBizId
,
tenantBizId
)
.
eq
(
ProjectThirdPartyBind:
:
getProjectBizId
,
projectBizId
)
.
eq
(
ProjectThirdPartyBind:
:
getPlatformType
,
platformType
)
.
eq
(
ProjectThirdPartyBind:
:
getIsDeleted
,
0
));
}
}
yd-user-service/src/main/java/com/yd/user/service/service/impl/ThirdPartyPlatformServiceImpl.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yd.user.service.dao.ThirdPartyPlatformMapper
;
import
com.yd.user.service.model.ThirdPartyPlatform
;
import
com.yd.user.service.service.IThirdPartyPlatformService
;
import
org.springframework.stereotype.Service
;
/**
* 第三方平台基础配置表 服务实现类
*/
@Service
public
class
ThirdPartyPlatformServiceImpl
extends
ServiceImpl
<
ThirdPartyPlatformMapper
,
ThirdPartyPlatform
>
implements
IThirdPartyPlatformService
{
@Override
public
ThirdPartyPlatform
getByAppId
(
String
appId
)
{
return
getOne
(
new
LambdaQueryWrapper
<
ThirdPartyPlatform
>()
.
eq
(
ThirdPartyPlatform:
:
getAppId
,
appId
)
.
eq
(
ThirdPartyPlatform:
:
getStatus
,
1
)
.
eq
(
ThirdPartyPlatform:
:
getIsDeleted
,
0
));
}
@Override
public
ThirdPartyPlatform
getByPlatformCode
(
String
platformCode
)
{
return
getOne
(
new
LambdaQueryWrapper
<
ThirdPartyPlatform
>()
.
eq
(
ThirdPartyPlatform:
:
getPlatformCode
,
platformCode
)
.
eq
(
ThirdPartyPlatform:
:
getStatus
,
1
)
.
eq
(
ThirdPartyPlatform:
:
getIsDeleted
,
0
));
}
}
yd-user-service/src/main/java/com/yd/user/service/service/impl/UserThirdPartyBindServiceImpl.java
0 → 100644
View file @
b62266e0
package
com
.
yd
.
user
.
service
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yd.user.service.dao.UserThirdPartyBindMapper
;
import
com.yd.user.service.model.UserThirdPartyBind
;
import
com.yd.user.service.service.IUserThirdPartyBindService
;
import
org.springframework.stereotype.Service
;
import
java.time.LocalDateTime
;
import
java.util.List
;
/**
* 用户与第三方绑定关系表 服务实现类
*/
@Service
public
class
UserThirdPartyBindServiceImpl
extends
ServiceImpl
<
UserThirdPartyBindMapper
,
UserThirdPartyBind
>
implements
IUserThirdPartyBindService
{
@Override
public
List
<
UserThirdPartyBind
>
queryByUnionidAndProject
(
String
unionid
,
String
projectBizId
)
{
return
list
(
new
LambdaQueryWrapper
<
UserThirdPartyBind
>()
.
eq
(
UserThirdPartyBind:
:
getUnionid
,
unionid
)
.
eq
(
UserThirdPartyBind:
:
getProjectBizId
,
projectBizId
)
.
eq
(
UserThirdPartyBind:
:
getBindStatus
,
1
)
.
eq
(
UserThirdPartyBind:
:
getIsDeleted
,
0
));
}
@Override
public
UserThirdPartyBind
queryByOpenidAndProject
(
String
openid
,
String
projectBizId
)
{
return
getOne
(
new
LambdaQueryWrapper
<
UserThirdPartyBind
>()
.
eq
(
UserThirdPartyBind:
:
getGzhOpenid
,
openid
)
.
eq
(
UserThirdPartyBind:
:
getProjectBizId
,
projectBizId
)
.
eq
(
UserThirdPartyBind:
:
getBindStatus
,
1
)
.
eq
(
UserThirdPartyBind:
:
getIsDeleted
,
0
));
}
/**
* 多条件查询绑定关系
* @param tenantBizId
* @param projectBizId
* @param unionid
* @param gzhOpenid
* @return
*/
@Override
public
UserThirdPartyBind
queryBind
(
String
tenantBizId
,
String
projectBizId
,
String
unionid
,
String
gzhOpenid
)
{
return
getOne
(
new
LambdaQueryWrapper
<
UserThirdPartyBind
>()
.
eq
(
UserThirdPartyBind:
:
getTenantBizId
,
tenantBizId
)
.
eq
(
UserThirdPartyBind:
:
getProjectBizId
,
projectBizId
)
.
eq
(
UserThirdPartyBind:
:
getUnionid
,
unionid
)
.
eq
(
UserThirdPartyBind:
:
getGzhOpenid
,
gzhOpenid
)
.
eq
(
UserThirdPartyBind:
:
getBindStatus
,
1
)
.
eq
(
UserThirdPartyBind:
:
getIsDeleted
,
0
)
.
last
(
" limit 1 "
));
}
@Override
public
boolean
bind
(
UserThirdPartyBind
bind
)
{
bind
.
setBindTime
(
LocalDateTime
.
now
());
bind
.
setBindStatus
(
1
);
bind
.
setIsDeleted
(
0
);
return
save
(
bind
);
}
@Override
public
boolean
unbind
(
Long
id
)
{
UserThirdPartyBind
bind
=
getById
(
id
);
if
(
bind
==
null
)
return
false
;
bind
.
setBindStatus
(
0
);
bind
.
setUnbindTime
(
LocalDateTime
.
now
());
return
updateById
(
bind
);
}
}
yd-user-service/src/main/java/com/yd/user/service/utils/MyBatisPlusCodeGenerator.java
View file @
b62266e0
...
...
@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
public
class
MyBatisPlusCodeGenerator
{
public
static
void
main
(
String
[]
args
)
{
FastAutoGenerator
.
create
(
"jdbc:mysql://139.224.145.34:3308/yd?serverTimezone=GMT%2B8"
,
"root"
,
"
Zxm7320017
"
)
FastAutoGenerator
.
create
(
"jdbc:mysql://139.224.145.34:3308/yd?serverTimezone=GMT%2B8"
,
"root"
,
"
csF@dev#0920!
"
)
.
globalConfig
(
builder
->
{
builder
.
author
(
"zxm"
)
// .outputDir("src/main/java/com/yd/user/service");
...
...
@@ -21,7 +21,7 @@ public class MyBatisPlusCodeGenerator {
})
.
strategyConfig
(
builder
->
{
builder
.
addInclude
(
"
user_sign_expand"
,
"user_sale_expa
nd"
"
third_party_platform"
,
"project_third_party_bi
nd"
// "rel_dept_user", "rel_group_role", "rel_group_user",
// "rel_project_menu", "rel_project_role", "rel_project_user",
// "rel_project_user_group", "rel_role_menu", "rel_tenant_dept",
...
...
yd-user-service/src/main/resources/mappers/ProjectThirdPartyBindMapper.xml
0 → 100644
View file @
b62266e0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.yd.user.service.dao.ProjectThirdPartyBindMapper"
>
</mapper>
yd-user-service/src/main/resources/mappers/ThirdPartyPlatformMapper.xml
0 → 100644
View file @
b62266e0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.yd.user.service.dao.ThirdPartyPlatformMapper"
>
</mapper>
yd-user-service/src/main/resources/mappers/UserThirdPartyBindMapper.xml
0 → 100644
View file @
b62266e0
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"com.yd.user.service.dao.UserThirdPartyBindMapper"
>
</mapper>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment