Alipay Guide

Accept payments from hundreds of millions of new customers using Alipay, China's most popular payment method. If you need help after reading this, check out our answers to common questions or chat live with other developers in #stripe on freenode.

Stripe users in the United States can accept Alipay, a digital wallet service, for USD payments using Checkout. Stripe handles Alipay payments in the same way as credit card payments—creating charges even uses the same server-side code which means no additional code changes are needed. Stripe’s fee for Alipay payments is even the same as credit card payments, too.

The entire Alipay payment process is completed on your site, so customers aren’t redirected to alipay.com. This provides Alipay users with a seamless payment experience, resulting in a higher conversion rate for sellers.

Alipay processes charges for their users in RMB, while Stripe handles conversion of this to USD automatically. A Chinese bank account or business entity is not required to accept Alipay payments.

Creating an Alipay charge uses the same process as a credit card charge. First, your customer provides their Alipay payment details in Checkout—Stripe creates a token and sends it to your integration. Next, your server-side code uses this token when creating a charge request via the Stripe API. Alipay payment information can even be saved as a reusable payment method.

Using Alipay in Checkout

During the payment process, SMS verification is used to authenticate the Alipay user. For some payments, Stripe will dynamically request the last five digits of the customer’s national ID number as an additional factor of authentication.

Using your test API keys, you can test Alipay payments in Checkout using any email address you wish. When performing test payments, the SMS verification code required is 123456 and the last five digits of the customer’s national ID number is 12345. Click the button below to see Checkout with Alipay in action.

Configuring Checkout

After integrating Checkout for card payments, only one code change is needed to begin accepting Alipay payments—the addition of data-alipay in your Checkout code, as shown below. This requires one of the following values:

  • true: Alipay is shown as a payment option in Checkout to all customers
  • auto: Alipay is shown as a payment option in Checkout only to customers likely to have an Alipay account
<form action="" method="POST">
  <script
    src="https://checkout.stripe.com/checkout.js" class="stripe-button"
    data-key=pk_test_6pRNASCoBOKtIshFeQd4XMUh
    data-amount="2000"
    data-name="Demo Site"
    data-description="2 widgets ($20.00)"
    data-image="/128x128.png"
    data-label="Pay with Card or Alipay"
    data-locale="auto"
    data-currency="usd"
    data-alipay="true">
  </script>
</form>

The default label of the Checkout button is “Pay with Card”. We recommend making use of the data-label option to promote your acceptance of Alipay more noticeable to customers.

Supported Alipay accounts

Because of foreign exchange restrictions on RMB, Alipay users can only use Checkout if their Alipay account is verified. The Alipay user must have proven their identity as a citizen of mainland China. The only other requirement on the customer’s Alipay account is that it has a linked mobile number and that it is capable of funding the payment.

Creating a charge

Alipay charges are created in the same way as card charges, even using the same server-side code. Checkout generates a token representing the payment details, which is then used by your server-side code when making a charge request to the Stripe API.

While Checkout returns a token of type card for card payments, Alipay payment details (referred to as Alipay accounts) result in a token of type alipay_account. Both types of token can be used in exactly the same way, for example, to create a charge.

curl https://api.stripe.com/v1/charges \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
   -d amount=1000 \
   -d currency=usd \
   -d source=atok_4XNshPRgmDRCVi \
   -d description="Example Alipay charge"
# 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_BQokikJOvBiI2HlWgH4olfQ2"

# Get the Alipay token submitted by Checkout
token = params[:stripeToken]

# Create a charge: this will charge the user's Alipay account
begin
  charge = Stripe::Charge.create(
    :amount => 1000, # Amount in cents
    :currency => "usd",
    :source => token,
    :description => "Example Alipay charge"
  )
rescue Stripe::CardError => e
  # The Alipay account has been declined
end
# 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_BQokikJOvBiI2HlWgH4olfQ2"

# Get the Alipay token submitted by Checkout
token = request.POST['stripeToken']

# Create a charge: this will charge the user's Alipay account
try:
  charge = stripe.Charge.create(
      amount=1000, # Amount in cents
      currency="usd",
      source=token,
      description="Example Alipay charge"
  )
except stripe.error.CardError as e:
  # The Alipay account has been declined
  pass
// 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_BQokikJOvBiI2HlWgH4olfQ2");

// Get the Alipay token submitted by Checkout
$token = $_POST['stripeToken'];

// Create a charge: this will charge the user's Alipay account
try {
  $charge = \Stripe\Charge::create(array(
    "amount" => 1000, // Amount in cents
    "currency" => "usd",
    "source" => $token,
    "description" => "Example Alipay charge"
    ));
} catch(\Stripe\Error\Card $e) {
  // The Alipay account has been declined
}
// 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_BQokikJOvBiI2HlWgH4olfQ2";

// Get the Alipay token submitted by Checkout
String token = request.getParameter("stripeToken");

