Alipay+ DocsAlipay+ Docs

Alipay+ Client SDK interfaces

This document introduces interfaces that are provided by Alipay+ client SDK.

1. Overview

This section describes the interfaces that are used in the interaction between Alipay+ SDK and Mobile Payment Provider APP.

1.1 API (Mobile Payment Provider APP -> Alipay+ SDK)

Interface name

Description

Required

init/initWithContext

The Mobile Payment Provider (MPP) app uses the init/initWithContext API to initialize the Alipay+ client SDK. The interface name for Android is init and for iOS is initWithContext.

M

openACCenter

Open the Alipay+ Center, which is a mini program.

M

getPaymentCode

The Mobile Payment Provider (MPP) app uses the getPaymentCode API to obtain the payment code from the Alipay+ client SDK. The payment code is returned by the paymentCodeListener object and needs to be rendered by the Mobile Payment Provider independently. Required for the User-presented Mode Payment product.

O

decode

The MPP app uses the decode API to send a decoding request to the Alipay+ client SDK.

Note: Required in the Merchant-presented Mode Payment and Cashier Payment scenarios.

O

clear

The Mobile Payment Provider (MPP) app must use the clear API to clear the login information that is cached by the SDK when the user logs out. Otherwise, some business errors might occur.

M

inquireQuote

The Mobile Payment Provider (MPP) app uses the inquireQuote API to query the exchange rate between a pair of currencies. However, the exchange rate returned by Alipay+ is only for reference.

O

signContract

The Mobile Payment Provider (MPP) app uses the signContract API to start the user authorization process for Auto Debit payments.

1.2 SPI (Alipay+ SDK -> Mobile Payment Provider APP)

Interface name

Description

Required

getAuthCode

The Alipay+ client SDK uses the getAuthCode SPI to obtain the authorization code from the Mobile Payment Provider (MPP).

M

showAuthPage

The Alipay+ client SDK uses the showAuthPage SPI to display the authorization page for the user to proceed with the authorization.

M

pay

The Alipay+ client SDK uses the pay SPI to open the payment confirmation page in the Mobile Payment Provider app.

M

getOpenUserInfo

Obtain the user open information.

M

scan

Use this interface to allow the user to scan a QR code or barcode presented by the merchant or selected from the album with Mobile Payment Provider app, then return the code string to Alipay+ SDK.

M

open

Use this interface to open a scheme, through which the user can view the wanted content. See Android app links and iOS Universal links for details.

M

2.API

2.1 init/initWithContext

The Mobile Payment Provider (MPP) app uses the init/initWithContext API to initialize the Alipay+ client SDK. The initialization takes little time and is suggested to be performed when the MPP app is launched. The initialization result is returned to the MPP app by the initCallback function for Android, and by the success/failure function for iOS.

Parameters

Item

Android type

iOS type

Description

Required

application

@NonNull Application

/

The Android application object

M

initConfig

@NonNull InitConfig

IAPConnectInitConfig

The configuration for initializing Alipay+ SDK

M

initCallback

@Nullable

InitCallback

/

The callback to be invoked by the initialization result.

Note: Required only for Android.

O

success/failure

/

@Nullable

Block

The callback to be invoked by the initialization result. Note: Required only for iOS.

O

Returns

N/A

Sample for Android

Sample of the SDK initialization:

copy
InitConfig initConfig = new InitConfig();
// for your productron version, please use 'PROD'
initConfig.envType = "DEV";

IAPConnect.init(this, initConfig, new InitCallback() {
            @Override
            public void onSuccess() {
                // to open Alipay+ service center
                // IAPConnect.openACCenter();
            }

            @Override
            public void onFailure(String errorCode, String errorMessage) {
                Toast.makeText(MyApplication.get(),
                    "Initialize error, errorCode: " + errorCode + ", errorMessage: " + errorMessage,
                    Toast.LENGTH_LONG).show();
            }
        });

Sample of the SPI configuration:

copy
/**
 * Meta info associated to subclasses of the BaseService class
 */
@ServiceMetaInfo(
        serviceName = "aplus.service.xxx", //xxx = oauth, member, payment
        category = ServiceCategory.ACL,
        type = ServiceType.OAUTH //OAUTH, MEMBER, PAYMENT
)


//Application class for registration

@Override
public void onCreate() {
    super.onCreate();
    //...
    
    //Register an implementation, this is done by the wallet devs
    //This is just to demonstrate that the implementation is initialised and loaded
    WalletServiceManager.getInstance().registerService(MemberServiceProvider.class);
    WalletServiceManager.getInstance().registerService(PaymentServiceProvider.class);
    WalletServiceManager.getInstance().registerService(OAuthServiceProvider.class);
    WalletServiceManager.getInstance().registerService(OpenCapabilityServiceProvider.class);
    WalletServiceManager.getInstance().registerService(CodeServiceProvider.class);
    WalletServiceManager.getInstance().registerService(DeeplinkServiceProvider.class);
}

Sample for iOS

Sample of the SDK initialization:

copy
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    let config = IAPConnectInitConfig()
    config.envType = "PROD"

    IAPConnectClient.sharedInstance()?.initWithContext(config, success: {
        
    }, failure: { (error, errorMessage) in
        
    })
return true

Sample of the SPI configuration:

copy
// WalletAPI initialization
// during application setup 

 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // register the api manager to wallet context
    IAPWalletContextManager.instance.serviceManager = IAPWalletAPIManager()
     
    // This meta info can be loaded in a invisible swift file to load the real data
    let IAPWalletPaymentServiceMetaInfo = IAPWalletBaseServiceProvider(
            type: IAPWalletServiceType(category: .acl, type: "payment"),
            name: NSStringFromClass(PaymentService.self))
        
    let IAPWalletOAuthServiceMetaInfo = IAPWalletBaseServiceProvider(
            type: IAPWalletServiceType(category: .acl, type: "oauth"),
            name: NSStringFromClass(OAuthService.self))
        
    let IAPWalletMemberServiceMetaInfo = IAPWalletBaseServiceProvider(
            type: IAPWalletServiceType(category: .acl, type: "account"),
            name: NSStringFromClass(MemberInfoService.self))
     
    let IAPWalletCodeServiceMetaInfo = IAPWalletBaseServiceProvider(
            type: IAPWalletServiceType(category: .foundation, type: "code"),
            name: NSStringFromClass(CodeService.self))
     
    let IAPWalletDeeplinkServiceMetaInfo = IAPWalletBaseServiceProvider(
            type: IAPWalletServiceType(category: .foundation, type: "deeplink"),
            name: NSStringFromClass(Deeplink.self))
        
    IAPWalletContextManager.instance.serviceManager?.registerServices(metaInfos: [
            IAPWalletPaymentServiceMetaInfo,
            IAPWalletOAuthServiceMetaInfo,
            IAPWalletMemberServiceMetaInfo,
            IAPWalletDeeplinkServiceMetaInfo,
            IAPWalletCodeServiceMetaInfo
        ])
        
    // do rest of the setup for app ...
    return true
}

2.2 openACCenter

Open the Alipay+ Center, which is a Mini Program.

Parameters

N/A

Returns

Android type

iOS type

Length

Description

Required

boolean

boolean

/

An indicator of whether the Alipay+ Center is opened successfully.

Yes

Sample for Android

copy

boolean result = IAPConnect.openACCenter();
if (result) {
	Log.d(TAG, "openACCenter succeeds");
} else {
	Log.e(TAG, "openACCenter fails");
}

Sample for iOS

copy
   UIViewController *centerVc = [IAPConnect openACCenter];
    if (centerVc) {
        NSLog(@"openACCenter succeeds");
        [self.navigationController pushViewController:centerVc animated:YES];
    }
    else
    {
        NSLog(@"openACCenter fails");
    }

2.3 getPaymentCode

The Mobile Payment Provider (MPP) app uses the getPaymentCode API to obtain the payment code from the Alipay+ client SDK. The payment code is returned by the paymentCodeListener object.

Parameters

Name

Android type

iOS type

Description

Required

region

@NonNull String

String

The region where the payment occurs. The value is a 2-digit code in ISO 3166-1 alpha-2, for example, CN. Contact your BD team for the list of supported regions.

M

paymentCodeListener

@NonNull IPaymentCodeListener

IAPConnectPaymentCodeListener

Listener for payment code. Called when the payment code is generated or updated.

M

Returns

N/A

Sample for Android

