• Python
  • Golang
  • Java

# 1. Applicable Scenarios

It is most suitable when the Gate Pay payment function is enabled in the merchants’ mobile APP.

After the merchant’s APP requests the SDK provided by Gate Pay to enable the Gate Pay payment function, the merchant APP’s page will jump to the Gate APP to complete the payment, and then jump back to the merchant’s APP interface once the payment is done, with the payment result displayed.

The function is currently available for IOS (Apple) and Android (Android) operating systems.

The interaction process is as follows:

Step 1: On the merchant’s APP, the users place an order, and confirm the purchase. After the payment process is started, a payment order will be created on the merchant’s service background. After being signed, the payment order will be transmitted to the APP.

Step 2: The users click to enter Gate’s payment interface, where they can request the Gate Pay payment. After the request is made, they will be directed to the page where confirmation of the payment is required.

Step 3: The users need to verify the payee and the payment amount, click “Pay”, and enter the password.

Step 4: The payment is completed once the correct password is provided. The payment result will be displayed on the page.

Step 5: Then the users will jump back to the merchant APP’s interface where the payment result will also be displayed in a manner set by the merchant.

# 2. Development Guidelines

The following is the sequence diagram of the interaction process. A signature is required for the order API, payment result notification API, and order query API, and the calls must be completed on the merchant server. The details are shown below.

调起支付时序图

Call payment runnning process:

Steps 1-6:

After the user initiates the payment, the merchant calls the GatePay order(/v1/pay/order)API to create a prepayment order.

After the merchant calls the order API, the merchant will operate according to the contents returned.

Normal return: prepay_id is returned, meaning the prepaid order is successfully created.

Abnormal return: http code or error code will be returned. The error code will indicate the cause and the next line of operations.

Steps 6-14:

Situation 1: If the merchant successfully obtains the prepayment order ID after the order interface is called, and at the same time the parameters and signature required to call the payment component interface are returned to the merchant’s APP, the merchant APP can directly call the payment component interface.

Situation 2: Step 6: If the prepayment order ID is returned to the merchant’s App without the calling parameters and signature, the merchant server side needs to provide an interface for obtaining the signature, and the merchant client side needs to request the merchant backend to provide it.

When the signature verification for calling the payment component is returned, the SDK pops up the payment component and calls to query the order information.

Steps 15-17:

After the user completes the payment, the payment result will be pushed to the client synchronously. Merchants can query the order status in the following two ways:

Method 1: Notification. After the user completes the payment, GatePay will synchronize the payment result with the merchant in the form of a callback notification. The merchant should provide the callback address as a part of the notify_url parameter when calling the APP order API.

Method 2: When the callback notification cannot be received due to network jitter or issues with the notify_url itself, the merchant can call the query order API (/v1/pay/order/query) to query the order status.

# 3. API list

# 3.1 Order status query interface

In order to synchronize order information with merchants, GatePay provides a query interface enabling the merchants to query prepaid orders and refund orders.

  • Request type:JSON (content-type: application/json)
  • Request method:POST
  • Verification method:signature
  • Path: /v1/pay/open/sdk

body type:

Parameter Name Variable Type Required Description
Application ID clientid string Yes The mobile app ID approved by Gate Open Platform
Merchant Number merchantid string Yes Merchant number
Pre-order ID prepayid string Yes Pre-order ID
Order Detail String package string Yes Fill in the fixed value GatePay for now

Example of request:

curl --location --request POST 'https://openplatform.gateapi.io/v1/pay/open/sdk' \
--header 'Content-Type: application/json' \
--header 'X-GatePay-Certificate-ClientId: zb6WUrBDZlRAT7qz' \
--header 'X-GatePay-Timestamp: 1674117221032' \
--header 'x-GatePay-Nonce: 7436636664' \
--header 'x-GatePay-Signature: 11e658cf6b09d917caf9d4bb6ec4493431c55f066a694e58a5571a4a1a114ebc2011d346f340e54a5a2e2edaa172e907742fbdc99b94d009dade4b551daabd07' \
--data-raw '{"prepayid":"50620368071692288","package_ext":"ext"}'

success response:

{
    "status":"SUCCESS",
    "code":"000000",
    "errorMessage":"",
    "data":{
        "prepayid":"50620368071692288"
    }
}

failed response:

{
    "status":"FAIL",
    "code":"10002",
    "errorMessage":"",
    "data":{}
}

# 3.2 Order status query interface

In order to synchronize order information with merchants, GatePay provides a query interface enabling the merchants to query prepaid orders and refund orders.

  • Request type:JSON (content-type: json)
  • Request method:POST
  • Validation Type:signature
  • Path:/v1/pay/order/query

request body type:

Attribute Name Type Required Description
prepayId string No Prepayment information. Either prepayId or merchantTradeNo must be provided.
merchantTradeNo string No Merchant order ID. Either prepayId or merchantTradeNo must be provided.

