Alipay on iOS

    Use Sources to accept payments in your iOS app using Alipay

    The Stripe iOS SDK natively supports Alipay, without the need to install a third party SDK.

    During the payment process, a Source object is created and your customer is redirected to Alipay for authorization. After completing authorization, the customer is redirected back to your app and your integration uses the Source to make a charge request and complete the payment.

    Alipay is a push-based, single-use and synchronous method of payment. This means that your customer takes action to authorize the push of funds through a redirect. There is immediate confirmation about the success or failure of a payment.

    Making Alipay payments using the iOS SDK is a 5 step process.

    1. Set up your client integration
    2. Create a Source object in your app or backend
    3. Redirect your customer to Alipay
    4. Charge the Source on your backend
    5. Confirm the Charge succeeded

    Step 1: Set up your integration Client-side

    Register your custom URL scheme

    The Alipay app redirects your customer back to your app when they finish paying, using a custom URL scheme. Register this URL scheme by going to the Info tab of your app target settings.

    When the Alipay app opens your app using the URL scheme, forward the URL to the Stripe SDK in your UIApplicationDelegate:

    // This method handles opening custom URL schemes (e.g., "your-app://")
    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        let stripeHandled = Stripe.handleURLCallback(with: url)
        if (stripeHandled) {
            return true
        } else {
            // This was not a Stripe url – handle the URL normally as you would
        }
        return false
    }
    // This method handles opening custom URL schemes (e.g., "your-app://")
    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
        BOOL stripeHandled = [Stripe handleStripeURLCallbackWithURL:url];
        if (stripeHandled) {
            return YES;
        } else {
            // This was not a Stripe url – handle the URL normally as you would
        }
        return NO;
    }

    Step 2: Create a Source object in your app or backend Client-side Server-side

    A Source object is either created client-side using the iOS SDK or server-side using the Source creation endpoint, with the following parameters:

    Parameter Value
    type alipay
    currency The currency of the payment. Must be the default currency for your country. Can be aud, cad, eur, gbp, hkd, jpy, nzd, sgd, or usd. Users in Denmark, Norway, Sweden, or Switzerland must use eur.
    redirect[return_url] The URL the customer should be redirected to after the authorization process. This must be your custom URL scheme with safepay/ appended. For example, if your custom URL scheme is “myapp”, your return URL must be myapp://safepay/
    amount A positive integer in the smallest currency unit representing the amount to charge the customer (e.g., 1099 for a $10.99 payment).

    To create a Source on the client, initialize an STPSourceParams instance and call STPAPIClient createSourceWithParams:completion:.

    // Create a Source
    let sourceParams = STPSourceParams.alipayParams(withAmount: 1099, currency: "USD", returnURL: "myapp://safepay/", statementDescriptor: nil)
    STPAPIClient.shared().createSource(with: sourceParams) { source, error in
        guard let source = source, error == nil else {
            // Handle error
            return
        }
        // ...continued in the next step
    }
    // Create a Source
    STPSourceParams *sourceParams = [STPSourceParams alipayParamsWithAmount:1099
                                                                   currency:@"USD"
                                                                  returnURL:@"myapp://safepay/"
                                                        statementDescriptor:nil];
    [[STPAPIClient sharedClient] createSourceWithParams:sourceParams completion:^(STPSource *source, NSError *error) {
        if (error) {
            // Handle error
            return;
        }
        // ...continued in the next step
    }];

    Using either method, Stripe returns a Source object containing the relevant details for the method of payment used. Information specific to Alipay is provided within the alipay subhash.

    {
      "id": "src_16xhynE8WzK49JbAs9M21jaR",
      "object": "source",
      "amount": 1099,
      "client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU",
      "created": 1445277809,
      "currency": "usd",
      "flow": "redirect",
      "livemode": true,
      "owner": {

    See all 33 lines "address": null, "email": null, "name": "null", "phone": null, "verified_address": null, "verified_email": null, "verified_name": "null", "verified_phone": null }, "redirect": { "return_url": "myapp://safepay/", "status": "pending", "url": "https://hooks.stripe.com/redirect/src_16xhynE8WzK49JbAs9M21jaR?client_secret=src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU" }, "statement_descriptor": null, "status": "pending", "type": "alipay", "usage": "single_use", "alipay": { "statement_descriptor": null, "native_url": null } }

    Error codes

    Source creation for Alipay payments may return any of the following errors:

    Error Description
    payment_method_not_available The payment method is currently not available. You should invite your customer to fallback to another payment method to proceed.
    processing_error An unexpected error occurred preventing us from creating the source. The source creation should be retried.

    Step 3: Redirect your customer to Alipay Client-side

    After creating a Source, its status is set to pending and cannot be used to make a charge request. Use STPRedirectContext to redirect your customer to their Alipay app to authorize the payment and make the Source chargeable.

    // Create a Source
    let sourceParams = STPSourceParams.alipayParams(withAmount: 1099, currency: "USD", returnURL: "myapp://safepay/", statementDescriptor: nil)
    STPAPIClient.shared().createSource(with: sourceParams) { source, error in
        guard let source = source, error == nil else {
            // Handle error
            return
        }
        // Redirect the customer to authorize the payment
        self.redirectContext = STPRedirectContext(source: source) { sourceID, clientSecret, error in
            guard error == nil else {
                // Handle error
                return
            }
            // Poll your backend for the status of the order
        }
        self.redirectContext.startRedirectFlow(from: self)
    }
    // Create a Source
    STPSourceParams *sourceParams = [STPSourceParams alipayParamsWithAmount:1099
                                                                   currency:@"USD"
                                                                  returnURL:@"myapp://safepay/"
                                                        statementDescriptor:nil];
    [[STPAPIClient sharedClient] createSourceWithParams:sourceParams completion:^(STPSource *source, NSError *error) {
        if (error) {
            // Handle error
            return;
        }
        // Redirect the customer to authorize the payment
        self.redirectContext = [[STPRedirectContext alloc] initWithSource:source completion:^(NSString *sourceID, NSString *clientSecret, NSError *error) {
            if (error) {
                // Handle error
                return;
            }
            // Poll your backend for the status of the order
        }];
        [self.redirectContext startRedirectFlowFromViewController:self];
    }];

    Step 4: Charge the Source Server-side

    Once the customer has authorized the payment, the source’s status transitions to chargeable and it can be used to make one charge request. This transition happens asynchronously and may occur after the customer was redirected back to your app.

    Some customers using Alipay assume that the order process is complete once they have authorized the payment and received confirmation on Alipay, instead of following the redirect and returning to your app.

    For this reason it is essential that your integration rely on webhooks to determine when the source becomes chargeable in order to create a charge. Please refer to our best practices for more details on how to best integrate payment methods using webhooks.

    Webhooks

    The following webhook events are sent to notify you about changes to the source’s status:

    Event Description
    source.chargeable A Source object becomes chargeable after a customer has authorized and verified a payment.
    source.failed A Source object failed to become chargeable as your customer declined to authorize the payment.
    source.canceled A Source object expired and cannot be used to create a charge.

    Make a charge request using the source

    Once the source is chargeable, from your source.chargeable webhook handler, you can make a charge request using the source ID as the value for the source parameter to complete the payment.

    curl https://api.stripe.com/v1/charges \
      -u sk_test_4eC39HqLyjWDarjtT1zdp7dc: \
      -d amount=1099 \
      -d currency=eur \
      -d source=src_18eYalAHEMiOZZp1l9ZTjSU0
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    charge = Stripe::Charge.create({
      amount: 1099,
      currency: 'eur',
      source: 'src_18eYalAHEMiOZZp1l9ZTjSU0',
    })
    
    # Set your secret key: remember to change this to your live secret key in production
    # See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
    
    charge = stripe.Charge.create(
      amount=1099,
      currency='eur',
      source='src_18eYalAHEMiOZZp1l9ZTjSU0',
    )
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    $charge = \Stripe\Charge::create([
      'amount' => 1099,
      'currency' => 'eur',
      'source' => 'src_18eYalAHEMiOZZp1l9ZTjSU0',
    ]);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("amount", 1099);
    params.put("currency", "eur");
    params.put("source", "src_18eYalAHEMiOZZp1l9ZTjSU0");
    
    Charge charge = Charge.create(params);
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
    
    stripe.charges.create({
      amount: 1099,
      currency: 'eur',
      source: 'src_18eYalAHEMiOZZp1l9ZTjSU0',
    }, function(err, charge) {
      // asynchronously called
    });
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"
    
    chargeParams := &stripe.ChargeParams{
      Amount: stripe.Int64(1099),
      Currency: stripe.String(string(stripe.CurrencyEUR)),
    }
    chargeParams.SetSource("src_18eYalAHEMiOZZp1l9ZTjSU0")
    ch, err := charge.New(chargeParams)
    
    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc";
    
    var options = new ChargeCreateOptions
    {
        Amount = 1099,
        Currency = "eur",
        Source = "src_18eYalAHEMiOZZp1l9ZTjSU0",
    };
    
    var service = new ChargeService();
    Charge charge = service.Create(options);
    

    By default, your account’s statement descriptor appears on customer statements whenever you create an Alipay payment.

    Error codes

    Charge creation for Alipay payments may return any of the following errors:

    Error Description
    insufficient_funds The Alipay account has insufficient funds to complete the purchase. The customer should fund their account and try again, or use an alternative payment method.
    invalid_amount This occurs if the charge amount is larger than supported by Alipay.

    Step 5: Confirm the Charge succeeded Server-side

    Since the customer has already authorized the payment as part of the redirect, unless there is an unexpected error, the Charge will immediately succeed.

    You will also receive the following webhook event as the charge is created:

    Event Description
    charge.succeeded The charge succeeded and the payment is complete.

    We recommend that you rely on the charge.succeeded webhook event to notify your customer that the payment process has been completed and their order is confirmed. Please refer to our best practices for more details on how to best integrate payment methods using webhooks.

    Disputed payments

    If a customer’s Alipay account is used illicitly, Alipay and Stripe handle the issue internally. In the context of Alipay, payments are only disputed if the customer has a complaint about the provided goods or service. Should a dispute occur, a dispute.created webhook event is sent, and Stripe deducts the amount of the dispute from your Stripe balance.

    Refunds

    Payments made with Alipay can only be submitted for refund within 90 days from the date of the original charge. After 90 days, it is no longer possible to refund the charge.

    Single-use Sources expiration

    A single-use Alipay source must be charged within six hours of becoming chargeable, or before 23:45 China Standard Time (GMT+8) due to Chinese government restrictions around settlement. If it is not, its status is automatically transitioned to canceled and your integration receives a source.canceled webhook event. Once a chargeable source is canceled, the customer’s authorized Alipay payment is refunded automatically—no money is moved into your account. For this reason, make sure the order is canceled on your end and the customer is notified when you receive the source.canceled event.

    Additionally, pending sources are canceled after one hour if they are not used to authorize a payment, ensuring that all sources eventually transition out of their pending state to the canceled state if they are not used.

    Settlement currencies

    Alipay supports like-for-like settlement only so the currency of Alipay sources must match your account’s default currency. If you have a bank account in another currency and would like to create Alipay sources in that currency, please get in touch. Support for additional currencies is provided on a case-by-case basis.

    Related resources

    Was this page helpful?

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page