修复googlePlay购买验证问题

This commit is contained in:
2026-04-03 16:03:53 +08:00
parent 83cb65a31f
commit 5220a22cbd
3 changed files with 27 additions and 11 deletions

View File

@@ -139,12 +139,20 @@ public class GooglePlayApiClient {
}
private GooglePlayPurchaseSnapshot mapOneTimeSnapshot(String packageName, String purchaseToken, JsonNode root) {
JsonNode lineItem = root.path("productLineItem");
// 1. 获取 productLineItem 数组的第一个元素 (index 0)
JsonNode firstLineItem = root.path("productLineItem").path(0);
// 2. 获取嵌套的 productOfferDetails 对象
JsonNode offerDetails = firstLineItem.path("productOfferDetails");
String state = mapOneTimeState(text(root.path("purchaseStateContext"), "purchaseState"));
String googleOrderId = text(root, "latestOrderId");
// 修正:一次性购买的订单号字段名为 "orderId"
String googleOrderId = text(root, "orderId");
return GooglePlayPurchaseSnapshot.builder()
.packageName(packageName)
.productId(text(lineItem, "productId"))
// 修正:从第一个元素中获取 productId
.productId(text(firstLineItem, "productId"))
.productType(GooglePlayConstants.PRODUCT_TYPE_ONE_TIME)
.purchaseToken(purchaseToken)
.orderKey(resolveOrderKey(googleOrderId, purchaseToken))
@@ -152,9 +160,10 @@ public class GooglePlayApiClient {
.linkedPurchaseToken(null)
.state(state)
.acknowledgementState(mapAcknowledgementState(text(root, "acknowledgementState")))
.consumptionState(mapConsumptionState(text(root, "consumptionState")))
.quantity(number(lineItem, "quantity"))
.refundableQuantity(number(root, "refundableQuantity"))
// 修正:从 productOfferDetails 中获取以下字段
.consumptionState(mapConsumptionState(text(offerDetails, "consumptionState")))
.quantity(number(offerDetails, "quantity"))
.refundableQuantity(number(offerDetails, "refundableQuantity"))
.autoRenewEnabled(false)
.accessGranted(GooglePlayConstants.STATE_ACTIVE.equals(state))
.externalAccountId(text(root.path("externalAccountIdentifiers"), "obfuscatedExternalAccountId"))
@@ -218,10 +227,14 @@ public class GooglePlayApiClient {
}
private String mapOneTimeState(String state) {
if (state == null) {
return GooglePlayConstants.STATE_UNKNOWN;
}
return switch (state) {
case "PURCHASE_STATE_PURCHASED" -> GooglePlayConstants.STATE_ACTIVE;
case "PURCHASE_STATE_PENDING" -> GooglePlayConstants.STATE_PENDING;
case "PURCHASE_STATE_CANCELLED" -> GooglePlayConstants.STATE_CANCELED;
// productsv2 API 返回短枚举名
case "PURCHASED", "PURCHASE_STATE_PURCHASED" -> GooglePlayConstants.STATE_ACTIVE;
case "PENDING", "PURCHASE_STATE_PENDING" -> GooglePlayConstants.STATE_PENDING;
case "CANCELLED", "PURCHASE_STATE_CANCELLED" -> GooglePlayConstants.STATE_CANCELED;
default -> GooglePlayConstants.STATE_UNKNOWN;
};
}

View File

@@ -35,11 +35,14 @@ public class GooglePlayStateService {
KeyboardProductItems product = loadProduct(snapshot.getProductId());
GooglePlayOrder order = buildOrder(command, snapshot);
GooglePlayPurchaseToken token = buildToken(command, snapshot);
// 先保存订单以确保 order.id 已生成,钱包充值等权益分发依赖 order.id 写入交易流水
saveOrder(order);
GooglePlayUserEntitlement entitlement = null;
if (command.getUserId() != null) {
entitlement = entitlementApplier.apply(command.getUserId(), product, snapshot, order);
purchaseRecordService.recordSuccess(command.getUserId(), product, snapshot, order, entitlement);
}
// 再次保存以持久化 apply() 中修改的 deliveryStatus/grantedQuantity
saveOrder(order);
token.setLatestOrderKey(order.getOrderKey());
token.setLatestOrderId(order.getGoogleOrderId());

View File

@@ -54,14 +54,14 @@ apple:
google:
play:
enabled: false
enabled: true
package-name: "com.boshan.key.of.love"
service-account-key-path: "classpath:keyboard-490601-ee503a425cc4.json"
oauth-token-uri: "https://oauth2.googleapis.com/token"
android-publisher-scope: "https://www.googleapis.com/auth/androidpublisher"
pubsub-token-info-uri: "https://oauth2.googleapis.com/tokeninfo"
validate-pubsub-jwt: true
require-obfuscated-account-id: true
require-obfuscated-account-id: false
pubsub:
expected-topic: "projects/keyboard-490601/topics/keyboard_topic"
expected-subscription: "projects/keyboard-490601/subscriptions/keyboard_topic-sub"