response type:

Property Name Type Required Description
status string (SUCCESS or FAIL) Yes Payment status
code string Yes Error code
data query order return type No Payment order information
errorMessage string No Error message

query order return type:

Property Name Type Required Description
prepayId string Yes The prepay ID.
merchantId int64 Yes Gate UID used to apply for a merchant account.
merchantTradeNo string Yes The merchant order number.
transactionId string Yes The transaction ID.
goodsName string Yes The name of the goods.
currency string Yes The currency of the order.
orderAmount string Yes The amount of the order.
status string Yes The status of the order. PENDING - Order pending payment, PROCESS - Payment processing, PAID - Payment succeeded, EXPIRED - Order expired, CANCELLED - Order cancelled by merchant, ERROR - Payment failed due to error.
createTime int64 Yes The timestamp when the prepay was created (in milliseconds).
expireTime int64 Yes The timestamp when the prepay will expire (in milliseconds).
transactTime int64 Yes The timestamp when the payment was completed (in milliseconds).
order_name string Yes The name of the order.
pay_currency string Yes The currency used for payment.
pay_amount string Yes The amount paid by the user.
expectCurrency string No The revenue currency specified by the merchant when creating the order. Only returned in details of orders with a specified settlement currency.
actualCurrency string No The actual currency used by Gate for settlement to the merchant after payment. Only returned after settlement.
actualAmount string No The actual amount settled by Gate to the merchant after payment. Only returned after settlement.
rate string Yes The exchange rate used for flash payment.
channelId string No Client Name.

Example of request:

curl --location '127.0.0.1:8201/v1/pay/order/query' \
--header 'Content-Type: application/json' \
--header 'X-GatePay-Certificate-ClientId: zb6WUrBDZlRAT7qz' \
--header 'X-GatePay-Timestamp: 1678442053228' \
--header 'x-GatePay-Nonce: 2002257450' \
--header 'x-GatePay-Signature: ce9ed61041a3a76d292c7475e3957d2e788dd21e7e8b6aa523867a047892e4395a0dfd0e851e9a357a3582babe6a02e40ccff8111ee86d317cf56838f0b5568c' \
--data '{  
    "prepayId": "56416503889661952"
}'

Example of response:

{
    "status": "SUCCESS",
    "code": "000000",
    "errorMessage": "",
    "data": {
        "prepayId": "56335302571069440",
        "merchantId": 10002,
        "merchantTradeNo": "118223456798",
        "transactionId": "",
        "goodsName": "NF2T",
        "currency": "USDT",
        "orderAmount": "1.9",
        "status": "EXPIRED",
        "createTime": 1675392982792,
        "expireTime": 1675396480000,
        "transactTime": 0,
        "order_name": "MiniApp-Payment#118223456798",
        "pay_currency": "",
        "pay_amount": "0",
        "expectCurrency": "BTC",
        "rate": "0",
        "channelId": "123456"
    }
}

# 3.3 Order status change callback notification

When the status of the prepaid order changes, such as expiration of the order due to exhaustion of payment time or successful payment of the order, the GatePay background will send a notification to the merchant to the notification address, which is the callback url provided by the merchant at registration.

If the notification fails to be sent to the merchant due to a network issue or other unknown reasons, GatePay background will resend it every 3 seconds, 10 times at most until it is sent successfully. If it still does not work, the merchant can query the status of the prepaid order by querying API.

  • Request type: JSON (content-type: application/json)
  • Request method:POST
  • request body content:
Attribute Type Required Description
bizType string Yes The type of the business, must be "PAY".
bizId string Yes The ID of the prepayment.
bizStatus string Yes The status of the business, can be "PAY_SUCCESS" or "PAY_CLOSED".
data string Yes The JSON format string of the order data type object.

order data types

Property Name Type Required Description
merchantTradeNo string Yes The merchant order ID
goodsName string Yes The name of the goods
terminalType string Yes The transaction source, for example, "MINIAPP"
currency string Yes The order currency
orderAmount string Yes The transaction amount
payerId int64 No The ID of the payer

Example of request:

{
    "bizType": "PAY",
    "data": "{\"merchantTradeNo\":\"56236\", \"terminalType\":\"MINIAPP\", \"currency\":\"BTC\", \"orderAmount\":\"1.91\", \"payerId\":513301}",
    "bizId": "1647557960944",
    "bizStatus": "PAY_SUCCESS"
}

Example of response:

{
    "returnCode": "SUCCESS",
    "returnMessage": null
}

# 4. SDK Integration for iOS

# 4.1 Version

  • http://gate.com iOS App: 3.11.1+
  • iOS:iOS11.0+

# 4.2 Integration

Cocoapods: pod 'GateOpen'

