fix(apple): 增加无效收据原因日志并补充订阅过期时间调试输出

This commit is contained in:
2025-12-15 21:21:47 +08:00
parent 0ad9de1011
commit c305dfaae4
5 changed files with 24 additions and 3 deletions

View File

@@ -12,6 +12,9 @@ import org.springframework.ai.retry.RetryUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.util.MultiValueMap;
import java.util.Map;
/* /*
@@ -32,6 +35,7 @@ public class LLMConfig {
public OpenAiApi openAiApi() { public OpenAiApi openAiApi() {
return OpenAiApi.builder() return OpenAiApi.builder()
.apiKey(apiKey) .apiKey(apiKey)
.headers(MultiValueMap.fromSingleValue(Map.of("X-Title", "key of love")))
.baseUrl(baseUrl) .baseUrl(baseUrl)
.build(); .build();
} }

View File

@@ -36,6 +36,7 @@ public class AppleReceiptController {
private final ApplePurchaseService applePurchaseService; private final ApplePurchaseService applePurchaseService;
private final SignedDataVerifier signedDataVerifier; private final SignedDataVerifier signedDataVerifier;
public AppleReceiptController(AppleReceiptService appleReceiptService, public AppleReceiptController(AppleReceiptService appleReceiptService,
ApplePurchaseService applePurchaseService, ApplePurchaseService applePurchaseService,
SignedDataVerifier signedDataVerifier) { SignedDataVerifier signedDataVerifier) {
@@ -83,12 +84,13 @@ public class AppleReceiptController {
*/ */
@PostMapping("/notification") @PostMapping("/notification")
public BaseResponse<Boolean> receiveNotification(@RequestBody Map<String, String> body, HttpServletRequest request) { public BaseResponse<Boolean> receiveNotification(@RequestBody Map<String, String> body, HttpServletRequest request) {
if (body == null) { if (body == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "body 不能为空"); throw new BusinessException(ErrorCode.PARAMS_ERROR, "body 不能为空");
} }
// 从请求体中获取 Apple 签名的载荷 // 从请求体中获取 Apple 签名的载荷
String signedPayload = body.get("signedPayload"); String signedPayload = body.get("signedPayload");
// 校验 signedPayload 是否为空 // 校验 signedPayload 是否为空
if (signedPayload == null || signedPayload.isBlank()) { if (signedPayload == null || signedPayload.isBlank()) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "signedPayload 不能为空"); throw new BusinessException(ErrorCode.PARAMS_ERROR, "signedPayload 不能为空");

View File

@@ -70,6 +70,7 @@ public class ApplePurchaseServiceImpl implements ApplePurchaseService {
public void processPurchase(Long userId, AppleReceiptValidationResult validationResult) { public void processPurchase(Long userId, AppleReceiptValidationResult validationResult) {
// 1. 校验收据有效性 // 1. 校验收据有效性
if (validationResult == null || !validationResult.isValid()) { if (validationResult == null || !validationResult.isValid()) {
log.error("Invalid receipt, reason={}", validationResult.getReason());
throw new BusinessException(ErrorCode.RECEIPT_INVALID); throw new BusinessException(ErrorCode.RECEIPT_INVALID);
} }

View File

@@ -86,6 +86,8 @@ public class AppleReceiptServiceImpl implements AppleReceiptService {
try { try {
// 1. 从收据里解析出 transactionId不做验证只是解析 ASN.1 // 1. 从收据里解析出 transactionId不做验证只是解析 ASN.1
String transactionId = receiptUtility.extractTransactionIdFromAppReceipt(appReceipt); String transactionId = receiptUtility.extractTransactionIdFromAppReceipt(appReceipt);
// todo 验证服务器传输的transactionId
// String transactionId = receiptUtility.extractTransactionIdFromTransactionReceipt(appReceipt);
if (transactionId == null) { if (transactionId == null) {
return invalid("no_transaction_id_in_receipt"); return invalid("no_transaction_id_in_receipt");
} }
@@ -193,6 +195,7 @@ public class AppleReceiptServiceImpl implements AppleReceiptService {
// 有 expiresDate 的一般是订阅(自动续订等),过期就无效 // 有 expiresDate 的一般是订阅(自动续订等),过期就无效
if (payload.getExpiresDate() != null) { if (payload.getExpiresDate() != null) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
log.error("Now Date:{} ,Expires Date: {}",now, payload.getExpiresDate());
return now < payload.getExpiresDate(); return now < payload.getExpiresDate();
} }

View File

@@ -56,9 +56,20 @@ public class JwtParser {
// 获取第一个证书Base64 编码标准格式非URL安全格式 // 获取第一个证书Base64 编码标准格式非URL安全格式
String certBase64 = x5cArray.getString(0); String certBase64 = x5cArray.getString(0);
// 调试信息
System.out.println("Cert Base64 length: " + certBase64.length());
System.out.println("First 50 chars: " + certBase64.substring(0, Math.min(50, certBase64.length())));
// x5c 中的证书使用标准 Base64 编码(非 URL 安全编码) // x5c 中的证书使用标准 Base64 编码(非 URL 安全编码)
byte[] certBytes = Base64.getDecoder().decode(certBase64); byte[] certBytes;
try {
certBytes = Base64.getDecoder().decode(certBase64); // 使用标准 Base64 解码
System.out.println("Decoded cert bytes length: " + certBytes.length);
} catch (IllegalArgumentException e) {
System.err.println("Base64 decode error: " + e.getMessage());
throw new Exception("Failed to decode certificate from x5c", e);
}
// 生成 X509 证书并提取公钥 // 生成 X509 证书并提取公钥
CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); CertificateFactory certFactory = CertificateFactory.getInstance("X.509");