From 6edca5478ccd5f0db6aae84cb6a7176992ad9bdc Mon Sep 17 00:00:00 2001 From: eric <465889110@qq.com> Date: Sun, 28 Sep 2025 11:35:45 +0800 Subject: [PATCH] no message --- .../com/sczx/pay/config/SwaggerConfig.java | 2 + .../controller/AliPayNotifyController.java | 49 ++++ .../pay/dto/AlipayFinishFreezeRequest.java | 19 ++ .../sczx/pay/dto/AlipayFundFreezeRequest.java | 16 ++ .../pay/dto/AlipayFundFreezeResponse.java | 14 + .../pay/dto/AlipayQueryFreezeRequest.java | 12 + .../pay/dto/AlipayQueryFreezeResponse.java | 14 + .../com/sczx/pay/mapper/OrderPayMapper.java | 27 +- .../com/sczx/pay/service/AlipayService.java | 25 ++ .../sczx/pay/service/WechatPayService.java | 20 +- .../pay/service/impl/AlipayServiceImpl.java | 253 +++++++++++++++++- .../sczx/pay/thirdpart/facade/SyncFacade.java | 16 ++ .../pay/thirdpart/integration/SyncInteg.java | 34 +++ .../com/sczx/pay/utils/AlipaySdkUtil.java | 4 + .../com/sczx/pay/utils/ThreadPoolUtils.java | 57 ++++ 15 files changed, 543 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/sczx/pay/dto/AlipayFinishFreezeRequest.java create mode 100644 src/main/java/com/sczx/pay/dto/AlipayFundFreezeRequest.java create mode 100644 src/main/java/com/sczx/pay/dto/AlipayFundFreezeResponse.java create mode 100644 src/main/java/com/sczx/pay/dto/AlipayQueryFreezeRequest.java create mode 100644 src/main/java/com/sczx/pay/dto/AlipayQueryFreezeResponse.java create mode 100644 src/main/java/com/sczx/pay/thirdpart/facade/SyncFacade.java create mode 100644 src/main/java/com/sczx/pay/thirdpart/integration/SyncInteg.java create mode 100644 src/main/java/com/sczx/pay/utils/ThreadPoolUtils.java diff --git a/src/main/java/com/sczx/pay/config/SwaggerConfig.java b/src/main/java/com/sczx/pay/config/SwaggerConfig.java index 21050f4..f0c2dc7 100644 --- a/src/main/java/com/sczx/pay/config/SwaggerConfig.java +++ b/src/main/java/com/sczx/pay/config/SwaggerConfig.java @@ -3,6 +3,7 @@ package com.sczx.pay.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ParameterBuilder; import springfox.documentation.builders.PathSelectors; @@ -17,6 +18,7 @@ import java.util.Arrays; @Configuration @EnableSwagger2 +@Profile("!prod") // 除了prod环境外都启用 public class SwaggerConfig { @Bean public Docket createRestApi() { diff --git a/src/main/java/com/sczx/pay/controller/AliPayNotifyController.java b/src/main/java/com/sczx/pay/controller/AliPayNotifyController.java index 0e54192..1c80d7c 100644 --- a/src/main/java/com/sczx/pay/controller/AliPayNotifyController.java +++ b/src/main/java/com/sczx/pay/controller/AliPayNotifyController.java @@ -138,6 +138,55 @@ public class AliPayNotifyController { } } + /** + * 支付宝退款结果通知 + */ + @ApiOperation(value = "支付宝免押通知") + @PostMapping("/freeze/notify") + public String alipayFreezeNotify(HttpServletRequest request) { + try { + // 读取支付宝退款回调数据 + Map params = new HashMap<>(); + Map requestParams = request.getParameterMap(); + for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { + String name = iter.next(); + String[] values = requestParams.get(name); + String valueStr = ""; + for (int i = 0; i < values.length; i++) { + valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; + } + params.put(name, valueStr); + } + + log.info("收到支付宝免押结果通知, 数据: {}", params); + + // 验证签名 + // 注意:支付宝退款通知的签名验证方式可能与支付通知不同 + // 这里简化处理,实际应根据支付宝文档实现 + + + String status = params.get("status"); + + if ("SUCCESS".equals(status)) { + log.warn("支付宝免押通知状态失败: {}", status); + // 处理免押通知 + String outOrderNo = params.get("out_order_no"); + String authNo = params.get("auth_no"); + + // 更新数据库中的免押支付状态 + boolean success = alipayService.processFreezeNotify(outOrderNo,authNo); + if (success) { + log.info("支付宝免押处理完成,支付单号: {}, 支付宝授权资金订单号: {}", + outOrderNo, authNo); + return buildResponse("success"); + } + } + } catch (Exception e) { + log.error("处理支付宝退款通知异常", e); + } + return buildResponse("failure"); + } + private String buildResponse(String result) { return result; } diff --git a/src/main/java/com/sczx/pay/dto/AlipayFinishFreezeRequest.java b/src/main/java/com/sczx/pay/dto/AlipayFinishFreezeRequest.java new file mode 100644 index 0000000..c357861 --- /dev/null +++ b/src/main/java/com/sczx/pay/dto/AlipayFinishFreezeRequest.java @@ -0,0 +1,19 @@ +package com.sczx.pay.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("支付宝资金冻结请求参数") +@Data +public class AlipayFinishFreezeRequest { + private String companyId; + @ApiModelProperty(value = "支付宝资金授权订单号") + private String authNo; + + @ApiModelProperty(value = "解冻请求流水号") + private String outRequestNo; + + @ApiModelProperty(value = "解冻金额") + private String amount; +} diff --git a/src/main/java/com/sczx/pay/dto/AlipayFundFreezeRequest.java b/src/main/java/com/sczx/pay/dto/AlipayFundFreezeRequest.java new file mode 100644 index 0000000..5a6b39e --- /dev/null +++ b/src/main/java/com/sczx/pay/dto/AlipayFundFreezeRequest.java @@ -0,0 +1,16 @@ +package com.sczx.pay.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("支付宝资金冻结请求参数") +@Data +public class AlipayFundFreezeRequest { + private String companyId; + private String outOrderNo; + private String title; + private String amount; + @ApiModelProperty(value = "支付宝资金授权订单号") + private String authNo; +} diff --git a/src/main/java/com/sczx/pay/dto/AlipayFundFreezeResponse.java b/src/main/java/com/sczx/pay/dto/AlipayFundFreezeResponse.java new file mode 100644 index 0000000..bf572f1 --- /dev/null +++ b/src/main/java/com/sczx/pay/dto/AlipayFundFreezeResponse.java @@ -0,0 +1,14 @@ +package com.sczx.pay.dto; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +@ApiModel("支付宝资金冻结响应参数") +@Data +public class AlipayFundFreezeResponse { + private boolean success; + private String message; + private String outTradeNo; // 商户订单号 + private String orderStr; // 支付串(用于前端调起支付) + private String code; // 状态码 +} diff --git a/src/main/java/com/sczx/pay/dto/AlipayQueryFreezeRequest.java b/src/main/java/com/sczx/pay/dto/AlipayQueryFreezeRequest.java new file mode 100644 index 0000000..9ca37c5 --- /dev/null +++ b/src/main/java/com/sczx/pay/dto/AlipayQueryFreezeRequest.java @@ -0,0 +1,12 @@ +package com.sczx.pay.dto; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +@ApiModel("支付宝资金冻结请求参数") +@Data +public class AlipayQueryFreezeRequest { + private String companyId; + private String outOrderNo; + private String operationType; +} diff --git a/src/main/java/com/sczx/pay/dto/AlipayQueryFreezeResponse.java b/src/main/java/com/sczx/pay/dto/AlipayQueryFreezeResponse.java new file mode 100644 index 0000000..9755cc1 --- /dev/null +++ b/src/main/java/com/sczx/pay/dto/AlipayQueryFreezeResponse.java @@ -0,0 +1,14 @@ +package com.sczx.pay.dto; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +@ApiModel("支付宝资金冻结响应参数") +@Data +public class AlipayQueryFreezeResponse { + private boolean success; + private String message; + private String outTradeNo; // 商户订单号 + private String authNo; // 支付串(用于前端调起支付) + private String code; // 状态码 +} diff --git a/src/main/java/com/sczx/pay/mapper/OrderPayMapper.java b/src/main/java/com/sczx/pay/mapper/OrderPayMapper.java index 9630be6..864a2d7 100644 --- a/src/main/java/com/sczx/pay/mapper/OrderPayMapper.java +++ b/src/main/java/com/sczx/pay/mapper/OrderPayMapper.java @@ -29,24 +29,24 @@ public interface OrderPayMapper { "os.payment_method = #{payType}" + " where om.order_id = os.order_id and os.payment_id = #{outTradeNo}") int updateSubOrderPaymentStatus(@Param("outTradeNo") String outTradeNo, - @Param("payType") String payType, - @Param("payStatus") String payStatus, - @Param("transactionId") String transactionId); + @Param("payType") String payType, + @Param("payStatus") String payStatus, + @Param("transactionId") String transactionId); @Update("UPDATE zc_order_main SET order_status = #{orderStatus}" + "WHERE order_no = #{outTradeNo}") int updateOrderStatus(@Param("outTradeNo") String outTradeNo, - @Param("orderStatus") String orderStatus); + @Param("orderStatus") String orderStatus); @Update("UPDATE zc_order_main SET order_status = #{orderStatus} , end_rent_time = #{returnTime}, overdue_days = #{overdueDays}, order_amount = #{orderAmount}" + "WHERE order_no = #{outTradeNo}") int updateOrderStatusAndEndRentTime(@Param("outTradeNo") String outTradeNo,@Param("returnTime") LocalDateTime returnTime,@Param("overdueDays") Integer overdueDays,@Param("orderAmount") BigDecimal orderAmount, - @Param("orderStatus") String orderStatus); + @Param("orderStatus") String orderStatus); @Update("update zc_order_main as om,zc_order_sub as os set os.transaction_id = #{paymentId},os.pay_status = #{payStatus}" + " where om.order_id = os.order_id and om.order_no = #{outTradeNo} and suborder_type = 'DEPOSIT'") int updateRefundOrderStatus(@Param("outTradeNo") String outTradeNo, - @Param("orderStatus") String orderStatus, + @Param("orderStatus") String orderStatus, @Param("transactionId") String transactionId); @@ -58,10 +58,10 @@ public interface OrderPayMapper { @Update("update zc_order_main as om,zc_order_sub as os set os.transaction_id = #{refundId},os.pay_status = #{payStatus}, os.amount = #{refundFee},os.update_time = #{updateTime}" + " where om.order_id = os.order_id and os.payment_id = #{outTradeNo} and os.suborder_type = 'FD_DEPOSIT'" ) int updateSubOrderRefundStatus(@Param("outTradeNo") String outTradeNo, - @Param("payStatus") String payStatus, - @Param("refundFee") BigDecimal refundFee, - @Param("updateTime") Date updateTime, - @Param("refundId") String refundId); + @Param("payStatus") String payStatus, + @Param("refundFee") BigDecimal refundFee, + @Param("updateTime") Date updateTime, + @Param("refundId") String refundId); @Select("select suborder_id from zc_order_sub where payment_id = #{paymentId} and suborder_type = 'RENTBATTEY' limit 1") @@ -70,4 +70,11 @@ public interface OrderPayMapper { @Select("select * from zc_order_sub where payment_id = #{paymentId} order by suborder_id desc limit 1") OrderSub getSubOrderByTradeNo(@Param("paymentId") String paymentId); + /** + * 免押成功,更新子订单状态 + */ + @Update("update zc_order_sub set transaction_id = #{transactionId},pay_status = 'SUCCESS'" + + " where payment_id = #{authNo}") + int updateFreezeSubOrderPaymentStatus(@Param("authNo") String authNo, + @Param("transactionId") String transactionId); } diff --git a/src/main/java/com/sczx/pay/service/AlipayService.java b/src/main/java/com/sczx/pay/service/AlipayService.java index 03cbff6..53bb8b9 100644 --- a/src/main/java/com/sczx/pay/service/AlipayService.java +++ b/src/main/java/com/sczx/pay/service/AlipayService.java @@ -30,6 +30,26 @@ public interface AlipayService { */ AlipayResponse refundQuery(AlipayRefundRequest refundQueryRequest); + /** + * 资金授权冻结接口 + */ + AlipayFundFreezeResponse fundFreeze(AlipayFundFreezeRequest alipayFundFreezeRequest); + + /** + * 撤销资金授权冻结接口 + */ + AlipayFundFreezeResponse cancelFundFreeze(AlipayFundFreezeRequest alipayFundFreezeRequest); + + /** + * 查询资金授权冻结接口 + */ + AlipayQueryFreezeResponse queryFundFreeze(AlipayQueryFreezeRequest alipayQueryFreezeRequest); + + /** + * 完结冻结接口 + */ + AlipayResponse finishFreeze(AlipayFinishFreezeRequest alipayFinishFreezeRequest); + /** * 验证通知签名 */ @@ -44,4 +64,9 @@ public interface AlipayService { * 处理退款通知 */ boolean processRefundNotify(Map notifyMap); + + /** + * 处理免押通知 + */ + boolean processFreezeNotify(String outOrderNo,String authNo); } diff --git a/src/main/java/com/sczx/pay/service/WechatPayService.java b/src/main/java/com/sczx/pay/service/WechatPayService.java index 170a822..5de96b6 100644 --- a/src/main/java/com/sczx/pay/service/WechatPayService.java +++ b/src/main/java/com/sczx/pay/service/WechatPayService.java @@ -11,6 +11,7 @@ import com.sczx.pay.mapper.OrderPayMapper; import com.sczx.pay.mapper.PaymentRecordMapper; import com.sczx.pay.mapper.RefundRecordMapper; import com.sczx.pay.sdk.WXPay; +import com.sczx.pay.thirdpart.integration.SyncInteg; import com.sczx.pay.utils.WXPayUtil; import com.sczx.pay.utils.IPUtils; import org.slf4j.Logger; @@ -51,6 +52,9 @@ public class WechatPayService { @Autowired private OrderPayMapper orderPayMapper; + @Autowired + private SyncInteg syncInteg; + @Value("${wechat.pay.app-id}") private String appId; @@ -271,7 +275,7 @@ public class WechatPayService { refundNotifyUrl ); - String path = certPath+companyConfig.getMchId()+".p12"; + String path = certPath+"wechatpay-"+companyConfig.getMchId()+"/"+companyConfig.getMchId()+".p12"; String certAbsolutePath = getCertAbsolutePath(path); wxPayConfig.setCertPath(certAbsolutePath); @@ -293,9 +297,14 @@ public class WechatPayService { /** * 记录退款信息到数据库 */ - private void recordRefundInfo(RefundRequest request, CompanyWechatConfig companyConfig, Map result,BigDecimal totalFee) { + private void recordRefundInfo(RefundRequest request, CompanyWechatConfig companyConfig, Map result, BigDecimal totalFee) { try { - RefundRecord refundRecord = new RefundRecord(); + RefundRecord refundRecord = refundRecordMapper.getRefundRecordByOutRefundNo(request.getOutRefundNo()); + if (refundRecord != null) { + logger.warn("已存在对应的退款记录,退款单号: {}", request.getOutRefundNo()); + return; + } + refundRecord = new RefundRecord(); refundRecord.setCompanyId(request.getCompanyId()); refundRecord.setOutTradeNo(request.getOutTradeNo()); refundRecord.setOutRefundNo(request.getOutRefundNo()); @@ -316,6 +325,8 @@ public class WechatPayService { refundRecordMapper.insertRefundRecord(refundRecord); logger.info("退款记录已保存,退款单号: {}", request.getOutRefundNo()); + + } catch (Exception e) { logger.error("保存退款记录异常,退款单号: {}", request.getOutRefundNo(), e); } @@ -416,6 +427,9 @@ public class WechatPayService { }else if (OrderStatus.equals("RERENT_WAIT_PAY")){ OrderSub orderSub = orderPayMapper.getSubOrderByTradeNo(outTradeNo); orderPayMapper.updateOrderStatusAndEndRentTime(orderMain.getOrderNo(),orderSub.getReturnTime(),0,orderMain.getOrderAmount().add(orderSub.getAmount()),"RENT_ING"); + //发送租电订单同步 + Long batterySubOrderId = orderPayMapper.getSubOrderIdByTradeNo(outTradeNo); + syncInteg.sendSubOrderId(batterySubOrderId); } orderPayMapper.updateSubOrderPaymentStatus(outTradeNo,"WX_PAY",PayStatus.SUCCESS.getCode(),transactionId); diff --git a/src/main/java/com/sczx/pay/service/impl/AlipayServiceImpl.java b/src/main/java/com/sczx/pay/service/impl/AlipayServiceImpl.java index bf11cae..9bfda61 100644 --- a/src/main/java/com/sczx/pay/service/impl/AlipayServiceImpl.java +++ b/src/main/java/com/sczx/pay/service/impl/AlipayServiceImpl.java @@ -14,8 +14,11 @@ import com.sczx.pay.mapper.OrderPayMapper; import com.sczx.pay.mapper.PaymentRecordMapper; import com.sczx.pay.mapper.RefundRecordMapper; import com.sczx.pay.service.AlipayService; +import com.sczx.pay.thirdpart.integration.SyncInteg; import com.sczx.pay.utils.AlipaySdkUtil; +import com.sczx.pay.utils.ThreadPoolUtils; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -40,9 +43,16 @@ public class AlipayServiceImpl implements AlipayService { @Value("${alipay.refund-notify-url}") private String refundNotifyUrl; + @Value("${alipay.freeze-notify-url}") + private String freezeNotifyUrl; + + @Value("${alipay.alipay-public-cert-path}") private String alipayPublicCertPath; + @Value("${alipay.serviceid}") + private String serviceId ; + @Autowired private PaymentRecordMapper paymentRecordMapper; @@ -53,6 +63,9 @@ public class AlipayServiceImpl implements AlipayService { @Autowired private OrderPayMapper orderPayMapper; + @Autowired + private SyncInteg syncInteg; + @Override public AlipayCreateResponse unifiedOrder(AlipayCreateRequest alipayCreateRequest) { AlipayCreateResponse response = new AlipayCreateResponse(); @@ -277,6 +290,16 @@ public class AlipayServiceImpl implements AlipayService { response.setSuccess(true); response.setCode("SUCCESS"); response.setMessage("退款成功"); + ThreadPoolUtils.getThreadPool().execute(() -> { + refundRecordMapper.updateRefundStatus( + refundQueryRequest.getOutRequestNo(), + refundQueryResponse.getRefundStatus(), + refundQueryResponse.getRefundReason(), + refundQueryRequest.getOutRequestNo(), + new Date(),// 退款成功时间 + new Date() // 更新时间 + ); + }); } else { response.setSuccess(false); response.setCode("FAIL"); @@ -291,6 +314,205 @@ public class AlipayServiceImpl implements AlipayService { return response; } + @Override + public AlipayFundFreezeResponse fundFreeze(AlipayFundFreezeRequest alipayFundFreezeRequest) { + AlipayFundFreezeResponse response = new AlipayFundFreezeResponse(); + try { + // 构造请求参数以调用接口 + AlipayFundAuthOrderAppFreezeRequest request = new AlipayFundAuthOrderAppFreezeRequest(); + AlipayFundAuthOrderAppFreezeModel model = new AlipayFundAuthOrderAppFreezeModel(); + + // 设置订单标题 + model.setOrderTitle(alipayFundFreezeRequest.getTitle()); + + // 设置商户授权资金订单号 + model.setOutOrderNo(alipayFundFreezeRequest.getOutOrderNo()); + + // 设置商户本次资金操作的请求流水号 + model.setOutRequestNo(alipayFundFreezeRequest.getOutOrderNo()); + + // 设置需要冻结的金额 + model.setAmount(alipayFundFreezeRequest.getAmount()); + + // 设置预授权订单相对超时时间 + model.setTimeoutExpress("5m"); + + // 设置销售产品码 + model.setProductCode("PRE_AUTH_ONLINE"); + + // 设置业务扩展参数 + model.setExtraParam("{\"category\": \"CHARGE_PILE_CAR\",\"serviceId\": \""+serviceId+"\"}"); + + // 设置免押受理台模式 + model.setDepositProductMode("DEPOSIT_ONLY"); + + request.setBizModel(model); + + // 设置异步通知地址 + request.setNotifyUrl(freezeNotifyUrl); + log.info("免押冻结请求 : {}",request); + AlipayFundAuthOrderAppFreezeResponse fundAuthOrderAppFreezeResponse = alipaySdkUtil.sdkExecute(request); + log.info("免押冻结响应 : {}",fundAuthOrderAppFreezeResponse.getBody()); + + if (fundAuthOrderAppFreezeResponse.isSuccess()) { + response.setOrderStr(fundAuthOrderAppFreezeResponse.getBody()); + response.setSuccess(true); + response.setCode("SUCCESS"); + response.setMessage("免押冻结成功"); + + } else { + response.setSuccess(false); + response.setCode("FAIL"); + response.setMessage("免押冻结失败: " + fundAuthOrderAppFreezeResponse.getMsg() + ":" + fundAuthOrderAppFreezeResponse.getSubMsg()); + } + } catch (Exception e) { + log.error("支付宝免押冻结异常,公司ID: {}, 订单号: {}", alipayFundFreezeRequest.getCompanyId(), alipayFundFreezeRequest.getOutOrderNo(), e); + response.setSuccess(false); + response.setCode("FAIL"); + response.setMessage("支付宝免押冻结失败异常: " + e.getMessage()); + } + return response; + } + + @Override + public AlipayFundFreezeResponse cancelFundFreeze(AlipayFundFreezeRequest alipayFundFreezeRequest) { + AlipayFundFreezeResponse response = new AlipayFundFreezeResponse(); + try { + // 构造请求参数以调用接口 + AlipayFundAuthOperationCancelRequest request = new AlipayFundAuthOperationCancelRequest(); + AlipayFundAuthOperationCancelModel model = new AlipayFundAuthOperationCancelModel(); + + // 设置商户的授权资金订单号 + model.setOutOrderNo(alipayFundFreezeRequest.getOutOrderNo()); + + // 设置商户的授权资金操作流水号 + model.setOutRequestNo(alipayFundFreezeRequest.getOutOrderNo()); + + //设置商户的授权资金操作流水号 + model.setAuthNo(alipayFundFreezeRequest.getAuthNo()); + + // 设置商户对本次撤销操作的附言描述 + model.setRemark(alipayFundFreezeRequest.getTitle()); + + request.setBizModel(model); + + request.setBizModel(model); + log.info("取消免押冻结请求 : {}",request.getTextParams()); + AlipayFundAuthOperationCancelResponse fundAuthOperationCancelResponse = alipaySdkUtil.execute(request); + log.info("取消免押冻结响应 : {}",fundAuthOperationCancelResponse.getBody()); + + if (fundAuthOperationCancelResponse.isSuccess()) { + response.setSuccess(true); + response.setCode("SUCCESS"); + response.setMessage("取消免押冻结成功"); + + } else { + response.setSuccess(false); + response.setCode("FAIL"); + response.setMessage("取消免押冻结失败: " + fundAuthOperationCancelResponse.getMsg() + ":" + fundAuthOperationCancelResponse.getSubMsg()); + } + } catch (Exception e) { + log.error("支付宝取消免押冻结异常,公司ID: {}, 订单号: {}", alipayFundFreezeRequest.getCompanyId(), alipayFundFreezeRequest.getOutOrderNo(), e); + response.setSuccess(false); + response.setCode("FAIL"); + response.setMessage("支付宝取消免押冻结失败异常: " + e.getMessage()); + } + return response; + } + + @Override + public AlipayQueryFreezeResponse queryFundFreeze(AlipayQueryFreezeRequest alipayQueryFreezeRequest) { + AlipayQueryFreezeResponse response = new AlipayQueryFreezeResponse(); + try { + // 构造请求参数以调用接口 + AlipayFundAuthOperationDetailQueryRequest request = new AlipayFundAuthOperationDetailQueryRequest(); + AlipayFundAuthOperationDetailQueryModel model = new AlipayFundAuthOperationDetailQueryModel(); +// +// // 设置支付宝授权资金订单号 +// model.setAuthNo("2014021601002000640012345678"); + + // 设置商户的授权资金订单号 + model.setOutOrderNo(alipayQueryFreezeRequest.getOutOrderNo()); + +// // 设置支付宝的授权资金操作流水号 +// model.setOperationId("20140216010020006400"); + + // 设置商户的授权资金操作流水号 + model.setOutRequestNo(alipayQueryFreezeRequest.getOutOrderNo()); + + // 设置需要查询的授权资金操作类型 + model.setOperationType(alipayQueryFreezeRequest.getOperationType()); + + request.setBizModel(model); + log.info("查询免押冻结请求 : {}",request); + AlipayFundAuthOperationDetailQueryResponse queryResponse = alipaySdkUtil.execute(request); + log.info("查询免押冻结响应 : {}",queryResponse.getBody()); + + if (queryResponse.isSuccess() && StringUtils.equalsIgnoreCase(queryResponse.getOrderStatus(), "AUTHORIZED")) { + response.setSuccess(true); + response.setCode("SUCCESS"); + response.setAuthNo(queryResponse.getAuthNo()); + response.setOutTradeNo(queryResponse.getOutOrderNo()); + response.setMessage("查询免押冻结成功"); + + } else { + response.setSuccess(false); + response.setCode("FAIL"); + response.setMessage("查询免押冻结失败: " + queryResponse.getMsg() + ":" + queryResponse.getSubMsg()); + } + } catch (Exception e) { + log.error("支付宝查询免押冻结异常,公司ID: {}, 订单号: {}", alipayQueryFreezeRequest.getCompanyId(), alipayQueryFreezeRequest.getOutOrderNo(), e); + response.setSuccess(false); + response.setCode("FAIL"); + response.setMessage("支付宝查询免押冻结失败异常: " + e.getMessage()); + } + return response; + } + + @Override + public AlipayResponse finishFreeze(AlipayFinishFreezeRequest alipayFinishFreezeRequest) { + AlipayResponse response = new AlipayResponse(); + try { + // 构造请求参数以调用接口 + AlipayFundAuthOrderUnfreezeRequest request = new AlipayFundAuthOrderUnfreezeRequest(); + AlipayFundAuthOrderUnfreezeModel model = new AlipayFundAuthOrderUnfreezeModel(); + + // 设置支付宝资金授权订单号 + model.setAuthNo(alipayFinishFreezeRequest.getAuthNo()); + + // 设置解冻请求流水号 + model.setOutRequestNo(alipayFinishFreezeRequest.getOutRequestNo()); + + // 设置本次操作解冻的金额 + model.setAmount(alipayFinishFreezeRequest.getAmount()); + + // 设置商户对本次解冻操作的附言描述 + model.setRemark("还车解冻押金"); + request.setBizModel(model); + // 第三方代调用模式下请设置app_auth_token + // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->"); + log.info("完结免押冻结请求 : {}",request); + AlipayFundAuthOrderUnfreezeResponse unFreezeResponse = alipaySdkUtil.execute(request); + log.info("完结免押冻结响应 : {}",unFreezeResponse.getBody()); + + if (unFreezeResponse.isSuccess()) { + response.setSuccess(true); + response.setCode("SUCCESS"); + response.setMessage("完结免押冻结成功"); + } else { + response.setSuccess(false); + response.setCode("FAIL"); + response.setMessage("完结免押冻结失败: " + unFreezeResponse.getMsg() + ":" + unFreezeResponse.getSubMsg()); + } + } catch (Exception e) { + log.error("支付宝完结免押冻结异常,公司ID: {}, 订单号: {}", alipayFinishFreezeRequest.getCompanyId(), alipayFinishFreezeRequest.getOutRequestNo(), e); + response.setSuccess(false); + response.setCode("FAIL"); + response.setMessage("支付宝完结免押冻结失败异常: " + e.getMessage()); + } + return response; + } + @Override public boolean verifyNotifySign(Long companyId, Map params) { try { @@ -332,6 +554,9 @@ public class AlipayServiceImpl implements AlipayService { }else if (OrderStatus.equals("RERENT_WAIT_PAY")){ OrderSub orderSub = orderPayMapper.getSubOrderByTradeNo(outTradeNo); orderPayMapper.updateOrderStatusAndEndRentTime(orderMain.getOrderNo(),orderSub.getReturnTime(),0,orderMain.getOrderAmount().add(orderSub.getAmount()),"RENT_ING"); + //发送租电订单同步 + Long batterySubOrderId = orderPayMapper.getSubOrderIdByTradeNo(outTradeNo); + syncInteg.sendSubOrderId(batterySubOrderId); } orderPayMapper.updateSubOrderPaymentStatus(outTradeNo,"ZFB_PAY", PayStatus.SUCCESS.getCode(),tradeNo); return true; @@ -395,7 +620,7 @@ public class AlipayServiceImpl implements AlipayService { refundStatus, statusDesc, outRequestNo, - "SUCCESS".equals(refundStatus) ? new Date() : null, // 退款成功时间 + "REFUND_SUCCESS".equals(refundStatus) ? new Date() : null, // 退款成功时间 new Date() // 更新时间 ); @@ -403,15 +628,27 @@ public class AlipayServiceImpl implements AlipayService { log.info("支付宝退款记录状态已更新,退款单号: {}, 支付宝退款单号: {}, 状态: {}", outRequestNo, outRequestNo, refundStatus); return true; } else { - log.warn("未找到对应的微信退款记录,退款单号: {}", outRequestNo); + log.warn("未找到对应的支付宝退款记录,退款单号: {}", outRequestNo); return false; } } catch (Exception e) { - log.error("处理微信退款通知异常,退款单号: {}", notifyMap.get("out_request_no"), e); + log.error("处理支付宝退款通知异常,退款单号: {}", notifyMap.get("out_request_no"), e); return false; } } + @Override + public boolean processFreezeNotify(String outOrderNo, String authNo) { + try { + log.info("处理支付宝免押支付成功通知, 更新状态,订单号: {}, 授权号: {}", outOrderNo, authNo); + int result = orderPayMapper.updateFreezeSubOrderPaymentStatus(outOrderNo, authNo); + return result>0; + } catch (Exception e) { + log.error("处理支付宝免押支付成功通知异常,订单号: {}", outOrderNo, e); + } + return false; + } + /** * 记录支付信息到数据库 */ @@ -442,9 +679,13 @@ public class AlipayServiceImpl implements AlipayService { */ private void recordRefundInfo(AlipayRefundRequest request) { try { - PaymentRecord paymentRecord = paymentRecordMapper.getPaymentRecordByOutTradeNo(request.getOutTradeNo()); - - RefundRecord refundRecord = new RefundRecord(); + PaymentRecord paymentRecord = paymentRecordMapper.getPaymentRecordByOutTradeNo(request.getOutTradeNo()); + RefundRecord refundRecord = refundRecordMapper.getRefundRecordByOutRefundNo(request.getOutRequestNo()); + if (refundRecord != null) { + log.warn("已存在对应的退款记录,退款单号: {}", request.getOutRequestNo()); + return; + } + refundRecord = new RefundRecord(); refundRecord.setCompanyId(request.getCompanyId()); refundRecord.setOutTradeNo(request.getOutTradeNo()); refundRecord.setOutRefundNo(request.getOutRequestNo()); diff --git a/src/main/java/com/sczx/pay/thirdpart/facade/SyncFacade.java b/src/main/java/com/sczx/pay/thirdpart/facade/SyncFacade.java new file mode 100644 index 0000000..dc272fc --- /dev/null +++ b/src/main/java/com/sczx/pay/thirdpart/facade/SyncFacade.java @@ -0,0 +1,16 @@ +package com.sczx.pay.thirdpart.facade; + + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +import java.util.Map; + +@FeignClient(name = "sczx-sync", url = "${sczx-sync.ribbon.listOfServers:}") +public interface SyncFacade { + + @GetMapping("/send/subOrder/{subOrderId}") + Map sendSubOrderId(@PathVariable Long subOrderId); + +} \ No newline at end of file diff --git a/src/main/java/com/sczx/pay/thirdpart/integration/SyncInteg.java b/src/main/java/com/sczx/pay/thirdpart/integration/SyncInteg.java new file mode 100644 index 0000000..a431283 --- /dev/null +++ b/src/main/java/com/sczx/pay/thirdpart/integration/SyncInteg.java @@ -0,0 +1,34 @@ +package com.sczx.pay.thirdpart.integration; + + +import com.sczx.pay.exception.InnerException; +import com.sczx.pay.thirdpart.facade.SyncFacade; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +@Slf4j +@Component +public class SyncInteg { + + @Autowired + private SyncFacade syncFacade; + + public Map sendSubOrderId(Long subOrderId){ + try{ + Map result = syncFacade.sendSubOrderId(subOrderId); + if(result.get("code") == "200"){ + return result; + } + } catch (Exception e){ + log.error("发送租电订单同步失败",e); + throw new InnerException("发送租电订单同步失败"); + } + return null; + } + + + +} diff --git a/src/main/java/com/sczx/pay/utils/AlipaySdkUtil.java b/src/main/java/com/sczx/pay/utils/AlipaySdkUtil.java index 439b884..0b4664f 100644 --- a/src/main/java/com/sczx/pay/utils/AlipaySdkUtil.java +++ b/src/main/java/com/sczx/pay/utils/AlipaySdkUtil.java @@ -68,6 +68,10 @@ public class AlipaySdkUtil { return alipayClient.certificateExecute(request); } + public T sdkExecute(AlipayRequest request) throws AlipayApiException { + return alipayClient.sdkExecute(request); + } + private AlipayConfig getAlipayConfig() { AlipayConfig alipayConfig = new AlipayConfig(); alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do"); diff --git a/src/main/java/com/sczx/pay/utils/ThreadPoolUtils.java b/src/main/java/com/sczx/pay/utils/ThreadPoolUtils.java new file mode 100644 index 0000000..0993588 --- /dev/null +++ b/src/main/java/com/sczx/pay/utils/ThreadPoolUtils.java @@ -0,0 +1,57 @@ +package com.sczx.pay.utils; + +import org.springframework.stereotype.Service; + +import java.util.concurrent.*; + +/** + * 线程池工具类,用于执行异步任务 + * Created by zengji on 2019/5/13. + * + */ +@Service +public class ThreadPoolUtils { + + public static ThreadPoolExecutor threadPool; + //核心线程大小 + private static int corePoolSize=120; + //最大线程个数 + private static int maximumPoolSize=180; + //空闲线程存活时间 + private static long keepAliveTime=300; + //队列容量 + private static int capacity=200; + + /** + * 无返回值 + */ + public static void execute(Runnable runnable){ + getThreadPool().execute(runnable); + } + + /** + * 有返回值 + */ + public static Future submit(Callable callable){ + return getThreadPool().submit(callable); + } + + + /** + * dcs获取线程池 + * @return 线程池对象 + */ + public static ThreadPoolExecutor getThreadPool() { + if (threadPool != null) { + return threadPool; + } else { + synchronized (ThreadPoolUtils.class) { + if (threadPool == null) { + threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(capacity), new ThreadPoolExecutor.CallerRunsPolicy()); + } + return threadPool; + } + } + } +}