// Create a charge: this will charge the user's Alipay account
try {
  Map<String, Object> chargeParams = new HashMap<String, Object>();
  chargeParams.put("amount", 1000); // Amount in cents
  chargeParams.put("currency", "usd");
  chargeParams.put("source", token);
  chargeParams.put("description", "Example Alipay charge");

  Charge charge = Charge.create(chargeParams);
} catch (CardException e) {
  // The Alipay account has been declined
}
// 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
var stripe = require("stripe")("sk_test_BQokikJOvBiI2HlWgH4olfQ2");

// Get the Alipay token submitted by Checkout
var token = request.body.stripeToken; // Using Express

// Create a charge: this will charge the user's Alipay account
stripe.charges.create({
  amount: 1000, // Amount in cents
  currency: "usd",
  source: token,
  description: "Example Alipay charge charge"
}, function(err, charge) {
  if (err && err.type === 'StripeCardError') {
    // The Alipay account has been declined
  }
});
// 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_BQokikJOvBiI2HlWgH4olfQ2"

// Get the Alipay token submitted by Checkout:
token := r.FormValue("stripeToken")

// Create a charge: this will charge the user's Alipay account
chargeParams := &stripe.ChargeParams{
  Amount: 1000,
  Currency: "usd",
  Desc: "Example Alipay charge",
}
chargeParams.SetSource(stripeToken)
ch, err := charge.New(chargeParams)

When creating one-time charges, you must pass the amount and currency parameters. This is referred to as non-reusable account access (the verification SMS also informs the customer of the amount and currency). To save Alipay account information to create future charges, enable reusable account access.

Refunds

Alipay’s refund policy allows for payments to be refunded up to 90 days from their creation date. Should you need to refund a payment after this time, an alternative form of credit has to be provided to the customer.

We recommend you provide a discount to your customer through the use of a discount code system that can be used to change the amount of a future order. Check out our recipe on creating a coupon system for standalone charges to find out how you could build this.

Partial refunds are only supported if the currency of the payment is USD. If the payment was created in any other currency, partial refunds are not supported—you can only refund the entire payment.

Declines and disputes

As is the case with card payments, Alipay payments can be declined by either Alipay or Stripe. Should this occur, your integration receives the appropriate error response to act upon.

There is no dispute process that Stripe users see for Alipay payments. If a customer’s Alipay account is used illicitly, Alipay and Stripe will 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.

Payment limits

Stripe sets both per charge and per Alipay user payment limits to prevent any potential abuse of a compromised Alipay account:

  • 750.00 USD per payment
  • 2,250.00 USD per customer per month

If you need to increase this limit, please let us know.

Reusable account access

To use an Alipay account for recurring payments, include data-alipay-reusable="true" when loading Checkout. Alipay users are accustomed to only allowing reusable access in certain circumstances so you should only ask for this access where necessary, and make this clear to the user. Checkout will also display a message to your customer that you’ve requested reusable access.

You can check if reusable access is available by making an API request with the received Alipay account token to the /v1/tokens endpoint.

curl https://api.stripe.com/v1/tokens/atok_4XNshPRgmDRCVi \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2:
# 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_BQokikJOvBiI2HlWgH4olfQ2"

Stripe::Token.retrieve("atok_4XNshPRgmDRCVi")
# 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_BQokikJOvBiI2HlWgH4olfQ2"

stripe.Token.retrieve("atok_4XNshPRgmDRCVi")
// 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_BQokikJOvBiI2HlWgH4olfQ2");

\Stripe\Token::retrieve("atok_4XNshPRgmDRCVi");
// 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_BQokikJOvBiI2HlWgH4olfQ2";

Token.retrieve("atok_4XNshPRgmDRCVi");
// 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
var stripe = require("stripe")("sk_test_BQokikJOvBiI2HlWgH4olfQ2");