copy
String region = "CN";
IPaymentCodeListener paymentCodeListener = new IPaymentCodeListener() {
    @Override
    public void onPaymentCodeUpdated(String paymentCode) {
        // handle the paymentCode
        // please to render the QR code and bar code in this callback
    }

    @Override
    public void onPaymentCodeUpdateFailed(Result result) {
        //handle the error code and error message
        // Display error information to user or try to refresh the payment code again
        Log.i(TAG, result.resultCode);
    }
};
IAPConnect.getPaymentCode(region, paymentCodeListener);

Sample for iOS

copy
[IAPConnect getPaymentCode:@"CN" paymentCodeListener:self];
------------
- (void)onPaymentCodeUpdateFailed:(NSString *)resultCode resultMessage:(NSString *)resultMessage{
    //handle the error code and error message
    
}

- (void)onPaymentCodeUpdated:(NSString *)paymentCode{
    // handle the paymentCode
}

2.4 decode

The Mobile Payment Provider (MPP) app uses the decode API to send a decoding request to the Alipay+ client SDK. The MPP app may pass in an order code or entry code.

Parameters

Item

Android type

iOS type

Length

Description

Required

context

@NonNull Context

/

/

The context of the Android activity.

Note: Required only for Andriod.

M

decodeParameter

@NonNull DecodeParameter 

DecodeParameter

/

The parameters that are required in the decoding process. See DecodeParameter for details.

Note: The value of this parameter is returned by the Alipay+ server SDK in the code identification result.

M

decodeCallback

@NonNull IDecodeCallback

decodeCallback 

/

The callback to be invoked to return the decoding result.

M

Returns

N/A

Sample for Android

copy
// handled by SDK if isAcCode is true
if (isAcCode){
    decode(context, codeValue, acDecodeConfig, new IDecodeCallback(){
        @Override
        public void onResult(Result result){
            Log.i(TAG, result.resultCode);
        }
        
        @Override
        public void showLoading() {
            // some SDK operation is time consuming, here to show loading dialog
            // or the other UI to remind user
        }

        @Override
        public void dismissLoading() {
            // dismiss the dialog or tips UI
        }
    });
} 
// handled by Mobile Payment Partner if isAcCode is false
else {
    
}

Sample for iOS

copy
IAPConnectDecodeModel *model = [IAPConnectDecodeModel new];
    model.scene = fromScene;
    model.codeValue = codeValue;
    [[IAPConnectClient sharedInstance] decodeWithModel:model
                                        decodeCallback:^(IAPConnectDecodeResult *result) { 
                                          NSLog(@"resultCode:%@===resultMessage:%@",result.resultCode,result.resultMessage);
                                           }];


2.5 clear

The Mobile Payment Provider (MPP) app must use the clear API to clear the login information that is cached by the SDK when the user logs out. Otherwise, some business errors might occur.

Parameters

N/A

Returns

N/A

Sample for Android

copy
IAPConnect.clear();

Sample for iOS

copy
[IAPConnect clear];

2.6 inquireQuote

The Mobile Payment Provider (MPP) app uses the inquireQuote API to query the exchange rate between a pair of currencies. However, the exchange rate returned by Alipay+ is only for reference.

Parameters

Item

Android Type

iOS Type

Description

quoteCurrency

@NonNull QuoteCurrency

IAPConnectQuoteCurrency

The currency pair for which the exchange rate is queried.

callback

@NonNull InquireQuoteCallback

IAPConnectInquireQuoteCallback

The callback that is used to return the exchange rate.

Returns

N/A

Sample for Android

copy
QuoteCurrency quoteCurrency = new QuoteCurrency();
quoteCurrency.sellCurrency = "KRW";
quoteCurrency.buyCurrency = "JPY";
IAPConnect.inquireQuote(quoteCurrency, new InquireQuoteCallback() {
    	@Override
		public void onResult(@NonNull String resultCode, @Nullable ForeignExchangeQuote foreignExchangeQuote) {
            if (TextUtils.equals(resultCode, ResultCode.SUCCESS
                                && foreignExchangeRate != null) {
                // get the foreignExchangeQuote to display
            } else {
            	// handle the fail case
                Log.e(TAG, "fail to inquire quote, errorCode: " + resultCode);
            }
        }
});

Sample for iOS

copy
IAPConnectQuoteCurrency *quoteCurrency = [IAPConnectQuoteCurrency new];
quoteCurrency.sellCurrency = @"KRW";
quoteCurrency.buyCurrency = @"JPY";
    [IAPConnect inquireQuote:quoteCurrency quoteCallback:^(NSString * _Nonnull resultCode, IAPConnectForeignExchangeQuote * _Nonnull result) {
    if (([resultCode isEqualToString:kIAPACSUCCESS])) {
    	// get the foreignExchangeQuote to display
    } else {
    	// handle the fail case
    }
 }];

2.7 signContract

The Mobile Payment Provider (MPP) app uses the signContract API to start the user authorization process for Auto Debit payments.

Parameters

Name

Android type

iOS type

Description

request

@NonNull SignContractRequest

@NonNull SignContractRequest

The request model for the user authorization request.

callback

@NonNull AcCallback<AcBaseResult>

@NonNull AcCallback<AcBaseResult>

The callback to be invoked on user authorization completion.

Returns

N/A

Sample for Android

copy
Uri data = getIntent().getData();
String source = data.getQueryParameter("source");
if ("AlipayConnect".equals(source)) {
    SignContractRequest request = new SignContractRequest();
    request.needCallback = data.getBooleanQueryParameter("needCallback", false);
    String bizContent = data.getQueryParameter("bizContent");
    request.bizContent = bizContent;
    if (TextUtils.isEmpty(bizContent)) {
        request.authUrl = data.toString();
    }
    IAPConnect.signContract(request, result -> {
            if (result.success) {
                Log.i(TAG, "sign contract is success.");
                return;
            }
            if (TextUtils.equals(result.errorCode, ResultCode.USER_CANCEL)) {
                Log.i(TAG, "sign contract is cancelled by user.");
            } else {
                Log.i(TAG, "sign contract is failed, resultMessage: " + result.errorMessage);
            }
        });
} else {
    // it is not the sign contract requirement from Alipay+
}

Sample for iOS

copy
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        
        var data : Dictionary<String, String> = [:]
        var needCallback :Bool?
        var bizContent :String?
        var source :String?
        var authUrl :String?
        
        let urlcomp = URLComponents(url: url, resolvingAgainstBaseURL: false)
        if let items = urlcomp?.queryItems {
            for item in items {
                if item.name == "code" {
                    data["code"] = item.value ?? ""
                }
                
                if item.name == "merchantType" {
                    data["merchantType"] = item.value ?? ""
                }
                if item.name == "needCallback" {
                    needCallback = (item.value! as NSString).boolValue
                }
                if item.name == "bizContent" {
                    bizContent = item.value!
                }
                if item.name == "source" {
                    source = item.value!
                }
            }
        }
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "alipayconnect"), object: data)
        
        if (source == "AlipayConnect") {
            let signContractRequest = IAPGOLSignContractRequest()
            if bizContent?.count ?? 0 > 0 {
                signContractRequest.bizContent = bizContent
            } else {
                signContractRequest.authUrl = url.absoluteString

            }
                  signContractRequest.needCallback = needCallback ?? true
                  IAPGOLSignContract.signContract(signContractRequest) { (result) in
                    if result?.success ?? false {
                        SVProgressHUD.showSuccess(withStatus: "success")
                    } else {
                        SVProgressHUD.showError(withStatus: result?.errorCode)
                    }
            }
        }
        
        return true
    }

3. SPI

An optional context model exists across all SPI method signature, which provides context information for tracing request, retrieving relevant merchant and acquirer information, and so on.

Context

Field

Description

source

MANDATORY String

Valid values are:

  • MiniProgram
  • AlipayConnect
  • InteractivePlatform

miniProgramInfo

OPTIONAL MiniprogramMetaData/IAPWalletMiniprogramMetaData

The mini program meta data information that is generated from Alipay+ mini program platform. This field is required for the payment scenarios in the mini program. 

extendInfo

OPTIONAL Map<String, String>/Dictionary

Extended information. The field is reserved for future use.

MiniprogramMetaData (Android)/IAPWalletMiniprogramMetaData (iOS)

Field

Description

appId

OPTIONAL String

The unique ID that is assigned by Alipay+ mini program platform to identify a mini program

merchantId

OPTIONAL String

The unique ID that is assigned by Alipay+ mini program platform to identify a merchant

deployVersion

OPTIONAL String

Deployment version

