修复googlePlay购买验证问题
This commit is contained in:
@@ -139,12 +139,20 @@ public class GooglePlayApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private GooglePlayPurchaseSnapshot mapOneTimeSnapshot(String packageName, String purchaseToken, JsonNode root) {
|
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 state = mapOneTimeState(text(root.path("purchaseStateContext"), "purchaseState"));
|
||||||
String googleOrderId = text(root, "latestOrderId");
|
|
||||||
|
// 修正:一次性购买的订单号字段名为 "orderId"
|
||||||
|
String googleOrderId = text(root, "orderId");
|
||||||
|
|
||||||
return GooglePlayPurchaseSnapshot.builder()
|
return GooglePlayPurchaseSnapshot.builder()
|
||||||
.packageName(packageName)
|
.packageName(packageName)
|
||||||
.productId(text(lineItem, "productId"))
|
// 修正:从第一个元素中获取 productId
|
||||||
|
.productId(text(firstLineItem, "productId"))
|
||||||
.productType(GooglePlayConstants.PRODUCT_TYPE_ONE_TIME)
|
.productType(GooglePlayConstants.PRODUCT_TYPE_ONE_TIME)
|
||||||
.purchaseToken(purchaseToken)
|
.purchaseToken(purchaseToken)
|
||||||
.orderKey(resolveOrderKey(googleOrderId, purchaseToken))
|
.orderKey(resolveOrderKey(googleOrderId, purchaseToken))
|
||||||
@@ -152,9 +160,10 @@ public class GooglePlayApiClient {
|
|||||||
.linkedPurchaseToken(null)
|
.linkedPurchaseToken(null)
|
||||||
.state(state)
|
.state(state)
|
||||||
.acknowledgementState(mapAcknowledgementState(text(root, "acknowledgementState")))
|
.acknowledgementState(mapAcknowledgementState(text(root, "acknowledgementState")))
|
||||||
.consumptionState(mapConsumptionState(text(root, "consumptionState")))
|
// 修正:从 productOfferDetails 中获取以下字段
|
||||||
.quantity(number(lineItem, "quantity"))
|
.consumptionState(mapConsumptionState(text(offerDetails, "consumptionState")))
|
||||||
.refundableQuantity(number(root, "refundableQuantity"))
|
.quantity(number(offerDetails, "quantity"))
|
||||||
|
.refundableQuantity(number(offerDetails, "refundableQuantity"))
|
||||||
.autoRenewEnabled(false)
|
.autoRenewEnabled(false)
|
||||||
.accessGranted(GooglePlayConstants.STATE_ACTIVE.equals(state))
|
.accessGranted(GooglePlayConstants.STATE_ACTIVE.equals(state))
|
||||||
.externalAccountId(text(root.path("externalAccountIdentifiers"), "obfuscatedExternalAccountId"))
|
.externalAccountId(text(root.path("externalAccountIdentifiers"), "obfuscatedExternalAccountId"))
|
||||||
@@ -218,10 +227,14 @@ public class GooglePlayApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String mapOneTimeState(String state) {
|
private String mapOneTimeState(String state) {
|
||||||
|
if (state == null) {
|
||||||
|
return GooglePlayConstants.STATE_UNKNOWN;
|
||||||
|
}
|
||||||
return switch (state) {
|
return switch (state) {
|
||||||
case "PURCHASE_STATE_PURCHASED" -> GooglePlayConstants.STATE_ACTIVE;
|
// productsv2 API 返回短枚举名
|
||||||
case "PURCHASE_STATE_PENDING" -> GooglePlayConstants.STATE_PENDING;
|
case "PURCHASED", "PURCHASE_STATE_PURCHASED" -> GooglePlayConstants.STATE_ACTIVE;
|
||||||
case "PURCHASE_STATE_CANCELLED" -> GooglePlayConstants.STATE_CANCELED;
|
case "PENDING", "PURCHASE_STATE_PENDING" -> GooglePlayConstants.STATE_PENDING;
|
||||||
|
case "CANCELLED", "PURCHASE_STATE_CANCELLED" -> GooglePlayConstants.STATE_CANCELED;
|
||||||
default -> GooglePlayConstants.STATE_UNKNOWN;
|
default -> GooglePlayConstants.STATE_UNKNOWN;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,11 +35,14 @@ public class GooglePlayStateService {
|
|||||||
KeyboardProductItems product = loadProduct(snapshot.getProductId());
|
KeyboardProductItems product = loadProduct(snapshot.getProductId());
|
||||||
GooglePlayOrder order = buildOrder(command, snapshot);
|
GooglePlayOrder order = buildOrder(command, snapshot);
|
||||||
GooglePlayPurchaseToken token = buildToken(command, snapshot);
|
GooglePlayPurchaseToken token = buildToken(command, snapshot);
|
||||||
|
// 先保存订单以确保 order.id 已生成,钱包充值等权益分发依赖 order.id 写入交易流水
|
||||||
|
saveOrder(order);
|
||||||
GooglePlayUserEntitlement entitlement = null;
|
GooglePlayUserEntitlement entitlement = null;
|
||||||
if (command.getUserId() != null) {
|
if (command.getUserId() != null) {
|
||||||
entitlement = entitlementApplier.apply(command.getUserId(), product, snapshot, order);
|
entitlement = entitlementApplier.apply(command.getUserId(), product, snapshot, order);
|
||||||
purchaseRecordService.recordSuccess(command.getUserId(), product, snapshot, order, entitlement);
|
purchaseRecordService.recordSuccess(command.getUserId(), product, snapshot, order, entitlement);
|
||||||
}
|
}
|
||||||
|
// 再次保存以持久化 apply() 中修改的 deliveryStatus/grantedQuantity
|
||||||
saveOrder(order);
|
saveOrder(order);
|
||||||
token.setLatestOrderKey(order.getOrderKey());
|
token.setLatestOrderKey(order.getOrderKey());
|
||||||
token.setLatestOrderId(order.getGoogleOrderId());
|
token.setLatestOrderId(order.getGoogleOrderId());
|
||||||
|
|||||||
@@ -54,14 +54,14 @@ apple:
|
|||||||
|
|
||||||
google:
|
google:
|
||||||
play:
|
play:
|
||||||
enabled: false
|
enabled: true
|
||||||
package-name: "com.boshan.key.of.love"
|
package-name: "com.boshan.key.of.love"
|
||||||
service-account-key-path: "classpath:keyboard-490601-ee503a425cc4.json"
|
service-account-key-path: "classpath:keyboard-490601-ee503a425cc4.json"
|
||||||
oauth-token-uri: "https://oauth2.googleapis.com/token"
|
oauth-token-uri: "https://oauth2.googleapis.com/token"
|
||||||
android-publisher-scope: "https://www.googleapis.com/auth/androidpublisher"
|
android-publisher-scope: "https://www.googleapis.com/auth/androidpublisher"
|
||||||
pubsub-token-info-uri: "https://oauth2.googleapis.com/tokeninfo"
|
pubsub-token-info-uri: "https://oauth2.googleapis.com/tokeninfo"
|
||||||
validate-pubsub-jwt: true
|
validate-pubsub-jwt: true
|
||||||
require-obfuscated-account-id: true
|
require-obfuscated-account-id: false
|
||||||
pubsub:
|
pubsub:
|
||||||
expected-topic: "projects/keyboard-490601/topics/keyboard_topic"
|
expected-topic: "projects/keyboard-490601/topics/keyboard_topic"
|
||||||
expected-subscription: "projects/keyboard-490601/subscriptions/keyboard_topic-sub"
|
expected-subscription: "projects/keyboard-490601/subscriptions/keyboard_topic-sub"
|
||||||
|
|||||||
Reference in New Issue
Block a user