diff --git a/README.md b/README.md index 5b4229e..6859fbc 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,124 @@ ### 配置 #### 微信支付 在Spring Boot项目中的`application.yaml`中配置`wechat.pay`相关参数。 -启用`@EnableWechatPay`注解 +```yaml +wechat: + pay: + v3: +# 沙盒模式 默认不开启 用于开发测试 + sandbox-mode: true +# 服务商模式 默认不开启 + partner-mode: false +# 应用appId 必填 + app-id: wx55a75ae9fd5d3b98 +# api 密钥 必填 + app-secret: Djkjchina19491001 +# api v3 密钥 必填 + app-v3-secret: 0e5f4fac75b2dc7a3b44927e455703ec +# 微信支付商户号 必填 + mch-id: 1603257459 +# 合作商 选填 + partner-key: +# 商户服务器域名 用于回调 需要放开回调接口的安全策略 必填 + domain: https://127.0.0.1 +# 商户 api 证书 必填 + cert-path: apiclient_cert.p12 +``` +然后启用`@EnableWechatPay`注解: +```java +@EnableMobilePay +@Configuration +public class PayConfig { +} +``` ### API使用 -施工中…… +微信支付 V2、V3开放接口引入: +```java + @Autowired + WechatPayV3Service wechatPayV3Service; + @Autowired + WechatPayV2Service wechatPayV2Service; +``` +#### V2 +例如V2转账到微信零钱: +```java + PayToWechatModel model = new PayToWechatModel(); + model.setDesc("test"); + model.setAmount("10000"); + model.setDeviceInfo("IOS"); + model.setOpenid("wx1232131231256655"); + model.setPartnerTradeNo("X323994343345"); + model.setSpbillCreateIp("127.0.0.1"); + WechatResponseBody responseBody = wechatPayV2Service.model(model) + .payType(V2PayType.PAY_TO_WECHAT) + .request(); + System.out.println("responseBody = " + responseBody); +``` +打印返回: +``` + +``` + + +#### V3 +例如V3 APP 支付 + +```java + /** + * App pay test. + */ + @Test + public void appPayTest() { + wechatPayV3Service + .request(baseModel -> new V3PayTypeBodyAndConsumer(V3PayType.APP, + baseModel.jsonBody() + ,System.out::println)) + .withModel(appPayModel()); + } + + + + /** + * 构造参数 + */ + private static AppPayModel appPayModel() { + AppPayModel appPayModel = new AppPayModel(); + + appPayModel.setGoodsTag("WXG"); + appPayModel.setNotifyUrl("/callback/app"); + appPayModel.setDescription("中国移动-手机充值"); + appPayModel.setOutTradeNo("100862342355223"); + + Amount amount = new Amount(); + amount.setTotal(1000); + appPayModel.setAmount(amount); + + SceneInfo sceneInfo = new SceneInfo(); + + sceneInfo.setDeviceId("12312"); + sceneInfo.setPayerClientIp("129.122.0.1"); + + StoreInfo storeInfo = new StoreInfo(); + storeInfo.setAddress("cn"); + storeInfo.setAreaCode("471800"); + storeInfo.setId("232313213"); + storeInfo.setName("jack"); + + sceneInfo.setStoreInfo(storeInfo); + + H5Info h5Info = new H5Info(); + + h5Info.setAppName("APP"); + h5Info.setAppUrl("https://felord"); + h5Info.setBundleId("1313213"); + h5Info.setPackageName("com.dj"); + h5Info.setType("IOS"); + +// sceneInfo.setH5Info(h5Info); + + appPayModel.setSceneInfo(sceneInfo); + return appPayModel; + } +``` ## CHANGELOG diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/EnableWechatPay.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/EnableMobilePay.java similarity index 77% rename from payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/EnableWechatPay.java rename to payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/EnableMobilePay.java index a358227..89df301 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/EnableWechatPay.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/EnableMobilePay.java @@ -11,6 +11,6 @@ import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import(WechatPayConfiguration.class) -public @interface EnableWechatPay { +@Import(PayConfiguration.class) +public @interface EnableMobilePay { } diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/PayConfiguration.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/PayConfiguration.java new file mode 100644 index 0000000..d8deaeb --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/PayConfiguration.java @@ -0,0 +1,80 @@ +package com.enongm.dianji.payment.autoconfigure; + +import com.enongm.dianji.payment.wechat.v2.WechatPayV2Service; +import com.enongm.dianji.payment.wechat.v3.KeyPairFactory; +import com.enongm.dianji.payment.wechat.v3.SignatureProvider; +import com.enongm.dianji.payment.wechat.v3.WechatPayV3Service; +import com.enongm.dianji.payment.wechat.v3.model.WechatMetaBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Dax + * @since 14:47 + */ +@Configuration + +public class PayConfiguration { + /** + * The type Wechat pay configuration. + */ + @Configuration + @ConditionalOnProperty(prefix = "wechat.pay", name = "v3.app-id") + @EnableConfigurationProperties(WechatPayProperties.class) + static class WechatPayConfiguration { + private static final String CERT_ALIAS = "Tenpay Certificate"; + + /** + * 微信支付公私钥 以及序列号等元数据. + * + * @param wechatPayProperties the wechat pay properties + * @return the wechat cert bean + */ + @Bean + WechatMetaBean wechatMetaBean(WechatPayProperties wechatPayProperties) { + + String certPath = wechatPayProperties.getV3().getCertPath(); + String mchId = wechatPayProperties.getV3().getMchId(); + WechatMetaBean wechatMetaBean = new KeyPairFactory().createPKCS12(certPath, CERT_ALIAS, mchId); + wechatMetaBean.setWechatPayProperties(wechatPayProperties); + return wechatMetaBean; + } + + /** + * 微信支付V3签名工具. + * + * @param wechatMetaBean the wechat meta bean + * @return the signature provider + */ + @Bean + SignatureProvider signatureProvider(WechatMetaBean wechatMetaBean) { + return new SignatureProvider(wechatMetaBean); + } + + + /** + * 微信支付V2 只实现V3支付没有的支付业务。 + * + * @param wechatPayProperties the wechat pay properties + * @return the wechat pay v 2 service + */ + @Bean + public WechatPayV2Service wechatPayV2Service(WechatPayProperties wechatPayProperties) { + System.out.println("wechatPayProperties = " + wechatPayProperties); + return new WechatPayV2Service(wechatPayProperties); + } + + /** + * 微信支付V3 全量支持. + * + * @param signatureProvider the signature provider + * @return the wechat pay service + */ + @Bean + public WechatPayV3Service wechatPayService(SignatureProvider signatureProvider) { + return new WechatPayV3Service(signatureProvider); + } + } +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/WechatPayConfiguration.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/WechatPayConfiguration.java deleted file mode 100644 index f2871b1..0000000 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/WechatPayConfiguration.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.enongm.dianji.payment.autoconfigure; - - -import com.enongm.dianji.payment.wechat.v3.KeyPairFactory; -import com.enongm.dianji.payment.wechat.v3.WechatPayV3Service; -import com.enongm.dianji.payment.wechat.v2.WechatPayV2Service; -import com.enongm.dianji.payment.wechat.v3.SignatureProvider; -import com.enongm.dianji.payment.wechat.v3.model.WechatMetaBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * The type Wechat pay configuration. - */ -@Configuration -@EnableConfigurationProperties(WechatPayProperties.class) -public class WechatPayConfiguration { - private static final String CERT_ALIAS = "Tenpay Certificate"; - - /** - * 微信支付公私钥 以及序列号等元数据. - * - * @param wechatPayProperties the wechat pay properties - * @return the wechat cert bean - */ - @Bean - WechatMetaBean wechatMetaBean(WechatPayProperties wechatPayProperties) { - - String certPath = wechatPayProperties.getV3().getCertPath(); - String mchId = wechatPayProperties.getV3().getMchId(); - WechatMetaBean wechatMetaBean = new KeyPairFactory().createPKCS12(certPath, CERT_ALIAS, mchId); - wechatMetaBean.setWechatPayProperties(wechatPayProperties); - return wechatMetaBean; - } - - /** - * 微信支付V3签名工具. - * - * @param wechatMetaBean the wechat meta bean - * @return the signature provider - */ - @Bean - SignatureProvider signatureProvider(WechatMetaBean wechatMetaBean) { - return new SignatureProvider(wechatMetaBean); - } - - - /** - * 微信支付V2 只实现V3支付没有的支付业务。 - * - * @param wechatPayProperties the wechat pay properties - * @return the wechat pay v 2 service - */ - @Bean - public WechatPayV2Service wechatPayV2Service(WechatPayProperties wechatPayProperties) { - System.out.println("wechatPayProperties = " + wechatPayProperties); - return new WechatPayV2Service(wechatPayProperties); - } - - /** - * 微信支付V3 全量支持. - * - * @param signatureProvider the signature provider - * @return the wechat pay service - */ - @Bean - public WechatPayV3Service wechatPayService(SignatureProvider signatureProvider) { - return new WechatPayV3Service(signatureProvider); - } -} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/WechatPayProperties.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/WechatPayProperties.java index 965d467..995d731 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/WechatPayProperties.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/autoconfigure/WechatPayProperties.java @@ -18,6 +18,14 @@ public class WechatPayProperties { @Data public static class V3 { + /** + * set as true in develop mode + */ + private boolean sandboxMode; + /** + * set as true in partner mode + */ + private boolean partnerMode; /** * app id for wechat pay is required */ diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v2/model/BaseModel.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v2/model/BaseModel.java index 9c5647d..e5076ae 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v2/model/BaseModel.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v2/model/BaseModel.java @@ -56,6 +56,10 @@ public class BaseModel { private String appSecret; @JsonIgnore private V2PayType payType; + @JsonIgnore + private final WeChatServer weChatServer = WeChatServer.CHINA; + private boolean sandboxMode; + private boolean partnerMode; public BaseModel appId(String appId) { @@ -136,9 +140,16 @@ public class BaseModel { @SneakyThrows public WechatResponseBody request() { Assert.notNull(payType, "wechat pay payType is required"); + + String url = payType.defaultUri(this.weChatServer); + if (sandboxMode) { + url = partnerMode ? this.payType.partnerSandboxUri(this.weChatServer) : + this.payType.defaultSandboxUri(this.weChatServer); + } + Request request = new Request.Builder() .method(payType.method(), RequestBody.create(MediaType.parse("application/x-www-form-urlencoded"), this.xml())) - .url(payType.defaultUri(WeChatServer.CHINA)) + .url(url) .build(); System.out.println("request.toString() = " + request.toString()); Response response = CLIENT.newCall(request).execute(); diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/V3PayTypeBodyAndConsumer.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/V3PayTypeBodyAndConsumer.java new file mode 100644 index 0000000..7b10a08 --- /dev/null +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/V3PayTypeBodyAndConsumer.java @@ -0,0 +1,33 @@ +package com.enongm.dianji.payment.wechat.v3; + +import com.enongm.dianji.payment.wechat.enumeration.V3PayType; + +import java.util.function.Consumer; + +/** + * @author Dax + * @since 15:27 + */ +public class V3PayTypeBodyAndConsumer { + private final V3PayType payType; + private final String jsonBody; + private final Consumer responseBodyConsumer; + + public V3PayTypeBodyAndConsumer(V3PayType payType, String jsonBody, Consumer responseBodyConsumer) { + this.payType = payType; + this.jsonBody = jsonBody; + this.responseBodyConsumer = responseBodyConsumer; + } + + public V3PayType getPayType() { + return payType; + } + + public String getJsonBody() { + return jsonBody; + } + + public Consumer getResponseBodyConsumer() { + return responseBodyConsumer; + } +} diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayRequest.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayRequest.java index 2d7e3e9..230849f 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayRequest.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayRequest.java @@ -18,6 +18,8 @@ import java.util.function.Consumer; @Getter public class WechatPayRequest { private V3PayType v3PayType; + private boolean isSandbox; + private boolean isPartner; private WeChatServer weChatServer; private String body; private final Map headers = new HashMap<>(); @@ -35,6 +37,28 @@ public class WechatPayRequest { return this; } + /** + * Is sandbox wechat pay request. + * + * @param isSandbox the is sandbox + * @return the wechat pay request + */ + public WechatPayRequest isSandbox(boolean isSandbox) { + this.isSandbox = isSandbox; + return this; + } + + /** + * Is partner wechat pay request. + * + * @param isPartner the is partner + * @return the wechat pay request + */ + public WechatPayRequest isPartner(boolean isPartner) { + this.isPartner = isPartner; + return this; + } + /** * We chat server. * @@ -85,6 +109,10 @@ public class WechatPayRequest { * @return the string */ public String url() { + if (isSandbox) { + return isPartner ? this.v3PayType.partnerSandboxUri(this.weChatServer): + this.v3PayType.defaultSandboxUri(this.weChatServer); + } return this.v3PayType.defaultUri(this.weChatServer); } diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayV3Service.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayV3Service.java index b12d934..fd831e3 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayV3Service.java +++ b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/WechatPayV3Service.java @@ -2,10 +2,7 @@ package com.enongm.dianji.payment.wechat.v3; -import com.enongm.dianji.payment.wechat.v3.filter.BodyMergeFilter; -import com.enongm.dianji.payment.wechat.v3.filter.HeaderFilter; -import com.enongm.dianji.payment.wechat.v3.filter.HttpRequestFilter; -import com.enongm.dianji.payment.wechat.v3.filter.WechatServerFilter; +import com.enongm.dianji.payment.wechat.v3.filter.*; import com.enongm.dianji.payment.wechat.v3.model.BaseModel; import com.enongm.dianji.payment.wechat.v3.model.WechatMetaBean; @@ -57,7 +54,7 @@ public class WechatPayV3Service { * @param requestFunction the request function * @return the executor */ - public Executor request(Function requestFunction) { + public Executor request(Function requestFunction) { return new Executor<>(this.payFilterChain, requestFunction); } @@ -68,7 +65,7 @@ public class WechatPayV3Service { * @param the type parameter * @param the type parameter */ - public static class Executor { + public static class Executor { /** * The Pay filter chain. */ @@ -95,7 +92,11 @@ public class WechatPayV3Service { * @param model the model */ public void withModel(M model) { - payFilterChain.doChain(requestFunction.apply(model)); + R apply = requestFunction.apply(model); + WechatPayRequest wechatPayRequest = new WechatPayRequest().v3PayType(apply.getPayType()) + .body(apply.getJsonBody()) + .responseConsumer(apply.getResponseBodyConsumer()); + payFilterChain.doChain(wechatPayRequest); } } diff --git a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/service/WechatPayV3Api.java b/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/service/WechatPayV3Api.java deleted file mode 100644 index d76fa03..0000000 --- a/payment-spring-boot-autoconfigure/src/main/java/com/enongm/dianji/payment/wechat/v3/service/WechatPayV3Api.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.enongm.dianji.payment.wechat.v3.service; - - -import com.enongm.dianji.payment.wechat.enumeration.V3PayType; -import com.enongm.dianji.payment.wechat.v3.WechatPayRequest; -import com.enongm.dianji.payment.wechat.v3.model.AppPayModel; - -/** - * The type Wechat pay v 3 api. - * - * @author Dax - * @since 17 :47 - */ -public class WechatPayV3Api { - - /** - * APP 支付. - * - * @param appPayModel the app pay model - * @return the wechat pay request - */ - public static WechatPayRequest appPay(AppPayModel appPayModel) { - - return new WechatPayRequest().responseConsumer(System.out::println) - // 如果需要支持容灾 需要对server 进行一些处理 - .v3PayType(V3PayType.APP) - .body(appPayModel.jsonBody()); - } - - -}