提交修改

This commit is contained in:
quyixiao 2026-04-04 15:30:07 +08:00
parent 4417f5fb27
commit 6551a43f40
4 changed files with 109 additions and 11 deletions

View File

@ -3,20 +3,28 @@ package com.heyu.api.jsapi.dto.pay;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import lombok.Data; import lombok.Data;
/**
* 微信支付商品详情
*/
@Data @Data
public class GoodsDetail { public class GoodsDetail {
/** 商户侧商品编码 */
@SerializedName("merchant_goods_id") @SerializedName("merchant_goods_id")
private String merchantGoodsId; private String merchantGoodsId;
/** 微信支付商品编码 */
@SerializedName("wechatpay_goods_id") @SerializedName("wechatpay_goods_id")
private String wechatpayGoodsId; private String wechatpayGoodsId;
/** 商品名称 */
@SerializedName("goods_name") @SerializedName("goods_name")
private String goodsName; private String goodsName;
/** 商品数量 */
@SerializedName("quantity") @SerializedName("quantity")
private Long quantity; private Long quantity;
/** 商品单价,单位为分 */
@SerializedName("unit_price") @SerializedName("unit_price")
private Long unitPrice; private Long unitPrice;
} }

View File

@ -3,8 +3,15 @@ package com.heyu.api.jsapi.dto.pay;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import lombok.Data; import lombok.Data;
/**
* JSAPI下单 - 支付者信息
*/
@Data @Data
public class JsapiReqPayerInfo { public class JsapiReqPayerInfo {
/**
* 用户在直连商户appid下的唯一标识
*/
@SerializedName("openid") @SerializedName("openid")
private String openid; private String openid;
} }

View File