Example: 6.1.1712141809.54

name

OPTIONAL String

Mini program name

logo

OPTIONAL String

Logo URL

Example: http://www.avatar.com/logo.png

desc

OPTIONAL String

Description of the mini program

developerVersion

OPTIONAL String

Internal developement version

Example: 6.1.0

appType

OPTIONAL Int

App type. Valid values are:

  • 1: HTML offline package
  • 2: Mini program

acquirerId

OPTIONAL String

The unique ID that is assigned by Alipay+ to identify an acquirer 

languages

OPTIONAL Map<String, Map<String, String>>/NSDictionary<NSString*, NSDictionary<NSString*, NSString*>>

Mini program information in different languages, which contains name, description, and logo.

Example:

{

    "en_US": {

       "name": "miniprogram",

       "description": "miniprogram desc",

       "logo": "usa.jpg"

     },

     "zh_CN": {

       "name": "小程序测试",

       "description": "小程序测试desc",

       "logo": "china.jpg"

     }

}

clientParams

OPTIONAL Map<String, String>/Dictionary

Currently the sub field of appSourceTag is contained, which describes the source category of the mini program. Valid values of appSourceTag are:

  • 1: Second party, which means Mobile Payment Provider's mini program.
  • 2: Third party, which means merchant's mini program that is onboarding into the Mobile Payment Provider app.

Example:

"clientParams": {

    "appSourceTag": 1

 },

publishStatus

OPTIONAL String

Status of the mini program. Valid values are:

  • PUBLISHED
  • SUSPENDED
  • REMOVED

authClientID

OPTIONAL String

The unique ID that is assigned by Alipay+ to identify an AuthClient

acParams

OPTIONAL Map<String, String>/Dictionary

Extended information. The field is reserved for future use.

3.1 getAuthCode

The Alipay+ client SDK uses the getAuthCode SPI to obtain the authorization code from the Mobile Payment Provider (MPP).

Implement the interface according to the following method signature:

Signature

getAuthCode(String clientId,

Set<String> scopes

OAuthCodeFlowType type

Map<String,String> extendedInfo,

APIContext context,

Callback<OAuthResult> callback);

getAuthCode(String url,

OAuthCodeFlowType type,

Map<String,String> extendedInfo,

APIContext context, 

Callback<OAuthResult> callback)

Parameters

Name

Android & iOS type

Description

authResult

OAuthResult

The reuslt of the authorization, including the authorization code, authorization statement, and the scopes that are granted. See authorization scopes for all the possible scopes.

OAuthCodeFlowType

AuthFlowType

The type of OAuth flow.

In Android system, valid values are:

  • STANDARD
  • ALIPAY_CONNECT
  • LOCAL_MINI_PROGRAM

In IOS system, valid values are:

  • Standard
  • AlipayConnect
  • LocalMiniProgram
Returns

N/A

Sample for Android

copy
/**
 * OAuth, implement the OAuthService class
 * Call the getAuthorizedCodes to check which grant is provided to a clientId, before
 * making requests to the associated services of <? extends BaseService>
 */

import com.alipay.ap.android.wallet.acl.base.Callback;
import com.alipay.ap.android.wallet.acl.oauth.OAuthResult;
import com.alipay.ap.android.wallet.acl.oauth.OAuthService;

import java.util.Set;

/**
 * @since 0.1.1
 */
public class OAuthServiceProvider implements OAuthService {
    
    /**
     * Called to trigger the wallet to start the OAuth process, which will return the Authorisation
     * Code
     *
     * @param clientId clientId
     * @param scopes scopes of the client's request, 
     *          See authorization scopes
     * @param oauthFlowType The type of OAuth flow [Standard, Alipay_connect, local_mini_program]
     * @param extendedInfo Support specific scenario for non-unified scenarios,
     *                     etc #REUSE#A+#IDae3be7b7-e21e-45d9-9800-d0821a2c6e93# has need for clientAuthId
     * @param callback The callback on the result of the user's OAuth approval
     * @since 0.3.0
     */
    void getAuthCode(String clientId, Set<String> scopes, OAuthCodeFlowType oauthFlowType,
                     Map<String, String> extendedInfo, APIContext apContext, Callback<OAuthResult> callback) {
        
        OAuthResult authResult = new OAuthResult();

        //Implement the OAuth flow and retrieve the authToken
        //...

        callback.result(authResult);
    }
    
    /**
     * This method is invoked when some service starts OAuth flow by passing in a agreement url
     * which needs to be rendered and signed by the user
     *
     * @param url The agreement url to open and sign
     * @param oauthFlowType The type of OAuth flow [Standard, Alipay_connect, local_mini_program]
     * @param extendedInfo Support specific scenario for non-unified scenarios,
     *                     etc #REUSE#A+#IDae3be7b7-e21e-45d9-9800-d0821a2c6e93# has need for clientAuthId
     * @param callback The callback on the result of the user's OAuth approval
     * @since 0.3.0
     */
    void getAuthCode(String url, OAuthCodeFlowType oauthFlowType, Map<String, String> extendedInfo
                     , APIContext apContext, Callback<OAuthResult> callback) {
        OAuthResult oAuthResult = new OAuthResult();
        
        //Decodes the URL, and perform OAuth permission grant
        
        callback.result(oAuthResult);
    }
}
    /*
     Possible Auth Scopes: https://globaltech.alipay.com/docs/GPP/wallet-api/wallet-api
     */

Sample for iOS

copy
final class OAuthService: IAPWalletOAuthServiceSignature {
    
    /*
     Possible Auth Scopes: https://globaltech.alipay.com/docs/GPP/wallet-api/wallet-api
    */
    
    /// This method is invoked when some service starts OAuth process from the wallet
    /// - Parameters:
    ///   - clientId: the cliend Id of the service registered from the
    ///   - scopes: the scopes the client plans to apply
    ///   - type: the type of the authCode grant flow, default as standard the API caller can also specify it as a .alipayConnect specific flow.
    ///   - extendedInfo: Extended info parameters for non standard authflow
    ///   - callback: callback which will be used to inform the service caller about the service result
    override func getAuthCode(clientId: String, 
                              scopes: Set<String>, 
                              type: IAPWalletOAuthCodeFlowType, 
                              extendedInfo: [String: String],
                              in context: IAPWalletAPIContext?,
                              callback: @escaping (IAPWalletOAuthResult) -> Void) {
        // 1. execute auth process
        // type: .standard -> only the clientId is needed to get the authCode.
        // type: .localMiniProgram / .alipayConnect -> need to pass both the clientId as well as the authClientId
        
        // 2. based on auth result, cache current authorized scopes under userId and clientId
        // the scopes are granted via step 1. from the PSP OAuth server
        updateScopes(clientId: "clientId", incrementedScopes: ["BASE_USER_INFO"], decrementedScopes: ["USER_INFO"])
        
        // 3. after the authcode has been retrieved (in an asynchronous loop), trigger the callback
        // ----> async remote call: {
        callback(IAPWalletOAuthResult(authCode: "${server-issued-authCode}",
                                      authState: "${server-issued-authState}",
                                      authErrorScopes: ["USER_INFO": "${failed reasons}"],
                                      authSuccessScopes: ["BASE_USER_INFO"]))
        // ----> async remote call: }

    }
    
    /// This method is invoked when some service starts OAuth flow by passing in a agreement url which needs to be
    /// rendered and signed by the user
    /// - Parameters:
    ///   - url: The aggreement url to open and sign
    ///   - type: the type of the authCode grant flow, default as standard the API caller can also specify it as a .alipayConnect specific flow.
    ///   - extendedInfo: Extended info parameters for non strandard authflow
    ///   - callback: callback which will be user to inform the service caller about the service result
    override func getAuthCode(url: String, 
                              type: IAPWalletOAuthCodeFlowType, 
                              extendedInfo: [String: String], 
                              in context: IAPWalletAPIContext?,
                              callback: @escaping (IAPWalletOAuthResult) -> Void) {
        // 1. open the webview via url, check whether the following params are presented in the url
        // type: .standard -> only the clientId is needed to get the authCode.
        // type: .localMiniProgram / .alipayConnect -> need to pass both the clientId as well as the authClientId
        
        // 2. detect the universal link/redirect link triggered by the webpage
        
        // 3. based on auth result, cache current authorized scopes under userId and clientId
        // the scopes are retrieved from step 2.
        updateScopes(clientId: "clientId", incrementedScopes: ["BASE_USER_INFO"], decrementedScopes: ["USER_INFO"])
        
        // 4. after the authcode has been retrieved (in an asynchronous loop), trigger the callback
        // ----> async remote call: {
        callback(IAPWalletOAuthResult(authCode: "${server-issued-authCode}",
                                      authState: "${server-issued-authState}",
                                      authErrorScopes: ["USER_INFO": "${failed reasons}"],
                                      authSuccessScopes: ["BASE_USER_INFO"]))
        // ----> async remote call: }
    }
    
    // Provide updateScopes for store authScope info at the point when OAuth success, 
    // and getScopes for retrieving previously granted authScopes of the specific user.
    
    func updateScopes(clientId: String, incrementedScopes: [String] = [], decrementedScopes: [String] = []) {
        let userId = "${current-user-id-in-app}"
        let key = String(format: "IAPWalletAuthScope-%@-%@", userId, clientId)
        let raw = UserDefaults.standard.array(forKey: key) as? [String] ?? []
        let currentScopes = Set(raw)
        UserDefaults.standard.set(currentScopes
            .union(incrementedScopes)
            .subtracting(decrementedScopes)
            .sorted(), forKey: key)
    }
    
    func getScopes(clientId: String) -> [String] {
        let userId = "${current-user-id-in-app}"
        let key = String(format: "IAPWalletAuthScope-%@-%@", userId, clientId)
        return UserDefaults.standard.array(forKey: key) as? [String] ?? []
    }
}
 

3.2 showAuthPage

The Alipay+ client SDK uses the showAuthPage SPI to display the authorization page for the user to proceed with the authorization.

Implement the SPI according to the following method signature:

Signature

showAuthPage(clientId: String, name: String,

                          logo: String, scopes: Set<String>, extendedInfo: [String : String]? = nil,

                          in context: IAPWalletAPIContext?,

                          callback: @escaping (IAPWalletAuthPageConfirmResult) -> Void)

public void showAuthPage(String clientId,

String name,

String logo,

Set<String> scopes,

Map<String, String> extendedInfo,

APIContext apContext,

Callback<OAuthPageConfirmResult> callback)

Parameters

Name

Android & iOS type

Description

pageConfirmResult

AuthPageConfirmResult

The user authorization result for the auto-debit payment.

Returns

N/A

Sample for Android

copy
/**
 * OAuth, implement the OAuthService class
 * Call the getAuthorizedCodes to check which grant is provided to a clientId, before
 * making requests to the associated services of <? extends BaseService>
 */

import com.alipay.ap.android.wallet.acl.base.Callback;
import com.alipay.ap.android.wallet.acl.oauth.OAuthResult;
import com.alipay.ap.android.wallet.acl.oauth.OAuthService;

import java.util.Set;

/**
 * @since 0.1.1
 */
public class OAuthServiceProvider implements OAuthService {
    

    /**
     * This method is invoked when some service starts OAuth flow by passing in a agreement url
     * which needs to be rendered and signed by the user
     *
     * @param clientId the clientId of the app which triggers the authpage
     * @param name the name of the app to be displayed in the auth page
     * @param logo the app's logo, in form of a valid http/https resource 'url' to a logo image
     * @param scopes: the auth scopes the app is applying for, refer to this reference here: https://yuque.antfin-inc.com/imobile-end/tva9vq/tvq2t9
     * @param extendedInfo Support specific scenario for non-unified scenarios,
     *                     etc #REUSE#A+#IDae3be7b7-e21e-45d9-9800-d0821a2c6e93# has need for clientAuthId
     * @param callback The callback on the result of the user's OAuth approval
     * @since 0.3.1
     */
    public void showAuthPage(String clientId, String name, String logo, Set<String> scopes,
                      Map<String, String> extendedInfo, APIContext apContext, Callback<OAuthPageConfirmResult> callback) {
        
        //Generate the OAuth permission page as required.
        //UI design of the page is specific to PSP implementation.
        
        OAuthPageConfirmResult confirmResult = null;
        String referenceAgreementId = ${OAuth service returns a reference approval id}; //optional, can be null
        
        if(${user approved}) {//If success
            confirmResult = new OAuthPageConfirmResult(referenceAgreementId);
        } else { //If fail/error
            confirmResult = new OAuthPageConfirmResult(null);
            //Error handling reference
            //https://yuque.antfin-inc.com/global-integration-technology/hhc5bf/ez52pl#iHVrc
        }
        
        callback.result(confirmResult);
    }
}

 /*
   Possible Auth Scopes: https://globaltech.alipay.com/docs/GPP/wallet-api/wallet-api
 */

Sample for iOS

copy
import IAPWalletContext

final class OAuthService: IAPWalletOAuthServiceSignature {
    
    /// **Note: ** the following SPIs are not used by Ant SDKs
    /// consultAuthPage(authId: String, extendedInfo: [String : String] = [:], callback: @escaping (IAPWalletOAuthConsultResult) -> Void)
    /// consultAuthPage(clientId: String, scopes: Set<String>, extendedInfo: [String : String] = [:], callback: @escaping (IAPWalletOAuthConsultResult) -> Void)
    
    /// This API is triggered by some of the Ant SDK use cases, like local miniprogram to ask App for displaying an authPage.
    /// - Parameter clientId: the clientId of the app which triggers the authpage
    /// - Parameter name: the name of the app to be displayed in the auth page
    /// - Parameter logo: the app's logo, in form of `url`
    /// - Parameter scopes: the auth scopes the app is applying for, refer to this [link](https://yuque.antfin-inc.com/docs/share/8bfa2603-7d4e-4ef7-b4f3-11565bf763c1?#) for the complete list of scopes.
    /// - Parameter extendedInfo: the extra optional information which the app might require to display on the authPage, refer to this [link]() for complete list of optional params
    /// - Parameter callback: the async callback to inform whether the user abort or confirm the authPage. If error object is not nil in the service result, it means the user reject/aborts the authPage. 
    override func showAuthPage(clientId: String,
                               name: String,
                               logo: String,
                               scopes: Set<String>,
                               extendedInfo: [String : String]? = nil,
                               in context: IAPWalletAPIContext?,
                               callback: @escaping (IAPWalletAuthPageConfirmResult) -> Void) {
        // override the method to provide a authpage confirmation popover
        var scopeInfo = ""
        for scope in scopes {
            if (scope == OAuthService.SCOPE_BASE_USER_INFO) {
                scopeInfo += "- Access basic user information\n"
            } else if (scope == OAuthService.SCOPE_AGREEMENT_PAY) {
                scopeInfo += "- Conduct aggreement pay automatically\n"
            } else if (scope == OAuthService.SCOPE_USER_NAME) {
                scopeInfo += "- Access to user's real name\n"
            } else if (scope == OAuthService.SCOPE_USER_LOGIN_ID) {
                scopeInfo += "- Retrieve user login id in the app.\n"
            } // ... iterate through all possible scopes
        }
        
        let authPage = UIAlertController(title: "Authorisation Confirmation",
                                         message: "\(name) wants to access for the following information: \n\(scopeInfo)" ,
                                         preferredStyle: .alert)
        
        authPage.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default action"),
                                         style: .default,
                                         handler: { _ in
                                            // 1. synchronize with wallet server regarding aggreement check
                                            // ----> async remote call: {
                                                ----- case 1 -----
                                                // 2.1 Option 1: when confirmation is purely checked offline
                                                // then inform the SDK that agreement has ben confirmed
                                                let result = IAPWalletAuthPageConfirmResult()
                                                callback(result)
                                                
                                                ----- case 2 ----- 
                                                // 2.2 Option 2: when confirmation is passed to server for ack
                                                // then inform the SDK with the agreementId from server
                                                let result = IAPWalletAuthPageConfirmResult("${agreementReferenceId}")
                                                callback(result)
                                            // ----> }
        }))
        
        authPage.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: "User reject"),
                                         style: .cancel,
                                         handler: { _ in
                                            
                                            // 1. if error is presented, the SDK will assume user abort the operation.
                                            let result = IAPWalletAuthPageConfirmResult()
                                            result.error = NSError(domain: "${psp-wallet-domain}",
                                                                   code: IAPWalletBaseServiceResult.ERROR_CODE_USER_CANCEL, // or any ${psp-wallet-domain-code}
                                                                   userInfo: [NSLocalizedDescriptionKey: "user canceled"])
                                            callback(result)
                                            
        }))
    }
    

    /*
     Possible Auth Scopes: https://globaltech.alipay.com/docs/GPP/wallet-api/wallet-api
     */
}

3.3 pay