# 4.3 Do the following

  1. Download the GateOpenSDK.framework dynamic library file
  2. Add GateOpenSDK.framework to your project file
  3. Select the Build Phases option to add GateOpenSDK.framework to Embed Frameworks

# 4.4 Use

Info.plist

Configure the necessary parameters of Info.plist:

Add parameters of gate and gatepay to LSApplicationQueriesSchemes

# 4.5 Initiate payment

@interface GOPayRequest : GORequest
///api_key provided by Gate
@property (nonatomic, copy) NSString *api_key;
///The UTC timestamp when the request was made
@property (nonatomic, copy) NSString *timestamp;
///Random string, the length of which had better not exceed 32 characters, and which should contain numbers and letters.
@property (nonatomic, copy) NSString *nonce;
///Request for signature
@property (nonatomic, copy) NSString *sign;
/// prepaid order ID
@property (nonatomic, copy) NSString *prepayid;
/// Jump back scheme such as: scheme://xxxx
/// If it is a deep link: <https://xxxx>
@property (nonatomic, copy) NSString *redirectUri;

@end
GateOpenManager
GateOpenManager is used to initiate and receive class of payment request callbacks.
@interface GateOpenManager : NSObject

+ (instancetype)shared;

/// Call payment method
/// @ param payItem payment required parameters
/// @ param handle payment result callback
- (void)payment:(GOPayRequest *)payItem result:(PayResultHandle)handle;

/// appdelegate jump analysis
/// @param url delegate OpenURL
- (void)handle:(NSURL *)url;
@end
GOPayResponse
GOPayResponse is used to encapsulate the parameters for payment result.
/// The return class after payment is completed. 
@interface GOPayResponse : GOResponse

///  Whether the payment is successful?
@property (nonatomic, assign) BOOL isSuccess;

/// Affiliated information
@property (nonatomic, strong) NSString * _Nullable message;

- (instancetype _Nonnull)initWith:(BOOL)isSuccess
                          message:(NSString * _Nullable)message;

@end

# 4.6 Code call

# 4.6.1 Initiate payment

The third-party application needs to obtain payment request parameters from its own server, create a GOPayRequest object, and then submit a payment request to the payment SDK.

/// Create payment request parameters GOPayRequest

GOPayRequest *payRequest = [[GOPayRequest alloc] init];
        payRequest.prepayid = @"prepayId";
        payRequest.timestamp = @"timestamp"   
        payRequest.nonce = @"signature";
        payRequest.sign = @"signature";
        payRequest.api_key = @"api_key";
        payRequest.redirectUri = @"schemes://";
        
        /// 发起支付请求
        [[GateOpenManager shared] payment:payRequest result:^(GOPayResponse * _Nullable response) {
            wSelf.payResultInfo.text = response.isSuccess ? @"支付成功" : @"支付失败";
            wSelf.payResultInfo.textColor = response.isSuccess ? UIColor.greenColor : UIColor.redColor;
       }];

# 4.6.2 Callback configuration

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    [[GateOpenManager shared] handle:url];
    return YES;
}

# 5. SDK Integration for Android

# 5.1 Obtain the SDK package and introduce dependencies

  1. Integrate the <repos> folder provided by Gate Pay into the project root directory, or into the local maven repository.
  2. Add the local maven address into build.gradle of the project level.
  3. Add the following into the dependencies of the app module's build.gradle file

Integrate the <repos> folder provided by Gate Pay into the project root directory, or into the local maven repository

allprojects {
   repositories {
        maven {
           url uri("${rootProject.projectDir}/repos")
       }
     }
   }

Add the following into the dependencies of the app module's build.gradle file

implementation 'com.gateio.sdk:gatepay-sdk:1.0.0'

# 5.2 Initialize the SDK

Parameters Description:

Parameter Name Type Required Description
isDebug boolean No Whether to enable debug mode (DO NOT enable on production version!!!) (You can filter log messages with "gate_pay_sdk" to get corresponding exception information.)
context Context Yes It is recommended to pass the Application Context.
clientId String Yes The clientId obtained from GatePay platform (i.e., the api_key provided by Gate).
redirectUri String Yes The scheme uri that the current application needs to callback (If the project has not implemented scheme redirection, you can try passing "gate_default_scheme", and gatepay-sdk will automatically obtain the current Activity to implement redirection).

Note: None of the parameters can be null, otherwise the initialization will fail.

Initialize SDK in onCreate in Application:

GatePaySDK.init(boolean isDebug, final Context context, String clientId, String redirectUri)

# 5.3 Call payment component

Parameters Description:

