diff --git a/src/main/java/com/yolo/keyborad/config/LLMConfig.java b/src/main/java/com/yolo/keyborad/config/LLMConfig.java index eb08d6f..a8b97ff 100644 --- a/src/main/java/com/yolo/keyborad/config/LLMConfig.java +++ b/src/main/java/com/yolo/keyborad/config/LLMConfig.java @@ -12,6 +12,9 @@ import org.springframework.ai.retry.RetryUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; 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() { return OpenAiApi.builder() .apiKey(apiKey) + .headers(MultiValueMap.fromSingleValue(Map.of("X-Title", "key of love"))) .baseUrl(baseUrl) .build(); } diff --git a/src/main/java/com/yolo/keyborad/controller/AppleReceiptController.java b/src/main/java/com/yolo/keyborad/controller/AppleReceiptController.java index c42b9bf..21160cc 100644 --- a/src/main/java/com/yolo/keyborad/controller/AppleReceiptController.java +++ b/src/main/java/com/yolo/keyborad/controller/AppleReceiptController.java @@ -36,6 +36,7 @@ public class AppleReceiptController { private final ApplePurchaseService applePurchaseService; private final SignedDataVerifier signedDataVerifier; + public AppleReceiptController(AppleReceiptService appleReceiptService, ApplePurchaseService applePurchaseService, SignedDataVerifier signedDataVerifier) { @@ -83,12 +84,13 @@ public class AppleReceiptController { */ @PostMapping("/notification") public BaseResponse receiveNotification(@RequestBody Map body, HttpServletRequest request) { + + if (body == null) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "body 不能为空"); } // 从请求体中获取 Apple 签名的载荷 String signedPayload = body.get("signedPayload"); - // 校验 signedPayload 是否为空 if (signedPayload == null || signedPayload.isBlank()) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "signedPayload 不能为空"); diff --git a/src/main/java/com/yolo/keyborad/service/impl/ApplePurchaseServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/ApplePurchaseServiceImpl.java index d3d4c17..ba870f8 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/ApplePurchaseServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/ApplePurchaseServiceImpl.java @@ -70,6 +70,7 @@ public class ApplePurchaseServiceImpl implements ApplePurchaseService { public void processPurchase(Long userId, AppleReceiptValidationResult validationResult) { // 1. 校验收据有效性 if (validationResult == null || !validationResult.isValid()) { + log.error("Invalid receipt, reason={}", validationResult.getReason()); throw new BusinessException(ErrorCode.RECEIPT_INVALID); } diff --git a/src/main/java/com/yolo/keyborad/service/impl/AppleReceiptServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/AppleReceiptServiceImpl.java index 6754eee..0001e2d 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/AppleReceiptServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/AppleReceiptServiceImpl.java @@ -86,6 +86,8 @@ public class AppleReceiptServiceImpl implements AppleReceiptService { try { // 1. 从收据里解析出 transactionId(不做验证,只是解析 ASN.1) String transactionId = receiptUtility.extractTransactionIdFromAppReceipt(appReceipt); +// todo 验证服务器传输的transactionId +// String transactionId = receiptUtility.extractTransactionIdFromTransactionReceipt(appReceipt); if (transactionId == null) { return invalid("no_transaction_id_in_receipt"); } @@ -193,6 +195,7 @@ public class AppleReceiptServiceImpl implements AppleReceiptService { // 有 expiresDate 的一般是订阅(自动续订等),过期就无效 if (payload.getExpiresDate() != null) { long now = System.currentTimeMillis(); + log.error("Now Date:{} ,Expires Date: {}",now, payload.getExpiresDate()); return now < payload.getExpiresDate(); } diff --git a/src/main/java/com/yolo/keyborad/utils/JwtParser.java b/src/main/java/com/yolo/keyborad/utils/JwtParser.java index b6fc4d8..22970c6 100644 --- a/src/main/java/com/yolo/keyborad/utils/JwtParser.java +++ b/src/main/java/com/yolo/keyborad/utils/JwtParser.java @@ -56,9 +56,20 @@ public class JwtParser { // 获取第一个证书(Base64 编码,标准格式非URL安全格式) 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 安全编码) - 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 证书并提取公钥 CertificateFactory certFactory = CertificateFactory.getInstance("X.509");