Description

The Alipay+ client SDK uses the pay SPI to open the payment confirmation page in the Mobile Payment Provider app.

Implement the SPI according to the following method signature:

iOS

pay(with request: IAPWalletPaymentRequest,

                   in context: IAPWalletAPIContext?,

                   callback: (IAPWalletPaymentResult) -> Void)

Android

void pay (PaymentRequest paymentRequest,

APIContext apiContext,

Callback<PaymentResult> callback)

Parameters

Name

Android & iOS type

Length

Description

paymentRequest

PaymentRequest

/

The object that initiates a payment.

paymentResult

PaymentResult

/

The callback that is used to return the payment result.

Returns

N/A

Sample for Android

copy
public class PaymentServiceProvider implements PaymentService {
    
    /**
     * The method that is call for any payment request to bring up e.g. the cashier pay to fulfill
     * payment to the payment requestee
     * @param request The request object
     * @param callback The callback on the payment result, success/failures
     */
    @Override
    public void pay(PaymentRequest request, APIContext apContext, Callback<PaymentResult> callback) {
        PaymentResult paymentResult = new PaymentResult();
        
        //Implement logic to open the cashier page
        // e.g. With Griver, Griver.openUrl(...)
        //...
        
        //To handle callbacks - Griver-H5 typed
        // 1. Consider having a custom JSAPI that is able to passing payment status
        // to the native level, to callback to the Callback<PaymentResult> object
        // 2. Have the JSAPI implement observer pattern, to intercept requests specific
        // to payment result page closure, and register the Callback<PaymentResult> object
        // as an observer to it.
        
        //To handle callbacks - Native/Java typed
        // 1. Consider designing an observer pattern for your native cashier to observe for
        // Cashier result page closure e.g. activity.finish()
        // 2. And register the register the Callback<PaymentResult> object as observer
        
        callback.result(paymentResult);
    }
}

/*
 * Referring to payment codes from:
 * - Miniprogram : https://opendocs.alipay.com/mini/api/openapi-pay
 * provide a superset of the payment codes.
 */
//Payment: ACL standardized Result Codes
public static final String CODE_PENDING = "8000";
public static final String CODE_FAILURE = "4000";
public static final String CODE_SUCCESS = "9000";
public static final String CODE_USER_CANCEL = "6001";

Sample for iOS

copy
final class PaymentService: IAPWalletPaymentServiceSignature {
    
    /*
      Referring to payment codes from:
        - #REUSE#A+#IDae3be7b7-e21e-45d9-9800-d0821a2c6e93# 2.0 : https://yuque.antfin-inc.com/docs/share/d2577213-2311-45b3-871a-670cceb64fcf?#TMqJ0
      provide a superset of the payment codes. This codes can be consumed by Miniprogram & #REUSE#A+#IDae3be7b7-e21e-45d9-9800-d0821a2c6e93# directly
     */
    public static let CODE_PENDING = "8000" // PAY_PENDING
    public static let CODE_FAILURE = "4000" // PAY_FAILURE
    public static let CODE_SUCCESS = "9000" // PAY_SUCCESS
    public static let CODE_USER_CANCEL = "6001" // USER_CANCEL
    
    override func pay(with request: IAPWalletPaymentRequest, 
                      in context: IAPWalletAPIContext?,
                      callback: (IAPWalletPaymentResult) -> Void) -> Void {
        // Step 1. Check the payment type request parameters, which could be:
        //  - orderId: orderId
        //  - paymentId: paymentId
        //  - cashierUrl: cashier url to be rendered by web cashier
        //  - orderString: a string which contains complete order information. (in mini program case, this payment type is not currently used)
        
        // Step 2. Render cashier and conduct payment process
        
        // Step 3. Invoke callback to inform mini program about the payment result
        // result code please refer to the code const listed above the pay() method.
        // result message there is not strict limitation.
        // ----> async remote call: {
        callback(IAPWalletPaymentResult(resultCode: CODE_SUCCESS, resultMessage: "payment success"))
        // ----> async remote call: }
    }
}

@end

3.4 getOpenUserInfo

Description

Use this interface to obtain the open user information. When Mobile Payment Provider app obtains the information from Mobile Payment Provider server, the open user information is passed to Alipay+ SDK by userInfoCallback asynchronously.

Implement the SPI according to the following method signature:

Signature

getMemberInfo(strategy: IAPWalletMemberInfoFetchStrategy,

                      scope: IAPWalletMemberInfoScope?,

                      in context: IAPWalletAPIContext?,

                      callback: @escaping (IAPWalletMemberInfoFetchResult) -> Void)

Parameters

N/A

Returns

Name

iOS & Android type

Length

Description

memberInfo

MemberInfo

/

The object that contains the user information

memberInfoResult

MemberInfoResult

/

The callback for getMemberInfo(), which includes the payload of memberInfo

fetchStrategy

MemberInfoFetchStrategy

/

The strategy to fetch the user information suggested by Alipay+ Client SDK

memberInfoScope

MemberInfoScope

/

The user information scope

Sample for Android

copy
public interface MemberService extends BaseService {

    /**
     * Gets the current member info for this user
     *
     * @param fetchStrategy the strategy used to fetch user info, can be a
     * <br>userId only - {@link com.alipay.iap.android.wallet.acl.member.MemberService.MemberInfoFetchStrategy#LOCAL_USER_ID_ONLY},
     * <br>locally cached full memberInfo - {@link com.alipay.iap.android.wallet.acl.member.MemberService.MemberInfoFetchStrategy#LOCAL_CACHED}, or
     * <br>force to fetch from remote - {@link com.alipay.iap.android.wallet.acl.member.MemberService.MemberInfoFetchStrategy#REMOTE_FETCH}
     * <br><br>Depending on user info sensitivity, you may have to consider also to validate if the
     * related OAuth scope for MemberInfo has been granted via {@link com.alipay.iap.android.wallet.acl.oauth.OAuthService#getAuthorizedScopes(String, Map, APIContext, Callback)},
     * if not, you may have to request {@link com.alipay.iap.android.wallet.acl.oauth.OAuthService#getAuthCode(String, OAuthCodeFlowType, Map, APIContext, Callback)} first
     * @param memberInfoScope the scope of the member information should cover
     * @param apiContext The api context associated with this request {@link com.alipay.iap.android.wallet.acl.base.APIContext} - Optional, set as null if not used
     * @param memberInfoCallback callback returning the MemberInfoResult
     *
     * @version 0.4.1 added APIContext parameter in method signature
     */
    void getMemberInfo(MemberInfoFetchStrategy fetchStrategy, MemberInfoScope memberInfoScope, APIContext apiContext, Callback<MemberInfoResult> memberInfoCallback);

    /**
     * Defines the type of strategy to return the MemberInfo details
     */
    enum MemberInfoFetchStrategy {

        /**
         * Strategy to return only the userId
         * The MemberService.getMemberInfo(), should immediately invoke the callback
         * to simulate a synchronous response
         */
        LOCAL_USER_ID_ONLY,

        /**
         * Strategy to returns the locally cached MemberInfo
         * The MemberService.getMemberInfo(), should immediately invoke the callback
         * to simulate a synchronous response
         */
        LOCAL_CACHED,

        /**
         * Strategy to return the remote up to date MemberInfo
         * The MemberService.getMemberInfo(), this response can be asynchronously responded
         * based on network/remote response.
         */
        REMOTE_FETCH
    }

}

Sample for iOS

copy
final class MemberInfoService: IAPWalletMemberServiceSignature {
    
    override func getMemberInfo(strategy: IAPWalletMemberInfoFetchStrategy,
                                scope: IAPWalletMemberInfoScope?,
                                in context: IAPWalletAPIContext?,
                                callback: @escaping (IAPWalletMemberInfoFetchResult) -> Void) {
        
        if (strategy == .localCached) {
            
            // return the full amount of userInformation from local cache
            let memberInfo = IAPWalletMemberInfo(
                userId: "${user-id}",
                sessionId: "${session-id}",
                loginId: "${login-id}",
                gender: "m/f",
                avatar: "${avatar-url}",
                userName: "${user-name}")
            memberInfo.extendedInfo = [
                "nickName": "nick name of user",
                "countryCode": "65/86",
                "province": "xxx",
                "province": "xxx",
                                      ]
            // synchronized call
            callback(IAPWalletMemberInfoFetchResult(memberInfo: memberInfo))
            
        } else if (strategy == .localUserIdOnly) {
            
            // return user id only, this strategy is used when some of the SDK's internal logic wants
            // to get a user specified path for data storage
            let memberInfo = IAPWalletMemberInfo(userId: "${user-id}")
            
            // synchronized call
            callback(IAPWalletMemberInfoFetchResult(memberInfo: memberInfo))
            
        }
    }
}

3.5 scan

Description

Use this interface to allow the user to scan a QR code or barcode that is presented by the merchant or selected from the album with the Mobile Payment Provider app, then return the code string to Alipay+ SDK.

Implement the SPI according to the following method signature:

Signature

scan(with option: IAPWalletScannerOption,

                 in context: IAPWalletAPIContext?,

                 callback: @escaping (IAPWalletScannerResult) -> Void)

Paramters

Name

Android & IOS type

Length

Description

scannerOption

ScannerOption

/

The options that Mobile Payment Provider must provide for the user to scan the QR code/barcode. The options are:

  • Scanning the QR code/barcode presented by the merchant
  • Scanning the QR code/barcode in the picture that is selected from the album

scanResult

ScannerResult

/

The result collected from the scanned code

Returns

N/A

Sample for Android

copy
public class CodeServiceProvider implements CodeService {
    @Override
    public void scan(ScannerOption scannerOption, APIContext apContext, Callback<ScannerResult> scannerResultCallback) {
        ScannerResult scannerResult = new ScannerResult("xxxxcodexxxx");
        scannerResult.setExtendedInfo(null);
        scannerResult.getExtendedInfo();
        scannerResultCallback.result(scannerResult);
    }
}

Sample for iOS

copy
final class CodeService: IAPWalletCodeServiceSignature {
    
    // Mark: this API is currently used by Miniprogram combined with #REUSE#A+#IDae3be7b7-e21e-45d9-9800-d0821a2c6e93# 2.0 case.
    override func scan(with option: IAPWalletScannerOption, 
                       in context: IAPWalletAPIContext?,
                       callback: @escaping (IAPWalletScannerResult) -> Void) {
        // open up your qrcode scanner in your app based on the following option:
        // option.type = .qrCode -> qrcode scanner
        // option.type = .barCode -> barcode scanner
        
        // invoke the callback to passback the result, this can be invoked asynchronously.
        // ----> async remote call: {
        callback(IAPWalletScannerResult(code: "${code extracted}"))
        // ----> async remote call: }
    }
}

3.6 open

3.6.1 open scheme

Description

Use this interface to open an in-app page of the destination scene or navigate to the destination scene across apps. See Android app links and iOS Universal links for details.

Implement the SPI according to the following method signature:

  • Android Signature

bool open(Uri scheme, APIContext apiContext)

  • iOS Signature
  • Swift Signatures

open(scheme: URL, in context: IAPWalletAPI.IAPWalletAPIContext? = nil) -> Bool

  • Objective-C signature

BOOL openScheme:(NSString *)url context:(APIContext *)apiContext

Parameters

Item

Android type

iOS type

Length

Description

scheme

Uri

NSString

Immutable URI reference. A URI reference includes a URI and a fragment. The component of the URI is followed by a number sign (#). Build and parse URI references which conform to RFC 2396.

Returns

Android type

iOS type

Length

Description

Required

boolean

boolean

/

An indicator of whether the scheme is opened successfully.

M

Sample for Android

copy
public class DeeplinkServiceProvider implements DeeplinkService {
    @Override
    public boolean open(Uri deepLink) {
        
        //Your operation to open this URI
        if(isAuthorised(deepLink)) {
            //Handles the deeplink either natively, or as webview
        } else {
            //Returns false if deeplink is not handled
            return false;
        }
        
        return true;
    }
}

Sample for iOS

copy
final class DeeplinkService: IAPWalletDeeplinkService {
    
    // Mark: this API is currently used by Miniprogram combined with #REUSE#A+#IDae3be7b7-e21e-45d9-9800-d0821a2c6e93# 2.0 case.
    override func open(scheme: URL,
                       in context: IAPWalletAPIContext?) -> Bool {
        // the wallet app can choose to process the scheme as deeplink,
        // or ordinary url open in webview, the follow is returned synchronously
        if UIApplication.shared.canOpenURL(scheme) {
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(scheme, options: [:], completionHandler: nil)
                return true
            } else {
                UIApplication.shared.openURL(scheme)
                return true
            }
        } else {
            return false
        }
    }
}

3.6.2 open sceneCode

Description

Use this interface to open an in-app page of the destination scene or navigate to the destination scene across apps. See Android app links and iOS Universal links for details.

Implement the SPIs according to the following method signature:

  • Android Signature

open(@NonNull String sceneCode,

                   @NonNull Map<String, String> params,

                   @Nullable APIContext apiContext,

                   @NonNull Callback<BaseResult> openBizSceneCallback)

  • iOS Signatures
  • Swift Signature

open(bizSceneCode: String,

              with params: [String:String],

              in context: IAPWalletAPIContext? = nil,

              callback: @escaping (IAPWalletBaseServiceResult) -> Void)

  • Objective-C Signature

openBizSceneCode:(NSString *)sceneCode

                      params:(NSDictionary<NSString *, NSString *> *)params

                      context:(IAPWalletAPIContext *)context

   callback:(void(^)(IAPWalletBaseServiceResult *))callback;

Parameters

Item

Android type

iOS type

Length

Description

sceneCode

String

NSString

/

Scene code that presents a scene, such as SCAN and QR_CODE.

params

Map<String, String>

NSDictionary<NSString *, NSString *>

/

The parameters that the my.navigateToBizScene JSAPI provides, used for data transmission of this JSAPI. 

context

APIContext

IAPWalletAPIContext

/

The JSAPI context of mini programs.

Returns

Android type

iOS type

Length

Description

Required

void

void

/

An indicator of whether the scene code is opened successfully.

M

Sample for Android

copy
public class DeeplinkServiceProvider implements DeeplinkService {

    @Override
    public void open(@NonNull String sceneCode,
                     @NonNull Map<String, String> params,
                     @Nullable APIContext apiContext,
                     @NonNull Callback<BaseResult> openBizSceneCallback) {

        BaseResult baseResult = new BaseResult();
        baseResult.setExtendedInfo(params);
        try {
            // mock handle the navigate scene.
            if (sceneCode.contains("FAILURE")) {
                // mock fail callback
                baseResult.setResultError(new ResultError(
                        ResultError.ERROR_CODE_UNKNOWN_ERROR, "the is mock errorDesc in baseResult."));
            }
        }catch (Exception e) {
            Toast.makeText(MyApplication.get(), "openBizScene exception: " + e, Toast.LENGTH_LONG).show();
        }

        openBizSceneCallback.result(baseResult);
    }
}

Sample for iOS

copy
final class DeeplinkService: IAPWalletDeeplinkServiceSignature {
    
    // Mark: this API is designed for future AC-Combo use cases. currently not in use. developers may leave it empty.
    override func open(bizSceneCode: String, with params: [String:String], in context: IAPWalletAPIContext? = nil, callback: @escaping (IAPWalletBaseServiceResult) -> Void) {
        
        let result = IAPWalletBaseServiceResult()
        if (bizSceneCode == IAPWalletDeeplinkServiceSignature.SCENE_WEB_PAGE) {
            result.extendedInfo = ["${result-param-1-key}" : "${result-param-1-value}"]
            callback(result)
        } else if (bizSceneCode == IAPWalletDeeplinkServiceSignature.SCENE_SCAN) {
            result.extendedInfo = ["${result-param-1-key}" : "${result-param-1-value}"]
            callback(result)
        } else if (bizSceneCode == IAPWalletDeeplinkServiceSignature.SCENE_TOP_UP) {
            result.extendedInfo = ["${result-param-1-key}" : "${result-param-1-value}"]
            callback(result)
        }
        
        // implement all the relevant scene codes here.
    }
}

4. Appendix

This section describes the fields that are involved in the APIs and SPIs. If the interface names or class names are different for Android and iOS, the names are separated by a slash (/), of which the former one is for Android and the latter one is for iOS.

Authorization scopes

String

Scope

Description

AC

BASE_USER_INFO

The auth client can obtain the wallet user's unique account ID.

AGREEMENT_PAY

The auth client can use an access token to deduct funds from the user's wallet for Auto Debit payments.

USER_LOGIN_ID

The auth client can obtain the desensitized user login ID.

HASH_LOGIN_ID

The auth client can obtain the wallet user's hash login ID.

SEND_OTP

The auth client can request to send and verify OTPs.

