Integration of AliPay Payment Gateway using Stripe Sources

Image result for alipay logo svg

Integration of AliPay Payment Gateway using Stripe Sources

This blog post explains the process of how Stripe Sources has been leveraged to integrate AliPay to extend the payment options in China.

Stripe provides a plethora of payment options configurable with Sources

Source objects allow you to accept a variety of payment methods with a single API. A source represents a customer’s payment instrument, and can be used with the Stripe API to create payments. Sources can be charged directly, or attached to customers for later reuse.

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.

   Workflow of Alipay on the backend

During the payment process, a Source API object is created and your customer is redirected to AliPay for authorization.

Payment Flow

  1. Create a Source Object with the parameters currency, redirect_url and amount.
  2. Create a page for completion of customer authorization by specifying the redirect_url.
  3. Change the source status from pending to chargeable.
  4. Confirm the payment by redirecting to the confirmation page and process the refund for any unsuccessful payments(if deducted)

Configuration Manager

Initially, we define a class named as AliPayPaymentsManager which handles the configuration of API keys and has methods to create source objects and make them chargeable.

class AliPayPaymentsManager(object):
    """
    Class to manage AliPay Payments
    """

    @staticmethod
    def create_source(amount, currency, redirect_return_uri):
        stripe.api_key = get_settings()['alipay_publishable_key']
        response = stripe.Source.create(type='alipay',
                                        currency=currency,
                                        amount=amount,
                                        redirect={
                                            'return_url': redirect_return_uri
                                        }
                                        )
        return response

    @staticmethod
    def charge_source(order_identifier):
        order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
        stripe.api_key = get_settings()['alipay_secret_key']
        charge = stripe.Charge.create(
                 amount=int(order.amount),
                 currency=order.event.payment_currency,
                 source=order.order_notes,
                 )
        return charge

                Methods to create & charge the source

The challenge of charging the source & redirection

After creating the source object, we need to make the source object chargeable. For this purpose, the user must be redirected to the external AliPay payment gateway page where the source object is authorized and its status is changed to chargeable. The main challenge to overcome here was the method in which the redirect link was attached to the object. The parameter _external is really crucial for this process as Flask would only recognize the url as an external url if this parameter is passed to url_for.

@alipay_blueprint.route('/create_source/<string:order_identifier>', methods=['GET', 'POST'])
def create_source(order_identifier):
    """
    Create a source object for alipay payments.
    :param order_identifier:
    :return: The alipay redirection link.
    """
    try:
        order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
        source_object = AliPayPaymentsManager.create_source(amount=int(order.amount), currency='usd',
                                                            redirect_return_uri=url_for('alipay_blueprint.alipay_return_uri',
                                                            order_identifier=order.identifier, _external=True))
        order.order_notes = source_object.id
        save_to_db(order)
        return jsonify(link=source_object.redirect['url'])
    except TypeError:
        return BadRequestError({'source': ''}, 'Source creation error').respond()

Route which creates the source and returns external redirection url

After the source object is created, the status changes to pending. To charge the user, the source object must become chargeable. For this, we need to redirect the user to an external page where the payment can be authorized and the source object can become chargeable.

External Authorization Page for AliPay

After authorizing the payment, we redirect to the url given in return_redirect_uri which is configured with the source object which tries to charge the source object as it is now chargeable. After this, a POST request is sent to the return_redirect_uri route which handles success and failure cases

@alipay_blueprint.route('/alipay_return_uri/', methods=['GET', 'POST'])
def alipay_return_uri(order_identifier):
    """
    Charge Object creation & Order finalization for Alipay payments.
    :param order_identifier:
    :return: JSON response of the payment status.
    """
    try:
        charge_response = AliPayPaymentsManager.charge_source(order_identifier)
        if charge_response.status == 'succeeded':
            order = safe_query(db, Order, 'identifier', order_identifier, 'identifier')
            order.status = 'completed'
            save_to_db(order)
            return redirect(make_frontend_url('/orders/{}/view'.format(order_identifier)))
        else:
            return jsonify(status=False, error='Charge object failure')
    except TypeError:
        return jsonify(status=False, error='Source object status error')

After AliPay authorization, the order is saved and payment is completed

Resources:

Related work and code repo:

Tags:

Eventyay, FOSSASIA, Flask, Ember.js, Open Event, Python, AliPay, Stripe

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.