Fire TV purchase hangs on SDK 3.0.9 — store gets metadata response and abandons the flow; IAP 2.x work fine

Summary

On Fire TV with Appstore SDK 3.x, PurchasingService.purchase(sku) never produces a purchase dialog and never delivers onPurchaseResponse(). The Appstore accepts the command, issues its product-metadata request, receives a response within one second, and then stops entirely — no billing type, no dialog, no callback, no error, no retry, and no further network activity or logging.

The identical purchase (same device, same account, same SKU, same LAT build, minutes apart) completes in 96 ms using the legacy in-app-purchasing 2.x SDK.

This looks related to this thread ( Bug: Different Amazon Purchase UI and Infinite Loading State When Retrying a Purchase ) but is not the same case: there, the first purchase works and only the retry-after-Back hangs, and clearing Appstore cache restores it. Here a clean first purchase hangs, and cache clear, data clear, reboot, Home-and-reopen and a brand-new Amazon account all make no difference.

Environment

  • Fire TV Stick , Fire OS 7.7.1.5
  • Appstore release-8.5104.5.v.x.246516.0_429364910
  • Appstore SDK 3.0.9 (also reproduced on 3.0.7)
  • SKU tvod_rental_movie_3_preprod (consumable)
  • Client library: openiap / expo-iap (calls the single-arg PurchasingService.purchase(String) on the main thread)

Appstore event timeline

Failing — SDK 3.x. From your own IapAD3LoggingDelegate, single requestId:

IapPurchaseItemCommandInitiated
IapPurchaseItemCommandResetSyncingCheckpoints
IapPurchaseItemCommandSuccess
IapTimeFromStartToFinishPurchaseItemCommandCompleted
IapTimeFromPurchaseItemCommandToDetailDialogInitiated
IapPurchaseItemCommandCompleted
IapGetIAPProductDetailsByVendorSkuListInitiated
IapGetIAPProductDetailsByVendorSkuListCompleted
IapGetIAPProductDetailsByVendorSkuListCalledWithGapm ← last event, ever

Working — legacy IAP 2.x, same device/account/SKU, 20 minutes earlier:

IapGetIAPProductDetailsByVendorSkuListCalledWithGapm (11:05:40.366)
IapPurchaseItemCommandMissingBillingType (11:05:40.407)
IapInAppBillingTypeHandled (11:05:40.428)
IapTimeFromStartToFinishGetItemInfoInitiated
IapProductDetailsFetchedFromODS (11:05:40.462) ← 96 ms after GAPM
IapConsumableFtvPurchaseV2DialogRendered
IapPurchaseConsumableInitiated
Questions:

  1. What causes the purchase flow to terminate after IapGetIAPProductDetailsByVendorSkuListCalledWithGapm without emitting IapProductDetailsFetchedFromODS, an error, or any callback?

2.Why does 2.x reach IapPurchaseItemCommandMissingBillingType → IapInAppBillingTypeHandled while 3.x never emits MissingBillingType for the same SKU? Does the 3.x request require a billing type that this LAT item cannot supply, and is there no fallback for that case ?

Hi @hanchaoui

Welcome to Amazon Developer Community!

Short version: the flow isn’t “abandoning” after metadata; it is stalling at the billing-type / GetAvailablePaymentMethods (GAPM) resolution step that sits between the product-details (GetIAPProductDetailsByVendorSkuList) call and IapProductDetailsFetchedFromODS.
In the Appstore’s own metric flow, IapGetIAPProductDetailsByVendorSkuListCalledWithGapm is not the end of the sequence - it’s immediately followed by billing-type handling, and only then does ODS get called. Your log ending on …CalledWithGapm means the billing-type step never completed.

On your two questions:
Q1 - Why does it terminate after CalledWithGapm with no ODS fetch, error, or callback?
A: IapGetIAPProductDetailsByVendorSkuListCalledWithGapm is emitted when the store fetches product/pricing data with a GAPM (available-payment-methods) request attached. In the working sequence, the very next steps are:

  1. …CalledWithGapm
  2. IapPurchaseItemCommandMissingBillingType → IapInAppBillingTypeHandled (billing type resolved from the GAPM/payment-methods response)
  3. IapProductDetailsFetchedFromODS
  4. dialog rendered
    IapProductDetailsFetchedFromODS is only logged from onGetItemProductDetailsFromODS(), which runs after billing type is resolved.
    Because your 3.x run stops at step 1 and never reaches step 2, the ODS fetch is never invoked - so there’s no dialog and no onPurchaseResponse(). It’s a silent stall in the FTV GAPM/payment-methods callback path, not a crash and not a rejected command (your IapPurchaseItemCommandSuccess confirms the command itself was accepted). This is why cache/data/reboot/new-account don’t help - the command dispatch succeeds every time; it’s the async payment-methods resolution that hangs.

Q2 - Why does 2.x reach MissingBillingType → InAppBillingTypeHandled but 3.x never emits MissingBillingType?
A: This is the key difference and it’s expected up to a point. The MissingBillingType event means no billing type was supplied, so resolve one - i.e., the store proactively runs the GAPM/payment-methods resolution to derive a billing type. In 2.x you see MissingBillingType → InAppBillingTypeHandled → ProductDetailsFetchedFromODS within ~40 ms, so resolution succeeds and the flow proceeds.
In 3.x, the store attaches GAPM to the product-details call itself (that’s what CalledWithGapm records). The 3.x FTV path expects the GAPM/available-payment-methods response to come back and drive billing-type handling (handleGAPMCallCompleted / loadPaymentMethods in the FireTV overrides). If that response is null, empty, or never returns for this account+SKU, the FTV path has a null-response branch that doesn’t fail loudly - it just doesn’t advance to ODS, and no MissingBillingType/error is emitted. So 3.x never reaching MissingBillingType for the same SKU points at the GAPM/payment-methods lookup returning nothing usable (or hanging) for this LAT preprod item, with no fallback to the 2.x-style resolve then proceed path.

What this most likely is (and what to check):

  • A preprod/LAT catalog + payment-methods mismatch on tvod_rental_movie_3_preprod: 2.x resolves billing type from the legacy catalog path; 3.x’s GAPM-attached path needs an available-payment-method for the account in the preprod marketplace, and if GAPM returns none, 3.x stalls where 2.x fell back. Worth confirming whether this account has a valid payment method in the preprod environment specifically (the 2.x success doesn’t prove this, because 2.x takes a different resolution path).
  • The single-arg main-thread PurchasingService.purchase(String) via openiap/expo-iap is a second thing to rule out - if the GAPM callback is posted to a main thread that’s blocked, loadPaymentMethods() never runs. Worth testing the same SKU with the official Amazon Appstore SDK sample (not the openiap wrapper) to isolate client-library vs. store behavior.

To help us root-cause, could you attach:

  1. Full unfiltered logs for that requestId from IapPurchaseItemCommandInitiated through ~10s after the last event (especially any GetAvailablePaymentMethods/GAPM /loadPaymentMethods / AvailablePaymentMethodResponse == null lines).
  2. Confirmation the test account has a valid payment instrument in the preprod marketplace.
  3. Result of the same purchase via the official Amazon Appstore SDK sample (rules the openiap/expo-iap wrapper in or out).

Warm Regards,
Ivy