From f2b8a735f2696d575b575d0dfa0f39f5f0a57dc8 Mon Sep 17 00:00:00 2001 From: wangzhiwei Date: Wed, 1 Apr 2026 15:50:58 +0800 Subject: [PATCH] =?UTF-8?q?refactor(payment):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?token=E6=B6=88=E8=B4=B9=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改reduceBalanceWithToken方法使用TokenConsumptionDto参数对象 - 添加通过会话ID查询用户的功能并验证用户会话有效性 - 在支付控制器中更新订单信息时保存二维码内容 - 为PaymentOrder实体添加codeUrl和qrCode字段支持 - 更新SysUserMapper添加getBySessionId查询方法 - 优化微信和支付宝支付回调日志记录 - 改进token消费参数验证逻辑 - 调整数据库映射文件以支持新增字段 --- .../skills/controller/AccountController.java | 16 +---- .../skills/controller/PayController.java | 5 ++ .../com/kexue/skills/entity/PaymentOrder.java | 6 ++ .../entity/dto/TokenConsumptionDto.java | 9 ++- .../kexue/skills/mapper/AccountMapper.java | 1 + .../kexue/skills/mapper/SysUserMapper.java | 2 + .../kexue/skills/service/AccountService.java | 15 +---- .../service/impl/AccountServiceImpl.java | 63 +++++++++++-------- .../skills/service/impl/PayServiceImpl.java | 18 +++++- .../resources/mapper/PaymentOrderMapper.xml | 16 +++-- src/main/resources/mapper/SysUserMapper.xml | 8 +++ 11 files changed, 97 insertions(+), 62 deletions(-) diff --git a/src/main/java/com/kexue/skills/controller/AccountController.java b/src/main/java/com/kexue/skills/controller/AccountController.java index e597777..34c36db 100644 --- a/src/main/java/com/kexue/skills/controller/AccountController.java +++ b/src/main/java/com/kexue/skills/controller/AccountController.java @@ -116,20 +116,8 @@ public class AccountController { @Operation(summary = "减少账户余额(token消费转换)", description = "减少账户余额(token消费转换)") @PostMapping("/reduceBalanceWithToken") @RequireAuth - public CommonResult reduceBalanceWithToken( - @RequestBody TokenConsumptionDto tokenConsumptionDto) { - return CommonResult.success(this.accountService.reduceBalanceWithToken( - tokenConsumptionDto.getUserId(), - tokenConsumptionDto.getInputToken(), - tokenConsumptionDto.getOutputToken(), - tokenConsumptionDto.getTotalTokens(), - tokenConsumptionDto.getModelName(), - tokenConsumptionDto.getQuestion(), - tokenConsumptionDto.getTransactionNo(), - tokenConsumptionDto.getBusinessId(), - tokenConsumptionDto.getBusinessType(), - tokenConsumptionDto.getRemark() - )); + public CommonResult reduceBalanceWithToken( @RequestBody TokenConsumptionDto tokenConsumptionDto) { + return CommonResult.success(this.accountService.reduceBalanceWithToken(tokenConsumptionDto)); } /** diff --git a/src/main/java/com/kexue/skills/controller/PayController.java b/src/main/java/com/kexue/skills/controller/PayController.java index a0fab51..05ff942 100644 --- a/src/main/java/com/kexue/skills/controller/PayController.java +++ b/src/main/java/com/kexue/skills/controller/PayController.java @@ -108,6 +108,11 @@ public class PayController { PaymentOrder createdOrder = paymentOrderService.createPaymentOrder(order); // 生成支付宝支付表单 String form = payService.createAlipay(createdOrder); + + // 更新订单信息 + createdOrder.setQrCode( form); + paymentOrderService.update(createdOrder); + return CommonResult.success(form); } catch (Exception e) { logger.error("创建支付宝支付订单失败", e); diff --git a/src/main/java/com/kexue/skills/entity/PaymentOrder.java b/src/main/java/com/kexue/skills/entity/PaymentOrder.java index 901c6d4..0ddb54a 100644 --- a/src/main/java/com/kexue/skills/entity/PaymentOrder.java +++ b/src/main/java/com/kexue/skills/entity/PaymentOrder.java @@ -44,6 +44,12 @@ public class PaymentOrder extends BaseEntity implements Serializable { @Schema(description ="支付渠道订单号") private String channelOrderNo; + @Schema(description ="微信二维码URL") + private String codeUrl; + + @Schema(description ="支付宝二维码HTML内容") + private String qrCode; + @Schema(description ="商品名称") private String productName; diff --git a/src/main/java/com/kexue/skills/entity/dto/TokenConsumptionDto.java b/src/main/java/com/kexue/skills/entity/dto/TokenConsumptionDto.java index 03f5ce9..9a51678 100644 --- a/src/main/java/com/kexue/skills/entity/dto/TokenConsumptionDto.java +++ b/src/main/java/com/kexue/skills/entity/dto/TokenConsumptionDto.java @@ -13,7 +13,10 @@ import lombok.Data; @Data public class TokenConsumptionDto { - @Schema(description ="用户ID") + @Schema(description ="用户的会话ID") + private String sessionId; + + @Schema(description ="用户ID" ,hidden = true) private Long userId; @Schema(description ="输入token") @@ -34,10 +37,10 @@ public class TokenConsumptionDto { @Schema(description ="交易单号") private String transactionNo; - @Schema(description ="业务ID") + @Schema(description ="业务ID" ,hidden = true) private Long businessId; - @Schema(description ="业务类型") + @Schema(description ="业务类型",hidden = true) private String businessType; @Schema(description ="备注") diff --git a/src/main/java/com/kexue/skills/mapper/AccountMapper.java b/src/main/java/com/kexue/skills/mapper/AccountMapper.java index 7daa360..9e58517 100644 --- a/src/main/java/com/kexue/skills/mapper/AccountMapper.java +++ b/src/main/java/com/kexue/skills/mapper/AccountMapper.java @@ -99,4 +99,5 @@ public interface AccountMapper { * @return 影响行数 */ int deleteById(Long accountId); + } \ No newline at end of file diff --git a/src/main/java/com/kexue/skills/mapper/SysUserMapper.java b/src/main/java/com/kexue/skills/mapper/SysUserMapper.java index 29b33f5..c9e4927 100644 --- a/src/main/java/com/kexue/skills/mapper/SysUserMapper.java +++ b/src/main/java/com/kexue/skills/mapper/SysUserMapper.java @@ -86,4 +86,6 @@ public interface SysUserMapper { SysUser getByTel(String tel); + SysUser getBySessionId(String sessionId); + } diff --git a/src/main/java/com/kexue/skills/service/AccountService.java b/src/main/java/com/kexue/skills/service/AccountService.java index 0f619c2..ce92cf9 100644 --- a/src/main/java/com/kexue/skills/service/AccountService.java +++ b/src/main/java/com/kexue/skills/service/AccountService.java @@ -3,6 +3,7 @@ package com.kexue.skills.service; import com.github.pagehelper.PageInfo; import com.kexue.skills.entity.Account; import com.kexue.skills.entity.dto.AccountDto; +import com.kexue.skills.entity.dto.TokenConsumptionDto; import java.math.BigDecimal; import java.util.List; @@ -104,20 +105,10 @@ public interface AccountService extends BaseService { /** * 减少账户余额(token消费转换) + * @param tokenConsumptionDto token消费 * - * @param userId 用户ID - * @param inputToken 输入token - * @param outputToken 输出token - * @param totalTokens 合计tokens - * @param modelName 处理的模型名称 - * @param question 对应回答的问题或需求 - * @param transactionNo 交易单号 - * @param businessId 业务ID - * @param businessType 业务类型 - * @param remark 备注 - * @return 影响行数 */ - int reduceBalanceWithToken(Long userId, Integer inputToken, Integer outputToken, Integer totalTokens, String modelName, String question, String transactionNo, Long businessId, String businessType, String remark); + int reduceBalanceWithToken(TokenConsumptionDto tokenConsumptionDto); /** * 增加账户余额(签到奖励token转换) diff --git a/src/main/java/com/kexue/skills/service/impl/AccountServiceImpl.java b/src/main/java/com/kexue/skills/service/impl/AccountServiceImpl.java index 1a90d21..bb21486 100644 --- a/src/main/java/com/kexue/skills/service/impl/AccountServiceImpl.java +++ b/src/main/java/com/kexue/skills/service/impl/AccountServiceImpl.java @@ -4,11 +4,14 @@ import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.kexue.skills.entity.Account; import com.kexue.skills.entity.AccountTransaction; +import com.kexue.skills.entity.SysUser; import com.kexue.skills.entity.dto.AccountDto; import com.kexue.skills.common.Assert; +import com.kexue.skills.entity.dto.TokenConsumptionDto; import com.kexue.skills.exception.BizException; import com.kexue.skills.mapper.AccountMapper; import com.kexue.skills.mapper.AccountTransactionMapper; +import com.kexue.skills.mapper.SysUserMapper; import com.kexue.skills.service.AccountService; import com.kexue.skills.service.ModelPriceService; import com.kexue.skills.entity.ModelPrice; @@ -31,6 +34,8 @@ import java.util.List; public class AccountServiceImpl implements AccountService { @Resource private AccountMapper accountMapper; + @Resource + private SysUserMapper sysUserMapper; @Resource private AccountTransactionMapper accountTransactionMapper; @@ -246,40 +251,35 @@ public class AccountServiceImpl implements AccountService { /** * 减少账户余额(token消费转换) - * - * @param userId 用户ID - * @param amount 减少金额 - * @param inputToken 输入token - * @param outputToken 输出token - * @param totalTokens 合计tokens - * @param modelName 处理的模型名称 - * @param question 对应回答的问题或需求 - * @param transactionNo 交易单号 - * @param businessId 业务ID - * @param businessType 业务类型 - * @param remark 备注 * @return 影响行数 */ @Override - public int reduceBalanceWithToken(Long userId, Integer inputToken, Integer outputToken, Integer totalTokens, String modelName, String question, String transactionNo, Long businessId, String businessType, String remark) { + public int reduceBalanceWithToken(TokenConsumptionDto dto) { + validate(dto); // 1. 查询账户信息 + Long userId = null ;//根据会话ID查询用户ID + SysUser bySessionId = sysUserMapper.getBySessionId(dto.getSessionId()); + if(bySessionId == null){ + throw new BizException("会话ID不存在"); + } + userId = bySessionId.getUserId(); Account account = this.queryByUserId(userId); Assert.notNull(account, "账户不存在"); // 2. 查询模型价格信息 - ModelPrice modelPrice = modelPriceService.queryByModelName(modelName); + ModelPrice modelPrice = modelPriceService.queryByModelName(dto.getModelName()); Assert.notNull(modelPrice, "模型价格信息不存在"); // 3. 计算金额 // 输入token费用:输入token数量 / inputPerCent,不足1分按1分计算 - long inputFee = inputToken / modelPrice.getInputPerCent(); - if (inputToken % modelPrice.getInputPerCent() > 0) { + long inputFee = dto.getInputToken() / modelPrice.getInputPerCent(); + if (dto.getInputToken() % modelPrice.getInputPerCent() > 0) { inputFee += 1; } // 输出token费用:输出token数量 / outputPerCent,不足1分按1分计算 - long outputFee = outputToken / modelPrice.getOutputPerCent(); - if (outputToken % modelPrice.getOutputPerCent() > 0) { + long outputFee = dto.getOutputToken() / modelPrice.getOutputPerCent(); + if (dto.getOutputToken() % modelPrice.getOutputPerCent() > 0) { outputFee += 1; } @@ -300,23 +300,32 @@ public class AccountServiceImpl implements AccountService { transaction.setBeforeBalance(account.getBalance()); transaction.setAfterBalance(account.getBalance().subtract(amount)); transaction.setStatus(1); // 成功 - transaction.setTransactionNo(transactionNo); + transaction.setTransactionNo(dto.getTransactionNo()); transaction.setPayType(3); // 余额支付 - transaction.setBusinessId(businessId); - transaction.setBusinessType(businessType); - transaction.setRemark(remark); + transaction.setRemark(dto.getRemark()); transaction.setIsExpense(1); // 支出 - transaction.setInputToken(inputToken); - transaction.setOutputToken(outputToken); - transaction.setTotalTokens(totalTokens); - transaction.setModelName(modelName); - transaction.setQuestion(question); + transaction.setInputToken(dto.getInputToken()); + transaction.setOutputToken(dto.getOutputToken()); + transaction.setTotalTokens(dto.getTotalTokens()); + transaction.setModelName(dto.getModelName()); + transaction.setQuestion(dto.getQuestion()); this.accountTransactionMapper.insert(transaction); // 6. 更新账户余额 return this.accountMapper.updateBalance(userId, amount, 2); } + void validate(TokenConsumptionDto dto) { + Assert.notNull(dto, "参数不能为空"); + Assert.notNull(dto.getSessionId(), "会话ID不能为空"); + Assert.notNull(dto.getUserId(), "用户ID不能为空"); + Assert.notNull(dto.getQuestion(), "问题不能为空"); + Assert.notNull(dto.getModelName(), "模型名称不能为空"); + Assert.notNull(dto.getQuestion(), "问题不能为空"); + Assert.notNull(dto.getModelName(), "模型名称不能为空"); + Assert.notNull(dto.getQuestion(), "问题不能为空"); + } + /** * 增加账户余额(签到奖励token转换) * diff --git a/src/main/java/com/kexue/skills/service/impl/PayServiceImpl.java b/src/main/java/com/kexue/skills/service/impl/PayServiceImpl.java index 79b151b..02c7da6 100644 --- a/src/main/java/com/kexue/skills/service/impl/PayServiceImpl.java +++ b/src/main/java/com/kexue/skills/service/impl/PayServiceImpl.java @@ -424,9 +424,15 @@ public class PayServiceImpl implements PayService { throw new RuntimeException("支付下单失败:" + errorMsg); } + // 保存微信支付二维码URL到订单 + String codeUrl = result.get("code_url"); + order.setCodeUrl(codeUrl); + order.setChannelOrderNo(result.get("order_no")); + paymentOrderService.update(order); + // 返回成功结果 Map payParams = new HashMap<>(); - payParams.put("code_url", result.get("code_url")); + payParams.put("code_url", codeUrl); payParams.put("order_no", order.getOrderNo()); return payParams; @@ -460,6 +466,8 @@ public class PayServiceImpl implements PayService { // 解析XML Map params = xmlToMap(xmlData); + logger.info("微信支付回调数据:{}", params); + // 验证签名 String sign = params.get("sign"); if (sign == null) { @@ -543,7 +551,11 @@ public class PayServiceImpl implements PayService { // 生成支付表单 AlipayTradePagePayResponse response = alipayClient.pageExecute(request); if (response.isSuccess()) { - return response.getBody(); + String htmlForm = response.getBody(); + // 保存支付宝支付HTML内容到订单 + order.setQrCode(htmlForm); + paymentOrderService.update(order); + return htmlForm; } else { logger.error("支付宝支付下单失败: {}", response.getMsg()); throw new RuntimeException("支付宝支付下单失败: " + response.getMsg()); @@ -570,6 +582,8 @@ public class PayServiceImpl implements PayService { } }); + logger.info("支付宝支付回调参数: {}", params); + // 初始化支付宝客户端 AlipayClient alipayClient = new DefaultAlipayClient( paymentConfig.getAlipay().getGatewayUrl(), diff --git a/src/main/resources/mapper/PaymentOrderMapper.xml b/src/main/resources/mapper/PaymentOrderMapper.xml index 6a56092..e4d7a3d 100644 --- a/src/main/resources/mapper/PaymentOrderMapper.xml +++ b/src/main/resources/mapper/PaymentOrderMapper.xml @@ -11,6 +11,8 @@ + + @@ -25,7 +27,7 @@ @@ -34,7 +36,7 @@ @@ -43,7 +45,7 @@ select order_id, order_no, user_id, user_name, amount, pay_type, status, channel_order_no, - business_id, business_type, remark, create_time, update_time, create_by, update_by, delete_flag + code_url, qr_code, business_id, business_type, remark, create_time, update_time, create_by, update_by, delete_flag from payment_order @@ -121,6 +123,8 @@ pay_type, status, channel_order_no, + code_url, + qr_code, business_id, business_type, remark, @@ -138,6 +142,8 @@ #{payType}, #{status}, #{channelOrderNo}, + #{codeUrl}, + #{qrCode}, #{businessId}, #{businessType}, #{remark}, @@ -160,6 +166,8 @@ pay_type = #{payType}, status = #{status}, channel_order_no = #{channelOrderNo}, + code_url = #{codeUrl}, + qr_code = #{qrCode}, business_id = #{businessId}, business_type = #{businessType}, remark = #{remark}, diff --git a/src/main/resources/mapper/SysUserMapper.xml b/src/main/resources/mapper/SysUserMapper.xml index 6ae2ba9..efde24b 100644 --- a/src/main/resources/mapper/SysUserMapper.xml +++ b/src/main/resources/mapper/SysUserMapper.xml @@ -208,5 +208,13 @@ and delete_flag = 0 limit 1 +