From 3ad69e9a299ea4ffed86929b347eadacc464dca8 Mon Sep 17 00:00:00 2001 From: terrfly Date: Thu, 12 Aug 2021 15:27:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=BD=AC=E8=B4=A6API?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=9A=84=E5=AE=9E=E7=8E=B0=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/sql/init.sql | 37 +++ .../jeepay/core/entity/MchNotifyRecord.java | 3 +- .../jeepay/core/entity/TransferOrder.java | 195 ++++++++++++++ .../com/jeequan/jeepay/core/utils/SeqKit.java | 9 + .../pay/channel/IPayOrderQueryService.java | 4 +- .../jeepay/pay/channel/ITransferService.java | 44 ++++ .../channel/wxpay/WxpayTransferService.java | 114 ++++++++ .../transfer/TransferOrderController.java | 248 ++++++++++++++++++ .../rqrs/transfer/QueryTransferOrderRQ.java | 37 +++ .../rqrs/transfer/QueryTransferOrderRS.java | 148 +++++++++++ .../pay/rqrs/transfer/TransferOrderRQ.java | 82 ++++++ .../pay/rqrs/transfer/TransferOrderRS.java | 84 ++++++ .../pay/service/PayMchNotifyService.java | 64 +++++ .../service/impl/MchNotifyRecordService.java | 5 + .../impl/PayInterfaceConfigService.java | 22 +- .../service/impl/TransferOrderService.java | 102 +++++++ .../service/mapper/TransferOrderMapper.java | 31 +++ .../service/mapper/TransferOrderMapper.xml | 36 +++ 18 files changed, 1258 insertions(+), 7 deletions(-) create mode 100644 jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/TransferOrder.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/ITransferService.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/wxpay/WxpayTransferService.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/transfer/TransferOrderController.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/QueryTransferOrderRQ.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/QueryTransferOrderRS.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/TransferOrderRQ.java create mode 100644 jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/TransferOrderRS.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/TransferOrderService.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/TransferOrderMapper.java create mode 100644 jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/TransferOrderMapper.xml diff --git a/docs/sql/init.sql b/docs/sql/init.sql index a006cf2..25517df 100644 --- a/docs/sql/init.sql +++ b/docs/sql/init.sql @@ -365,6 +365,43 @@ CREATE TABLE `t_refund_order` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='退款订单表'; +-- 转账订单表 +DROP TABLE IF EXISTS t_transfer_order; +CREATE TABLE `t_transfer_order` ( + `transfer_id` VARCHAR(32) NOT NULL COMMENT '转账订单号', + `mch_no` VARCHAR(64) NOT NULL COMMENT '商户号', + `isv_no` VARCHAR(64) COMMENT '服务商号', + `app_id` VARCHAR(64) NOT NULL COMMENT '应用ID', + `mch_name` VARCHAR(30) NOT NULL COMMENT '商户名称', + `mch_type` TINYINT(6) NOT NULL COMMENT '类型: 1-普通商户, 2-特约商户(服务商模式)', + `mch_order_no` VARCHAR(64) NOT NULL COMMENT '商户订单号', + `if_code` VARCHAR(20) NOT NULL COMMENT '支付接口代码', + `entry_type` VARCHAR(20) NOT NULL COMMENT '入账方式: WX_CASH-微信零钱; ALIPAY_CASH-支付宝转账; BANK_CARD-银行卡', + `amount` BIGINT(20) NOT NULL COMMENT '转账金额,单位分', + `currency` VARCHAR(3) NOT NULL DEFAULT 'cny' COMMENT '三位货币代码,人民币:cny', + `account_no` VARCHAR(64) NOT NULL COMMENT '收款账号', + `account_name` VARCHAR(64) COMMENT '收款人姓名', + `bank_name` VARCHAR(32) COMMENT '收款人开户行名称', + `transfer_desc` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '转账备注信息', + `client_ip` VARCHAR(32) DEFAULT NULL COMMENT '客户端IP', + `state` TINYINT(6) NOT NULL DEFAULT '0' COMMENT '支付状态: 0-订单生成, 1-转账中, 2-转账成功, 3-转账失败, 4-订单关闭', + `notify_state` TINYINT(6) NOT NULL DEFAULT '0' COMMENT '向下游回调状态, 0-未发送, 1-已发送', + `channel_extra` VARCHAR(512) DEFAULT NULL COMMENT '特定渠道发起额外参数', + `channel_order_no` VARCHAR(64) DEFAULT NULL COMMENT '渠道订单号', + `err_code` VARCHAR(128) DEFAULT NULL COMMENT '渠道支付错误码', + `err_msg` VARCHAR(256) DEFAULT NULL COMMENT '渠道支付错误描述', + `ext_param` VARCHAR(128) DEFAULT NULL COMMENT '商户扩展参数', + `notify_url` VARCHAR(128) NOT NULL default '' COMMENT '异步通知地址', + `success_time` DATETIME DEFAULT NULL COMMENT '转账成功时间', + `created_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间', + `updated_at` TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间', + PRIMARY KEY (`transfer_id`), + UNIQUE KEY `Uni_MchNo_MchOrderNo` (`mch_no`, `mch_order_no`), + INDEX(`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='转账订单表'; + + + ##### ↑↑↑↑↑↑↑↑↑↑ 表结构DDL ↑↑↑↑↑↑↑↑↑↑ ##### ##### ↓↓↓↓↓↓↓↓↓↓ 初始化DML ↓↓↓↓↓↓↓↓↓↓ ##### diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/MchNotifyRecord.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/MchNotifyRecord.java index e3b1be0..ef3ccc5 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/MchNotifyRecord.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/MchNotifyRecord.java @@ -41,9 +41,10 @@ import java.util.Date; @TableName("t_mch_notify_record") public class MchNotifyRecord extends BaseModel implements Serializable { - //订单类型:1-支付,2-退款 + //订单类型:1-支付,2-退款, 3-转账 public static final byte TYPE_PAY_ORDER = 1; public static final byte TYPE_REFUND_ORDER = 2; + public static final byte TYPE_TRANSFER_ORDER = 3; //通知状态 public static final byte STATE_ING = 1; diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/TransferOrder.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/TransferOrder.java new file mode 100644 index 0000000..cc1037e --- /dev/null +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/TransferOrder.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.core.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 转账订单表 + *

+ * + * @author [mybatis plus generator] + * @since 2021-08-11 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("t_transfer_order") +public class TransferOrder implements Serializable { + + /** 入账方式 **/ + public static final String ENTRY_WX_CASH = "WX_CASH"; + public static final String ENTRY_ALIPAY_CASH = "ALIPAY_CASH"; + public static final String ENTRY_BANK_CARD = "BANK_CARD"; + + public static final byte STATE_INIT = 0; //订单生成 + public static final byte STATE_ING = 1; //转账中 + public static final byte STATE_SUCCESS = 2; //转账成功 + public static final byte STATE_FAIL = 3; //转账失败 + public static final byte STATE_CLOSED = 4; //转账关闭 + + + public static final LambdaQueryWrapper gw(){ + return new LambdaQueryWrapper<>(); + } + + + private static final long serialVersionUID=1L; + + /** + * 转账订单号 + */ + private String transferId; + + /** + * 商户号 + */ + private String mchNo; + + /** + * 服务商号 + */ + private String isvNo; + + /** + * 应用ID + */ + private String appId; + + /** + * 商户名称 + */ + private String mchName; + + /** + * 类型: 1-普通商户, 2-特约商户(服务商模式) + */ + private Byte mchType; + + /** + * 商户订单号 + */ + private String mchOrderNo; + + /** + * 支付接口代码 + */ + private String ifCode; + + /** + * 入账方式: WX_CASH-微信零钱; ALIPAY_CASH-支付宝转账; BANK_CARD-银行卡 + */ + private String entryType; + + /** + * 转账金额,单位分 + */ + private Long amount; + + /** + * 三位货币代码,人民币:cny + */ + private String currency; + + /** + * 收款账号 + */ + private String accountNo; + + /** + * 收款人姓名 + */ + private String accountName; + + /** + * 收款人开户行名称 + */ + private String bankName; + + /** + * 转账备注信息 + */ + private String transferDesc; + + /** + * 客户端IP + */ + private String clientIp; + + /** + * 支付状态: 0-订单生成, 1-转账中, 2-转账成功, 3-转账失败, 4-订单关闭 + */ + private Byte state; + + /** + * 向下游回调状态, 0-未发送, 1-已发送 + */ + private Byte notifyState; + + /** + * 特定渠道发起额外参数 + */ + private String channelExtra; + + /** + * 渠道订单号 + */ + private String channelOrderNo; + + /** + * 渠道支付错误码 + */ + private String errCode; + + /** + * 渠道支付错误描述 + */ + private String errMsg; + + /** + * 商户扩展参数 + */ + private String extParam; + + /** + * 异步通知地址 + */ + private String notifyUrl; + + /** + * 转账成功时间 + */ + private Date successTime; + + /** + * 创建时间 + */ + private Date createdAt; + + /** + * 更新时间 + */ + private Date updatedAt; + +} diff --git a/jeepay-core/src/main/java/com/jeequan/jeepay/core/utils/SeqKit.java b/jeepay-core/src/main/java/com/jeequan/jeepay/core/utils/SeqKit.java index 037f5d4..0d13bcc 100644 --- a/jeepay-core/src/main/java/com/jeequan/jeepay/core/utils/SeqKit.java +++ b/jeepay-core/src/main/java/com/jeequan/jeepay/core/utils/SeqKit.java @@ -34,9 +34,11 @@ public class SeqKit { private static final AtomicLong PAY_ORDER_SEQ = new AtomicLong(0L); private static final AtomicLong REFUND_ORDER_SEQ = new AtomicLong(0L); private static final AtomicLong MHO_ORDER_SEQ = new AtomicLong(0L); + private static final AtomicLong TRANSFER_ID_SEQ = new AtomicLong(0L); private static final String PAY_ORDER_SEQ_PREFIX = "P"; private static final String REFUND_ORDER_SEQ_PREFIX = "R"; private static final String MHO_ORDER_SEQ_PREFIX = "M"; + private static final String TRANSFER_ID_SEQ_PREFIX = "T"; /** 生成支付订单号 **/ public static String genPayOrderId() { @@ -60,4 +62,11 @@ public class SeqKit { (int) MHO_ORDER_SEQ.getAndIncrement() % 10000); } + /** 模拟生成商户订单号 **/ + public static String genTransferId() { + return String.format("%s%s%04d", TRANSFER_ID_SEQ_PREFIX, + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN), + (int) TRANSFER_ID_SEQ.getAndIncrement() % 10000); + } + } diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/IPayOrderQueryService.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/IPayOrderQueryService.java index 179bbd1..d82f17f 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/IPayOrderQueryService.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/IPayOrderQueryService.java @@ -19,7 +19,7 @@ import com.jeequan.jeepay.core.entity.PayOrder; import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; import com.jeequan.jeepay.pay.model.MchAppConfigContext; -/* +/** * 查单(渠道侧)接口定义 * * @author terrfly @@ -28,7 +28,7 @@ import com.jeequan.jeepay.pay.model.MchAppConfigContext; */ public interface IPayOrderQueryService { - /* 获取到接口code **/ + /** 获取到接口code **/ String getIfCode(); /** 查询订单 **/ diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/ITransferService.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/ITransferService.java new file mode 100644 index 0000000..0282db1 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/ITransferService.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.pay.channel; + +import com.jeequan.jeepay.core.entity.TransferOrder; +import com.jeequan.jeepay.pay.model.MchAppConfigContext; +import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; +import com.jeequan.jeepay.pay.rqrs.transfer.TransferOrderRQ; + +/** +* 转账接口 +* +* @author terrfly +* @site https://www.jeepay.vip +* @date 2021/8/11 13:59 +*/ +public interface ITransferService { + + /* 获取到接口code **/ + String getIfCode(); + + /** 是否支持该支付入账方式 */ + boolean isSupport(String entryType); + + /** 前置检查如参数等信息是否符合要求, 返回错误信息或直接抛出异常即可 */ + String preCheck(TransferOrderRQ bizRQ, TransferOrder refundOrder); + + /** 调起退款接口,并响应数据; 内部处理普通商户和服务商模式 **/ + ChannelRetMsg transfer(TransferOrderRQ bizRQ, TransferOrder refundOrder, MchAppConfigContext mchAppConfigContext) throws Exception; + +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/wxpay/WxpayTransferService.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/wxpay/WxpayTransferService.java new file mode 100644 index 0000000..59762ad --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/wxpay/WxpayTransferService.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.pay.channel.wxpay; + +import com.github.binarywang.wxpay.bean.entpay.EntPayRequest; +import com.github.binarywang.wxpay.bean.entpay.EntPayResult; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.jeequan.jeepay.core.constants.CS; +import com.jeequan.jeepay.core.entity.TransferOrder; +import com.jeequan.jeepay.core.model.params.wxpay.WxpayNormalMchParams; +import com.jeequan.jeepay.pay.channel.ITransferService; +import com.jeequan.jeepay.pay.channel.wxpay.kits.WxpayKit; +import com.jeequan.jeepay.pay.model.MchAppConfigContext; +import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; +import com.jeequan.jeepay.pay.rqrs.transfer.TransferOrderRQ; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +/** +* 转账接口: 微信官方 +* +* @author terrfly +* @site https://www.jeepay.vip +* @date 2021/8/11 14:05 +*/ +@Slf4j +@Service +public class WxpayTransferService implements ITransferService { + + @Override + public String getIfCode() { + return CS.IF_CODE.WXPAY; + } + + @Override + public boolean isSupport(String entryType) { + + // 微信仅支持 零钱 和 银行卡入账方式 + if(TransferOrder.ENTRY_WX_CASH.equals(entryType) || TransferOrder.ENTRY_BANK_CARD.equals(entryType)){ + return true; + } + + return false; + } + + @Override + public String preCheck(TransferOrderRQ bizRQ, TransferOrder refundOrder) { + return null; + } + + @Override + public ChannelRetMsg transfer(TransferOrderRQ bizRQ, TransferOrder transferOrder, MchAppConfigContext mchAppConfigContext){ + + try { + + WxpayNormalMchParams params = mchAppConfigContext.getNormalMchParamsByIfCode(getIfCode(), WxpayNormalMchParams.class); + + EntPayRequest request = new EntPayRequest(); + request.setMchAppid(params.getAppId()); // 商户账号appid + request.setMchId(params.getMchId()); //商户号 + + request.setPartnerTradeNo(transferOrder.getTransferId()); //商户订单号 + request.setOpenid(transferOrder.getAccountNo()); //openid + request.setAmount(transferOrder.getAmount().intValue()); //付款金额,单位为分 + request.setSpbillCreateIp(transferOrder.getClientIp()); + request.setDescription(transferOrder.getTransferDesc()); //付款备注 + if(StringUtils.isNotEmpty(transferOrder.getAccountName())){ + request.setReUserName(transferOrder.getAccountName()); + request.setCheckName("FORCE_CHECK"); + }else{ + request.setCheckName("NO_CHECK"); + } + + EntPayResult entPayResult = mchAppConfigContext.getWxServiceWrapper().getWxPayService().getEntPayService().entPay(request); + + // SUCCESS/FAIL,注意:当状态为FAIL时,存在业务结果未明确的情况。如果状态为FAIL,请务必关注错误代码(err_code字段),通过查询接口确认此次付款的结果。 + if("SUCCESS".equalsIgnoreCase(entPayResult.getResultCode())){ + return ChannelRetMsg.confirmSuccess(entPayResult.getPaymentNo()); + }else{ + return ChannelRetMsg.waiting(); + } + + } catch (WxPayException e) { + + //出现未明确的错误码时(SYSTEMERROR等),请务必用原商户订单号重试,或通过查询接口确认此次付款的结果。 + if("SYSTEMERROR".equalsIgnoreCase(e.getErrCode())){ + return ChannelRetMsg.waiting(); + } + + return ChannelRetMsg.confirmFail(null, + WxpayKit.appendErrCode(e.getReturnMsg(), e.getErrCode()), + WxpayKit.appendErrMsg(e.getReturnMsg(), StringUtils.defaultIfEmpty(e.getErrCodeDes(), e.getCustomErrorMsg()))); + + } catch (Exception e) { + log.error("转账异常:", e); + return ChannelRetMsg.waiting(); + } + } + +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/transfer/TransferOrderController.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/transfer/TransferOrderController.java new file mode 100644 index 0000000..096c2ae --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/transfer/TransferOrderController.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.pay.ctrl.transfer; + +import com.jeequan.jeepay.core.entity.MchApp; +import com.jeequan.jeepay.core.entity.MchInfo; +import com.jeequan.jeepay.core.entity.TransferOrder; +import com.jeequan.jeepay.core.exception.BizException; +import com.jeequan.jeepay.core.model.ApiRes; +import com.jeequan.jeepay.core.utils.SeqKit; +import com.jeequan.jeepay.core.utils.SpringBeansUtil; +import com.jeequan.jeepay.core.utils.StringKit; +import com.jeequan.jeepay.pay.channel.ITransferService; +import com.jeequan.jeepay.pay.ctrl.ApiController; +import com.jeequan.jeepay.pay.exception.ChannelException; +import com.jeequan.jeepay.pay.model.MchAppConfigContext; +import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg; +import com.jeequan.jeepay.pay.rqrs.transfer.TransferOrderRQ; +import com.jeequan.jeepay.pay.rqrs.transfer.TransferOrderRS; +import com.jeequan.jeepay.pay.service.ConfigContextService; +import com.jeequan.jeepay.pay.service.PayMchNotifyService; +import com.jeequan.jeepay.service.impl.PayInterfaceConfigService; +import com.jeequan.jeepay.service.impl.TransferOrderService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Date; + +/** +* 转账接口 +* +* @author terrfly +* @site https://www.jeepay.vip +* @date 2021/8/11 11:07 +*/ +@Slf4j +@RestController +public class TransferOrderController extends ApiController { + + @Autowired private ConfigContextService configContextService; + @Autowired private TransferOrderService transferOrderService; + @Autowired private PayInterfaceConfigService payInterfaceConfigService; + @Autowired private PayMchNotifyService payMchNotifyService; + + /** + * 转账 + * **/ + @PostMapping("/api/transferOrder") + public ApiRes transferOrder(){ + + TransferOrder transferOrder = null; + + //获取参数 & 验签 + TransferOrderRQ bizRQ = getRQByWithMchSign(TransferOrderRQ.class); + + try { + + + String mchNo = bizRQ.getMchNo(); + String appId = bizRQ.getAppId(); + String ifCode = bizRQ.getIfCode(); + + // 商户订单号是否重复 + if(transferOrderService.count(TransferOrder.gw().eq(TransferOrder::getMchNo, mchNo).eq(TransferOrder::getMchOrderNo, bizRQ.getMchOrderNo())) > 0){ + throw new BizException("商户订单["+bizRQ.getMchOrderNo()+"]已存在"); + } + + if(StringUtils.isNotEmpty(bizRQ.getNotifyUrl()) && !StringKit.isAvailableUrl(bizRQ.getNotifyUrl())){ + throw new BizException("异步通知地址协议仅支持http:// 或 https:// !"); + } + + // 商户配置信息 + MchAppConfigContext mchAppConfigContext = configContextService.getMchAppConfigContext(mchNo, appId); + if(mchAppConfigContext == null){ + throw new BizException("获取商户应用信息失败"); + } + + MchInfo mchInfo = mchAppConfigContext.getMchInfo(); + MchApp mchApp = mchAppConfigContext.getMchApp(); + + // 是否已正确配置 + if(!payInterfaceConfigService.mchAppHasAvailableIfCode(appId, ifCode)){ + throw new BizException("应用未开通此接口配置!"); + } + + + ITransferService transferService = SpringBeansUtil.getBean(ifCode + "TransferService", ITransferService.class); + if(transferService == null){ + throw new BizException("无此转账通道接口"); + } + + if(!transferService.isSupport(bizRQ.getEntryType())){ + throw new BizException("该接口不支持该入账方式"); + } + + transferOrder = genTransferOrder(bizRQ, mchInfo, mchApp, ifCode); + + //预先校验 + String errMsg = transferService.preCheck(bizRQ, transferOrder); + if(StringUtils.isNotEmpty(errMsg)){ + throw new BizException(errMsg); + } + + // 入库 + transferOrderService.save(transferOrder); + + // 调起上游接口 + ChannelRetMsg channelRetMsg = transferService.transfer(bizRQ, transferOrder, mchAppConfigContext); + + //处理退款单状态 + this.processChannelMsg(channelRetMsg, transferOrder); + + TransferOrderRS bizRes = TransferOrderRS.buildByRecord(transferOrder); + return ApiRes.okWithSign(bizRes, mchApp.getAppSecret()); + + } catch (BizException e) { + return ApiRes.customFail(e.getMessage()); + + } catch (ChannelException e) { + + //处理上游返回数据 + this.processChannelMsg(e.getChannelRetMsg(), transferOrder); + + if(e.getChannelRetMsg().getChannelState() == ChannelRetMsg.ChannelState.SYS_ERROR ){ + return ApiRes.customFail(e.getMessage()); + } + + TransferOrderRS bizRes = TransferOrderRS.buildByRecord(transferOrder); + return ApiRes.okWithSign(bizRes, configContextService.getMchAppConfigContext(bizRQ.getMchNo(), bizRQ.getAppId()).getMchApp().getAppSecret()); + + } catch (Exception e) { + log.error("系统异常:{}", e); + return ApiRes.customFail("系统异常"); + } + } + + + private TransferOrder genTransferOrder(TransferOrderRQ rq, MchInfo mchInfo, MchApp mchApp, String ifCode){ + + TransferOrder transferOrder = new TransferOrder(); + transferOrder.setTransferId(SeqKit.genTransferId()); //生成转账订单号 + transferOrder.setMchNo(mchInfo.getMchNo()); //商户号 + transferOrder.setIsvNo(mchInfo.getIsvNo()); //服务商号 + transferOrder.setAppId(mchApp.getAppId()); //商户应用appId + transferOrder.setMchName(mchInfo.getMchShortName()); //商户名称(简称) + transferOrder.setMchType(mchInfo.getType()); //商户类型 + transferOrder.setMchOrderNo(rq.getMchOrderNo()); //商户订单号 + transferOrder.setIfCode(ifCode); //接口代码 + transferOrder.setEntryType(rq.getEntryType()); //入账方式 + transferOrder.setAmount(rq.getAmount()); //订单金额 + transferOrder.setCurrency(rq.getCurrency()); //币种 + transferOrder.setClientIp(StringUtils.defaultIfEmpty(rq.getClientIp(), getClientIp())); //客户端IP + transferOrder.setState(TransferOrder.STATE_INIT); //订单状态, 默认订单生成状态 + transferOrder.setAccountNo(rq.getAccountNo()); //收款账号 + transferOrder.setAccountName(rq.getAccountName()); //账户姓名 + transferOrder.setBankName(rq.getBankName()); //银行名称 + transferOrder.setTransferDesc(rq.getTransferDesc()); //转账备注 + transferOrder.setExtParam(rq.getExtParam()); //商户扩展参数 + transferOrder.setNotifyUrl(rq.getNotifyUrl()); //异步通知地址 + transferOrder.setCreatedAt(new Date()); //订单创建时间 + return transferOrder; + + } + + + /** + * 处理返回的渠道信息,并更新订单状态 + * TransferOrder将对部分信息进行 赋值操作。 + * **/ + private void processChannelMsg(ChannelRetMsg channelRetMsg, TransferOrder transferOrder){ + + //对象为空 || 上游返回状态为空, 则无需操作 + if(channelRetMsg == null || channelRetMsg.getChannelState() == null){ + return ; + } + + String transferId = transferOrder.getTransferId(); + + //明确成功 + if(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS == channelRetMsg.getChannelState()) { + + this.updateInitOrderStateThrowException(TransferOrder.STATE_SUCCESS, transferOrder, channelRetMsg); + payMchNotifyService.transferOrderNotify(transferOrder); + + //明确失败 + }else if(ChannelRetMsg.ChannelState.CONFIRM_FAIL == channelRetMsg.getChannelState()) { + + this.updateInitOrderStateThrowException(TransferOrder.STATE_FAIL, transferOrder, channelRetMsg); + payMchNotifyService.transferOrderNotify(transferOrder); + + // 上游处理中 || 未知 || 上游接口返回异常 订单为支付中状态 + }else if( ChannelRetMsg.ChannelState.WAITING == channelRetMsg.getChannelState() || + ChannelRetMsg.ChannelState.UNKNOWN == channelRetMsg.getChannelState() || + ChannelRetMsg.ChannelState.API_RET_ERROR == channelRetMsg.getChannelState() + + ){ + this.updateInitOrderStateThrowException(TransferOrder.STATE_ING, transferOrder, channelRetMsg); + + // 系统异常: 订单不再处理。 为: 生成状态 + }else if( ChannelRetMsg.ChannelState.SYS_ERROR == channelRetMsg.getChannelState()){ + + }else{ + + throw new BizException("ChannelState 返回异常!"); + } + + } + + + /** 更新订单状态 --》 订单生成--》 其他状态 (向外抛出异常) **/ + private void updateInitOrderStateThrowException(byte orderState, TransferOrder transferOrder, ChannelRetMsg channelRetMsg){ + + transferOrder.setState(orderState); + transferOrder.setChannelOrderNo(channelRetMsg.getChannelOrderId()); + transferOrder.setErrCode(channelRetMsg.getChannelErrCode()); + transferOrder.setErrMsg(channelRetMsg.getChannelErrMsg()); + + + boolean isSuccess = transferOrderService.updateInit2Ing(transferOrder.getTransferId()); + if(!isSuccess){ + throw new BizException("更新转账订单异常!"); + } + + isSuccess = transferOrderService.updateIng2SuccessOrFail(transferOrder.getTransferId(), transferOrder.getState(), + channelRetMsg.getChannelOrderId(), channelRetMsg.getChannelErrCode(), channelRetMsg.getChannelErrMsg()); + if(!isSuccess){ + throw new BizException("更新转账订单异常!"); + } + } + + +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/QueryTransferOrderRQ.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/QueryTransferOrderRQ.java new file mode 100644 index 0000000..2cea2f1 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/QueryTransferOrderRQ.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.pay.rqrs.transfer; + +import com.jeequan.jeepay.pay.rqrs.AbstractMchAppRQ; +import lombok.Data; + +/* +* 查询转账单请求参数对象 +* +* @author terrfly +* @site https://www.jeequan.com +* @date 2021/6/17 14:07 +*/ +@Data +public class QueryTransferOrderRQ extends AbstractMchAppRQ { + + /** 商户转账单号 **/ + private String mchRefundNo; + + /** 支付系统转账单号 **/ + private String transferId; + +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/QueryTransferOrderRS.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/QueryTransferOrderRS.java new file mode 100644 index 0000000..9d6186e --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/QueryTransferOrderRS.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.pay.rqrs.transfer; + +import com.jeequan.jeepay.core.entity.TransferOrder; +import com.jeequan.jeepay.pay.rqrs.AbstractRS; +import lombok.Data; +import org.springframework.beans.BeanUtils; + +/* +* 查询转账订单 响应参数 +* +* @author terrfly +* @site https://www.jeequan.com +* @date 2021/6/17 14:08 +*/ +@Data +public class QueryTransferOrderRS extends AbstractRS { + + /** + * 转账订单号 + */ + private String transferId; + + /** + * 商户号 + */ + private String mchNo; + + /** + * 应用ID + */ + private String appId; + + /** + * 商户订单号 + */ + private String mchOrderNo; + + /** + * 支付接口代码 + */ + private String ifCode; + + /** + * 入账方式: WX_CASH-微信零钱; ALIPAY_CASH-支付宝转账; BANK_CARD-银行卡 + */ + private String entryType; + + /** + * 转账金额,单位分 + */ + private Long amount; + + /** + * 三位货币代码,人民币:cny + */ + private String currency; + + /** + * 收款账号 + */ + private String accountNo; + + /** + * 收款人姓名 + */ + private String accountName; + + /** + * 收款人开户行名称 + */ + private String bankName; + + /** + * 转账备注信息 + */ + private String transferDesc; + + /** + * 支付状态: 0-订单生成, 1-转账中, 2-转账成功, 3-转账失败, 4-订单关闭 + */ + private Byte state; + + /** + * 特定渠道发起额外参数 + */ + private String channelExtra; + + /** + * 渠道订单号 + */ + private String channelOrderNo; + + /** + * 渠道支付错误码 + */ + private String errCode; + + /** + * 渠道支付错误描述 + */ + private String errMsg; + + /** + * 商户扩展参数 + */ + private String extParam; + + /** + * 转账成功时间 + */ + private Long successTime; + + /** + * 创建时间 + */ + private Long createdAt; + + + public static QueryTransferOrderRS buildByRecord(TransferOrder record){ + + if(record == null){ + return null; + } + + QueryTransferOrderRS result = new QueryTransferOrderRS(); + BeanUtils.copyProperties(record, result); + result.setSuccessTime(record.getSuccessTime() == null ? null : record.getSuccessTime().getTime()); + result.setCreatedAt(record.getCreatedAt() == null ? null : record.getCreatedAt().getTime()); + return result; + } + + +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/TransferOrderRQ.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/TransferOrderRQ.java new file mode 100644 index 0000000..17d5294 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/TransferOrderRQ.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.pay.rqrs.transfer; + +import com.jeequan.jeepay.pay.rqrs.AbstractMchAppRQ; +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/* +* 申请转账 请求参数 +* +* @author terrfly +* @site https://www.jeequan.com +* @date 2021/8/10 11:31 +*/ +@Data +public class TransferOrderRQ extends AbstractMchAppRQ { + + /** 商户订单号 **/ + @NotBlank(message="商户订单号不能为空") + private String mchOrderNo; + + /** 支付接口代码 **/ + @NotBlank(message="支付接口代码不能为空") + private String ifCode; + + /** 入账方式 **/ + @NotBlank(message="入账方式不能为空") + private String entryType; + + /** 支付金额, 单位:分 **/ + @NotNull(message="转账金额不能为空") + @Min(value = 1, message = "转账金额不能小于1分") + private Long amount; + + /** 货币代码 **/ + @NotBlank(message="货币代码不能为空") + private String currency; + + /** 收款账号 **/ + @NotBlank(message="收款账号不能为空") + private String accountNo; + + /** 收款人姓名 **/ + private String accountName; + + /** 收款人开户行名称 **/ + private String bankName; + + /** 客户端IP地址 **/ + private String clientIp; + + /** 转账备注信息 **/ + @NotBlank(message="转账备注信息不能为空") + private String transferDesc; + + /** 异步通知地址 **/ + private String notifyUrl; + + /** 特定渠道发起额外参数 **/ + private String channelExtra; + + /** 商户扩展参数 **/ + private String extParam; + +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/TransferOrderRS.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/TransferOrderRS.java new file mode 100644 index 0000000..57147b5 --- /dev/null +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/transfer/TransferOrderRS.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.pay.rqrs.transfer; + +import com.jeequan.jeepay.core.entity.TransferOrder; +import com.jeequan.jeepay.pay.rqrs.AbstractRS; +import lombok.Data; +import org.springframework.beans.BeanUtils; + +/* +* 创建订单(统一订单) 响应参数 +* +* @author terrfly +* @site https://www.jeequan.com +* @date 2021/6/8 17:34 +*/ +@Data +public class TransferOrderRS extends AbstractRS { + + + /** 转账单号 **/ + private String transferId; + + /** 商户单号 **/ + private String mchOrderNo; + + /** 转账金额 **/ + private Long amount; + + /** + * 收款账号 + */ + private String accountNo; + + /** + * 收款人姓名 + */ + private String accountName; + + /** + * 收款人开户行名称 + */ + private String bankName; + + /** 状态 **/ + private Byte state; + + /** 渠道退款单号 **/ + private String channelOrderNo; + + /** 渠道返回错误代码 **/ + private String errCode; + + /** 渠道返回错误信息 **/ + private String errMsg; + + public static TransferOrderRS buildByRecord(TransferOrder record){ + + if(record == null){ + return null; + } + + TransferOrderRS result = new TransferOrderRS(); + BeanUtils.copyProperties(record, result); + + return result; + } + + + +} diff --git a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/service/PayMchNotifyService.java b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/service/PayMchNotifyService.java index 61cf0b4..014ad23 100644 --- a/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/service/PayMchNotifyService.java +++ b/jeepay-payment/src/main/java/com/jeequan/jeepay/pay/service/PayMchNotifyService.java @@ -21,10 +21,12 @@ import com.jeequan.jeepay.components.mq.vender.IMQSender; import com.jeequan.jeepay.core.entity.MchNotifyRecord; import com.jeequan.jeepay.core.entity.PayOrder; import com.jeequan.jeepay.core.entity.RefundOrder; +import com.jeequan.jeepay.core.entity.TransferOrder; import com.jeequan.jeepay.core.utils.JeepayKit; import com.jeequan.jeepay.core.utils.StringKit; import com.jeequan.jeepay.pay.rqrs.payorder.QueryPayOrderRS; import com.jeequan.jeepay.pay.rqrs.refund.QueryRefundOrderRS; +import com.jeequan.jeepay.pay.rqrs.transfer.QueryTransferOrderRS; import com.jeequan.jeepay.service.impl.MchNotifyRecordService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -138,6 +140,51 @@ public class PayMchNotifyService { } + /** 商户通知信息,转账订单的通知接口 **/ + public void transferOrderNotify(TransferOrder dbTransferOrder){ + + try { + // 通知地址为空 + if(StringUtils.isEmpty(dbTransferOrder.getNotifyUrl())){ + return ; + } + + //获取到通知对象 + MchNotifyRecord mchNotifyRecord = mchNotifyRecordService.findByTransferOrder(dbTransferOrder.getTransferId()); + + if(mchNotifyRecord != null){ + log.info("当前已存在通知消息, 不再发送。"); + return ; + } + + //商户app私钥 + String appSecret = configContextService.getMchAppConfigContext(dbTransferOrder.getMchNo(), dbTransferOrder.getAppId()).getMchApp().getAppSecret(); + + // 封装通知url + String notifyUrl = createNotifyUrl(dbTransferOrder, appSecret); + mchNotifyRecord = new MchNotifyRecord(); + mchNotifyRecord.setOrderId(dbTransferOrder.getTransferId()); + mchNotifyRecord.setOrderType(MchNotifyRecord.TYPE_TRANSFER_ORDER); + mchNotifyRecord.setMchNo(dbTransferOrder.getMchNo()); + mchNotifyRecord.setMchOrderNo(dbTransferOrder.getMchOrderNo()); //商户订单号 + mchNotifyRecord.setIsvNo(dbTransferOrder.getIsvNo()); + mchNotifyRecord.setAppId(dbTransferOrder.getAppId()); + mchNotifyRecord.setNotifyUrl(notifyUrl); + mchNotifyRecord.setResResult(""); + mchNotifyRecord.setNotifyCount(0); + mchNotifyRecord.setState(MchNotifyRecord.STATE_ING); // 通知中 + mchNotifyRecordService.save(mchNotifyRecord); + + //推送到MQ + Long notifyId = mchNotifyRecord.getNotifyId(); + mqSender.send(PayOrderMchNotifyMQ.build(notifyId)); + + } catch (Exception e) { + log.error("推送失败!", e); + } + } + + /** * 创建响应URL */ @@ -172,6 +219,23 @@ public class PayMchNotifyService { } + /** + * 创建响应URL + */ + public String createNotifyUrl(TransferOrder transferOrder, String appSecret) { + + QueryTransferOrderRS rs = QueryTransferOrderRS.buildByRecord(transferOrder); + JSONObject jsonObject = (JSONObject)JSONObject.toJSON(rs); + jsonObject.put("reqTime", System.currentTimeMillis()); //添加请求时间 + + // 报文签名 + jsonObject.put("sign", JeepayKit.getSign(jsonObject, appSecret)); + + // 生成通知 + return StringKit.appendUrlQuery(transferOrder.getNotifyUrl(), jsonObject); + } + + /** * 创建响应URL */ diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/MchNotifyRecordService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/MchNotifyRecordService.java index 0a70edc..6ba1416 100644 --- a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/MchNotifyRecordService.java +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/MchNotifyRecordService.java @@ -49,6 +49,11 @@ public class MchNotifyRecordService extends ServiceImpl 0; + + } + + } diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/TransferOrderService.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/TransferOrderService.java new file mode 100644 index 0000000..078845e --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/TransferOrderService.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.service.impl; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.jeequan.jeepay.core.entity.TransferOrder; +import com.jeequan.jeepay.service.mapper.TransferOrderMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; + +/** + *

+ * 转账订单表 服务实现类 + *

+ * + * @author [mybatis plus generator] + * @since 2021-08-11 + */ +@Service +public class TransferOrderService extends ServiceImpl { + + + /** 更新转账订单状态 【转账订单生成】 --》 【转账中】 **/ + public boolean updateInit2Ing(String transferId){ + + TransferOrder updateRecord = new TransferOrder(); + updateRecord.setState(TransferOrder.STATE_ING); + + return update(updateRecord, new LambdaUpdateWrapper() + .eq(TransferOrder::getTransferId, transferId).eq(TransferOrder::getState, TransferOrder.STATE_INIT)); + } + + + /** 更新转账订单状态 【转账中】 --》 【转账成功】 **/ + @Transactional + public boolean updateIng2Success(String transferId, String channelOrderNo){ + + TransferOrder updateRecord = new TransferOrder(); + updateRecord.setState(TransferOrder.STATE_SUCCESS); + updateRecord.setChannelOrderNo(channelOrderNo); + updateRecord.setSuccessTime(new Date()); + + //更新转账订单表数据 + if(! update(updateRecord, new LambdaUpdateWrapper() + .eq(TransferOrder::getTransferId, transferId).eq(TransferOrder::getState, TransferOrder.STATE_ING)) + ){ + return false; + } + + return true; + } + + + /** 更新转账订单状态 【转账中】 --》 【转账失败】 **/ + @Transactional + public boolean updateIng2Fail(String transferId, String channelOrderNo, String channelErrCode, String channelErrMsg){ + + TransferOrder updateRecord = new TransferOrder(); + updateRecord.setState(TransferOrder.STATE_FAIL); + updateRecord.setErrCode(channelErrCode); + updateRecord.setErrMsg(channelErrMsg); + updateRecord.setChannelOrderNo(channelOrderNo); + + return update(updateRecord, new LambdaUpdateWrapper() + .eq(TransferOrder::getTransferId, transferId).eq(TransferOrder::getState, TransferOrder.STATE_ING)); + } + + + /** 更新转账订单状态 【转账中】 --》 【转账成功/转账失败】 **/ + @Transactional + public boolean updateIng2SuccessOrFail(String transferId, Byte updateState, String channelOrderNo, String channelErrCode, String channelErrMsg){ + + if(updateState == TransferOrder.STATE_ING){ + return true; + }else if(updateState == TransferOrder.STATE_SUCCESS){ + return updateIng2Success(transferId, channelOrderNo); + }else if(updateState == TransferOrder.STATE_FAIL){ + return updateIng2Fail(transferId, channelOrderNo, channelErrCode, channelErrMsg); + } + return false; + } + + + + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/TransferOrderMapper.java b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/TransferOrderMapper.java new file mode 100644 index 0000000..205289f --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/TransferOrderMapper.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * 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. + */ +package com.jeequan.jeepay.service.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jeequan.jeepay.core.entity.TransferOrder; + +/** + *

+ * 转账订单表 Mapper 接口 + *

+ * + * @author [mybatis plus generator] + * @since 2021-08-11 + */ +public interface TransferOrderMapper extends BaseMapper { + +} diff --git a/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/TransferOrderMapper.xml b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/TransferOrderMapper.xml new file mode 100644 index 0000000..c49be1d --- /dev/null +++ b/jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/TransferOrderMapper.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +