我正在使用应用内计费 (
com.android.billingclient:[email protected]:2
) lib 在 Android 中进行付款。
计费库:提供产品详细信息,如
ProductDetails
响应 QueryInventory。
我使用
Gson
Lib 将这些产品详细信息作为 JSON 字符串存储在会话中。
JSON 字符串
{
"zza": "{\"productId\":\"com.abc.xyz\",\"type\":\"inapp\",\"title\":\"One-Time Purchase \",\"name\":\"One-Time Purchase\",\"description\":\"One-Time Purchase and Get premium content\",\"localizedIn\":[\"en-US\"],\"skuDetailsToken\":\"AEuhp4L1zoq6cjMTf8R2UF1nkG69D_MsfpoBqHySShV1u0cU5_NuObiMwl\",\"oneTimePurchaseOfferDetails\":{\"priceAmountMicros\":2900000000,\"priceCurrencyCode\":\"INR\",\"formattedPrice\":\"₹2,900.00\"}}",
"zzb": {
"nameValuePairs": {
"productId": "com.abc.xyz",
"type": "inapp",
"title": "One-Time Purchase",
"name": "One-Time Purchase",
"description": "One-Time Purchase and Get premium content",
"localizedIn": {
"values": [
"en-US"
]
},
"skuDetailsToken": "AEuhp4L1zoq6cjMTf8R2UF1nkG69D_MsfpoBqHySShV1u0cU5_NuObiMwl",
"oneTimePurchaseOfferDetails": {
"nameValuePairs": {
"priceAmountMicros": 2900000000,
"priceCurrencyCode": "INR",
"formattedPrice": "₹2,900.00"
}
}
}
},
"zzc": "com.abc.xyz",
"zzd": "inapp",
"zze": "One-Time Purchase",
"zzf": "One-Time Purchase",
"zzg": "One-Time Purchase and Get premium content",
"zzh": "AEuhp4L1zoq6cjMTf8R2UF1nkG69D_MsfpoBqHySShV1u0cU5_NuObiMwl",
"zzi": "",
"zzj": "",
"zzk": "",
"zzm": [
{
"zza": "₹2,900.00",
"zzb": 2900000000,
"zzc": "INR",
"zzd": "",
"zze": "",
"zzf": []
}
]
}
现在,我使用
ProductDetails
lib 从 JSON 创建了相同的 Gson
对象。
但是我在尝试获取
LinkedTreeMap
信息时遇到 oneTimePurchaseOfferDetails
转换异常。
产品详情.class
package com.android.billingclient.api;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.internal.play_billing.zzu;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public final class ProductDetails {
private final String zza;
private final JSONObject zzb;
private final String zzc;
private final String zzd;
private final String zze;
private final String zzf;
private final String zzg;
private final String zzh;
private final String zzi;
private final String zzj;
@Nullable
private final String zzk;
@Nullable
private final List zzl;
@Nullable
private final List zzm;
public int hashCode() {
return this.zza.hashCode();
}
@Nullable
public ProductDetails.OneTimePurchaseOfferDetails getOneTimePurchaseOfferDetails() {
List var1 = this.zzm;
return var1 != null && !var1.isEmpty() ? (ProductDetails.OneTimePurchaseOfferDetails)this.zzm.get(0) : null;
}
@NonNull
public String getDescription() {
return this.zzg;
}
@NonNull
public String getName() {
return this.zzf;
}
@NonNull
public String getProductId() {
return this.zzc;
}
@NonNull
public String getProductType() {
return this.zzd;
}
@NonNull
public String getTitle() {
return this.zze;
}
@NonNull
public String toString() {
String var1 = this.zza;
String var2 = this.zzb.toString();
String var3 = this.zzc;
String var4 = this.zzd;
String var5 = this.zze;
String var6 = this.zzh;
String var10000 = String.valueOf(this.zzl);
StringBuilder var10001 = new StringBuilder();
var10001.append("ProductDetails{jsonString='");
var10001.append(var1);
var10001.append("', parsedJson=");
var10001.append(var2);
var10001.append(", productId='");
var10001.append(var3);
var10001.append("', productType='");
var10001.append(var4);
var10001.append("', title='");
var10001.append(var5);
var10001.append("', productDetailsToken='");
var10001.append(var6);
var10001.append("', subscriptionOfferDetails=");
var10001.append(var10000);
var10001.append("}");
return var10001.toString();
}
@Nullable
public List<ProductDetails.SubscriptionOfferDetails> getSubscriptionOfferDetails() {
return this.zzl;
}
ProductDetails(String var1) throws JSONException {
this.zza = var1;
this.zzb = new JSONObject(this.zza);
this.zzc = this.zzb.optString("productId");
this.zzd = this.zzb.optString("type");
if (TextUtils.isEmpty(this.zzc)) {
throw new IllegalArgumentException("Product id cannot be empty.");
} else if (TextUtils.isEmpty(this.zzd)) {
throw new IllegalArgumentException("Product type cannot be empty.");
} else {
this.zze = this.zzb.optString("title");
this.zzf = this.zzb.optString("name");
this.zzg = this.zzb.optString("description");
this.zzi = this.zzb.optString("packageDisplayName");
this.zzj = this.zzb.optString("iconUrl");
this.zzh = this.zzb.optString("skuDetailsToken");
this.zzk = this.zzb.optString("serializedDocid");
JSONArray var2 = this.zzb.optJSONArray("subscriptionOfferDetails");
ArrayList var3;
int var4;
if (var2 != null) {
var3 = new ArrayList();
for(var4 = 0; var4 < var2.length(); ++var4) {
var3.add(new ProductDetails.SubscriptionOfferDetails(var2.getJSONObject(var4)));
}
this.zzl = var3;
} else {
ArrayList var5;
if (!this.zzd.equals("subs") && !this.zzd.equals("play_pass_subs")) {
var5 = null;
} else {
var5 = new ArrayList();
}
this.zzl = var5;
}
JSONObject var6 = this.zzb.optJSONObject("oneTimePurchaseOfferDetails");
var2 = this.zzb.optJSONArray("oneTimePurchaseOfferDetailsList");
var3 = new ArrayList();
if (var2 == null) {
if (var6 != null) {
var3.add(new ProductDetails.OneTimePurchaseOfferDetails(var6));
this.zzm = var3;
} else {
this.zzm = null;
}
} else {
for(var4 = 0; var4 < var2.length(); ++var4) {
var3.add(new ProductDetails.OneTimePurchaseOfferDetails(var2.getJSONObject(var4)));
}
this.zzm = var3;
}
}
}
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
} else if (!(o instanceof ProductDetails)) {
return false;
} else {
ProductDetails o1 = (ProductDetails)o;
return TextUtils.equals(this.zza, o1.zza);
}
}
@NonNull
public final String zza() {
return this.zzb.optString("packageName");
}
final String zzb() {
return this.zzh;
}
@Nullable
public String zzc() {
return this.zzk;
}
public static final class SubscriptionOfferDetails {
private final String zza;
@Nullable
private final String zzb;
private final String zzc;
private final ProductDetails.PricingPhases zzd;
private final List zze;
@Nullable
private final zzbf zzf;
@NonNull
public ProductDetails.PricingPhases getPricingPhases() {
return this.zzd;
}
@NonNull
public String getBasePlanId() {
return this.zza;
}
@Nullable
public String getOfferId() {
return this.zzb;
}
@NonNull
public String getOfferToken() {
return this.zzc;
}
@NonNull
public List<String> getOfferTags() {
return this.zze;
}
SubscriptionOfferDetails(JSONObject var1) throws JSONException {
this.zza = var1.optString("basePlanId");
String var2 = var1.optString("offerId");
if (var2.isEmpty()) {
var2 = null;
}
this.zzb = var2;
this.zzc = var1.getString("offerIdToken");
var2 = "pricingPhases";
this.zzd = new ProductDetails.PricingPhases(var1.getJSONArray(var2));
JSONObject var5 = var1.optJSONObject("installmentPlanDetails");
zzbf var6;
if (var5 == null) {
var6 = null;
} else {
var6 = new zzbf(var5);
}
this.zzf = var6;
ArrayList var7 = new ArrayList();
JSONArray var3 = var1.optJSONArray("offerTags");
if (var3 != null) {
for(int var4 = 0; var4 < var3.length(); ++var4) {
var7.add(var3.getString(var4));
}
}
this.zze = var7;
}
}
public static final class OneTimePurchaseOfferDetails {
private final String zza;
private final long zzb;
private final String zzc;
private final String zzd;
private final String zze;
private final zzu zzf;
@Nullable
private final zzbg zzg;
@Nullable
private final zzbi zzh;
@Nullable
private final zzbh zzi;
public long getPriceAmountMicros() {
return this.zzb;
}
@NonNull
public String getFormattedPrice() {
return this.zza;
}
@NonNull
public String getPriceCurrencyCode() {
return this.zzc;
}
OneTimePurchaseOfferDetails(JSONObject var1) throws JSONException {
this.zza = var1.optString("formattedPrice");
this.zzb = var1.optLong("priceAmountMicros");
this.zzc = var1.optString("priceCurrencyCode");
this.zzd = var1.optString("offerIdToken");
this.zze = var1.optString("offerId");
var1.optInt("offerType");
JSONArray var3 = var1.optJSONArray("offerTags");
ArrayList var4 = new ArrayList();
if (var3 != null) {
for(int var2 = 0; var2 < var3.length(); ++var2) {
var4.add(var3.getString(var2));
}
}
this.zzf = zzu.zzj(var4);
var1.optLong("fullPriceMicros");
JSONObject var6 = var1.optJSONObject("discountDisplayInfo");
zzbg var7;
if (var6 == null) {
var7 = null;
} else {
var7 = new zzbg(var6);
}
this.zzg = var7;
var6 = var1.optJSONObject("validTimeWindow");
zzbi var8;
if (var6 == null) {
var8 = null;
} else {
var8 = new zzbi(var6);
}
this.zzh = var8;
var1 = var1.optJSONObject("limitedQuantityInfo");
zzbh var5;
if (var1 == null) {
var5 = null;
} else {
var5 = new zzbh(var1);
}
this.zzi = var5;
}
@NonNull
public final String zza() {
return this.zzd;
}
}
@Retention(RetentionPolicy.SOURCE)
public @interface RecurrenceMode {
int INFINITE_RECURRING = 1;
int FINITE_RECURRING = 2;
int NON_RECURRING = 3;
}
public static final class PricingPhase {
private final String zza;
private final long zzb;
private final String zzc;
private final String zzd;
private final int zze;
private final int zzf;
public int getBillingCycleCount() {
return this.zze;
}
public int getRecurrenceMode() {
return this.zzf;
}
public long getPriceAmountMicros() {
return this.zzb;
}
@NonNull
public String getBillingPeriod() {
return this.zzd;
}
@NonNull
public String getFormattedPrice() {
return this.zza;
}
@NonNull
public String getPriceCurrencyCode() {
return this.zzc;
}
PricingPhase(JSONObject var1) {
this.zzd = var1.optString("billingPeriod");
this.zzc = var1.optString("priceCurrencyCode");
this.zza = var1.optString("formattedPrice");
this.zzb = var1.optLong("priceAmountMicros");
this.zzf = var1.optInt("recurrenceMode");
this.zze = var1.optInt("billingCycleCount");
}
}
public static class PricingPhases {
private final List zza;
@NonNull
public List<ProductDetails.PricingPhase> getPricingPhaseList() {
return this.zza;
}
PricingPhases(JSONArray var1) {
ArrayList var3 = new ArrayList();
if (var1 != null) {
for(int var2 = 0; var2 < var1.length(); ++var2) {
JSONObject var4 = var1.optJSONObject(var2);
if (var4 != null) {
var3.add(new ProductDetails.PricingPhase(var4));
}
}
}
this.zza = var3;
}
}
}
到目前为止,我所看到的是在整个代码片段中一次又一次地使用类似的变量名称。看到问题出在哪里会让人感到困惑,但如果您只想在其中包含单个对象类型,我建议您在定义的列表中使用泛型。 例如:将 zzm 定义为
List<ProductDetails.OneTimePurchaseOfferDetails> zzm;
而不是:
List zzm;
这将确保 getOneTimePurchaseOfferDetails() 方法中的 this.zzm.get(0) 只会获取 ProductDetails.OneTimePurchaseOfferDetails 类型的对象,并且如果您有机会尝试添加不同的对象有点反对该列表,您根本无法这样做。
如果仍然不起作用,请告诉我。