UNPKG

a0-purchases

Version:

Lightweight subscription management for AI apps with auto-detecting providers

119 lines 5.8 kB
import { useState, useEffect, useCallback, useRef } from "react"; import { Platform } from "react-native"; import { useStripe, PaymentSheetError } from "./stripe"; import { registerStripePresenter, createLibraryError, PURCHASES_ERROR_CODE } from "./legacy-compat"; // Rename the component here export const A0PaymentProvider = () => { // Early return for iOS - disable all Stripe functionality if (Platform.OS === 'ios') { // Register a no-op presenter that rejects all requests on iOS useEffect(() => { registerStripePresenter({ requestPresentation: (request) => { request.reject(createLibraryError("Payment processing is disabled on iOS to comply with App Store guidelines.", PURCHASES_ERROR_CODE.STORE_PROBLEM_ERROR)); }, }); return () => { registerStripePresenter(null); }; }, []); // Return null - no Stripe functionality on iOS return null; } const { initPaymentSheet, presentPaymentSheet } = useStripe(); const [currentRequest, setCurrentRequest] = useState(null); const [isSheetInitialized, setIsSheetInitialized] = useState(false); const currentRequestRef = useRef(currentRequest); // Ref to avoid stale closures in callbacks useEffect(() => { currentRequestRef.current = currentRequest; }, [currentRequest]); // Callback for the service to trigger presentation const handlePresentationRequest = useCallback((request) => { // Update log messages // Ensure no request is already in progress if (currentRequestRef.current) { request.reject(createLibraryError("Another Stripe payment presentation is already in progress.", PURCHASES_ERROR_CODE.OPERATION_ALREADY_IN_PROGRESS_ERROR)); return; } setCurrentRequest(request); setIsSheetInitialized(false); // Reset initialization state }, []); // Register the callback with the service on mount, unregister on unmount useEffect(() => { // Update log message in PurchasesService.ts to reflect A0PaymentProvider if desired registerStripePresenter({ requestPresentation: handlePresentationRequest, }); return () => { registerStripePresenter(null); }; }, [handlePresentationRequest]); // Effect to initialize the Payment Sheet when a request arrives useEffect(() => { if (!currentRequest || isSheetInitialized) { return; } const initialize = async () => { // Update log messages const incomingPublishableKey = currentRequest.params .publishableKey; // await initStripe({ // stripeAccountId: (currentRequest.params as any).stripeAccountId, // publishableKey: incomingPublishableKey, // }); const { error } = await initPaymentSheet({ customerEphemeralKeySecret: currentRequest.params.ephemeralKey, merchantDisplayName: "A0", paymentIntentClientSecret: currentRequest.params.paymentIntent, setupIntentClientSecret: incomingPublishableKey, appearance: {}, // customerId: currentRequest.params.customer, // customerEphemeralKeySecret: currentRequest.params.ephemeralKey, // returnURL: 'yourappscheme://stripe-redirect', // Optional: for specific redirect flows // defaultBillingDetails: { ... } // Optional }); if (error) { // Update log messages console.error("[A0PaymentProvider] Error initializing Payment Sheet:", error); currentRequest.reject(createLibraryError(`Payment Sheet initialization failed: ${error.message}`, PURCHASES_ERROR_CODE.NETWORK_ERROR, // Or map Stripe errors error)); setCurrentRequest(null); // Clear the request on failure } else { setIsSheetInitialized(true); // Mark as initialized to trigger presentation } }; initialize(); }, [currentRequest, isSheetInitialized, initPaymentSheet]); // Effect to present the Payment Sheet once initialized useEffect(() => { if (!isSheetInitialized || !currentRequest) { return; } const present = async () => { const { error } = await presentPaymentSheet(); if (error) { // Update log messages console.log("[A0PaymentProvider] Payment Sheet presentation error or cancelled:", error); const userCancelled = error.code === PaymentSheetError.Canceled; // Corrected Canceled spelling currentRequest.reject(createLibraryError(userCancelled ? "Payment cancelled by user." : `Payment failed: ${error.message}`, userCancelled ? PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR : PURCHASES_ERROR_CODE.PURCHASE_INVALID_ERROR, // Map Stripe errors better if needed error, userCancelled)); } else { // IMPORTANT: Server-side verification via webhooks is still crucial here! currentRequest.resolve({ completed: true }); } // Clear the request and state regardless of outcome setCurrentRequest(null); setIsSheetInitialized(false); }; present(); }, [isSheetInitialized, currentRequest, presentPaymentSheet]); // This component does not render anything visual itself return null; }; //# sourceMappingURL=A0PaymentProvider.js.map