@ -620,19 +620,25 @@ public class AppOrderController {
vo.setPaySign(sign); vo.setPaySign(sign);
vo.setPrepayId("prepay_id=" + prepay_id); vo.setPrepayId("prepay_id=" + prepay_id);
log.info("[添加订单] 订单创建完成, tradeOrderId={}, outTradeNo={}, payAmount={}",
vvTradeOrderEntity.getId(), vvTradeOrderEntity.getOutTradeNo(), vvTradeOrderEntity.getPayAmount());
return R.ok().setData(vo); return R.ok().setData(vo);
} }
/**
/*** * 订单再次支付
* 订单 再次支付 * 当订单支付失败或超时后用户可以再次发起支付
* *
* http://localhost:8888/app/order/to/pay * @param vvOrderRequest 支付请求参数
* @return 微信支付参数
*/ */
@Describe("添加订单") @Describe("订单再次支付")
@RequestMapping("/to/pay") @RequestMapping("/to/pay")
@AppRealyLogin @AppRealyLogin
public R toPay(@RequestBody VvTradeOrderToPayDTO vvOrderRequest) { public R toPay(@RequestBody VvTradeOrderToPayDTO vvOrderRequest) {
log.info("[订单再次支付] 开始处理, tradeOrderId={}, buyerId={}",
vvOrderRequest.getTradeOrderId(), vvOrderRequest.getBuyerId());
VvTradeOrderEntity vvTradeOrderEntity = vvTradeOrderDao.selectVvTradeOrderById(vvOrderRequest.getTradeOrderId()); VvTradeOrderEntity vvTradeOrderEntity = vvTradeOrderDao.selectVvTradeOrderById(vvOrderRequest.getTradeOrderId());
VvBuyerEntity vvBuyerEntity = vvBuyerDao.selectVvBuyerById(vvOrderRequest.getBuyerId()); VvBuyerEntity vvBuyerEntity = vvBuyerDao.selectVvBuyerById(vvOrderRequest.getBuyerId());
@ -682,11 +688,19 @@ public class AppOrderController {
return R.ok().setData(vo); return R.ok().setData(vo);
} }
// /app/order/delete /**
* 删除订单
* 将订单状态更新为已删除仅在特定状态下允许删除
*
* @param vvOrderRequest 删除请求参数
* @return 删除结果
*/
@Describe("删除订单") @Describe("删除订单")
@RequestMapping("/delete") @RequestMapping("/delete")
@AppRealyLogin @AppRealyLogin
public R delete(@RequestBody VvTradeOrderDeleteDTO vvOrderRequest) { public R delete(@RequestBody VvTradeOrderDeleteDTO vvOrderRequest) {
log.info("[删除订单] 开始处理, tradeOrderId={}, trackNumber={}, buyerId={}",
vvOrderRequest.getTradeOrderId(), vvOrderRequest.getTrackNumber(), vvOrderRequest.getBuyerId());
List<VvTradeOrderLineEntity> vvTradeOrderLineEntityList = null; List<VvTradeOrderLineEntity> vvTradeOrderLineEntityList = null;
if (StringUtils.isNotEmpty(vvOrderRequest.getTrackNumber())) { if (StringUtils.isNotEmpty(vvOrderRequest.getTrackNumber())) {
vvTradeOrderLineEntityList = vvTradeOrderLineDao.selectVvTradeOrderLineByTrackNumberBuyerId(vvOrderRequest.getTrackNumber(), vvOrderRequest.getBuyerId()); vvTradeOrderLineEntityList = vvTradeOrderLineDao.selectVvTradeOrderLineByTrackNumberBuyerId(vvOrderRequest.getTrackNumber(), vvOrderRequest.getBuyerId());

View File

@ -29,30 +29,70 @@ import java.util.Base64;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
/**
* 微信支付回调通知控制器
* <p>
* 用于处理微信支付的异步通知回调接收微信支付平台发送的支付结果通知
* 并根据通知内容更新订单状态
* </p>
*
* @author heyu
* @since 1.0
*/
@Slf4j @Slf4j
@RestController @RestController
@RequestMapping("/app/weixin") @RequestMapping("/app/weixin")
public class AppWeiXinPayNotifyController { public class AppWeiXinPayNotifyController {
/**
* 交易订单明细数据访问对象
*/
@Autowired @Autowired
private VvTradeOrderLineDao vvTradeOrderLineDao; private VvTradeOrderLineDao vvTradeOrderLineDao;
/**
// 微信支付APIv3密钥 * 微信支付APIv3密钥用于解密回调通知中的加密数据
*/
@Value("${eb.config.weixin.pay.apiv3key}") @Value("${eb.config.weixin.pay.apiv3key}")
private String apiv3key; private String apiv3key;
/**
* 交易订单数据访问对象
*/
@Autowired @Autowired
private VvTradeOrderDao tradeOrderDao; private VvTradeOrderDao tradeOrderDao;
/**
* 微信支付商户号
*/
@Value("${eb.config.weixin.pay.mchid}") @Value("${eb.config.weixin.pay.mchid}")
private String mchid; private String mchid;
/**
* JSAPI预支付服务
*/
@Autowired @Autowired
private JsapiPrepay jsapiPrepay; private JsapiPrepay jsapiPrepay;
/**
* 处理微信支付回调通知
* <p>
* 接收微信支付平台发送的异步通知解密通知内容验证支付结果并更新订单状态
* </p>
*
* <p>处理流程</p>
* <ol>
* <li>解析微信支付回调通知的JSON数据</li>
* <li>提取加密字段ciphertextassociated_datanonce</li>
* <li>使用AES-GCM算法解密数据</li>
* <li>解析解密后的支付结果数据</li>
* <li>如果支付成功更新商户订单状态</li>
* <li>返回处理结果给微信支付平台</li>
* </ol>
*
* @param requestBody 微信支付回调通知的原始JSON数据
* @return 处理结果的JSON字符串成功返回 {"code":"SUCCESS","message":"OK"}失败返回 {"code":"FAIL","message":"Server Error"}
*/
@Describe("微信支付回调") @Describe("微信支付回调")
@PostMapping("/payNotify") @PostMapping("/payNotify")
public String handleWeChatPayCallback(@RequestBody String requestBody) { public String handleWeChatPayCallback(@RequestBody String requestBody) {
@ -86,7 +126,19 @@ public class AppWeiXinPayNotifyController {
} }
} }
// AES-GCM解密方法 /**
* AES-GCM解密方法
* <p>
* 使用微信支付APIv3密钥对回调通知中的加密数据进行解密
* 采用AES-GCM算法密钥长度为256位GCM标签长度为128位
* </p>
*
* @param ciphertext 加密后的密文Base64编码
* @param associatedData 附加数据用于GCM认证
* @param nonce 随机数用作GCM初始化向量
* @return 解密后的明文字符串
* @throws Exception 解密过程中发生的异常
*/
private String decrypt(String ciphertext, String associatedData, String nonce) throws Exception { private String decrypt(String ciphertext, String associatedData, String nonce) throws Exception {
// 将APIv3密钥转为字节数组 // 将APIv3密钥转为字节数组
byte[] key = apiv3key.getBytes(StandardCharsets.UTF_8); byte[] key = apiv3key.getBytes(StandardCharsets.UTF_8);
@ -103,6 +155,23 @@ public class AppWeiXinPayNotifyController {
return new String(decryptedData, StandardCharsets.UTF_8); return new String(decryptedData, StandardCharsets.UTF_8);
} }
/**
* 更新订单状态
* <p>
* 根据微信支付回调通知的结果更新商户订单及子订单的支付状态
* </p>
*
* <p>更新内容</p>
* <ul>
* <li>查询微信支付订单详情并保存到主订单的交易信息字段</li>
* <li>更新主订单的微信支付交易号</li>
* <li>将所有子订单的状态更新为"待发货"</li>
* <li>记录子订单的支付时间和微信支付交易号</li>
* </ul>
*
* @param outTradeNo 商户订单号
* @param transactionId 微信支付交易号
*/
private void updateOrderStatus(String outTradeNo, String transactionId) { private void updateOrderStatus(String outTradeNo, String transactionId) {
try { try {
DirectAPIv3QueryResponse response = jsapiPrepay.queryOrder(transactionId); DirectAPIv3QueryResponse response = jsapiPrepay.queryOrder(transactionId);