提交租赁订单支付接口

This commit is contained in:
2025-09-06 23:50:55 +08:00
parent ec7b992d92
commit 002a549f86
7 changed files with 318 additions and 1 deletions

View File

@ -1,13 +1,84 @@
package com.sczx.pay.controller;
import com.sczx.pay.service.AlipayRentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@Api(value = "支付宝租赁订单回调接口", tags = "支付宝租赁订单回调接口")
@Slf4j
@RestController
@RequestMapping("/alipay/rent/notify")
public class AlipayRentNotifyController {
@Autowired
private AlipayRentService alipayRentService;
/**
* 支付宝租赁订单支付结果通知
*/
@ApiOperation(value = "支付宝租赁订单支付结果通知")
@PostMapping("/pay")
public String alipayNotify(HttpServletRequest request) {
try {
// 读取支付宝回调数据
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> 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);
}
String outTradeNo = params.get("out_trade_no");
String companyIdStr = params.get("passback_params"); // 通过回传参数获取公司ID
Long companyId = companyIdStr != null ? Long.parseLong(companyIdStr) : null;
log.info("收到支付宝租赁订单支付通知,数据: {}, 商户订单号: {}", params, outTradeNo);
// 验证签名
// if (!alipayService.verifyNotifySign(companyId, params)) {
// log.warn("支付宝支付通知签名验证失败公司ID: {}", companyId);
// return buildResponse("failure");
// }
String tradeStatus = params.get("trade_status");
if (!"TRADE_SUCCESS".equals(tradeStatus) && !"TRADE_FINISHED".equals(tradeStatus)) {
log.warn("支付宝支付通知状态失败,商户订单号: {}: {}", outTradeNo, tradeStatus);
return "success"; // 状态不是成功时也返回success避免重复通知
}
// 处理支付成功的业务逻辑
String tradeNo = params.get("trade_no");
String totalAmount = params.get("total_amount");
// 更新数据库中的订单状态
boolean success = alipayRentService.processPaySuccessNotify(params);
if (success) {
log.info("支付宝支付成功公司ID: {}, 订单号: {}, 支付宝交易号: {}, 金额: {}",
companyId, outTradeNo, tradeNo, totalAmount);
return "success";
} else {
log.error("更新支付宝支付状态失败公司ID: {}, 订单号: {}", companyId, outTradeNo);
return "failure";
}
} catch (Exception e) {
log.error("处理支付宝支付通知异常", e);
return "failure";
}
}
}

View File

@ -0,0 +1,13 @@
package com.sczx.pay.dto.ali.rent;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@ApiModel(value = "支付宝租赁订单支付请求")
@Data
public class AlipayRentPayReq {
private Long companyId; // 公司ID
private String outTradeNo; // 商户订单号
private String orderId; //交易组件业务订单号
private String payAmount; // 支付金额
}

View File

@ -0,0 +1,17 @@
package com.sczx.pay.dto.ali.rent;
import com.sczx.pay.dto.AlipayResponse;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "支付宝租赁订单支付结果")
@Data
public class AlipayRentPayResponse extends AlipayResponse {
private String tradeNo; // 支付宝交易号
private String outTradeNo; // 商户订单号
private String orderId; //交易组件业务订单号
private String payAmount; // 支付金额
}

View File

