Alipay+Alipay+

Guide on redirections between the merchant and the Mobile Payment Partner

1. Overview

For Alipay+ Auto Debit, redirections between the merchant and the Mobile Payment Partner (MPP, normally, a digital wallet) occur during the authorization process.

For Alipay+ Cashier Payment, redirections between the merchant and the MPP occur during the payment process.

This document explains how the redirections work on Android, iOS, and Web sides, and provides best practices on how to handle the redirections in different scenarios.

1.1 Process

This section describes the redirection processes for Auto Debit and Cashier Payment in detail.

1.1.1 Auto Debit

The following figure illustrates the redirection process:

Guide on redirections between the merchant and the Mobile Payment Partner

For Auto Debit, redirections occur during the authorization process. See the following list for the process breakdown:

  1. On the merchant side, the user selects a wallet to authorize. The merchant sends the authorization info to the Acquiring Partner (ACQP) (Step 1 - 3).
  2. The ACQP uses prepare interface to obtain the authorization URL (Step 4 - 10). authRedirectUrl must be included in the request, which is used to redirect the user back to the merchant at the user completes the authorization.
  3. The merchant system redirects the user to the authorization page specified by the authorization URL (Step 11).
  4. The wallet system renders the authorization page, where the user completes the authorization (Step 12 - 13).
  5. The wallet processes the authorization and redirects the user back to the merchant page specified by authRedirectUrl (Step 14 - 16). The authorization code (authCode) is attached in the authRedirectUrl (Step 14 - 16).
  6. With the authCode, the merchant system uses the applyToken interface to obtain accessToken, which is used to debit funds from the user's authorized wallet (Step 17 - 24).

1.1.2 Cashier Payment

The following figure illustrates the redirection process:

Guide on redirections between the merchant and the Mobile Payment Partner

For Cashier Payment, redirections occur during the payment process. See the following list for the process breakdown:

  1. On the merchant side, the user selects a wallet to pay. The merchant sends the payment order info to the ACQP (Step 1 - 3).
  2. The ACQP uses the pay interface to send the payment request to Alipay+ (Step 4). paymentRedirectUrl must be included in the request, which is used to redirect the user back to the merchant after the payment is completed.
  3. Alipay+ processes the request and returns the payment redirection URL to the merchant (Step 5 -9).
  4. The merchant redirects the user to the cashier page specified by the payment URL, where the user pays (Step 10 - 12).
  5. The wallet processes the payment and redirects the user back to the merchant page specified by paymentRedirectUrl (Step 14 - 16).

Note:

When the terminal type of the merchant is Web, and if the order code is merchant-rendered QR code, no redirection occurs.

For more information about limitations for redirection, see section 1.2.

1.2 Client type and redirections

For both Auto Debit and Cashier Payment, the redirections always occur in 2 stages:

  1. The user is redirected from the merchant side to the wallet side.
  2. The user is redirected from the wallet side back to the merchant side.

For Auto Debit, both redirections must succeed. For Cashier Payment, the second redirection does not affect the payment result.

Furthermore, the merchant client and the wallet client can be either app, WAP, or web. However, redirections can only happen between certain terminal types of client-side. See the following sections for details.

1.2.1 Auto Debit

  1. Redirection from the merchant to the wallet:

From

merchant

To MPP

App

WAP

Web

App

✅ Supported.

✅ Supported.

Used when the MPP app is not available.

N/A

WAP

Forbidden.

The user can be only redirected from the merchant's WAP page to the wallet's WAP page. Otherwise, when redirecting the user back from an app to a WAP page, the user login info might be lost and result in authorization failure.

✅ Supported.

N/A

Web

N/A

N/A

✅ Supported.

  1. Redirection from the wallet back to the merchant:

From

MPP

To merchant

App

WAP

Web

App

✅ Supported.

N/A

The user can only be redirected from the merchant's WAP page to the wallet's WAP page, therefore, the redirection-back from the wallet app to the merchant WAP client will not occur.