Property Name Type Required Description
activity Activity Yes The current activity of the application.
signature String Yes The request signature. Gate Pay uses this signature to verify the legitimacy of the request.
timesTamp String Yes The UTC timestamp when the request was generated, in milliseconds. Please note that Gate Pay does not process requests with timestamps that differ more than 5 seconds from the time it received the request.
nonce String Yes A random string composed of numbers and letters that conforms to HTTP header specifications. It is recommended to keep the length of the string within 32 characters.
prepayId String Yes The prepay order ID obtained from the payment request.
packageExt String Yes The package extension field with a fixed value of "GatePay".
navigationGatePayListener NavigationGatePayListener Yes A listener to handle the success or failure of the payment request and perform the corresponding actions.

Error code description:

onGateOpenFailed(int code, String errorMessage)

  1. code:10021 errorMessage:openPackage failed Please check whether the App has the license to call other application.
  2. code:10022 errorMessage:intentData error Please check if PrepayId and redirectUri are correct.
  3. code:10023 errorMessage:response data is null Please check whether the signature verification parameters are correct.
  4. code:10023 errorMessage:Get throwable.getMessage() dynamically Please check the onGateOpenFailed exception information prompt and find the cause.
  5. code:10024 errorMessage:params error Please check whether the initialization or calling payment parameters are correct.

Note: For codes other than the above, you can directly check the errorMessage for the information, or check the corresponding connecting error code in the Gate Pay server.

# 5.4 Payment result callback

  1. In the onResume() of the current page Activity in step 3, decide whether it is GatePay depending upon the boolean GatePaySDK.gateResumePayResult(). If yes, process the GatePay callback logic.

Note: Repeated callbacks can be avoided with the GatePaySDK.gateResumePayResult() method. The logic has been cleared, and it can only be obtained once. If you need to print the Log or make other judgments, you can temporarily store the value after obtaining it.

  1. Get the payment status of Gate App: Code: GatePaySDK.gateResumePayState().getCode() State: GatePaySDK.gateResumePayState().getState()

Notes:

Code value in the callback

Code: 10005--- failed (constant value: GatePayConstant.MESSENGER_STATE_CODE_FAILED)

Code:10006---cancel (constant value: GatePayConstant.MESSENGER_STATE_CODE_FAILED_CANCEL_PAY)

Code:10010---success (constant value: GatePayConstant.MESSENGER_STATE_CODE_SUCCESS)

Note: If it is 10010--success, check the payment result in the background and then display it. Note that the result returned by the client is not conclusive evidence of the payment result. Rather, the payment notification received by the server or the result returned by the query API shall prevail.

# 5.5 FAQ for Android

  1. Can't return to the app after filling in the redirectUri? Check AndroidManifest to see whether android:exported="true" is active for the current Activity (had better in the mode of android:launchMode="singleTask")

  2. No response for calling the startGatePay method? Set isDebug to true during initialization, and filter by keyword the "gate_pay_sdk" through Logcat to view the corresponding exception prompt:

The causes might Include but not limited to the following:

  • The SDK is not initialized
  • The clientId is not filled in
  • The redirectUri is not filled in
  • The Gate App has not been installed yet (the SDK has redirected to download it.)
  • The Gate App is not in the latest version [3.11.1+] (the SDK has popped reminders suggesting to update and download the latest version)

After prepaid order and signature information is obtained on the current page, call the Gate payment component through GatePaySDK.startGatePay.

GatePaySDK.startGatePay(Activity activity, String signature, String timesTamp, String nonce,
   String prepayId, String packageExt, NavigationGatePayListener navigationGatePayListener)
  1. Unable to obtain the payment result callback status? Check whether the App is prevented from interacting with other Apps. If there is no issue with the interaction permission and the parameters are correct, but the result still cannot be obtained, enter "gate_default_scheme"(Please refer to step 2 instructions) in redirectUri , and get the Intent value from onNewIntent (only valid in "gate_default_scheme").

Get GatePayConstant.INTENT_GATE_B_CLASS_PARAM, with the parameter in Json format, such as: {"code":10006,"state":"cancel"}

Method 1): Obtain it directly from onNewIntent
   @Override
   protected void onNewIntent(Intent intent) {
       super.onNewIntent(intent);
       if (intent != null) {
           String intentData = intent.getStringExtra(GatePayConstant.INTENT_GATE_B_CLASS_PARAM);
       }
     }

  Method 2): Get it in onResume()
   @Override
   protected void onNewIntent(Intent intent) {
       super.onNewIntent(intent);
        setIntent(intent);
   }

   @Override
   protected void onResume() {
       super.onResume();
       Intent intent = getIntent();
       if (intent != null) {
           String intentData = intent.getStringExtra(GatePayConstant.INTENT_GATE_B_CLASS_PARAM);
       }
   }
  1. Why the signature information should be obtained through the server when calling the payment component?

After receiving the platform information, Gate Pay will provide the third party with api_key and api_secret, of which the api_key is used to identify the identity, and the api_secret is used to request signatures. The api_secret must be properly stored, and the signature information can only be generated through the server.

Note: Refer to GatePayDemo to view the complete access process.