﻿# Auth-Capture

## 1. Business Introduction

The Auth-Capture pattern and the Sales pattern are both basic interaction patterns for payment processing (commonly used for card payments):

- **Sales Mode (One Interaction)**: When the user pays, authorization and deduction are completed at the same time, and the funds are immediately deducted from the user's bank card;

- **Auth-Capture Mode (Secondary Interaction)**：The transaction is divided into two steps. The first is authorization, which freezes the user's funds; then the merchant initiates a capture to actually complete the deduction.

### 1.1 Authorization

The merchant/institution requests authorization for a specific amount from the user's card issuer.

- The card issuer verifies the user's bank card, such as whether the funds/credit limit are sufficient and whether the card is valid (not frozen or reported lost);

- If the authorization is successful, the card issuer will freeze the funds;

- At this time, there is no fund flow, it is just a temporary freeze;

- If the authorization is not requested within the validity period (7 days), it will expire and the frozen amount will be released.

### 1.2 Capture

- After the merchant confirms the completion of the transaction, request to transfer the authorized funds;

- Funds flow occurs: deduct money from the cardholder's bank account;

- Currently, one-time payment request is supported, and over-amount payment request is not supported.

## 2. Applicable Scenarios

- **Hotel and Tourism Industry**: When users book a hotel or rent a car, they first authorize the user to freeze the credit card funds as a deposit. When the user leaves the hotel or returns the car, they initiate a payment request based on the actual consumption amount and complete the deduction;

- **Power Bank Rental Scenarios**: When a user rents a power bank, the merchant authorizes the merchant to freeze the deposit of the power bank. When the user returns the power bank, the merchant initiates a payment request based on the actual consumption amount and completes the deduction;

- **Large e-commerce platforms**: After consumers place an order on an e-commerce platform, they first need to authorize the payment, and then request payment after the merchant ships the goods to complete the payment process.

## 3. Integration Preparation