PLAINTEXT_USER_LOGIN_ID

The auth client can obtain the wallet user's plain-text login ID.

AuthPageConfirmResult

Item

Description

referenceAgreementId

The unique ID that is assigned by the auth client to identify an authorization.

Note: Required if the authorization for the Auto Debit payment is successful.

ACConstants.Scene

public class Scene / enum Scene

Andriod Item

Andriod type

iOS item

iOS type

Description

ACConstants.Scene.SOURCE_FROM_WEBVIEW("from_webview")

String

IAPConnectDecodeScene.IAPConnectDecodeFromWebview(1001)

NSInteger

Indicates that the decode API is called in a webview of the MPP app.

ACConstants.Scene.SOURCE_FROM_SCAN("from_scan")

String

IAPConnectDecodeScene.IAPConnectDecodeFromScan(1002)

NSInteger

Indicates that the decode API is called on the code-scanning page of the MPP app.

ACConstants.Scene.SOURCE_FROM_OTHER_APP("from_other_app")

String

IAPConnectDecodeScene.IAPConnectDecodeFromOtherApp(1003)

NSInteger

Indicates that the decode API is called by a deep link from other apps.

AcCallback

public interface AcCallback<T extends AcResult>

Return type

Method

Description

void

onResult(T t)

The interface that is used to return a specified result.

AcBaseResult

public class AcBaseResult

Item

Type

Description

Required

success

boolean

Specifies whether the operation is successful.

M

errorCode

String

The error code that is required if an error occurs.

O

errorMessage

String

The error message that is required if an error occurs.

O

bizContent

Item

Description

Required

acquirerId

The unique ID that is assigned by Alipay+ to identify an Acquiring Service Provider.

M

pspId

The unique ID that is assigned by Alipay+ to identify an MPP.

M

authClientId

The unique ID that is assigned by the ACQP to identify the auth client.

M

authClientName

The registered legal name of the auth client. Usually appears with the agreement on the authorization page.

M

authClientLogo

The URL for the MPP to display the auth client logo. The URL domain is provided by the auth client.

O

authRedirectUrl

The first part of the redirection URL that the user is redirected to after the user agrees to authorize.

M

scopes

The authorization scopes, which means what resources or capabilities are authorized to the auth client. For Auth Debit payments, the value is fixed as AGREEMENT_PAY.

M

terminalType

The type of the auth client terminal that initiates the authorization. Valid values:

  • WEB: The terminal is a Web page.
  • WAP: The terminal is a WAP page.
  • APP: The terminal is a mobile app.
  • MINI_APP: The terminal is a mini-program.

M

referenceAgreementId

The unique ID that is assigned by the auth client to identify an authorization.

M

authState

The authorization statement that is generated by the auth client. The value of this field must be appended to the value of authRedirectUrl to prevent Cross-site request forgery (CSRF) attacks.

M

DecodeParameter

public class DecodeParameter / class IAPConnectDecodeModel

Item

Android Type

iOS Type

Description

scene

@NonNull String

Enum

The scene in which the decode API is called. Valid values are:

  • from_webview
  • from_scan
  • from_other_app

See ACConstants.Scene for details. The default value is from_scan.

codeValue

@NonNull String

NSString

The code value that needs to be decoded by Alipay+.

acDecodeConfigFromServer/decodeConfig

@NonNull String

NSString

The configuration that is required for decoding.

Note: The value of this parameter is received from the MPP server and generated by the Alipay+ server SDK in the code identification result.

merchantType

@Nullable String

NSString

The terminal type of the merchant.

Note:

  • Required if the value of the scene parameter is  Scene.SOURCE_FROM_OTHER_APP.
  • The value of this parameter is usually passed by a deep link.

sourceAppPackageName

@Nullable String

null

The package name of the merchant app.

Note:

  • Required if the value of the scene parameter is Scene.SOURCE_FROM_OTHER_APP.
  • The package name can be resolved from the intent object. You can also pass in the intent object of the deep link and Alipay+ client SDK resolves the package name.

Error codes

Code

Value

Generic

ERROR_CODE_UNKNOWN_ERROR

1000

ERROR_CODE_USER_CANCEL

1001

ERROR_CODE_APP_SERVICE_ERROR

1002

ERROR_CODE_TIMEOUT

1003

Auth

ERROR_CODE_AUTH_PENDING_AGREEMENT

2001

ExtendedInfo Use Cases

Service

Interface

Keys in ExtendedInfo

PaymentService

pay

  • paymentId (optional, appears when paymentType is cashierUrl, but there could be a paymentId in the extendedInfo)

OAuthService

getAuthCode

  • authClientId
  • referenceAgreementId (when showAuthPage SPL returns a referenceAgreementId from the MPP server)
  • acquirerId (provides a optional parameter for the server side)

ForeignExchangeQuote

public class ForeignExchangeQuote / class IAPForeignExchangeQuote

Item

Type

Length

Description

Required

quoteId

String

64

The unique ID that is assigned by Alipay+ to identify a quote

M

quoteCurrencyPair

String

8

The currency pair that the exchange rate applies to. The value is 2 currencies (in ISO-4217) separated by a slash. For example, USD/KRW.

M

quotePrice

String

20

The quotation of the exchange rate between the currency pair that is specified on the quoteCurrencyPair parameter.

M

baseCurrency

String

3

The first currency in the value of

quoteCurrencyPair, in ISO-4217.

O

quoteUnit

String

12

The amount in the currency of the value of the baseCurrency parameter.

O

quoteStartTime

long

/

The date and time when the quotePrice starts to be effective. The time is UTC time in millisecond.

O

quoteExpiryTime

long

/

The date and time when the quotePrice expires. The time is UTC time, accurate to millisecond.

O

InitConfig

public class InitConfig / class IAPConnectInitConfig

Item

Type

Description

Required

envType

String

The environment of the MPP server. Valid values are:

  • PROD: Indicates the production environment
  • DEV: Indicates the development environment

Default value: PROD.

M

sourcePlatform

String

This parameter indicates which app sends the request.

M

tid

String

The terminal ID of the current device. If the parameter is empty, SDK generates a terminal ID internally. If the value is tid, SDK uses the value directly. The length of tid cannot exceed 256, or unknown errors might occur.

O

userAgent

String

The user agent of the MPP device.

Note:

Required for Merchant-presented Mode Payment scenario.

O

acLogDisabled

BOOL

This parameter specifies whether log writing for Alipay+ services is disabled. When the value is true, there will be no log writing for Alipay+ services. The default value is false.

O

InitCallback (only for Android)

public class InitCallback

Return type

Android method

iOS block method

Description

void

onSuccess

(void (^)(void))success

The callback to be invoked on initialization success.

void

onFailure(InitErrorCode initErrorCode, String errorMessage);

(void (^)(IAPConnectInitErrorCode errorCode,NSString *errorMessage))failure

The callback to be invoked on initialization failure. For more information about the failure reasons, see initErrorCode. The errorMessage field describes the failure in detail.

InitErrorCode

public enum InitErrorCode

Error code

Error message

INITIALIZE_UNKNOWN_EXCEPTION

Unknown exceptions occurred during the initialization. See the errorMessage paramter for details.

INITIALIZE_PARAM_ILLEGAL

Illegal parameters exist. For example, the application field or the initConfig parameter is null.

IDecodeCallback/decodeCallback

public interface IDecodeCallback / decodeCallback:(void (^)(IAPConnectDecodeResult *result))decodeCallback

Return type

Android method

iOS block

Description

void

onResult(Result result)

void (^)(IAPConnectDecodeResult *result)

The callback that is used to return the decoding result.

void

showLoading()

Null

The callback that is used to show the loading dialog.

void

dismissLoading()

Null

The callback that is used to dismiss the loading dialog.

IPaymentCodeListener/IAPConnectPaymentCodeListener

public interface IPaymentCodeListener / @protocol IAPConnectPaymentCodeListener <NSObject>

Return type

Method

Description

void

onPaymentCodeUpdated(@NonNull String paymentCode)

The callback method to be invoked on payment code generation or update by the Alipay+ client SDK.

void

onPaymentCodeUpdateFailed(@NonNull String errorCode, @NonNull String errorMessage)

The callback to be invoked on payment code generation or update failure.

IAPWalletPaymentAmount

Item

Type

Description

currency

String

The currency code of the amount. The value of this parameter must be an alphabetic code that follows the ISO 4217 standard, for example, "EUR" for Euros.

value

Int

