diff --git a/ebike-payment/pom.xml b/ebike-payment/pom.xml
index 036b922e..61176243 100644
--- a/ebike-payment/pom.xml
+++ b/ebike-payment/pom.xml
@@ -32,12 +32,12 @@
ebike-feign
0.0.1-SNAPSHOT
-
- com.github.wechatpay-apiv3
- wechatpay-java
- 0.2.17
+ org.springframework.boot
+ spring-boot-starter-web
+ ${boot.version}
+
com.mybatis-flex
@@ -50,6 +50,33 @@
${mybatis-flex.version}
provided
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+ ${nacos.version}
+
+
+ com.mysql
+ mysql-connector-j
+ ${mysql.version}
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter
+ ${boot.version}
+
+
+ org.springframework.cloud
+ spring-cloud-starter-loadbalancer
+
+
+
+ com.github.wechatpay-apiv3
+ wechatpay-java
+ 0.2.17
+
org.projectlombok
lombok
@@ -101,28 +128,6 @@
fastjson2
${fastjson.version}
-
-
- com.alibaba.cloud
- spring-cloud-starter-alibaba-nacos-discovery
- ${nacos.version}
-
-
- org.springframework.cloud
- spring-cloud-starter-loadbalancer
-
-
- com.mysql
- mysql-connector-j
- ${mysql.version}
- runtime
-
-
- jakarta.servlet
- jakarta.servlet-api
- 6.0.0
- provided
-
org.springframework.boot
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/EbikePaymentApplication.java b/ebike-payment/src/main/java/com/cdzy/payment/EbikePaymentApplication.java
index f4aaa2e2..950d1016 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/EbikePaymentApplication.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/EbikePaymentApplication.java
@@ -3,6 +3,7 @@ package com.cdzy.payment;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
@@ -14,6 +15,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
*/
@SpringBootApplication
@MapperScan("com.cdzy.payment.mapper")
+@EnableFeignClients(basePackages = "com.ebike.feign")
public class EbikePaymentApplication {
public static void main(String[] args) {
SpringApplication.run(EbikePaymentApplication.class, args);
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java b/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java
index 2b42de6a..a5f281ae 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/config/WxPayConfig.java
@@ -3,6 +3,7 @@ package com.cdzy.payment.config;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.cipher.RSASigner;
+import com.wechat.pay.java.core.cipher.Signer;
import com.wechat.pay.java.core.util.PemUtil;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.refund.RefundService;
@@ -62,9 +63,14 @@ public class WxPayConfig {
private String refundNotifyUrl;
/**
* 支付、退款过期时间(分钟)
- * 默认5分钟,超过5分钟订单会自动关闭
+ * 默认24小时,超过24小时订单会自动关闭
*/
- private Integer expireMinute = 5;
+ private Integer expireMinute = 1440;
+ /**
+ * 定时任务执行表达式
+ * 默认每12小时执行1次
+ */
+ private String cronExpression = "0 0 0,12 * * ?";
@Bean
public Config certificateConfig() {
@@ -90,9 +96,8 @@ public class WxPayConfig {
}
@Bean
- public RSASigner wxRsaSigner(){
- PrivateKey privateKey = PemUtil.loadPrivateKeyFromPath(privateKeyPath);
- return new RSASigner(merchantSerialNumber, privateKey);
+ public Signer wxRsaSigner(Config certificateConfig){
+ return certificateConfig.createSigner();
}
}
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java b/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java
index 9f7509f5..4882b754 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/controller/EbikeWxPaymentController.java
@@ -31,7 +31,7 @@ public class EbikeWxPaymentController {
* @param orderId 骑行订单id
* @return 下单成功返回true,否则返回false
*/
- @PostMapping("/prepay")
+ @GetMapping("/prepay")
public JsonResult> prepay(@RequestParam(name = "orderId") String orderId) {
JSONObject r = wxPayService.prepay(orderId);
return r.containsKey("error")?JsonResult.failed("下单失败: "+ r.getString("error")):JsonResult.success(r);
@@ -44,8 +44,8 @@ public class EbikeWxPaymentController {
* @return 支付订单信息
*/
@GetMapping("/queryOrder/{orderId}")
- public JsonResult> queryOrderByOutTradeNo(@PathVariable String orderId) {
- Transaction r = wxPayService.queryOrderByOutTradeNo(orderId);
+ public JsonResult> queryOrderByOrderId(@PathVariable(name = "orderId") String orderId) {
+ Transaction r = wxPayService.queryOrderByOrderId(orderId);
return r == null?JsonResult.failed(String.format("骑行订单号{%s}查询支付订单失败", orderId)):JsonResult.success(r);
}
@@ -56,8 +56,8 @@ public class EbikeWxPaymentController {
* @return 订单信息支付状态
*/
@GetMapping("/queryOrderStatus/{orderId}")
- public JsonResult> queryOrderStatusById(@PathVariable String orderId) {
- HandleNotifyResult r = wxPayService.queryOrderStatusByOutTradeNo(orderId);
+ public JsonResult> queryOrderStatusById(@PathVariable(name = "orderId") String orderId) {
+ HandleNotifyResult r = wxPayService.queryOrderStatusByOrderId(orderId);
return JsonResult.success(r);
}
@@ -93,7 +93,7 @@ public class EbikeWxPaymentController {
* @return 退款信息
*/
@GetMapping("/queryRefund/{refundId}")
- public JsonResult> refundQuery(@PathVariable String refundId) {
+ public JsonResult> refundQuery(@PathVariable(name = "refundId") String refundId) {
Refund r = wxPayService.queryRefundByOutNo(refundId);
return r == null?JsonResult.failed(String.format("退款单号{%s}查询退款失败", refundId)):JsonResult.success(r);
}
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/model/dto/WxJsapiPromptDto.java b/ebike-payment/src/main/java/com/cdzy/payment/model/dto/WxJsapiPromptDto.java
index 93896d5b..b8abd887 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/model/dto/WxJsapiPromptDto.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/model/dto/WxJsapiPromptDto.java
@@ -2,8 +2,8 @@ package com.cdzy.payment.model.dto;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.annotation.JSONField;
-import com.wechat.pay.java.core.cipher.RSASigner;
import com.wechat.pay.java.core.cipher.SignatureResult;
+import com.wechat.pay.java.core.cipher.Signer;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -49,15 +49,11 @@ public class WxJsapiPromptDto {
*/
private String paySign;
- public JSONObject toJson(RSASigner rsaSigner) {
+ public JSONObject toJson(Signer rsaSigner) {
try{
// 计算签名
- StringJoiner signMsg = new StringJoiner("\n");
- signMsg.add(appId);
- signMsg.add(timeStamp);
- signMsg.add(nonceStr);
- signMsg.add(extension);
- SignatureResult sign = rsaSigner.sign(signMsg.toString());
+ String signMsg = appId + "\n" + timeStamp + "\n" + nonceStr + "\n" + extension + "\n";
+ SignatureResult sign = rsaSigner.sign(signMsg);
this.paySign = sign.getSign();
//result.put("package", result.remove("extension"));
return JSONObject.parseObject(JSONObject.toJSONString(this));
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikePayment.java b/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikePayment.java
index e2ee5841..e5ebdb5f 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikePayment.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikePayment.java
@@ -40,7 +40,7 @@ public class EbikePayment implements Serializable {
private String orderId;
/**
- * 预支付交易会话标识;有效期为2小时
+ * 支付交易用订单编号,重新请求时需要更新
*/
private String paymentId;
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikeRefund.java b/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikeRefund.java
index 582e3a3d..3fa0490b 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikeRefund.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/model/entity/EbikeRefund.java
@@ -39,10 +39,6 @@ public class EbikeRefund implements Serializable {
*/
private String orderId;
- /**
- * 支付记录id
- */
- private String recordId;
/**
* 微信支付订单号
@@ -76,7 +72,7 @@ public class EbikeRefund implements Serializable {
private Double refund;
/**
- * 退款总金额
+ * 原订单金额
*/
private Double total;
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/WxPayService.java b/ebike-payment/src/main/java/com/cdzy/payment/service/WxPayService.java
index 0ca5189f..11c42fbb 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/service/WxPayService.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/service/WxPayService.java
@@ -27,27 +27,36 @@ public interface WxPayService {
/**
* JSAPI支付下单
*
- * @param outTradeNo 订单id
+ * @param orderId 订单id
* @return 下单成功返回wx支付请求参数,否则返回null
*/
- JSONObject prepay(String outTradeNo);
+ JSONObject prepay(String orderId);
+
+
+ /**
+ * 通过支付订单号查询支付订单
+ *
+ * @param outTradeNo 支付订单号
+ * @return 支付订单信息
+ */
+ Transaction queryOrderByOutTradeNo(String outTradeNo);
/**
* 通过商户(骑行)订单号查询支付订单
*
- * @param outTradeNo 商户(骑行)订单号
+ * @param orderId 商户(骑行)订单号
* @return 支付订单信息
*/
- Transaction queryOrderByOutTradeNo(String outTradeNo);
+ Transaction queryOrderByOrderId(String orderId);
/**
* 通过订单号查询支付订单状态
*
- * @param outTradeNo 商户(骑行)订单号
+ * @param orderId 商户(骑行)订单号
* @return 支付订单信息
*/
- HandleNotifyResult queryOrderStatusByOutTradeNo(String outTradeNo);
+ HandleNotifyResult queryOrderStatusByOrderId(String orderId);
/**
* 处理支付回调
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikePaymentServiceImpl.java b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikePaymentServiceImpl.java
index fe01d420..235649a6 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikePaymentServiceImpl.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikePaymentServiceImpl.java
@@ -4,8 +4,6 @@ import com.cdzy.payment.model.enums.PayMethod;
import com.cdzy.payment.utils.StringUtils;
import com.ebike.feign.clients.OrdersFeignClient;
import com.ebike.feign.model.res.ResFeignOrderPaymentDto;
-import com.mybatisflex.core.query.QueryColumn;
-import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cdzy.payment.model.entity.EbikePayment;
@@ -18,6 +16,7 @@ import org.springframework.stereotype.Service;
import java.util.List;
import static com.cdzy.payment.model.entity.table.EbikePaymentTableDef.EBIKE_PAYMENT;
+import static com.mybatisflex.core.constant.FuncName.*;
/**
* 用户订单支付记录 服务层实现。
@@ -33,27 +32,29 @@ public class EbikePaymentServiceImpl extends ServiceImpl getNoPayOrderByDuration(int duration) {
- QueryColumn time = QueryMethods.secToTime(String.valueOf(duration * 60));
// trade_state 等于 NOTPAY未支付的, 并且创建时间未超过duration分钟的订单
+ String timeFilter = String.format("%s(%s, %s(%s))<%s()", ADDTIME, EBIKE_PAYMENT.CREATE_TIME.getName(), SEC_TO_TIME
+ , String.valueOf(duration * 60), NOW);
QueryWrapper query = QueryWrapper.create()
.where(EBIKE_PAYMENT.TRADE_STATE.eq(Transaction.TradeStateEnum.NOTPAY.ordinal()))
- .and(QueryMethods.addTime(EBIKE_PAYMENT.CREATE_TIME, time).lt(QueryMethods.now()));
+ .and(timeFilter);
return list(query);
}
@Override
public List getExpireOrderByDuration(int duration) {
- QueryColumn time = QueryMethods.secToTime(String.valueOf(duration * 60));
// trade_state 等于 NOTPAY未支付的, 并且创建时间超过duration分钟的订单
+ String timeFilter = String.format("%s(%s, %s(%s))>=%s()", ADDTIME, EBIKE_PAYMENT.CREATE_TIME.getName(), SEC_TO_TIME
+ , String.valueOf(duration * 60), NOW);
QueryWrapper query = QueryWrapper.create()
.where(EBIKE_PAYMENT.TRADE_STATE.eq(Transaction.TradeStateEnum.NOTPAY.ordinal()))
- .and(QueryMethods.addTime(EBIKE_PAYMENT.CREATE_TIME, time).ge(QueryMethods.now()));
+ .and(timeFilter);
return list(query);
}
@Override
public Boolean updatePaymentStatus(Transaction transaction) {
- EbikePayment ebikePayment = new EbikePayment();
+ EbikePayment ebikePayment = getByPaymentId(transaction.getOutTradeNo());
//ebikePayment.setRecordId(recordId);
ebikePayment.setTradeState(String.valueOf(transaction.getTradeState().ordinal()));
if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
@@ -65,14 +66,12 @@ public class EbikePaymentServiceImpl extends ServiceImpl getNoSuccessRefundOrderByDuration(int duration) {
- // trade_state 不等于 SUCCESS退款成功的, 并且创建时间超过duration分钟的订单
+ // trade_state 等于 PROCESSING正在退款中的, 并且创建时间超过duration分钟的订单
+ String timeFilter = String.format("%s(%s, %s(%s))>=%s()", ADDTIME, EBIKE_REFUND.CREATE_TIME.getName(), SEC_TO_TIME
+ , String.valueOf(duration * 60), NOW);
QueryWrapper query = QueryWrapper.create()
.where(EBIKE_REFUND.STATUS.eq(Status.PROCESSING.ordinal()))
- .and(QueryMethods.addTime(EBIKE_REFUND.CREATE_TIME, QueryMethods.secToTime(String.valueOf(duration * 60))).ge(QueryMethods.now()));
+ .and(timeFilter);
return list(query);
}
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/WxPayServiceImpl.java b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/WxPayServiceImpl.java
index daad6155..64cd1be4 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/WxPayServiceImpl.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/WxPayServiceImpl.java
@@ -18,7 +18,7 @@ import com.ebike.feign.model.rsp.AmountDto;
import com.ebike.feign.model.rsp.DetailDto;
import com.ebike.feign.model.rsp.EbikePaymentDto;
import com.wechat.pay.java.core.Config;
-import com.wechat.pay.java.core.cipher.RSASigner;
+import com.wechat.pay.java.core.cipher.Signer;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
@@ -41,6 +41,8 @@ import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.*;
+import java.util.ArrayList;
+import java.util.List;
import static com.wechat.pay.java.core.http.Constant.*;
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_SERIAL;
@@ -63,7 +65,7 @@ public class WxPayServiceImpl implements WxPayService {
@Resource
private WxPayConfig wxPayConfig;
@Resource
- private RSASigner wxRsaSigner;
+ private Signer wxRsaSigner;
@Resource
private Config certificateConfig;
@Resource
@@ -71,13 +73,14 @@ public class WxPayServiceImpl implements WxPayService {
@Resource
private EbikeRefundService ebikeRefundService;
@Resource
- private OrdersFeignClient orderFeingClient;
+ private OrdersFeignClient ordersFeignClient;
@Override
public boolean closeOrder(String outTradeNo) {
try {
CloseOrderRequest request = new CloseOrderRequest();
request.setOutTradeNo(outTradeNo);
+ request.setMchid(wxPayConfig.getMerchantId());
wxJsapiService.closeOrder(request);
log.info("关闭订单成功,订单号:{}", outTradeNo);
// ebikePaymentService.updatePaymentStatus(outTradeNo, 2);
@@ -90,27 +93,42 @@ public class WxPayServiceImpl implements WxPayService {
@Override
- public JSONObject prepay(String outTradeNo){
+ public JSONObject prepay(String orderId){
JSONObject r = new JSONObject();
// 首先检查订单是否正在付中、或者已经支付成功
- EbikePayment ebikePayment = ebikePaymentService.getByOrderId(outTradeNo);
+ // 关闭了的订单,重新发起请求
+ EbikePayment ebikePayment = ebikePaymentService.getByOrderId(orderId);
if (ebikePayment != null) {
- if (String.valueOf(Transaction.TradeStateEnum.SUCCESS.ordinal()).equals(ebikePayment.getTradeState())) {
- log.info("订单已经支付成功,订单号:{}", outTradeNo);
+ String tradeState = ebikePayment.getTradeState();
+ if (String.valueOf(Transaction.TradeStateEnum.SUCCESS.ordinal()).equals(tradeState)) {
+ log.info("订单已经支付成功,订单号:{}", orderId);
r.put("error", "订单已经支付成功");
return r;
}
- if (String.valueOf(Transaction.TradeStateEnum.NOTPAY.ordinal()).equals(ebikePayment.getTradeState())
- ||String.valueOf(Transaction.TradeStateEnum.USERPAYING.ordinal()).equals(ebikePayment.getTradeState())) {
- log.info("订单正在支付中,订单号:{}", outTradeNo);
- r.put("error", "订单正在支付中");
- return null;
+ if (String.valueOf(Transaction.TradeStateEnum.NOTPAY.ordinal()).equals(tradeState)
+ ||String.valueOf(Transaction.TradeStateEnum.USERPAYING.ordinal()).equals(tradeState)) {
+ // 检查订单是否关闭
+ Transaction t = queryOrderByOutTradeNo(ebikePayment.getPaymentId());
+ if (t != null && Transaction.TradeStateEnum.CLOSED.equals(t.getTradeState())) {
+ log.info("订单已经关闭,订单号:{}, 重新发起请求", orderId);
+ ebikePayment.setTradeState(String.valueOf(Transaction.TradeStateEnum.CLOSED.ordinal()));
+ ebikePayment.setPaymentId(StringUtils.generateSnowflakeId("paymentId"));
+ }else{
+ log.info("订单正在支付中,订单号:{}", orderId);
+ }
+ } else if (String.valueOf(Transaction.TradeStateEnum.CLOSED.ordinal()).equals(tradeState)) {
+ log.info("订单已经关闭,订单号:{}, 重新发起请求", orderId);
+ ebikePayment.setPaymentId(StringUtils.generateSnowflakeId("paymentId"));
+ }else {
+ log.info("订单状态异常,订单号:{}", orderId);
+ r.put("error", "订单状态异常: ");
+ return r;
}
}
//查询订单, orderFeingClient.getOrderById(orderId)
- JsonResult> result = orderFeingClient.getPaymentDetails(Long.valueOf(outTradeNo));
+ JsonResult> result = ordersFeignClient.getPaymentDetails(Long.valueOf(orderId));
if (result.getCode() != 200) {
- log.error("查询订单 {} 失败, {}", outTradeNo, result.getMessage());
+ log.error("查询订单 {} 失败, {}", orderId, result.getMessage());
r.put("error", "查询订单失败, "+result.getMessage());
return r;
}
@@ -127,18 +145,20 @@ public class WxPayServiceImpl implements WxPayService {
* @return 下单成功返回wx支付请求参数,否则返回null
*/
private JSONObject prepay(EbikePaymentDto paymentDto, EbikePayment ebikePayment) {
+ JSONObject r = new JSONObject();
String outTradeNo = paymentDto.getOrderId();
String description = paymentDto.getDescription();
String goodsTag = paymentDto.getGoodsTag();
String openId = paymentDto.getOpenId();
AmountDto amount = paymentDto.getAmount();
DetailDto detail = paymentDto.getDetail();
+ String payId = ebikePayment==null?outTradeNo : ebikePayment.getPaymentId();
try {
PrepayRequest request = new PrepayRequest();
request.setAppid(wxPayConfig.getAppId());
request.setMchid(wxPayConfig.getMerchantId());
request.setDescription(description);
- request.setOutTradeNo(outTradeNo);
+ request.setOutTradeNo(payId);
request.setNotifyUrl(wxPayConfig.getPayNotifyUrl());
LocalDateTime expireTime = LocalDateTime.now().plusMinutes(wxPayConfig.getExpireMinute());
request.setTimeExpire(StringUtils.formatLocalDatetime(expireTime));
@@ -151,22 +171,36 @@ public class WxPayServiceImpl implements WxPayService {
payer.setOpenid(openId);
request.setPayer(payer);
Detail detailReq = new Detail();
- detailReq.setGoodsDetail(detail.getGoodsDetail().stream().map(goodsDetail -> {
+ List goodsDetails = detail.getGoodsDetail().stream().map(goodsDetail -> {
GoodsDetail goodsDetailReq = new GoodsDetail();
goodsDetailReq.setGoodsName(goodsDetail.getItemName());
goodsDetailReq.setMerchantGoodsId(goodsDetail.getItemId());
goodsDetailReq.setQuantity(goodsDetail.getQuantity());
goodsDetailReq.setUnitPrice(BigDecimal.valueOf(goodsDetail.getUnitPrice()*100.0).intValue());
return goodsDetailReq;
- }).toList());
+ }).toList();
+ if (goodsDetails.isEmpty()){
+ goodsDetails = new ArrayList<>();
+ GoodsDetail goodsDetail = new GoodsDetail();
+ String snowId = StringUtils.generateSnowflakeId("goodsId");
+ goodsDetail.setMerchantGoodsId(snowId);
+ goodsDetail.setGoodsName(goodsTag);
+ goodsDetail.setQuantity(1);
+ goodsDetail.setUnitPrice(BigDecimal.valueOf(amount.getTotal()*100.0).intValue());
+ goodsDetails.add(goodsDetail);
+ }
+ detailReq.setGoodsDetail(goodsDetails);
detailReq.setCostPrice(BigDecimal.valueOf(detail.getCostPrice()*100.0).intValue());
detailReq.setInvoiceId(detail.getInvoiceId());
request.setDetail(detailReq);
-
+ SettleInfo settleInfo = new SettleInfo();
+ settleInfo.setProfitSharing(false);
+ request.setSettleInfo(settleInfo);
+ //log.info("微信支付下单prepay,订单号:{}, {}", outTradeNo, JSONObject.toJSONString(request));
PrepayResponse response = wxJsapiService.prepay(request);
- String payId = response.getPrepayId();
//入库, 重新发起支付更新记录(订单号<-->记录号一一对应)
- if (payId != null) {
+ if (response != null && response.getPrepayId() != null) {
+ log.info("微信支付下单prepay成功,支付订单号:{}", response.getPrepayId());
if (ebikePayment == null) {
ebikePayment = new EbikePayment();
ebikePayment.setOrderId(outTradeNo);
@@ -189,14 +223,16 @@ public class WxPayServiceImpl implements WxPayService {
wxJsapiPromptDto.setAppId(wxPayConfig.getAppId());
wxJsapiPromptDto.setTimeStamp(String.valueOf(Instant.now().getEpochSecond()));
wxJsapiPromptDto.setNonceStr(NonceUtil.createNonce(32));
- wxJsapiPromptDto.setExtension("prepay_id=" + payId);
+ wxJsapiPromptDto.setExtension("prepay_id=" + response.getPrepayId());
return wxJsapiPromptDto.toJson(wxRsaSigner);
}
log.error("微信支付下单prepay失败,订单号:{}", outTradeNo);
- return null;
+ r.put("error", "微信支付下单prepay失败");
+ return r;
}catch (Exception e) {
logError("微信支付下单prepay", e);
- return null;
+ r.put("error", "微信支付下单prepay失败: "+e.getMessage());
+ return r;
}
}
@@ -209,13 +245,23 @@ public class WxPayServiceImpl implements WxPayService {
}
@Override
- public HandleNotifyResult queryOrderStatusByOutTradeNo(String outTradeNo) {
+ public Transaction queryOrderByOrderId(String orderId) {
+ EbikePayment ebikePayment = ebikePaymentService.getByOrderId(orderId);
+ if (ebikePayment==null){
+ log.error("{}支付订单不存在", orderId);
+ return null;
+ }
+ return queryOrderByOutTradeNo(ebikePayment.getPaymentId());
+ }
+
+ @Override
+ public HandleNotifyResult queryOrderStatusByOrderId(String orderId) {
// 先查本地数据库,如果退款状态不为SUCCESS,需要查询微信支付
HandleNotifyResult result = new HandleNotifyResult();
- EbikePayment ebikePayment = ebikePaymentService.getByOrderId(outTradeNo);
+ EbikePayment ebikePayment = ebikePaymentService.getByOrderId(orderId);
if (ebikePayment==null){
- log.error("{}支付订单不存在", outTradeNo);
- result.setMessage(String.format("{%s}支付订单不存在", outTradeNo));
+ log.error("{}支付订单不存在", orderId);
+ result.setMessage(String.format("{%s}支付订单不存在", orderId));
return result;
}
result.setSuccess(String.valueOf(Transaction.TradeStateEnum.SUCCESS.ordinal()).equals(ebikePayment.getTradeState()));
@@ -223,11 +269,9 @@ public class WxPayServiceImpl implements WxPayService {
result.setMessage(String.format("订单%s支付成功", ebikePayment.getOrderId()));
return result;
}
- QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
- request.setOutTradeNo(outTradeNo);
- request.setMchid(wxPayConfig.getMerchantId());
- Transaction r = wxJsapiService.queryOrderByOutTradeNo(request);
- if(r!=null&& r.getTradeState().equals(Transaction.TradeStateEnum.SUCCESS)) {
+
+ Transaction r =queryOrderByOutTradeNo(ebikePayment.getPaymentId());
+ if(r!=null&& Transaction.TradeStateEnum.SUCCESS.equals(r.getTradeState())) {
result.setMessage(String.format("订单%s支付成功", ebikePayment.getOrderId()));
result.setSuccess(true);
// 更新支付状态
@@ -295,6 +339,7 @@ public class WxPayServiceImpl implements WxPayService {
ebikeRefund.setCreateTime(LocalDateTime.now());
ebikeRefund.setRefundId(outRefundNo);
ebikeRefund.setOrderId(outTradeNo);
+ ebikeRefund.setTotal(ebikePayment.getTotal());
ebikeRefund.setTransactionId(transactionId);
ebikeRefund.setReason(reason);
ebikeRefund.setStatus(String.valueOf(Status.PROCESSING.ordinal()));
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/task/ScheduledTaskManager.java b/ebike-payment/src/main/java/com/cdzy/payment/task/ScheduledTaskManager.java
index 3fa11b05..b2bd8456 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/task/ScheduledTaskManager.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/task/ScheduledTaskManager.java
@@ -1,5 +1,6 @@
package com.cdzy.payment.task;
+import com.cdzy.payment.config.WxPayConfig;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@@ -17,17 +18,18 @@ import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ScheduledTaskManager {
- // 每隔30秒执行1次
- private final static String CRON_EXPRESSION = "0/30 * * * *?";
// @Scheduled任务线程默认串行执行,需要考虑并发问题
@Resource
+ private WxPayConfig wxPayConfig;
+ @Resource
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
@Resource
private WsPayTask wxPayTask;
@PostConstruct
public void init() {
+ String CRON_EXPRESSION = wxPayConfig.getCronExpression();
// 启动定时任务
// 1. 每隔30秒执行1次,查询创建未超过5分钟,并且未支付的订单
threadPoolTaskScheduler.schedule(new Runnable() {
@@ -41,17 +43,18 @@ public class ScheduledTaskManager {
}
}, new CronTrigger(CRON_EXPRESSION));
- // 2. 每隔30秒执行1次,查询创建超过5分钟,并且未支付的订单
- threadPoolTaskScheduler.schedule(new Runnable() {
- @Override
- public void run() {
- try {
- wxPayTask.closeOrder();
- } catch (Exception e) {
- log.error("closeOrder 执行异常", e);
- }
- }
- }, new CronTrigger(CRON_EXPRESSION));
+ //========支付系统自动关闭,不主动关闭,每次发起请求的时候检测是否关闭========
+ //// 2. 每隔30秒执行1次,查询创建超过5分钟,并且未支付的订单
+ //threadPoolTaskScheduler.schedule(new Runnable() {
+ // @Override
+ // public void run() {
+ // try {
+ // wxPayTask.closeOrder();
+ // } catch (Exception e) {
+ // log.error("closeOrder 执行异常", e);
+ // }
+ // }
+ //}, new CronTrigger(CRON_EXPRESSION));
// 3. 每隔30秒执行1次,查询创建未超过5分钟,并且未成功的退款单
threadPoolTaskScheduler.schedule(new Runnable() {
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/task/WsPayTask.java b/ebike-payment/src/main/java/com/cdzy/payment/task/WsPayTask.java
index 3a0e0dc2..a68b2b9b 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/task/WsPayTask.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/task/WsPayTask.java
@@ -36,7 +36,7 @@ public class WsPayTask {
/**
- * 查询创建未超过5分钟,并且未支付的订单
+ * 查询创建未超过24小时,并且未支付的订单
*/
public void checkOrderStatus() throws Exception {
log.info("checkOrderStatus 执行......");
@@ -54,7 +54,7 @@ public class WsPayTask {
}
/**
- * 查询创建超过5分钟,并且未支付的订单
+ * 查询创建超过24小时,并且未支付的订单
*/
public void closeOrder() throws Exception {
log.info("closeOrder 执行......");
@@ -76,7 +76,7 @@ public class WsPayTask {
}
/**
- * 查询创建未超过5分钟,并且未成功的退款单
+ * 查询创建未超过24小时,并且未成功的退款单
*/
public void checkRefundStatus() throws Exception {
log.info("checkRefundStatus 执行......");
diff --git a/ebike-payment/src/main/resources/application-dev.yml b/ebike-payment/src/main/resources/application-dev.yml
index 946a6df1..5531b6d4 100644
--- a/ebike-payment/src/main/resources/application-dev.yml
+++ b/ebike-payment/src/main/resources/application-dev.yml
@@ -36,13 +36,14 @@ payment:
app-id: wx327d788d7bd6eddf
merchant-id: 1715147005
private-key-path: D:/Projects/eBIKE/docs/secrets/apiclient_key.pem
- public-key-path: D:/Projects/eBIKE/docs/secrets/apiclient_cert.pem
+ public-key-path: D:/Projects/eBIKE/docs/secrets/apiclient_pubkey.pem
merchant-serial-number: 7873E3E694ADD0368EA3E9FAC929F496EECB8DF9
api-v3-key: 1715147005V3Key20250425174554633
public-key-id: PUB_KEY_ID_0117151470052025042500331704000601
pay-notify_url: http://192.168.2.156:10017/wxPayment/pay-notify
refund-notify_url: http://192.168.2.156:10017/wxPayment/refund-notify
- expire-minutes: 5
+ expire-minutes: 1440
+ cron-expression: 0 0 0,12 * * ?
task-scheduler-pool:
poolSize: 100
threadNamePrefix: task-scheduled-