+ [Register developer center account](https://docs.payermax.com/en/202606-version/developer/integration-guide.md#_3-2-register-as-a-developer)；

+ [Upload test merchant public key](https://docs.payermax.com/en/202606-version/developer/integration-guide.md#_3-4-1-configure-key-information-for-the-test-environment)，get the platform public key, AppID, test merchant number and other integration information；

+ [Configure the callback address (WebHook)](https://docs.payermax.com/en/202606-version/developer/integration-guide.md#_3-4-2-configure-the-callback-address-for-the-test-environment), including the payment result callback address, refund result callback address, and so on;

+ [Setting up a test environment server IP whitelist](https://docs.payermax.com/en/202606-version/developer/integration-guide.md#_3-5-setting-up-a-whitelist-of-server-ips-for-the-test-environment)；

+ [Configure and enable the appropriate payment methods](https://docs.payermax.com/en/202606-version/developer/integration-guide.md#_3-6-open-integrated-payment-methods)；

+ [View request addresses for different environments](https://docs.payermax.com/en/202606-version/developer/integration-guide.md#_2-environmental-information)；

+ [Understand the principles of request message signing and verification](https://docs.payermax.com/en/202606-version/developer/config-settings.md), for generating a `sign` signature string for each HTTP request Header.

## 4. Interaction Process 

```mermaid
%%{init: {
  'theme': 'base',
  'themeVariables': {
    'primaryColor': '#e6f0ff',
    'primaryTextColor': '#333',
    'primaryBorderColor': '#5b9bd5',
    'lineColor': '#888',
    'actorMargin': 40,
    'noteBkgColor': '#0056b3',
    'noteTextColor': '#ffffff',
    'noteBorderColor': '#004a99'
  }
}}%%
sequenceDiagram
    participant User as User
    participant Client as Merchant Client
    participant MServer as Merchant Server
    participant Checkout as PayerMax Cashier 
    participant PMServer as PayerMax Server
    participant Channel as Payment Channel
Wallet/Bank, etc.

    %% 1. Order and Redirect
    User->>Client: 1.1 Select product and place order
    Client->>MServer: 1.2 Place order
    MServer->>PMServer: 1.3 Create payment
Call Cashier checkout API (Auth)
    PMServer->>PMServer: Create transaction
    PMServer-->>MServer: 1.4 Return payment creation response
including PayerMax Cashier URL
    MServer-->>Client: 1.4 Return response
    Client->>Checkout: 2.1 Redirect to PayerMax Cashier page

    %% 2. Payment Interaction
    User->>Checkout: 3.1 Select payment method and submit payment
    Checkout->>PMServer: 3.2 Payment request
    PMServer->>Channel: 3.3 Payment request
    PMServer-->>Checkout: 3.4 Response
including PayerMax payment result URL
    Checkout->>Checkout: 3.5 Redirect to PayerMax payment result page
    User->>Checkout: 4.1 User clicks [Return to Merchant]
    Checkout-->>Client: 4.2 Redirect to merchant-specified page

    %% 3. Obtain Authorization Result (Logic Box)
    rect rgb(235, 245, 255)
        Note over MServer, PMServer: Obtain Authorization Result
        Note over MServer, PMServer: Via Payment Result Notification
        PMServer->>MServer: 5.1 Asynchronous notification of payment result
        MServer->>MServer: 5.2 Update payment status
        MServer-->>PMServer: 5.3 Return response

        Note over MServer, PMServer: Via Payment Order Query
        MServer->>PMServer: 6.1 Query payment transaction
        PMServer-->>MServer: 6.2 Transaction details, including payment result
        MServer->>MServer: 6.3 Update payment status
    end

    %% 4. Capture Process
    MServer->>PMServer: 7.1 Initiate capture, call Capture API
    PMServer->>Channel: 7.2 Capture request
    PMServer-->>MServer: 7.3 Return response

    %% 5. Obtain Capture Result (Logic Box)
    rect rgb(235, 245, 255)
        Note over MServer, PMServer: Obtain Capture Result
        Note over MServer, PMServer: Via Capture Result Notification
        PMServer->>MServer: 8.1 Asynchronous notification of capture result
        MServer->>MServer: 8.2 Update capture status
        MServer-->>PMServer: 8.3 Return response
    end

    %% 6. Void/Cancel Process
    MServer->>PMServer: 9.1 Initiate void, call Void API
    PMServer->>Channel: 9.2 Void request
    PMServer-->>MServer: 9.3 Return response

    %% 7. Obtain Void Result (Logic Box)
    rect rgb(235, 245, 255)
        Note over MServer, PMServer: Obtain Void Result
        Note over MServer, PMServer: Via Void Result Notification
        PMServer->>MServer: 10.1 Asynchronous notification of void result
        MServer->>MServer: 10.2 Update void status
        MServer-->>PMServer: 10.3 Return response
    end
```

## 5. Interface List

| Associative Interaction Timing                          | Calling direction        | Interface PATH                                                                                                                                    |
| ------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1.3 Create payment and call the cashier order interface | `Merchant` -> `PayerMax` | [/orderAndPay](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-orderAndPay/post) |
| 5.1 Asynchronous notification of payment results        | `PayerMax` -> `Merchant` | [/authResultNotifyUrl](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/(AuthResultNotifyUrl/post)          |
| 6.1 Check payment transactions                          | `Merchant` -> `PayerMax` | [/orderQuery](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-orderQuery/post)   |
| 7.1 Initiate payment request                            | `Merchant` -> `PayerMax` | [/capture](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-capture/post)         |
| 8.1 Asynchronous notification of payment request result | `PayerMax` -> `Merchant` | [/captureResultNotifyUrl](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/captureResultNotifyUrl/post)     |
| 9.1 Initiate a revocation                               | `Merchant` -> `PayerMax` | [/cancel](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-cancel/post)           |
| 10.1 Asynchronous notification of cancellation results  | `PayerMax` -> `Merchant` | [/cancelResultNotifyUrl](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/cancelResultNotifyUrl/post)       |

## 6. Environmental Information

- **Test environment request address**：https:// `pay-gate-uat.payermax.com`/aggregate-pay/api/gateway/ `<Interface PATH>`

- **Production environment request address**：https:// `pay-gate.payermax.com`/aggregate-pay/api/gateway/ `<Interface PATH>`

## 7. Integration Steps

### 7.1 Authorization Application

The authorization mode is divided into three different integrated mode authorizations:

- [Cashier Authorization](https://docs.payermax.com/en/202606-version/acquiring/start-integration/advanced-capabilities-integration/auth-capture/cash-payment-integration.md)

- [Direct API Authorization](https://docs.payermax.com/en/202606-version/acquiring/start-integration/advanced-capabilities-integration/auth-capture/direct-api-integration.md)

- [Drop In Authorization](https://docs.payermax.com/en/202606-version/acquiring/start-integration/advanced-capabilities-integration/auth-capture/drop-in-integration.md)

### 7.2 Get Authorization Results

For authorization result integration, refer to the [Get Payment Result Integration](https://docs.payermax.com/en/202606-version/acquiring/start-integration/related-capabilities-integration/payment-result.md) docking steps, which have the same functions. If the `Auth-capture` function is used, the following fields will be returned in the payment result notification or payment order query return:

| Field Name          | Field Type | Required or Not | Description                                                           |
| ------------------- | ---------- | --------------- | --------------------------------------------------------------------- |
| `captureMode`       | `string`   | `Yes`           | Payment mode:`MANUAL`                                                 |
| `authorizationType` | `string`   | `No`            | Authorization type:`PRE_AUTH`，`FINAL_AUTH`；Defaults to `FINAL_AUTH` |

#### 7.2.1 Authorization Notification

For authorization notification, please view [Authorization Notice/authResultNotifyUrl API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/(AuthResultNotifyUrl/post).

Here is an example:

``` json
{
  "code": "APPLY_SUCCESS",
  "msg": "",
  "keyVersion": "1",
  "appId": "3b242b56a8b64274bcc37dac281120e3",
  "merchantNo": "020213827212251",
  "notifyTime": "2022-01-17T09:33:54.540+00:00",
  "notifyType": "PAYMENT",
  "data": {
    "outTradeNo": "P1642410680681",
    "tradeToken": "T2024062702289232000001",
    "totalAmount": 10000,
    "captureMode":"MANUAL",
    "authorizationType":"FINAL_AUTH",
    "currency": "IDR",
    "country": "ID",
    "status": "SUCCESS",
    "completeTime": "2023-10-20T03:28:23.092Z",
    "paymentDetails": [
      {
        "paymentMethodType": "CARD"
      }
    ],
    "reference": "020213827524152"
  }
}
``` 

#### 7.2.2 Inquiry by Payment Order

Merchants can also obtain payment results by calling the [transaction query/orderQuery API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-orderQuery/post).

[Transaction Query/orderQuery API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-orderQuery/post) request example:

``` js
curl --request POST \
  --url https://pay-gate-uat.payermax.com/aggregate-pay/api/gateway/orderQuery \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'sign: FPFVT3o227JrFRbqu19boZCpVVTF9KznxyRawUmxpfXilHV/0yK46haPhAjNu1hPUMy7Vw/ILXhfzffNm4Fj0apWknlTY9OJxnSoQxS9BTFtc61tn5yV1q69x/kkBl82/qwg+XTJ4fOzy7Mar3VaC1E2PlDA6RkkKBUyNE6RYgsdB+Su7an4+4HVTNAnoe74WyvBgxTLMNg28igBTdqxaO3w/UBY6ObVp7vkqkQGdL1Y+HgmMYaAVwrM3+ALWGId0sJ+YqTY4WJ+0xCRGhaSnybiIjZsQEYyID68WNUfuavDLDsEhaMm/HfQvf5p0R1Ltovp3wwJnEbQcjY458iX5A==' \
  --data '{
  "version": "1.4",
  "keyVersion": "1",
  "requestTime": "2022-01-17T07:51:15.597+00:00",
  "appId": "a0dddd1f622243cb9aa1b676e808b5f8",
  "merchantNo": "02021382719993",
  "data": {
    "outTradeNo": "P1642410680681" # Merchant order number
  }
}'
```

[Transaction Query/orderQuery API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-orderQuery/post) response example:

``` json
{
  "msg": "Success.",
  "code": "APPLY_SUCCESS",
  "data": {
    "reference": "Reference query and callback return",
    "country": "SA",
    "totalAmount": 10,
    "outTradeNo": "DEVTest1669616467952",
    "currency": "SAR",
    "channelNo": "DMCP000000000177005",
    "thirdChannelNo": "4ikqJ6ktEqyRawE1dvqb9c",
    "paymentCode": "2312121212",
    "tradeToken": "T2024062702289232000001",
    "completeTime": "2023-10-20T03:28:23.092Z",
    "captureMode":"MANUAL",
    "authorizationType":"FINAL_AUTH",
    "paymentDetails": [
      {
        "targetOrg": "*",
        "cardInfo": {
          "cardOrg": "VISA",
          "country": "SA",
          "cardIdentifierNo": "400555******0001",
          "cardIdentifierName": "**ngwei"
        },
        "payAmount": 10,
        "exchangeRate": "1",
        "paymentMethod": "CARD",
        "payCurrency": "SAR",
        "paymentMethodType": "CARD"
      }
    ],
    "fees": {
      "merFee": {
        "url": "https://cashier-n-test-new.payermax.com/static/invoice.html?country=AE&merchantNo=P01010113843429&timestamp=1687769788704&version=1.0&orderTaxToken=XWXFKKBOPExplK4aX0r7wgiMtiAMLBKObPFdCMpM9HmCq3AAOob%252BcAZOkP27Kh3W",
        "amount": "100",
        "currency": "SAR"
      }
    },
    "status": "SUCCESS",
    "resultMsg": ""
  }
}
```

### 7.3 Initiate payment request

After the authorization is successful, when the business needs to request payment, you need to initiate another payment request. For the interface content, please refer to the [Request payment/capture API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-capture/post) interface.

::: warning Note:
1. The original authorization must be successful;
2. Initiate a payment request with the original order number **`outTradeNo`** and pass in the amount to be paid.
:::

**Key Parameters**：

| Field Name   | Field Type | Required or Not | Description                                          |
| ------------ | ---------- | --------------- | ---------------------------------------------------- |
| `requestId`  | `string`   | `Yes`           | The unique ID of the merchant's payment request      |
| `outTradeNo` | `string`   | `Yes`           | Merchant order number                                |
| `currency`   | `string`   | `Yes`           | Request currency (same as order currency)            |
| `amount`     | `number`   | `Yes`           | Request amount (cannot exceed the authorized amount) |

[/capture API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-capture/post) request example:

``` js
{
    "version": "1.4",
    "keyVersion": "1",
    "requestTime": "2024-11-06T11:56:13.000+08:00",
    "appId": "8f8b0895b60f41abbdb05405052971c8",
    "merchantNo": "P01010114178824",
    "data": {
        "requestId": "xxxxx",
        "outTradeNo": "xxxxxxxx",
        "currency": "USD",
        "amount": 100
    }
}
```
[/capture API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-capture/post) response example:

``` js
{
"msg": "Success.",
"code": "APPLY_SUCCESS",
"data": {
"captureNo": "20230806235954ED7856775040587834005", // PayerMax unique payment request number
"requestId":"xxxxx", // requestId accepted for this request
"outTradeNo":"xxxxxxxx",
"amount":10,
"currency":"SAR"
"status": "PENDING", // SUCCESS FAILED
"isFinal": true,
"createdTime": "2023-08-06T23:50:59 +0000",
"succeededTime": null, // Success time
"failedTime": null, // Failure time
"errorCode": null, // Failure reason
"errorMsg": null
}
}
```

When the payment request interface responds to the payment request result synchronously, the payment request status is as follows:

| Status    | Description | Remarks             |
| --------- | ----------- | ------------------- |
| `FAILED`  | Failed      | Payment failed      |
| `PENDING` | Processing  | Payment in progress |
| `SUCCESS` | Success     | Payment completed   |

::: warning Note: 
Currently **`only one`** payment request is supported, and the payment amount must be less than or equal to the grant amount. Multiple payment requests are not supported.
:::

### 7.4 Get Payment Request Result

After the payment request succeeds or fails, the payment request status notification will also be called back to the merchant's server. For the notification content, please refer to the [/captureResultNotifyUrl API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/captureResultNotifyUrl/post) interface. For the integration callback notification, please refer to the [Get Payment Result Integration](https://docs.payermax.com/en/202606-version/acquiring/start-integration/related-capabilities/payment-result.html) docking steps.

**Key Parameters**：

| Field Name   | Field Type | Required or Not | Description                  |
| ------------ | ---------- | --------------- | ---------------------------- |
| `notifyType` | `string`   | `No`            | Notification Type: `CAPTURE` |

When **`notifyType = CAPTURE`**, it is the callback for requesting payment. The example is as follows:

``` json
{
"keyVersion": "1",
"appId": "5f843bfc8cec49c2b8e9e99847325548",
"merchantNo": "P01010114418097",
"notifyTime": "2023-07-23T00:00:01 +0000",
"notifyType": "CAPTURE", // Type of payment request
"data": {
"captureNo": "20230806235954ED7856775040587834005", // paymermax unique payment request number
"requestId":"xxxxx", // requestId accepted for this request
"outTradeNo":"xxxxxxxx",
"status": "SUCCESS", // SUCCESS FAILED
"isFinal": true,
"createdTime": "2023-08-06T23:50:59 +0000",
"succeededTime": "2023-08-06T23:50:59 +0000", // Success time
"failedTime": null, // Failure time
"errorCode": null, // Failure reason
"errorMsg": null
}
}
```

### 7.5 Initiate Revocation

When initiating a cancellation, the authorization must be successful and no payment request has been initiated. You can view the [/cancel API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/aggregate-pay-api-gateway-cancel/post) interface.

Initiate a cancellation request with the original order number **`outTradeNo`**, the **key parameters** are:

| Field Name   | Field Type | Required or Not | Description                                |
| ------------ | ---------- | --------------- | ------------------------------------------ |
| `requestId`  | `string`   | `Yes`           | Unique id of merchant cancellation request |
| `outTradeNo` | `string`   | `Yes`           | Merchant order number                      |

The cancellation is a full cancellation, and there is no need to specify the amount. The following is an example:

``` json
// Input parameters
{
"version": "1.4",
"keyVersion": "1",
"requestTime": "2024-11-06T11:56:13.000+08:00",
"appId": "8f8b0895b60f41abbdb05405052971c8",
"merchantNo": "P01010114178824",
"data": {
"requestId": "xxxxx", // This request number
"outTradeNo": "xxxxxxxx", // Original order number
}
}
```

``` json
// Output parameters
{
"msg": "Success.",
"code": "APPLY_SUCCESS",
"data": {
"cancelNo": "20230806235954ED7856775040587834005", // PayerMax unique cancellation number
"requestId":"xxxxx", // requestId accepted for this request
"outTradeNo":"xxxxxxxx",
"status": "SUCCESS", // SUCCESS FAILED
"createdTime": "2023-08-06T23:50:59 +0000",
"succeededTime": null, // Success time
"failedTime": null, // Failure time
"errorCode": null, // Failure reason
"errorMsg": null
}
}
```
Calling the revocation interface will synchronously respond to the revocation result. The revocation status is:

| Status    | Description | Remarks               |
| --------- | ----------- | --------------------- |
| `FAILED`  | Failed      | Revocation failed     |
| `PENDING` | Processing  | Revoking              |
| `SUCCESS` | Success     | Revocation successful |

  
### 7.6 Get the Revocation Result

After the cancellation succeeds or fails, the cancellation status notification will also be called back to the merchant's server. The notification content can be viewed in the [/cancelResultNotifyUrl API](https://docs.payermax.com/api.html?docName=New%20Version&docVer=v1.0&docLang=en#/paths/cancelResultNotifyUrl/post) interface. For integrated callback notifications, please refer to the [Get Payment Result Integration](https://docs.payermax.com/en/202606-version/acquiring/start-integration/related-capabilities-integration/payment-result.md) docking steps.

**Key Parameters**:

| Field name   | Field type | Required or Not | Description                 |
| ------------ | ---------- | --------------- | --------------------------- |
| `notifyType` | `string`   | `yes`           | Notification type: `CANCEL` |

When **`notifyType=CANCEL`**, it is the cancellation callback:

``` json
{
"keyVersion": "1",
"appId": "5f843bfc8cec49c2b8e9e99847325548",
"merchantNo": "P01010114418097",
"notifyTime": "2023-07-23T00:00:01 +0000",
"notifyType": "CANCEL",
"data": {
"cancelNo": "20230806235954ED7856775040587834005", // PayerMax unique payment request number
"requestId":"xxxxx", // requestId accepted for this request
"outTradeNo":"xxxxxxxx",
"status": "SUCCESS", // SUCCESS FAILED
"createdTime": "2023-08-06T23:50:59 +0000",
"succeededTime": "2023-08-06T23:50:59 +0000", // Success time
"failedTime": null, // Failure time
"errorCode": null, // Failure reason
"errorMsg": null
}
}
```

## 8.  Test Go Live

The following introduces the integration test simulation rules of Auth-Capture.

### 8.1 Authorization test

For authorization test, please refer to [Start a test](https://docs.payermax.com/en/202606-version/acquiring/integration-testing-and-troubleshooting/start-a-test.md).

::: warning Note: 
Request and revocation can only be initiated after authorization is successful.
:::

### 8.2 Request test

The request interface parameter `amount` specifies the following values to mock the request result:

- `Failed`: `amount` = 500,1000,1500,2000;

- `PENDING`: `amount` = 6000,900;

- `Success`: other amounts.

### 8.3 Revocation test

The authorization interface parameter `totalAmount` specifies the following values to mock the revocation result:

- `Failed`: `amount` = 2000,2500;

- `PENDING`: `amount` = 6500;

- `Success`: other amounts.