@ -14,6 +14,7 @@ public class PaymentRecord {
private BigDecimal totalFee; // 订单金额
private String body; // 商品描述
private String openid; // 用户标识(微信支付专用)
private String tradeCompOrderId; // 支付宝交易组件订单号
private String tradeState; // 交易状态
private String tradeStateDesc; // 交易状态描述
private Date createTime; // 创建时间
@ -26,7 +27,8 @@ public class PaymentRecord {
// 支付渠道枚举
public enum PayChannel {
WECHAT("微信支付"),
ALIPAY("支付宝");
ALIPAY("支付宝"),
ALIPAY_RENT("支付宝租赁支付");
private final String description;
@ -164,4 +166,12 @@ public class PaymentRecord {
public void setBuyerId(String buyerId) {
this.buyerId = buyerId;
}
public String getTradeCompOrderId() {
return tradeCompOrderId;
}
public void setTradeCompOrderId(String tradeCompOrderId) {
this.tradeCompOrderId = tradeCompOrderId;
}
}

View File

@ -1,4 +1,23 @@
package com.sczx.pay.service;
import com.sczx.pay.dto.ali.rent.AlipayRentPayReq;
import com.sczx.pay.dto.ali.rent.AlipayRentPayResponse;
import java.util.Map;
public interface AlipayRentService {
/**
* 租赁订单支付
* @param request
* @return
*/
AlipayRentPayResponse rentPay(AlipayRentPayReq request);
/**
* 支付成功回调
* @param notifyMap
* @return
*/
boolean processPaySuccessNotify(Map<String, String> notifyMap);
}

View File

@ -1,10 +1,194 @@
package com.sczx.pay.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.domain.AlipayCommerceRentOrderPayModel;
import com.alipay.api.domain.RentPayItemDTO;
import com.alipay.api.request.AlipayCommerceRentOrderPayRequest;
import com.alipay.api.response.AlipayCommerceRentOrderPayResponse;
import com.sczx.pay.config.AlipayConf;
import com.sczx.pay.dto.ali.rent.AlipayRentPayReq;
import com.sczx.pay.dto.ali.rent.AlipayRentPayResponse;
import com.sczx.pay.entity.OrderMain;
import com.sczx.pay.entity.PayStatus;
import com.sczx.pay.entity.PaymentRecord;
import com.sczx.pay.mapper.OrderPayMapper;
import com.sczx.pay.mapper.PaymentRecordMapper;
import com.sczx.pay.mapper.RefundRecordMapper;
import com.sczx.pay.service.AlipayRentService;
import com.sczx.pay.utils.AlipaySdkUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class AlipayRentServiceImpl implements AlipayRentService {
@Autowired
private AlipayConf alipayConf;
@Autowired
private AlipaySdkUtil alipaySdkUtil;
@Value("${alipay.rent.payNotifyUrl}")
private String notifyUrl;
@Autowired
private PaymentRecordMapper paymentRecordMapper;
@Autowired
private RefundRecordMapper refundRecordMapper;
@Autowired
private OrderPayMapper orderPayMapper;
@Override
public AlipayRentPayResponse rentPay(AlipayRentPayReq alipayRentPayReq) {
AlipayRentPayResponse response = new AlipayRentPayResponse();
try {
// 构造请求参数以调用接口
AlipayCommerceRentOrderPayRequest request = new AlipayCommerceRentOrderPayRequest();
AlipayCommerceRentOrderPayModel model = new AlipayCommerceRentOrderPayModel();
// 设置租金支付外部请求号
model.setOutTradeNo(alipayRentPayReq.getOutTradeNo());
// 设置业务订单号
model.setOrderId(alipayRentPayReq.getOrderId());
// 设置支付方式pay_method还可以选择PRE_AUTH 预授权支付。部分支付场景不可使用租赁代扣 RENT_DEDUCT
model.setPayMethod("JSAPI");
// 设置支付金额
model.setPayAmount(alipayRentPayReq.getPayAmount());
// 设置订单费用项明细列表
List<RentPayItemDTO> payItems = new ArrayList<RentPayItemDTO>();
RentPayItemDTO payItems0 = new RentPayItemDTO();
payItems0.setType("RENT");
payItems0.setPayAmount(alipayRentPayReq.getPayAmount());
payItems.add(payItems0);
model.setPayItems(payItems);
//二级商户信息
// RentSubMerchantDTO rentSubMerchantDTO = new RentSubMerchantDTO();
// rentSubMerchantDTO.setMerchantId(alipayConf.getCompanyAppid(alipayRentPayReq.getCompanyId()));
// model.setSubMerchant(rentSubMerchantDTO);
// 设置支付结果通知地址
model.setPayNotifyUrl(notifyUrl);
// 设置支付超时时间
model.setPayTimeoutExpress("15m");
request.setBizModel(model);
// 第三方代调用模式下请设置app_auth_token
// request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
// 第三方代调用模式下请设置app_auth_token
// request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
log.info("支付宝租赁订单下单请求:{}", JSONObject.toJSONString(request));
AlipayCommerceRentOrderPayResponse rentOrderPayResponse = alipaySdkUtil.execute(request);
log.info("支付宝租赁订单下单下单返回:{}", JSONObject.toJSONString(rentOrderPayResponse));
if (rentOrderPayResponse.isSuccess()) {
response.setSuccess(true);
response.setOutTradeNo(rentOrderPayResponse.getOutTradeNo());
response.setTradeNo(rentOrderPayResponse.getTradeNo());
response.setCode("SUCCESS");
response.setMessage("下单成功");
//保存支付单
recordPaymentInfo(alipayRentPayReq);
} else {
response.setSuccess(false);
response.setCode("FAIL");
response.setMessage("下单失败: " + rentOrderPayResponse.getMsg() + ":" + rentOrderPayResponse.getSubMsg());
}
} catch (Exception e) {
log.error("支付宝下单异常公司ID: {}, 订单号: {}", alipayRentPayReq.getCompanyId(), alipayRentPayReq.getOutTradeNo(), e);
response.setSuccess(false);
response.setCode("FAIL");
response.setMessage("下单异常: " + e.getMessage());
}
return response;
}
@Override
public boolean processPaySuccessNotify(Map<String, String> notifyMap) {
try {
// 这里实现您的业务逻辑
// 例如:更新订单状态、发送通知等
String outTradeNo = notifyMap.get("out_trade_no");
String tradeNo = notifyMap.get("trade_no");
String totalAmount = notifyMap.get("total_amount");
log.info("处理支付宝租赁订单支付成功通知,订单号: {}, 交易号: {}, 金额: {}",
outTradeNo, tradeNo, totalAmount);
// 更新支付记录状态
int updated = paymentRecordMapper.updateToSuccess(
outTradeNo,
tradeNo,
new Date(), // 支付时间
new Date() // 更新时间
);
if (updated > 0) {
log.info("支付宝支付记录状态已更新,订单号: {}, 支付宝交易号: {}", outTradeNo, tradeNo);
//更新主订单状态
OrderMain orderMain = orderPayMapper.getOrderStatusByOrderNo(outTradeNo);
String OrderStatus = orderMain.getOrderStatus();
if(OrderStatus.equals("WAIT_PAY")){
orderPayMapper.updateOrderStatus(orderMain.getOrderNo(),"WAIT_PICK");
}else if (OrderStatus.equals("RERENT_WAIT_PAY")){
orderPayMapper.updateOrderStatus(orderMain.getOrderNo(),"RENT_ING");
}
orderPayMapper.updateSubOrderPaymentStatus(outTradeNo,"ZFB_PAY", PayStatus.SUCCESS.getCode(),tradeNo);
return true;
} else {
log.warn("未找到对应的支付宝支付记录,订单号: {}", outTradeNo);
return false;
}
} catch (Exception e) {
log.error("处理支付宝支付成功通知异常", e);
return false;
}
}
/**
* 记录支付信息到数据库
*/
private void recordPaymentInfo(AlipayRentPayReq alipayRentPayReq) {
try {
PaymentRecord paymentRecord = new PaymentRecord();
paymentRecord.setCompanyId(alipayRentPayReq.getCompanyId());
paymentRecord.setOutTradeNo(alipayRentPayReq.getOutTradeNo());
paymentRecord.setTotalFee(new BigDecimal(alipayRentPayReq.getPayAmount())); // 转换为元
paymentRecord.setTradeCompOrderId(alipayRentPayReq.getOrderId());
paymentRecord.setTradeState("NOTPAY"); // 未支付
paymentRecord.setTradeStateDesc("未支付");
paymentRecord.setCreateTime(new Date());
paymentRecord.setUpdateTime(new Date());
// paymentRecord.setAttach(request.getAttach());
paymentRecord.setPayChannel(PaymentRecord.PayChannel.ALIPAY_RENT.name()); // 设置支付渠道为支付宝支付
paymentRecordMapper.insertPaymentRecord(paymentRecord);
log.info("支付记录已保存,订单号: {}", alipayRentPayReq.getOutTradeNo());
} catch (Exception e) {
log.error("保存支付记录异常,订单号: {}", alipayRentPayReq.getOutTradeNo(), e);
}
}
}

View File

@ -91,3 +91,6 @@ alipay:
alipay-root-cert-path: /root/cert/alipayRootCert.crt
notify-url: http://115.190.8.52:8019/alipay/pay/notify
refund-notify-url: http://115.190.8.52:8019/alipay/refund/notify
rent:
payNotifyUrl: http://115.190.8.52:8019/alipay/rent/notify/pay