The value of the amount as a natural number. By default, the value of this parameter is in the smallest currency unit. For example, if the currency is USD and the amount is $1.00, set the value of this parameter to 100; or if the currency is JPY and the amount is ¥1, set the value of this parameter to 1.

IAPWalletPaymentType

Enum

Type

Description

orderId

The unique ID that is assigned by the merchant to identify an order.

paymentId

The unique ID that is assigned by the MPP to identify a payment order.

orderStr

The detailed order information. The value of this parameter is in a JSON string.

cashierUrl

The payment URL to which the user is redirected to confirm the payment.

IAPWalletCodeType

Enum

Type

Description

qrCode

QR code

barCode

Barcode

InquireQuoteCallback

public interface InquireQuoteCallback / foreignExchangeQuote: void (^)(ForeignExchangeQuote *result)

Return type

Android method

iOS block

Description

void

onResult(String resultCodeForeignExchangeQuote foreignExchangeQuote)

void (^)(String resultCodeForeignExchangeQuote *result)

The callback that is used to return the exchange rate inquiry result.

MemberInfo

Item

Description

userId

The user ID in the Mobile Payment Provider system

sessionId

Session ID

loginId

Login ID

loginIdTypeDeprecated

Login ID type. Valid values are:

  • email
  • mobile
  • index

avatar

HTTP URL of the image

gender

Gender. Valid values are:

  • m: Male
  • f: Female

birthday

Deprecated

The birthday that are expressed in UTC

userName

User name. Encrypting the value is allowed.

extendedInfo

Extended information in the set of key-value pairs. The following keys might be used:

  • nickName: Nick name. Encrypting the value is allowed.
  • countryCode: The two-character ISO 3166 country/region code
  • province: Province. Encrypting the value is allowed.
  • city: City. Encrypting the value is allowed.

See ExtendedInfo Use Cases for details.

MemberInfoFetchStrategy

Enum

Type

Description

LOCAL_USER_ID_ONLY

Obtain the locally cached user ID but payloaded into MemberInfo

LOCAL_CACHED

Obtain the locally cached MemberInfo

REMOTE_FETCH

Obtain the latest remote MemberInfo

MemberInfoScope

Item

Description

Required

appId

The ID of the app that calls the interface

O

scopes

The user information scopes. For more information about the scopes, see Authorization scopes.

O

OAuthResult

Item

Description

authCode

The authorization code that is generated by the MPP.

authState

A string that is generated by the auth client to represent the request. The consistency of this field and that in the redirection URL needs to be guaranteed if the authorization code is returned.

Note: This field is optional.

authErrorScopes

The scopes that are failed to be granted.

authSucessScopes

The scopes that are granted successfully.

PaymentRequest

Item

Type

Description

amount

IAPWalletPaymentAmount

The amount of payment.

type

IAPWalletPaymentType

The type of payment service. Each payment service represents a payment flow. Valid values are:

  • orderId
  • paymentId
  • orderStr
  • cashierUrl

paymentString

String

The payment string. The value of this parameter is set to the same value as the type parameter.

extendedInfo

Map<String, String>/Dictionary

The extended information about the payment request. The value of this parameter is in a set of key-value pairs.

If the value of the type parameter is cashierUrl, paymentId is provided in extendedInfo. For more information, see ExtendedInfo Use Cases.

PaymentResult

Item

Description

resultCode

The result code that indicates the payment result. For more information, see Error codes.

resultMessage

The result message that describes the result code in detail.

QuoteCurrency

public class QuoteCurrency / class IAPConnectQuoteCurrency

Item

Type

Length

Description

Required

sellCurrency

String

3

The currency that Alipay+ sells on behalf of the user. The value of this parameter is a 3-character ISO 4217 currency code.

M

buyCurrency

String

3

The currency that Alipay+ buys on behalf of the user. The value of this parameter is a 3-character ISO 4217 currency code.

M

Result/IAPConnectDecodeResult

public class Result / class IAPConnectDecodeResult

Item

Type

Description

resultCode

String

The result code that indicates the decoding result. For more information, see ResultCode.

resultMessage

String

The result message that describes the result code in detail.

paymentRedirectUrl

String

The HTTPS URL of the payment result page to which the user is redirected after payment processing is completed.

Note: Required if model(IAPConnectDecodeModel).scene is IAPConnectDecodeFromWebview.

closeWebpage

boolean

Specifies whether the web page is closed.

Note: This value of this parameter is set to false if model(IAPConnectDecodeModel).scene is IAPConnectDecodeFromWebview; otherwise, the value is true.

ResultCode

public interface ResultCode / IAPConnectConstant

Name

ErrorMessage

Description

SUCCESS

Success.

The operation is successful.

PROCESSING

The payment is in processing.

The payment is in processing.

PARAM_ILLEGAL

Oops! System busy. Try again later!

Invalid parameters exist. For example, a non-numeric input, or an invalid date.

INVALID_NETWORK

Oops! System busy. Try again later!

A network error occurred.

UNKNOWN_EXCEPTION

Oops! System busy. Try again later!

An unknown exception occurred.

PROCESS_TERMINATED

Oops! System busy. Try again later!

The process is terminated.

OTP_DUPLICATE_DECODE

Oops! System busy. Try again later!

Duplicate OTP decoding.

SERVICE_EXCEED_LIMIT

Oops! System busy. Try again later!

The backend service exceeds the limit.

PROCESS_FAIL

Oops! System busy. Try again later!

OAuth authorization failed.

CLIENT_KEY_INVALID

Oops! System busy. Try again later!

The client key is invalid.

INVALID_SIGNATURE

Oops! System busy. Try again later!

The verification of the agreement signature failed.

INVALID_CODE

Oops! System busy. Try again later!

The code value is invalid.

INVALID_AUTHCODE

Oops! System busy. Try again later!

The authorization code is invalid.

INVAILD_REDIRECTURL

Oops! System busy. Try again later!

The redirect URL is invalid.

SAL_FAIL_ICIF

Oops! System busy. Try again later!

Failed to call ICIF (International Customer Core Service System).

EXPIRED_CODE

Oops! System busy. Try again later!

The payment code is expired.

USER_NOT_EXIST

Oops! System busy. Try again later!

The user does not exist.

USER_STATUS_ABNORMAL

Abnormal account activity detached.

The user status is abnormal.

REPEAT_REQ_INCONSISTENT

Oops! System busy. Try again later!

Repeated requests are inconsistent.

ORDER_NOT_EXIST

Oops! System busy. Try again later!

The order does not exist.

SDK_NOT_SUPPORT

Your app version is low, please upgrade to the latest version.

Your app version is outdated. Upgrade to the latest version.

EXPIRED_CODE

The payment code is expired, please refresh.

The payment code is expired. Refresh the code.

PAY_FAILURE

[The error message is from Mobile Payment Provider]

The payment failed.

Note: If the MPP calls the pay SPI and the payment fails, the MPP must send the PAY_FAILURE error code and error message to the Alipay+ client SDK.

ScannerOption

Item

Type

Description

type

IAPWalletPaymentAmount

Code type. Valid values are:

  • qrCode: QR code
  • barCode: Barcode 

hideAlbum

String

An indicator of whether the user scans a QR code/barcode in the picture selected from the album.

  • When the value is true, the user can use the camera to scan a QR code or barcode presented by the merchant, or select a barcode or QR code from the album to scan.
  • When the value is false, the user only can use the camera to scan the QR code or barcode presented by the merchant.

extendedInfo

String

This field is reserved for future use

ScannerResult

Item

Type

Description

code

String

The code value extracted by the scanner. This field is empty if some errors occur during scanning.

SignContractRequest

public class SignContractRequest / class IAPConnectSignContractRequest

Item

Type

Description

Required

bizContent

String

The business content for the user authorization, which is generated by Alipay+. See bizContent for details.

Note: Required if the authUrl parameter is empty.

O

authUrl

String 

The URL of the authorization page that is generated by the Mobile Payment Provider server and used by the Mobile Payment Provider app.

Note: Required if the bizContent parameter is empty.

O

needCallback

boolean

This paramter indicates whether the Alipay+ client SDK needs to send the obtained authorization code to the Alipay+ server. In details:

  • false: The Alipay+ client SDK does not need to send the obtained authCode to the Alipay+ server. Because the auth client uses authCode to apply for the access token.
  • true: The Alipay+ client SDK needs to sends the obtained authCode to the Alipay+ server to map the received referenceAgreementId with the auth client. Because the auth client uses referenceAgreementId to apply for the access token.

M