N/A

WAP

✅ Supported.

Used when the MPP app is not available.

✅ Supported.

N/A

Web

N/A

N/A

✅ Supported.

1.2.2 Cashier Payment

  1. Redirection from the merchant to the wallet:

From

merchant

To MPP

App

WAP

Web

App

✅ Supported.

✅ Supported.

Used when the MPP app is not available.

N/A

WAP

✅ Supported.

Not recommended. The redirection-back from an app to a WAP page might lose the user login info and the payment result page might not be able to display.

✅ Supported.

N/A

Web

N/A

N/A

✅ Supported.

  1. Redirection from the wallet back to the merchant:

From

MPP

To merchant

App

WAP

Web

App

✅ Supported.

✅ Supported.

Not recommended. The redirection-back from an app to a WAP page might lose the user login info and the payment result page might not be able to display.

N/A

WAP

✅ Supported.

Used when the MPP app is not available.

✅ Supported.

N/A

Web

N/A

N/A

✅ Supported.

Note:

When the terminal type of the merchant is Web, and if the order code is merchant-rendered QR code, no redirection occurs.

2. Alipay+ redirection standards

2.1 Basic conceptions

2.1.1 Deep linking

In the context of Web development, deep linking is the use of a hyperlink that links to a specific, generally searchable or indexed, piece of web content on a website (e.g. http://example.com/my-awesome-content-page ), rather than the website's home page (e.g. http://example.com).

In the context of mobile development, deep linking refers to directly linking to in-app content using a hyperlink.

For Auto Debit, the redirection uses deep linking to redirect the user from the merchant side to the authorization page on the MPP side while retaining the context about the authorization.

For Cashier Payment, the redirection uses deep linking to redirect the user from the merchant side to the payment page on the MPP side, while retaining the context of the payment.

2.1.2 URL scheme, Universal Link, and App Link.

URL scheme, Universal Link, and App Link are ways to realize deep linking.

URL scheme is the part of a URI that specifies the app your device uses to open a URL. In the context of mobile development, URL schemes (more precisely, custom URL schemes) allow users to open your app from other apps or WAP pages. However, the URL scheme has some inherent limitations:

  • Errors occur if the app to be opened is not installed.
  • You cannot decide which app to open if multiple schemes with the same name are registered.

To solve these problems, iOS uses Universal Link. Android uses App Link. You can visit the pages in the hyperlinks to learn more about them.

2.1.3 Alipay+ URL types

Alipay+ uses schemeUrl, applinkUrl, and normalUrl.

  • schemeUrl represents URL schemes.
  • applinkUrl represents Universal Links and App Links.
  • normalUrl represents the ordinary Web/WAP URL that redirects users to a Web/WAP page.

See section 2.2.1 for details.

2.2 Handle the redirection

2.2.1 Redirection to the wallet

For Cashier Payment, the MPP enables Alipay+ to construct the payment URLs of the types as introduced in section 2.1.3. Alipay+ returns the URL as the paymentUrl field to the merchant.

For Auto Debit, Alipay+ uses the prepare interface to request that the MPP provides the authorization URL. The MPP must construct the URL accordingly. See the prepare interface for details.

For redirections with appLinkUrl, a fallback logic is strongly recommended to be applied by the MPP, to ensure that when the user redirects to the MPP's page by using an appLinkUrl, the MPP's wallet app (if installed) can be invoked.

To achieve that, add the following logic at the appLinkUrl page:

  1. Check if the webview is Safari of at least iOS 9 or higher. If it is, use the <a> tag for redirection.
  2. Check if the webview is Android Chrome. If it is, use the intent method for redirection. See intent for details about the method.
  3. In other scenarios, use the <iframe> tag for redirection.

The logic is illustrated by the figure below:


Sample code:

copy
const ua = window.navigator.userAgent
const isIOS = ua.match(/(iPhone|iPad|iPod)/)
const osVersion = (() => {
  const matched = ua.match(/OS ([\d_.]+) like Mac OS X/)
  if (matched) {
    return matched[1].split('_').join('.')
  }
  return ''
})()
const isSafari = isIOS && ua.match(/Safari/) && ua.match(/Version\/([\d.]+)/)

function verCompare (a, b) {
  const v1 = a.split('.')
  const v2 = b.split('.')

  for (let i = 0; i < v1.length || i < v2.length; i += 1) {
    const n1 = parseInt(v1[i], 10) || 0
    const n2 = parseInt(v2[i], 10) || 0

    if (n1 < n2) {
      return -1
    } else if (n1 > n2) {
      return 1
    }
  }
  return 0
}

function useAnchorLink (url) {
  const doc = window.document
  const a = doc.createElement('a')
  a.setAttribute('href', url)
  a.style.display = 'none'
  doc.body.appendChild(a)

  const e = doc.createEvent('HTMLEvents')
  e.initEvent('click', false, false)
  a.dispatchEvent(e)
}

const ios9SafariFix = isIOS && verCompare(osVersion, '9.0') >= 0 && isSafari

let iframe
function callInIframe (url) {
  const doc = window.document
  if (!iframe) {
    iframe = doc.createElement('iframe')
    iframe.id = `callapp_iframe_${Date.now()}`
    iframe.frameborder = '0'
    iframe.style.cssText = 'display:none;border:0;width:0;height:0;'
    doc.body.appendChild(iframe)
  }
  iframe.src = url
}
const isOriginalChrome = (() => {
  let isChrome = false
  let isWebview = false
  const isAndroid = ua.match(/Android[\s/]([\d.]+)/)
  if (ua.match(/(?:Chrome|CriOS)\/([\d.]+)/)) {
    isChrome = true
    if (ua.match(/Version\/[\d+.]+\s*Chrome/)) {
      isWebview = true
    }
  }
  return isAndroid && isChrome && !isWebview
})()
const gotoApp = (scheme, packageName) => {
  if (isOriginalChrome) {
    const protocol = scheme.substring(0, scheme.indexOf('://'))
    const hash = `#Intent;scheme=${protocol};package=${packageName};end`
    scheme = scheme.replace(/.*?:\/\//, 'intent://')
    scheme += hash
  }
  if (ios9SafariFix) {
    useAnchorLink(scheme)
  } else if (scheme.indexOf('intent:') === 0) {
    window.location.href = scheme
  } else {
    callInIframe(scheme)
  }
}


Note:

The scheme in the sample code is the wallet's schemeURL, the packageName is the wallet's app package name.

copy
// demo
gotoApp('yourscheme://goto', 'android.package.name')

2.2.2 Redirection back to the merchant

The fields for redirection back to the merchant are provided in the interface request, specifically:

  • authRedirectUrl for Auto Debit, in the prepare interface request.
  • paymentRedirectUrl for Cashier Payment, in the pay interface request.

The MPP must be able to handle all the URLs from the merchant, which includes 3 types according to the merchant side environment, specifically:

  • If the merchant side is the merchant's app, schemeUrl or applinkUrl is used.
  • If the merchant side is browsers or other apps, applinkUrl or normalUrl is used.

2.2.2.1 From iOS app

Try opening the merchant app with schemeUrl, universal link, and normalUrl. For the priority of these URLs, schemeUrl > applinkUrl > normalUrl.

Note:

To use the schemeUrl, the wallet app must add the merchant app in the allowlist. So the schemeUrl is suitable for scenarios where the merhcant information is available to the wallet.

To add the merchant app's scheme into the allowlist, add LSApplicationQueriesSchemes and set the scheme of the target app into the wallet app's Info.plist file, as described by the figure below:

image.png

Sample code:

copy
// Place following code for init webView to right place.
//    self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
//    [self.view addSubview:_webView];

NSString *applinkUrl = @"Your AppLinkUrl";
NSString *schemeUrl = @"Your SchemeUrl";
NSString *normalUrl = @"Your NormalUrl";

UIApplication *application = [UIApplication sharedApplication];

if ([application canOpenURL:[NSURL URLWithString:schemeUrl]]) {
    if (@available(iOS 10.0, *)) {
        [application openURL:[NSURL URLWithString:schemeUrl] options:@{} completionHandler:^(BOOL success) {
            if (success) {
                // do something.
            }
        }];
    } else {
        [application openURL:[NSURL URLWithString:schemeUrl]];
    }
} else if ([application canOpenURL:[NSURL URLWithString:applinkUrl]]) {
    // applink.
    if (@available(iOS 10.0, *)) {
        [application openURL:[NSURL URLWithString:applinkUrl] options:@{UIApplicationOpenURLOptionUniversalLinksOnly: @YES} completionHandler:^(BOOL success) {
            if (success) {
                // do something.
            } else {
                // Can't open universal link directly, it might not install related App.
                NSURL *url = [NSURL URLWithString:applinkUrl];
                NSURLRequest *request = [NSURLRequest requestWithURL:url];
                [self.webView loadRequest:request];
            }
        }];
    } else {
        NSURL *url = [NSURL URLWithString:applinkUrl];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [self.webView loadRequest:request];
    }

} else {
    // normal url.
    NSURL *url = [NSURL URLWithString:normalUrl];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [self.webView loadRequest:request];
}

2.2.2.2 From Android app

Use the logic below for the redirection-back from Android apps:

copy
Intent intent = new Intent(Intent.ACTION_VIEW, authUri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//If you know the merhcant app name, set the package name with it
intent.setPackage(packageName)
contex.startActivity(intent);

2.2.2.3 From WAP/Web

When redirects back from the wallet WAP/Web page:

  1. Check if the merchant page URL starts with https/http. If it is, redirect directly.
  2. Check if the webview is Safari of at least iOS 9 or higher. If it is, use the <a> tag for redirection.
  3. In other scenarios, use the <iframe> tag for redirection.

Sample code:

copy
const ua = window.navigator.userAgent
const isIOS = ua.match(/(iPhone|iPad|iPod)/)
const osVersion = (() => {
  const matched = ua.match(/OS ([\d_.]+) like Mac OS X/)
  if (matched) {
    return matched[1].split('_').join('.')
  }
  return ''
})()
const isSafari = isIOS && ua.match(/Safari/) && ua.match(/Version\/([\d.]+)/)

function verCompare (a, b) {
  const v1 = a.split('.')
  const v2 = b.split('.')

  for (let i = 0; i < v1.length || i < v2.length; i += 1) {
    const n1 = parseInt(v1[i], 10) || 0
    const n2 = parseInt(v2[i], 10) || 0

    if (n1 < n2) {
      return -1
    } else if (n1 > n2) {
      return 1
    }
  }
  return 0
}

function useAnchorLink (url) {
  const doc = window.document
  const a = doc.createElement('a')
  a.setAttribute('href', url)
  a.style.display = 'none'
  doc.body.appendChild(a)

  const e = doc.createEvent('HTMLEvents')
  e.initEvent('click', false, false)
  a.dispatchEvent(e)
}

const ios9SafariFix = isIOS && verCompare(osVersion, '9.0') >= 0 && isSafari

let iframe
function callInIframe (url) {
  const doc = window.document
  if (!iframe) {
    iframe = doc.createElement('iframe')
    iframe.id = `callapp_iframe_${Date.now()}`
    iframe.frameborder = '0'
    iframe.style.cssText = 'display:none;border:0;width:0;height:0;'
    doc.body.appendChild(iframe)
  }
  iframe.src = url
}
const gotoApp = url => {
  // appLink 直接跳转
  if (/^(http|https):\/\//.test(url)) {
    window.location.href = url
  }
  if (ios9SafariFix) {
    useAnchorLink(url)
  } else {
    callInIframe(url)
  }
}

Test code:

copy
// Applink
gotoApp('http://test.com')
// Scheme
gotoApp('test://xxx')