From 3c07c9f5c6a1f2bef49c20f2c38e825aed92f94c Mon Sep 17 00:00:00 2001 From: HH Date: Fri, 25 Mar 2022 19:29:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E5=B0=8F=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E6=8E=A5=E5=8F=A3=E5=92=8CAdapay=E5=9B=9E?= =?UTF-8?q?=E8=B0=83=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ghy-common/pom.xml | 29 ++++++++ .../adapay/AdapayAutoConfiguration.java | 22 ++++++ .../ghy/common/adapay/AdapayProperties.java | 58 +++++++++++++++ .../com/ghy/common/adapay/AdapayService.java | 43 +++++++++++ .../java/com/ghy/common/adapay/EventEnum.java | 49 +++++++++++++ .../com/ghy/common/adapay/PayChannelEnum.java | 28 ++++++++ .../ghy/common/adapay/PayResultMapping.java | 40 +++++++++++ .../callback/AdapayCallbackController.java | 71 +++++++++++++++++++ .../com/ghy/common/adapay/callback/Event.java | 40 +++++++++++ .../common/adapay/callback/PayCallback.java | 13 ++++ pom.xml | 28 ++++++++ 11 files changed, 421 insertions(+) create mode 100644 ghy-common/src/main/java/com/ghy/common/adapay/AdapayAutoConfiguration.java create mode 100644 ghy-common/src/main/java/com/ghy/common/adapay/AdapayProperties.java create mode 100644 ghy-common/src/main/java/com/ghy/common/adapay/AdapayService.java create mode 100644 ghy-common/src/main/java/com/ghy/common/adapay/EventEnum.java create mode 100644 ghy-common/src/main/java/com/ghy/common/adapay/PayChannelEnum.java create mode 100644 ghy-common/src/main/java/com/ghy/common/adapay/PayResultMapping.java create mode 100644 ghy-common/src/main/java/com/ghy/common/adapay/callback/AdapayCallbackController.java create mode 100644 ghy-common/src/main/java/com/ghy/common/adapay/callback/Event.java create mode 100644 ghy-common/src/main/java/com/ghy/common/adapay/callback/PayCallback.java diff --git a/ghy-common/pom.xml b/ghy-common/pom.xml index 968f3cdb..a1029ff3 100644 --- a/ghy-common/pom.xml +++ b/ghy-common/pom.xml @@ -116,6 +116,35 @@ javax.servlet-api + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + com.huifu.adapay.core + adapay-core-sdk + + + com.huifu.adapay + adapay-java-sdk + + + + + org.apache.httpcomponents + httpmime + + + + + org.apache.httpcomponents + httpclient + + \ No newline at end of file diff --git a/ghy-common/src/main/java/com/ghy/common/adapay/AdapayAutoConfiguration.java b/ghy-common/src/main/java/com/ghy/common/adapay/AdapayAutoConfiguration.java new file mode 100644 index 00000000..64c69c72 --- /dev/null +++ b/ghy-common/src/main/java/com/ghy/common/adapay/AdapayAutoConfiguration.java @@ -0,0 +1,22 @@ +package com.ghy.common.adapay; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Adapay 自动装载 + * + * @author HH 2022/3/25 + */ +@Configuration +@EnableConfigurationProperties(AdapayProperties.class) +public class AdapayAutoConfiguration { + + @Bean + public AdapayService adapayService(AdapayProperties adapayProperties) { + AdapayService adapayService = new AdapayService(); + adapayService.setAdapayProperties(adapayProperties); + return adapayService; + } +} \ No newline at end of file diff --git a/ghy-common/src/main/java/com/ghy/common/adapay/AdapayProperties.java b/ghy-common/src/main/java/com/ghy/common/adapay/AdapayProperties.java new file mode 100644 index 00000000..19583146 --- /dev/null +++ b/ghy-common/src/main/java/com/ghy/common/adapay/AdapayProperties.java @@ -0,0 +1,58 @@ +package com.ghy.common.adapay; + +import com.huifu.adapay.Adapay; +import com.huifu.adapay.model.MerConfig; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.util.Assert; + +/** + * Adapay 配置类 + * + * @author HH 2022/3/25 + */ +@Data +@Slf4j +@ConfigurationProperties("adapay") +public class AdapayProperties implements InitializingBean { + + /** + * 是否打印调用日志,默认不打印 + */ + private boolean debug = false; + + /** + * 是否是prod_mode 默认为 true + */ + private boolean prodMode = true; + + private String appId; + private String notifyUrl; + + /** + * 初始化商户配置,服务器启动前,必须通过该方式初始化商户配置完成 + * apiKey为prod模式的API KEY + * mockApiKey为mock模式的API KEY + * rsaPrivateKey为商户发起请求时,用于请求参数加签所需要的RSA私钥 + */ + private String apiKey; + private String mockApiKey; + private String rsaPrivateKey; + + @Override + public void afterPropertiesSet() throws Exception { + log.info("Adapay.debug={}, Adapay.prodMode={}", debug, prodMode); + Assert.hasText(appId, "Adapay.appId is blank!"); + Assert.hasText(apiKey, "Adapay.apiKey is blank!"); + Assert.hasText(mockApiKey, "Adapay.mockApiKey is blank!"); + Assert.hasText(rsaPrivateKey, "Adapay.rsaPrivateKey is blank!"); + + MerConfig merConfig = new MerConfig(); + merConfig.setApiKey(apiKey); + merConfig.setApiMockKey(mockApiKey); + merConfig.setRSAPrivateKey(rsaPrivateKey); + Adapay.initWithMerConfig(merConfig); + } +} \ No newline at end of file diff --git a/ghy-common/src/main/java/com/ghy/common/adapay/AdapayService.java b/ghy-common/src/main/java/com/ghy/common/adapay/AdapayService.java new file mode 100644 index 00000000..82e4f35a --- /dev/null +++ b/ghy-common/src/main/java/com/ghy/common/adapay/AdapayService.java @@ -0,0 +1,43 @@ +package com.ghy.common.adapay; + +import com.ghy.common.adapay.callback.PayCallback; +import com.huifu.adapay.core.exception.BaseAdaPayException; +import com.huifu.adapay.model.Payment; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author HH 2022/3/25 + */ +@Slf4j +@Setter +public class AdapayService { + + AdapayProperties adapayProperties; + + /** + * @param callback 处理支付结果的回调接口 + * @param orderNo 订单号 + * @param payAmt 支付金额 + * @param goodsTittle 商品名称 + * @param goodsDesc 商品描述 + * @param description 订单附加说明 + */ + public Map wxLitePay(PayCallback callback, String orderNo, String payAmt, String goodsTittle, String goodsDesc, String description) throws BaseAdaPayException { + Map paymentParams = new HashMap<>(10); + paymentParams.put("app_id", adapayProperties.getAppId()); + paymentParams.put("notify_url", adapayProperties.getNotifyUrl()); + paymentParams.put("order_no", orderNo); + paymentParams.put("pay_channel", PayChannelEnum.WX_LITE.getCode()); + paymentParams.put("pay_amt", payAmt); + paymentParams.put("goods_title", goodsTittle); + paymentParams.put("goods_desc", goodsDesc); + paymentParams.put("description", description); + PayResultMapping.putCallback(orderNo, callback); + return Payment.create(paymentParams); + } + +} \ No newline at end of file diff --git a/ghy-common/src/main/java/com/ghy/common/adapay/EventEnum.java b/ghy-common/src/main/java/com/ghy/common/adapay/EventEnum.java new file mode 100644 index 00000000..3fbe34de --- /dev/null +++ b/ghy-common/src/main/java/com/ghy/common/adapay/EventEnum.java @@ -0,0 +1,49 @@ +package com.ghy.common.adapay; + +/** + * Event时间枚举 + * + * @author HH 2022/3/25 + */ +public enum EventEnum { + + PAY_SUCCEEDED("payment.succeeded", "支付成功"), + PAY_FAILED("payment.failed", "支付失败"), + + PAY_CLOSE_SUCCEEDED("payment.close.succeeded", "关闭支付订单成功"), + PAY_CLOSE_FAILED("payment.close.failed", "关闭支付订单失败"), + + REFUND_SUCCEEDED("refund.succeeded", "退款成功"), + REFUND_FAILED("refund.failed", "退款失败"), + + CORP_MEMBER_SUCCEEDED("corp_member.succeeded", "开户成功"), + CORP_MEMBER_FAILED("corp_member.failed", "开户失败"), + + PAYMENT_REVERSE_SUCCEEDED("payment_reverse.succeeded", "支付撤销成功"), + PAYMENT_REVERSE_FAILED("payment_reverse.failed", "支付撤销失败"), + + CASH_SUCCEEDED("cash.succeeded", "取现成功"), + CASH_FAILED("cash.failed", "取现失败"), + + ACCOUNT_PAYMENT_SUCCEEDED("account_payment.succeeded", "钱包支付成功"), + ACCOUNT_PAYMENT_FAILED("account_payment.failed", "钱包支付失败"), + + FASTPAY_SUCCEEDED("fastpay.succeeded", "快捷支付成功"), + FASTPAY_FAILED("fastpay.failed", "快捷支付失败"); + + private final String type; + private final String description; + + EventEnum(String type, String description) { + this.type = type; + this.description = description; + } + + public String getType() { + return type; + } + + public String getDescription() { + return description; + } +} diff --git a/ghy-common/src/main/java/com/ghy/common/adapay/PayChannelEnum.java b/ghy-common/src/main/java/com/ghy/common/adapay/PayChannelEnum.java new file mode 100644 index 00000000..dd3189a1 --- /dev/null +++ b/ghy-common/src/main/java/com/ghy/common/adapay/PayChannelEnum.java @@ -0,0 +1,28 @@ +package com.ghy.common.adapay; + +/** + * 支付渠道 + * + * @author HH 2022/3/25 + */ +public enum PayChannelEnum { + + ALIPAY_QR("alipay_qr", "支付宝正扫"), + WX_LITE("wx_lite", "wx_lite"); + + private final String code; + private final String description; + + PayChannelEnum(String code, String description) { + this.code = code; + this.description = description; + } + + public String getCode() { + return code; + } + + public String getDescription() { + return description; + } +} diff --git a/ghy-common/src/main/java/com/ghy/common/adapay/PayResultMapping.java b/ghy-common/src/main/java/com/ghy/common/adapay/PayResultMapping.java new file mode 100644 index 00000000..4b13ce03 --- /dev/null +++ b/ghy-common/src/main/java/com/ghy/common/adapay/PayResultMapping.java @@ -0,0 +1,40 @@ +package com.ghy.common.adapay; + +import com.alibaba.fastjson.JSON; +import com.ghy.common.adapay.callback.Event; +import com.ghy.common.adapay.callback.PayCallback; +import com.huifu.adapay.model.Payment; +import org.springframework.util.Assert; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * 支付结果匹配池 + * + * @author HH 2022/3/25 + */ +public class PayResultMapping { + + /** + * 临时保存支付结果 + * key: orderNo + * value: 处理支付结果的回调接口 + */ + private final static ConcurrentHashMap PAY_RESULT_CALLBACK_MAP = new ConcurrentHashMap<>(1024); + + public static void putResult(Event event) { + String data = event.getData(); + Payment payment = JSON.parseObject(data, Payment.class); + Assert.hasText(payment.getOrderNo(), "orderNo is blank !!!"); + PayCallback callback = PAY_RESULT_CALLBACK_MAP.remove(payment.getOrderNo()); + if (callback != null) { + callback.onResponse(payment); + } + } + + public static void putCallback(String orderNo, PayCallback callback) { + Assert.hasText(orderNo, "orderNo is blank !!!"); + Assert.notNull(callback, "PayCallback is null !!!"); + PAY_RESULT_CALLBACK_MAP.put(orderNo, callback); + } +} diff --git a/ghy-common/src/main/java/com/ghy/common/adapay/callback/AdapayCallbackController.java b/ghy-common/src/main/java/com/ghy/common/adapay/callback/AdapayCallbackController.java new file mode 100644 index 00000000..c5eebe74 --- /dev/null +++ b/ghy-common/src/main/java/com/ghy/common/adapay/callback/AdapayCallbackController.java @@ -0,0 +1,71 @@ +package com.ghy.common.adapay.callback; + +import com.ghy.common.adapay.PayResultMapping; +import com.huifu.adapay.core.AdapayCore; +import com.huifu.adapay.core.util.AdapaySign; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 提供给 Adapay 的回调接口 + * + * @author HH 2022/3/25 + */ +@Slf4j +@RestController +public class AdapayCallbackController { + + @PostMapping("/adapay/callback") + public String callback(@RequestBody Event event) { + //验签请参data + String data = event.getData(); + //验签请参sign + String sign = event.getSign(); + boolean verifySign = false; + try { + verifySign = verifySign(data, sign); + } catch (Exception e) { + log.error("签名验证失败 {}", e.getMessage()); + } + if (verifySign) { + //Event事件类型 + String type = event.getType(); + if (StringUtils.isBlank(type)) { + return "NG"; + } + switch (type) { + case "payment.succeeded": + case "payment.failed": + PayResultMapping.putResult(event); + break; + default: + log.warn("UNKNOWN EVENT TYPE [{}]", type); + return "NG"; + } + return "OK"; + } + log.warn("签名验证失败 data=[{}], sign=[{}]", data, sign); + return "NG"; + } + + /** + * 校验签名 + * + * @param data AdapayCallback.data + * @param sign AdapayCallback.sign + * @return TRUE=校验成功 + */ + private boolean verifySign(String data, String sign) throws Exception { + Assert.hasText(data, "data is blank!"); + Assert.hasText(sign, "sign is blank!"); + //验签请参publicKey + String publicKey = AdapayCore.PUBLIC_KEY; + log.debug("验签请参:data={}sign={}", data, sign); + //验签 + return AdapaySign.verifySign(data, sign, publicKey); + } +} diff --git a/ghy-common/src/main/java/com/ghy/common/adapay/callback/Event.java b/ghy-common/src/main/java/com/ghy/common/adapay/callback/Event.java new file mode 100644 index 00000000..269d7949 --- /dev/null +++ b/ghy-common/src/main/java/com/ghy/common/adapay/callback/Event.java @@ -0,0 +1,40 @@ +package com.ghy.common.adapay.callback; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +/** + * 支付结果 + * + * @author HH 2022/3/25 + */ +@Data +public class Event { + + /** + * 由 Adapay 生成的支付对象 id, 该 id 在 Adapay 系统内唯一 + */ + private String id; + /** + * 签名 + */ + private String sign; + /** + * 支付创建时的 10 位时间戳 + */ + @JSONField(name = "created_time") + private Long createdTime; + /** + * 是否 prod模式,true 是 prod模式,false 是 mock模式 + */ + @JSONField(name = "created_time") + private String prodMode; + /** + * Event 事件类型 + */ + private String type; + /** + * 支付对象 + */ + private String data; +} \ No newline at end of file diff --git a/ghy-common/src/main/java/com/ghy/common/adapay/callback/PayCallback.java b/ghy-common/src/main/java/com/ghy/common/adapay/callback/PayCallback.java new file mode 100644 index 00000000..35800b94 --- /dev/null +++ b/ghy-common/src/main/java/com/ghy/common/adapay/callback/PayCallback.java @@ -0,0 +1,13 @@ +package com.ghy.common.adapay.callback; + +import com.huifu.adapay.model.Payment; + +/** + * 处理支付结果的回调接口 + * + * @author HH 2022/3/25 + */ +public interface PayCallback { + + void onResponse(Payment payment); +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 8002d1f6..855ff8ce 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,8 @@ 7.4.0 2.8.5 0.4.3 + 1.2.10 + 4.5.13 @@ -199,6 +201,32 @@ ${fastjson.version} + + + com.huifu.adapay.core + adapay-core-sdk + ${Adapay.version} + + + com.huifu.adapay + adapay-java-sdk + ${Adapay.version} + + + + + org.apache.httpcomponents + httpmime + ${httpcomponents.version} + + + + + org.apache.httpcomponents + httpclient + ${httpcomponents.version} + + org.apache.logging.log4j