stripe.tokens.retrieve("atok_4XNshPRgmDRCVi",
  function(err, token) {
    // 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_BQokikJOvBiI2HlWgH4olfQ2"

t, err := token.Get("atok_4XNshPRgmDRCVi", nil)

If reusable access is available, reusable is set to true. Both payment_amount and payment_currency are also set to null.

"alipay_account": {
  "id": "aliacc_4VlyMzbhx5cMJ4",
  "object": "alipay_account",
  "livemode": false,
  "created": 1406916427,
  "fingerprint": "VcfP7nsUODDwkd5M",
  "used": false,
  "reusable": true,
  "payment_amount": null,
  "payment_currency": null
}

If you do not have reusable access, reusable is set to false. Both payment_amount and payment_currency then indicate the amount and currency of the payment that you can create.

Alipay account objects have a used attribute that indicate whether it has been used to create a payment.

"alipay_account": {
  "id": "aliacc_3REbvwet45Rfg3",
  "object": "alipay_account",
  "livemode": false,
  "created": 1406916427,
  "fingerprint": "eHYF4hgbCfgf64Vv",
  "used": false,
  "reusable": false,
  "payment_amount": 2000,
  "payment_currency": "USD"
}

Saving an Alipay account to a customer

An Alipay account that has granted you reusable access can be saved to a Customer object, in the same way as card details. The Alipay account is then available as a payment method for future charges and recurring payments.

curl https://api.stripe.com/v1/customers/cus_7iLOlPKxhQJ75a \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
   -d source=atok_4XNshPRgmDRCVi
# 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_BQokikJOvBiI2HlWgH4olfQ2"

# Get the Alipay token submitted by Checkout
token = params[:stripeToken]

# Retrieve a Customer object and save the token to it
cu = Stripe::Customer.retrieve("cus_7iLOlPKxhQJ75a")
cu.source = token
cu.save
# 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_BQokikJOvBiI2HlWgH4olfQ2"

# Get the Alipay token submitted by Checkout
token = request.POST['stripeToken']

# Retrieve a Customer object and save the token to it
cu = stripe.Customer.retrieve("cus_7iLOlPKxhQJ75a")
cu.source = token
cu.save()
// 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_BQokikJOvBiI2HlWgH4olfQ2");

// Get the Alipay token submitted by Checkout
$token = $_POST['stripeToken'];

// Retrieve a Customer object and save the token to it
$cu = \Stripe\Customer::retrieve("cus_7iLOlPKxhQJ75a");
$cu->source = $token;
$cu->save();
// 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_BQokikJOvBiI2HlWgH4olfQ2";

// Get the Alipay token submitted by Checkout
String token = request.getParameter("stripeToken");

// Retrieve a Customer object and save the token to it
Customer cu = Customer.retrieve("cus_7iLOlPKxhQJ75a");
Map<String, Object> updateParams = new HashMap<String, Object>();
updateParams.put("SOURCE", token);

cu.update(updateParams);
// 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
var stripe = require("stripe")("sk_test_BQokikJOvBiI2HlWgH4olfQ2");

// Get the Alipay token submitted by Checkout
var token = request.body.stripeToken; // Using Express

// Retrieve a Customer object and save the token to it
stripe.customers.update("cus_7iLOlPKxhQJ75a", {
  source: token
}, function(err, customer) {
  // 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_BQokikJOvBiI2HlWgH4olfQ2"

// Get the Alipay token submitted by Checkout:
token := r.FormValue("stripeToken")

// Retrieve a Customer object and save the token to it
customerParams := &stripe.CustomerParams{}
customerParams.SetSource(token);
c, err := customer.Update("cus_7iLOlPKxhQJ75a", customerParams);

Creating test Alipay account tokens

You can create Alipay account tokens in test mode directly through the API, rather than going through the process of using Checkout.

curl https://api.stripe.com/v1/tokens \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
   -d email="maidongxi@example.com" \
   -d alipay_account[reusable]=true
# 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_BQokikJOvBiI2HlWgH4olfQ2"

Stripe::Token.create(
  :email => "maidongxi@example.com",
  :alipay_account => {
    # Create an Alipay account token with reusable account access
    :reusable => "true"
  },
)
# 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_BQokikJOvBiI2HlWgH4olfQ2"

stripe.Token.create(
  email="maidongxi@example.com",
  alipay_account={
    # Create an Alipay account token with reusable account access
    "reusable": 'true'
  },
)
// 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_BQokikJOvBiI2HlWgH4olfQ2");

\Stripe\Token::create(array(
  "email" => "maidongxi@example.com",
  "alipay_account" => array(
    // Create an Alipay account token with reusable account access
    "reusable" => "true"
  )
));
// 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_BQokikJOvBiI2HlWgH4olfQ2";

Map<String, Object> tokenParams = new HashMap<String, Object>();
Map<String, Object> sourceParams = new HashMap<String, Object>();
sourceParams.put("reusable", "true");
tokenParams.put("email", "maidongxi@example.com");
// Create an Alipay account token with reusable account access
tokenParams.put("alipay_account", sourceParams);

Token.create(tokenParams);
// 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
var stripe = require("stripe")("sk_test_BQokikJOvBiI2HlWgH4olfQ2");

stripe.tokens.create({
  email: 'maidongxi@example.com',
  alipay_account: {
    // Create an Alipay account token with reusable account access
    "reusable": 'true'
  }
}, function(err, token) {
  // 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_BQokikJOvBiI2HlWgH4olfQ2"

// Support for creating Alipay test tokens in our Go library is forthcoming.

The alipay_account parameter supports the following fields:

  • alipay_username: Optional. Default to the email address on the token.
  • reusable: Required. Either true or false.
  • payment_amount and payment_currency: Provide these only if reusable is false.
"id": "atok_8BTuerteJtzAht",
"object": "token",
"alipay_account": {
  "id": "aliacc_8BTuRDFkT09LRJ",
  "object": "alipay_account",
  "created": 1459435110,
  "customer": null,
  "fingerprint": "KEtHmiDqXq6tbQJl",
  "livemode": false,
  "metadata": {},
  "payment_amount": null,
  "payment_currency": null,
  "reusable": true,
  "used": false,
  "username": "maidongxi@example.com"
},
...

More information about Alipay account tokens is available in our API reference.

Webhook events

A successful Alipay payment generates the charge.succeeded event, which is the same as a successful credit card charge.

You can refer to our webhooks documentation for more information on receiving webhook notifications.