diff --git a/.DS_Store b/.DS_Store index 78e659e..b7cf63b 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Jenkinsfile b/Jenkinsfile index 5887320..e75c553 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,7 +19,7 @@ pipeline { // DockerHub 账号名 DOCKERHUB_NAMESPACE = 'docker_username' // GitHub 账号名 - GITHUB_ACCOUNT = 'https://gitee.com/zhijiantianya/ruoyi-vue-pro' + GITHUB_ACCOUNT = 'https://gitee.com/guchengwuyue/yshop-pro' // 应用名称 APP_NAME = 'yshop-server' // 应用部署路径 @@ -29,7 +29,7 @@ pipeline { stages { stage('检出') { steps { - git url: "https://gitee.com/will-we/ruoyi-vue-pro.git", + git url: "https://gitee.com/will-we/yshop-pro.git", branch: "devops" } } diff --git a/LICENSE b/LICENSE deleted file mode 100644 index bd9da62..0000000 --- a/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2021 ruoyi-vue-pro - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/pom.xml b/pom.xml index 86a2b51..4b4f723 100644 --- a/pom.xml +++ b/pom.xml @@ -20,12 +20,14 @@ yshop-module-mp yshop-module-mall - yshop-example + yshop-sso-example + yshop-module-express + yshop-module-message ${project.artifactId} - yshop项目基础脚手架 - https://github.com/YunaiV/ruoyi-vue-pro + yshop-pro项目 + 1.7.2-snapshot diff --git a/yshop-dependencies/pom.xml b/yshop-dependencies/pom.xml index a967f96..8f9f658 100644 --- a/yshop-dependencies/pom.xml +++ b/yshop-dependencies/pom.xml @@ -11,7 +11,7 @@ ${project.artifactId} 基础 bom 文件,管理整个项目的依赖版本 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro 1.7.2-snapshot @@ -70,6 +70,9 @@ 1.5.6 2.12.2 4.3.0 + 1.0.3 + 2.14.5 + @@ -611,6 +614,27 @@ spring-boot-starter-websocket ${spring.boot.version} + + + com.egzosn + pay-spring-boot-starter + ${pay.boot.version} + + + com.egzosn + pay-java-ali + ${pay.version} + + + com.egzosn + pay-java-wx + ${pay.version} + + + com.egzosn + pay-java-web-support + ${pay.version} + diff --git a/yshop-example/pom.xml b/yshop-example/pom.xml deleted file mode 100644 index 6e3e000..0000000 --- a/yshop-example/pom.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - 4.0.0 - - - - co.yixiang.boot - yshop-example - 1.0.0-snapshot - pom - - yshop-sso-demo-by-code - yshop-sso-demo-by-password - - - ${project.artifactId} - 提供各种示例,例如说:SSO 单点登录 - https://github.com/YunaiV/ruoyi-vue-pro - - diff --git a/yshop-example/yshop-sso-demo-by-code/pom.xml b/yshop-example/yshop-sso-demo-by-code/pom.xml deleted file mode 100644 index a85da47..0000000 --- a/yshop-example/yshop-sso-demo-by-code/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - - - - co.yixiang.boot - yshop-sso-demo-by-code - 1.0.0-snapshot - jar - - ${project.artifactId} - 基于授权码模式,如何实现 SSO 单点登录? - https://github.com/YunaiV/ruoyi-vue-pro - - - - 8 - 8 - UTF-8 - - 2.7.10 - - - - - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-security - - - - cn.hutool - hutool-all - 5.8.15 - - - - org.projectlombok - lombok - true - - - - diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/SSODemoApplication.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/SSODemoApplication.java deleted file mode 100644 index 928cf66..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/SSODemoApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.yixiang.yshop.ssodemo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SSODemoApplication { - - public static void main(String[] args) { - SpringApplication.run(SSODemoApplication.class, args); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/OAuth2Client.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/OAuth2Client.java deleted file mode 100644 index 921e635..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/OAuth2Client.java +++ /dev/null @@ -1,157 +0,0 @@ -package co.yixiang.yshop.ssodemo.client; - -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO; -import co.yixiang.yshop.ssodemo.client.dto.oauth2.OAuth2CheckTokenRespDTO; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; -import org.springframework.stereotype.Component; -import org.springframework.util.Assert; -import org.springframework.util.Base64Utils; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.nio.charset.StandardCharsets; - -/** - * OAuth 2.0 客户端 - * - * 对应调用 OAuth2OpenController 接口 - */ -@Component -public class OAuth2Client { - - private static final String BASE_URL = "http://127.0.0.1:48080/admin-api/system/oauth2"; - - /** - * 租户编号 - * - * 默认使用 1;如果使用别的租户,可以调整 - */ - public static final Long TENANT_ID = 1L; - - private static final String CLIENT_ID = "yshop-sso-demo-by-code"; - private static final String CLIENT_SECRET = "test"; - - -// @Resource // 可优化,注册一个 RestTemplate Bean,然后注入 - private final RestTemplate restTemplate = new RestTemplate(); - - /** - * 使用 code 授权码,获得访问令牌 - * - * @param code 授权码 - * @param redirectUri 重定向 URI - * @return 访问令牌 - */ - public CommonResult postAccessToken(String code, String redirectUri) { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", TENANT_ID.toString()); - addClientHeader(headers); - // 1.2 构建请求参数 - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("grant_type", "authorization_code"); - body.add("code", code); - body.add("redirect_uri", redirectUri); -// body.add("state", ""); // 选填;填了会校验 - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/token", - HttpMethod.POST, - new HttpEntity<>(body, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - /** - * 校验访问令牌,并返回它的基本信息 - * - * @param token 访问令牌 - * @return 访问令牌的基本信息 - */ - public CommonResult checkToken(String token) { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", TENANT_ID.toString()); - addClientHeader(headers); - // 1.2 构建请求参数 - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("token", token); - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/check-token", - HttpMethod.POST, - new HttpEntity<>(body, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - /** - * 使用刷新令牌,获得(刷新)访问令牌 - * - * @param refreshToken 刷新令牌 - * @return 访问令牌 - */ - public CommonResult refreshToken(String refreshToken) { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", TENANT_ID.toString()); - addClientHeader(headers); - // 1.2 构建请求参数 - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("grant_type", "refresh_token"); - body.add("refresh_token", refreshToken); - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/token", - HttpMethod.POST, - new HttpEntity<>(body, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - /** - * 删除访问令牌 - * - * @param token 访问令牌 - * @return 成功 - */ - public CommonResult revokeToken(String token) { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", TENANT_ID.toString()); - addClientHeader(headers); - // 1.2 构建请求参数 - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("token", token); - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/token", - HttpMethod.DELETE, - new HttpEntity<>(body, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - private static void addClientHeader(HttpHeaders headers) { - // client 拼接,需要 BASE64 编码 - String client = CLIENT_ID + ":" + CLIENT_SECRET; - client = Base64Utils.encodeToString(client.getBytes(StandardCharsets.UTF_8)); - headers.add("Authorization", "Basic " + client); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/UserClient.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/UserClient.java deleted file mode 100644 index 48c11a6..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/UserClient.java +++ /dev/null @@ -1,73 +0,0 @@ -package co.yixiang.yshop.ssodemo.client; - -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.user.UserInfoRespDTO; -import co.yixiang.yshop.ssodemo.client.dto.user.UserUpdateReqDTO; -import co.yixiang.yshop.ssodemo.framework.core.LoginUser; -import co.yixiang.yshop.ssodemo.framework.core.util.SecurityUtils; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; -import org.springframework.stereotype.Component; -import org.springframework.util.Assert; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -/** - * 用户 User 信息的客户端 - * - * 对应调用 OAuth2UserController 接口 - */ -@Component -public class UserClient { - - private static final String BASE_URL = "http://127.0.0.1:48080/admin-api//system/oauth2/user"; - - // @Resource // 可优化,注册一个 RestTemplate Bean,然后注入 - private final RestTemplate restTemplate = new RestTemplate(); - - public CommonResult getUser() { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", OAuth2Client.TENANT_ID.toString()); - addTokenHeader(headers); - // 1.2 构建请求参数 - MultiValueMap body = new LinkedMultiValueMap<>(); - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/get", - HttpMethod.GET, - new HttpEntity<>(body, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - public CommonResult updateUser(UserUpdateReqDTO updateReqDTO) { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.set("tenant-id", OAuth2Client.TENANT_ID.toString()); - addTokenHeader(headers); - // 1.2 构建请求参数 - // 使用 updateReqDTO 即可 - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/update", - HttpMethod.PUT, - new HttpEntity<>(updateReqDTO, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - - private static void addTokenHeader(HttpHeaders headers) { - LoginUser loginUser = SecurityUtils.getLoginUser(); - Assert.notNull(loginUser, "登录用户不能为空"); - headers.add("Authorization", "Bearer " + loginUser.getAccessToken()); - } -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/CommonResult.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/CommonResult.java deleted file mode 100644 index cbc2e89..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/CommonResult.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto; - -import lombok.Data; - -import java.io.Serializable; - -/** - * 通用返回 - * - * @param 数据泛型 - */ -@Data -public class CommonResult implements Serializable { - - /** - * 错误码 - */ - private Integer code; - /** - * 返回数据 - */ - private T data; - /** - * 错误提示,用户可阅读 - */ - private String msg; - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2AccessTokenRespDTO.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2AccessTokenRespDTO.java deleted file mode 100644 index 3e19e4f..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2AccessTokenRespDTO.java +++ /dev/null @@ -1,45 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto.oauth2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 访问令牌 Response DTO - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class OAuth2AccessTokenRespDTO { - - /** - * 访问令牌 - */ - @JsonProperty("access_token") - private String accessToken; - - /** - * 刷新令牌 - */ - @JsonProperty("refresh_token") - private String refreshToken; - - /** - * 令牌类型 - */ - @JsonProperty("token_type") - private String tokenType; - - /** - * 过期时间;单位:秒 - */ - @JsonProperty("expires_in") - private Long expiresIn; - - /** - * 授权范围;如果多个授权范围,使用空格分隔 - */ - private String scope; - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2CheckTokenRespDTO.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2CheckTokenRespDTO.java deleted file mode 100644 index d9dee50..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2CheckTokenRespDTO.java +++ /dev/null @@ -1,59 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto.oauth2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 校验令牌 Response DTO - * - * @author yshop - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class OAuth2CheckTokenRespDTO { - - /** - * 用户编号 - */ - @JsonProperty("user_id") - private Long userId; - /** - * 用户类型 - */ - @JsonProperty("user_type") - private Integer userType; - /** - * 租户编号 - */ - @JsonProperty("tenant_id") - private Long tenantId; - - /** - * 客户端编号 - */ - @JsonProperty("client_id") - private String clientId; - /** - * 授权范围 - */ - private List scopes; - - /** - * 访问令牌 - */ - @JsonProperty("access_token") - private String accessToken; - - /** - * 过期时间 - * - * 时间戳 / 1000,即单位:秒 - */ - private Long exp; - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserInfoRespDTO.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserInfoRespDTO.java deleted file mode 100644 index 4aa1ae3..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserInfoRespDTO.java +++ /dev/null @@ -1,97 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto.user; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 获得用户基本信息 Response dto - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class UserInfoRespDTO { - - /** - * 用户编号 - */ - private Long id; - - /** - * 用户账号 - */ - private String username; - - /** - * 用户昵称 - */ - private String nickname; - - /** - * 用户邮箱 - */ - private String email; - /** - * 手机号码 - */ - private String mobile; - - /** - * 用户性别 - */ - private Integer sex; - - /** - * 用户头像 - */ - private String avatar; - - /** - * 所在部门 - */ - private Dept dept; - - /** - * 所属岗位数组 - */ - private List posts; - - /** - * 部门 - */ - @Data - public static class Dept { - - /** - * 部门编号 - */ - private Long id; - - /** - * 部门名称 - */ - private String name; - - } - - /** - * 岗位 - */ - @Data - public static class Post { - - /** - * 岗位编号 - */ - private Long id; - - /** - * 岗位名称 - */ - private String name; - - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserUpdateReqDTO.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserUpdateReqDTO.java deleted file mode 100644 index e2b7912..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserUpdateReqDTO.java +++ /dev/null @@ -1,35 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto.user; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 更新用户基本信息 Request DTO - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class UserUpdateReqDTO { - - /** - * 用户昵称 - */ - private String nickname; - - /** - * 用户邮箱 - */ - private String email; - - /** - * 手机号码 - */ - private String mobile; - - /** - * 用户性别 - */ - private Integer sex; - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/controller/AuthController.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/controller/AuthController.java deleted file mode 100644 index cd6eddb..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/controller/AuthController.java +++ /dev/null @@ -1,63 +0,0 @@ -package co.yixiang.yshop.ssodemo.controller; - -import cn.hutool.core.util.StrUtil; -import co.yixiang.yshop.ssodemo.client.OAuth2Client; -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO; -import co.yixiang.yshop.ssodemo.framework.core.util.SecurityUtils; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; - -@RestController -@RequestMapping("/auth") -public class AuthController { - - @Resource - private OAuth2Client oauth2Client; - - /** - * 使用 code 访问令牌,获得访问令牌 - * - * @param code 授权码 - * @param redirectUri 重定向 URI - * @return 访问令牌;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段 - */ - @PostMapping("/login-by-code") - public CommonResult loginByCode(@RequestParam("code") String code, - @RequestParam("redirectUri") String redirectUri) { - return oauth2Client.postAccessToken(code, redirectUri); - } - - /** - * 使用刷新令牌,获得(刷新)访问令牌 - * - * @param refreshToken 刷新令牌 - * @return 访问令牌;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段 - */ - @PostMapping("/refresh-token") - public CommonResult refreshToken(@RequestParam("refreshToken") String refreshToken) { - return oauth2Client.refreshToken(refreshToken); - } - - /** - * 退出登录 - * - * @param request 请求 - * @return 成功 - */ - @PostMapping("/logout") - public CommonResult logout(HttpServletRequest request) { - String token = SecurityUtils.obtainAuthorization(request, "Authorization"); - if (StrUtil.isNotBlank(token)) { - return oauth2Client.revokeToken(token); - } - // 返回成功 - return new CommonResult<>(); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/controller/UserController.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/controller/UserController.java deleted file mode 100644 index 59b0854..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/controller/UserController.java +++ /dev/null @@ -1,40 +0,0 @@ -package co.yixiang.yshop.ssodemo.controller; - -import co.yixiang.yshop.ssodemo.client.UserClient; -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.user.UserInfoRespDTO; -import co.yixiang.yshop.ssodemo.client.dto.user.UserUpdateReqDTO; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; - -@RestController -@RequestMapping("/user") -public class UserController { - - @Resource - private UserClient userClient; - - /** - * 获得当前登录用户的基本信息 - * - * @return 用户信息;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段 - */ - @GetMapping("/get") - public CommonResult getUser() { - return userClient.getUser(); - } - - /** - * 更新当前登录用户的昵称 - * - * @param nickname 昵称 - * @return 成功 - */ - @PutMapping("/update") - public CommonResult updateUser(@RequestParam("nickname") String nickname) { - UserUpdateReqDTO updateReqDTO = new UserUpdateReqDTO(nickname, null, null, null); - return userClient.updateUser(updateReqDTO); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/config/SecurityConfiguration.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/config/SecurityConfiguration.java deleted file mode 100644 index 0c01f80..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/config/SecurityConfiguration.java +++ /dev/null @@ -1,52 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.config; - -import co.yixiang.yshop.ssodemo.framework.core.filter.TokenAuthenticationFilter; -import co.yixiang.yshop.ssodemo.framework.core.handler.AccessDeniedHandlerImpl; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; - -import javax.annotation.Resource; - -@Configuration(proxyBeanMethods = false) -@EnableWebSecurity -public class SecurityConfiguration{ - - @Resource - private TokenAuthenticationFilter tokenAuthenticationFilter; - - @Resource - private AccessDeniedHandlerImpl accessDeniedHandler; - @Resource - private AuthenticationEntryPoint authenticationEntryPoint; - - @Bean - protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { - // 设置 URL 安全权限 - httpSecurity.csrf().disable() // 禁用 CSRF 保护 - .authorizeRequests() - // 1. 静态资源,可匿名访问 - .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() - // 2. 登录相关的接口,可匿名访问 - .antMatchers("/auth/login-by-code").permitAll() - .antMatchers("/auth/refresh-token").permitAll() - .antMatchers("/auth/logout").permitAll() - // last. 兜底规则,必须认证 - .and().authorizeRequests() - .anyRequest().authenticated(); - - // 设置处理器 - httpSecurity.exceptionHandling().accessDeniedHandler(accessDeniedHandler) - .authenticationEntryPoint(authenticationEntryPoint); - - // 添加 Token Filter - httpSecurity.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); - return httpSecurity.build(); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/LoginUser.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/LoginUser.java deleted file mode 100644 index 10ad44e..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/LoginUser.java +++ /dev/null @@ -1,37 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core; - -import lombok.Data; - -import java.util.List; - -/** - * 登录用户信息 - * - * @author yshop - */ -@Data -public class LoginUser { - - /** - * 用户编号 - */ - private Long id; - /** - * 用户类型 - */ - private Integer userType; - /** - * 租户编号 - */ - private Long tenantId; - /** - * 授权范围 - */ - private List scopes; - - /** - * 访问令牌 - */ - private String accessToken; - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/filter/TokenAuthenticationFilter.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/filter/TokenAuthenticationFilter.java deleted file mode 100644 index 075c291..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/filter/TokenAuthenticationFilter.java +++ /dev/null @@ -1,66 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.filter; - -import co.yixiang.yshop.ssodemo.client.OAuth2Client; -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.oauth2.OAuth2CheckTokenRespDTO; -import co.yixiang.yshop.ssodemo.framework.core.LoginUser; -import co.yixiang.yshop.ssodemo.framework.core.util.SecurityUtils; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.annotation.Resource; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Token 过滤器,验证 token 的有效性 - * 验证通过后,获得 {@link LoginUser} 信息,并加入到 Spring Security 上下文 - * - * @author yshop - */ -@Component -public class TokenAuthenticationFilter extends OncePerRequestFilter { - - @Resource - private OAuth2Client oauth2Client; - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { - // 1. 获得访问令牌 - String token = SecurityUtils.obtainAuthorization(request, "Authorization"); - if (StringUtils.hasText(token)) { - // 2. 基于 token 构建登录用户 - LoginUser loginUser = buildLoginUserByToken(token); - // 3. 设置当前用户 - if (loginUser != null) { - SecurityUtils.setLoginUser(loginUser, request); - } - } - - // 继续过滤链 - filterChain.doFilter(request, response); - } - - private LoginUser buildLoginUserByToken(String token) { - try { - CommonResult accessTokenResult = oauth2Client.checkToken(token); - OAuth2CheckTokenRespDTO accessToken = accessTokenResult.getData(); - if (accessToken == null) { - return null; - } - // 构建登录用户 - return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType()) - .setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes()) - .setAccessToken(accessToken.getAccessToken()); - } catch (Exception exception) { - // 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可 - return null; - } - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AccessDeniedHandlerImpl.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AccessDeniedHandlerImpl.java deleted file mode 100644 index 2a35ede..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AccessDeniedHandlerImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.handler; - -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.framework.core.util.SecurityUtils; -import co.yixiang.yshop.ssodemo.framework.core.util.ServletUtils; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.security.web.access.ExceptionTranslationFilter; -import org.springframework.stereotype.Component; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。 - * - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#handleAccessDeniedException(HttpServletRequest, HttpServletResponse, FilterChain, AccessDeniedException)} 方法,调用当前类 - * - * @author yshop - */ -@Component -@SuppressWarnings("JavadocReference") -@Slf4j -public class AccessDeniedHandlerImpl implements AccessDeniedHandler { - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) - throws IOException, ServletException { - // 打印 warn 的原因是,不定期合并 warn,看看有没恶意破坏 - log.warn("[commence][访问 URL({}) 时,用户({}) 权限不够]", request.getRequestURI(), - SecurityUtils.getLoginUserId(), e); - // 返回 403 - CommonResult result = new CommonResult<>(); - result.setCode(HttpStatus.FORBIDDEN.value()); - result.setMsg("没有该操作权限"); - ServletUtils.writeJSON(response, result); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AuthenticationEntryPointImpl.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AuthenticationEntryPointImpl.java deleted file mode 100644 index 8ad8bd0..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AuthenticationEntryPointImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.handler; - -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.framework.core.util.ServletUtils; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.security.web.access.ExceptionTranslationFilter; -import org.springframework.stereotype.Component; - -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * 访问一个需要认证的 URL 资源,但是此时自己尚未认证(登录)的情况下,返回 {@link GlobalErrorCodeConstants#UNAUTHORIZED} 错误码,从而使前端重定向到登录页 - * - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#sendStartAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, AuthenticationException)} 方法,调用当前类 - */ -@Component -@Slf4j -@SuppressWarnings("JavadocReference") // 忽略文档引用报错 -public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { - - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) { - log.debug("[commence][访问 URL({}) 时,没有登录]", request.getRequestURI(), e); - // 返回 401 - CommonResult result = new CommonResult<>(); - result.setCode(HttpStatus.UNAUTHORIZED.value()); - result.setMsg("账号未登录"); - ServletUtils.writeJSON(response, result); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/SecurityUtils.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/SecurityUtils.java deleted file mode 100644 index 1154f0b..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/SecurityUtils.java +++ /dev/null @@ -1,103 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.util; - -import co.yixiang.yshop.ssodemo.framework.core.LoginUser; -import org.springframework.lang.Nullable; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.util.StringUtils; - -import javax.servlet.http.HttpServletRequest; -import java.util.Collections; - -/** - * 安全服务工具类 - * - * @author yshop - */ -public class SecurityUtils { - - public static final String AUTHORIZATION_BEARER = "Bearer"; - - private SecurityUtils() {} - - /** - * 从请求中,获得认证 Token - * - * @param request 请求 - * @param header 认证 Token 对应的 Header 名字 - * @return 认证 Token - */ - public static String obtainAuthorization(HttpServletRequest request, String header) { - String authorization = request.getHeader(header); - if (!StringUtils.hasText(authorization)) { - return null; - } - int index = authorization.indexOf(AUTHORIZATION_BEARER + " "); - if (index == -1) { // 未找到 - return null; - } - return authorization.substring(index + 7).trim(); - } - - /** - * 获得当前认证信息 - * - * @return 认证信息 - */ - public static Authentication getAuthentication() { - SecurityContext context = SecurityContextHolder.getContext(); - if (context == null) { - return null; - } - return context.getAuthentication(); - } - - /** - * 获取当前用户 - * - * @return 当前用户 - */ - @Nullable - public static LoginUser getLoginUser() { - Authentication authentication = getAuthentication(); - if (authentication == null) { - return null; - } - return authentication.getPrincipal() instanceof LoginUser ? (LoginUser) authentication.getPrincipal() : null; - } - - /** - * 获得当前用户的编号,从上下文中 - * - * @return 用户编号 - */ - @Nullable - public static Long getLoginUserId() { - LoginUser loginUser = getLoginUser(); - return loginUser != null ? loginUser.getId() : null; - } - - /** - * 设置当前用户 - * - * @param loginUser 登录用户 - * @param request 请求 - */ - public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) { - // 创建 Authentication,并设置到上下文 - Authentication authentication = buildAuthentication(loginUser, request); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - - private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) { - // 创建 UsernamePasswordAuthenticationToken 对象 - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( - loginUser, null, Collections.emptyList()); - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - return authenticationToken; - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/ServletUtils.java b/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/ServletUtils.java deleted file mode 100644 index 4d81655..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/ServletUtils.java +++ /dev/null @@ -1,32 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.util; - -import cn.hutool.extra.servlet.ServletUtil; -import cn.hutool.json.JSONUtil; -import org.springframework.http.MediaType; - -import javax.servlet.http.HttpServletResponse; - -/** - * 客户端工具类 - * - * @author yshop - */ -public class ServletUtils { - - /** - * 返回 JSON 字符串 - * - * @param response 响应 - * @param object 对象,会序列化成 JSON 字符串 - */ - @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码 - public static void writeJSON(HttpServletResponse response, Object object) { - String content = JSONUtil.toJsonStr(object); - ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE); - } - - public static void write(HttpServletResponse response, String text, String contentType) { - ServletUtil.write(response, text, contentType); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/resources/application.yaml b/yshop-example/yshop-sso-demo-by-code/src/main/resources/application.yaml deleted file mode 100644 index a62cf97..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/resources/application.yaml +++ /dev/null @@ -1,2 +0,0 @@ -server: - port: 18080 diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/resources/static/callback.html b/yshop-example/yshop-sso-demo-by-code/src/main/resources/static/callback.html deleted file mode 100644 index 123a1af..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/resources/static/callback.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - SSO 授权后的回调页 - - - - - - - - -正在使用 code 授权码,进行 accessToken 访问令牌的获取 - - diff --git a/yshop-example/yshop-sso-demo-by-code/src/main/resources/static/index.html b/yshop-example/yshop-sso-demo-by-code/src/main/resources/static/index.html deleted file mode 100644 index 40a6c1c..0000000 --- a/yshop-example/yshop-sso-demo-by-code/src/main/resources/static/index.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - 首页 - - - - - - - - - - - - - - diff --git a/yshop-example/yshop-sso-demo-by-password/pom.xml b/yshop-example/yshop-sso-demo-by-password/pom.xml deleted file mode 100644 index b61327d..0000000 --- a/yshop-example/yshop-sso-demo-by-password/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - - - - co.yixiang.boot - yshop-sso-demo-by-password - 1.0.0-snapshot - jar - - ${project.artifactId} - 基于密码模式,如何实现 SSO 单点登录? - https://github.com/YunaiV/ruoyi-vue-pro - - - - 8 - 8 - UTF-8 - - 2.7.10 - - - - - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-security - - - - cn.hutool - hutool-all - 5.8.15 - - - - org.projectlombok - lombok - true - - - - diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/SSODemoApplication.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/SSODemoApplication.java deleted file mode 100644 index 928cf66..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/SSODemoApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.yixiang.yshop.ssodemo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SSODemoApplication { - - public static void main(String[] args) { - SpringApplication.run(SSODemoApplication.class, args); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/OAuth2Client.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/OAuth2Client.java deleted file mode 100644 index 5492961..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/OAuth2Client.java +++ /dev/null @@ -1,127 +0,0 @@ -package co.yixiang.yshop.ssodemo.client; - -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO; -import co.yixiang.yshop.ssodemo.client.dto.oauth2.OAuth2CheckTokenRespDTO; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; -import org.springframework.stereotype.Component; -import org.springframework.util.Assert; -import org.springframework.util.Base64Utils; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.nio.charset.StandardCharsets; - -/** - * OAuth 2.0 客户端 - * - * 对应调用 OAuth2OpenController 接口 - */ -@Component -public class OAuth2Client { - - private static final String BASE_URL = "http://127.0.0.1:48080/admin-api/system/oauth2"; - - /** - * 租户编号 - * - * 默认使用 1;如果使用别的租户,可以调整 - */ - public static final Long TENANT_ID = 1L; - - private static final String CLIENT_ID = "yshop-sso-demo-by-password"; - private static final String CLIENT_SECRET = "test"; - - -// @Resource // 可优化,注册一个 RestTemplate Bean,然后注入 - private final RestTemplate restTemplate = new RestTemplate(); - - /** - * 校验访问令牌,并返回它的基本信息 - * - * @param token 访问令牌 - * @return 访问令牌的基本信息 - */ - public CommonResult checkToken(String token) { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", TENANT_ID.toString()); - addClientHeader(headers); - // 1.2 构建请求参数 - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("token", token); - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/check-token", - HttpMethod.POST, - new HttpEntity<>(body, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - /** - * 使用刷新令牌,获得(刷新)访问令牌 - * - * @param refreshToken 刷新令牌 - * @return 访问令牌 - */ - public CommonResult refreshToken(String refreshToken) { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", TENANT_ID.toString()); - addClientHeader(headers); - // 1.2 构建请求参数 - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("grant_type", "refresh_token"); - body.add("refresh_token", refreshToken); - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/token", - HttpMethod.POST, - new HttpEntity<>(body, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - /** - * 删除访问令牌 - * - * @param token 访问令牌 - * @return 成功 - */ - public CommonResult revokeToken(String token) { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", TENANT_ID.toString()); - addClientHeader(headers); - // 1.2 构建请求参数 - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("token", token); - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/token", - HttpMethod.DELETE, - new HttpEntity<>(body, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - private static void addClientHeader(HttpHeaders headers) { - // client 拼接,需要 BASE64 编码 - String client = CLIENT_ID + ":" + CLIENT_SECRET; - client = Base64Utils.encodeToString(client.getBytes(StandardCharsets.UTF_8)); - headers.add("Authorization", "Basic " + client); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/UserClient.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/UserClient.java deleted file mode 100644 index 48c11a6..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/UserClient.java +++ /dev/null @@ -1,73 +0,0 @@ -package co.yixiang.yshop.ssodemo.client; - -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.user.UserInfoRespDTO; -import co.yixiang.yshop.ssodemo.client.dto.user.UserUpdateReqDTO; -import co.yixiang.yshop.ssodemo.framework.core.LoginUser; -import co.yixiang.yshop.ssodemo.framework.core.util.SecurityUtils; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; -import org.springframework.stereotype.Component; -import org.springframework.util.Assert; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -/** - * 用户 User 信息的客户端 - * - * 对应调用 OAuth2UserController 接口 - */ -@Component -public class UserClient { - - private static final String BASE_URL = "http://127.0.0.1:48080/admin-api//system/oauth2/user"; - - // @Resource // 可优化,注册一个 RestTemplate Bean,然后注入 - private final RestTemplate restTemplate = new RestTemplate(); - - public CommonResult getUser() { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("tenant-id", OAuth2Client.TENANT_ID.toString()); - addTokenHeader(headers); - // 1.2 构建请求参数 - MultiValueMap body = new LinkedMultiValueMap<>(); - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/get", - HttpMethod.GET, - new HttpEntity<>(body, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - public CommonResult updateUser(UserUpdateReqDTO updateReqDTO) { - // 1.1 构建请求头 - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.set("tenant-id", OAuth2Client.TENANT_ID.toString()); - addTokenHeader(headers); - // 1.2 构建请求参数 - // 使用 updateReqDTO 即可 - - // 2. 执行请求 - ResponseEntity> exchange = restTemplate.exchange( - BASE_URL + "/update", - HttpMethod.PUT, - new HttpEntity<>(updateReqDTO, headers), - new ParameterizedTypeReference>() {}); // 解决 CommonResult 的泛型丢失 - Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功"); - return exchange.getBody(); - } - - - private static void addTokenHeader(HttpHeaders headers) { - LoginUser loginUser = SecurityUtils.getLoginUser(); - Assert.notNull(loginUser, "登录用户不能为空"); - headers.add("Authorization", "Bearer " + loginUser.getAccessToken()); - } -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/CommonResult.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/CommonResult.java deleted file mode 100644 index cbc2e89..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/CommonResult.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto; - -import lombok.Data; - -import java.io.Serializable; - -/** - * 通用返回 - * - * @param 数据泛型 - */ -@Data -public class CommonResult implements Serializable { - - /** - * 错误码 - */ - private Integer code; - /** - * 返回数据 - */ - private T data; - /** - * 错误提示,用户可阅读 - */ - private String msg; - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2AccessTokenRespDTO.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2AccessTokenRespDTO.java deleted file mode 100644 index 3e19e4f..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2AccessTokenRespDTO.java +++ /dev/null @@ -1,45 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto.oauth2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 访问令牌 Response DTO - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class OAuth2AccessTokenRespDTO { - - /** - * 访问令牌 - */ - @JsonProperty("access_token") - private String accessToken; - - /** - * 刷新令牌 - */ - @JsonProperty("refresh_token") - private String refreshToken; - - /** - * 令牌类型 - */ - @JsonProperty("token_type") - private String tokenType; - - /** - * 过期时间;单位:秒 - */ - @JsonProperty("expires_in") - private Long expiresIn; - - /** - * 授权范围;如果多个授权范围,使用空格分隔 - */ - private String scope; - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2CheckTokenRespDTO.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2CheckTokenRespDTO.java deleted file mode 100644 index d9dee50..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/oauth2/OAuth2CheckTokenRespDTO.java +++ /dev/null @@ -1,59 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto.oauth2; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 校验令牌 Response DTO - * - * @author yshop - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class OAuth2CheckTokenRespDTO { - - /** - * 用户编号 - */ - @JsonProperty("user_id") - private Long userId; - /** - * 用户类型 - */ - @JsonProperty("user_type") - private Integer userType; - /** - * 租户编号 - */ - @JsonProperty("tenant_id") - private Long tenantId; - - /** - * 客户端编号 - */ - @JsonProperty("client_id") - private String clientId; - /** - * 授权范围 - */ - private List scopes; - - /** - * 访问令牌 - */ - @JsonProperty("access_token") - private String accessToken; - - /** - * 过期时间 - * - * 时间戳 / 1000,即单位:秒 - */ - private Long exp; - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserInfoRespDTO.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserInfoRespDTO.java deleted file mode 100644 index 4aa1ae3..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserInfoRespDTO.java +++ /dev/null @@ -1,97 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto.user; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 获得用户基本信息 Response dto - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class UserInfoRespDTO { - - /** - * 用户编号 - */ - private Long id; - - /** - * 用户账号 - */ - private String username; - - /** - * 用户昵称 - */ - private String nickname; - - /** - * 用户邮箱 - */ - private String email; - /** - * 手机号码 - */ - private String mobile; - - /** - * 用户性别 - */ - private Integer sex; - - /** - * 用户头像 - */ - private String avatar; - - /** - * 所在部门 - */ - private Dept dept; - - /** - * 所属岗位数组 - */ - private List posts; - - /** - * 部门 - */ - @Data - public static class Dept { - - /** - * 部门编号 - */ - private Long id; - - /** - * 部门名称 - */ - private String name; - - } - - /** - * 岗位 - */ - @Data - public static class Post { - - /** - * 岗位编号 - */ - private Long id; - - /** - * 岗位名称 - */ - private String name; - - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserUpdateReqDTO.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserUpdateReqDTO.java deleted file mode 100644 index e2b7912..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/client/dto/user/UserUpdateReqDTO.java +++ /dev/null @@ -1,35 +0,0 @@ -package co.yixiang.yshop.ssodemo.client.dto.user; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 更新用户基本信息 Request DTO - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class UserUpdateReqDTO { - - /** - * 用户昵称 - */ - private String nickname; - - /** - * 用户邮箱 - */ - private String email; - - /** - * 手机号码 - */ - private String mobile; - - /** - * 用户性别 - */ - private Integer sex; - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/controller/AuthController.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/controller/AuthController.java deleted file mode 100644 index c5482d7..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/controller/AuthController.java +++ /dev/null @@ -1,50 +0,0 @@ -package co.yixiang.yshop.ssodemo.controller; - -import cn.hutool.core.util.StrUtil; -import co.yixiang.yshop.ssodemo.client.OAuth2Client; -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.oauth2.OAuth2AccessTokenRespDTO; -import co.yixiang.yshop.ssodemo.framework.core.util.SecurityUtils; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; - -@RestController -@RequestMapping("/auth") -public class AuthController { - - @Resource - private OAuth2Client oauth2Client; - - /** - * 使用刷新令牌,获得(刷新)访问令牌 - * - * @param refreshToken 刷新令牌 - * @return 访问令牌;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段 - */ - @PostMapping("/refresh-token") - public CommonResult refreshToken(@RequestParam("refreshToken") String refreshToken) { - return oauth2Client.refreshToken(refreshToken); - } - - /** - * 退出登录 - * - * @param request 请求 - * @return 成功 - */ - @PostMapping("/logout") - public CommonResult logout(HttpServletRequest request) { - String token = SecurityUtils.obtainAuthorization(request, "Authorization"); - if (StrUtil.isNotBlank(token)) { - return oauth2Client.revokeToken(token); - } - // 返回成功 - return new CommonResult<>(); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/controller/UserController.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/controller/UserController.java deleted file mode 100644 index 59b0854..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/controller/UserController.java +++ /dev/null @@ -1,40 +0,0 @@ -package co.yixiang.yshop.ssodemo.controller; - -import co.yixiang.yshop.ssodemo.client.UserClient; -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.user.UserInfoRespDTO; -import co.yixiang.yshop.ssodemo.client.dto.user.UserUpdateReqDTO; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; - -@RestController -@RequestMapping("/user") -public class UserController { - - @Resource - private UserClient userClient; - - /** - * 获得当前登录用户的基本信息 - * - * @return 用户信息;注意,实际项目中,最好创建对应的 ResponseVO 类,只返回必要的字段 - */ - @GetMapping("/get") - public CommonResult getUser() { - return userClient.getUser(); - } - - /** - * 更新当前登录用户的昵称 - * - * @param nickname 昵称 - * @return 成功 - */ - @PutMapping("/update") - public CommonResult updateUser(@RequestParam("nickname") String nickname) { - UserUpdateReqDTO updateReqDTO = new UserUpdateReqDTO(nickname, null, null, null); - return userClient.updateUser(updateReqDTO); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/config/SecurityConfiguration.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/config/SecurityConfiguration.java deleted file mode 100644 index efc4c4a..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/config/SecurityConfiguration.java +++ /dev/null @@ -1,52 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.config; - -import co.yixiang.yshop.ssodemo.framework.core.filter.TokenAuthenticationFilter; -import co.yixiang.yshop.ssodemo.framework.core.handler.AccessDeniedHandlerImpl; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; - -import javax.annotation.Resource; - -@Configuration(proxyBeanMethods = false) -@EnableWebSecurity -public class SecurityConfiguration { - - @Resource - private TokenAuthenticationFilter tokenAuthenticationFilter; - - @Resource - private AccessDeniedHandlerImpl accessDeniedHandler; - @Resource - private AuthenticationEntryPoint authenticationEntryPoint; - - @Bean - protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { - // 设置 URL 安全权限 - httpSecurity.csrf().disable() // 禁用 CSRF 保护 - .authorizeRequests() - // 1. 静态资源,可匿名访问 - .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() - // 2. 登录相关的接口,可匿名访问 - .antMatchers("/auth/login-by-code").permitAll() - .antMatchers("/auth/refresh-token").permitAll() - .antMatchers("/auth/logout").permitAll() - // last. 兜底规则,必须认证 - .and().authorizeRequests() - .anyRequest().authenticated(); - - // 设置处理器 - httpSecurity.exceptionHandling().accessDeniedHandler(accessDeniedHandler) - .authenticationEntryPoint(authenticationEntryPoint); - - // 添加 Token Filter - httpSecurity.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); - return httpSecurity.build(); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/LoginUser.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/LoginUser.java deleted file mode 100644 index 10ad44e..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/LoginUser.java +++ /dev/null @@ -1,37 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core; - -import lombok.Data; - -import java.util.List; - -/** - * 登录用户信息 - * - * @author yshop - */ -@Data -public class LoginUser { - - /** - * 用户编号 - */ - private Long id; - /** - * 用户类型 - */ - private Integer userType; - /** - * 租户编号 - */ - private Long tenantId; - /** - * 授权范围 - */ - private List scopes; - - /** - * 访问令牌 - */ - private String accessToken; - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/filter/TokenAuthenticationFilter.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/filter/TokenAuthenticationFilter.java deleted file mode 100644 index 075c291..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/filter/TokenAuthenticationFilter.java +++ /dev/null @@ -1,66 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.filter; - -import co.yixiang.yshop.ssodemo.client.OAuth2Client; -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.client.dto.oauth2.OAuth2CheckTokenRespDTO; -import co.yixiang.yshop.ssodemo.framework.core.LoginUser; -import co.yixiang.yshop.ssodemo.framework.core.util.SecurityUtils; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.annotation.Resource; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Token 过滤器,验证 token 的有效性 - * 验证通过后,获得 {@link LoginUser} 信息,并加入到 Spring Security 上下文 - * - * @author yshop - */ -@Component -public class TokenAuthenticationFilter extends OncePerRequestFilter { - - @Resource - private OAuth2Client oauth2Client; - - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { - // 1. 获得访问令牌 - String token = SecurityUtils.obtainAuthorization(request, "Authorization"); - if (StringUtils.hasText(token)) { - // 2. 基于 token 构建登录用户 - LoginUser loginUser = buildLoginUserByToken(token); - // 3. 设置当前用户 - if (loginUser != null) { - SecurityUtils.setLoginUser(loginUser, request); - } - } - - // 继续过滤链 - filterChain.doFilter(request, response); - } - - private LoginUser buildLoginUserByToken(String token) { - try { - CommonResult accessTokenResult = oauth2Client.checkToken(token); - OAuth2CheckTokenRespDTO accessToken = accessTokenResult.getData(); - if (accessToken == null) { - return null; - } - // 构建登录用户 - return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType()) - .setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes()) - .setAccessToken(accessToken.getAccessToken()); - } catch (Exception exception) { - // 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可 - return null; - } - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AccessDeniedHandlerImpl.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AccessDeniedHandlerImpl.java deleted file mode 100644 index 2a35ede..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AccessDeniedHandlerImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.handler; - -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.framework.core.util.SecurityUtils; -import co.yixiang.yshop.ssodemo.framework.core.util.ServletUtils; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.security.web.access.ExceptionTranslationFilter; -import org.springframework.stereotype.Component; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。 - * - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#handleAccessDeniedException(HttpServletRequest, HttpServletResponse, FilterChain, AccessDeniedException)} 方法,调用当前类 - * - * @author yshop - */ -@Component -@SuppressWarnings("JavadocReference") -@Slf4j -public class AccessDeniedHandlerImpl implements AccessDeniedHandler { - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) - throws IOException, ServletException { - // 打印 warn 的原因是,不定期合并 warn,看看有没恶意破坏 - log.warn("[commence][访问 URL({}) 时,用户({}) 权限不够]", request.getRequestURI(), - SecurityUtils.getLoginUserId(), e); - // 返回 403 - CommonResult result = new CommonResult<>(); - result.setCode(HttpStatus.FORBIDDEN.value()); - result.setMsg("没有该操作权限"); - ServletUtils.writeJSON(response, result); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AuthenticationEntryPointImpl.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AuthenticationEntryPointImpl.java deleted file mode 100644 index 8ad8bd0..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/handler/AuthenticationEntryPointImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.handler; - -import co.yixiang.yshop.ssodemo.client.dto.CommonResult; -import co.yixiang.yshop.ssodemo.framework.core.util.ServletUtils; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.security.web.access.ExceptionTranslationFilter; -import org.springframework.stereotype.Component; - -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * 访问一个需要认证的 URL 资源,但是此时自己尚未认证(登录)的情况下,返回 {@link GlobalErrorCodeConstants#UNAUTHORIZED} 错误码,从而使前端重定向到登录页 - * - * 补充:Spring Security 通过 {@link ExceptionTranslationFilter#sendStartAuthentication(HttpServletRequest, HttpServletResponse, FilterChain, AuthenticationException)} 方法,调用当前类 - */ -@Component -@Slf4j -@SuppressWarnings("JavadocReference") // 忽略文档引用报错 -public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { - - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) { - log.debug("[commence][访问 URL({}) 时,没有登录]", request.getRequestURI(), e); - // 返回 401 - CommonResult result = new CommonResult<>(); - result.setCode(HttpStatus.UNAUTHORIZED.value()); - result.setMsg("账号未登录"); - ServletUtils.writeJSON(response, result); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/SecurityUtils.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/SecurityUtils.java deleted file mode 100644 index 1154f0b..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/SecurityUtils.java +++ /dev/null @@ -1,103 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.util; - -import co.yixiang.yshop.ssodemo.framework.core.LoginUser; -import org.springframework.lang.Nullable; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.util.StringUtils; - -import javax.servlet.http.HttpServletRequest; -import java.util.Collections; - -/** - * 安全服务工具类 - * - * @author yshop - */ -public class SecurityUtils { - - public static final String AUTHORIZATION_BEARER = "Bearer"; - - private SecurityUtils() {} - - /** - * 从请求中,获得认证 Token - * - * @param request 请求 - * @param header 认证 Token 对应的 Header 名字 - * @return 认证 Token - */ - public static String obtainAuthorization(HttpServletRequest request, String header) { - String authorization = request.getHeader(header); - if (!StringUtils.hasText(authorization)) { - return null; - } - int index = authorization.indexOf(AUTHORIZATION_BEARER + " "); - if (index == -1) { // 未找到 - return null; - } - return authorization.substring(index + 7).trim(); - } - - /** - * 获得当前认证信息 - * - * @return 认证信息 - */ - public static Authentication getAuthentication() { - SecurityContext context = SecurityContextHolder.getContext(); - if (context == null) { - return null; - } - return context.getAuthentication(); - } - - /** - * 获取当前用户 - * - * @return 当前用户 - */ - @Nullable - public static LoginUser getLoginUser() { - Authentication authentication = getAuthentication(); - if (authentication == null) { - return null; - } - return authentication.getPrincipal() instanceof LoginUser ? (LoginUser) authentication.getPrincipal() : null; - } - - /** - * 获得当前用户的编号,从上下文中 - * - * @return 用户编号 - */ - @Nullable - public static Long getLoginUserId() { - LoginUser loginUser = getLoginUser(); - return loginUser != null ? loginUser.getId() : null; - } - - /** - * 设置当前用户 - * - * @param loginUser 登录用户 - * @param request 请求 - */ - public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) { - // 创建 Authentication,并设置到上下文 - Authentication authentication = buildAuthentication(loginUser, request); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - - private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) { - // 创建 UsernamePasswordAuthenticationToken 对象 - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( - loginUser, null, Collections.emptyList()); - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - return authenticationToken; - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/ServletUtils.java b/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/ServletUtils.java deleted file mode 100644 index 4d81655..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/java/co/yixiang/yshop/ssodemo/framework/core/util/ServletUtils.java +++ /dev/null @@ -1,32 +0,0 @@ -package co.yixiang.yshop.ssodemo.framework.core.util; - -import cn.hutool.extra.servlet.ServletUtil; -import cn.hutool.json.JSONUtil; -import org.springframework.http.MediaType; - -import javax.servlet.http.HttpServletResponse; - -/** - * 客户端工具类 - * - * @author yshop - */ -public class ServletUtils { - - /** - * 返回 JSON 字符串 - * - * @param response 响应 - * @param object 对象,会序列化成 JSON 字符串 - */ - @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码 - public static void writeJSON(HttpServletResponse response, Object object) { - String content = JSONUtil.toJsonStr(object); - ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE); - } - - public static void write(HttpServletResponse response, String text, String contentType) { - ServletUtil.write(response, text, contentType); - } - -} diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/resources/application.yaml b/yshop-example/yshop-sso-demo-by-password/src/main/resources/application.yaml deleted file mode 100644 index a62cf97..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/resources/application.yaml +++ /dev/null @@ -1,2 +0,0 @@ -server: - port: 18080 diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/resources/static/index.html b/yshop-example/yshop-sso-demo-by-password/src/main/resources/static/index.html deleted file mode 100644 index 8a53729..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/resources/static/index.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - 首页 - - - - - - - - - - - - - - diff --git a/yshop-example/yshop-sso-demo-by-password/src/main/resources/static/login.html b/yshop-example/yshop-sso-demo-by-password/src/main/resources/static/login.html deleted file mode 100644 index e9c2ee6..0000000 --- a/yshop-example/yshop-sso-demo-by-password/src/main/resources/static/login.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - 登录 - - - - - - -账号:
-密码:
- - - - diff --git a/yshop-framework/pom.xml b/yshop-framework/pom.xml index 3834ae0..02950c5 100644 --- a/yshop-framework/pom.xml +++ b/yshop-framework/pom.xml @@ -30,7 +30,6 @@ yshop-spring-boot-starter-biz-dict yshop-spring-boot-starter-biz-sms - yshop-spring-boot-starter-biz-pay yshop-spring-boot-starter-biz-weixin yshop-spring-boot-starter-biz-social yshop-spring-boot-starter-biz-tenant @@ -55,6 +54,6 @@ 2. 业务组件:和业务相关的组件的封装,例如说数据字典、操作日志等等。 如果是业务组件,Maven 名字会包含 biz - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-common/pom.xml b/yshop-framework/yshop-common/pom.xml index 0f8a33c..df50609 100644 --- a/yshop-framework/yshop-common/pom.xml +++ b/yshop-framework/yshop-common/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 定义基础 pojo 类、枚举、工具类等等 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-common/src/main/java/co/yixiang/yshop/framework/common/constant/ShopConstants.java b/yshop-framework/yshop-common/src/main/java/co/yixiang/yshop/framework/common/constant/ShopConstants.java index d66fba6..d797c9f 100644 --- a/yshop-framework/yshop-common/src/main/java/co/yixiang/yshop/framework/common/constant/ShopConstants.java +++ b/yshop-framework/yshop-common/src/main/java/co/yixiang/yshop/framework/common/constant/ShopConstants.java @@ -181,4 +181,7 @@ public interface ShopConstants { String WECHAT_FOLLOW_IMG="wechat_follow_img"; /**后台api地址*/ String ADMIN_API_URL="admin_api_url"; + + //快递查询接口Logistic + String KDNIAO_LOGISTIC_QUERY="https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx"; } diff --git a/yshop-framework/yshop-common/《芋道 Spring Boot 参数校验 Validation 入门》.md b/yshop-framework/yshop-common/《芋道 Spring Boot 参数校验 Validation 入门》.md deleted file mode 100644 index cedbca3..0000000 --- a/yshop-framework/yshop-common/《芋道 Spring Boot 参数校验 Validation 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-banner/pom.xml b/yshop-framework/yshop-spring-boot-starter-banner/pom.xml index 94a14aa..47d63a6 100644 --- a/yshop-framework/yshop-spring-boot-starter-banner/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-banner/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} Banner 用于在 console 控制台,打印开发文档、接口文档等 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-biz-data-permission/pom.xml b/yshop-framework/yshop-spring-boot-starter-biz-data-permission/pom.xml index 483683b..be5dd12 100644 --- a/yshop-framework/yshop-spring-boot-starter-biz-data-permission/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-biz-data-permission/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 数据权限 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-biz-dict/pom.xml b/yshop-framework/yshop-spring-boot-starter-biz-dict/pom.xml index 2d726dd..008b102 100644 --- a/yshop-framework/yshop-spring-boot-starter-biz-dict/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-biz-dict/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 字典类型、数据 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-biz-error-code/pom.xml b/yshop-framework/yshop-spring-boot-starter-biz-error-code/pom.xml index 8bab301..5dbb4d1 100644 --- a/yshop-framework/yshop-spring-boot-starter-biz-error-code/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-biz-error-code/pom.xml @@ -18,7 +18,7 @@ 2. 自动更新:管理员在管理后台修数据库中的 ErrorCode 错误码时,项目自动从 system-server 服务加载最新的 ErrorCode 错误码; 3. 自动写入:项目启动时,将项目本地的错误码写到 system-server 服务中,方便管理员在管理后台编辑; - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-biz-ip/pom.xml b/yshop-framework/yshop-spring-boot-starter-biz-ip/pom.xml index 0d55aca..c907f92 100644 --- a/yshop-framework/yshop-spring-boot-starter-biz-ip/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-biz-ip/pom.xml @@ -18,7 +18,7 @@ 2. 城市功能:查询城市编码对应的城市信息 基于 https://github.com/modood/Administrative-divisions-of-China 实现 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-biz-operatelog/pom.xml b/yshop-framework/yshop-spring-boot-starter-biz-operatelog/pom.xml index 17d6282..791af79 100644 --- a/yshop-framework/yshop-spring-boot-starter-biz-operatelog/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-biz-operatelog/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 操作日志 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/pom.xml b/yshop-framework/yshop-spring-boot-starter-biz-pay/pom.xml deleted file mode 100644 index 56c8b9b..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/pom.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - yshop-framework - co.yixiang.boot - ${revision} - - 4.0.0 - - yshop-spring-boot-starter-biz-pay - ${project.artifactId} - 支付拓展,接入国内多个支付渠道 - 1. 支付宝,基于官方 SDK 接入 - 2. 微信支付,基于 weixin-java-pay 接入 - - - - - co.yixiang.boot - yshop-common - - - - - org.springframework.boot - spring-boot-starter - - - - - org.springframework.boot - spring-boot-starter-validation - - - - org.slf4j - slf4j-api - - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-core - - - - - com.alipay.sdk - alipay-sdk-java - 4.35.79.ALL - - - org.bouncycastle - bcprov-jdk15on - - - - - com.github.binarywang - weixin-java-pay - 4.4.0 - - - - - - co.yixiang.boot - yshop-spring-boot-starter-test - test - - - - diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/config/PayProperties.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/config/PayProperties.java deleted file mode 100644 index 266ce32..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/config/PayProperties.java +++ /dev/null @@ -1,35 +0,0 @@ -package co.yixiang.yshop.framework.pay.config; - -import lombok.Data; -import org.hibernate.validator.constraints.URL; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.validation.annotation.Validated; - -import javax.validation.constraints.NotEmpty; - -@ConfigurationProperties(prefix = "yshop.pay") -@Validated -@Data -public class PayProperties { - - /** - * 回调地址 - * - * 实际上,对应的 PayNotifyController 的 notifyCallback 方法的 URL - * - * 注意,支付渠道统一回调到 payNotifyUrl 地址,由支付模块统一处理;然后,自己的支付模块,在回调 PayAppDO.payNotifyUrl 地址 - */ - @NotEmpty(message = "回调地址不能为空") - @URL(message = "回调地址的格式必须是 URL") - private String callbackUrl; - - /** - * 回跳地址 - * - * 实际上,对应的 PayNotifyController 的 returnCallback 方法的 URL - */ - @URL(message = "回跳地址的格式必须是 URL") - @NotEmpty(message = "回跳地址不能为空") - private String returnUrl; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/config/YshopPayAutoConfiguration.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/config/YshopPayAutoConfiguration.java deleted file mode 100644 index 8b2d0c0..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/config/YshopPayAutoConfiguration.java +++ /dev/null @@ -1,23 +0,0 @@ -package co.yixiang.yshop.framework.pay.config; - -import co.yixiang.yshop.framework.pay.core.client.PayClientFactory; -import co.yixiang.yshop.framework.pay.core.client.impl.PayClientFactoryImpl; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; - -/** - * 支付配置类 - * - * @author yshop - */ -@AutoConfiguration -@EnableConfigurationProperties(PayProperties.class) -public class YshopPayAutoConfiguration { - - @Bean - public PayClientFactory payClientFactory() { - return new PayClientFactoryImpl(); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/PayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/PayClient.java deleted file mode 100644 index 0ed7b66..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/PayClient.java +++ /dev/null @@ -1,52 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client; - -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayNotifyReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO; - -/** - * 支付客户端,用于对接各支付渠道的 SDK,实现发起支付、退款等功能 - * - * @author yshop - */ -public interface PayClient { - - /** - * 获得渠道编号 - * - * @return 渠道编号 - */ - Long getId(); - - /** - * 调用支付渠道,统一下单 - * - * @param reqDTO 下单信息 - * @return 各支付渠道的返回结果 - */ - PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO); - - /** - * 调用支付渠道,进行退款 - * @param reqDTO 统一退款请求信息 - * @return 各支付渠道的统一返回结果 - */ - PayRefundUnifiedRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO); - - /** - * 解析回调数据 - * - * @param rawNotify 通知内容 - * @return 回调对象 - * 1. {@link PayRefundNotifyRespDTO} 退款通知 - * 2. {@link PayOrderNotifyRespDTO} 支付通知 - */ - default Object parseNotify(PayNotifyReqDTO rawNotify) { - throw new UnsupportedOperationException("未实现 parseNotify 方法!"); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/PayClientConfig.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/PayClientConfig.java deleted file mode 100644 index 693ce63..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/PayClientConfig.java +++ /dev/null @@ -1,42 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client; - -import com.fasterxml.jackson.annotation.JsonTypeInfo; - -import javax.validation.ConstraintViolation; -import javax.validation.ConstraintViolationException; -import javax.validation.Validator; -import java.util.Set; - -/** - * 支付客户端的配置,本质是支付渠道的配置 - * 每个不同的渠道,需要不同的配置,通过子类来定义 - * - * @author yshop - */ -@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) -// @JsonTypeInfo 注解的作用,Jackson 多态 -// 1. 序列化到时数据库时,增加 @class 属性。 -// 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型 -public interface PayClientConfig { - - /** - * 配置验证参数是 - * - * @param validator 校验对象 - * @return 配置好的验证参数 - */ - Set> verifyParam(Validator validator); - - // TODO @aquan:貌似抽象一个 validation group 就好了! - /** - * 参数校验 - * - * @param validator 校验对象 - */ - default void validate(Validator validator) { - Set> violations = verifyParam(validator); - if (!violations.isEmpty()) { - throw new ConstraintViolationException(violations); - } - } -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/PayClientFactory.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/PayClientFactory.java deleted file mode 100644 index 3ae36de..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/PayClientFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client; - -/** - * 支付客户端的工厂接口 - * - * @author yshop - */ -public interface PayClientFactory { - - /** - * 获得支付客户端 - * - * @param channelId 渠道编号 - * @return 支付客户端 - */ - PayClient getPayClient(Long channelId); - - /** - * 创建支付客户端 - * - * @param channelId 渠道编号 - * @param channelCode 渠道编码 - * @param config 支付配置 - */ - void createOrUpdatePayClient(Long channelId, String channelCode, - Config config); - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/notify/PayNotifyReqDTO.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/notify/PayNotifyReqDTO.java deleted file mode 100644 index fa271c8..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/notify/PayNotifyReqDTO.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.dto.notify; - -import lombok.Builder; -import lombok.Data; -import lombok.ToString; - -import java.util.Map; - - -/** - * 支付订单,退款订单回调,渠道的统一通知请求数据 - */ -@Data -@ToString -@Builder -public class PayNotifyReqDTO { - - - /** - * HTTP 回调接口的 request body - */ - private String body; - - /** - * HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数 - */ - private Map params; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/notify/PayOrderNotifyRespDTO.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/notify/PayOrderNotifyRespDTO.java deleted file mode 100644 index 43706ed..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/notify/PayOrderNotifyRespDTO.java +++ /dev/null @@ -1,48 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.dto.notify; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; - -/** - * 支付通知 Response DTO - * - * @author yshop - */ -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class PayOrderNotifyRespDTO { - - /** - * 支付订单号(支付模块的) - */ - private String orderExtensionNo; - /** - * 支付渠道编号 - */ - private String channelOrderNo; - /** - * 支付渠道用户编号 - */ - private String channelUserId; - /** - * 支付成功时间 - */ - private LocalDateTime successTime; - - /** - * TODO @jason 结合其他的渠道定义成枚举, - * - * alipay - * TRADE_CLOSED,未付款交易超时关闭,或支付完成后全额退款。 - * TRADE_SUCCESS, 交易支付成功 - * TRADE_FINISHED 交易结束,不可退款。 - */ - private String tradeStatus; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/notify/PayRefundNotifyRespDTO.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/notify/PayRefundNotifyRespDTO.java deleted file mode 100644 index 5e4c468..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/notify/PayRefundNotifyRespDTO.java +++ /dev/null @@ -1,58 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.dto.notify; - -import co.yixiang.yshop.framework.pay.core.enums.PayNotifyRefundStatusEnum; -import lombok.Builder; -import lombok.Data; -import lombok.ToString; - -import java.time.LocalDateTime; - -/** - * 从渠道返回数据中解析得到的支付退款通知的Notify DTO - * - * @author jason - */ -@Data -@ToString -@Builder -public class PayRefundNotifyRespDTO { - - /** - * 支付渠道编号 - */ - private String channelOrderNo; - - /** - * 交易订单号,根据规则生成 - * 调用支付渠道时,使用该字段作为对接的订单号。 - * 1. 调用微信支付 https://api.mch.weixin.qq.com/pay/unifiedorder 时,使用该字段作为 out_trade_no - * 2. 调用支付宝 https://opendocs.alipay.com/apis 时,使用该字段作为 out_trade_no - * 这里对应 pay_extension 里面的 no - * 例如说,P202110132239124200055 - */ - private String tradeNo; - - /** - * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no - * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_request_no - * 退款请求号。 - * 标识一次退款请求,需要保证在交易号下唯一,如需部分退款,则此参数必传。 - * 注:针对同一次退款请求,如果调用接口失败或异常了,重试时需要保证退款请求号不能变更, - * 防止该笔交易重复退款。支付宝会保证同样的退款请求号多次请求只会退一次。 - * 退款单请求号,根据规则生成 - * - * 例如说,RR202109181134287570000 - */ - private String reqNo; - - /** - * 退款是否成功 - */ - private PayNotifyRefundStatusEnum status; - - /** - * 退款成功时间 - */ - private LocalDateTime refundSuccessTime; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/order/PayOrderUnifiedReqDTO.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/order/PayOrderUnifiedReqDTO.java deleted file mode 100644 index 4895d36..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/order/PayOrderUnifiedReqDTO.java +++ /dev/null @@ -1,92 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.dto.order; - -import co.yixiang.yshop.framework.pay.core.enums.PayDisplayModeEnum; -import lombok.Data; -import org.hibernate.validator.constraints.Length; -import org.hibernate.validator.constraints.URL; - -import javax.validation.constraints.DecimalMin; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.awt.*; -import java.time.LocalDateTime; -import java.util.Map; - -/** - * 统一下单 Request DTO - * - * @author yshop - */ -@Data -public class PayOrderUnifiedReqDTO { - - /** - * 用户 IP - */ - @NotEmpty(message = "用户 IP 不能为空") - private String userIp; - - // ========== 商户相关字段 ========== - - /** - * 商户订单编号 - */ - @NotEmpty(message = "商户订单编号不能为空") - private String merchantOrderId; - /** - * 商品标题 - */ - @NotEmpty(message = "商品标题不能为空") - @Length(max = 32, message = "商品标题不能超过 32") - private String subject; - /** - * 商品描述信息 - */ - @NotEmpty(message = "商品描述信息不能为空") - @Length(max = 128, message = "商品描述信息长度不能超过128") - private String body; - /** - * 支付结果的 notify 回调地址 - */ - @NotEmpty(message = "支付结果的回调地址不能为空") - @URL(message = "支付结果的 notify 回调地址必须是 URL 格式") - private String notifyUrl; - /** - * 支付结果的 return 回调地址 - */ - @URL(message = "支付结果的 return 回调地址必须是 URL 格式") - private String returnUrl; - - // ========== 订单相关字段 ========== - - /** - * 支付金额,单位:分 - */ - @NotNull(message = "支付金额不能为空") - @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零") - private Integer amount; - - /** - * 支付过期时间 - */ - @NotNull(message = "支付过期时间不能为空") - private LocalDateTime expireTime; - - // ========== 拓展参数 ========== - /** - * 支付渠道的额外参数 - * - * 例如说,微信公众号需要传递 openid 参数 - */ - private Map channelExtras; - - /** - * 展示模式 - * - * 如果不传递,则每个支付渠道使用默认的方式 - * - * 枚举 {@link PayDisplayModeEnum} - */ - private String displayMode; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/order/PayOrderUnifiedRespDTO.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/order/PayOrderUnifiedRespDTO.java deleted file mode 100644 index e050553..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/order/PayOrderUnifiedRespDTO.java +++ /dev/null @@ -1,23 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.dto.order; - -import lombok.AllArgsConstructor; -import lombok.Data; - -/** - * 统一下单 Response DTO - * - * @author yshop - */ -@Data -public class PayOrderUnifiedRespDTO { - - /** - * 展示模式 - */ - private String displayMode; - /** - * 展示内容 - */ - private String displayContent; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java deleted file mode 100644 index 8159de5..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java +++ /dev/null @@ -1,74 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.dto.refund; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; -import org.hibernate.validator.constraints.URL; - -import javax.validation.constraints.DecimalMin; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -/** - * 统一 退款 Request DTO - * - * @author jason - */ -@Accessors(chain = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -@Data -public class PayRefundUnifiedReqDTO { - - /** - * 用户 IP - */ - private String userIp; - - // TODO @jason:这个是否为非必传字段呀,只需要传递 payTradeNo 字段即可。尽可能精简 - /** - * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 transaction_id - * https://opendocs.alipay.com/apis alipay.trade.refund 中的 trade_no - * 渠道订单号 - */ - private String channelOrderNo; - - /** - * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_trade_no - * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no - * 支付交易号 {PayOrderExtensionDO no字段} 和 渠道订单号 不能同时为空 - */ - private String payTradeNo; - - /** - * https://api.mch.weixin.qq.com/v3/refund/domestic/refunds 中的 out_refund_no - * https://opendocs.alipay.com/apis alipay.trade.refund 中的 out_trade_no - * 退款请求单号 同一退款请求单号多次请求只退一笔。 - * 使用 商户的退款单号。{PayRefundDO 字段 merchantRefundNo} - */ - @NotEmpty(message = "退款请求单号") - private String merchantRefundId; - - /** - * 退款原因 - */ - @NotEmpty(message = "退款原因不能为空") - private String reason; - - /** - * 退款金额,单位:分 - */ - @NotNull(message = "退款金额不能为空") - @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零") - private Integer amount; - - /** - * 退款结果 notify 回调地址, 支付宝退款不需要回调地址, 微信需要 - */ - @URL(message = "支付结果的 notify 回调地址必须是 URL 格式") - private String notifyUrl; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/refund/PayRefundUnifiedRespDTO.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/refund/PayRefundUnifiedRespDTO.java deleted file mode 100644 index bfefd5a..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/dto/refund/PayRefundUnifiedRespDTO.java +++ /dev/null @@ -1,25 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.dto.refund; - -import co.yixiang.yshop.framework.pay.core.enums.PayChannelRefundRespEnum; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; -/** - * 统一退款 Response DTO - * - * @author jason - */ -@Accessors(chain = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -@Data -public class PayRefundUnifiedRespDTO { - - /** - * 渠道退款单编号 - */ - private String channelRefundId; -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/AbstractPayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/AbstractPayClient.java deleted file mode 100644 index 419f892..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/AbstractPayClient.java +++ /dev/null @@ -1,141 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl; - -import cn.hutool.core.date.LocalDateTimeUtil; -import co.yixiang.yshop.framework.pay.core.client.PayClient; -import co.yixiang.yshop.framework.pay.core.client.PayClientConfig; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO; -import com.alipay.api.AlipayResponse;import lombok.extern.slf4j.Slf4j; - -import javax.validation.Validation; -import java.time.LocalDateTime; - -import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER; -import static cn.hutool.core.date.DatePattern.NORM_DATETIME_MS_FORMATTER; -import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception; -import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception0; -import static co.yixiang.yshop.framework.common.util.json.JsonUtils.toJsonString; -import static co.yixiang.yshop.framework.pay.core.enums.PayFrameworkErrorCodeConstants.PAY_EXCEPTION; - -/** - * 支付客户端的抽象类,提供模板方法,减少子类的冗余代码 - * - * @author yshop - */ -@Slf4j -public abstract class AbstractPayClient implements PayClient { - - /** - * 渠道编号 - */ - private final Long channelId; - /** - * 渠道编码 - */ - private final String channelCode; - /** - * 支付配置 - */ - protected Config config; - - public AbstractPayClient(Long channelId, String channelCode, Config config) { - this.channelId = channelId; - this.channelCode = channelCode; - this.config = config; - } - - /** - * 初始化 - */ - public final void init() { - doInit(); - log.info("[init][配置({}) 初始化完成]", config); - } - - /** - * 自定义初始化 - */ - protected abstract void doInit(); - - public final void refresh(Config config) { - // 判断是否更新 - if (config.equals(this.config)) { - return; - } - log.info("[refresh][配置({})发生变化,重新初始化]", config); - this.config = config; - // 初始化 - this.init(); - } - - @Override - public Long getId() { - return channelId; - } - - @Override - public final PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { - Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO); - // 执行短信发送 - PayOrderUnifiedRespDTO result; - try { - result = doUnifiedOrder(reqDTO); - } catch (Throwable ex) { - // 打印异常日志 - log.error("[unifiedOrder][request({}) 发起支付失败]", toJsonString(reqDTO), ex); - throw buildException(ex); - } - return result; - } - - protected abstract PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) - throws Throwable; - - @Override - public PayRefundUnifiedRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) { - PayRefundUnifiedRespDTO resp; - try { - resp = doUnifiedRefund(reqDTO); - } catch (Throwable ex) { - // 记录异常日志 - log.error("[unifiedRefund][request({}) 发起退款失败]", toJsonString(reqDTO), ex); - throw buildException(ex); - } - return resp; - } - - protected abstract PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable; - - // ========== 各种工具方法 ========== - - private RuntimeException buildException(Throwable ex) { - if (ex instanceof RuntimeException) { - return (RuntimeException) ex; - } - throw new RuntimeException(ex); - } - - protected void validateSuccess(AlipayResponse response) { - if (response.isSuccess()) { - return; - } - throw exception0(PAY_EXCEPTION.getCode(), response.getSubMsg()); - } - - protected String formatAmount(Integer amount) { - return String.valueOf(amount / 100.0); - } - - protected String formatTime(LocalDateTime time) { - // "yyyy-MM-dd HH:mm:ss" - return LocalDateTimeUtil.format(time, NORM_DATETIME_FORMATTER); - } - - protected LocalDateTime parseTime(String str) { - // "yyyy-MM-dd HH:mm:ss" - return LocalDateTimeUtil.parse(str, NORM_DATETIME_FORMATTER); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/PayClientFactoryImpl.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/PayClientFactoryImpl.java deleted file mode 100644 index 169bb68..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/PayClientFactoryImpl.java +++ /dev/null @@ -1,78 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl; - -import cn.hutool.core.lang.Assert; -import co.yixiang.yshop.framework.pay.core.client.PayClient; -import co.yixiang.yshop.framework.pay.core.client.PayClientConfig; -import co.yixiang.yshop.framework.pay.core.client.PayClientFactory; -import co.yixiang.yshop.framework.pay.core.client.impl.alipay.*; -import co.yixiang.yshop.framework.pay.core.client.impl.wx.WXLitePayClient; -import co.yixiang.yshop.framework.pay.core.client.impl.wx.WXNativePayClient; -import co.yixiang.yshop.framework.pay.core.client.impl.wx.WXPayClientConfig; -import co.yixiang.yshop.framework.pay.core.client.impl.wx.WXPubPayClient; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import lombok.extern.slf4j.Slf4j; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * 支付客户端的工厂实现类 - * - * @author yshop - */ -@Slf4j -public class PayClientFactoryImpl implements PayClientFactory { - - /** - * 支付客户端 Map - * key:渠道编号 - */ - private final ConcurrentMap> clients = new ConcurrentHashMap<>(); - - @Override - public PayClient getPayClient(Long channelId) { - AbstractPayClient client = clients.get(channelId); - if (client == null) { - log.error("[getPayClient][渠道编号({}) 找不到客户端]", channelId); - } - return client; - } - - @Override - @SuppressWarnings("unchecked") - public void createOrUpdatePayClient(Long channelId, String channelCode, - Config config) { - AbstractPayClient client = (AbstractPayClient) clients.get(channelId); - if (client == null) { - client = this.createPayClient(channelId, channelCode, config); - client.init(); - clients.put(client.getId(), client); - } else { - client.refresh(config); - } - } - - @SuppressWarnings("unchecked") - private AbstractPayClient createPayClient( - Long channelId, String channelCode, Config config) { - PayChannelEnum channelEnum = PayChannelEnum.getByCode(channelCode); - Assert.notNull(channelEnum, String.format("支付渠道(%s) 为空", channelEnum)); - // 创建客户端 - // TODO @yshop WX_LITE WX_APP 如果不添加在 项目启动的时候去初始化会报错无法启动。所以我手动加了两个,具体需要你来配 - switch (channelEnum) { - case WX_PUB: return (AbstractPayClient) new WXPubPayClient(channelId, (WXPayClientConfig) config); - case WX_LITE: return (AbstractPayClient) new WXLitePayClient(channelId, (WXPayClientConfig) config); //微信小程序请求支付 - case WX_APP: return (AbstractPayClient) new WXPubPayClient(channelId, (WXPayClientConfig) config); - case WX_NATIVE: return (AbstractPayClient) new WXNativePayClient(channelId, (WXPayClientConfig) config); - case ALIPAY_WAP: return (AbstractPayClient) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config); - case ALIPAY_QR: return (AbstractPayClient) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); - case ALIPAY_APP: return (AbstractPayClient) new AlipayAppPayClient(channelId, (AlipayPayClientConfig) config); - case ALIPAY_PC: return (AbstractPayClient) new AlipayPcPayClient(channelId, (AlipayPayClientConfig) config); - case ALIPAY_BAR: return (AbstractPayClient) new AlipayBarPayClient(channelId, (AlipayPayClientConfig) config); - } - // 创建失败,错误日志 + 抛出异常 - log.error("[createPayClient][配置({}) 找不到合适的客户端实现]", config); - throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", config)); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AbstractAlipayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AbstractAlipayClient.java deleted file mode 100644 index 9867f9d..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AbstractAlipayClient.java +++ /dev/null @@ -1,115 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.alipay; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.http.HttpUtil; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayNotifyReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.client.impl.AbstractPayClient; -import co.yixiang.yshop.framework.pay.core.enums.PayNotifyRefundStatusEnum; -import com.alipay.api.AlipayApiException; -import com.alipay.api.AlipayConfig; -import com.alipay.api.DefaultAlipayClient; -import com.alipay.api.domain.AlipayTradeRefundModel; -import com.alipay.api.internal.util.AlipaySignature; -import com.alipay.api.request.AlipayTradeRefundRequest; -import com.alipay.api.response.AlipayTradeRefundResponse; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; - -import java.nio.charset.StandardCharsets; -import java.util.Map; - -import static co.yixiang.yshop.framework.common.util.json.JsonUtils.toJsonString; - -/** - * 支付宝抽象类, 实现支付宝统一的接口。如退款 - * - * @author jason - */ -@Slf4j -public abstract class AbstractAlipayClient extends AbstractPayClient { - - protected DefaultAlipayClient client; - - public AbstractAlipayClient(Long channelId, String channelCode, AlipayPayClientConfig config) { - super(channelId, channelCode, config); - } - - @Override - @SneakyThrows - protected void doInit() { - AlipayConfig alipayConfig = new AlipayConfig(); - BeanUtil.copyProperties(config, alipayConfig, false); - this.client = new DefaultAlipayClient(alipayConfig); - } - - /** - * 支付宝统一的退款接口 alipay.trade.refund - * @param reqDTO 退款请求 request DTO - * @return 退款请求 Response - */ - @Override - protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { - AlipayTradeRefundModel model=new AlipayTradeRefundModel(); - model.setTradeNo(reqDTO.getChannelOrderNo()); - model.setOutTradeNo(reqDTO.getPayTradeNo()); - - model.setOutRequestNo(reqDTO.getMerchantRefundId()); - model.setRefundAmount(formatAmount(reqDTO.getAmount()).toString()); - model.setRefundReason(reqDTO.getReason()); - - AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest(); - refundRequest.setBizModel(model); - refundRequest.setNotifyUrl(reqDTO.getNotifyUrl()); - refundRequest.setReturnUrl(reqDTO.getNotifyUrl()); - try { - AlipayTradeRefundResponse response = client.execute(refundRequest); - log.info("[doUnifiedRefund][response({}) 发起退款 渠道返回", toJsonString(response)); - if (response.isSuccess()) { - //退款导致触发的异步通知是发送到支付接口中设置的notify_url - //支付宝不返回退款单号,设置为空 - PayRefundUnifiedRespDTO respDTO = new PayRefundUnifiedRespDTO(); - respDTO.setChannelRefundId(""); -// return PayCommonResult.build(response.getCode(), response.getMsg(), respDTO, codeMapping); TODO - return null; - } - // 失败。需要抛出异常 -// return PayCommonResult.build(response.getCode(), response.getMsg(), null, codeMapping); TODO - return null; - } catch (AlipayApiException e) { - // TODO 记录异常日志 - log.error("[doUnifiedRefund][request({}) 发起退款失败,网络读超时,退款状态未知]", toJsonString(reqDTO), e); -// return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping); TODO - return null; - } - } - - @Override - @SneakyThrows - public Object parseNotify(PayNotifyReqDTO rawNotify) { - // 1. 校验回调数据 - String body = rawNotify.getBody(); - Map params = rawNotify.getParams(); - Map bodyObj = HttpUtil.decodeParamMap(body, StandardCharsets.UTF_8); - AlipaySignature.rsaCheckV1(bodyObj, config.getAlipayPublicKey(), - StandardCharsets.UTF_8.name(), "RSA2"); - - // 2.1 退款的情况 - if (bodyObj.containsKey("refund_fee")) { - return PayRefundNotifyRespDTO.builder().channelOrderNo(bodyObj.get("trade_no")) - .tradeNo(bodyObj.get("out_trade_no")).reqNo(bodyObj.get("out_biz_no")) - .status(PayNotifyRefundStatusEnum.SUCCESS) - .refundSuccessTime(parseTime(params.get("gmt_refund"))) - .build(); - } - // 2.2 支付的情况 - return PayOrderNotifyRespDTO.builder().orderExtensionNo(bodyObj.get("out_trade_no")) - .channelOrderNo(bodyObj.get("trade_no")).channelUserId(bodyObj.get("seller_id")) - .tradeStatus(bodyObj.get("trade_status")).successTime(parseTime(params.get("notify_time"))) - .build(); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java deleted file mode 100644 index dfcde9b..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayAppPayClient.java +++ /dev/null @@ -1,57 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.alipay; - -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import co.yixiang.yshop.framework.pay.core.enums.PayDisplayModeEnum; -import com.alipay.api.AlipayApiException; -import com.alipay.api.domain.AlipayTradeAppPayModel; -import com.alipay.api.request.AlipayTradeAppPayRequest; -import com.alipay.api.response.AlipayTradeAppPayResponse; -import lombok.extern.slf4j.Slf4j; - -/** - * 支付宝【App 支付】的 PayClient 实现类 - * - * 文档:App 支付 - * - * // TODO yshop:未详细测试,因为手头没 App - * - * @author yshop - */ -@Slf4j -public class AlipayAppPayClient extends AbstractAlipayClient { - - public AlipayAppPayClient(Long channelId, AlipayPayClientConfig config) { - super(channelId, PayChannelEnum.ALIPAY_APP.getCode(), config); - } - - @Override - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { - // 1.1 构建 AlipayTradeAppPayModel 请求 - AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); - // ① 通用的参数 - model.setOutTradeNo(reqDTO.getMerchantOrderId()); - model.setSubject(reqDTO.getSubject()); - model.setBody(reqDTO.getBody()); - model.setTotalAmount(formatAmount(reqDTO.getAmount())); - model.setProductCode(" QUICK_MSECURITY_PAY"); // 销售产品码:无线快捷支付产品 - // ② 个性化的参数【无】 - // ③ 支付宝扫码支付只有一种展示 - String displayMode = PayDisplayModeEnum.APP.getMode(); - - // 1.2 构建 AlipayTradePrecreateRequest 请求 - AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); - request.setBizModel(model); - request.setNotifyUrl(reqDTO.getNotifyUrl()); - request.setReturnUrl(reqDTO.getReturnUrl()); - - // 2.1 执行请求 - AlipayTradeAppPayResponse response = client.execute(request); - // 2.2 处理结果 - validateSuccess(response); - return new PayOrderUnifiedRespDTO() - .setDisplayMode(displayMode).setDisplayContent(""); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java deleted file mode 100644 index 8b33ef6..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayBarPayClient.java +++ /dev/null @@ -1,66 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.alipay; - -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import co.yixiang.yshop.framework.pay.core.enums.PayDisplayModeEnum; -import com.alipay.api.AlipayApiException; -import com.alipay.api.domain.AlipayTradePayModel; -import com.alipay.api.request.AlipayTradePayRequest; -import com.alipay.api.response.AlipayTradePayResponse; -import lombok.extern.slf4j.Slf4j; - -import static co.yixiang.yshop.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; -import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception; -import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception0; - -/** - * 支付宝【条码支付】的 PayClient 实现类 - * - * 文档:当面付 - * - * @author yshop - */ -@Slf4j -public class AlipayBarPayClient extends AbstractAlipayClient { - - public AlipayBarPayClient(Long channelId, AlipayPayClientConfig config) { - super(channelId, PayChannelEnum.ALIPAY_BAR.getCode(), config); - } - - @Override - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { - String authCode = MapUtil.getStr(reqDTO.getChannelExtras(), "auth_code"); - if (StrUtil.isEmpty(authCode)) { - throw exception0(BAD_REQUEST.getCode(), "条形码不能为空"); - } - - // 1.1 构建 AlipayTradePayModel 请求 - AlipayTradePayModel model = new AlipayTradePayModel(); - // ① 通用的参数 - model.setOutTradeNo(reqDTO.getMerchantOrderId()); - model.setSubject(reqDTO.getSubject()); - model.setBody(reqDTO.getBody()); - model.setTotalAmount(formatAmount(reqDTO.getAmount())); - model.setScene("bar_code"); // 当面付条码支付场景 - // ② 个性化的参数 - model.setAuthCode(authCode); - // ③ 支付宝条码支付只有一种展示 - String displayMode = PayDisplayModeEnum.BAR_CODE.getMode(); - - // 1.2 构建 AlipayTradePayRequest 请求 - AlipayTradePayRequest request = new AlipayTradePayRequest(); - request.setBizModel(model); - request.setNotifyUrl(reqDTO.getNotifyUrl()); - request.setReturnUrl(reqDTO.getReturnUrl()); - - // 2.1 执行请求 - AlipayTradePayResponse response = client.execute(request); - // 2.2 处理结果 - validateSuccess(response); - return new PayOrderUnifiedRespDTO() - .setDisplayMode(displayMode).setDisplayContent(""); - } -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayPayClientConfig.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayPayClientConfig.java deleted file mode 100644 index 14691cc..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayPayClientConfig.java +++ /dev/null @@ -1,117 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.alipay; - -import co.yixiang.yshop.framework.pay.core.client.PayClientConfig; -import lombok.Data; - -import javax.validation.ConstraintViolation; -import javax.validation.Validator; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.util.Set; - -// TODO yshop:参数校验 - -/** - * 支付宝的 PayClientConfig 实现类 - * 属性主要来自 {@link com.alipay.api.AlipayConfig} 的必要属性 - * - * @author yshop - */ -@Data -public class AlipayPayClientConfig implements PayClientConfig { - - /** - * 网关地址 - 线上 - */ - public static final String SERVER_URL_PROD = "https://openapi.alipay.com/gateway.do"; - /** - * 网关地址 - 沙箱 - */ - public static final String SERVER_URL_SANDBOX = "https://openapi.alipaydev.com/gateway.do"; - - /** - * 公钥类型 - 公钥模式 - */ - public static final Integer MODE_PUBLIC_KEY = 1; - /** - * 公钥类型 - 证书模式 - */ - public static final Integer MODE_CERTIFICATE = 2; - - /** - * 签名算法类型 - RSA - */ - public static final String SIGN_TYPE_DEFAULT = "RSA2"; - - /** - * 网关地址 - * 1. {@link #SERVER_URL_PROD} - * 2. {@link #SERVER_URL_SANDBOX} - */ - @NotBlank(message = "网关地址不能为空", groups = {ModePublicKey.class, ModeCertificate.class}) - private String serverUrl; - - /** - * 开放平台上创建的应用的 ID - */ - @NotBlank(message = "开放平台上创建的应用的 ID不能为空", groups = {ModePublicKey.class, ModeCertificate.class}) - private String appId; - - /** - * 签名算法类型,推荐:RSA2 - *

- * {@link #SIGN_TYPE_DEFAULT} - */ - @NotBlank(message = "签名算法类型不能为空", groups = {ModePublicKey.class, ModeCertificate.class}) - private String signType; - - /** - * 公钥类型 - * 1. {@link #MODE_PUBLIC_KEY} 情况,privateKey + alipayPublicKey - * 2. {@link #MODE_CERTIFICATE} 情况,appCertContent + alipayPublicCertContent + rootCertContent - */ - @NotNull(message = "公钥类型不能为空", groups = {ModePublicKey.class, ModeCertificate.class}) - private Integer mode; - - // ========== 公钥模式 ========== - /** - * 商户私钥 - */ - @NotBlank(message = "商户私钥不能为空", groups = {ModePublicKey.class}) - private String privateKey; - - /** - * 支付宝公钥字符串 - */ - @NotBlank(message = "支付宝公钥字符串不能为空", groups = {ModePublicKey.class}) - private String alipayPublicKey; - - // ========== 证书模式 ========== - /** - * 指定商户公钥应用证书内容字符串 - */ - @NotBlank(message = "指定商户公钥应用证书内容不能为空", groups = {ModeCertificate.class}) - private String appCertContent; - /** - * 指定支付宝公钥证书内容字符串 - */ - @NotBlank(message = "指定支付宝公钥证书内容不能为空", groups = {ModeCertificate.class}) - private String alipayPublicCertContent; - /** - * 指定根证书内容字符串 - */ - @NotBlank(message = "指定根证书内容字符串不能为空", groups = {ModeCertificate.class}) - private String rootCertContent; - - public interface ModePublicKey { - } - - public interface ModeCertificate { - } - - @Override - public Set> verifyParam(Validator validator) { - return validator.validate(this, - MODE_PUBLIC_KEY.equals(this.getMode()) ? ModePublicKey.class : ModeCertificate.class); - } -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java deleted file mode 100644 index 718148f..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayPcPayClient.java +++ /dev/null @@ -1,91 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.alipay; - -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.http.Method; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import co.yixiang.yshop.framework.pay.core.enums.PayDisplayModeEnum; -import com.alipay.api.AlipayApiException; -import com.alipay.api.domain.AlipayTradePagePayModel; -import com.alipay.api.request.AlipayTradePagePayRequest; -import com.alipay.api.response.AlipayTradePagePayResponse; -import lombok.extern.slf4j.Slf4j; - -import java.util.Objects; - -/** - * 支付宝【PC 网站】的 PayClient 实现类 - * - * 文档:电脑网站支付 - * - * @author XGD - */ -@Slf4j -public class AlipayPcPayClient extends AbstractAlipayClient { - - public AlipayPcPayClient(Long channelId, AlipayPayClientConfig config) { - super(channelId, PayChannelEnum.ALIPAY_PC.getCode(), config); - } - - @Override - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { - // 1.1 构建 AlipayTradePagePayModel 请求 - AlipayTradePagePayModel model = new AlipayTradePagePayModel(); - // ① 通用的参数 - model.setOutTradeNo(reqDTO.getMerchantOrderId()); - model.setSubject(reqDTO.getSubject()); - model.setBody(reqDTO.getBody()); - model.setTotalAmount(formatAmount(reqDTO.getAmount())); - model.setTimeExpire(formatTime(reqDTO.getExpireTime())); - model.setProductCode("FAST_INSTANT_TRADE_PAY"); // 销售产品码. 目前 PC 支付场景下仅支持 FAST_INSTANT_TRADE_PAY - // ② 个性化的参数 - // 参考 https://www.pingxx.com/api/支付渠道 extra 参数说明.html 的 alipay_pc_direct 部分 - model.setQrPayMode(MapUtil.getStr(reqDTO.getChannelExtras(), "qr_pay_mode")); - model.setQrcodeWidth(MapUtil.getLong(reqDTO.getChannelExtras(), "qr_code_width")); - // ③ 支付宝 PC 支付有多种展示模式,因此这里需要计算 - String displayMode = getDisplayMode(reqDTO.getDisplayMode(), model.getQrPayMode()); - - // 1.2 构建 AlipayTradePagePayRequest 请求 - AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); - request.setBizModel(model); - request.setNotifyUrl(reqDTO.getNotifyUrl()); - request.setReturnUrl(reqDTO.getReturnUrl()); - - // 2.1 执行请求 - AlipayTradePagePayResponse response; - if (Objects.equals(displayMode, PayDisplayModeEnum.FORM.getMode())) { - response = client.pageExecute(request, Method.POST.name()); // 需要特殊使用 POST 请求 - } else { - response = client.pageExecute(request, Method.GET.name()); - } - - // 2.2 处理结果 - validateSuccess(response); - return new PayOrderUnifiedRespDTO().setDisplayMode(displayMode) - .setDisplayContent(response.getBody()); - } - - /** - * 获得最终的支付 UI 展示模式 - * - * @param displayMode 前端传递的 UI 展示模式 - * @param qrPayMode 前端传递的二维码模式 - * @return 最终的支付 UI 展示模式 - */ - private String getDisplayMode(String displayMode, String qrPayMode) { - // 1.1 支付宝二维码的前置模式 - if (StrUtil.equalsAny(qrPayMode, "0", "1", "3", "4")) { - return PayDisplayModeEnum.IFRAME.getMode(); - } - // 1.2 支付宝二维码的跳转模式 - if (StrUtil.equals(qrPayMode, "2")) { - return PayDisplayModeEnum.URL.getMode(); - } - // 2. 前端传递了 UI 展示模式 - return displayMode != null ? displayMode : - PayDisplayModeEnum.URL.getMode(); // 模式使用 URL 跳转 - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java deleted file mode 100644 index 2edf2f9..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java +++ /dev/null @@ -1,54 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.alipay; - -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import co.yixiang.yshop.framework.pay.core.enums.PayDisplayModeEnum; -import com.alipay.api.AlipayApiException; -import com.alipay.api.domain.AlipayTradePrecreateModel; -import com.alipay.api.request.AlipayTradePrecreateRequest; -import com.alipay.api.response.AlipayTradePrecreateResponse; -import lombok.extern.slf4j.Slf4j; - -/** - * 支付宝【扫码支付】的 PayClient 实现类 - * - * 文档:扫码支付 - * - * @author yshop - */ -@Slf4j -public class AlipayQrPayClient extends AbstractAlipayClient { - - public AlipayQrPayClient(Long channelId, AlipayPayClientConfig config) { - super(channelId, PayChannelEnum.ALIPAY_QR.getCode(), config); - } - - @Override - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { - // 1.1 构建 AlipayTradePrecreateModel 请求 - AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); - // ① 通用的参数 - model.setOutTradeNo(reqDTO.getMerchantOrderId()); - model.setSubject(reqDTO.getSubject()); - model.setBody(reqDTO.getBody()); - model.setTotalAmount(formatAmount(reqDTO.getAmount())); - model.setProductCode("FACE_TO_FACE_PAYMENT"); // 销售产品码. 目前扫码支付场景下仅支持 FACE_TO_FACE_PAYMENT - // ② 个性化的参数【无】 - // ③ 支付宝扫码支付只有一种展示,考虑到前端可能希望二维码扫描后,手机打开 - String displayMode = PayDisplayModeEnum.QR_CODE.getMode(); - - // 1.2 构建 AlipayTradePrecreateRequest 请求 - AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); - request.setBizModel(model); - request.setNotifyUrl(reqDTO.getNotifyUrl()); - request.setReturnUrl(reqDTO.getReturnUrl()); - - // 2.1 执行请求 - AlipayTradePrecreateResponse response = client.execute(request); - // 2.2 处理结果 - validateSuccess(response); - return new PayOrderUnifiedRespDTO() - .setDisplayMode(displayMode).setDisplayContent(response.getQrCode()); - } -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java deleted file mode 100644 index 98cfae5..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java +++ /dev/null @@ -1,60 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.alipay; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.http.Method; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import co.yixiang.yshop.framework.pay.core.enums.PayDisplayModeEnum; -import com.alipay.api.AlipayApiException; -import com.alipay.api.domain.AlipayTradeWapPayModel; -import com.alipay.api.request.AlipayTradeWapPayRequest; -import com.alipay.api.response.AlipayTradeWapPayResponse; -import lombok.extern.slf4j.Slf4j; - -/** - * 支付宝【Wap 网站】的 PayClient 实现类 - * - * 文档:手机网站支付接口 - * - * @author yshop - */ -@Slf4j -public class AlipayWapPayClient extends AbstractAlipayClient { - - public AlipayWapPayClient(Long channelId, AlipayPayClientConfig config) { - super(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), config); - } - - @Override - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws AlipayApiException { - // 1.1 构建 AlipayTradeWapPayModel 请求 - AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); - // ① 通用的参数 - model.setOutTradeNo(reqDTO.getMerchantOrderId()); - model.setSubject(reqDTO.getSubject()); - model.setBody(reqDTO.getBody()); - model.setTotalAmount(formatAmount(reqDTO.getAmount())); - model.setProductCode("QUICK_WAP_PAY"); // 销售产品码. 目前 Wap 支付场景下仅支持 QUICK_WAP_PAY - // ② 个性化的参数【无】 - // ③ 支付宝 Wap 支付只有一种展示,考虑到前端可能希望二维码扫描后,手机打开 - String displayMode = ObjectUtil.defaultIfNull(reqDTO.getDisplayMode(), - PayDisplayModeEnum.URL.getMode()); - - // 1.2 构建 AlipayTradeWapPayRequest 请求 - AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest(); - request.setBizModel(model); - request.setNotifyUrl(reqDTO.getNotifyUrl()); - request.setReturnUrl(reqDTO.getReturnUrl()); - model.setQuitUrl(reqDTO.getReturnUrl()); - - // 2.1 执行请求 - AlipayTradeWapPayResponse response = client.pageExecute(request, Method.GET.name()); - - // 2.2 处理结果 - validateSuccess(response); - return new PayOrderUnifiedRespDTO() - .setDisplayMode(displayMode).setDisplayContent(response.getBody()); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXLitePayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXLitePayClient.java deleted file mode 100644 index e8c2050..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXLitePayClient.java +++ /dev/null @@ -1,198 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.wx; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; -import co.yixiang.yshop.framework.common.util.io.FileUtils; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayNotifyReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.client.impl.AbstractPayClient; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; -import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request; -import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result; -import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; -import com.github.binarywang.wxpay.config.WxPayConfig; -import com.github.binarywang.wxpay.constant.WxPayConstants; -import com.github.binarywang.wxpay.exception.WxPayException; -import com.github.binarywang.wxpay.service.WxPayService; -import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; -import lombok.extern.slf4j.Slf4j; - -import java.time.ZoneId; -import java.util.Date; -import java.util.Objects; - -/** - * 微信小程序下支付 - * - * @author zwy - */ -@Slf4j -public class WXLitePayClient extends AbstractPayClient { - - private WxPayService client; - - public WXLitePayClient(Long channelId, WXPayClientConfig config) { - super(channelId, PayChannelEnum.WX_LITE.getCode(), config); - } - - @Override - protected void doInit() { - WxPayConfig payConfig = new WxPayConfig(); - BeanUtil.copyProperties(config, payConfig, "privateKeyContent","privateCertContent"); - payConfig.setTradeType(WxPayConstants.TradeType.JSAPI); // 设置使用 JS API 支付方式 -// if (StrUtil.isNotEmpty(config.getKeyContent())) { -// payConfig.setKeyContent(config.getKeyContent().getBytes(StandardCharsets.UTF_8)); -// } - if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) { - // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决 - payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath()); - } - if (StrUtil.isNotEmpty(config.getPrivateCertContent())) { - // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决 - payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath()); - } - // 真实客户端 - this.client = new WxPayServiceImpl(); - client.setConfig(payConfig); - } - - @Override - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { - throw new UnsupportedOperationException(); -// WxPayMpOrderResult response; -// try { -// switch (config.getApiVersion()) { -// case WXPayClientConfig.API_VERSION_V2: -// response = this.unifiedOrderV2(reqDTO); -// break; -// case WXPayClientConfig.API_VERSION_V3: -// WxPayUnifiedOrderV3Result.JsapiResult responseV3 = this.unifiedOrderV3(reqDTO); -// // 将 V3 的结果,统一转换成 V2。返回的字段是一致的 -// response = new WxPayMpOrderResult(); -// BeanUtil.copyProperties(responseV3, response, true); -// break; -// default: -// throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); -// } -// } catch (WxPayException e) { -// log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e); -// return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"), -// ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()), null, codeMapping); -// } -// return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, response, codeMapping); - } - - private WxPayMpOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { - // 构建 WxPayUnifiedOrderRequest 对象 - WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() - .outTradeNo(reqDTO.getMerchantOrderId()) - .body(reqDTO.getBody()) - .totalFee(reqDTO.getAmount().intValue()) // 单位分 - .timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss")) // v2的时间格式 - .spbillCreateIp(reqDTO.getUserIp()) - .openid(getOpenid(reqDTO)) - .notifyUrl(reqDTO.getNotifyUrl()) - .build(); - // 执行请求 - return client.createOrder(request); - } - - private WxPayUnifiedOrderV3Result.JsapiResult unifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { - // 构建 WxPayUnifiedOrderRequest 对象 - WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); - request.setOutTradeNo(reqDTO.getMerchantOrderId()); - - request.setDescription(reqDTO.getBody()); - request.setAmount(new WxPayUnifiedOrderV3Request - .Amount() - .setTotal(reqDTO - .getAmount() - .intValue())); // 单位分 - request.setTimeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")); // v3的时间格式 - request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO))); - request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp())); - request.setNotifyUrl(reqDTO.getNotifyUrl()); - // 执行请求 - return client.createOrderV3(TradeTypeEnum.JSAPI, request); - } - - private static String getOpenid(PayOrderUnifiedReqDTO reqDTO) { - String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid"); - if (StrUtil.isEmpty(openid)) { - throw new IllegalArgumentException("支付请求的 openid 不能为空!"); - } - return openid; - } - - /** - * - * 微信支付回调 分 v2 和v3 的处理方式 - * - * @param data 通知结果 - * @return 支付回调对象 - * @throws WxPayException 微信异常类 - */ -// @Override - public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyReqDTO data) throws WxPayException { - log.info("[parseOrderNotify][微信支付回调data数据:{}]", data.getBody()); - // 微信支付 v2 回调结果处理 - switch (config.getApiVersion()) { - case WXPayClientConfig.API_VERSION_V2: - return parseOrderNotifyV2(data); - case WXPayClientConfig.API_VERSION_V3: - return parseOrderNotifyV3(data); - default: - throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); - } - } - - private PayOrderNotifyRespDTO parseOrderNotifyV3(PayNotifyReqDTO data) throws WxPayException { - WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = client.parseOrderNotifyV3Result(data.getBody(), null); - WxPayOrderNotifyV3Result.DecryptNotifyResult result = wxPayOrderNotifyV3Result.getResult(); - // 转换结果 - Assert.isTrue(Objects.equals(wxPayOrderNotifyV3Result.getResult().getTradeState(), "SUCCESS"), - "支付结果非 SUCCESS"); - - return PayOrderNotifyRespDTO - .builder() - .orderExtensionNo(result.getOutTradeNo()) - .channelOrderNo(result.getTransactionId()) - .channelUserId(result.getPayer().getOpenid()) - .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) - .build(); - } - - private PayOrderNotifyRespDTO parseOrderNotifyV2(PayNotifyReqDTO data) throws WxPayException { - WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody()); - Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS"); - // 转换结果 - return PayOrderNotifyRespDTO - .builder() - .orderExtensionNo(notifyResult.getOutTradeNo()) - .channelOrderNo(notifyResult.getTransactionId()) - .channelUserId(notifyResult.getOpenid()) - .successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) - .build(); - - } - - @Override - protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { - //TODO 需要实现 - throw new UnsupportedOperationException(); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXNativePayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXNativePayClient.java deleted file mode 100644 index 4261120..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXNativePayClient.java +++ /dev/null @@ -1,181 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.wx; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.StrUtil; -import co.yixiang.yshop.framework.common.util.io.FileUtils; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayNotifyReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayRefundNotifyRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.client.impl.AbstractPayClient; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; -import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult; -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request; -import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; -import com.github.binarywang.wxpay.config.WxPayConfig; -import com.github.binarywang.wxpay.constant.WxPayConstants; -import com.github.binarywang.wxpay.exception.WxPayException; -import com.github.binarywang.wxpay.service.WxPayService; -import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; -import lombok.extern.slf4j.Slf4j; - -import java.time.ZoneId; -import java.util.Date; -import java.util.Objects; - -/** - * 微信 App 支付 - * - * @author zwy - */ -@Slf4j -public class WXNativePayClient extends AbstractPayClient { - - private WxPayService client; - - public WXNativePayClient(Long channelId, WXPayClientConfig config) { - super(channelId, PayChannelEnum.WX_NATIVE.getCode(), config); - } - - @Override - protected void doInit() { - WxPayConfig payConfig = new WxPayConfig(); - BeanUtil.copyProperties(config, payConfig, "keyContent"); - payConfig.setTradeType(WxPayConstants.TradeType.NATIVE); // 设置使用 native 支付方式 -// if (StrUtil.isNotEmpty(config.getKeyContent())) { -// payConfig.setKeyContent(config.getKeyContent().getBytes(StandardCharsets.UTF_8)); -// } - if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) { - // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决 - payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath()); - } - if (StrUtil.isNotEmpty(config.getPrivateCertContent())) { - // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决 - payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath()); - } - // 真实客户端 - this.client = new WxPayServiceImpl(); - client.setConfig(payConfig); - } - - @Override - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { - throw new UnsupportedOperationException(); -// // 这里原生的返回的是支付的 url 所以直接使用string接收 -// // "invokeResponse": "weixin://wxpay/bizpayurl?pr=EGYAem7zz" -// String responseV3; -// try { -// switch (config.getApiVersion()) { -// case WXPayClientConfig.API_VERSION_V2: -// responseV3 = unifiedOrderV2(reqDTO).getCodeUrl(); -// break; -// case WXPayClientConfig.API_VERSION_V3: -// responseV3 = this.unifiedOrderV3(reqDTO); -// break; -// default: -// throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); -// } -// } catch (WxPayException e) { -// log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e); -// return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"), -// ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()), null, codeMapping); -// } -// return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, responseV3, codeMapping); - } - - private WxPayNativeOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { - //前端 - String tradeType = reqDTO.getChannelExtras().get("trade_type"); - // 构建 WxPayUnifiedOrderRequest 对象 - WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest - .newBuilder() - .outTradeNo(reqDTO.getMerchantOrderId()) - .body(reqDTO.getBody()) - .totalFee(reqDTO.getAmount().intValue()) // 单位分 - .timeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")) - .spbillCreateIp(reqDTO.getUserIp()) - .notifyUrl(reqDTO.getNotifyUrl()) - .productId(tradeType) - .build(); - // 执行请求 - return client.createOrder(request); - } - - private String unifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { - // 构建 WxPayUnifiedOrderRequest 对象 - WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); - request.setOutTradeNo(reqDTO.getMerchantOrderId()); - request.setDescription(reqDTO.getBody()); - request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount().intValue())); // 单位分 - request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp())); - request.setNotifyUrl(reqDTO.getNotifyUrl()); - // 执行请求 - return client.createOrderV3(TradeTypeEnum.NATIVE, request); - } - - /** - * - * 微信支付回调 分v2 和v3 的处理方式 - * - * @param data 通知结果 - * @return 支付回调对象 - * @throws WxPayException 微信异常类 - */ -// @Override - public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyReqDTO data) throws WxPayException { - log.info("微信支付回调data数据:{}", data.getBody()); - // 微信支付 v2 回调结果处理 - switch (config.getApiVersion()) { - case WXPayClientConfig.API_VERSION_V2: - return parseOrderNotifyV2(data); - case WXPayClientConfig.API_VERSION_V3: - return parseOrderNotifyV3(data); - default: - throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); - } - } - - private PayOrderNotifyRespDTO parseOrderNotifyV3(PayNotifyReqDTO data) throws WxPayException { - WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = client.parseOrderNotifyV3Result(data.getBody(), null); - WxPayOrderNotifyV3Result.DecryptNotifyResult result = wxPayOrderNotifyV3Result.getResult(); - // 转换结果 - Assert.isTrue(Objects.equals(wxPayOrderNotifyV3Result.getResult().getTradeState(), "SUCCESS"), - "支付结果非 SUCCESS"); - return PayOrderNotifyRespDTO - .builder() - .orderExtensionNo(result.getOutTradeNo()) - .channelOrderNo(result.getTradeState()) - .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) - .build(); - } - - private PayOrderNotifyRespDTO parseOrderNotifyV2(PayNotifyReqDTO data) throws WxPayException { - WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody()); - Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS"); - // 转换结果 - return PayOrderNotifyRespDTO - .builder() - .orderExtensionNo(notifyResult.getOutTradeNo()) - .channelOrderNo(notifyResult.getTransactionId()) - .channelUserId(notifyResult.getOpenid()) - .successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) - .build(); - - } - - @Override - protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { - // TODO 需要实现 - throw new UnsupportedOperationException(); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXPayClientConfig.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXPayClientConfig.java deleted file mode 100644 index 66845bd..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXPayClientConfig.java +++ /dev/null @@ -1,111 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.wx; - -import cn.hutool.core.io.IoUtil; -import co.yixiang.yshop.framework.pay.core.client.PayClientConfig; -import lombok.Data; - -import javax.validation.ConstraintViolation; -import javax.validation.Validator; -import javax.validation.constraints.NotBlank; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.util.Set; - -/** - * 微信支付的 PayClientConfig 实现类 - * 属性主要来自 {@link com.github.binarywang.wxpay.config.WxPayConfig} 的必要属性 - * - * @author yshop - */ -@Data -public class WXPayClientConfig implements PayClientConfig { - - /** - * API 版本 - V2 - * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1 - */ - public static final String API_VERSION_V2 = "v2"; - /** - * API 版本 - V3 - * https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml - */ - public static final String API_VERSION_V3 = "v3"; - - /** - * 公众号或者小程序的 appid - */ - @NotBlank(message = "APPID 不能为空", groups = {V2.class, V3.class}) - private String appId; - /** - * 商户号 - */ - @NotBlank(message = "商户号 不能为空", groups = {V2.class, V3.class}) - private String mchId; - /** - * API 版本 - */ - @NotBlank(message = "API 版本 不能为空", groups = {V2.class, V3.class}) - private String apiVersion; - - // ========== V2 版本的参数 ========== - - /** - * 商户密钥 - */ - @NotBlank(message = "商户密钥 不能为空", groups = V2.class) - private String mchKey; - /** - * apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. - * 对应的字符串 - * - * 注意,可通过 {@link #main(String[])} 读取 - */ - /// private String keyContent; - - // ========== V3 版本的参数 ========== - /** - * apiclient_key.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. - * 对应的字符串 - * 注意,可通过 {@link #main(String[])} 读取 - */ - @NotBlank(message = "apiclient_key 不能为空", groups = V3.class) - private String privateKeyContent; - /** - * apiclient_cert.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. - * 对应的字符串 - *

- * 注意,可通过 {@link #main(String[])} 读取 - */ - @NotBlank(message = "apiclient_cert 不能为空", groups = V3.class) - private String privateCertContent; - /** - * apiV3 密钥值 - */ - @NotBlank(message = "apiV3 密钥值 不能为空", groups = V3.class) - private String apiV3Key; - - /** - * 分组校验 v2版本 - */ - public interface V2 { - } - - /** - * 分组校验 v3版本 - */ - public interface V3 { - } - - @Override - public Set> verifyParam(Validator validator) { - return validator.validate(this, this.getApiVersion().equals(API_VERSION_V2) ? V2.class : V3.class); - } - - public static void main(String[] args) throws FileNotFoundException { - String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.p12"; - /// String path = "/Users/yunai/Downloads/wx_pay/apiclient_key.pem"; - /// String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.pem"; - System.out.println(IoUtil.readUtf8(new FileInputStream(path))); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXPubPayClient.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXPubPayClient.java deleted file mode 100644 index a4b9501..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/client/impl/wx/WXPubPayClient.java +++ /dev/null @@ -1,196 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.wx; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.date.TemporalAccessorUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; -import co.yixiang.yshop.framework.common.util.io.FileUtils; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayNotifyReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO; -import co.yixiang.yshop.framework.pay.core.client.impl.AbstractPayClient; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; -import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request; -import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result; -import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; -import com.github.binarywang.wxpay.config.WxPayConfig; -import com.github.binarywang.wxpay.constant.WxPayConstants; -import com.github.binarywang.wxpay.exception.WxPayException; -import com.github.binarywang.wxpay.service.WxPayService; -import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; -import lombok.extern.slf4j.Slf4j; - -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.Objects; - -/** - * 微信支付(公众号)的 PayClient 实现类 - * - * @author yshop - */ -@Slf4j -public class WXPubPayClient extends AbstractPayClient { - - private WxPayService client; - - public WXPubPayClient(Long channelId, WXPayClientConfig config) { - super(channelId, PayChannelEnum.WX_PUB.getCode(), config); - } - - @Override - protected void doInit() { - WxPayConfig payConfig = new WxPayConfig(); - BeanUtil.copyProperties(config, payConfig, "keyContent"); - payConfig.setTradeType(WxPayConstants.TradeType.JSAPI); // 设置使用 JS API 支付方式 -// if (StrUtil.isNotEmpty(config.getKeyContent())) { -// payConfig.setKeyContent(config.getKeyContent().getBytes(StandardCharsets.UTF_8)); -// } - if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) { - // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决 - payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath()); - } - if (StrUtil.isNotEmpty(config.getPrivateCertContent())) { - // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决 - payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath()); - } - // 真实客户端 - this.client = new WxPayServiceImpl(); - client.setConfig(payConfig); - } - - @Override - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { - throw new UnsupportedOperationException(); -// -// WxPayMpOrderResult response; -// try { -// switch (config.getApiVersion()) { -// case WXPayClientConfig.API_VERSION_V2: -// response = this.unifiedOrderV2(reqDTO); -// break; -// case WXPayClientConfig.API_VERSION_V3: -// WxPayUnifiedOrderV3Result.JsapiResult responseV3 = this.unifiedOrderV3(reqDTO); -// // 将 V3 的结果,统一转换成 V2。返回的字段是一致的 -// response = new WxPayMpOrderResult(); -// BeanUtil.copyProperties(responseV3, response, true); -// break; -// default: -// throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); -// } -// } catch (WxPayException e) { -// log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e); -// return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"), -// ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()),null, codeMapping); -// } -// return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, response, codeMapping); - } - - - private WxPayMpOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { - // 构建 WxPayUnifiedOrderRequest 对象 - WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() - .outTradeNo(reqDTO.getMerchantOrderId()) - .body(reqDTO.getBody()) - .totalFee(reqDTO.getAmount()) // 单位分 - .timeExpire(formatDate(reqDTO.getExpireTime())) - .spbillCreateIp(reqDTO.getUserIp()) - .openid(getOpenid(reqDTO)) - .notifyUrl(reqDTO.getNotifyUrl()) - .build(); - // 执行请求 - return client.createOrder(request); - } - - private WxPayUnifiedOrderV3Result.JsapiResult unifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { - // 构建 WxPayUnifiedOrderRequest 对象 - WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); - request.setOutTradeNo(reqDTO.getMerchantOrderId()); - request.setDescription(reqDTO.getBody()); - request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount())); // 单位分 - request.setTimeExpire(formatDate(reqDTO.getExpireTime())); - request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO))); - request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp())); - request.setNotifyUrl(reqDTO.getNotifyUrl()); - // 执行请求 - return client.createOrderV3(TradeTypeEnum.JSAPI, request); - } - - private static String getOpenid(PayOrderUnifiedReqDTO reqDTO) { - String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid"); - if (StrUtil.isEmpty(openid)) { - throw new IllegalArgumentException("支付请求的 openid 不能为空!"); - } - return openid; - } - - /** - * - * 微信支付回调 分v2 和v3 的处理方式 - * - * @param data 通知结果 - * @return 支付回调对象 - * @throws WxPayException 微信异常类 - */ -// @Override - public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyReqDTO data) throws WxPayException { - log.info("[parseOrderNotify][微信支付回调data数据: {}]", data.getBody()); - // 微信支付 v2 回调结果处理 - switch (config.getApiVersion()) { - case WXPayClientConfig.API_VERSION_V2: - return parseOrderNotifyV2(data); - case WXPayClientConfig.API_VERSION_V3: - return parseOrderNotifyV3(data); - default: - throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); - } - } - - private PayOrderNotifyRespDTO parseOrderNotifyV3(PayNotifyReqDTO data) throws WxPayException { - WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = client.parseOrderNotifyV3Result(data.getBody(), null); - WxPayOrderNotifyV3Result.DecryptNotifyResult result = wxPayOrderNotifyV3Result.getResult(); - // 转换结果 - Assert.isTrue(Objects.equals(wxPayOrderNotifyV3Result.getResult().getTradeState(), "SUCCESS"), - "支付结果非 SUCCESS"); - return PayOrderNotifyRespDTO - .builder() - .orderExtensionNo(result.getOutTradeNo()) - .channelOrderNo(result.getTradeState()) - .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) - .build(); - } - - private PayOrderNotifyRespDTO parseOrderNotifyV2(PayNotifyReqDTO data) throws WxPayException { - WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody()); - Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS"); - // 转换结果 - return PayOrderNotifyRespDTO - .builder() - .orderExtensionNo(notifyResult.getOutTradeNo()) - .channelOrderNo(notifyResult.getTransactionId()) - .channelUserId(notifyResult.getOpenid()) - .successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) - .build(); - - } - - @Override - protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable { - // TODO 需要实现 - throw new UnsupportedOperationException(); - } - - private static String formatDate(LocalDateTime time) { - return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), "yyyy-MM-dd'T'HH:mm:ssXXX"); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayChannelEnum.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayChannelEnum.java deleted file mode 100644 index f4c70b3..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayChannelEnum.java +++ /dev/null @@ -1,61 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.enums; - -import cn.hutool.core.util.ArrayUtil; -import co.yixiang.yshop.framework.pay.core.client.PayClientConfig; -import co.yixiang.yshop.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; -import co.yixiang.yshop.framework.pay.core.client.impl.wx.WXPayClientConfig; -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 支付渠道的编码的枚举 - * 枚举值 - * - * @author yshop - */ -@Getter -@AllArgsConstructor -public enum PayChannelEnum { - - WX_PUB("wx_pub", "微信 JSAPI 支付", WXPayClientConfig.class), // 公众号网页 - WX_LITE("wx_lite", "微信小程序支付", WXPayClientConfig.class), - WX_APP("wx_app", "微信 App 支付", WXPayClientConfig.class), - WX_NATIVE("wx_native", "微信 native 支付", WXPayClientConfig.class), - - ALIPAY_PC("alipay_pc", "支付宝 PC 网站支付", AlipayPayClientConfig.class), - ALIPAY_WAP("alipay_wap", "支付宝 Wap 网站支付", AlipayPayClientConfig.class), - ALIPAY_APP("alipay_app", "支付宝App 支付", AlipayPayClientConfig.class), - ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class), - ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class); - - /** - * 编码 - *

- * 参考 https://www.pingxx.com/api/支付渠道属性值.html - */ - private final String code; - /** - * 名字 - */ - private final String name; - - /** - * 配置类 - */ - private final Class configClass; - - /** - * 微信支付 - */ - public static final String WECHAT = "WECHAT"; - - /** - * 支付宝支付 - */ - public static final String ALIPAY = "ALIPAY"; - - public static PayChannelEnum getByCode(String code) { - return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values()); - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayChannelRefundRespEnum.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayChannelRefundRespEnum.java deleted file mode 100644 index 740a24e..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayChannelRefundRespEnum.java +++ /dev/null @@ -1,23 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 渠道统一的退款返回结果 - * - * @author jason - */ -@Getter -@AllArgsConstructor -public enum PayChannelRefundRespEnum { - - SUCCESS(1, "退款成功"), - FAILURE(2, "退款失败"), - PROCESSING(3,"退款处理中"), - CLOSED(4, "退款关闭"); - - private final Integer status; - private final String name; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayDisplayModeEnum.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayDisplayModeEnum.java deleted file mode 100644 index 1a9ac5b..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayDisplayModeEnum.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 支付 UI 展示模式 - * - * @author yshop - */ -@Getter -@AllArgsConstructor -public enum PayDisplayModeEnum { - - URL("url"), // Redirect 跳转链接的方式 - IFRAME("iframe"), // IFrame 内嵌链接的方式 - FORM("form"), // HTML 表单提交 - QR_CODE("qr_code"), // 二维码的文字内容 - QR_CODE_URL("qr_code_url"), // 二维码的图片链接 - BAR_CODE("bar_code"), // 条形码 - APP("app"), // 应用 - ; - - /** - * 展示模式 - */ - private final String mode; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayFrameworkErrorCodeConstants.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayFrameworkErrorCodeConstants.java deleted file mode 100644 index 6b77c23..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayFrameworkErrorCodeConstants.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.enums; - -import co.yixiang.yshop.framework.common.exception.ErrorCode; - -/** - * 支付框架的错误码枚举 - * - * 支付框架,使用 2-002-000-000 段 - * - * @author yshop - */ -public interface PayFrameworkErrorCodeConstants { - - ErrorCode PAY_UNKNOWN = new ErrorCode(2002000000, "未知错误,需要解析"); - - // ========== 配置相关相关 2002000100 ========== - // todo yshop:如下的错误码,怎么处理掉 - ErrorCode PAY_CONFIG_APP_ID_ERROR = new ErrorCode(2002000100, "支付渠道 AppId 不正确"); - ErrorCode PAY_CONFIG_SIGN_ERROR = new ErrorCode(2002000100, "签名错误"); // 例如说,微信支付,配置错了 mchId 或者 mchKey - - - // ========== 其它相关 2002000900 开头 ========== - // todo yshop:如下的错误码,怎么处理掉 - ErrorCode PAY_OPENID_ERROR = new ErrorCode(2002000900, "无效的 openid"); // 例如说,微信 openid 未授权过 - ErrorCode PAY_PARAM_MISSING = new ErrorCode(2002000901, "请求参数缺失"); // 例如说,支付少传了金额 - - ErrorCode PAY_EXCEPTION = new ErrorCode(2002000999, "调用异常"); - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayNotifyRefundStatusEnum.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayNotifyRefundStatusEnum.java deleted file mode 100644 index 04b788e..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/java/co/yixiang/yshop/framework/pay/core/enums/PayNotifyRefundStatusEnum.java +++ /dev/null @@ -1,22 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.enums; - -/** - * 退款通知, 统一的渠道退款状态 - * - * @author jason - */ -public enum PayNotifyRefundStatusEnum { - - /** - * 支付宝 中 全额退款 trade_status=TRADE_CLOSED, 部分退款 trade_status=TRADE_SUCCESS - * 退款成功 - */ - SUCCESS, - - /** - * 支付宝退款通知没有这个状态 - * 退款异常 - */ - ABNORMAL; - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 47e8cc5..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -co.yixiang.yshop.framework.pay.config.YshopPayAutoConfiguration \ No newline at end of file diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yshop.framework.pay.core.client.impl/PayClientFactoryImplIntegrationTest.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yshop.framework.pay.core.client.impl/PayClientFactoryImplIntegrationTest.java deleted file mode 100644 index 62319d2..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yshop.framework.pay.core.client.impl/PayClientFactoryImplIntegrationTest.java +++ /dev/null @@ -1,134 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl; - -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.RandomUtil; -import co.yixiang.yshop.framework.common.pojo.CommonResult; -import co.yixiang.yshop.framework.common.util.json.JsonUtils; -import co.yixiang.yshop.framework.pay.core.client.PayClient; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; -import co.yixiang.yshop.framework.pay.core.client.impl.alipay.AlipayQrPayClient; -import co.yixiang.yshop.framework.pay.core.client.impl.alipay.AlipayWapPayClient; -import co.yixiang.yshop.framework.pay.core.client.impl.wx.WXPayClientConfig; -import co.yixiang.yshop.framework.pay.core.client.impl.wx.WXPubPayClient; -import co.yixiang.yshop.framework.pay.core.enums.PayChannelEnum; -import com.alipay.api.response.AlipayTradePrecreateResponse; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; - -/** - * {@link PayClientFactoryImpl} 的集成测试 - * - * @author yshop - */ -@Disabled -public class PayClientFactoryImplIntegrationTest { - - private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl(); - - /** - * {@link WXPubPayClient} 的 V2 版本 - */ - @Test - public void testCreatePayClient_WX_PUB_V2() { - // 创建配置 - WXPayClientConfig config = new WXPayClientConfig(); - config.setAppId("wx041349c6f39b268b"); - config.setMchId("1545083881"); - config.setApiVersion(WXPayClientConfig.API_VERSION_V2); - config.setMchKey("0alL64UDQdlCwiKZ73ib7ypaIjMns06p"); - // 创建客户端 - Long channelId = RandomUtil.randomLong(); - payClientFactory.createOrUpdatePayClient(channelId, PayChannelEnum.WX_PUB.getCode(), config); - PayClient client = payClientFactory.getPayClient(channelId); - // 发起支付 - PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); -// CommonResult result = client.unifiedOrder(reqDTO); -// System.out.println(result); - } - - /** - * {@link WXPubPayClient} 的 V3 版本 - */ - @Test - public void testCreatePayClient_WX_PUB_V3() throws FileNotFoundException { - // 创建配置 - WXPayClientConfig config = new WXPayClientConfig(); - config.setAppId("wx041349c6f39b268b"); - config.setMchId("1545083881"); - config.setApiVersion(WXPayClientConfig.API_VERSION_V3); - config.setPrivateKeyContent(IoUtil.readUtf8(new FileInputStream("/Users/yunai/Downloads/wx_pay/apiclient_key.pem"))); - config.setPrivateCertContent(IoUtil.readUtf8(new FileInputStream("/Users/yunai/Downloads/wx_pay/apiclient_cert.pem"))); - config.setApiV3Key("joerVi8y5DJ3o4ttA0o1uH47Xz1u2Ase"); - // 创建客户端 - Long channelId = RandomUtil.randomLong(); - payClientFactory.createOrUpdatePayClient(channelId, PayChannelEnum.WX_PUB.getCode(), config); - PayClient client = payClientFactory.getPayClient(channelId); - // 发起支付 - PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); -// CommonResult result = client.unifiedOrder(reqDTO); -// System.out.println(result); - } - - /** - * {@link AlipayQrPayClient} - */ - @Test - @SuppressWarnings("unchecked") - public void testCreatePayClient_ALIPAY_QR() { - // 创建配置 - AlipayPayClientConfig config = new AlipayPayClientConfig(); - config.setAppId("2021000118634035"); - config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX); - config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT); - config.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJv890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScwlSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63trepo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdkUSmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENivAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPwYcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQOLFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsmyX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i95Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOUhVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v18p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4eN0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6pbKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erxTRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8="); - config.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB"); - // 创建客户端 - Long channelId = RandomUtil.randomLong(); - payClientFactory.createOrUpdatePayClient(channelId, PayChannelEnum.ALIPAY_QR.getCode(), config); - PayClient client = payClientFactory.getPayClient(channelId); - // 发起支付 - PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); - reqDTO.setNotifyUrl("http://yunai.natapp1.cc/admin-api/pay/notify/callback/18"); // TODO @tina: 这里改成你的 natapp 回调地址 -// CommonResult result = (CommonResult) client.unifiedOrder(reqDTO); -// System.out.println(JsonUtils.toJsonString(result)); -// System.out.println(result.getData().getQrCode()); - } - - /** - * {@link AlipayWapPayClient} - */ - @Test - public void testCreatePayClient_ALIPAY_WAP() { - // 创建配置 - AlipayPayClientConfig config = new AlipayPayClientConfig(); - config.setAppId("2021000118634035"); - config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX); - config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT); - config.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJv890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScwlSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63trepo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdkUSmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENivAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPwYcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQOLFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsmyX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i95Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOUhVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v18p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4eN0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6pbKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erxTRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8="); - config.setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB"); - // 创建客户端 - Long channelId = RandomUtil.randomLong(); - payClientFactory.createOrUpdatePayClient(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), config); - PayClient client = payClientFactory.getPayClient(channelId); - // 发起支付 - PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); -// CommonResult result = client.unifiedOrder(reqDTO); -// System.out.println(JsonUtils.toJsonString(result)); - } - - private static PayOrderUnifiedReqDTO buildPayOrderUnifiedReqDTO() { - PayOrderUnifiedReqDTO reqDTO = new PayOrderUnifiedReqDTO(); - reqDTO.setAmount(123); - reqDTO.setSubject("IPhone 13"); - reqDTO.setBody("biubiubiu"); - reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis())); - reqDTO.setUserIp("127.0.0.1"); - reqDTO.setNotifyUrl("http://127.0.0.1:8080"); - return reqDTO; - } - -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yshop.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java b/yshop-framework/yshop-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yshop.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java deleted file mode 100644 index 09769d6..0000000 --- a/yshop-framework/yshop-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yshop.framework.pay.core.client.impl/alipay/AlipayQrPayClientTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package co.yixiang.yshop.framework.pay.core.client.impl.alipay; -import cn.hutool.core.util.ReflectUtil; -import co.yixiang.yshop.framework.common.exception.enums.GlobalErrorCodeConstants; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; -import co.yixiang.yshop.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; -import co.yixiang.yshop.framework.test.core.ut.BaseMockitoUnitTest; -import com.alipay.api.AlipayApiException; -import com.alipay.api.DefaultAlipayClient; -import com.alipay.api.request.AlipayTradePrecreateRequest; -import com.alipay.api.response.AlipayTradePrecreateResponse; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentMatcher; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -import static co.yixiang.yshop.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotSame; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.when; - -public class AlipayQrPayClientTest extends BaseMockitoUnitTest { - - private final AlipayPayClientConfig config = new AlipayPayClientConfig() - .setAppId("2021000118634035") - .setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX) - .setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT) - // TODO @tina:key 可以随机就好,简洁一点哈。 - .setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCHsEV1cDupwJ" + - "v890x84qbppUtRIfhaKSwSVN0thCcsDCaAsGR5MZslDkO8NCT9V4r2SVXjyY7eJUZlZd1M0C8T" + - "01Tg4UOx5LUbic0O3A1uJMy6V1n9IyYwbAW3AEZhBd5bSbPgrqvmv3NeWSTQT6Anxnllf+2iDH" + - "6zyA2fPl7cYyQtbZoDJQFGqr4F+cGh2R6akzRKNoBkAeMYwoY6es2lX8sJxCVPWUmxNUoL3tScw" + - "lSpd7Bxw0q9c/X01jMwuQ0+Va358zgFiGERTE6yD01eu40OBDXOYO3z++y+TAYHlQQ2toMO63tr" + - "epo88X3xV3R44/1DH+k2pAm2IF5ixiLrAgMBAAECggEAPx3SoXcseaD7rmcGcE0p4SMfbsUDdk" + - "USmBBbtfF0GzwnqNLkWa+mgE0rWt9SmXngTQH97vByAYmLPl1s3G82ht1V7Sk7yQMe74lhFllr" + - "8eEyTjeVx3dTK1EEM4TwN+936DTXdFsr4TELJEcJJdD0KaxcCcfBLRDs2wnitEFZ9N+GoZybVmY8w" + - "0e0MI7PLObUZ2l0X4RurQnfG9ZxjXjC7PkeMVv7cGGylpNFi3BbvkRhdhLPDC2E6wqnr9e7zk+hiENi" + - "vAezXrtxtwKovzCtnWJ1r0IO14Rh47H509Ic0wFnj+o5YyUL4LdmpL7yaaH6fM7zcSLFjNZPHvZCKPw" + - "YcQKBgQDQFho98QvnL8ex4v6cry4VitGpjSXm1qP3vmMQk4rTsn8iPWtcxPjqGEqOQJjdi4Mi0VZKQO" + - "LFwlH0kl95wNrD/isJ4O1yeYfX7YAXApzHqYNINzM79HemO3Yx1qLMW3okRFJ9pPRzbQ9qkTpsaegsm" + - "yX316zOBhzGRYjKbutTYwKBgQCm7phr9XdFW5Vh+XR90mVs483nrLmMiDKg7YKxSLJ8amiDjzPejCn7i9" + - "5Hah08P+2MIZLIPbh2VLacczR6ltRRzN5bg5etFuqSgfkuHyxpoDmpjbe08+Q2h8JBYqcC5Nhv1AKU4iOU" + - "hVLHo/FBAQliMcGc/J3eiYTFC7EsNx382QKBgClb20doe7cttgFTXswBvaUmfFm45kmla924B7SpvrQpDD" + - "/f+VDtDZRp05fGmxuduSjYdtA3aVtpLiTwWu22OUUvZZqHDGruYOO4Hvdz23mL5b4ayqImCwoNU4bAZIc9v1" + - "8p/UNf3/55NNE3oGcf/bev9rH2OjCQ4nM+Ktwhg8CFAoGACSgvbkShzUkv0ZcIf9ppu+ZnJh1AdGgINvGwaJ" + - "8vQ0nm/8h8NOoFZ4oNoGc+wU5Ubops7dUM6FjPR5e+OjdJ4E7Xp7d5O4J1TaIZlCEbo5OpdhaTDDcQvrkFu+Z4e" + - "N0qzj+YAKjDAOOrXc4tbr5q0FsgXscwtcNfaBuzFVTUrUkCgYEAwzPnMNhWG3zOWLUs2QFA2GP4Y+J8cpUYfj6p" + - "bKKzeLwyG9qBwF1NJpN8m+q9q7V9P2LY+9Lp9e1mGsGeqt5HMEA3P6vIpcqLJLqE/4PBLLRzfccTcmqb1m71+erx" + - "TRhHBRkGS+I7dZEb3olQfnS1Y1tpMBxiwYwR3LW4oXuJwj8=") - .setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0" + - "gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBN" + - "lrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZ" + - "ikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB"); - - @InjectMocks - AlipayQrPayClient client = new AlipayQrPayClient(10L,config); - - @Mock - private DefaultAlipayClient defaultAlipayClient; - - @Test - public void testDoInit(){ - client.doInit(); - assertNotSame(defaultAlipayClient, ReflectUtil.getFieldValue(client, "defaultAlipayClient")); - } - - @Test - @Disabled // TODO yshop:临时禁用 - public void create() throws AlipayApiException { - // TODO @tina:参数可以尽量随机一点,使用随机方法。这样的好处是,避免对固定参数的依赖,导致可能仅仅满足固定参数的结果 - // 这里,设置可以直接随机整个对象。 - Long shopOrderId = System.currentTimeMillis(); - PayOrderUnifiedReqDTO reqDTO=new PayOrderUnifiedReqDTO(); - reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis())); - reqDTO.setAmount(1); - reqDTO.setBody("内容:" + shopOrderId); - reqDTO.setSubject("标题:"+shopOrderId); - String notify="http://niubi.natapp1.cc/api/pay/order/notify"; - reqDTO.setNotifyUrl(notify); - - AlipayTradePrecreateResponse response=randomPojo(AlipayTradePrecreateResponse.class,o->o.setQrCode("success")); - - when(defaultAlipayClient.execute(argThat((ArgumentMatcher) request ->{ - assertEquals(notify,request.getNotifyUrl()); - return true; - }))).thenReturn(response); - - -// PayCommonResult result = client.doUnifiedOrder(reqDTO); -// // 断言 -// assertEquals(response.getCode(), result.getApiCode()); -// assertEquals(response.getMsg(), result.getApiMsg()); -// // TODO @tina:这个断言木有过? -// assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); -// assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - - } -} diff --git a/yshop-framework/yshop-spring-boot-starter-biz-sms/pom.xml b/yshop-framework/yshop-spring-boot-starter-biz-sms/pom.xml index 84fa6ff..e93b68c 100644 --- a/yshop-framework/yshop-spring-boot-starter-biz-sms/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-biz-sms/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 短信拓展,支持阿里云、腾讯云 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-biz-tenant/pom.xml b/yshop-framework/yshop-spring-boot-starter-biz-tenant/pom.xml index b9e4082..025b420 100644 --- a/yshop-framework/yshop-spring-boot-starter-biz-tenant/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-biz-tenant/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 多租户 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-biz-weixin/pom.xml b/yshop-framework/yshop-spring-boot-starter-biz-weixin/pom.xml index b9111ef..7940d97 100644 --- a/yshop-framework/yshop-spring-boot-starter-biz-weixin/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-biz-weixin/pom.xml @@ -16,7 +16,7 @@ 1. 基于 weixin-java-mp 库,对接微信公众号平台。目前主要解决微信公众号的支付场景。 2. 基于 weixin-java-miniapp 库,对接微信小程序。目前主要解决微信小程序的一键登录场景。 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-excel/pom.xml b/yshop-framework/yshop-spring-boot-starter-excel/pom.xml index c08d738..f10086d 100644 --- a/yshop-framework/yshop-spring-boot-starter-excel/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-excel/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} Excel 拓展 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-file/pom.xml b/yshop-framework/yshop-spring-boot-starter-file/pom.xml index 88ea200..30d3dfb 100644 --- a/yshop-framework/yshop-spring-boot-starter-file/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-file/pom.xml @@ -18,7 +18,7 @@ 4. db:数据库 5. s3:支持 S3 协议的云存储服务,例如说 MinIO、阿里云、华为云、腾讯云、七牛云等等 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-file/src/main/java/co/yixiang/yshop/framework/file/core/client/s3/S3FileClientConfig.java b/yshop-framework/yshop-spring-boot-starter-file/src/main/java/co/yixiang/yshop/framework/file/core/client/s3/S3FileClientConfig.java index b583e83..42a5691 100644 --- a/yshop-framework/yshop-spring-boot-starter-file/src/main/java/co/yixiang/yshop/framework/file/core/client/s3/S3FileClientConfig.java +++ b/yshop-framework/yshop-spring-boot-starter-file/src/main/java/co/yixiang/yshop/framework/file/core/client/s3/S3FileClientConfig.java @@ -23,7 +23,7 @@ public class S3FileClientConfig implements FileClientConfig { /** * 节点地址 - * 1. MinIO:https://www.iocoder.cn/Spring-Boot/MinIO 。例如说,http://127.0.0.1:9000 + * 1. MinIO:https://www.yixiang.co/Spring-Boot/MinIO 。例如说,http://127.0.0.1:9000 * 2. 阿里云:https://help.aliyun.com/document_detail/31837.html * 3. 腾讯云:https://cloud.tencent.com/document/product/436/6224 * 4. 七牛云:https://developer.qiniu.com/kodo/4088/s3-access-domainname @@ -49,7 +49,7 @@ public class S3FileClientConfig implements FileClientConfig { /** * 访问 Key - * 1. MinIO:https://www.iocoder.cn/Spring-Boot/MinIO + * 1. MinIO:https://www.yixiang.co/Spring-Boot/MinIO * 2. 阿里云:https://ram.console.aliyun.com/manage/ak * 3. 腾讯云:https://console.cloud.tencent.com/cam/capi * 4. 七牛云:https://portal.qiniu.com/user/key diff --git a/yshop-framework/yshop-spring-boot-starter-file/src/test/java/co/yixiang/yshop/framework/file/core/client/local/LocalFileClientTest.java b/yshop-framework/yshop-spring-boot-starter-file/src/test/java/co/yixiang/yshop/framework/file/core/client/local/LocalFileClientTest.java index fe92857..f3918d1 100644 --- a/yshop-framework/yshop-spring-boot-starter-file/src/test/java/co/yixiang/yshop/framework/file/core/client/local/LocalFileClientTest.java +++ b/yshop-framework/yshop-spring-boot-starter-file/src/test/java/co/yixiang/yshop/framework/file/core/client/local/LocalFileClientTest.java @@ -13,7 +13,7 @@ public class LocalFileClientTest { // 创建客户端 LocalFileClientConfig config = new LocalFileClientConfig(); config.setDomain("http://127.0.0.1:48080"); - config.setBasePath("/Users/yunai/file_test"); + config.setBasePath("/Users/yshop/file_test"); LocalFileClient client = new LocalFileClient(0L, config); client.init(); // 上传文件 diff --git a/yshop-framework/yshop-spring-boot-starter-file/src/test/java/co/yixiang/yshop/framework/file/core/client/s3/S3FileClientTest.java b/yshop-framework/yshop-spring-boot-starter-file/src/test/java/co/yixiang/yshop/framework/file/core/client/s3/S3FileClientTest.java index a264f92..2b57601 100644 --- a/yshop-framework/yshop-spring-boot-starter-file/src/test/java/co/yixiang/yshop/framework/file/core/client/s3/S3FileClientTest.java +++ b/yshop-framework/yshop-spring-boot-starter-file/src/test/java/co/yixiang/yshop/framework/file/core/client/s3/S3FileClientTest.java @@ -33,8 +33,8 @@ public class S3FileClientTest { // 配置成你自己的 config.setAccessKey(System.getenv("ALIYUN_ACCESS_KEY")); config.setAccessSecret(System.getenv("ALIYUN_SECRET_KEY")); - config.setBucket("yunai-aoteman"); - config.setDomain(null); // 如果有自定义域名,则可以设置。http://ali-oss.iocoder.cn + config.setBucket("yshop-aoteman"); + config.setDomain(null); // 如果有自定义域名,则可以设置。http://ali-oss.yixiang.co // 默认北京的 endpoint config.setEndpoint("oss-cn-beijing.aliyuncs.com"); @@ -50,7 +50,7 @@ public class S3FileClientTest { config.setAccessKey(System.getenv("QCLOUD_ACCESS_KEY")); config.setAccessSecret(System.getenv("QCLOUD_SECRET_KEY")); config.setBucket("aoteman-1255880240"); - config.setDomain(null); // 如果有自定义域名,则可以设置。http://tengxun-oss.iocoder.cn + config.setDomain(null); // 如果有自定义域名,则可以设置。http://tengxun-oss.yixiang.co // 默认上海的 endpoint config.setEndpoint("cos.ap-shanghai.myqcloud.com"); @@ -67,8 +67,8 @@ public class S3FileClientTest { // config.setAccessSecret(System.getenv("QINIU_SECRET_KEY")); config.setAccessKey("b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8"); config.setAccessSecret("kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP"); - config.setBucket("ruoyi-vue-pro"); - config.setDomain("http://test.yshop.iocoder.cn"); // 如果有自定义域名,则可以设置。http://static.yshop.iocoder.cn + config.setBucket("yshop-pro"); + config.setDomain("http://test.yshop.yixiang.co"); // 如果有自定义域名,则可以设置。http://static.yshop.yixiang.co // 默认上海的 endpoint config.setEndpoint("s3-cn-south-1.qiniucs.com"); diff --git a/yshop-framework/yshop-spring-boot-starter-job/pom.xml b/yshop-framework/yshop-spring-boot-starter-job/pom.xml index aba645e..2bea5ab 100644 --- a/yshop-framework/yshop-spring-boot-starter-job/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-job/pom.xml @@ -16,7 +16,7 @@ 1. 定时任务,基于 Quartz 拓展 2. 异步任务,基于 Spring Async 拓展 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-job/《芋道 Spring Boot 定时任务入门》.md b/yshop-framework/yshop-spring-boot-starter-job/《芋道 Spring Boot 定时任务入门》.md deleted file mode 100644 index ea824d4..0000000 --- a/yshop-framework/yshop-spring-boot-starter-job/《芋道 Spring Boot 定时任务入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-job/《芋道 Spring Boot 异步任务入门》.md b/yshop-framework/yshop-spring-boot-starter-job/《芋道 Spring Boot 异步任务入门》.md deleted file mode 100644 index 8fe01f4..0000000 --- a/yshop-framework/yshop-spring-boot-starter-job/《芋道 Spring Boot 异步任务入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-monitor/pom.xml b/yshop-framework/yshop-spring-boot-starter-monitor/pom.xml index 0593c9c..a76da12 100644 --- a/yshop-framework/yshop-spring-boot-starter-monitor/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-monitor/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 服务监控,提供链路追踪、日志服务、指标收集等等功能 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md b/yshop-framework/yshop-spring-boot-starter-monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md deleted file mode 100644 index 3a64023..0000000 --- a/yshop-framework/yshop-spring-boot-starter-monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-monitor/《芋道 Spring Boot 监控端点 Actuator 入门》.md b/yshop-framework/yshop-spring-boot-starter-monitor/《芋道 Spring Boot 监控端点 Actuator 入门》.md deleted file mode 100644 index df48157..0000000 --- a/yshop-framework/yshop-spring-boot-starter-monitor/《芋道 Spring Boot 监控端点 Actuator 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-monitor/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md b/yshop-framework/yshop-spring-boot-starter-monitor/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md deleted file mode 100644 index e502b67..0000000 --- a/yshop-framework/yshop-spring-boot-starter-monitor/《芋道 Spring Boot 链路追踪 SkyWalking 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-mq/pom.xml b/yshop-framework/yshop-spring-boot-starter-mq/pom.xml index 992c869..8d4923a 100644 --- a/yshop-framework/yshop-spring-boot-starter-mq/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-mq/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 消息队列,基于 Redis Pub/Sub 实现广播消费,基于 Stream 实现集群消费 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-mybatis/pom.xml b/yshop-framework/yshop-spring-boot-starter-mybatis/pom.xml index 67fdc11..5a7f5d3 100644 --- a/yshop-framework/yshop-spring-boot-starter-mybatis/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-mybatis/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 数据库连接池、多数据源、事务、MyBatis 拓展 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-mybatis/《芋道 Spring Boot MyBatis 入门》.md b/yshop-framework/yshop-spring-boot-starter-mybatis/《芋道 Spring Boot MyBatis 入门》.md deleted file mode 100644 index 9deae8a..0000000 --- a/yshop-framework/yshop-spring-boot-starter-mybatis/《芋道 Spring Boot MyBatis 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-mybatis/《芋道 Spring Boot 多数据源(读写分离)入门》.md b/yshop-framework/yshop-spring-boot-starter-mybatis/《芋道 Spring Boot 多数据源(读写分离)入门》.md deleted file mode 100644 index a2f32da..0000000 --- a/yshop-framework/yshop-spring-boot-starter-mybatis/《芋道 Spring Boot 多数据源(读写分离)入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-mybatis/《芋道 Spring Boot 数据库连接池入门》.md b/yshop-framework/yshop-spring-boot-starter-mybatis/《芋道 Spring Boot 数据库连接池入门》.md deleted file mode 100644 index da86080..0000000 --- a/yshop-framework/yshop-spring-boot-starter-mybatis/《芋道 Spring Boot 数据库连接池入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-protection/pom.xml b/yshop-framework/yshop-spring-boot-starter-protection/pom.xml index ecc0c89..743184e 100644 --- a/yshop-framework/yshop-spring-boot-starter-protection/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-protection/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 服务保证,提供分布式锁、幂等、限流、熔断等等功能 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-protection/src/main/java/co/yixiang/yshop/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md b/yshop-framework/yshop-spring-boot-starter-protection/src/main/java/co/yixiang/yshop/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md deleted file mode 100644 index 9b9e8bc..0000000 --- a/yshop-framework/yshop-spring-boot-starter-protection/src/main/java/co/yixiang/yshop/framework/resilience4j/《芋道 Spring Boot 服务容错 Resilience4j 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-redis/pom.xml b/yshop-framework/yshop-spring-boot-starter-redis/pom.xml index 08f56b3..c3a3f32 100644 --- a/yshop-framework/yshop-spring-boot-starter-redis/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-redis/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} Redis 封装拓展 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-redis/《芋道 Spring Boot Cache 入门》.md b/yshop-framework/yshop-spring-boot-starter-redis/《芋道 Spring Boot Cache 入门》.md deleted file mode 100644 index baeb0f6..0000000 --- a/yshop-framework/yshop-spring-boot-starter-redis/《芋道 Spring Boot Cache 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-redis/《芋道 Spring Boot Redis 入门》.md b/yshop-framework/yshop-spring-boot-starter-redis/《芋道 Spring Boot Redis 入门》.md deleted file mode 100644 index 64352cc..0000000 --- a/yshop-framework/yshop-spring-boot-starter-redis/《芋道 Spring Boot Redis 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-security/pom.xml b/yshop-framework/yshop-spring-boot-starter-security/pom.xml index e18d3a9..9f0f341 100644 --- a/yshop-framework/yshop-spring-boot-starter-security/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-security/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 用户的认证、权限的校验 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md b/yshop-framework/yshop-spring-boot-starter-security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md deleted file mode 100644 index 45a47c7..0000000 --- a/yshop-framework/yshop-spring-boot-starter-security/《芋道 Spring Boot 安全框架 Spring Security 入门》.md +++ /dev/null @@ -1,2 +0,0 @@ -* yshop Spring Security 入门: -* Spring Security 基本概念: diff --git a/yshop-framework/yshop-spring-boot-starter-test/pom.xml b/yshop-framework/yshop-spring-boot-starter-test/pom.xml index 1c33877..d1a642f 100644 --- a/yshop-framework/yshop-spring-boot-starter-test/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-test/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} 测试组件,用于单元测试、集成测试 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-test/《芋道 Spring Boot 单元测试 Test 入门》.md b/yshop-framework/yshop-spring-boot-starter-test/《芋道 Spring Boot 单元测试 Test 入门》.md deleted file mode 100644 index 0355f55..0000000 --- a/yshop-framework/yshop-spring-boot-starter-test/《芋道 Spring Boot 单元测试 Test 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-web/pom.xml b/yshop-framework/yshop-spring-boot-starter-web/pom.xml index 9222322..12567e8 100644 --- a/yshop-framework/yshop-spring-boot-starter-web/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-web/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} Web 框架,全局异常、API 日志等 - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-framework/yshop-spring-boot-starter-web/《芋道 Spring Boot API 接口文档 Swagger 入门》.md b/yshop-framework/yshop-spring-boot-starter-web/《芋道 Spring Boot API 接口文档 Swagger 入门》.md deleted file mode 100644 index e2d0f0f..0000000 --- a/yshop-framework/yshop-spring-boot-starter-web/《芋道 Spring Boot API 接口文档 Swagger 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-web/《芋道 Spring Boot SpringMVC 入门》.md b/yshop-framework/yshop-spring-boot-starter-web/《芋道 Spring Boot SpringMVC 入门》.md deleted file mode 100644 index 82156d7..0000000 --- a/yshop-framework/yshop-spring-boot-starter-web/《芋道 Spring Boot SpringMVC 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-framework/yshop-spring-boot-starter-websocket/pom.xml b/yshop-framework/yshop-spring-boot-starter-websocket/pom.xml index 620b44f..21246a1 100644 --- a/yshop-framework/yshop-spring-boot-starter-websocket/pom.xml +++ b/yshop-framework/yshop-spring-boot-starter-websocket/pom.xml @@ -13,7 +13,7 @@ ${project.artifactId} WebSocket - https://github.com/YunaiV/ruoyi-vue-pro + https://github.com/guchengwuyue/yshop-pro diff --git a/yshop-module-express/.DS_Store b/yshop-module-express/.DS_Store new file mode 100644 index 0000000..13425ad Binary files /dev/null and b/yshop-module-express/.DS_Store differ diff --git a/yshop-module-express/pom.xml b/yshop-module-express/pom.xml new file mode 100644 index 0000000..6c0e2cd --- /dev/null +++ b/yshop-module-express/pom.xml @@ -0,0 +1,24 @@ + + + + co.yixiang.boot + yshop + ${revision} + + 4.0.0 + yshop-module-express + pom + + yshop-module-express-api + yshop-module-express-biz + + + ${project.artifactId} + + pay 模块 + + + + diff --git a/yshop-module-express/yshop-module-express-api/.DS_Store b/yshop-module-express/yshop-module-express-api/.DS_Store new file mode 100644 index 0000000..51c55bb Binary files /dev/null and b/yshop-module-express/yshop-module-express-api/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-api/pom.xml b/yshop-module-express/yshop-module-express-api/pom.xml new file mode 100644 index 0000000..77053a1 --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/pom.xml @@ -0,0 +1,41 @@ + + + + yshop-module-express + co.yixiang.boot + ${revision} + + 4.0.0 + yshop-module-express-api + jar + + ${project.artifactId} + + pay 模块 API,暴露给其它模块调用 + + + + + co.yixiang.boot + yshop-common + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + + co.yixiang.boot + yshop-spring-boot-starter-mybatis + + + + + + diff --git a/yshop-module-express/yshop-module-express-api/src/.DS_Store b/yshop-module-express/yshop-module-express-api/src/.DS_Store new file mode 100644 index 0000000..038a03c Binary files /dev/null and b/yshop-module-express/yshop-module-express-api/src/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-api/src/main/.DS_Store b/yshop-module-express/yshop-module-express-api/src/main/.DS_Store new file mode 100644 index 0000000..228f65a Binary files /dev/null and b/yshop-module-express/yshop-module-express-api/src/main/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/.DS_Store b/yshop-module-express/yshop-module-express-api/src/main/java/.DS_Store new file mode 100644 index 0000000..49d2f94 Binary files /dev/null and b/yshop-module-express/yshop-module-express-api/src/main/java/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/.DS_Store b/yshop-module-express/yshop-module-express-api/src/main/java/co/.DS_Store new file mode 100644 index 0000000..2b288e3 Binary files /dev/null and b/yshop-module-express/yshop-module-express-api/src/main/java/co/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/.DS_Store b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/.DS_Store new file mode 100644 index 0000000..b738c36 Binary files /dev/null and b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/.DS_Store b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/.DS_Store new file mode 100644 index 0000000..5131c0b Binary files /dev/null and b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/.DS_Store b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/.DS_Store new file mode 100644 index 0000000..5dfbd7e Binary files /dev/null and b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/enums/ErrorCodeConstants.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/enums/ErrorCodeConstants.java new file mode 100644 index 0000000..76c99e0 --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/enums/ErrorCodeConstants.java @@ -0,0 +1,11 @@ +package co.yixiang.yshop.module.express.enums; + +import co.yixiang.yshop.framework.common.exception.ErrorCode; + +public interface ErrorCodeConstants { + // ========== 快递公司 1008008000 ========== + ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1008008000, "快递公司不存在"); + // ========== 电子面单 ========== + ErrorCode ELECTRONICS_ORDER_NOT_EXISTS = new ErrorCode(1008009000, "电子面单不存在"); +} + diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/enums/KdniaoLogisticsCodeEnum.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/enums/KdniaoLogisticsCodeEnum.java new file mode 100644 index 0000000..5c259b9 --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/enums/KdniaoLogisticsCodeEnum.java @@ -0,0 +1,73 @@ +package co.yixiang.yshop.module.express.kdniao.enums; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.SneakyThrows; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +/** + *

物流公司-对应编码-枚举

+ * + * @author hupeng + * @date 2023/7/219 + */ +@Getter +@AllArgsConstructor +public enum KdniaoLogisticsCodeEnum { + + /** + * 申通 + */ + STO("STO", "申通"), + /** + * 中通 + */ + ZTO("ZTO", "中通"), + /** + * 圆通 + */ + YTO("YTO", "圆通"), + /** + * 韵达 + */ + YD("YD", "韵达"), + /** + * 顺丰 + */ + SF("SF", "顺丰"); + + /** + * 物流编码 + */ + private final String code; + /** + * 物流名 + */ + private final String name; + + + private static final List LIST = new ArrayList(); + + static { + LIST.addAll(Arrays.asList(KdniaoLogisticsCodeEnum.values())); + } + + /** + * 根据值查找相应枚举 + */ + @SneakyThrows(Exception.class) + public static KdniaoLogisticsCodeEnum getEnumByName(String name) { + for (KdniaoLogisticsCodeEnum itemEnum : LIST) { + if (itemEnum.getName().equals(name)) { + return itemEnum; + } + } + throw new Exception("暂无此物流编码信息,请联系系统管理员!"); + } + +} diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/enums/KdniaoLogisticsStatusEnum.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/enums/KdniaoLogisticsStatusEnum.java new file mode 100644 index 0000000..8c1746b --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/enums/KdniaoLogisticsStatusEnum.java @@ -0,0 +1,134 @@ +package co.yixiang.yshop.module.express.kdniao.enums; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +/** + *

物流状态枚举

+ * + * @author hupeng + * @date 2023/7/219 + */ +@Getter +@AllArgsConstructor +public enum KdniaoLogisticsStatusEnum { + + /** + * 暂无轨迹信息 + */ + NO_TRACE(0, "暂无轨迹信息"), + /** + * 已揽收 + */ + HAVE_PAID(1, "已揽收"), + /** + * 已揽收 ----------------------------------------------------------------------------- + */ + ON_THE_WAY(2, "在途中"), + /** + * 到达派件城市 + */ + ARRIVE_AT_THE_DISPATCH_CITY(201, "到达派件城市"), + /** + * 派件中 + */ + IN_THE_DELIVERY(202, "派件中"), + /** + * 已放入快递柜或驿站 + */ + HAS_STORED(211, "已放入快递柜或驿站"), + /** + * 签收 ----------------------------------------------------------------------------- + */ + SIGN(3, "签收"), + /** + * 正常签收 + */ + SIGN_NORMAL(301, "正常签收"), + /** + * 派件异常后最终签收 + */ + SIGN_ABNORMAL(302, "派件异常后最终签收"), + /** + * 代收签收 + */ + SIGN_COLLECTION(304, "代收签收"), + /** + * 快递柜或驿站签收 + */ + SIGN_STORED(311, "快递柜或驿站签收"), + /** + * 问题件 ----------------------------------------------------------------------------- + */ + PROBLEM_SHIPMENT(4, "问题件"), + /** + * 发货无信息 + */ + DELIVERY_NO_INFO(401, "发货无信息"), + /** + * 超时未签收 + */ + NO_SIGN_OVER_TIME(402, "超时未签收"), + /** + * 超时未更新 + */ + NOT_UPDATED_DUE_TO_TIMEOUT(403, "超时未更新"), + /** + * 拒收(退件) + */ + REJECTION(404, "拒收(退件)"), + /** + * 派件异常 + */ + SEND_A_ABNORMAL(405, "派件异常"), + /** + * 退货签收 + */ + RETURN_TO_SIGN_FOR(406, "退货签收"), + /** + * 退货未签收 + */ + RETURN_NOT_SIGNED_FOR(407, "退货未签收"), + /** + * 快递柜或驿站超时未取 + */ + STORED_OVER_TIME(412, "快递柜或驿站超时未取"), + /** + * - + */ + DEFAULT(0, "-"); + + /** + * 状态 + */ + private final Integer status; + /** + * 描述 + */ + private final String desc; + + private static final List LIST = new ArrayList(); + + static { + LIST.addAll(Arrays.asList(KdniaoLogisticsStatusEnum.values())); + } + + /** + * 根据物流状态查找相应枚举 + */ + public static KdniaoLogisticsStatusEnum getEnum(Integer status) { + for (KdniaoLogisticsStatusEnum itemEnum : LIST) { + if (itemEnum.getStatus().equals(status)) { + return itemEnum; + } + } + return KdniaoLogisticsStatusEnum.DEFAULT; + } + +} diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoApiBaseDTO.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoApiBaseDTO.java new file mode 100644 index 0000000..2d53bb7 --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoApiBaseDTO.java @@ -0,0 +1,34 @@ +package co.yixiang.yshop.module.express.kdniao.model.dto; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + *

+ * 快递鸟-物流-查询base参数 + *

+ * + * @author hupeng + * @date 2023/7/21 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +//快递鸟-物流-查询base参数 +public class KdniaoApiBaseDTO { + + //用户ID + private String eBusinessID; + + //API key + private String apiKey; + + //请求url + //https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx + private String reqURL; + +} diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoApiDTO.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoApiDTO.java new file mode 100644 index 0000000..869fe83 --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoApiDTO.java @@ -0,0 +1,31 @@ +package co.yixiang.yshop.module.express.kdniao.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + *

+ * 快递鸟-物流-查询参数 + *

+ * + * @author hupeng + * @date 2023/7/21 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +//快递鸟-物流-查询参数 +public class KdniaoApiDTO extends KdniaoApiBaseDTO { + + //快递公司编码 ZTO + private String shipperCode; + + //快递单号 + private String logisticCode; + +} diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoElectronicsOrderDTO.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoElectronicsOrderDTO.java new file mode 100644 index 0000000..60aefa7 --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoElectronicsOrderDTO.java @@ -0,0 +1,193 @@ +package co.yixiang.yshop.module.express.kdniao.model.dto; + +import lombok.*; + +/** + * 电子面单 DTO + * + * @author yshop + */ +@Data +@ToString(callSuper = true) +@NoArgsConstructor +@AllArgsConstructor +public class KdniaoElectronicsOrderDTO extends KdniaoApiBaseDTO { + + //用户 + private Long memberID; + + //订单编号 + private String orderCode; + + //快递公司编码 + private String shipperCode; + + //快递单号 + private String logisticCode; + + //其他费用 + private Double otherCost; + + /** + * 运费支付方式:1=现付,2=到付,3=月结,4=第三方付(仅SF支持) + */ + private Integer paytype; + /** + * 线下网点客户号 + */ + private String customerName; + /** + * 线下网点密码 + */ + private String customerPwd; + /** + * 网点名称 + */ + private String sendSite; + /** + * 网点快递员 + */ + private String sendStaff; + + //快递运费 + private Double cost; + /** + * 月结编号 + */ + private String monthCode; + /** + * 是否通知揽件:0=通知揽件,1=不通知揽件 + */ + private Integer isNotice; + /** + * 是否返回电子面单模板:0=不返回,1=返回 + */ + private Integer isReturnTemp; + /** + * 是否需要短信提醒:0=否,1=是 + */ + private Integer isSendMessage; + /** + * 模板尺寸 + */ + private String templateSize; + /** + * 签回单操作要求(如:签名、盖章、身份证复印件等) + */ + private String operateRequire; + + /** + * 上门揽件开始时间 + */ + private Integer startDate; + /** + * 上门揽件结束时间 + */ + private Integer endDate; + /** + * 备注 + */ + private String remark; + /** + * 快递类型:1=标准快件 + */ + private Integer expType; + /** + * 是否要签回单:0=否,1=是 + */ + private Integer isReturnSignBill; + /** + * 发件人公司 + */ + private String company; + /** + * 发件人省 + */ + private String provinceName; + /** + * 发件人市 + */ + private String cityName; + /** + * 发件人区 + */ + private String expAreaName; + /** + * 发件人详细地址 + */ + private String address; + /** + * 发件人姓名 + */ + private String name; + /** + * 发件人电话 + */ + private String tel; + /** + * 发件人手机号码 + */ + private String mobile; + /** + * 发件地邮编 + */ + private String postCode; + + + /** + * 收件人公司 + */ + private String receiverCompany; + /** + * 收件人省 + */ + private String receiverProvinceName; + /** + * 收件人市 + */ + private String receiverCityName; + /** + * 收件人区 + */ + private String receiverExpAreaName; + /** + * 收件人详细地址 + */ + private String receiverAddress; + /** + * 收件人姓名 + */ + private String receiverName; + /** + * 收件人电话 + */ + private String receiverTel; + /** + * 收件人手机号码 + */ + private String receiverMobile; + /** + * 收件地邮编 + */ + private String receiverPostCode; + + /** + * 重量 + */ + private Double weight; + + /** + * 重量 + */ + private Integer quantity; + + /** + * 体积 + * + */ + private Double volume; + + + + +} diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoElectronicsOrderGoodsDTO.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoElectronicsOrderGoodsDTO.java new file mode 100644 index 0000000..7e2387a --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/dto/KdniaoElectronicsOrderGoodsDTO.java @@ -0,0 +1,52 @@ +package co.yixiang.yshop.module.express.kdniao.model.dto; + +import lombok.*; +import org.omg.PortableInterceptor.INACTIVE; + +/** + * 电子面单 DTO + * + * @author yshop + */ +@Data +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class KdniaoElectronicsOrderGoodsDTO { + + /** + * 商品名称 + */ + private String goodsName; + + /** + * 商品编号 + */ + private String goodsCode; + /** + * 商品件数 + */ + private Integer goodsQuantity; + /** + * 商品价格 + */ + private Double goodsPrice; + /** + * 商品重量kg + */ + private Double goodsWeight; + /** + * 商品描述 + */ + private String GoodsDesc; + /** + * 商品体积m³ + */ + private Double GoodsVol; + + + + + +} diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/vo/KdniaoApiVO.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/vo/KdniaoApiVO.java new file mode 100644 index 0000000..888f9ed --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/vo/KdniaoApiVO.java @@ -0,0 +1,122 @@ +package co.yixiang.yshop.module.express.kdniao.model.vo; + + +import co.yixiang.yshop.module.express.kdniao.enums.KdniaoLogisticsStatusEnum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 快递鸟-物流-响应参数 + *

+ * @author hupeng + * @date 2023/7/21 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class KdniaoApiVO { + + /** + * {@link KdniaoLogisticsStatusEnum } + * 增值物流状态: + * 0-暂无轨迹信息 + * 1-已揽收 + * 2-在途中 + * 201-到达派件城市, 202-派件中, 211-已放入快递柜或驿站, + * 3-已签收 + * 301-正常签收, 302-派件异常后最终签收, 304-代收签收, 311-快递柜或驿站签收, + * 4-问题件 + * 401-发货无信息, 402-超时未签收, 403-超时未更新, 404-拒收(退件), 405-派件异常, 406-退货签收, 407-退货未签收, 412-快递柜或驿站超时未取 + */ + + //增值物流状态 + private Integer StateEx; + + //增值物流状态名称 + private String statusExName; + + //快递单号 + private String LogisticCode; + + //快递公司编码 + private String ShipperCode; + + + //失败原因 + private String Reason; + + + //事件轨迹集 + private List Traces; + + /** + * {@link KdniaoLogisticsStatusEnum } + */ + //物流状态:0-暂无轨迹信息,1-已揽收,2-在途中,3-签收,4-问题件 + private Integer State; + + //状态名称 + private String statusName; + + //用户ID + private String EBusinessID; + + //送货人 + private String DeliveryMan; + + + //送货人电话号码 + private String DeliveryManTel; + + //成功与否 true/false + private String Success; + + + //所在城市 + private String Location; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + //事件轨迹集 + public static class TraceItem { + /** + * {@link KdniaoLogisticsStatusEnum } + */ + //当前状态(同StateEx) + private Integer Action; + + //状态名称 + private String actionName; + + //描述 + private String AcceptStation; + + //时间 + private String AcceptTime; + + //所在城市 + private String Location; + } + + + public void handleData() { + this.statusName = KdniaoLogisticsStatusEnum.getEnum(this.State).getDesc(); + this.statusExName = KdniaoLogisticsStatusEnum.getEnum(this.StateEx).getDesc(); + if (CollectionUtils.isEmpty(this.Traces)) { + this.Traces = new ArrayList(); + } + this.Traces.forEach(item -> item.actionName = KdniaoLogisticsStatusEnum.getEnum(item.Action).getDesc()); + } + +} diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/vo/KdniaoLogisticsVO.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/vo/KdniaoLogisticsVO.java new file mode 100644 index 0000000..cd5ba35 --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/vo/KdniaoLogisticsVO.java @@ -0,0 +1,97 @@ +package co.yixiang.yshop.module.express.kdniao.model.vo; + +import co.yixiang.yshop.module.express.kdniao.enums.KdniaoLogisticsCodeEnum; +import co.yixiang.yshop.module.express.kdniao.enums.KdniaoLogisticsStatusEnum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + *

快递鸟-物流-参数

+ * + * @author hupeng + * @date 2023/7/21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class KdniaoLogisticsVO { + + /** + * {@link KdniaoLogisticsCodeEnum } + */ + //快递公司编码 + private String logisticsCode; + + //快递单号 + private String logisticsNo; + + //事件轨迹集 + private List traceList; + + //送货人名称 + private String delivererName; + + + //送货人电话号码 + private String delivererPhone; + + //所在城市 + private String location; + + /** + * {@link KdniaoLogisticsStatusEnum } + */ + //物流状态 + private Integer status; + + //状态名称 + private String statusName; + + /** + * {@link KdniaoLogisticsStatusEnum } + */ + //增值物流状态 + private Integer statusEx; + + //增值物流状态名称 + private String statusExName; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + //事件轨迹集 + public static class TraceItem { + //状态 + private Integer status; + + //状态名称 + private String statusName; + + //描述 + private String desc; + + //时间 + private String time; + + //所在城市 + private String location; + } + + public void handleData() { + this.statusName = KdniaoLogisticsStatusEnum.getEnum(this.status).getDesc(); + this.statusExName = KdniaoLogisticsStatusEnum.getEnum(this.statusEx).getDesc(); + if (CollectionUtils.isEmpty(this.traceList)) { + this.traceList = new ArrayList(); + } + this.traceList.forEach(item -> item.statusName = KdniaoLogisticsStatusEnum.getEnum(item.status).getDesc()); + } + +} diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/vo/KdniaoOrderVO.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/vo/KdniaoOrderVO.java new file mode 100644 index 0000000..a2cef70 --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/model/vo/KdniaoOrderVO.java @@ -0,0 +1,114 @@ +package co.yixiang.yshop.module.express.kdniao.model.vo; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + *

+ * 快递鸟-面单-响应参数 + *

+ * @author hupeng + * @date 2023/7/22 + */ +@Data +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +public class KdniaoOrderVO { + //返回编码 + private String ResultCode; + + //失败原因 + private String Reason; + + //成功与否 true/false + private String Success; + + //面单打印模板内容(html格式) + private String PrintTemplate; + + //唯一标识 + private String UniquerRequestNumber; + + //子单数量 + private Integer SubCount; + + //子单单号 + private String SubOrders; + + //子单模板内容(html格式) + private String SubPrintTemplates; + + //签回单模板内容 + private String SignBillPrintTemplate; + + //订单信息 + private OrderInfo Order; + + + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class OrderInfo { + + //订单编号 + private String OrderCode; + + //快递公司编码 + private String ShipperCode; + + //快递单号 + private String LogisticCode; + + //大头笔 + private String MarkDestination; + + //签回单单号 + private String SignWaybillCode; + + + //始发地区域编码 + private String OriginCode; + + //始发地/始发网点 + private String OriginName; + + //目的地区域编码 + private String DestinatioCode; + + //目的地/到达网点 + private String DestinatioName; + + //分拣编码 + private String SortingCode; + + + //集包编码 + private String PackageCode; + + //集包地 + private String PackageName; + + //目的地分拨 + private String DestinationAllocationCentre; + + //配送产品类型 + private Integer TransType; + + //运输方式(用于自行设计京东模板): + //0:陆运 + //1:航空 + private Integer TransportType; + + //自行设计模板用 + private String ShipperInfo; + } + + +} diff --git a/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/util/KdniaoUtil.java b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/util/KdniaoUtil.java new file mode 100644 index 0000000..a386253 --- /dev/null +++ b/yshop-module-express/yshop-module-express-api/src/main/java/co/yixiang/yshop/module/express/kdniao/util/KdniaoUtil.java @@ -0,0 +1,339 @@ +package co.yixiang.yshop.module.express.kdniao.util; + +import co.yixiang.yshop.framework.common.exception.ErrorCode; +import co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil; +import co.yixiang.yshop.module.express.kdniao.model.dto.KdniaoApiDTO; +import co.yixiang.yshop.module.express.kdniao.model.dto.KdniaoElectronicsOrderDTO; +import co.yixiang.yshop.module.express.kdniao.model.dto.KdniaoElectronicsOrderGoodsDTO; +import co.yixiang.yshop.module.express.kdniao.model.vo.KdniaoApiVO; +import co.yixiang.yshop.module.express.kdniao.model.vo.KdniaoOrderVO; +import com.alibaba.fastjson.JSON; +import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + *

快递鸟工具类

+ * + * @author hupeng + * @date 2023/7/219 + */ +@Slf4j +public class KdniaoUtil { + //查询物流当url + private final String KDNIAO_LOGISTIC_QUERY = "https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx"; + //电子面单url + private final String KDNIAO_ELECT_QUERY = "https://api.kdniao.com/api/EOrderService"; + + /** + * 快递查询接口 + * + * @param queryDTO 请求参数 + * @return 物流信息 + */ + public static KdniaoApiVO getLogisticInfo(KdniaoApiDTO queryDTO){ + KdniaoApiVO kdniaoApiVO = new KdniaoUtil().getLogisticBase(queryDTO); + if (kdniaoApiVO.getSuccess() == "false"){ + throw ServiceExceptionUtil.exception(new ErrorCode(999999,kdniaoApiVO.getReason())); + } + + kdniaoApiVO.handleData(); + return kdniaoApiVO; + } + + /** + * 获取电子面单信息 + * @param queryDTO + * @param kdniaoElectronicsOrderGoodsDTOList + * @return + */ + public static KdniaoOrderVO getOrderInfo(KdniaoElectronicsOrderDTO queryDTO, + List kdniaoElectronicsOrderGoodsDTOList) { + KdniaoOrderVO kdniaoOrderVO = new KdniaoUtil().getEleCtBase(queryDTO,kdniaoElectronicsOrderGoodsDTOList); + //todo 由于目前快递鸟订单打印需要申请当地营业网店账号 所有目前这个没法测试 如果有其他用户有可以测试反馈给我们官方 + if (kdniaoOrderVO.getSuccess() == "false"){ + log.error(kdniaoOrderVO.getReason()); + throw ServiceExceptionUtil.exception(new ErrorCode(999999,kdniaoOrderVO.getReason())); + } + + return kdniaoOrderVO; + } + + /** + * 快递查询接口 + * + * @param queryDTO 请求参数 + * @return 物流信息 + */ + @SneakyThrows(Exception.class) + private KdniaoApiVO getLogisticBase(KdniaoApiDTO queryDTO) { + String EBusinessID = queryDTO.getEBusinessID(); + String ApiKey = queryDTO.getApiKey(); + String shipperCode = queryDTO.getShipperCode(); + String logisticCode = queryDTO.getLogisticCode(); + + // 组装应用级参数 + Map requestParamMap = new HashMap<>(); + requestParamMap.put("shipperCode", shipperCode); + requestParamMap.put("LogisticCode", logisticCode); + String RequestData = JSON.toJSONString(requestParamMap); + // 组装系统级参数 + Map params = new HashMap<>(); + params.put("RequestData", this.urlEncoder(RequestData, "UTF-8")); + params.put("EBusinessID", EBusinessID); + params.put("RequestType", "1002");//免费1002 收费8001 + String dataSign = this.encrypt(RequestData, ApiKey, "UTF-8"); + params.put("DataSign", this.urlEncoder(dataSign, "UTF-8")); + params.put("DataType", "2"); + // 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数 + String resultJson = this.sendPost(KDNIAO_LOGISTIC_QUERY, params); + return JSON.parseObject(resultJson, KdniaoApiVO.class); + } + + /** + * 快递查询接口 + * + * @param queryDTO 请求参数 + * @return 物流信息 + */ + @SneakyThrows(Exception.class) + private KdniaoOrderVO getEleCtBase(KdniaoElectronicsOrderDTO queryDTO, + List kdniaoElectronicsOrderGoodsDTOList) { + String EBusinessID = queryDTO.getEBusinessID(); + String ApiKey = queryDTO.getApiKey(); + + + Map requestParamMap = this.doMap(queryDTO,kdniaoElectronicsOrderGoodsDTOList); + System.out.println("map:"+requestParamMap); + String RequestData = JSON.toJSONString(requestParamMap); + // 组装系统级参数 + Map params = new HashMap<>(); + params.put("RequestData", this.urlEncoder(RequestData, "UTF-8")); + params.put("EBusinessID", EBusinessID); + params.put("RequestType", "1007"); + String dataSign = this.encrypt(RequestData, ApiKey, "UTF-8"); + params.put("DataSign", this.urlEncoder(dataSign, "UTF-8")); + params.put("DataType", "2"); + + String resultJson = this.sendPost(KDNIAO_ELECT_QUERY, params); + return JSON.parseObject(resultJson, KdniaoOrderVO.class); + } + + //组合数据 + private Map doMap(KdniaoElectronicsOrderDTO queryDTO, + List kdniaoElectronicsOrderGoodsDTOList){ + + // 组装应用级参数 + Map requestParamMap = new HashMap<>(); + requestParamMap.put("MemberID", queryDTO.getMemberID()); + requestParamMap.put("OrderCode", queryDTO.getOrderCode()); + requestParamMap.put("ShipperCode", queryDTO.getShipperCode()); + requestParamMap.put("LogisticCode", queryDTO.getLogisticCode()); + requestParamMap.put("CustomerName", queryDTO.getCustomerName()); + requestParamMap.put("CustomerPwd", queryDTO.getCustomerPwd()); + requestParamMap.put("SendSite", queryDTO.getSendSite()); + + requestParamMap.put("PayType", queryDTO.getPaytype()); + requestParamMap.put("MonthCode", queryDTO.getMonthCode()); + requestParamMap.put("IsReturnSignBill", queryDTO.getIsReturnSignBill()); + requestParamMap.put("OperateRequire", queryDTO.getOperateRequire()); + requestParamMap.put("ExpType", queryDTO.getExpType()); + requestParamMap.put("Cost", queryDTO.getCost()); + + requestParamMap.put("OtherCost", queryDTO.getOtherCost()); + + Map senderMap = new HashMap<>(); + senderMap.put("Name", queryDTO.getName()); + senderMap.put("Tel", queryDTO.getTel()); + senderMap.put("Company", queryDTO.getCompany()); + senderMap.put("Mobile", queryDTO.getMobile()); + senderMap.put("PostCode", queryDTO.getPostCode()); + senderMap.put("ProvinceName", queryDTO.getProvinceName()); + senderMap.put("CityName", queryDTO.getCityName()); + senderMap.put("ExpAreaName", queryDTO.getExpAreaName()); + senderMap.put("Address", queryDTO.getAddress()); + requestParamMap.put("Sender", senderMap); + + Map receiverMap = new HashMap<>(); + receiverMap.put("Name", queryDTO.getReceiverName()); + receiverMap.put("Tel", queryDTO.getReceiverTel()); + receiverMap.put("Company", queryDTO.getReceiverCompany()); + receiverMap.put("Mobile", queryDTO.getReceiverMobile()); + receiverMap.put("PostCode", queryDTO.getReceiverPostCode()); + receiverMap.put("ProvinceName", queryDTO.getReceiverProvinceName()); + receiverMap.put("CityName", queryDTO.getReceiverCityName()); + receiverMap.put("ExpAreaName", queryDTO.getReceiverExpAreaName()); + receiverMap.put("Address", queryDTO.getReceiverAddress()); + requestParamMap.put("Receiver", receiverMap); + + List> commodityMapList = new ArrayList<>(); + for (KdniaoElectronicsOrderGoodsDTO kdniaoElectronicsOrderGoodsDTO : kdniaoElectronicsOrderGoodsDTOList) { + Map commodityMap = new HashMap<>(); + commodityMap.put("GoodsName", kdniaoElectronicsOrderGoodsDTO.getGoodsName()); + commodityMap.put("GoodsCode", kdniaoElectronicsOrderGoodsDTO.getGoodsCode()); + commodityMap.put("Goodsquantity", kdniaoElectronicsOrderGoodsDTO.getGoodsQuantity()); + commodityMap.put("GoodsPrice", kdniaoElectronicsOrderGoodsDTO.getGoodsPrice()); + commodityMap.put("GoodsWeight", kdniaoElectronicsOrderGoodsDTO.getGoodsWeight()); + commodityMap.put("GoodsVol", kdniaoElectronicsOrderGoodsDTO.getGoodsVol()); + commodityMap.put("GoodsDesc", kdniaoElectronicsOrderGoodsDTO.getGoodsDesc()); + + commodityMapList.add(commodityMap); + } + + requestParamMap.put("Commodity", commodityMapList); + + requestParamMap.put("IsNotice", queryDTO.getIsNotice()); + requestParamMap.put("StartDate", queryDTO.getStartDate()); + requestParamMap.put("EndDate", queryDTO.getEndDate()); + requestParamMap.put("Weight", queryDTO.getWeight()); + requestParamMap.put("Quantity", queryDTO.getQuantity()); + requestParamMap.put("Volume", queryDTO.getVolume()); + requestParamMap.put("IsReturnPrintTemplate", queryDTO.getIsReturnTemp()); + requestParamMap.put("Remark", queryDTO.getRemark()); + + return requestParamMap; + + } + + + /** + * MD5加密 + * str 内容 + * charset 编码方式 + * + * @throws Exception + */ + @SuppressWarnings("unused") + private String MD5(String str, String charset) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(str.getBytes(charset)); + byte[] result = md.digest(); + StringBuffer sb = new StringBuffer(32); + for (int i = 0; i < result.length; i++) { + int val = result[i] & 0xff; + if (val <= 0xf) { + sb.append("0"); + } + sb.append(Integer.toHexString(val)); + } + return sb.toString().toLowerCase(); + } + + /** + * base64编码 + * str 内容 + * charset 编码方式 + * + * @throws UnsupportedEncodingException + */ + private String base64(String str, String charset) throws UnsupportedEncodingException { + String encoded = Base64.encode(str.getBytes(charset)); + return encoded; + } + + @SuppressWarnings("unused") + private String urlEncoder(String str, String charset) throws UnsupportedEncodingException { + String result = URLEncoder.encode(str, charset); + return result; + } + + /** + * 电商Sign签名生成 + * content 内容 + * keyValue ApiKey + * charset 编码方式 + * + * @return DataSign签名 + * @throws UnsupportedEncodingException ,Exception + */ + @SuppressWarnings("unused") + private String encrypt(String content, String keyValue, String charset) throws UnsupportedEncodingException, Exception { + if (keyValue != null) { + return base64(MD5(content + keyValue, charset), charset); + } + return base64(MD5(content, charset), charset); + } + + /** + * 向指定 URL 发送POST方法的请求 + * url 发送请求的 URL + * params 请求的参数集合 + * + * @return 远程资源的响应结果 + */ + @SuppressWarnings("unused") + private String sendPost(String url, Map params) { + OutputStreamWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try { + URL realUrl = new URL(url); + HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); + // 发送POST请求必须设置如下两行 + conn.setDoOutput(true); + conn.setDoInput(true); + // POST方法 + conn.setRequestMethod("POST"); + // 设置通用的请求属性 + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + conn.connect(); + // 获取URLConnection对象对应的输出流 + out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); + // 发送请求参数 + if (params != null) { + StringBuilder param = new StringBuilder(); + for (Map.Entry entry : params.entrySet()) { + if (param.length() > 0) { + param.append("&"); + } + param.append(entry.getKey()); + param.append("="); + param.append(entry.getValue()); + } + log.info("[快递鸟] 请求参数: [{}]", param); + out.write(param.toString()); + } + // flush输出流的缓冲 + out.flush(); + // 定义BufferedReader输入流来读取URL的响应 + in = new BufferedReader( + new InputStreamReader(conn.getInputStream(), "UTF-8")); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + } catch (Exception e) { + e.printStackTrace(); + } + //使用finally块来关闭输出流、输入流 + finally { + try { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } catch (IOException ex) { + ex.printStackTrace(); + } + } + return result.toString(); + } + +} diff --git a/yshop-module-express/yshop-module-express-biz/.DS_Store b/yshop-module-express/yshop-module-express-biz/.DS_Store new file mode 100644 index 0000000..9a874b5 Binary files /dev/null and b/yshop-module-express/yshop-module-express-biz/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-biz/pom.xml b/yshop-module-express/yshop-module-express-biz/pom.xml new file mode 100644 index 0000000..dc8de4a --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/pom.xml @@ -0,0 +1,72 @@ + + + + yshop-module-express + co.yixiang.boot + ${revision} + + 4.0.0 + yshop-module-express-biz + jar + + ${project.artifactId} + + 快递 模块 + + + + + co.yixiang.boot + yshop-module-express-api + ${revision} + + + + + co.yixiang.boot + yshop-spring-boot-starter-biz-operatelog + + + co.yixiang.boot + yshop-spring-boot-starter-biz-tenant + + + + + co.yixiang.boot + yshop-spring-boot-starter-security + + + + + co.yixiang.boot + yshop-spring-boot-starter-redis + + + + + + co.yixiang.boot + yshop-spring-boot-starter-mq + + + + + co.yixiang.boot + yshop-spring-boot-starter-test + test + + + + + co.yixiang.boot + yshop-spring-boot-starter-excel + + + + + + + diff --git a/yshop-module-express/yshop-module-express-biz/src/.DS_Store b/yshop-module-express/yshop-module-express-biz/src/.DS_Store new file mode 100644 index 0000000..7b0d367 Binary files /dev/null and b/yshop-module-express/yshop-module-express-biz/src/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-biz/src/main/.DS_Store b/yshop-module-express/yshop-module-express-biz/src/main/.DS_Store new file mode 100644 index 0000000..5ddc54c Binary files /dev/null and b/yshop-module-express/yshop-module-express-biz/src/main/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/.DS_Store b/yshop-module-express/yshop-module-express-biz/src/main/java/.DS_Store new file mode 100644 index 0000000..2b21b20 Binary files /dev/null and b/yshop-module-express/yshop-module-express-biz/src/main/java/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/.DS_Store b/yshop-module-express/yshop-module-express-biz/src/main/java/co/.DS_Store new file mode 100644 index 0000000..4f19478 Binary files /dev/null and b/yshop-module-express/yshop-module-express-biz/src/main/java/co/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/.DS_Store b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/.DS_Store new file mode 100644 index 0000000..945215c Binary files /dev/null and b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/.DS_Store b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/.DS_Store new file mode 100644 index 0000000..0d00963 Binary files /dev/null and b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/.DS_Store b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/.DS_Store new file mode 100644 index 0000000..5dfbd7e Binary files /dev/null and b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/.DS_Store differ diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/ElectronicsOrderController.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/ElectronicsOrderController.java new file mode 100644 index 0000000..c666951 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/ElectronicsOrderController.java @@ -0,0 +1,101 @@ +package co.yixiang.yshop.module.express.controller.admin.electronicsorder; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import co.yixiang.yshop.framework.common.pojo.PageResult; +import co.yixiang.yshop.framework.common.pojo.CommonResult; +import static co.yixiang.yshop.framework.common.pojo.CommonResult.success; + +import co.yixiang.yshop.framework.excel.core.util.ExcelUtils; + +import co.yixiang.yshop.framework.operatelog.core.annotations.OperateLog; +import static co.yixiang.yshop.framework.operatelog.core.enums.OperateTypeEnum.*; + +import co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo.*; +import co.yixiang.yshop.module.express.dal.dataobject.electronicsorder.ElectronicsOrderDO; +import co.yixiang.yshop.module.express.convert.electronicsorder.ElectronicsOrderConvert; +import co.yixiang.yshop.module.express.service.electronicsorder.ElectronicsOrderService; + +@Tag(name = "管理后台 - 电子面单") +@RestController +@RequestMapping("/express/electronics-order") +@Validated +public class ElectronicsOrderController { + + @Resource + private ElectronicsOrderService electronicsOrderService; + + @PostMapping("/create") + @Operation(summary = "创建电子面单") + @PreAuthorize("@ss.hasPermission('express:electronics-order:create')") + public CommonResult createElectronicsOrder(@Valid @RequestBody ElectronicsOrderCreateReqVO createReqVO) { + return success(electronicsOrderService.createElectronicsOrder(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新电子面单") + @PreAuthorize("@ss.hasPermission('express:electronics-order:update')") + public CommonResult updateElectronicsOrder(@Valid @RequestBody ElectronicsOrderUpdateReqVO updateReqVO) { + electronicsOrderService.updateElectronicsOrder(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除电子面单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('express:electronics-order:delete')") + public CommonResult deleteElectronicsOrder(@RequestParam("id") Long id) { + electronicsOrderService.deleteElectronicsOrder(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得电子面单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('express:electronics-order:query')") + public CommonResult getElectronicsOrder(@RequestParam("id") Long id) { + ElectronicsOrderDO electronicsOrder = electronicsOrderService.getElectronicsOrder(id); + return success(ElectronicsOrderConvert.INSTANCE.convert(electronicsOrder)); + } + + @GetMapping("/list") + @Operation(summary = "获得电子面单列表") + @PreAuthorize("@ss.hasPermission('express:electronics-order:query')") + public CommonResult> getElectronicsOrderList() { + List list = electronicsOrderService.getElectronicsOrderList(); + return success(ElectronicsOrderConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得电子面单分页") + @PreAuthorize("@ss.hasPermission('express:electronics-order:query')") + public CommonResult> getElectronicsOrderPage(@Valid ElectronicsOrderPageReqVO pageVO) { + PageResult pageResult = electronicsOrderService.getElectronicsOrderPage(pageVO); + return success(ElectronicsOrderConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出电子面单 Excel") + @PreAuthorize("@ss.hasPermission('express:electronics-order:export')") + @OperateLog(type = EXPORT) + public void exportElectronicsOrderExcel(@Valid ElectronicsOrderExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = electronicsOrderService.getElectronicsOrderList(exportReqVO); + // 导出 Excel + List datas = ElectronicsOrderConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "电子面单.xls", "数据", ElectronicsOrderExcelVO.class, datas); + } + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderBaseVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderBaseVO.java new file mode 100644 index 0000000..8815aa9 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderBaseVO.java @@ -0,0 +1,101 @@ +package co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import javax.validation.constraints.*; + +/** +* 电子面单 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class ElectronicsOrderBaseVO { + + @Schema(description = "快递公司id", example = "13715") + private Integer shipperId; + + @Schema(description = "运费支付方式:1=现付,2=到付,3=月结,4=第三方付(仅SF支持)", example = "2") + private Integer paytype; + + @Schema(description = "线下网点客户号", example = "张三") + private String customerName; + + @Schema(description = "线下网点密码") + private String customerPwd; + + @Schema(description = "网点名称") + private String sendSite; + + @Schema(description = "网点快递员") + private String sendStaff; + + @Schema(description = "月结编号") + private String monthCode; + + @Schema(description = "是否通知揽件:0=通知揽件,1=不通知揽件") + private Integer isNotice; + + @Schema(description = "是否返回电子面单模板:0=不返回,1=返回") + private Integer isReturnTemp; + + @Schema(description = "是否需要短信提醒:0=否,1=是") + private Integer isSendMessage; + + @Schema(description = "模板尺寸") + private String templateSize; + + @Schema(description = "签回单操作要求(如:签名、盖章、身份证复印件等)") + private String operateRequire; + + @Schema(description = "快递单号(仅宅急送可用)") + private String logisticCode; + + @Schema(description = "上门揽件开始时间") + private Integer startDate; + + @Schema(description = "上门揽件结束时间") + private Integer endDate; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "快递类型:1=标准快件", example = "1") + private Integer expType; + + @Schema(description = "是否要签回单:0=否,1=是") + private Integer isReturnSignBill; + + @Schema(description = "发件人公司") + private String company; + + @Schema(description = "发件人省", example = "李四") + private String provinceName; + + @Schema(description = "发件人市", example = "张三") + private String cityName; + + @Schema(description = "发件人区", example = "张三") + private String expAreaName; + + @Schema(description = "发件人详细地址") + private String address; + + @Schema(description = "发件人姓名", example = "张三") + private String name; + + @Schema(description = "发件人电话") + private String tel; + + @Schema(description = "发件人手机号码") + private String mobile; + + @Schema(description = "发件地邮编") + private String postCode; + + @Schema(description = "自定义名称") + private String title; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderCreateReqVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderCreateReqVO.java new file mode 100644 index 0000000..9e74ece --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderCreateReqVO.java @@ -0,0 +1,14 @@ +package co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - 电子面单创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ElectronicsOrderCreateReqVO extends ElectronicsOrderBaseVO { + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderExcelVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderExcelVO.java new file mode 100644 index 0000000..09e129c --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderExcelVO.java @@ -0,0 +1,109 @@ +package co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; + +import com.alibaba.excel.annotation.ExcelProperty; + +/** + * 电子面单 Excel VO + * + * @author yshop + */ +@Data +public class ElectronicsOrderExcelVO { + + @ExcelProperty("主键id") + private Long id; + + @ExcelProperty("快递公司id") + private Integer shipperId; + + @ExcelProperty("运费支付方式:1=现付,2=到付,3=月结,4=第三方付(仅SF支持)") + private Integer paytype; + + @ExcelProperty("线下网点客户号") + private String customerName; + + @ExcelProperty("线下网点密码") + private String customerPwd; + + @ExcelProperty("网点名称") + private String sendSite; + + @ExcelProperty("网点快递员") + private String sendStaff; + + @ExcelProperty("月结编号") + private String monthCode; + + @ExcelProperty("是否通知揽件:0=通知揽件,1=不通知揽件") + private Integer isNotice; + + @ExcelProperty("是否返回电子面单模板:0=不返回,1=返回") + private Integer isReturnTemp; + + @ExcelProperty("是否需要短信提醒:0=否,1=是") + private Integer isSendMessage; + + @ExcelProperty("模板尺寸") + private String templateSize; + + @ExcelProperty("签回单操作要求(如:签名、盖章、身份证复印件等)") + private String operateRequire; + + @ExcelProperty("快递单号(仅宅急送可用)") + private String logisticCode; + + @ExcelProperty("上门揽件开始时间") + private Integer startDate; + + @ExcelProperty("上门揽件结束时间") + private Integer endDate; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("快递类型:1=标准快件") + private Integer expType; + + @ExcelProperty("是否要签回单:0=否,1=是") + private Integer isReturnSignBill; + + @ExcelProperty("发件人公司") + private String company; + + @ExcelProperty("发件人省") + private String provinceName; + + @ExcelProperty("发件人市") + private String cityName; + + @ExcelProperty("发件人区") + private String expAreaName; + + @ExcelProperty("发件人详细地址") + private String address; + + @ExcelProperty("发件人姓名") + private String name; + + @ExcelProperty("发件人电话") + private String tel; + + @ExcelProperty("发件人手机号码") + private String mobile; + + @ExcelProperty("发件地邮编") + private String postCode; + + @ExcelProperty("自定义名称") + private String title; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderExportReqVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderExportReqVO.java new file mode 100644 index 0000000..333e982 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderExportReqVO.java @@ -0,0 +1,106 @@ +package co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import co.yixiang.yshop.framework.common.pojo.PageParam; +import java.time.LocalDateTime; +import org.springframework.format.annotation.DateTimeFormat; + +import static co.yixiang.yshop.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 电子面单 Excel 导出 Request VO,参数和 ElectronicsOrderPageReqVO 是一致的") +@Data +public class ElectronicsOrderExportReqVO { + + @Schema(description = "快递公司id", example = "13715") + private Integer shipperId; + + @Schema(description = "运费支付方式:1=现付,2=到付,3=月结,4=第三方付(仅SF支持)", example = "2") + private Integer paytype; + + @Schema(description = "线下网点客户号", example = "张三") + private String customerName; + + @Schema(description = "线下网点密码") + private String customerPwd; + + @Schema(description = "网点名称") + private String sendSite; + + @Schema(description = "网点快递员") + private String sendStaff; + + @Schema(description = "月结编号") + private String monthCode; + + @Schema(description = "是否通知揽件:0=通知揽件,1=不通知揽件") + private Integer isNotice; + + @Schema(description = "是否返回电子面单模板:0=不返回,1=返回") + private Integer isReturnTemp; + + @Schema(description = "是否需要短信提醒:0=否,1=是") + private Integer isSendMessage; + + @Schema(description = "模板尺寸") + private String templateSize; + + @Schema(description = "签回单操作要求(如:签名、盖章、身份证复印件等)") + private String operateRequire; + + @Schema(description = "快递单号(仅宅急送可用)") + private String logisticCode; + + @Schema(description = "上门揽件开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private Integer[] startDate; + + @Schema(description = "上门揽件结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private Integer[] endDate; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "快递类型:1=标准快件", example = "1") + private Integer expType; + + @Schema(description = "是否要签回单:0=否,1=是") + private Integer isReturnSignBill; + + @Schema(description = "发件人公司") + private String company; + + @Schema(description = "发件人省", example = "李四") + private String provinceName; + + @Schema(description = "发件人市", example = "张三") + private String cityName; + + @Schema(description = "发件人区", example = "张三") + private String expAreaName; + + @Schema(description = "发件人详细地址") + private String address; + + @Schema(description = "发件人姓名", example = "张三") + private String name; + + @Schema(description = "发件人电话") + private String tel; + + @Schema(description = "发件人手机号码") + private String mobile; + + @Schema(description = "发件地邮编") + private String postCode; + + @Schema(description = "自定义名称") + private String title; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderPageReqVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderPageReqVO.java new file mode 100644 index 0000000..d2884d4 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderPageReqVO.java @@ -0,0 +1,108 @@ +package co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import co.yixiang.yshop.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static co.yixiang.yshop.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 电子面单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ElectronicsOrderPageReqVO extends PageParam { + + @Schema(description = "快递公司id", example = "13715") + private Integer shipperId; + + @Schema(description = "运费支付方式:1=现付,2=到付,3=月结,4=第三方付(仅SF支持)", example = "2") + private Integer paytype; + + @Schema(description = "线下网点客户号", example = "张三") + private String customerName; + + @Schema(description = "线下网点密码") + private String customerPwd; + + @Schema(description = "网点名称") + private String sendSite; + + @Schema(description = "网点快递员") + private String sendStaff; + + @Schema(description = "月结编号") + private String monthCode; + + @Schema(description = "是否通知揽件:0=通知揽件,1=不通知揽件") + private Integer isNotice; + + @Schema(description = "是否返回电子面单模板:0=不返回,1=返回") + private Integer isReturnTemp; + + @Schema(description = "是否需要短信提醒:0=否,1=是") + private Integer isSendMessage; + + @Schema(description = "模板尺寸") + private String templateSize; + + @Schema(description = "签回单操作要求(如:签名、盖章、身份证复印件等)") + private String operateRequire; + + @Schema(description = "快递单号(仅宅急送可用)") + private String logisticCode; + + @Schema(description = "上门揽件开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private Integer[] startDate; + + @Schema(description = "上门揽件结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private Integer[] endDate; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "快递类型:1=标准快件", example = "1") + private Integer expType; + + @Schema(description = "是否要签回单:0=否,1=是") + private Integer isReturnSignBill; + + @Schema(description = "发件人公司") + private String company; + + @Schema(description = "发件人省", example = "李四") + private String provinceName; + + @Schema(description = "发件人市", example = "张三") + private String cityName; + + @Schema(description = "发件人区", example = "张三") + private String expAreaName; + + @Schema(description = "发件人详细地址") + private String address; + + @Schema(description = "发件人姓名", example = "张三") + private String name; + + @Schema(description = "发件人电话") + private String tel; + + @Schema(description = "发件人手机号码") + private String mobile; + + @Schema(description = "发件地邮编") + private String postCode; + + @Schema(description = "自定义名称") + private String title; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/controller/admin/storeaftersalesitem/vo/StoreAfterSalesItemRespVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderRespVO.java similarity index 51% rename from yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/controller/admin/storeaftersalesitem/vo/StoreAfterSalesItemRespVO.java rename to yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderRespVO.java index afdf908..d14110e 100644 --- a/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/controller/admin/storeaftersalesitem/vo/StoreAfterSalesItemRespVO.java +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderRespVO.java @@ -1,19 +1,19 @@ -package co.yixiang.yshop.module.order.controller.admin.storeaftersalesitem.vo; +package co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.time.LocalDateTime; -@Schema(description = "管理后台 - 售后子 Response VO") +@Schema(description = "管理后台 - 电子面单 Response VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class StoreAfterSalesItemRespVO extends StoreAfterSalesItemBaseVO { +public class ElectronicsOrderRespVO extends ElectronicsOrderBaseVO { - @Schema(description = "主键id", required = true, example = "27129") + @Schema(description = "主键id", required = true, example = "4751") private Long id; - @Schema(description = "添加时间", required = true) + @Schema(description = "创建时间") private LocalDateTime createTime; } diff --git a/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/controller/admin/storeaftersalesitem/vo/StoreAfterSalesItemUpdateReqVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderUpdateReqVO.java similarity index 58% rename from yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/controller/admin/storeaftersalesitem/vo/StoreAfterSalesItemUpdateReqVO.java rename to yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderUpdateReqVO.java index 58c6356..033e01e 100644 --- a/yshop-module-mall/yshop-module-order-biz/src/main/java/co/yixiang/yshop/module/order/controller/admin/storeaftersalesitem/vo/StoreAfterSalesItemUpdateReqVO.java +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/electronicsorder/vo/ElectronicsOrderUpdateReqVO.java @@ -1,17 +1,17 @@ -package co.yixiang.yshop.module.order.controller.admin.storeaftersalesitem.vo; +package co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; import javax.validation.constraints.*; -@Schema(description = "管理后台 - 售后子更新 Request VO") +@Schema(description = "管理后台 - 电子面单更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class StoreAfterSalesItemUpdateReqVO extends StoreAfterSalesItemBaseVO { +public class ElectronicsOrderUpdateReqVO extends ElectronicsOrderBaseVO { - @Schema(description = "主键id", required = true, example = "27129") + @Schema(description = "主键id", required = true, example = "4751") @NotNull(message = "主键id不能为空") private Long id; diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/ExpressController.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/ExpressController.java new file mode 100644 index 0000000..9f73e48 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/ExpressController.java @@ -0,0 +1,138 @@ +package co.yixiang.yshop.module.express.controller.admin.express; + +import co.yixiang.yshop.framework.common.pojo.CommonResult; +import co.yixiang.yshop.framework.common.pojo.PageResult; +import co.yixiang.yshop.framework.excel.core.util.ExcelUtils; +import co.yixiang.yshop.framework.operatelog.core.annotations.OperateLog; +import co.yixiang.yshop.module.express.controller.admin.express.vo.*; +import co.yixiang.yshop.module.express.convert.express.ExpressConvert; +import co.yixiang.yshop.module.express.dal.dataobject.express.ExpressDO; +import co.yixiang.yshop.module.express.dal.redis.express.ExpressRedisDAO; +import co.yixiang.yshop.module.express.kdniao.model.dto.KdniaoApiBaseDTO; +import co.yixiang.yshop.module.express.kdniao.model.dto.KdniaoApiDTO; +import co.yixiang.yshop.module.express.kdniao.model.vo.KdniaoApiVO; +import co.yixiang.yshop.module.express.kdniao.util.KdniaoUtil; +import co.yixiang.yshop.module.express.service.express.ExpressService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static co.yixiang.yshop.framework.common.pojo.CommonResult.success; +import static co.yixiang.yshop.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - 快递公司") +@RestController +@RequestMapping("/order/express") +@Validated +public class ExpressController { + + @Resource + private ExpressService expressService; + @Resource + private ExpressRedisDAO expressRedisDAO; + + @PostMapping("/create") + @Operation(summary = "创建快递公司") + @PreAuthorize("@ss.hasPermission('order:express:create')") + public CommonResult createExpress(@Valid @RequestBody ExpressCreateReqVO createReqVO) { + return success(expressService.createExpress(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新快递公司") + @PreAuthorize("@ss.hasPermission('order:express:update')") + public CommonResult updateExpress(@Valid @RequestBody ExpressUpdateReqVO updateReqVO) { + expressService.updateExpress(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除快递公司") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('order:express:delete')") + public CommonResult deleteExpress(@RequestParam("id") Integer id) { + expressService.deleteExpress(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得快递公司") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('order:express:query')") + public CommonResult getExpress(@RequestParam("id") Integer id) { + ExpressDO express = expressService.getExpress(id); + return success(ExpressConvert.INSTANCE.convert(express)); + } + + @GetMapping("/list") + @Operation(summary = "获得快递公司列表") + @PreAuthorize("@ss.hasPermission('order:express:query')") + public CommonResult> getExpressList() { + List list = expressService.getExpressList(); + return success(ExpressConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得快递公司分页") + @PreAuthorize("@ss.hasPermission('order:express:query')") + public CommonResult> getExpressPage(@Valid ExpressPageReqVO pageVO) { + PageResult pageResult = expressService.getExpressPage(pageVO); + return success(ExpressConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出快递公司 Excel") + @PreAuthorize("@ss.hasPermission('order:express:export')") + @OperateLog(type = EXPORT) + public void exportExpressExcel(@Valid ExpressExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = expressService.getExpressList(exportReqVO); + // 导出 Excel + List datas = ExpressConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "快递公司.xls", "数据", ExpressExcelVO.class, datas); + } + + @GetMapping("/set") + @Operation(summary = "获得快递鸟配置") + public CommonResult getExpressSet() { + return success(expressRedisDAO.get()); + } + + @PostMapping("/set") + @Operation(summary = "获得快递鸟配置") + public CommonResult postExpressSet(@RequestBody KdniaoApiBaseDTO kdniaoApiBaseDTO) { + expressRedisDAO.set(kdniaoApiBaseDTO); + return success(true); + } + + @GetMapping("/getLogistic") + @Parameters({ + @Parameter(name = "shipperCode", description = "快递公司编码", required = true), + @Parameter(name = "logisticCode", description = "快递单号", required = true), + }) + @Operation(summary = "查询物流") + public CommonResult getLogistic(@RequestParam(value = "shipperCode") String shipperCode, + @RequestParam("logisticCode") String logisticCode) { + KdniaoApiBaseDTO kdniaoApiBaseDTO = expressRedisDAO.get(); + KdniaoApiDTO params = new KdniaoApiDTO(); + params.setLogisticCode(logisticCode); + params.setShipperCode(shipperCode); + params.setApiKey(kdniaoApiBaseDTO.getApiKey()); + params.setEBusinessID(kdniaoApiBaseDTO.getEBusinessID()); + //此处注意 这个地方分收费与免费当 目前用当免费免费当只支持圆通 申通 百世 如果是收费当 改里面RequestType参数 函数里有说明 + return success(KdniaoUtil.getLogisticInfo(params)); + } + + + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressBaseVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressBaseVO.java new file mode 100644 index 0000000..49382dd --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressBaseVO.java @@ -0,0 +1,27 @@ +package co.yixiang.yshop.module.express.controller.admin.express.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** +* 快递公司 Base VO,提供给添加、修改、详细的子 VO 使用 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 +*/ +@Data +public class ExpressBaseVO { + + @Schema(description = "快递公司简称", required = true) + @NotNull(message = "快递公司简称不能为空") + private String code; + + @Schema(description = "快递公司全称", required = true, example = "yshop") + @NotNull(message = "快递公司全称不能为空") + private String name; + + @Schema(description = "排序", required = true) + @NotNull(message = "排序不能为空") + private Integer sort; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressCreateReqVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressCreateReqVO.java new file mode 100644 index 0000000..05eba41 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressCreateReqVO.java @@ -0,0 +1,14 @@ +package co.yixiang.yshop.module.express.controller.admin.express.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 快递公司创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ExpressCreateReqVO extends ExpressBaseVO { + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressExcelVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressExcelVO.java new file mode 100644 index 0000000..0d2e4c6 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressExcelVO.java @@ -0,0 +1,31 @@ +package co.yixiang.yshop.module.express.controller.admin.express.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 快递公司 Excel VO + * + * @author yshop + */ +@Data +public class ExpressExcelVO { + + @ExcelProperty("快递公司id") + private Integer id; + + @ExcelProperty("快递公司简称") + private String code; + + @ExcelProperty("快递公司全称") + private String name; + + @ExcelProperty("排序") + private Integer sort; + + @ExcelProperty("添加时间") + private LocalDateTime createTime; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressExportReqVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressExportReqVO.java new file mode 100644 index 0000000..ecc7c86 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressExportReqVO.java @@ -0,0 +1,16 @@ +package co.yixiang.yshop.module.express.controller.admin.express.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 快递公司 Excel 导出 Request VO,参数和 ExpressPageReqVO 是一致的") +@Data +public class ExpressExportReqVO { + + @Schema(description = "快递公司简称") + private String code; + + @Schema(description = "快递公司全称", example = "yshop") + private String name; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressPageReqVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressPageReqVO.java new file mode 100644 index 0000000..81f5a59 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressPageReqVO.java @@ -0,0 +1,21 @@ +package co.yixiang.yshop.module.express.controller.admin.express.vo; + +import co.yixiang.yshop.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 快递公司分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ExpressPageReqVO extends PageParam { + + @Schema(description = "快递公司简称") + private String code; + + @Schema(description = "快递公司全称", example = "yshop") + private String name; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressRespVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressRespVO.java new file mode 100644 index 0000000..9d58c99 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressRespVO.java @@ -0,0 +1,22 @@ +package co.yixiang.yshop.module.express.controller.admin.express.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 快递公司 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ExpressRespVO extends ExpressBaseVO { + + @Schema(description = "快递公司id", required = true, example = "27172") + private Integer id; + + @Schema(description = "添加时间") + private LocalDateTime createTime; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressUpdateReqVO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressUpdateReqVO.java new file mode 100644 index 0000000..c3d67e5 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/controller/admin/express/vo/ExpressUpdateReqVO.java @@ -0,0 +1,20 @@ +package co.yixiang.yshop.module.express.controller.admin.express.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 快递公司更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ExpressUpdateReqVO extends ExpressBaseVO { + + @Schema(description = "快递公司id", required = true, example = "27172") + @NotNull(message = "快递公司id不能为空") + private Integer id; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/convert/electronicsorder/ElectronicsOrderConvert.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/convert/electronicsorder/ElectronicsOrderConvert.java new file mode 100644 index 0000000..4c329a6 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/convert/electronicsorder/ElectronicsOrderConvert.java @@ -0,0 +1,34 @@ +package co.yixiang.yshop.module.express.convert.electronicsorder; + +import java.util.*; + +import co.yixiang.yshop.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo.*; +import co.yixiang.yshop.module.express.dal.dataobject.electronicsorder.ElectronicsOrderDO; + +/** + * 电子面单 Convert + * + * @author yshop + */ +@Mapper +public interface ElectronicsOrderConvert { + + ElectronicsOrderConvert INSTANCE = Mappers.getMapper(ElectronicsOrderConvert.class); + + ElectronicsOrderDO convert(ElectronicsOrderCreateReqVO bean); + + ElectronicsOrderDO convert(ElectronicsOrderUpdateReqVO bean); + + ElectronicsOrderRespVO convert(ElectronicsOrderDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/convert/express/ExpressConvert.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/convert/express/ExpressConvert.java new file mode 100644 index 0000000..2758f4d --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/convert/express/ExpressConvert.java @@ -0,0 +1,36 @@ +package co.yixiang.yshop.module.express.convert.express; + +import co.yixiang.yshop.framework.common.pojo.PageResult; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressCreateReqVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressExcelVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressRespVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressUpdateReqVO; +import co.yixiang.yshop.module.express.dal.dataobject.express.ExpressDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 快递公司 Convert + * + * @author yshop + */ +@Mapper +public interface ExpressConvert { + + ExpressConvert INSTANCE = Mappers.getMapper(ExpressConvert.class); + + ExpressDO convert(ExpressCreateReqVO bean); + + ExpressDO convert(ExpressUpdateReqVO bean); + + ExpressRespVO convert(ExpressDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/dataobject/electronicsorder/ElectronicsOrderDO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/dataobject/electronicsorder/ElectronicsOrderDO.java new file mode 100644 index 0000000..2eabc3c --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/dataobject/electronicsorder/ElectronicsOrderDO.java @@ -0,0 +1,143 @@ +package co.yixiang.yshop.module.express.dal.dataobject.electronicsorder; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import co.yixiang.yshop.framework.mybatis.core.dataobject.BaseDO; + +/** + * 电子面单 DO + * + * @author yshop + */ +@TableName("yshop_electronics_order") +@KeySequence("yshop_electronics_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ElectronicsOrderDO extends BaseDO { + + /** + * 主键id + */ + @TableId + private Long id; + /** + * 快递公司id + */ + private Integer shipperId; + /** + * 运费支付方式:1=现付,2=到付,3=月结,4=第三方付(仅SF支持) + */ + private Integer paytype; + /** + * 线下网点客户号 + */ + private String customerName; + /** + * 线下网点密码 + */ + private String customerPwd; + /** + * 网点名称 + */ + private String sendSite; + /** + * 网点快递员 + */ + private String sendStaff; + /** + * 月结编号 + */ + private String monthCode; + /** + * 是否通知揽件:0=通知揽件,1=不通知揽件 + */ + private Integer isNotice; + /** + * 是否返回电子面单模板:0=不返回,1=返回 + */ + private Integer isReturnTemp; + /** + * 是否需要短信提醒:0=否,1=是 + */ + private Integer isSendMessage; + /** + * 模板尺寸 + */ + private String templateSize; + /** + * 签回单操作要求(如:签名、盖章、身份证复印件等) + */ + private String operateRequire; + /** + * 快递单号(仅宅急送可用) + */ + private String logisticCode; + /** + * 上门揽件开始时间 + */ + private Integer startDate; + /** + * 上门揽件结束时间 + */ + private Integer endDate; + /** + * 备注 + */ + private String remark; + /** + * 快递类型:1=标准快件 + */ + private Integer expType; + /** + * 是否要签回单:0=否,1=是 + */ + private Integer isReturnSignBill; + /** + * 发件人公司 + */ + private String company; + /** + * 发件人省 + */ + private String provinceName; + /** + * 发件人市 + */ + private String cityName; + /** + * 发件人区 + */ + private String expAreaName; + /** + * 发件人详细地址 + */ + private String address; + /** + * 发件人姓名 + */ + private String name; + /** + * 发件人电话 + */ + private String tel; + /** + * 发件人手机号码 + */ + private String mobile; + /** + * 发件地邮编 + */ + private String postCode; + /** + * 自定义名称 + */ + private String title; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/dataobject/express/ExpressDO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/dataobject/express/ExpressDO.java new file mode 100644 index 0000000..42e727c --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/dataobject/express/ExpressDO.java @@ -0,0 +1,42 @@ +package co.yixiang.yshop.module.express.dal.dataobject.express; + +import co.yixiang.yshop.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 快递公司 DO + * + * @author yshop + */ +@TableName("yshop_express") +@KeySequence("yshop_express_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ExpressDO extends BaseDO { + + /** + * 快递公司id + */ + @TableId + private Integer id; + /** + * 快递公司简称 + */ + private String code; + /** + * 快递公司全称 + */ + private String name; + /** + * 排序 + */ + private Integer sort; + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/mysql/electronicsorder/ElectronicsOrderMapper.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/mysql/electronicsorder/ElectronicsOrderMapper.java new file mode 100644 index 0000000..103c44a --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/mysql/electronicsorder/ElectronicsOrderMapper.java @@ -0,0 +1,88 @@ +package co.yixiang.yshop.module.express.dal.mysql.electronicsorder; + +import java.util.*; + +import co.yixiang.yshop.framework.common.pojo.PageResult; +import co.yixiang.yshop.framework.mybatis.core.query.LambdaQueryWrapperX; +import co.yixiang.yshop.framework.mybatis.core.mapper.BaseMapperX; +import co.yixiang.yshop.module.express.dal.dataobject.electronicsorder.ElectronicsOrderDO; +import org.apache.ibatis.annotations.Mapper; +import co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo.*; + +/** + * 电子面单 Mapper + * + * @author yshop + */ +@Mapper +public interface ElectronicsOrderMapper extends BaseMapperX { + + default PageResult selectPage(ElectronicsOrderPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ElectronicsOrderDO::getShipperId, reqVO.getShipperId()) + .eqIfPresent(ElectronicsOrderDO::getPaytype, reqVO.getPaytype()) + .likeIfPresent(ElectronicsOrderDO::getCustomerName, reqVO.getCustomerName()) + .eqIfPresent(ElectronicsOrderDO::getCustomerPwd, reqVO.getCustomerPwd()) + .eqIfPresent(ElectronicsOrderDO::getSendSite, reqVO.getSendSite()) + .eqIfPresent(ElectronicsOrderDO::getSendStaff, reqVO.getSendStaff()) + .eqIfPresent(ElectronicsOrderDO::getMonthCode, reqVO.getMonthCode()) + .eqIfPresent(ElectronicsOrderDO::getIsNotice, reqVO.getIsNotice()) + .eqIfPresent(ElectronicsOrderDO::getIsReturnTemp, reqVO.getIsReturnTemp()) + .eqIfPresent(ElectronicsOrderDO::getIsSendMessage, reqVO.getIsSendMessage()) + .eqIfPresent(ElectronicsOrderDO::getTemplateSize, reqVO.getTemplateSize()) + .eqIfPresent(ElectronicsOrderDO::getOperateRequire, reqVO.getOperateRequire()) + .eqIfPresent(ElectronicsOrderDO::getLogisticCode, reqVO.getLogisticCode()) + .betweenIfPresent(ElectronicsOrderDO::getStartDate, reqVO.getStartDate()) + .betweenIfPresent(ElectronicsOrderDO::getEndDate, reqVO.getEndDate()) + .eqIfPresent(ElectronicsOrderDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ElectronicsOrderDO::getExpType, reqVO.getExpType()) + .eqIfPresent(ElectronicsOrderDO::getIsReturnSignBill, reqVO.getIsReturnSignBill()) + .eqIfPresent(ElectronicsOrderDO::getCompany, reqVO.getCompany()) + .likeIfPresent(ElectronicsOrderDO::getProvinceName, reqVO.getProvinceName()) + .likeIfPresent(ElectronicsOrderDO::getCityName, reqVO.getCityName()) + .likeIfPresent(ElectronicsOrderDO::getExpAreaName, reqVO.getExpAreaName()) + .eqIfPresent(ElectronicsOrderDO::getAddress, reqVO.getAddress()) + .likeIfPresent(ElectronicsOrderDO::getName, reqVO.getName()) + .eqIfPresent(ElectronicsOrderDO::getTel, reqVO.getTel()) + .eqIfPresent(ElectronicsOrderDO::getMobile, reqVO.getMobile()) + .eqIfPresent(ElectronicsOrderDO::getPostCode, reqVO.getPostCode()) + .eqIfPresent(ElectronicsOrderDO::getTitle, reqVO.getTitle()) + .betweenIfPresent(ElectronicsOrderDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ElectronicsOrderDO::getId)); + } + + default List selectList(ElectronicsOrderExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(ElectronicsOrderDO::getShipperId, reqVO.getShipperId()) + .eqIfPresent(ElectronicsOrderDO::getPaytype, reqVO.getPaytype()) + .likeIfPresent(ElectronicsOrderDO::getCustomerName, reqVO.getCustomerName()) + .eqIfPresent(ElectronicsOrderDO::getCustomerPwd, reqVO.getCustomerPwd()) + .eqIfPresent(ElectronicsOrderDO::getSendSite, reqVO.getSendSite()) + .eqIfPresent(ElectronicsOrderDO::getSendStaff, reqVO.getSendStaff()) + .eqIfPresent(ElectronicsOrderDO::getMonthCode, reqVO.getMonthCode()) + .eqIfPresent(ElectronicsOrderDO::getIsNotice, reqVO.getIsNotice()) + .eqIfPresent(ElectronicsOrderDO::getIsReturnTemp, reqVO.getIsReturnTemp()) + .eqIfPresent(ElectronicsOrderDO::getIsSendMessage, reqVO.getIsSendMessage()) + .eqIfPresent(ElectronicsOrderDO::getTemplateSize, reqVO.getTemplateSize()) + .eqIfPresent(ElectronicsOrderDO::getOperateRequire, reqVO.getOperateRequire()) + .eqIfPresent(ElectronicsOrderDO::getLogisticCode, reqVO.getLogisticCode()) + .betweenIfPresent(ElectronicsOrderDO::getStartDate, reqVO.getStartDate()) + .betweenIfPresent(ElectronicsOrderDO::getEndDate, reqVO.getEndDate()) + .eqIfPresent(ElectronicsOrderDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ElectronicsOrderDO::getExpType, reqVO.getExpType()) + .eqIfPresent(ElectronicsOrderDO::getIsReturnSignBill, reqVO.getIsReturnSignBill()) + .eqIfPresent(ElectronicsOrderDO::getCompany, reqVO.getCompany()) + .likeIfPresent(ElectronicsOrderDO::getProvinceName, reqVO.getProvinceName()) + .likeIfPresent(ElectronicsOrderDO::getCityName, reqVO.getCityName()) + .likeIfPresent(ElectronicsOrderDO::getExpAreaName, reqVO.getExpAreaName()) + .eqIfPresent(ElectronicsOrderDO::getAddress, reqVO.getAddress()) + .likeIfPresent(ElectronicsOrderDO::getName, reqVO.getName()) + .eqIfPresent(ElectronicsOrderDO::getTel, reqVO.getTel()) + .eqIfPresent(ElectronicsOrderDO::getMobile, reqVO.getMobile()) + .eqIfPresent(ElectronicsOrderDO::getPostCode, reqVO.getPostCode()) + .eqIfPresent(ElectronicsOrderDO::getTitle, reqVO.getTitle()) + .betweenIfPresent(ElectronicsOrderDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ElectronicsOrderDO::getId)); + } + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/mysql/express/ExpressMapper.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/mysql/express/ExpressMapper.java new file mode 100644 index 0000000..976b7f4 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/mysql/express/ExpressMapper.java @@ -0,0 +1,35 @@ +package co.yixiang.yshop.module.express.dal.mysql.express; + +import co.yixiang.yshop.framework.common.pojo.PageResult; +import co.yixiang.yshop.framework.mybatis.core.mapper.BaseMapperX; +import co.yixiang.yshop.framework.mybatis.core.query.LambdaQueryWrapperX; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressExportReqVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressPageReqVO; +import co.yixiang.yshop.module.express.dal.dataobject.express.ExpressDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 快递公司 Mapper + * + * @author yshop + */ +@Mapper +public interface ExpressMapper extends BaseMapperX { + + default PageResult selectPage(ExpressPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ExpressDO::getCode, reqVO.getCode()) + .likeIfPresent(ExpressDO::getName, reqVO.getName()) + .orderByDesc(ExpressDO::getId)); + } + + default List selectList(ExpressExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(ExpressDO::getCode, reqVO.getCode()) + .likeIfPresent(ExpressDO::getName, reqVO.getName()) + .orderByDesc(ExpressDO::getId)); + } + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/redis/RedisKeyConstants.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/redis/RedisKeyConstants.java new file mode 100644 index 0000000..b8163ed --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/redis/RedisKeyConstants.java @@ -0,0 +1,23 @@ +package co.yixiang.yshop.module.express.dal.redis; + +import co.yixiang.yshop.framework.redis.core.RedisKeyDefine; +import co.yixiang.yshop.module.express.kdniao.model.dto.KdniaoApiBaseDTO; + +import static co.yixiang.yshop.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; + +/** + * System Redis Key 枚举类 + * + * @author yshop + */ +public interface RedisKeyConstants { + + + RedisKeyDefine YSHOP_EXPRESS_CACHE_KEY = new RedisKeyDefine("快递鸟配置", + "yshop_express_cache:", // + STRING, KdniaoApiBaseDTO.class, RedisKeyDefine.TimeoutTypeEnum.FOREVER); + + + + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/redis/express/ExpressRedisDAO.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/redis/express/ExpressRedisDAO.java new file mode 100644 index 0000000..e260249 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/dal/redis/express/ExpressRedisDAO.java @@ -0,0 +1,46 @@ +package co.yixiang.yshop.module.express.dal.redis.express; + +import co.yixiang.yshop.framework.common.util.json.JsonUtils; +import co.yixiang.yshop.module.express.kdniao.model.dto.KdniaoApiBaseDTO; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import javax.annotation.Resource; + +import static co.yixiang.yshop.module.express.dal.redis.RedisKeyConstants.YSHOP_EXPRESS_CACHE_KEY; + + +/** + * {@link KdniaoApiBaseDTO} 的 RedisDAO + * + * @author yshop + */ +@Repository +public class ExpressRedisDAO { + + @Resource + private StringRedisTemplate stringRedisTemplate; + + + public KdniaoApiBaseDTO get() { + String redisKey = YSHOP_EXPRESS_CACHE_KEY.getKeyTemplate(); + return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), KdniaoApiBaseDTO.class); + } + + public void set(KdniaoApiBaseDTO apiBaseDTO) { + String redisKey = YSHOP_EXPRESS_CACHE_KEY.getKeyTemplate(); + stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(apiBaseDTO)); + } + + public void delete() { + String redisKey =YSHOP_EXPRESS_CACHE_KEY.getKeyTemplate(); + stringRedisTemplate.delete(redisKey); + } + + + + private static String formatKey() { + return String.format(YSHOP_EXPRESS_CACHE_KEY.getKeyTemplate()); + } + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/electronicsorder/ElectronicsOrderService.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/electronicsorder/ElectronicsOrderService.java new file mode 100644 index 0000000..f3efd58 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/electronicsorder/ElectronicsOrderService.java @@ -0,0 +1,70 @@ +package co.yixiang.yshop.module.express.service.electronicsorder; + +import java.util.*; +import javax.validation.*; +import co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo.*; +import co.yixiang.yshop.module.express.dal.dataobject.electronicsorder.ElectronicsOrderDO; +import co.yixiang.yshop.framework.common.pojo.PageResult; + +/** + * 电子面单 Service 接口 + * + * @author yshop + */ +public interface ElectronicsOrderService { + + /** + * 创建电子面单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createElectronicsOrder(@Valid ElectronicsOrderCreateReqVO createReqVO); + + /** + * 更新电子面单 + * + * @param updateReqVO 更新信息 + */ + void updateElectronicsOrder(@Valid ElectronicsOrderUpdateReqVO updateReqVO); + + /** + * 删除电子面单 + * + * @param id 编号 + */ + void deleteElectronicsOrder(Long id); + + /** + * 获得电子面单 + * + * @param id 编号 + * @return 电子面单 + */ + ElectronicsOrderDO getElectronicsOrder(Long id); + + /** + * 获得电子面单列表 + * + * @param ids 编号 + * @return 电子面单列表 + */ + List getElectronicsOrderList(); + + /** + * 获得电子面单分页 + * + * @param pageReqVO 分页查询 + * @return 电子面单分页 + */ + PageResult getElectronicsOrderPage(ElectronicsOrderPageReqVO pageReqVO); + + /** + * 获得电子面单列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 电子面单列表 + */ + List getElectronicsOrderList(ElectronicsOrderExportReqVO exportReqVO); + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/electronicsorder/ElectronicsOrderServiceImpl.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/electronicsorder/ElectronicsOrderServiceImpl.java new file mode 100644 index 0000000..ec6289d --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/electronicsorder/ElectronicsOrderServiceImpl.java @@ -0,0 +1,82 @@ +package co.yixiang.yshop.module.express.service.electronicsorder; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; + +import java.util.*; +import co.yixiang.yshop.module.express.controller.admin.electronicsorder.vo.*; +import co.yixiang.yshop.module.express.dal.dataobject.electronicsorder.ElectronicsOrderDO; +import co.yixiang.yshop.framework.common.pojo.PageResult; + +import co.yixiang.yshop.module.express.convert.electronicsorder.ElectronicsOrderConvert; +import co.yixiang.yshop.module.express.dal.mysql.electronicsorder.ElectronicsOrderMapper; + +import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception; +import static co.yixiang.yshop.module.express.enums.ErrorCodeConstants.*; + +/** + * 电子面单 Service 实现类 + * + * @author yshop + */ +@Service +@Validated +public class ElectronicsOrderServiceImpl implements ElectronicsOrderService { + + @Resource + private ElectronicsOrderMapper electronicsOrderMapper; + + @Override + public Long createElectronicsOrder(ElectronicsOrderCreateReqVO createReqVO) { + // 插入 + ElectronicsOrderDO electronicsOrder = ElectronicsOrderConvert.INSTANCE.convert(createReqVO); + electronicsOrderMapper.insert(electronicsOrder); + // 返回 + return electronicsOrder.getId(); + } + + @Override + public void updateElectronicsOrder(ElectronicsOrderUpdateReqVO updateReqVO) { + // 校验存在 + validateElectronicsOrderExists(updateReqVO.getId()); + // 更新 + ElectronicsOrderDO updateObj = ElectronicsOrderConvert.INSTANCE.convert(updateReqVO); + electronicsOrderMapper.updateById(updateObj); + } + + @Override + public void deleteElectronicsOrder(Long id) { + // 校验存在 + validateElectronicsOrderExists(id); + // 删除 + electronicsOrderMapper.deleteById(id); + } + + private void validateElectronicsOrderExists(Long id) { + if (electronicsOrderMapper.selectById(id) == null) { + throw exception(ELECTRONICS_ORDER_NOT_EXISTS); + } + } + + @Override + public ElectronicsOrderDO getElectronicsOrder(Long id) { + return electronicsOrderMapper.selectById(id); + } + + @Override + public List getElectronicsOrderList() { + return electronicsOrderMapper.selectList(); + } + + @Override + public PageResult getElectronicsOrderPage(ElectronicsOrderPageReqVO pageReqVO) { + return electronicsOrderMapper.selectPage(pageReqVO); + } + + @Override + public List getElectronicsOrderList(ElectronicsOrderExportReqVO exportReqVO) { + return electronicsOrderMapper.selectList(exportReqVO); + } + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/express/ExpressService.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/express/ExpressService.java new file mode 100644 index 0000000..e0585c0 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/express/ExpressService.java @@ -0,0 +1,74 @@ +package co.yixiang.yshop.module.express.service.express; + +import co.yixiang.yshop.framework.common.pojo.PageResult; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressCreateReqVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressExportReqVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressPageReqVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressUpdateReqVO; +import co.yixiang.yshop.module.express.dal.dataobject.express.ExpressDO; + + +import javax.validation.Valid; +import java.util.List; + +/** + * 快递公司 Service 接口 + * + * @author yshop + */ +public interface ExpressService { + + /** + * 创建快递公司 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Integer createExpress(@Valid ExpressCreateReqVO createReqVO); + + /** + * 更新快递公司 + * + * @param updateReqVO 更新信息 + */ + void updateExpress(@Valid ExpressUpdateReqVO updateReqVO); + + /** + * 删除快递公司 + * + * @param id 编号 + */ + void deleteExpress(Integer id); + + /** + * 获得快递公司 + * + * @param id 编号 + * @return 快递公司 + */ + ExpressDO getExpress(Integer id); + + /** + * 获得快递公司列表 + * + * @return 快递公司列表 + */ + List getExpressList(); + + /** + * 获得快递公司分页 + * + * @param pageReqVO 分页查询 + * @return 快递公司分页 + */ + PageResult getExpressPage(ExpressPageReqVO pageReqVO); + + /** + * 获得快递公司列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 快递公司列表 + */ + List getExpressList(ExpressExportReqVO exportReqVO); + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/express/ExpressServiceImpl.java b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/express/ExpressServiceImpl.java new file mode 100644 index 0000000..b3edb08 --- /dev/null +++ b/yshop-module-express/yshop-module-express-biz/src/main/java/co/yixiang/yshop/module/express/service/express/ExpressServiceImpl.java @@ -0,0 +1,85 @@ +package co.yixiang.yshop.module.express.service.express; + +import co.yixiang.yshop.framework.common.pojo.PageResult; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressCreateReqVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressExportReqVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressPageReqVO; +import co.yixiang.yshop.module.express.controller.admin.express.vo.ExpressUpdateReqVO; +import co.yixiang.yshop.module.express.convert.express.ExpressConvert; +import co.yixiang.yshop.module.express.dal.dataobject.express.ExpressDO; +import co.yixiang.yshop.module.express.dal.mysql.express.ExpressMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception; +import static co.yixiang.yshop.module.express.enums.ErrorCodeConstants.EXPRESS_NOT_EXISTS; + + +/** + * 快递公司 Service 实现类 + * + * @author yshop + */ +@Service +@Validated +public class ExpressServiceImpl implements ExpressService { + + @Resource + private ExpressMapper expressMapper; + + @Override + public Integer createExpress(ExpressCreateReqVO createReqVO) { + // 插入 + ExpressDO express = ExpressConvert.INSTANCE.convert(createReqVO); + expressMapper.insert(express); + // 返回 + return express.getId(); + } + + @Override + public void updateExpress(ExpressUpdateReqVO updateReqVO) { + // 校验存在 + validateExpressExists(updateReqVO.getId()); + // 更新 + ExpressDO updateObj = ExpressConvert.INSTANCE.convert(updateReqVO); + expressMapper.updateById(updateObj); + } + + @Override + public void deleteExpress(Integer id) { + // 校验存在 + validateExpressExists(id); + // 删除 + expressMapper.deleteById(id); + } + + private void validateExpressExists(Integer id) { + if (expressMapper.selectById(id) == null) { + throw exception(EXPRESS_NOT_EXISTS); + } + } + + @Override + public ExpressDO getExpress(Integer id) { + return expressMapper.selectById(id); + } + + @Override + public List getExpressList() { + return expressMapper.selectList(); + } + + @Override + public PageResult getExpressPage(ExpressPageReqVO pageReqVO) { + return expressMapper.selectPage(pageReqVO); + } + + @Override + public List getExpressList(ExpressExportReqVO exportReqVO) { + return expressMapper.selectList(exportReqVO); + } + +} diff --git a/yshop-module-express/yshop-module-express-biz/src/main/resources/.DS_Store b/yshop-module-express/yshop-module-express-biz/src/main/resources/.DS_Store new file mode 100644 index 0000000..c1e09fa Binary files /dev/null and b/yshop-module-express/yshop-module-express-biz/src/main/resources/.DS_Store differ diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/ConfigController.java b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/ConfigController.java index fa119b0..20cc2ee 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/ConfigController.java +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/ConfigController.java @@ -69,7 +69,7 @@ public class ConfigController { @GetMapping(value = "/get-value-by-key") @Operation(summary = "根据参数键名查询参数值", description = "不可见的配置,不允许返回给前端") - @Parameter(name = "key", description = "参数键", required = true, example = "yunai.biz.username") + @Parameter(name = "key", description = "参数键", required = true, example = "yshop.biz.username") public CommonResult getConfigKey(@RequestParam("key") String key) { ConfigDO config = configService.getConfigByKey(key); if (config == null) { diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java index 9d182d2..d6ae9c5 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java @@ -12,7 +12,7 @@ import javax.validation.constraints.Size; @EqualsAndHashCode(callSuper = true) public class ConfigCreateReqVO extends ConfigBaseVO { - @Schema(description = "参数键名", required = true, example = "yunai.db.username") + @Schema(description = "参数键名", required = true, example = "yshop.db.username") @NotBlank(message = "参数键名长度不能为空") @Size(max = 100, message = "参数键名长度不能超过100个字符") private String key; diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigExportReqVO.java b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigExportReqVO.java index 3454bd8..416a034 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigExportReqVO.java +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigExportReqVO.java @@ -15,7 +15,7 @@ public class ConfigExportReqVO { @Schema(description = "参数名称", example = "模糊匹配") private String name; - @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username") + @Schema(description = "参数键名,模糊匹配", example = "yshop.db.username") private String key; @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1") diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigPageReqVO.java b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigPageReqVO.java index 3e40ecb..eb1ffd9 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigPageReqVO.java +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigPageReqVO.java @@ -20,7 +20,7 @@ public class ConfigPageReqVO extends PageParam { @Schema(description = "数据源名称,模糊匹配", example = "名称") private String name; - @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username") + @Schema(description = "参数键名,模糊匹配", example = "yshop.db.username") private String key; @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1") diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigRespVO.java b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigRespVO.java index e772021..259eac9 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigRespVO.java +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/config/vo/ConfigRespVO.java @@ -16,7 +16,7 @@ public class ConfigRespVO extends ConfigBaseVO { @Schema(description = "参数配置序号", required = true, example = "1024") private Long id; - @Schema(description = "参数键名", required = true, example = "yunai.db.username") + @Schema(description = "参数键名", required = true, example = "yshop.db.username") @NotBlank(message = "参数键名长度不能为空") @Size(max = 100, message = "参数键名长度不能超过100个字符") private String key; diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java index c76be1e..a0596ef 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java @@ -14,7 +14,7 @@ public class DataSourceConfigBaseVO { @NotNull(message = "数据源名称不能为空") private String name; - @Schema(description = "数据源连接", required = true, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro") + @Schema(description = "数据源连接", required = true, example = "jdbc:mysql://127.0.0.1:3306/yshop-pro") @NotNull(message = "数据源连接不能为空") private String url; diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/file/FileConfigController.http b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/file/FileConfigController.http deleted file mode 100644 index 85d6d66..0000000 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/file/FileConfigController.http +++ /dev/null @@ -1,45 +0,0 @@ -### 请求 /infra/file-config/create 接口 => 成功 -POST {{baseUrl}}/infra/file-config/create -Content-Type: application/json -tenant-id: {{adminTenentId}} -Authorization: Bearer {{token}} - -{ - "name": "S3 - 七牛云", - "remark": "", - "storage": 20, - "config": { - "accessKey": "b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8", - "accessSecret": "kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP", - "bucket": "ruoyi-vue-pro", - "endpoint": "s3-cn-south-1.qiniucs.com", - "domain": "http://test.yshop.iocoder.cn", - "region": "oss-cn-beijing" - } -} - -### 请求 /infra/file-config/update 接口 => 成功 -PUT {{baseUrl}}/infra/file-config/update -Content-Type: application/json -tenant-id: {{adminTenentId}} -Authorization: Bearer {{token}} - -{ - "id": 2, - "name": "S3 - 七牛云", - "remark": "", - "config": { - "accessKey": "b7yvuhBSAGjmtPhMFcn9iMOxUOY_I06cA_p0ZUx8", - "accessSecret": "kXM1l5ia1RvSX3QaOEcwI3RLz3Y2rmNszWonKZtP", - "bucket": "ruoyi-vue-pro", - "endpoint": "s3-cn-south-1.qiniucs.com", - "domain": "http://test.yshop.iocoder.cn", - "region": "oss-cn-beijing" - } -} - -### 请求 /infra/file-config/test 接口 => 成功 -GET {{baseUrl}}/infra/file-config/test?id=2 -Content-Type: application/json -tenant-id: {{adminTenentId}} -Authorization: Bearer {{token}} diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/file/vo/file/FileRespVO.java b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/file/vo/file/FileRespVO.java index 690e6dd..e0707c7 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/file/vo/file/FileRespVO.java +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/file/vo/file/FileRespVO.java @@ -21,7 +21,7 @@ public class FileRespVO { @Schema(description = "原文件名", required = true, example = "yshop.jpg") private String name; - @Schema(description = "文件 URL", required = true, example = "https://www.iocoder.cn/yshop.jpg") + @Schema(description = "文件 URL", required = true, example = "yshop.jpg") private String url; @Schema(description = "文件MIME类型", example = "application/octet-stream") diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/redis/RedisController.http b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/redis/RedisController.http deleted file mode 100644 index 0310dea..0000000 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/redis/RedisController.http +++ /dev/null @@ -1,9 +0,0 @@ -### 请求 /infra/redis/get-monitor-info 接口 => 成功 -GET {{baseUrl}}/infra/redis/get-monitor-info -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} - -### 请求 /infra/redis/get-key-list 接口 => 成功 -GET {{baseUrl}}/infra/redis/get-key-list -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/test/TestDemoController.http b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/test/TestDemoController.http deleted file mode 100644 index ed65d0b..0000000 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/controller/admin/test/TestDemoController.http +++ /dev/null @@ -1,19 +0,0 @@ -### 请求 /infra/test-demo/get 接口 => 成功 -GET {{baseUrl}}/infra/test-demo/get?id=106 -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} - -### 请求 /infra/test-demo/update 接口 => 成功 -PUT {{baseUrl}}/infra/test-demo/update -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} -Content-Type: application/json - - -{ - "id": 106, - "name": "测试", - "status": "0", - "type": 1, - "category": 1 -} diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md deleted file mode 100644 index 0ee6cf6..0000000 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md deleted file mode 100644 index 378c612..0000000 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/service/codegen/inner/CodegenBuilder.java b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/service/codegen/inner/CodegenBuilder.java index c3d5794..52cf0b2 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/service/codegen/inner/CodegenBuilder.java +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/java/co/yixiang/yshop/module/infra/service/codegen/inner/CodegenBuilder.java @@ -195,7 +195,7 @@ public class CodegenBuilder { } // url if (StrUtil.endWithIgnoreCase(column.getColumnName(), "url")) { - column.setExample("https://www.iocoder.cn"); + column.setExample("https://www.yixiang.co"); return; } // reason diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/resources/codegen/java/dal/mapper.xml.vm b/yshop-module-infra/yshop-module-infra-biz/src/main/resources/codegen/java/dal/mapper.xml.vm index d930db9..c1544ad 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/resources/codegen/java/dal/mapper.xml.vm +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/resources/codegen/java/dal/mapper.xml.vm @@ -6,7 +6,7 @@ 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。 无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。 代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。 - 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ + 文档可见:https://www.yixiang.co/MyBatis/x-plugins/ --> diff --git a/yshop-module-infra/yshop-module-infra-biz/src/main/resources/mapper/test/TestDemoMapper.xml b/yshop-module-infra/yshop-module-infra-biz/src/main/resources/mapper/test/TestDemoMapper.xml index e50a462..38fc902 100644 --- a/yshop-module-infra/yshop-module-infra-biz/src/main/resources/mapper/test/TestDemoMapper.xml +++ b/yshop-module-infra/yshop-module-infra-biz/src/main/resources/mapper/test/TestDemoMapper.xml @@ -6,7 +6,7 @@ 一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。 无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。 代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。 - 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ + 文档可见:https://www.yixiang.co/MyBatis/x-plugins/ -->