diff --git a/_license/LICENSE.md b/_license/LICENSE.md index aed2e432..0a680ef7 100644 --- a/_license/LICENSE.md +++ b/_license/LICENSE.md @@ -44,3 +44,6 @@ https://gitee.com/dromara/easy_trans vue3-vant4-mobile Vant4脚手架: https://github.com/xiangshu233/vue3-vant4-mobile + +全能第三方支付对接Java开发工具包: +https://gitee.com/egzosn/pay-java-parent diff --git a/_license/pay-java-parent/LICENSE b/_license/pay-java-parent/LICENSE new file mode 100644 index 00000000..9e66ea75 --- /dev/null +++ b/_license/pay-java-parent/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "{}" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright 2017 egan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/PayCallbackController.java b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/PayCallbackController.java index 0baac59a..bae29e2b 100644 --- a/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/PayCallbackController.java +++ b/daxpay-single/daxpay-single-gateway/src/main/java/cn/bootx/platform/daxpay/gateway/controller/PayCallbackController.java @@ -4,6 +4,8 @@ import cn.bootx.platform.common.core.annotation.IgnoreAuth; import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayCallbackService; import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayCallbackService; import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPayCallbackService; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; +import com.egzosn.pay.union.api.UnionPayConfigStorage; import com.ijpay.alipay.AliPayApi; import com.ijpay.core.kit.HttpKit; import com.ijpay.core.kit.WxPayKit; @@ -55,12 +57,14 @@ public class PayCallbackController { return weChatPayCallbackService.callback(params); } + @SuppressWarnings({"unchecked", "rawtypes"}) @SneakyThrows @Operation(summary = "云闪付支付信息回调") @PostMapping("/union") public String unionPayNotify(HttpServletRequest request) { - String xmlMsg = HttpKit.readData(request); - Map params = WxPayKit.xmlToMap(xmlMsg); - return unionPayCallbackService.callback(params); + UnionPayKit unionPayKit = new UnionPayKit(new UnionPayConfigStorage()); + // 实际返回的是 Map 格式数据 + Map parameter2Map = unionPayKit.getParameter2Map(request.getParameterMap(), request.getInputStream()); + return unionPayCallbackService.callback(parameter2Map); } } diff --git a/daxpay-single/daxpay-single-service/pom.xml b/daxpay-single/daxpay-single-service/pom.xml index e3d81187..f24b058b 100644 --- a/daxpay-single/daxpay-single-service/pom.xml +++ b/daxpay-single/daxpay-single-service/pom.xml @@ -100,11 +100,11 @@ ${wxjava.version} - + - com.github.javen205 - IJPay-UnionPay - ${IJPay.version} + com.egzosn + pay-java-union + ${egzosn-java.version} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/UnionPayCode.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/UnionPayCode.java index 7813fd1a..81e245e5 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/UnionPayCode.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/UnionPayCode.java @@ -64,4 +64,7 @@ public interface UnionPayCode { String ERR_MSG = "err_msg"; + /** 对账单下载类型编码 */ + String RECONCILE_BILL_TYPE = "00"; + } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/UnionPaySignTypeEnum.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/UnionPaySignTypeEnum.java new file mode 100644 index 00000000..cf7b6db4 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/UnionPaySignTypeEnum.java @@ -0,0 +1,20 @@ +package cn.bootx.platform.daxpay.service.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 云闪付签名类型 + * @author xxm + * @since 2024/3/8 + */ +@Getter +@AllArgsConstructor +public enum UnionPaySignTypeEnum { + + RSA2("RSA2","RSA2"); + + + private final String code; + private final String name; +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/configuration/sequence/DaxPaySequenceConfiguration.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/configuration/sequence/DaxPaySequenceConfiguration.java index d4966a79..fa56036f 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/configuration/sequence/DaxPaySequenceConfiguration.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/configuration/sequence/DaxPaySequenceConfiguration.java @@ -31,4 +31,12 @@ public class DaxPaySequenceConfiguration { public Sequence wechatReconcileSequence(SeqRangeManager seqRangeManager) { return SequenceUtil.create(1,1,1,"WechatReconcileSequence"); } + + /** + * 云闪付对账单序列生成器 + */ + @Bean + public Sequence unionPayReconcileSequence(SeqRangeManager seqRangeManager) { + return SequenceUtil.create(1,1,1,"UnionPayReconcileSequence"); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayReconcileService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayReconcileService.java index 8057bdb0..0a796519 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayReconcileService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayReconcileService.java @@ -5,10 +5,8 @@ import cn.bootx.platform.daxpay.code.ReconcileTradeEnum; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.service.code.AliPayCode; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; -import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliPayRecordManager; import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliReconcileBillDetailManager; import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliReconcileBillTotalManager; -import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig; import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliReconcileBillDetail; import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliReconcileBillTotal; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail; @@ -48,14 +46,11 @@ import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class AliPayReconcileService { - private final AliPayConfigService configService; private final AliReconcileBillDetailManager reconcileBillDetailManager; private final AliReconcileBillTotalManager reconcileBillTotalManager; - private final AliPayRecordManager recordManager; - /** * 下载对账单, 并进行解析进行保存 * @@ -65,8 +60,6 @@ public class AliPayReconcileService { @SneakyThrows @Transactional(rollbackFor = Exception.class) public void downAndSave(String date, Long recordOrderId){ - AliPayConfig config = configService.getConfig(); - configService.initConfig(config); try { AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel(); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/convert/UnionPayConvert.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/convert/UnionPayConvert.java index 81f27622..e26e41cf 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/convert/UnionPayConvert.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/convert/UnionPayConvert.java @@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.core.channel.union.convert; import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig; import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayRecord; +import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord; import cn.bootx.platform.daxpay.service.dto.channel.union.UnionPayConfigDto; import cn.bootx.platform.daxpay.service.dto.channel.union.UnionPayRecordDto; import org.mapstruct.Mapper; @@ -20,4 +21,6 @@ public interface UnionPayConvert { UnionPayRecordDto convert(UnionPayRecord in); + GeneralReconcileRecord convertReconcileRecord(UnionPayRecord in); + } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/entity/UnionPayConfig.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/entity/UnionPayConfig.java index bff8023e..0952a8ba 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/entity/UnionPayConfig.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/entity/UnionPayConfig.java @@ -1,8 +1,11 @@ package cn.bootx.platform.daxpay.service.core.channel.union.entity; +import cn.bootx.platform.common.core.annotation.BigField; +import cn.bootx.platform.common.core.annotation.EncryptionField; import cn.bootx.platform.common.core.function.EntityBaseFunction; import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity; import cn.bootx.platform.common.mybatisplus.handler.StringListTypeHandler; +import cn.bootx.platform.daxpay.service.code.UnionPaySignTypeEnum; import cn.bootx.platform.daxpay.service.core.channel.union.convert.UnionPayConvert; import cn.bootx.platform.daxpay.service.dto.channel.union.UnionPayConfigDto; import cn.bootx.table.modify.annotation.DbColumn; @@ -38,9 +41,61 @@ public class UnionPayConfig extends MpBaseEntity implements EntityBaseFunction 本网关进行处理 -> 重定向到业务系统中 + */ + @DbColumn(comment = "同步通知页面路径") + private String returnUrl; + /** 可用支付方式 */ @DbColumn(comment = "可用支付方式") @DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT) diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayCallbackService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayCallbackService.java index ff278d35..f7eabb22 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayCallbackService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayCallbackService.java @@ -8,10 +8,11 @@ import cn.bootx.platform.daxpay.service.common.context.CallbackLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig; import cn.bootx.platform.daxpay.service.func.AbsCallbackStrategy; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; import cn.hutool.core.date.DatePattern; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; -import com.ijpay.core.enums.SignType; +import com.egzosn.pay.common.bean.NoticeParams; import com.ijpay.core.kit.WxPayKit; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,6 +20,7 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.time.LocalDateTime; +import java.util.Collections; import java.util.Map; import java.util.Objects; @@ -57,13 +59,15 @@ public class UnionPayCallbackService extends AbsCallbackStrategy { // 支付回调信息校验 UnionPayConfig config = unionPayConfigService.getConfig(); + UnionPayKit unionPayKit = unionPayConfigService.initPayService(config); if (Objects.isNull(config)) { log.warn("云闪付支付配置不存在"); return false; } - // 注意此处签名方式需与统一下单的签名类型一致 - return WxPayKit.verifyNotify(params, config.getAppKey(), SignType.MD5); + NoticeParams noticeParams = new NoticeParams(); + noticeParams.setBody(Collections.unmodifiableMap(params)); + return unionPayKit.verify(noticeParams); } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayCloseService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayCloseService.java index 7f10649d..42b1b7e9 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayCloseService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayCloseService.java @@ -2,14 +2,10 @@ package cn.bootx.platform.daxpay.service.core.channel.union.service; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.service.code.UnionPayCode; -import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; import cn.hutool.core.util.StrUtil; -import com.ijpay.core.enums.SignType; -import com.ijpay.core.kit.WxPayKit; -import com.ijpay.unionpay.enums.ServiceEnum; -import com.ijpay.unionpay.model.CloseOrderModel; -import com.ijpay.wxpay.WxPayApi; +import com.egzosn.pay.common.bean.AssistOrder; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -32,17 +28,14 @@ public class UnionPayCloseService { /** * 关闭订单 */ - public void close(PayOrder payOrder, UnionPayConfig unionPayConfig) { - Map params = CloseOrderModel.builder() - .service(ServiceEnum.CLOSE.toString()) - .mch_id(unionPayConfig.getMachId()) - .out_trade_no(String.valueOf(payOrder.getId())) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(unionPayConfig.getAppKey(), SignType.HMACSHA256); - String xmlResult = WxPayApi.closeOrder(params); - Map result = WxPayKit.xmlToMap(xmlResult); - this.verifyErrorMsg(result); + public void close(PayOrder payOrder, UnionPayKit unionPayKit) { + AssistOrder closeOrder = new AssistOrder(); + + closeOrder.setOutTradeNo(String.valueOf(payOrder.getId())); + + Map result = unionPayKit.close(closeOrder); + +// this.verifyErrorMsg(result); } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayConfigService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayConfigService.java index a3454fd5..74ab897b 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayConfigService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayConfigService.java @@ -9,8 +9,12 @@ import cn.bootx.platform.daxpay.service.core.channel.union.dao.UnionPayConfigMan import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig; import cn.bootx.platform.daxpay.service.core.system.config.service.PayChannelConfigService; import cn.bootx.platform.daxpay.service.param.channel.alipay.AliPayConfigParam; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; +import com.egzosn.pay.common.bean.CertStoreType; +import com.egzosn.pay.common.http.HttpConfigStorage; +import com.egzosn.pay.union.api.UnionPayConfigStorage; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -77,4 +81,45 @@ public class UnionPayConfigService { return unionPayConfig; } + + /** + * 生成云闪付支付服务 + */ + public UnionPayKit initPayService(UnionPayConfig config){ + UnionPayConfigStorage unionPayConfigStorage = new UnionPayConfigStorage(); + unionPayConfigStorage.setMerId(config.getMachId()); + //是否为证书签名 + unionPayConfigStorage.setCertSign(config.isCertSign()); + + //中级证书 证书字符串信息 + unionPayConfigStorage.setAcpMiddleCert(config.getAcpMiddleCert()); + //根证书路径 证书字符串信息 + unionPayConfigStorage.setAcpRootCert(config.getAcpRootCert()); + // 私钥证书路径 证书字符串信息 + unionPayConfigStorage.setKeyPrivateCert(config.getKeyPrivateCert()); + //私钥证书对应的密码 私钥证书对应的密码 + unionPayConfigStorage.setKeyPrivateCertPwd(config.getKeyPrivateCertPwd()); + //设置证书对应的存储方式,证书字符串信息 + unionPayConfigStorage.setCertStoreType(CertStoreType.STR); + + // 回调地址 + unionPayConfigStorage.setNotifyUrl(config.getNotifyUrl()); + // 同步回调可不填 + unionPayConfigStorage.setReturnUrl(config.getReturnUrl()); + unionPayConfigStorage.setSignType(config.signType); + //是否为测试账号,沙箱环境 + unionPayConfigStorage.setTest(config.isSandbox()); + + // 网络请求配置 + HttpConfigStorage httpConfigStorage = new HttpConfigStorage(); + httpConfigStorage.setCertStoreType(CertStoreType.STR); + //最大连接数 + httpConfigStorage.setMaxTotal(20); + //默认的每个路由的最大连接数 + httpConfigStorage.setDefaultMaxPerRoute(10); + + // 创建支付服务 + return new UnionPayKit(unionPayConfigStorage, httpConfigStorage); + } + } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayReconcileService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayReconcileService.java index 7deb0a9f..d6abb838 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayReconcileService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayReconcileService.java @@ -1,9 +1,15 @@ package cn.bootx.platform.daxpay.service.core.channel.union.service; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.Date; +import java.util.Map; + +import static cn.bootx.platform.daxpay.service.code.UnionPayCode.RECONCILE_BILL_TYPE; + /** * 云闪付对账 * @author xxm @@ -14,4 +20,11 @@ import org.springframework.stereotype.Service; @RequiredArgsConstructor public class UnionPayReconcileService { + /** + * 下载对账单 + */ + public void downAndSave(Date date, Long recordOrderId, UnionPayKit unionPayKit){ + // 下载对账单 + Map stringObjectMap = unionPayKit.downloadBill(date, RECONCILE_BILL_TYPE); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayRefundService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayRefundService.java index 4e277619..912c976b 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayRefundService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayRefundService.java @@ -1,23 +1,20 @@ package cn.bootx.platform.daxpay.service.core.channel.union.service; -import cn.bootx.platform.daxpay.code.RefundStatusEnum; import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.service.code.UnionPayCode; import cn.bootx.platform.daxpay.service.common.context.RefundLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; -import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder; import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; +import cn.bootx.platform.daxpay.service.sdk.union.bean.UnionRefundOrder; import cn.hutool.core.util.StrUtil; -import com.ijpay.core.enums.SignType; -import com.ijpay.core.kit.WxPayKit; -import com.ijpay.unionpay.UnionPayApi; -import com.ijpay.unionpay.enums.ServiceEnum; -import com.ijpay.unionpay.model.RefundModel; +import com.egzosn.pay.union.bean.UnionRefundResult; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.math.BigDecimal; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -34,30 +31,29 @@ import static cn.bootx.platform.daxpay.service.code.UnionPayCode.*; @RequiredArgsConstructor public class UnionPayRefundService { - /** * 退款方法 */ - public void refund(RefundOrder refundOrder, int amount, PayChannelOrder channelOrder, UnionPayConfig unionPayConfig) { - Map params = RefundModel.builder() - .service(ServiceEnum.REFUND.toString()) - .mch_id(unionPayConfig.getMachId()) - .out_trade_no(String.valueOf(refundOrder.getPaymentId())) - .out_refund_no(String.valueOf(refundOrder.getId())) - .total_fee(String.valueOf(channelOrder.getAmount())) - .refund_fee(String.valueOf(amount)) - .op_user_id(unionPayConfig.getMachId()) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(unionPayConfig.getAppKey(), SignType.MD5); + public void refund(RefundOrder refundOrder, int amount, PayChannelOrder channelOrder, UnionPayKit unionPayKit) { - String xmlResult = UnionPayApi.execution(unionPayConfig.getServerUrl(), params); - Map result = WxPayKit.xmlToMap(xmlResult); - this.verifyErrorMsg(result); - // 云闪付退款是否成功需要查询状态, 所以设置为退款中状态 - RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo(); - refundInfo.setStatus(RefundStatusEnum.PROGRESS) - .setGatewayOrderNo(result.get(REFUND_ID)); + // 金额转换 + BigDecimal refundAmount = BigDecimal.valueOf(amount * 0.01); + BigDecimal orderAmount = BigDecimal.valueOf(channelOrder.getAmount() * 0.01); + + UnionRefundOrder unionRefundOrder = new UnionRefundOrder(); + unionRefundOrder.setOutTradeNo(String.valueOf(refundOrder.getPaymentId())); + unionRefundOrder.setRefundNo(String.valueOf(refundOrder.getId())); + unionRefundOrder.setRefundAmount(refundAmount); + unionRefundOrder.setTotalAmount(orderAmount); + UnionRefundResult refund = unionPayKit.refund(unionRefundOrder); + +// String xmlResult = UnionPayApi.execution(unionPayConfig.getServerUrl(), params); +// Map result = WxPayKit.xmlToMap(xmlResult); +// this.verifyErrorMsg(result); +// // 云闪付退款是否成功需要查询状态, 所以设置为退款中状态 +// RefundLocal refundInfo = PaymentContextLocal.get().getRefundInfo(); +// refundInfo.setStatus(RefundStatusEnum.PROGRESS) +// .setGatewayOrderNo(result.get(REFUND_ID)); } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayService.java index c024d7ac..43f0dbf2 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayService.java @@ -10,19 +10,17 @@ import cn.bootx.platform.daxpay.service.common.context.PayLocal; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder; -import cn.bootx.platform.daxpay.util.PayUtil; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; +import cn.bootx.platform.daxpay.service.sdk.union.bean.UnionPayOrder; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; -import com.ijpay.core.enums.SignType; -import com.ijpay.core.kit.WxPayKit; -import com.ijpay.unionpay.UnionPayApi; -import com.ijpay.unionpay.enums.ServiceEnum; -import com.ijpay.unionpay.model.MicroPayModel; -import com.ijpay.unionpay.model.UnifiedOrderModel; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.util.Date; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -59,180 +57,110 @@ public class UnionPayService { /** * 支付接口 */ - public void pay(PayOrder payOrder, PayChannelParam payChannelParam, UnionPayParam unionPayParam, UnionPayConfig unionPayConfig){ + public void pay(PayOrder payOrder, PayChannelParam payChannelParam, UnionPayParam unionPayParam, UnionPayKit unionPayKit){ Integer amount = payChannelParam.getAmount(); - String totalFee = String.valueOf(amount); + BigDecimal totalFee = BigDecimal.valueOf(amount * 0.01); PayLocal asyncPayInfo = PaymentContextLocal.get().getPayInfo();; String payBody = null; PayWayEnum payWayEnum = PayWayEnum.findByCode(payChannelParam.getWay()); - // 微信APP支付 - if (payWayEnum == PayWayEnum.APP) { - payBody = this.wxAppPay(totalFee, payOrder, unionPayParam, unionPayConfig); - } - // 微信公众号支付或者小程序支付 - else if (payWayEnum == PayWayEnum.JSAPI_WX_PAY) { - payBody = this.wxJsPay(totalFee, payOrder, unionPayParam.getOpenId(), unionPayConfig); - } - // 支付宝JS支付 - else if (payWayEnum == PayWayEnum.JSAPI_ALI_PAY) { - payBody = this.aliJsPay(totalFee, payOrder, unionPayParam, unionPayConfig); - } - // 银联JS支付 - else if (payWayEnum == PayWayEnum.JSAPI) { - payBody = this.unionJsPay(totalFee, payOrder, unionPayParam, unionPayConfig); - } // 二维码支付 - else if (payWayEnum == PayWayEnum.QRCODE) { - payBody = this.qrCodePay(totalFee, payOrder, unionPayConfig); + if (payWayEnum == PayWayEnum.QRCODE) { + payBody = this.qrCodePay(totalFee, payOrder, unionPayKit); } // 付款码支付 else if (payWayEnum == PayWayEnum.BARCODE) { - this.barCodePay(totalFee, payOrder, unionPayParam.getAuthCode(), unionPayConfig); + this.barCodePay(totalFee, payOrder, unionPayParam.getAuthCode(), unionPayKit); + } + // APP支付 + else if (payWayEnum == PayWayEnum.APP) { + payBody = this.appPay(totalFee, payOrder, unionPayParam, unionPayKit); } asyncPayInfo.setPayBody(payBody); } /** - * 支付宝生活号支付 + * APP支付 */ - private String aliJsPay(String amount, PayOrder payOrder, UnionPayParam unionPayParam, UnionPayConfig unionPayConfig) { - Map params = UnifiedOrderModel.builder() - .service(ServiceEnum.ALI_PAY_JS_PAY.toString()) - .mch_id(unionPayConfig.getMachId()) - .out_trade_no(WxPayKit.generateStr()) - .body(payOrder.getTitle()) - .total_fee(amount) - .mch_create_ip("127.0.0.15") - .notify_url(unionPayConfig.getNotifyUrl()) - .nonce_str(WxPayKit.generateStr()) - .buyer_id(unionPayParam.getBuyerId()) - .build() - .createSign(unionPayConfig.getAppKey(), SignType.MD5); + private String appPay(BigDecimal amount, PayOrder payOrder, UnionPayParam unionPayParam, UnionPayKit unionPayKit) { - String xmlResult = UnionPayApi.execution(unionPayConfig.getServerUrl(), params); - Map result = WxPayKit.xmlToMap(xmlResult); - this.verifyErrorMsg(result); - return null; - } + Date expiredTime = DateUtil.date(payOrder.getExpiredTime()); - /** - * 银联JS支付 - */ - private String unionJsPay(String amount, PayOrder payOrder, UnionPayParam unionPayParam, UnionPayConfig unionPayConfig) { - Map params = UnifiedOrderModel.builder() - .service(ServiceEnum.UNION_JS_PAY.toString()) - .mch_id(unionPayConfig.getMachId()) - .out_trade_no(WxPayKit.generateStr()) - .body(payOrder.getTitle()) - .user_id(unionPayParam.getUserId()) - .customer_ip(unionPayParam.getCustomerIp()) - .total_fee(amount) - .mch_create_ip("127.0.0.1") - .notify_url(unionPayConfig.getNotifyUrl()) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(unionPayConfig.getAppKey(), SignType.MD5); - System.out.println(params); + UnionPayOrder unionPayOrder = new UnionPayOrder(); + unionPayOrder.setOutTradeNo(String.valueOf(payOrder.getId())); + unionPayOrder.setSubject(payOrder.getTitle()); + unionPayOrder.setPrice(amount); + unionPayOrder.setExpirationTime(expiredTime); - String xmlResult = UnionPayApi.execution(unionPayConfig.getServerUrl(), params); - Map result = WxPayKit.xmlToMap(xmlResult); - this.verifyErrorMsg(result); - return null; - } - - /** - * 微信APP支付 - */ - private String wxAppPay(String amount, PayOrder payOrder, UnionPayParam unionPayParam, UnionPayConfig unionPayConfig) { - Map params = UnifiedOrderModel.builder() - .service(ServiceEnum.WEI_XIN_APP_PAY.toString()) - .mch_id(unionPayConfig.getMachId()) - .appid(unionPayParam.getAppId()) - .sub_appid(unionPayParam.getSubAppId()) - .out_trade_no(WxPayKit.generateStr()) - .body(payOrder.getTitle()) - .attach("聚合支付 SDK") - .total_fee(amount) - .mch_create_ip("127.0.0.1") - .notify_url(unionPayConfig.getNotifyUrl()) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(unionPayConfig.getAppKey(), SignType.MD5); - - String xmlResult = UnionPayApi.execution(unionPayConfig.getServerUrl(), params); - Map result = WxPayKit.xmlToMap(xmlResult); - this.verifyErrorMsg(result); - return null; - } - - /** - * 微信公众号支付或者小程序支付 - */ - private String wxJsPay(String amount, PayOrder payOrder, String openId, UnionPayConfig unionPayConfig) { - - Map params = UnifiedOrderModel.builder() - .service(ServiceEnum.WEI_XIN_JS_PAY.toString()) - .mch_id(unionPayConfig.getMachId()) - // 原生JS 值为1 - .is_raw("1") - .out_trade_no(WxPayKit.generateStr()) - .body(payOrder.getTitle()) - .sub_openid(openId) - .total_fee(amount) - .mch_create_ip("127.0.0.1") - .notify_url(unionPayConfig.getNotifyUrl()) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(unionPayConfig.getAppKey(), SignType.MD5); - String xmlResult = UnionPayApi.execution(unionPayConfig.getServerUrl(), params); - Map result = WxPayKit.xmlToMap(xmlResult); - this.verifyErrorMsg(result); + Map app = unionPayKit.app(unionPayOrder); return null; } /** * 扫码支付 */ - private String qrCodePay(String amount, PayOrder payOrder, UnionPayConfig config){ - Map params = UnifiedOrderModel.builder() - .service(ServiceEnum.NATIVE.toString()) - .mch_id(config.getMachId()) - .out_trade_no(String.valueOf(payOrder.getId())) - .body(payOrder.getTitle()) - .total_fee(amount) - .time_expire(PayUtil.getUnionExpiredTime(payOrder.getExpiredTime())) - .mch_create_ip("127.0.0.1") - .notify_url(config.getNotifyUrl()) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(config.getAppKey(), SignType.MD5); - String xmlResult = UnionPayApi.execution(config.getServerUrl(), params); - Map result = WxPayKit.xmlToMap(xmlResult); - this.verifyErrorMsg(result); - return result.get("code_url"); + private String qrCodePay(BigDecimal amount, PayOrder payOrder, UnionPayKit unionPayKit){ + Date expiredTime = DateUtil.date(payOrder.getExpiredTime()); + + UnionPayOrder unionPayOrder = new UnionPayOrder(); + + unionPayOrder.setOutTradeNo(String.valueOf(payOrder.getId())); + unionPayOrder.setSubject(payOrder.getTitle()); + unionPayOrder.setPrice(amount); + unionPayOrder.setExpirationTime(expiredTime); + + return unionPayKit.getQrPay(unionPayOrder); + + +// Map params = UnifiedOrderModel.builder() +// .service(ServiceEnum.NATIVE.toString()) +// .mch_id(unionPayKit.getMachId()) +// .out_trade_no(String.valueOf(payOrder.getId())) +// .body(payOrder.getTitle()) +// .total_fee(amount) +// .time_expire(PayUtil.getUnionExpiredTime(payOrder.getExpiredTime())) +// .mch_create_ip("127.0.0.1") +// .notify_url(unionPayKit.getNotifyUrl()) +// .nonce_str(WxPayKit.generateStr()) +// .build() +// .createSign(unionPayKit.getAppKey(), SignType.MD5); +// String xmlResult = UnionPayApi.execution(unionPayKit.getServerUrl(), params); +// Map result = WxPayKit.xmlToMap(xmlResult); +// this.verifyErrorMsg(result); +// return result.get("code_url"); } /** * 付款码支付 */ - private void barCodePay(String amount, PayOrder payOrder, String authCode, UnionPayConfig unionPayConfig) { - Map params = MicroPayModel.builder() - .service(ServiceEnum.MICRO_PAY.toString()) - .mch_id(unionPayConfig.getMachId()) - .out_trade_no(WxPayKit.generateStr()) - .body(payOrder.getTitle()) - .total_fee(amount) - .op_device_id("daxpay") - .mch_create_ip("127.0.0.1") - .auth_code(authCode) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(unionPayConfig.getAppKey(), SignType.MD5); + private void barCodePay(BigDecimal amount, PayOrder payOrder, String authCode, UnionPayKit unionPayKit) { + Date expiredTime = DateUtil.date(payOrder.getExpiredTime()); - String xmlResult = UnionPayApi.execution(unionPayConfig.getServerUrl(), params); + UnionPayOrder unionPayOrder = new UnionPayOrder(); + + unionPayOrder.setAuthCode(authCode); + unionPayOrder.setOutTradeNo(String.valueOf(payOrder.getId())); + unionPayOrder.setSubject(payOrder.getTitle()); + unionPayOrder.setPrice(amount); + unionPayOrder.setExpirationTime(expiredTime); + Map stringObjectMap = unionPayKit.microPay(unionPayOrder); + +// Map params = MicroPayModel.builder() +// .service(ServiceEnum.MICRO_PAY.toString()) +// .mch_id(unionPayKit.getMachId()) +// .out_trade_no(WxPayKit.generateStr()) +// .body(payOrder.getTitle()) +// .total_fee(amount) +// .op_device_id("daxpay") +// .mch_create_ip("127.0.0.1") +// .auth_code(authCode) +// .nonce_str(WxPayKit.generateStr()) +// .build() +// .createSign(unionPayKit.getAppKey(), SignType.MD5); +// +// String xmlResult = UnionPayApi.execution(unionPayKit.getServerUrl(), params); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPaySyncService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPaySyncService.java index 59f22413..eabe590d 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPaySyncService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPaySyncService.java @@ -1,29 +1,21 @@ package cn.bootx.platform.daxpay.service.core.channel.union.service; -import cn.bootx.platform.common.core.util.LocalDateTimeUtil; import cn.bootx.platform.daxpay.code.PaySyncStatusEnum; import cn.bootx.platform.daxpay.code.RefundSyncStatusEnum; import cn.bootx.platform.daxpay.service.code.UnionPayCode; -import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig; import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder; import cn.bootx.platform.daxpay.service.core.payment.sync.result.PayGatewaySyncResult; import cn.bootx.platform.daxpay.service.core.payment.sync.result.RefundGatewaySyncResult; -import cn.hutool.core.date.DatePattern; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; +import cn.bootx.platform.daxpay.service.sdk.union.bean.UnionRefundOrder; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; -import com.ijpay.core.enums.SignType; -import com.ijpay.core.kit.WxPayKit; -import com.ijpay.unionpay.UnionPayApi; -import com.ijpay.unionpay.enums.ServiceEnum; -import com.ijpay.unionpay.model.OrderQueryModel; -import com.ijpay.unionpay.model.RefundQueryModel; -import com.ijpay.wxpay.WxPayApi; +import com.egzosn.pay.common.bean.AssistOrder; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.time.LocalDateTime; import java.util.Map; import java.util.Objects; @@ -42,52 +34,47 @@ public class UnionPaySyncService { /** * 支付信息查询 */ - public PayGatewaySyncResult syncPayStatus(PayOrder order, UnionPayConfig unionPayConfig) { + public PayGatewaySyncResult syncPayStatus(PayOrder order, UnionPayKit unionPayKit) { PayGatewaySyncResult syncResult = new PayGatewaySyncResult().setSyncStatus(PaySyncStatusEnum.FAIL); - Map params = OrderQueryModel.builder() - .service(ServiceEnum.QUERY.toString()) - .mch_id(unionPayConfig.getMachId()) - .out_trade_no(String.valueOf(order.getId())) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(unionPayConfig.getAppKey(), SignType.MD5); - String xmlResult = UnionPayApi.execution(unionPayConfig.getServerUrl(), params); - Map result = WxPayKit.xmlToMap(xmlResult); + AssistOrder query = new AssistOrder(); + query.setOutTradeNo(String.valueOf(order.getId())); + Map result = unionPayKit.query(query); + syncResult.setSyncInfo(JSONUtil.toJsonStr(result)); - String status = result.get(STATUS); - String returnCode = result.get(RESULT_CODE); - - // 判断查询是否成功 - if (!(Objects.equals(SUCCESS, status) && Objects.equals(SUCCESS, returnCode))){ - log.warn("查询云闪付订单失败:{}", result); - return syncResult; - } - - // 设置微信支付网关订单号 - syncResult.setGatewayOrderNo(result.get(TRANSACTION_ID)); - // 查询到订单的状态 - String tradeStatus = result.get(TRADE_STATE); - // 支付完成 - if (Objects.equals(tradeStatus, SUCCESS)) { - String timeEnd = result.get(TIME_END); - LocalDateTime time = LocalDateTimeUtil.parse(timeEnd, DatePattern.PURE_DATETIME_PATTERN); - return syncResult.setPayTime(time).setSyncStatus(PaySyncStatusEnum.SUCCESS); - } - // 待支付 - if (Objects.equals(tradeStatus, TRADE_NOT_PAY)) { - return syncResult.setSyncStatus(PaySyncStatusEnum.PROGRESS); - } - - // 已退款/退款中 - if (Objects.equals(tradeStatus, TRADE_REFUND)) { - return syncResult.setSyncStatus(PaySyncStatusEnum.REFUND); - } - // 已关闭 - if (Objects.equals(tradeStatus, TRADE_CLOSED)) { - return syncResult.setSyncStatus(PaySyncStatusEnum.CLOSED); - } +// String status = result.get(STATUS); +// String returnCode = result.get(RESULT_CODE); +// +// // 判断查询是否成功 +// if (!(Objects.equals(SUCCESS, status) && Objects.equals(SUCCESS, returnCode))){ +// log.warn("查询云闪付订单失败:{}", result); +// return syncResult; +// } +// +// // 设置微信支付网关订单号 +// syncResult.setGatewayOrderNo(result.get(TRANSACTION_ID)); +// // 查询到订单的状态 +// String tradeStatus = result.get(TRADE_STATE); +// // 支付完成 +// if (Objects.equals(tradeStatus, SUCCESS)) { +// String timeEnd = result.get(TIME_END); +// LocalDateTime time = LocalDateTimeUtil.parse(timeEnd, DatePattern.PURE_DATETIME_PATTERN); +// return syncResult.setPayTime(time).setSyncStatus(PaySyncStatusEnum.SUCCESS); +// } +// // 待支付 +// if (Objects.equals(tradeStatus, TRADE_NOT_PAY)) { +// return syncResult.setSyncStatus(PaySyncStatusEnum.PROGRESS); +// } +// +// // 已退款/退款中 +// if (Objects.equals(tradeStatus, TRADE_REFUND)) { +// return syncResult.setSyncStatus(PaySyncStatusEnum.REFUND); +// } +// // 已关闭 +// if (Objects.equals(tradeStatus, TRADE_CLOSED)) { +// return syncResult.setSyncStatus(PaySyncStatusEnum.CLOSED); +// } return syncResult; } @@ -95,23 +82,21 @@ public class UnionPaySyncService { /** * 退款信息查询 */ - public RefundGatewaySyncResult syncRefundStatus(RefundOrder refundOrder, UnionPayConfig unionPayConfig){ + public RefundGatewaySyncResult syncRefundStatus(RefundOrder refundOrder, UnionPayKit unionPayKit){ RefundGatewaySyncResult syncResult = new RefundGatewaySyncResult(); - Map params = RefundQueryModel.builder() - .service(ServiceEnum.REFUND_QUERY.toString()) - .mch_id(unionPayConfig.getMachId()) - .refund_id(refundOrder.getGatewayOrderNo()) - .nonce_str(WxPayKit.generateStr()) - .build() - .createSign(unionPayConfig.getAppKey(), SignType.MD5); + + UnionRefundOrder query = new UnionRefundOrder(); + query.setRefundNo(String.valueOf(refundOrder.getId())); + Map results = unionPayKit.refundquery(query); + try { - String xmlResult = WxPayApi.orderRefundQuery(false, params); - Map result = WxPayKit.xmlToMap(xmlResult); - syncResult.setSyncInfo(JSONUtil.toJsonStr(result)); +// String xmlResult = WxPayApi.orderRefundQuery(false, params); +// Map result = WxPayKit.xmlToMap(xmlResult); +// syncResult.setSyncInfo(JSONUtil.toJsonStr(result)); // 设置微信支付网关订单号 - syncResult.setGatewayOrderNo(result.get(UnionPayCode.REFUND_ID)); +// syncResult.setGatewayOrderNo(result.get(UnionPayCode.REFUND_ID)); // 状态 // String tradeStatus = result.get(UnionPayCode.REFUND_STATUS); // // 退款成功 @@ -124,8 +109,8 @@ public class UnionPaySyncService { // if (Objects.equals(tradeStatus, UnionPayCode.REFUND_PROCESSING)) { // return syncResult.setSyncStatus(RefundSyncStatusEnum.PROGRESS); // } - String errorMsg = this.getErrorMsg(result); - return syncResult.setSyncStatus(RefundSyncStatusEnum.FAIL).setErrorMsg(errorMsg); +// String errorMsg = this.getErrorMsg(result); +// return syncResult.setSyncStatus(RefundSyncStatusEnum.FAIL).setErrorMsg(errorMsg); } catch (Exception e) { log.error("查询退款订单失败:", e); syncResult.setSyncStatus(RefundSyncStatusEnum.PROGRESS).setErrorMsg(e.getMessage()); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/close/strategy/UnionPayCloseStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/close/strategy/UnionPayCloseStrategy.java index 86a054b1..a8f666ab 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/close/strategy/UnionPayCloseStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/close/strategy/UnionPayCloseStrategy.java @@ -5,6 +5,7 @@ import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayCloseService; import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayConfigService; import cn.bootx.platform.daxpay.service.func.AbsPayCloseStrategy; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Scope; @@ -48,6 +49,7 @@ public class UnionPayCloseStrategy extends AbsPayCloseStrategy { */ @Override public void doCloseHandler() { - unionPayCloseService.close(this.getOrder(), this.unionPayConfig); + UnionPayKit unionPayKit = unionPayConfigService.initPayService(this.unionPayConfig); + unionPayCloseService.close(this.getOrder(), unionPayKit); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/strategy/UnionPayStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/strategy/UnionPayStrategy.java index 7a3c9bd4..3f8de3bc 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/strategy/UnionPayStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/pay/strategy/UnionPayStrategy.java @@ -14,6 +14,7 @@ import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayServi import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayChannelOrder; import cn.bootx.platform.daxpay.service.core.order.pay.service.PayChannelOrderService; import cn.bootx.platform.daxpay.service.func.AbsPayStrategy; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.json.JSONException; @@ -87,7 +88,8 @@ public class UnionPayStrategy extends AbsPayStrategy { */ @Override public void doPayHandler() { - unionPayService.pay(this.getOrder(), this.getPayChannelParam(), this.unionPayParam, this.unionPayConfig); + UnionPayKit unionPayKit = unionPayConfigService.initPayService(unionPayConfig); + unionPayService.pay(this.getOrder(), this.getPayChannelParam(), this.unionPayParam, unionPayKit); } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/UnionPayReconcileStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/UnionPayReconcileStrategy.java new file mode 100644 index 00000000..4ddd151d --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/UnionPayReconcileStrategy.java @@ -0,0 +1,102 @@ +package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy; + +import cn.bootx.platform.common.core.util.LocalDateTimeUtil; +import cn.bootx.platform.common.sequence.func.Sequence; +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.service.core.channel.union.convert.UnionPayConvert; +import cn.bootx.platform.daxpay.service.core.channel.union.dao.UnionPayRecordManager; +import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig; +import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayRecord; +import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayConfigService; +import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayReconcileService; +import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord; +import cn.bootx.platform.daxpay.service.func.AbsReconcileStrategy; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * + * @author xxm + * @since 2024/3/8 + */ +@Slf4j +@Service +@Scope(SCOPE_PROTOTYPE) +@RequiredArgsConstructor +public class UnionPayReconcileStrategy extends AbsReconcileStrategy { + + private final UnionPayConfigService configService; + + private final UnionPayReconcileService reconcileService; + + private final UnionPayRecordManager recordManager; + + @Qualifier("unionPayReconcileSequence") + private final Sequence sequence; + + private UnionPayKit unionPayKit; + + /** + * 生成对账序列号 + */ + @Override + public String generateSequence(LocalDate date) { + String prefix = getChannel().getReconcilePrefix(); + String dateStr = LocalDateTimeUtil.format(date, DatePattern.PURE_DATE_PATTERN); + String key = String.format("%02d", sequence.next()); + return prefix + dateStr + key; + } + + /** + * 对账前处理, 主要是初始化支付SDK配置 + */ + @Override + public void doBeforeHandler() { + UnionPayConfig config = configService.getConfig(); + this.unionPayKit = configService.initPayService(config); + } + + /** + * 下载对账单到本地进行保存 + */ + @Override + public void downAndSave() { + Date date = DateUtil.date(this.getRecordOrder().getDate()); + reconcileService.downAndSave(date, this.getRecordOrder().getId(), this.unionPayKit); + } + + /** + * 获取通用对账对象, 将流水记录转换为对账对象 + */ + @Override + public List getGeneralReconcileRecord() { + // 查询流水 + LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(this.getRecordOrder().getDate()); + LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime); + LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime); + List records = recordManager.findByDate(start, end); + return records.stream().map(UnionPayConvert.CONVERT::convertReconcileRecord).collect(Collectors.toList()); + } + + /** + * 策略标识 + */ + @Override + public PayChannelEnum getChannel() { + return PayChannelEnum.UNION_PAY; + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/UnionRefundStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/UnionRefundStrategy.java index a417c5bb..20678ffd 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/UnionRefundStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/refund/strategy/UnionRefundStrategy.java @@ -9,6 +9,7 @@ import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayRecor import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayRefundService; import cn.bootx.platform.daxpay.service.core.order.pay.service.PayChannelOrderService; import cn.bootx.platform.daxpay.service.func.AbsRefundStrategy; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -61,7 +62,8 @@ public class UnionRefundStrategy extends AbsRefundStrategy { */ @Override public void doRefundHandler() { - unionPayRefundService.refund(this.getRefundOrder(), this.getRefundChannelParam().getAmount(), this.getPayChannelOrder(), this.unionPayConfig); + UnionPayKit unionPayKit = unionPayConfigService.initPayService(unionPayConfig); + unionPayRefundService.refund(this.getRefundOrder(), this.getRefundChannelParam().getAmount(), this.getPayChannelOrder(), unionPayKit); } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/UnionPaySyncStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/UnionPaySyncStrategy.java index f7a06dbd..2217ed95 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/UnionPaySyncStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/strategy/pay/UnionPaySyncStrategy.java @@ -7,6 +7,7 @@ import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayConfi import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPaySyncService; import cn.bootx.platform.daxpay.service.core.payment.sync.result.PayGatewaySyncResult; import cn.bootx.platform.daxpay.service.func.AbsPaySyncStrategy; +import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -35,7 +36,8 @@ public class UnionPaySyncStrategy extends AbsPaySyncStrategy { @Override public PayGatewaySyncResult doSyncStatus() { UnionPayConfig config = unionPayConfigService.getConfig(); - return unionPaySyncService.syncPayStatus(this.getOrder(),config); + UnionPayKit unionPayKit = unionPayConfigService.initPayService(config); + return unionPaySyncService.syncPayStatus(this.getOrder(),unionPayKit); } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/sdk/union/api/UnionPayKit.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/sdk/union/api/UnionPayKit.java new file mode 100644 index 00000000..273638c3 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/sdk/union/api/UnionPayKit.java @@ -0,0 +1,25 @@ +package cn.bootx.platform.daxpay.service.sdk.union.api; + +import com.egzosn.pay.common.http.HttpConfigStorage; +import com.egzosn.pay.union.api.UnionPayConfigStorage; +import com.egzosn.pay.union.api.UnionPayService; + +/** + * 云闪付支付服务类重命名, 避免与系统中类名冲突 + * @author xxm + * @since 2024/3/8 + */ +public class UnionPayKit extends UnionPayService { + /** + * 构造函数 + * + * @param payConfigStorage 支付配置 + */ + public UnionPayKit(UnionPayConfigStorage payConfigStorage) { + super(payConfigStorage); + } + + public UnionPayKit(UnionPayConfigStorage payConfigStorage, HttpConfigStorage configStorage) { + super(payConfigStorage, configStorage); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/sdk/union/bean/UnionPayOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/sdk/union/bean/UnionPayOrder.java new file mode 100644 index 00000000..d5653ed7 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/sdk/union/bean/UnionPayOrder.java @@ -0,0 +1,11 @@ +package cn.bootx.platform.daxpay.service.sdk.union.bean; + +import com.egzosn.pay.common.bean.PayOrder; + +/** + * 继承SDK中的类, 防止与系统中的类名称冲突 + * @author xxm + * @since 2024/3/8 + */ +public class UnionPayOrder extends PayOrder { +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/sdk/union/bean/UnionRefundOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/sdk/union/bean/UnionRefundOrder.java new file mode 100644 index 00000000..27c3563e --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/sdk/union/bean/UnionRefundOrder.java @@ -0,0 +1,11 @@ +package cn.bootx.platform.daxpay.service.sdk.union.bean; + +import com.egzosn.pay.common.bean.RefundOrder; + +/** + * 继承SDK中的类, 防止与系统中的类名称冲突 + * @author xxm + * @since 2024/3/8 + */ +public class UnionRefundOrder extends RefundOrder { +} diff --git a/pom.xml b/pom.xml index 93f22ecf..82b39fd0 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,7 @@ 0.0.38 3.5.2 2.9.10 + 2.14.7 4.4.0 1.5.3.Final 0.2.0