diff --git a/packages/expo-in-app-purchases/android/src/main/java/expo/modules/inapppurchases/BillingManager.java b/packages/expo-in-app-purchases/android/src/main/java/expo/modules/inapppurchases/BillingManager.java index 7507000981f24..9273ab5e0156c 100644 --- a/packages/expo-in-app-purchases/android/src/main/java/expo/modules/inapppurchases/BillingManager.java +++ b/packages/expo-in-app-purchases/android/src/main/java/expo/modules/inapppurchases/BillingManager.java @@ -161,7 +161,7 @@ public Context getContext() { */ @Override public void onPurchasesUpdated(BillingResult result, List purchases) { - if (result.getResponseCode() == BillingResponseCode.OK) { + if (result.getResponseCode() == BillingResponseCode.OK && purchases != null) { for (Purchase purchase : purchases) { handlePurchase(purchase); } @@ -263,11 +263,11 @@ public void run() { PurchasesResult purchasesResult = mBillingClient.queryPurchases(SkuType.INAPP); // If there are subscriptions supported, we add subscription rows as well - if (areSubscriptionsSupported()) { + if (purchasesResult != null && areSubscriptionsSupported()) { PurchasesResult subscriptionResult = mBillingClient.queryPurchases(SkuType.SUBS); - if (subscriptionResult.getResponseCode() == BillingResponseCode.OK) { + if (subscriptionResult != null && subscriptionResult.getResponseCode() == BillingResponseCode.OK) { purchasesResult.getPurchasesList().addAll( subscriptionResult.getPurchasesList()); } @@ -441,7 +441,7 @@ private static Bundle purchaseHistoryToBundle(PurchaseHistoryRecord purchaseReco */ private void onQueryPurchasesFinished(PurchasesResult result, final Promise promise) { // Have we been disposed of in the meantime? If so, or bad result code, then quit - if (mBillingClient == null || result.getResponseCode() != BillingResponseCode.OK) { + if (mBillingClient == null || result == null || result.getResponseCode() != BillingResponseCode.OK) { promise.reject("E_QUERY_FAILED", "Billing client was null or query was unsuccessful"); return; } @@ -481,7 +481,7 @@ public void onSkuDetailsResponse(BillingResult inAppResult, mBillingClient.querySkuDetailsAsync(subs.build(), new SkuDetailsResponseListener() { @Override public void onSkuDetailsResponse(BillingResult billingResult, List subscriptionDetails) { - if (skuDetails != null) { + if (skuDetails != null && subscriptionDetails != null) { skuDetails.addAll(subscriptionDetails); } listener.onSkuDetailsResponse(billingResult, skuDetails); @@ -501,9 +501,11 @@ public void queryPurchasableItems(List itemList, final Promise promise) @Override public void onSkuDetailsResponse(BillingResult billingResult, List skuDetailsList) { ArrayList results = new ArrayList<>(); - for (SkuDetails skuDetails : skuDetailsList) { - mSkuDetailsMap.put(skuDetails.getSku(), skuDetails); - results.add(skuToBundle(skuDetails)); + if (skuDetailsList != null) { + for (SkuDetails skuDetails : skuDetailsList) { + mSkuDetailsMap.put(skuDetails.getSku(), skuDetails); + results.add(skuToBundle(skuDetails)); + } } Bundle response = formatResponse(billingResult, results); promise.resolve(response); diff --git a/packages/expo-in-app-purchases/ios/EXInAppPurchases/EXInAppPurchasesModule.m b/packages/expo-in-app-purchases/ios/EXInAppPurchases/EXInAppPurchasesModule.m index 8e23599485ca9..91ae384b10313 100644 --- a/packages/expo-in-app-purchases/ios/EXInAppPurchases/EXInAppPurchasesModule.m +++ b/packages/expo-in-app-purchases/ios/EXInAppPurchases/EXInAppPurchasesModule.m @@ -151,6 +151,7 @@ - (void)handleQuery:(SKProductsResponse *)response { NSMutableArray *result = [NSMutableArray array]; for (SKProduct *validProduct in response.products) { + if (!validProduct.localizedDescription) { continue; } // skip product with nil values - this can happen if it is in review "rejected" state NSDictionary *productData = [self getProductData:validProduct]; [result addObject:productData]; } @@ -167,6 +168,7 @@ -(void)handlePurchase:(SKProductsResponse *)response { } for (SKProduct *validProduct in response.products) { + if (!validProduct.localizedDescription) { continue; } // skip product with nil values - this can happen if it is in review "rejected" state [self purchase:validProduct]; } } @@ -412,35 +414,41 @@ - (NSDictionary *)formatResults:(SKErrorCode)errorCode }; } -// Convert native error code to match TS enum +// Convert native error code to match TS enum IAPErrorCode - (int)errorCodeNativeToJS:(SKErrorCode)errorCode { switch(errorCode) { case SKErrorUnknown: - return 0; + case SKErrorUnsupportedPlatform: + return 0; // UNKNOWN case SKErrorClientInvalid: case SKErrorPaymentInvalid: case SKErrorPaymentNotAllowed: case SKErrorPaymentCancelled: - return 1; + case SKErrorOverlayCancelled: + return 1; // PAYMENT_INVALID + case SKErrorOverlayTimeout: + return 4; // SERVICE_TIMEOUT case SKErrorStoreProductNotAvailable: - return 6; + return 6; // ITEM_UNAVAILABLE case SKErrorCloudServiceRevoked: case SKErrorCloudServicePermissionDenied: case SKErrorCloudServiceNetworkConnectionFailed: - return 10; + return 10; // CLOUD_SERVICE case SKErrorPrivacyAcknowledgementRequired: - return 11; + return 11; // PRIVACY_UNACKNOWLEDGED case SKErrorUnauthorizedRequestData: - return 12; + return 12; // UNAUTHORIZED_REQUEST case SKErrorInvalidSignature: case SKErrorInvalidOfferPrice: case SKErrorInvalidOfferIdentifier: - return 13; + case SKErrorOverlayInvalidConfiguration: + case SKErrorIneligibleForOffer: + return 13; // INVALID_IDENTIFIER case SKErrorMissingOfferParams: - return 14; + return 14; // MISSING_PARAMS default: - return 0; + return 0; // UNKNOWN } }