feat(purchase): 新增 Apple 内购完整链路

- AppleReceiptController 改造:验签后立刻落库并解锁权益
- 新增 ApplePurchaseService 处理业务:防重、写订单、发道具
- 新增 KeyboardUserPurchaseRecords 实体与 Mapper,记录用户购买
- ErrorCode 补充 RECEIPT_INVALID(50016)
- 删除过期 AGENTS.md,修正 i18n_message 表名与 CORS 白名单
This commit is contained in:
2025-12-12 18:18:55 +08:00
parent 2e16183cb8
commit a24a795887
16 changed files with 491 additions and 42 deletions

View File

@@ -1,6 +1,12 @@
package com.yolo.keyborad.controller;
import cn.dev33.satoken.stp.StpUtil;
import com.yolo.keyborad.common.BaseResponse;
import com.yolo.keyborad.common.ErrorCode;
import com.yolo.keyborad.common.ResultUtils;
import com.yolo.keyborad.exception.BusinessException;
import com.yolo.keyborad.model.dto.AppleReceiptValidationResult;
import com.yolo.keyborad.service.ApplePurchaseService;
import com.yolo.keyborad.service.AppleReceiptService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -14,14 +20,32 @@ import java.util.Map;
public class AppleReceiptController {
private final AppleReceiptService appleReceiptService;
private final ApplePurchaseService applePurchaseService;
public AppleReceiptController(AppleReceiptService appleReceiptService) {
public AppleReceiptController(AppleReceiptService appleReceiptService,
ApplePurchaseService applePurchaseService) {
this.appleReceiptService = appleReceiptService;
this.applePurchaseService = applePurchaseService;
}
// @PostMapping("/validate-receipt")
// public AppleReceiptValidationResult validateReceipt(@RequestBody Map<String, String> body) {
// String receipt = body.get("receipt");
// return appleReceiptService.validateReceipt(receipt);
// }
@PostMapping("/validate-receipt")
public AppleReceiptValidationResult validateReceipt(@RequestBody Map<String, String> body) {
public BaseResponse<Boolean> handlePurchase(@RequestBody Map<String, String> body) {
String receipt = body.get("receipt");
return appleReceiptService.validateReceipt(receipt);
if (receipt == null || receipt.isBlank()) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "receipt 不能为空");
}
Long userId = StpUtil.getLoginIdAsLong();
AppleReceiptValidationResult validationResult = appleReceiptService.validateReceipt(receipt);
applePurchaseService.processPurchase(userId, validationResult);
return ResultUtils.success(Boolean.TRUE);
}
}