1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Flutter] Issue with In-App Purchase Discount Promo Code Process for iOS in Flutter App...

Discussão em 'Mobile' iniciado por Stack, Outubro 10, 2024 às 10:42.

  1. Stack

    Stack Membro Participativo

    I am facing an issue while reviewing the In-App Purchase discount promo code process for iOS. It is working well on Android.

    We have integrated the In-App Purchase mechanism in our Flutter app and now want to verify it on iOS. On iOS, we display the PromoCodeRedemptionSheet (provided by Apple’s In-App Purchase Kit framework) where the user can enter a promo code.

    After entering the code and successfully applying it, once the redemption sheet is dismissed, we are not receiving the callback in the listener for the PurchaseUpdated event.

    It worked fine the first time, but the issue occurs when we attempt to review the process again.

    Note: To verify the promo code mechanism during debugging, we added a StoreKit file in Xcode and are using that StoreKit configuration to simulate the purchase process. When the redemption sheet opens, all the promo codes created in the Apple Developer Console are displayed, allowing the user to select one. The selected offer code is applied, and the user sees the sandbox payment sheet. After a successful payment, we see the "Thank You" screen with a "Close" button. However, after tapping the "Close" button and dismissing the redemption sheet, the callback is not received at the app level in the purchase stream.

    class OfferCodeScreenForIosState extends State<OfferCodeScreenForIos> {
    final InAppPurchase _iap = InAppPurchase.instance;
    late StreamSubscription<List<PurchaseDetails>> _subscription;
    bool _isAvailable = false;
    List<ProductDetails> _products = [];
    bool _loading = true;

    @override
    void initState() {
    super.initState();
    printf("Offer_Code_ScreenFor_iOS > initState");

    // Set up a listener for purchases
    final purchaseUpdated = _iap.purchaseStream;

    _subscription = purchaseUpdated.listen((purchases) {
    **//// THIS IS NOT WORKING WHEN PURCHASING THE DIFFERENT IN-APP SECOND TIME**
    printf("Offer_Code_ScreenFor_iOS > purchaseUpdated.listen");
    _handlePurchaseUpdates(purchases);
    }, onError: (error) {
    // Handle error
    printf("Purchase Error: $error");
    });

    // Initialize In-App Purchases
    _initializeStore();
    }

    Future<void> _initializeStore() async {
    // Check availability of the store
    _isAvailable = await _iap.isAvailable();
    if (_isAvailable) {
    const Set<String> ids = {
    '{{INAPP_PURCHASE_PRODUCT_ID}}',
    };
    final ProductDetailsResponse response =
    await _iap.queryProductDetails(ids);

    if (response.notFoundIDs.isNotEmpty) {
    printf("Not found IDs: ${response.notFoundIDs}");
    }

    setState(() {
    _products = response.productDetails;
    _loading = false;
    });
    }
    }

    Future<void> _redeemOfferCode() async {
    if (await SKPaymentQueueWrapper.canMakePayments()) {
    try {
    final iapStoreKitPlatformAddition =
    _iap.getPlatformAddition<InAppPurchaseStoreKitPlatformAddition>();

    await iapStoreKitPlatformAddition.presentCodeRedemptionSheet();
    } catch (e) {
    printf("Error presenting Offer Code Redemption Sheet: $e");
    }
    } else {
    printf("In-App Purchases are disabled on this device.");
    }
    }

    // Handle purchase updates
    void _handlePurchaseUpdates(List<PurchaseDetails> purchases) {
    for (var purchase in purchases) {
    if (purchase.status == PurchaseStatus.purchased) {
    printf("Purchase successful: ${purchase.productID}");
    //// COMPLETING PURCHASE FOR TESTING BUT WE WILL NEED TO VERIFY SERVER VERIFICATION DATA HERE
    _iap.completePurchase(purchase);

    } else if (purchase.status == PurchaseStatus.pending) {
    printf(
    "Purchase status pending purchaseID: ${purchase.purchaseID}");
    } else if (purchase.status == PurchaseStatus.restored) {
    printf("Purchase Restored: ${purchase.purchaseID}");
    } else if (purchase.status == PurchaseStatus.canceled) {
    printf("Purchase Cancelled: ${purchase.purchaseID}");
    } else if (purchase.status == PurchaseStatus.error) {
    printf("Purchase error: ${purchase.error?.message}");
    }
    }
    }
    }

    Continue reading...

Compartilhe esta Página