diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml index 4cc0eed0b..68b29bea0 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml @@ -19,6 +19,16 @@ yudao-common + + + jakarta.validation + jakarta.validation-api + + + org.hibernate.validator + hibernate-validator + + com.github.javen205 @@ -30,5 +40,6 @@ IJPay-WxPay 2.7.8 + diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/AbstractPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/AbstractPayClient.java deleted file mode 100644 index 7d42e9ffc..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/AbstractPayClient.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.framework.pay.core.client; - -import cn.iocoder.yudao.framework.pay.core.PayClient; -import com.alipay.api.DefaultAlipayClient; - -/** - * 支付客户端的抽象类,提供模板方法,减少子类的冗余代码 - * - * @author 芋道源码 - */ -public abstract class AbstractPayClient implements PayClient { - - - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/PayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java similarity index 50% rename from yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/PayClient.java rename to yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java index 42004ec78..37367a387 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/PayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java @@ -1,6 +1,7 @@ -package cn.iocoder.yudao.framework.pay.core; +package cn.iocoder.yudao.framework.pay.core.client; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; /** * 支付客户端,用于对接各支付渠道的 SDK,实现发起支付、退款等功能 @@ -9,6 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; */ public interface PayClient { - CommonResult unifiedOrder(); + // TODO 缺少注释 + CommonResult unifiedOrder(PayOrderUnifiedReqDTO reqDTO); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/PayClientConfig.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientConfig.java similarity index 79% rename from yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/PayClientConfig.java rename to yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientConfig.java index 0cc5378ca..4b7ff57b1 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/PayClientConfig.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientConfig.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.pay.core; +package cn.iocoder.yudao.framework.pay.core.client; /** * 支付客户端的配置,本质是支付渠道的配置 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayCodeMapping.java new file mode 100644 index 000000000..42238af77 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayCodeMapping.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.framework.pay.core.client; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.yudao.framework.pay.core.enums.PayFrameworkErrorCodeConstants; + +import java.util.function.Function; + +/** + * 将 API 的错误码,转换为通用的错误码 + * + * @see PayCommonResult + * @see PayFrameworkErrorCodeConstants + * + * @author 芋道源码 + */ +public interface PayCodeMapping extends Function { +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayCommonResult.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayCommonResult.java new file mode 100644 index 000000000..8346a845f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayCommonResult.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.framework.pay.core.client; + +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.pay.core.enums.PayFrameworkErrorCodeConstants; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * 支付的 CommonResult 拓展类 + * + * 考虑到不同的平台,返回的 code 和 msg 是不同的,所以统一额外返回 {@link #apiCode} 和 {@link #apiMsg} 字段 + * + * @author 芋道源码 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class PayCommonResult extends CommonResult { + + /** + * API 返回错误码 + * + * 由于第三方的错误码可能是字符串,所以使用 String 类型 + */ + private String apiCode; + /** + * API 返回提示 + */ + private String apiMsg; + + private PayCommonResult() { + } + + public static PayCommonResult build(String apiCode, String apiMsg, T data, PayCodeMapping codeMapping) { + Assert.notNull(codeMapping, "参数 codeMapping 不能为空"); + PayCommonResult result = new PayCommonResult().setApiCode(apiCode).setApiMsg(apiMsg); + result.setData(data); + // 翻译错误码 + if (codeMapping != null) { + ErrorCode errorCode = codeMapping.apply(apiCode); + if (errorCode == null) { + errorCode = PayFrameworkErrorCodeConstants.EXCEPTION; + } + result.setCode(errorCode.getCode()).setMsg(errorCode.getMsg()); + } + return result; + } + + public static PayCommonResult error(Throwable ex) { + PayCommonResult result = new PayCommonResult<>(); + result.setCode(PayFrameworkErrorCodeConstants.EXCEPTION.getCode()); + result.setMsg(ExceptionUtil.getRootCauseMessage(ex)); + return result; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/alipay/AlipayPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/alipay/AlipayPayClient.java deleted file mode 100644 index 8de2fea9c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/alipay/AlipayPayClient.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.framework.pay.core.client.alipay; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.pay.core.client.AbstractPayClient; -import com.alipay.api.AlipayApiException; -import com.alipay.api.DefaultAlipayClient; -import com.alipay.api.domain.AlipayTradePrecreateModel; -import com.alipay.api.request.AlipayTradePrecreateRequest; -import com.alipay.api.response.AlipayTradePrecreateResponse; - -/** - * 支付宝的 PayClient 实现类 - */ -public class AlipayPayClient extends AbstractPayClient { - - private DefaultAlipayClient client = new DefaultAlipayClient("https://openapi.alipaydev.com/gateway.do","2021000118634035","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=","json","utf-8","MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnq90KnF4dTnlzzmxpujbI05OYqi5WxAS6cL0gnZFv2gK51HExF8v/BaP7P979PhFMgWTqmOOI+Dtno5s+yD09XTY1WkshbLk6i4g2Xlr8fyW9ODnkU88RI2w9UdPhQU4cPPwBNlrsYhKkVK2OxwM3kFqjoBBY0CZoZCsSQ3LDH5WeZqPArlsS6xa2zqJBuuoKjMrdpELl3eXSjP8K54eDJCbeetCZNKWLL3DPahTPB7LZikfYmslb0QUvCgGapD0xkS7eVq70NaL1G57MWABs4tbfWgxike4Daj3EfUrzIVspQxj7w8HEj9WozJPgL88kSJSits0pqD3n5r8HSuseQIDAQAB","RSA2"); - - @Override - public CommonResult unifiedOrder() { - AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); - AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); - request.setBizModel(model); - model.setOutTradeNo(String.valueOf(System.currentTimeMillis())); - model.setTotalAmount("88.88"); - model.setSubject("Iphone6 16G"); - AlipayTradePrecreateResponse response = null; - try { - response = client.execute(request); - } catch (AlipayApiException e) { - e.printStackTrace(); - } - System.out.println(response.getBody()); - System.out.println(response.getQrCode()); - return null; - } - - public static void main(String[] args) { - AlipayPayClient client = new AlipayPayClient(); - client.unifiedOrder(); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java new file mode 100644 index 000000000..9e1f0412e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.framework.pay.core.client.dto; + +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.DecimalMin; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + * 统一下单 Request DTO + */ +@Data +public class PayOrderUnifiedReqDTO { + + /** + * 客户端 IP + */ + @NotEmpty(message = "客户端 IP 不能为空") + private String clientIp; + + // ========== 商户相关字段 ========== + + /** + * 商户订单编号 + */ + @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; + + // ========== 订单相关字段 ========== + + /** + * 支付金额,单位:分 + */ + @NotNull(message = "支付金额不能为空") + @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零") + private Integer amount; + + /** + * 支付过期时间 + */ + @NotNull(message = "支付过期时间不能为空") + private Date expireTime; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java new file mode 100644 index 000000000..4034a4a6f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.pay.core.client.impl; + +import cn.iocoder.yudao.framework.pay.core.client.PayClient; +import cn.iocoder.yudao.framework.pay.core.client.PayCodeMapping; + +/** + * 支付客户端的抽象类,提供模板方法,减少子类的冗余代码 + * + * @author 芋道源码 + */ +public abstract class AbstractPayClient implements PayClient { + + /** + * 错误码枚举类 + */ + protected PayCodeMapping codeMapping; + + protected Double calculateAmount(Integer amount) { + return amount / 100.0; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayClient.java new file mode 100644 index 000000000..7513d2039 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayClient.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; + +import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; +import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; +import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; +import com.alipay.api.AlipayApiException; +import com.alipay.api.AlipayConfig; +import com.alipay.api.DefaultAlipayClient; +import com.alipay.api.domain.AlipayTradePrecreateModel; +import com.alipay.api.request.AlipayTradePrecreateRequest; +import com.alipay.api.response.AlipayTradePrecreateResponse; +import lombok.SneakyThrows; + +/** + * 支付宝的 PayClient 实现类 + */ +public class AlipayPayClient extends AbstractPayClient { + + private final DefaultAlipayClient client; + + @SneakyThrows + public AlipayPayClient(AlipayPayConfig config) { + // 创建 DefaultAlipayClient 对象 + AlipayConfig alipayConfig = new AlipayConfig(); + BeanUtil.copyProperties(config, alipayConfig, false); + this.client = new DefaultAlipayClient(alipayConfig); + + // 创建 AlipayPayCodeMapping 对象 + super.codeMapping = new AlipayPayCodeMapping(); + } + + // TODO 芋艿:暂时是扫码支付,需要调整成 wap https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay + @Override + public CommonResult unifiedOrder(PayOrderUnifiedReqDTO reqDTO) { + // 构建 AlipayTradePrecreateModel 请求 + AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); + model.setOutTradeNo(reqDTO.getMerchantOrderId()); + model.setSubject(reqDTO.getSubject()); + model.setBody(reqDTO.getBody()); + model.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString()); + // TODO 芋艿:clientIp + expireTime + // 构建 AlipayTradePrecreateRequest + AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); + request.setBizModel(model); + + // 执行请求 + AlipayTradePrecreateResponse response = null; + try { + response = client.execute(request); + } catch (AlipayApiException e) { + return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping); + } + + System.out.println(response.getBody()); + System.out.println(response.getQrCode()); + + // TODO 芋艿:sub Code + return PayCommonResult.build(response.getCode(), response.getMsg(), response, codeMapping); + } + + public static void main(String[] args) { + AlipayPayConfig config = new AlipayPayConfig(); + config.setAppId("2021000118634035"); + config.setServerUrl(AlipayPayConfig.SERVER_URL_SANDBOX); + config.setSignType(AlipayPayConfig.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"); + AlipayPayClient client = new AlipayPayClient(config); + + PayOrderUnifiedReqDTO reqDTO = new PayOrderUnifiedReqDTO(); + reqDTO.setAmount(123); + reqDTO.setSubject("IPhone 13"); + reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis())); + client.unifiedOrder(reqDTO); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayCodeMapping.java new file mode 100644 index 000000000..a61a8cce1 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayCodeMapping.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; +import cn.iocoder.yudao.framework.pay.core.client.PayCodeMapping; + +public class AlipayPayCodeMapping implements PayCodeMapping { + + @Override + public ErrorCode apply(String s) { + return null; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/alipay/AlipayPayConfig.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayConfig.java similarity index 84% rename from yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/alipay/AlipayPayConfig.java rename to yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayConfig.java index 722efedd1..8b36e8aac 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/alipay/AlipayPayConfig.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayConfig.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.pay.core.client.alipay; +package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; import lombok.Data; @@ -15,11 +15,11 @@ public class AlipayPayConfig { /** * 网关地址 - 线上 */ - private static final String SERVER_URL_PROD = "https://openapi.alipay.com/gateway.do"; + public static final String SERVER_URL_PROD = "https://openapi.alipay.com/gateway.do"; /** * 网关地址 - 沙箱 */ - private static final String SERVER_URL_SANDBOX = "https://openapi.alipay.com/gateway.do"; + public static final String SERVER_URL_SANDBOX = "https://openapi.alipaydev.com/gateway.do"; /** * 公钥类型 - 公钥模式 @@ -33,7 +33,7 @@ public class AlipayPayConfig { /** * 签名算法类型 - RSA */ - private static final String SIGN_TYPE_DEFAULT = "RSA2"; + public static final String SIGN_TYPE_DEFAULT = "RSA2"; /** * 网关地址 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/package-info.java deleted file mode 100644 index 0b5348f1f..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.framework.pay.core.client; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayFrameworkErrorCodeConstants.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayFrameworkErrorCodeConstants.java new file mode 100644 index 000000000..524653911 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayFrameworkErrorCodeConstants.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.framework.pay.core.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * 支付框架的错误码枚举 + * + * 短信框架,使用 2-002-000-000 段 + * + * @author 芋道源码 + */ +public interface PayFrameworkErrorCodeConstants { + + ErrorCode PAY_UNKNOWN = new ErrorCode(2001000000, "未知错误,需要解析"); + +// // ========== 权限 / 限流等相关 2001000100 ========== +// +// ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限"); +// // 云片:可以配置 IP 白名单,只有在白名单中才可以发送短信 +// ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信"); +// +// // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 +// ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2001000102, "指定手机的发送限流"); +// // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。 +// ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2001000103, "每天的发送限流"); +// +// ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2001000104, "短信内容有敏感词"); +// +// // ========== 模板相关 2001000200 ========== +// ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2001000200, "短信模板不合法"); // 包括短信模板不存在 +// ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2001000201, "模板参数不正确"); +// +// // ========== 签名相关 2001000300 ========== +// ErrorCode SMS_SIGN_INVALID = new ErrorCode(2001000300, "短信签名不可用"); +// +// // ========== 账户相关 2001000400 ========== +// ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2001000400, "账户余额不足"); +// ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2001000401, "apiKey 不存在"); +// +// // ========== 其它相关 2001000900 开头 ========== +// ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2001000900, "请求参数缺失"); +// ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2001000901, "手机格式不正确"); +// ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2001000902, "手机号在黑名单中"); + + ErrorCode EXCEPTION = new ErrorCode(2002000999, "调用异常"); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java index 8adff8f60..9867e08db 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/yunpian/YunpianSmsClient.java @@ -83,7 +83,8 @@ public class YunpianSmsClient extends AbstractSmsClient { } // 参考 https://www.yunpian.com/official/document/sms/zh_cn/introduction_demos_encode_sample 格式化 StringJoiner joiner = new StringJoiner("&"); - templateParams.forEach(param -> joiner.add(String.format("#%s#=%s", param.getKey(), URLUtil.encode(String.valueOf(param.getValue()))))); + templateParams.forEach(param -> joiner.add(String.format("#%s#=%s", param.getKey(), + URLUtil.encode(String.valueOf(param.getValue()))))); return joiner.toString(); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiErrorLogCreateDTO.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiErrorLogCreateDTO.java index 51258d735..dac55e569 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiErrorLogCreateDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/dto/ApiErrorLogCreateDTO.java @@ -4,7 +4,6 @@ import lombok.Data; import lombok.experimental.Accessors; import javax.validation.constraints.NotNull; -import java.io.Serializable; import java.util.Date; /** @@ -14,7 +13,7 @@ import java.util.Date; */ @Data @Accessors(chain = true) -public class ApiErrorLogCreateDTO implements Serializable { +public class ApiErrorLogCreateDTO { /** * 链路编号