# Pay Interface

### Request for explanation

* This document is for partners who have applied for the channel number channelId and private key at us.
* Partner requirements: Provide channel name, register account.

### Process Chart

![](/files/-LbWFe-c3YKb4ajI-dcf)

![](file://D:/work/swftcoin/swft-h5/swft-api/images/swftpay.png?lastModify=1554262336)

#### Access process：

&#x20;① The developer calls us to create a payment order procotol and creates a payment order;

&#x20;② Our link that returns to the payment page, and the user makes a payment;

&#x20;③ to obtain payment results, the following two ways are doable: a. The developer provides a payment completion notification protocal, and after the user completes the payment, we call the protocal to notify; b. The developer can take the protocol of order status to get the status of the order payment result.

### Protocol list

| Request type          | Request method            | Description               |
| --------------------- | ------------------------- | ------------------------- |
| POST application/json | api/pay/createPayOrder    | Create a payment order    |
| POST application/json | api/pay/queryPayOrder     | Check order status        |
| POST application/json | Provided by the developer | Payment completion notice |

#### Create a payment order

#### api/pay/createPayOrder

#### Explanation

The partner calls the protocol to create a payment order.

#### Request parameter

| Parameter name | Is it necessary | Type of data | description             | Defaults | Ranges                               |
| -------------- | --------------- | ------------ | ----------------------- | -------- | ------------------------------------ |
| channelId      | Y               | String       | Channel number          |          | Provided by us，eg：payaaa201903212028 |
| channelName    | Y               | String       | Channel short name      |          | eg：xxMall                            |
| sign           | Y               | String       | Signature               |          | See "Signature Generation"           |
| timestamp      | Y               | Long         | Timestamp               |          | Millisecond timestamp                |
| channelOrderId | N               | String       | Channel order number    |          | Developer customization              |
| channelUserNo  | N               | String       | Channel username        |          | Developer customization              |
| coinCode       | Y               | String       | Payment currency name   |          | eg：ETH                               |
| amount         | Y               | String       | Payment currency amount |          | eg：1                                 |
| remark         | N               | String       | Remark                  |          | Remark of order                      |

#### Response parameter

```
 {
     "data": {
         "amount": "2",
         "channelOrderId": "channelorder001",
         "channelUserNo": "xxMall_zhangsan",
         "coinCode": "ETH",
         "payId": "jpedyB3T",
         "payUrl": "https://test.swftcoin.com/swft-v3/PayAPI.html?payID=jpedyB3T",
         "remark": "zhangsan pay to xxMall"
     },
     "resCode": "800",
     "resMsg": "success"
 }
```

#### data explanation

```
 {
     "amount": "Payment currency amount",
     "channelOrderId": "Channel order number",
     "channelUserNo": "Channel username",
     "coinCode": "Payment currency name",
     "payId": "Payment order number",
     "payUrl": "Payment page link",
     "remark": "Remark"
 }
```

#### Payment order status

#### api/pay/queryPayOrder

#### Explanation

Payment order status protocol

#### Request parameter

| Parameter name | Is it necessary | Type of data | description          | Defaults | Ranges                     |
| -------------- | --------------- | ------------ | -------------------- | -------- | -------------------------- |
| payId          | Y               | String       | Payment order number |          | eg : Nlt0OnQP              |
| channelId      | Y               | String       | Channel number       |          | eg：payaaa201903212028      |
| sign           | Y               | String       | Signature            |          | See "Signature Generation" |
| timestamp      | N               | String       | Timestamp            |          | Millisecond timestamp      |

#### Response parameter

```
 {
     "data": {
         "amount": "2",
         "channelId": "payaaa201903212028",
         "channelName": "xxMall",
         "coinCode": "ETH",
         "createTime": "2019-03-22 17:11:38",
         "payId": "XMdqbM8Q",
         "remark": "zhangsan pay to xxMall",
         "sign": "DB99639E8B9EC419F88C94355DF1C483ACD420B7366C27CAB8E86A6D7B84CB52",
         "status": "complete",
         "timestamp": 1553838107450,
         "transType": "PAY_IN",
         "userNo": "5****@qq.com"
     },
     "resCode": "800",
     "resMsg": "success"
 }
```

#### data explanation

```
   {
     "amount": "Payment currency amount",
     "channelOrderId": "Channel order number",
     "channelUserNo": "Channel username",
     "coinCode": "Payment currency name",
     "payId": "Payment order number",
     "remark": "Remark",
     "sign": "Signature",
     "status": "Payment order status",
     "timestamp": "Millisecond timestamp",
     "transType": "Order type",
     "userNo": "Third-party channel number has not been set up yet"
   }
```

#### Order payment completion notification

#### Explanation

Order payment completion notification protocol

#### Request parameter

| Parameter name | Is it necessary | Type of data | description          | Defaults | Ranges                 |
| -------------- | --------------- | ------------ | -------------------- | -------- | ---------------------- |
| payId          | Y               | String       | Payment order number |          | eg: Nlt0OnQP           |
| status         | Y               | String       | Payment order status |          | valid，complete，invalid |
| sign           | Y               | String       | Signature            |          |                        |
| timestamp      | Y               | String       | Timestamp            |          | Millisecond timestamp  |

#### Response parameter

```
 {
     "data": “Response completed”,
     "resCode": "800",
     "resMsg": "success"
 }
```

#### data explanation

```
 {
     "data": “response info”,
     "resCode": "Return status code",//800: indicates success, others indicate failure
     "resMsg": "Return result information"
 }
```

### Error code description

#### Return data resCode code

| Error code | Explanation                                                       |
| ---------- | ----------------------------------------------------------------- |
| 800        | Success                                                           |
| 900        | Servers busy, please try later                                    |
| 213        | Illegal Request                                                   |
| 214        | Currency does not exist                                           |
| 216        | Amount illegal                                                    |
| 907        | Required field is empty                                           |
| 1002       | Order doesn’t exist                                               |
| 1017       | Third-party channels or account does not exist                    |
| 1018       | Third-party channels have not been set up on the account.         |
| 1019       | Third-party channel number has not been set up yet.               |
| 1031       | The note is longer than 50 characters                             |
| 1032       | Third-party channel payment page address has not been set up yet. |

### Generate signature

The parameter names are sorted according to the order of the ASCII code, converted into a json string, signed with a private key, and HMAC-SHA256 encryption should be used.

#### Signature generation step description

**First step：**

Let's assume all the data sent or received to be the set M, and sort the parameters of the non-empty parameter values in the set M according to the parameter name ASCII code from small to large (dictionary order), using the format of the URL key-value pair (ie key1=value1\&key2=value2) ...) stitched into a string stringA.

**Pay special attention to the following important rules：**

1. The parameter name ASCII code is sorted from small to large (dictionary order);
2. app\_id, timestamp is a required parameter; timestamp is the last five minutes timestamp, which is invalid for more than 5 minutes;
3. If the value of the parameter is null, it does not participate in the signature;
4. Parameter names are case sensitive;
5. The transmitted sign parameter does not participate in the signature, and the generated signature will be checked based on the sign value.

**The Second step：**

The string is finally stitched to get the stringSignTemp string, and the stringSignTemp is programmed according to HMAC-SHA256, and then all the characters of the obtained string are converted to uppercase, then the signvalue is set.

**Pseudo code example**

Assume that the parameters transmitted are as follows： channelId: mttest timestamp : 1516320000 body : test

```
 First step: The parameters are sorted according to the key=value format and sorted according to the parameter name ASCII dictionary order as follows：
 stringA="app_id=mttest&body=test&timestamp=1516320000";
 The second step: splicing the API key:
 stringSignTemp=stringA+"&secret=my_test_secret" 
 sign=hash_hmac("sha256",stringSignTemp,key).toUpperCase()="6A9AE1657590FD6257D693A078E1C3E4BB6BA4DC30B23E0EE2496E54170DACD6" //Note: HMAC-SHA256 signature method"    
```

**Code example**

```
     @Test
     public void deductBalance() throws IOException {
         JTextField field ;
         String url = "http://localhost:8088/channel/deductBalance";
         TreeMap<String,Object> params = Maps.newTreeMap();
         params.put("orderId","my_order_id");
         params.put("channelId","test91021071617412");
         long timestamp = System.currentTimeMillis();
         params.put("timestamp",timestamp);
         String channelSign = getChannelSign(params, secret);
         params.put("sign",channelSign);
         System.out.println(url);
         System.out.println(JSON.toJSONString(params));
         String result = HttpUtils.sendRequestBody(url, params);
         System.out.println(result);
     }
 ​
     public static String getChannelSign(Map<String, Object> params,String secret) {
         StringBuilder result = new StringBuilder();
         if (params != null) {
             for (Object key : params.keySet()) {
                 Object value = params.get(key);
                 result.append(key).append("=").append(value).append("&");
             }
             String tempString = result + "secret=" + secret;
             try {
                 System.out.println(tempString);
                 String sign = EncryptUtils.sha256_HMAC(tempString, secret).toUpperCase();
                 System.out.println(sign);
                 return sign;
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
         return null;
     }
```

> The parameters and order in which the code participates in encryption are：`channelId=test91021071617412&orderId=my_test_id&timestamp=1547987604644&secret=my_secret`


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs-swft.en.swft.pro/pay-api/swft-pay-interface.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
