# CCPay Merchant Interface Document-2.2 [English Version](./) [中文版本](https://hackmd.io/JyAWrFm9QBiKdFkIVYmR2A?view) > 2.0 Updated one more payment callback, changed the original payto interface name to payback. The old version is still compatible > > 2.1 Changed the original names appKey and appSecret to businessKey and businessSecret > > 2.2 add some verification instructions and add recordid detection interface [TOC] ### Interface Domain Name Test environment: [https://paytest-api.cctip.io/](https://paytest-api.cctip.io/) Official environment: [https://pay-api.cctip.io/](https://pay-api.cctip.io/) ### Composition of Common Parameter Request Request: - header, which belongs to the `public part` of the interface: - reqId, the unique id for each request, a combination of letters and numbers. Illegal characters are not allowed, and the length should be limited to 32 characters; - platform, a robot platform, e.g. telegram; - businessKey, the only certificate of the merchant; - signature, signature information. See the Signature Method section below for the signature generation method. - body: - With the json parameters required by the corresponding interface Body example: ```json { "user_bot_id": "", "coin": { "chain_id": 0, "contract": "" }, "origin_amount": "", "backup": "" } ``` ### Public Return Structure The data returned is all in the structure of Json, and the fields are composed as follows: * errno `integer` is an error code; when it is 0, it represents a successful request * errmsg `string`, error message * data, `specific data`, defined according to different interfaces ### Types of Access Applications and Platforms Supported Merchant robot: * Telegram, the value of platform is: `telegram` CCTip·APP: - Telegram, the value of platform is: `telegram` - Twitter, the value of platform is: `twitter` - discord, the value of platform is: `discord` - reddit, the value of platform is: `reddit` - Apple, the value of platform is: `apple` ### Signature Method businessKey and businessSecret will be provided to merchants by `CCPay`: * businessKey, a key that uniquely identifies the merchant; * businessSecret key Signing steps for parameters: 1. Convert json to string in body to get A. No need for stitching if without body; 2. Be sure to use "_" to stitch them according to the following example format: `businessKey + _ + platform + _ + reqId + _ + A`. After stitching them, get Str; 3. Generate signature signature on Str with businessSecret. Don't convert the case, but save it as it is: ```json signature = base64_encode(hash_hmac('sha1', Str, businessSecret)); ``` > Note: For PHP language developers, please set the fourth parameter of the hash_hmac function, raw_output, to true URL of the online signature debugging tool:[https://1024tools.com/hmac](https://1024tools.com/hmac) ### Interface List #### 1. Get token information > The Token information returned in this interface is currently supported by CCPay. If it is not in the return list, it suggests that it is not supported. For the value of `chain_id` and `contract` in other related interfaces, please refer to this interface. The legality of the user's token recharge should also be subject to the one here, so as to prevent the token recharge attack of repeated symbols. | Router | Method | Authentification | Frequency limit | Header parameter | | :------------------- | :----- | :--------------- | :-------------- | :--------------- | | /v1/ccpay/token/list | GET | Yes | 5s/time | Yes | Parameter: * body N/A Return Failure: ```json { "data": null, "errmsg": "param invalid", "errno": 100 } ``` Success: ```json { "data": [{ "chain_id": 2, "name": "Bitcoin", "symbol": "BTC", "contract": "100000001", "decimals": 8, "platform": "twitter,wechat,telegram", "logo": "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579", "max": "0", "min": "1", "fee": "10000", "confirmed": 2, "web_site": "" }, { "chain_id": 4, "name": "Bitcoin Cash", "symbol": "BCH", "contract": "100000002", "decimals": 8, "platform": "twitter,wechat,telegram", "logo": "https://assets.coingecko.com/coins/images/780/large/bitcoin_cash.png?1547034541", "max": "0", "min": "1", "fee": "10000", "confirmed": 2, "web_site": "" }], "errmsg": "", "errno": 0 } ``` #### 2. Create a deposit order `interface maintenance` This interface allows merchants to help users generate relevant information for `on-chain` deposit. | Router | Method | Authentification | Frequency Limit | Header Parameter | | :----------------------------- | :----- | :--------------- | :-------------- | :--------------- | | /v1/ccpay/order/deposit/submit | POST | Yes | 20ms/time | Yes | Parameters: All fields, except `backup`, are required; - user_bot_id string, in the order, the id of the depositor based on the robot platform - chain_id` integer, the id of the chain where the Token is located` - `contract` string, the contract value of Token - origin_amount` string, the value to be deposited in the order, ` not a precision amplification value` ```json { "user_bot_id": "", "coin": { "chain_id": 0, "contract": "" }, "origin_amount": "2.3", "backup": "" } ``` Return: Failure: ```json { "data": null, "errmsg": "param invalid", "errno": 100 } ``` Success: * address string, the address where the user deposits the token; * fixed_amount_normal string, the value to be deposited, not a precision amplification value; * fixed_amount_big_val string, the value to be deposited, the precision amplification value; * Confirmation integer, the number of block confirmations identified in the CCTip system after the token is deposited. The deposit will be valid only after it reaches the block confirmation number; * expire_at string, the expiration time of the order, in milliseconds, which means it will expire after this time point; * record_id string, the sequence id of the order, always in 64 characters. Each successfully received order has a unique sequence id; * memo string, remarks ```json { "data": { "address": "0xA2d7Ef1C65d679c2D6770A4a356ad9A32d753396", "coin": { "amount": { "fixed_amount_normal": "2.7421", "fixed_amount_big_val": "2742100000000000000" }, "confirmation": 12, "chain_id": 1, "contract": "0x0000000000000000000000000000000000000000", "decimal": 18 }, "expire_at": "1586925482324", "record_id": "2eed99a4ed077ec4f0f3d93a8f8b95c05f962e90fff557dc7e692b2a1be3d686", "memo": "" }, "errmsg": "", "errno": 0 } ``` #### 3. Apply for withdrawal — on-chain — `interface maintenance` This interface allows merchants to withdraw their tokens for the CCTip system from the chain to the `chain address` specified by the user. | Router | Method | Authentification | Frequency Limit | Header Parameter | | :----------------- | :----- | :--------------- | :-------------- | :--------------- | | /v1/ccpay/withdraw | POST | Yes | 20ms/time | Yes | Parameteres: All fields are required - to_bot_id string, the user who the merchant wants to withdraw the corresponding Token to, the user id on the robot platform - `chain_id integer`, the id of the chain where the Token to be withdrawn is located - `contract` string, the contract value of the Token to be withdrawn` - `amount` string, the value of withdrawal, not a precision amplification value - `address`, the withdrawal address specified by the user ```json { "coin": { "chain_id": 0, "contract": "" }, "to_bot_id": "", "amount": "2.43232" } ``` Return: Failure: ```json { "data": null, "errmsg": "param invalid", "errno": 100 } ``` Success: * record_id withdrawal id ```json { "data": { "record_id": "A2d7Ef1C65d679c2D6770A4a356ad9A32d753396" }, "errmsg": "", "errno": 0 } ``` #### 4. Apply for transfer — off-chain This interface allows merchants to transfer their Token assets to designated users. Please note that the payback interface here is not the same as the `payto` command to deposit tokens in the `cctip_bot` robot private chat interface. | Router | Method | Authentification | Frequency Limit | Header Parameter | | :---------------- | :----- | :--------------- | :-------------- | :--------------- | | /v1/ccpay/payback | POST | Yes | 20ms/time | Yes | Parameters: All parameters, unless otherwise specified, are required > Fill in either `to_bot_id` or `to_sys_id` below. If both are filled in, `to_sys_id` should prevail. * to_bot_id string, the user who the merchant wants to withdraw the corresponding Token to, the user id on the robot platform * to_sys_id string, the user who the merchant wants to withdraw the corresponding Token to, the user id on the cctip system * `chain_id` integer, the id of the chain where the Token to be withdrawn is located * `contract` string, the contract value of the Token to be withdrawn * `amount` string, the value of withdrawal, `not a precision amplification value` * `order_id` is an optional parameter. Ccpay will record it, if any. When the request is successfully processed by this interface, the order_id is no longer available. A replay error will be returned. ```json { "coin": { "chain_id": 0, "contract": "" }, "to_bot_id": "", "amount": "2.43232", "order_id": "xxxxxx" // optimal } ``` Return: Failure: ```json { "data": null, "errmsg": "param invalid", "errno": 100 } ``` Success: * record_id withdrawal id ```json { "data": { "record_id": "A2d7Ef1C65d679c2D6770A4a356ad9A32d753396" }, "errmsg": "", "errno": 0 } ``` #### 5.Check merchant balance This interface allows merchants to query the Token balance of their merchant account in the CCTip system. | Router | Method | Authentification | Frequency Limit | Header Parameter | | :------------------------- | :----- | :--------------- | :-------------- | :--------------- | | /v1/ccpay/business/balance | POST | Yes | 20ms/time | Yes | Parameters: All parameters are required - chain_id integer, the id of the chain where the Token to be queried is located - If chain_id is 0, the balance of all currencies will be returned - contract string, the contract value of the Token to be queried ```json { "chain_id": 0, "contract": "" } ``` Failure: ```json { "data": null, "errmsg": "param invalid", "errno": 100 } ``` Success: - confirmed represents the confirmed balance; - balance is a precision amplification value - price is the current market price of the token, in `US$/unit` - unconfirmed is to be confirmed - locks are locked ```json { "data": { "confirmed": [ { "balance": "279006620705932878", "chain_id": 1, "contract": "0x0000000000000000000000000000000000000000", "decimals": 18, "logo": "https://raw.githubusercontent.com/BlockABC/eth-tokens/master/tokens/0x000000000000000000 0000000000000000000000/token.png", "name": "Ethereum", "price": "187.57", "symbol": "ETH" }], "unconfirmed": [ { "balance": "9006620705932878", "chain_id": 1, "contract": "0x0000000000000000000000000000000000000000", "decimals": 18, "logo": "https://raw.githubusercontent.com/BlockABC/eth-tokens/master/tokens/0x000000000000000000 0000000000000000000000/token.png", "name": "Ethereum", "price": "187.57", "symbol": "ETH" }], "locks": [ { "balance": "69006620705932878", "chain_id": 1, "contract": "0x0000000000000000000000000000000000000000", "decimals": 18, "logo": "https://raw.githubusercontent.com/BlockABC/eth-tokens/master/tokens/0x000000000000000000 0000000000000000000000/token.png", "name": "Ethereum", "price": "187.57", "symbol": "ETH" }] }, "errmsg": "", "errno": 0 } ``` #### 6. Merchants query their account's on-chain deposit address This interface allows merchants to query all chain-supported wallet addresses of their `merchant accounts` in the CCTip system. | Router | Method | Authentification | Frequency Limit | Head Parameter | | :------------------------- | :----- | :--------------- | :-------------- | :------------- | | /v1/ccpay/business/address | POST | Yes | 20ms/time | Yes | Parameters: * No parameter Failure: ```json { "data": null, "errmsg": "param invalid", "errno": 100 } ``` Success: * address is the address * chain_id corresponds to the chain id returned in the token/list interface, indicating what chain the address is on > Note: No tokens can be deposited to the address of TRON directly temporarily ```json { "errno": 0, "errmsg": "", "data": [ { "address": "0x1234...", "chain_id": 1 }, { "address": "0x1234...", "chain_id": 1 } ] } ``` #### 7. Verify the AccessToken issued by CCTip·APP This interface allows merchants to send requests in the background service to verify whether the `AccessToken` issued by `CCTip·APP` is valid. | Router | Method | Authentification | Frequency Limit | Header Parameter | | :-------------------------- | :----- | :--------------- | :-------------- | :--------------- | | /v1/ccpay/accesstoken/check | POST | Yes | 10ms/time | Yes | Parameters: All parameters, unless otherwise specified, are required * access_token ```json { "access_token": "xxxx" } ``` Return: Failure: ```json { "data": null, "errmsg": "param invalid", "errno": 100 } ``` Success: ```json { "data": { "sys_id": "xx" // The user id of the current user in the cctip system }, "errmsg": "", "errno": 0 } ``` #### 8. Check whether the recharge order has arrived --- important This interface allows merchants to send a request in the background service to check whether the charging order corresponding to recordid has been recorded. Since October 8, 2020, although the call back notification office has been able to ensure that the recharge will be returned only after the account is reached, it is recommended that the merchant check the recordid with this interface when receiving the callback or other necessary time! > Note: the best time to call the interface is within minutes after receiving the callback. If it is called after a long time, the result of the order expiration may be obtained. | Router | Method | Authentification | Frequency Limit | Header Parameter | | :-------------------------- | :----- | :--------------- | :-------------- | :--------------- | | /v1/ccpay/record/check | POST | Yes | 20ms/time | Yes | Parameters: All parameters, unless otherwise specified, are required * record_id ```json { "record_id": "Returned by callback `record_id`" } ``` Return: Failure: ```json { "data": null, "errmsg": "param invalid", "errno": 100 } ``` Success: ```json { "data": { "record_id": "xx" // return the same }, "errmsg": "", "errno": 0 } ``` #### 9. Deposit/ withdrawal callback The deposit / withdrawal callback includes the following four scenarios: 1. When the user successfully deposits the Token on the chain to the merchant through the order information, CCPay will inform the merchant; 2. When the tokens withdrawn by the merchant for the user on chain are credited to the account; 3. When the user deposits tokens to the telegram robot of the merchant using the payto command inCCTip in CCTip's telegram robot; 4. The user opens the merchant's application in the CCTip APP and deposits the Token to the merchant; 5. When the merchant has insufficient credit line for a certain token in CCTip, CCTip will notify the merchant. --- To receive callbacks from CCPay, the merchant must provide an interface that meets the following requirements. CCPay will call the following interface then. 1. Link: `{host}/ccpay/notify`, `host` is the service domain name of the merchant, not in ip format: 1. Legal example: `ccpay.cctip.io/v1/` 1. Illegal example: `47.23.44.252:81` 2. Method: `POST`header: 3. Requested parameters: 1. header: 1. reqId. See the description in the `Composition of Public Parameter Requests for analysis`; 2. signature, signature information. See 4 for the signature generation method. 2. json of body: 1. Types of type callback: 1. The value is 1, corresponding to Scenario 1 above; 2. The value is 2, corresponding to Scenario 2 above; 3. The value is 3, corresponding to Scenario 3 above; 4. The value is 4, corresponding to Scenario 4 above; 5. The value is 5, corresponding to Scenario 5 above. 2. Record_id corresponds to the operation stream id, and is set for account checking; 3. tx_hash corresponds to the hash value on the chain of the deposit transaction. When it is not operated on the chain, it will be an empty string; 4. The data body of attach: - For Types 3 and 4, the internal data is as follows: - action, action, income string for the time being - amount, value, the precision reduction value - app_id. The app id of the merchant when type = 4 - backup. Currently, only when type = 4 can it have a value. It corresponds to the value of the nonce field when the merchant accesses the `CCTip·APP` interface. It is transparently transmitted. - chat_id. The chat id, produced by the third platform, may be empty - platform. The third-party platform where the user is located. This field will only appear when type = 4. Note that it appears, not as an empty string - message_id. The message id, produced by a third-party platform, may be empty - sys_id. The id of the user who triggered the relevant operation on CCTip - timestamp. The timestamp when the operation is executed, in seconds - token_name. Token name - user_id. The id of the user who triggered the relevant operation on a third-party platform. If it is a CCTip APP user, it corresponds to the sns_id provided by the CCTip APP - username. The user name based on a third-party platform - When the type is `5`, the internal data is analyzed as follows: - left_value, the remaining credit line; - debt_value, the credit line of the debt; - timestamp, the timestamp of the credit prompt, in seconds. ​ 5. Tip: To uniquely determine a user based on `user_id`, it is advised to combine the `platfrom` parameter. ```json { "coin": { "chain_id": 1, "contract": "0x000..." }, "record_id": "abc234...", "type": 3, "tx_hash": "0x123456...", "attach": { "action": "income", "amount": "1", "app_id": "xxxx", "backup": "yyyy", "chat_id": -12334, "message_id": "2324", "platform": "telegram", // This field is only available when type = 4 "sys_id": "xxxx", "timestamp": 123242343, "token_name": "ETH", "user_id": "14214", "username": "lin_m" } } ``` ```json { "coin": { "chain_id": 1, "contract": "0x000..." }, "record_id": "", "type": 5, "tx_hash": "", "attach": { "debt_value": "0.02", "left_value": "0.005", "timestamp": 123242343 } } ``` 4. Signature method: 1. The json in the body is serialized to bytes; 2. Convert bytes to string to get A; 3. Use "_" to stitch `reqId + _ + A `to get Str; 4. Generate signature `signature` on Str with the businessSecret of the merchant: 5. What the merchant needs to do: 1. Detect the uniqueness of reqId to avoid `replay attacks`; 2. Verify the signature. After receiving the request parameters, generate the signature` signature_2` with your own businessSecret according to Step 4, and then compare signature == signature_2. If they are consistent, then the request information has not been tampered with. 6. Signature code example: ```plain signature = base64_encode(hash_hmac('sha1', Str, businessSecret)); ``` 7. Regardless of the merchant’s processing results, upon the receipt of the callback request, a response with `httpCode` of `200` must be returned to CCPay ### Order callback retry mechanism When CCPay calls back the merchant’s `notify` interface, if the returned response has a httpCode other than 200, then CCPay will consider the request to be unreachable. It will store the request information, and then make the next call `strategically`. All request information will be the same, including reqId. If the same callback still fails after a certain number of retries, CCPay will` record` and `discard` the callback. ### Error Code List | Value | Description | | :---- | :----------------------------------------------------------- | | 20 | The AccessToken issued by CCTip·APP has expired or is illegal | | Value | Description | | :---- | :----------------------------------------------------------- | | 100 | Parameter error | | 101 | CCPay internal service error | | 102 | Failed to verify signature | | 103 | Interface access limit | | 104 | Request replay | | 105 | Unsupported platform | | 106 | Parameter error | | 110 | Insufficient transfer balance | | 112 | The merchant withdraws tokens to the user, and orderld replays | | 120 | The deposit order does not exist | | Value | Description | | :---- | :----------------------------------------------------------- | | 145 | recordId overdue | | 146 | recordId not exist | | Value | Description | | :---- | :----------------------------------------------------------- | | 157 | Withdrawal parameter error | | 158 | Internal error of withdrawal system | | 159 | Insufficient withdrawal balance | | 160 | Unsupported token withdrawn | | 161 | Insufficient withdrawal fee | | 162 | TRON chain. The withdrawal address cannot be an address that has not been created yet | | 163 | TRON chain. The withdrawal address cannot be your own address. | | 164 | The record of application for withdrawal does not exist | | 165 | On-chain withdrawal function is under maintenance | | Value | Description | | :---- | :----------------------- | | 200X | Database operation error |