**钥匙库 Keeper** 是 Token 应用系统的私钥管理服务,类似于手机加密货币钱包,提供生成、保存私钥和签名的服务,Keeper 以 Docker 镜像部署于业务系统的内部环境,并通过接口进行内网访问,通过加密等防护措施确保私钥安全。具体接口如下:
[TOC]
## 演示环境
接口地址:https://47.104.196.35/bwallet/……
目前测试环境中使用的种子为:
~~~
"mnemonic": "donate hedgehog exit connect fly cargo velvet basic portion injury vehicle juice",
"seed": "f0a09a464d5c6d7af067841efc5d475f53f58fcb39b87716506a713b9fdb865e4391fd9457de77be98e45f487c3a02f23408859c63124e40a8078ae758e6e6e5"
~~~
虽然可以使用 generateseed 接口无限制的生成种子,但是一旦某种子被启用,在后继的生成私钥的操作中,该种子不可变更。除非清空数据库才可以重新启用新的种子,派生新的私钥。
## 接口
### 1. 生成种子
<span id="api00"></span>
接口名称:/api/v2/generate_seed
请求方法:GET
响应类型:JSON
状态:有效
接口描述:向私钥管理服务请求生成密钥种子,一旦使用了某密钥种子,请妥善保存该种子,可以将其记录与纸质文件或U盘中,由重要的人保管!
~~~[api:keeper]
get:/api/v2/generate_seed
<<<
success
{
"code": 0,
"data": {
"mnemonic": "supply disagree case say pipe unit use raw test faith mistake hole",
"seed": "05e8585bb7d5f6a3a7059c17c6213a980a34619edfe46b858553556e2c79041e8a30f8e1abd23ed27b7b60f0c34b1575cab254c67b8e9d9fcbf9439c1516e59a"
}
}
~~~
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| mnemonic | string | 种子助记词 |
| seed | string | 种子 |
### 2. 批量生成地址
<span id="api01"></span>
接口名称:/api/v2/generate_keys
请求方法:POST
响应类型:JSON
状态:有效
接口描述:向私钥管理服务请求生成新的私钥,私钥加密保存在内网,返回对应的公钥和地址,这里生成的地址都是未分配使用的。私钥的加密是定期更新的,确保即使加密被破解,也仅仅会影响一段时间的安全性。
~~~[api:keeper]
post:/api/v2/generate_keys
*string:seed#生成私钥所需要的种子
*number:amount#新生成地址数量
string:network_id#1:测试网络(缺省),4:正式网络
<<<
success
{
"code": 0,
"data": [
{
"pubKey": "f25fad5ae82804d3e990af6a1b5379dabae5fafd5f26a5295f6cbfc2b33e8989b896192bf14be8c0b2bab184242bc569bccfae224b511a65fd1c51c4f85a96d8",
"address": "AUUk3GpbpZum_B5YKLGgQT3FhaXNbN0QGA",
"index": 0
},
{
"pubKey": "483c5cb5d57bbe2b8223548269dd65d7f9c8d2ceb7b8afa8fa7da7a27960475db45be102e5aa396600d12f1864b2bc6e1c7d5601a37acf28f4c0444de02fe61b",
"address": "AfdIP-Gy32OQztxT1iimiWBBHGcbxecG0A",
"index": 1
},
{
"pubKey": "29b20d5a0e9523a78525698b3d2506e3091630f0a32f0ee86cc95cff7d4aec4258f207e25d3e0286a5c38234a73154f26be8056e5e757e8582dc47da8199e857",
"address": "AYRhYtOjRmQ_VXFDZPihkQcZB4Za2fjByg",
"index": 2
},
{
"pubKey": "2fa3b60b50a587af844c6daefb084c37796b41c85600bdf2f07d7511a00227aeffd0f756e4a734dfbbbd58f31451c1e5d2f20b135341b66662ccf47bacb880ce",
"address": "Admlc1WtfTi2ygjoS-_zNHiWSrTUcE3EoA",
"index": 3
},
{
"pubKey": "3a0d1e5f9aec94c91acb9432f2fa993bea017b38ca95da6d3a975b99f1aead4e300adc8622d9ea3fe262653915b944d3190e8790d722568286e08908351f4733",
"address": "AVXND9zP2cX2RABbMiTj0ON5jmKBTHYvCw",
"index": 4
}
],
"msg": "success"
}
<<<
error
{
"code": 5000,
"msg": "系统异常"
}
~~~
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| pubKey | string | 地址公钥 |
| address | string | 地址 |
| index | integer | 地址索引 |
### 3. 获取 1 个未使用的地址
接口名称:/api/v2/get_unused_key
请求方法:POST
响应类型:JSON
状态:有效
接口描述:申请一个未使用的地址公钥对
~~~[api:keeper]
post:/api/v2/get_unused_key
<<<
success
{
"code": 0,
"data": {
"pubKey": "f7fd57df8a840a26af0cd5671af737d78bfd183a286ea926015a06933a31646b1b6e81976882a245d34a907d0e898580fda242c27cdc16123d8adedb83b400d8",
"address": "AdkELJpYcCk4U5QCAit1t54OtasEBH8wtw",
"index": 14
}
}
<<<
error
{
"code": 5000,
"msg": "系统异常"
}
~~~
** 返回第一个未使用的地址公钥对, "pubKey"为公钥, "address"为对应地址, "index"为索引, 该地址返回后, keeper内部将标示其为已使用. 如果没有可用的地址, "data"为 {} **
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| pubKey | string | 地址公钥 |
| address | string | 地址 |
| index | integer | 地址索引 |
### 4. 获取未使用的地址数量
接口名称: /api/v2/get_unused_key_count
请求方法:GET
响应类型:JSON
状态:有效
接口描述:返回keeper内部未使用的地址公钥对数量
~~~[api:keeper]
get:/api/v2/get_unused_key_count
<<<
success
{
"code": 0,
"data": {
"count": 11
}
}
<<<
error
{
"code": 5000,
"msg": "系统异常"
}
~~~
** 返回未使用的地址公钥对数量**
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| count | int | 未使用地址数量 |
### 5. 事务签名(指定公钥)
接口名称:/api/v2/sign_by_key
请求方法:POST
响应类型:JSON
请求数据类型: application/json
状态:有效
接口描述:指定由公钥对应的私钥对未签名事务 hash 进行签名,返回签名
~~~[api:keeper]
post:/api/v2/sign_by_key
string:hash#待签名事务hash(32字节,编码后为64字符)
string:pub_key#服务端使用参数所指定公钥对应的私钥进行签名
<<<
success
{
code: 0,
data: {
"signed_hash" : "f62a74dd5c55e2dc4af650654348b6884bf6b08a2fbb59f424c1ddcfa3974fb49c281fb2aafa7394f0bc20e84866a1094bd9d9ea7ab11a7d91b610855e312764,de67efffc14cc1b2f0bc3bec5f993471f1fa9c411b90249b60511ed960041abb445d49711168315d01ef20a842675f9c89f9a14839d1f093fa934ac9f008f85a"
}
}
<<<
error
{
code: 4100,
msg: '签名服务已关闭'
}
~~~
** 返回数据里"signed_hash"即为签名成功后的数据, 如果公钥不合法,或者签名服务已关闭,则将返回错误信息 **
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| signed_hash | string | 签名数据 |
### 6. 事务签名(指定地址)
接口名称:/api/v2/sign_by_addr
请求方法:POST
响应类型:JSON
请求数据类型: application/json
状态:有效
接口描述:指定由参数所指定地址对应的私钥对未签名事务 hash 进行签名,返回签名
~~~[api:keeper]
post:/api/v2/sign_by_addr
string:hash#待签名事务 hash(32 字节,编码后为 64 字符)
string:address#服务端使用该地址对应的私钥进行签名
<<<
success
{
code: 0,
data: {
"signed_hash" : "f62a74dd5c55e2dc4af650654348b6884bf6b08a2fbb59f424c1ddcfa3974fb49c281fb2aafa7394f0bc20e84866a1094bd9d9ea7ab11a7d91b610855e312764,de67efffc14cc1b2f0bc3bec5f993471f1fa9c411b90249b60511ed960041abb445d49711168315d01ef20a842675f9c89f9a14839d1f093fa934ac9f008f85a"
}
}
<<<
error
{
code: 4200,
msg: '系统异常'
}
~~~
** 接口返回数据里"signed_hash"即为签名成功后的数据, 如果地址不合法,或者签名服务已关闭,则将返回错误信息 **
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| signed_hash | string | 签名数据 |
### 7. 设置系统参数
接口名称:/api/v2/set_params
请求方法:POST
响应类型:JSON
请求数据类型: application/json
状态:有效
接口描述:设置系统的运行时参数,用于限制是否可以签名,黑白地址名单等,这里设置的黑白名单将清除服务端原有的黑白名单设置。
~~~[api:keeper]
post:/api/v2/set_params
number:sign_count#签名数,目前 <= 0 关闭签名服务 > 0 开启签名服务
string:blacklist#白名单数组(数组字符串需要经过编码处理:[],等数组里的特俗字符)
string:whitelist#黑名单数组(数组字符串需要经过编码处理:[],等数组里的特俗字符)
<<<
success
{
code: 0,
msg: 'success'
}
<<<
error
{
code: 4500,
msg: '系统异常'
}
~~~
参数示例:
```
{
sign_count: 1,
blacklist: [{"pub_key": "89c114d91fad38a04a4b0ecc682e7b87bf5e386869c183cac5052c0d8852b1aae139595e811ce95ab93b6a05d3687206f839f13dce0bc27d6334ac918bcfb5f7", "address": "AZvnLUhQSmyE0t-sWTacMdu4ldnsE66mrA"}],
whitelist: [{"pub_key": "23e484676e5c783afa8fd4a8fa8783f965d7954649419ed6659e6f6a1796646e97235464d96a137c016f9f2442f8443057fad5208765a0faff8140b1e4f385ac", "address": "ASYJcGipUeKzHxxnILy7T9v8nFZlRAK_gw"}]
}
```
### 8. 黑名单操作
接口名称:/api/v2/operate_black_list
请求方法:POST
响应类型:JSON
请求数据类型: application/json
状态:有效
接口描述:对黑名单进行操作
~~~[api:keeper]
post:/api/v2/operate_black_list
string:action#动作(add、remove、get)
string:keypairs#公钥地址对数组(数组字符串,特殊字符需要经过编码处理 )
<<<
success
{
code: 0,
msg: 'success'
}
<<<
error
{
code: 4600,
msg: '系统异常'
}
~~~
参数示例:
- 新增黑名单
```
{
action: 'add',
keypairs: [{"pub_key": "89c114d91fad38a04a4b0ecc682e7b87bf5e386869c183cac5052c0d8852b1aae139595e811ce95ab93b6a05d3687206f839f13dce0bc27d6334ac918bcfb5f7", "address": "AZvnLUhQSmyE0t-sWTacMdu4ldnsE66mrA"}]
}
```
- 移除黑名单
```
{
action: 'remove',
keypairs: [{"pub_key": "89c114d91fad38a04a4b0ecc682e7b87bf5e386869c183cac5052c0d8852b1aae139595e811ce95ab93b6a05d3687206f839f13dce0bc27d6334ac918bcfb5f7", "address": "AZvnLUhQSmyE0t-sWTacMdu4ldnsE66mrA"}]
}
```
- 获取黑名单
```
{
action: 'get'
}
```
### 9. 白名单操作
接口名称:/api/v2/operate_white_list
请求方法:POST
响应类型:JSON
请求数据类型:application/json
状态:有效
接口描述:对白名单进行操作
~~~[api:keeper]
post:/api/v2/operate_white_list
string:action#动作(add、remove、get)
string:keypairs#公钥地址对数组(数组字符串,特殊字符需要经过编码处理 )
<<<
success
{
code: 0,
msg: 'success'
}
<<<
error
{
code: 4700,
msg: '系统异常'
}
~~~
参数示例:
- 新增白名单
```
{
action: 'add',
keypairs: [{"pub_key": "89c114d91fad38a04a4b0ecc682e7b87bf5e386869c183cac5052c0d8852b1aae139595e811ce95ab93b6a05d3687206f839f13dce0bc27d6334ac918bcfb5f7", "address": "AZvnLUhQSmyE0t-sWTacMdu4ldnsE66mrA"}]
}
```
- 移除白名单
```
{
action: 'remove',
keypairs: [{"pub_key":"89c114d91fad38a04a4b0ecc682e7b87bf5e386869c183cac5052c0d8852b1aae139595e811ce95ab93b6a05d3687206f839f13dce0bc27d6334ac918bcfb5f7", "address": "AZvnLUhQSmyE0t-sWTacMdu4ldnsE66mrA"}]
}
```
- 获取白名单
```
{
action: 'get'
}
```
### 10. 获取地址使用状态
接口名称:/api/v2/export_keys
请求方法:GET
响应类型:JSON
状态:有效
接口描述:导出私钥管理服务系统中的的私钥被使用的数量以及总数等信息。由外部调用,用于定期备份密钥状态
~~~[api:keeper]
get:/api/v2/export_keys
<<<
success
{
"code": 0,
"data": [
{
"used": 10,
"total": 32,
"pubkey": "89c114d91fad38a04a4b0ecc682e7b87bf5e386869c183cac5052c0d8852b1aae139595e811ce95ab93b6a05d3687206f839f13dce0bc27d6334ac918bcfb5f7"
}
]
}
<<<
error
{
"code": 5000,
"msg": "系统异常"
}
~~~
** 接口返回数据里"used"为已使用的私钥的数量,"total"为总的私钥数量,"pubkey"为total对应的公钥的值,如果签名服务已关闭,则将返回错误信息 **
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| used | integer | 已使用的私钥的数量 |
| total | integer | 总的私钥数量 |
| pubkey | string | total对应公钥 |
### 11. 恢复密钥
接口名称:/api/v2/import_keys
请求方法:POST
响应类型:JSON
请求数据类型:application/json
状态:有效
接口描述:通过输入种子和外部备份的密钥状态信息,可以恢复导出密钥状态时的密钥状态情况。当服务异常、升级等情况下可以用来恢复数据
**请求参数**
~~~
{
"seed":"38627b052f6ac556cc09e0812f272b37f2f4036b1af919b79f9c93ed6ba17d0938280b72aa3749da30e9cae7a7b79c72f57204a7730283dfc3ba000e33bc3510",
"used":1,
"total":1,
"pubkey":"d82677732d9fdb46265e0f80c2086770e792e5e2a497271e47b623a24bb6bc907ce2dcddc0d0510dd452ef384a30ef733e805a04273be34d449bd55d1874a101"
}
~~~
~~~[api:keeper]
post:/api/v2/import_keys
string:seed#种子字符串
int:used#使用过的密钥数
int:total#总共的密钥数
string:pubkey#total对应的公钥
<<<
success
{
"code": 0,
"data": [
{
"pubKey": "f25fad5ae82804d3e990af6a1b5379dabae5fafd5f26a5295f6cbfc2b33e8989b896192bf14be8c0b2bab184242bc569bccfae224b511a65fd1c51c4f85a96d8",
"address": "AUUk3GpbpZum_B5YKLGgQT3FhaXNbN0QGA",
"index": 0
},
{
"pubKey": "483c5cb5d57bbe2b8223548269dd65d7f9c8d2ceb7b8afa8fa7da7a27960475db45be102e5aa396600d12f1864b2bc6e1c7d5601a37acf28f4c0444de02fe61b",
"address": "AfdIP-Gy32OQztxT1iimiWBBHGcbxecG0A",
"index": 1
},
{
"pubKey": "29b20d5a0e9523a78525698b3d2506e3091630f0a32f0ee86cc95cff7d4aec4258f207e25d3e0286a5c38234a73154f26be8056e5e757e8582dc47da8199e857",
"address": "AYRhYtOjRmQ_VXFDZPihkQcZB4Za2fjByg",
"index": 2
},
{
"pubKey": "2fa3b60b50a587af844c6daefb084c37796b41c85600bdf2f07d7511a00227aeffd0f756e4a734dfbbbd58f31451c1e5d2f20b135341b66662ccf47bacb880ce",
"address": "Admlc1WtfTi2ygjoS-_zNHiWSrTUcE3EoA",
"index": 3
},
{
"pubKey": "3a0d1e5f9aec94c91acb9432f2fa993bea017b38ca95da6d3a975b99f1aead4e300adc8622d9ea3fe262653915b944d3190e8790d722568286e08908351f4733",
"address": "AVXND9zP2cX2RABbMiTj0ON5jmKBTHYvCw",
"index": 4
}
],
msg: 'success'
}
<<<
error
{
code: 5000,
msg: '系统异常'
}
~~~
** 接口返回数据里"code"为0表示正常,data为公钥地址对数组,"pubkey"为公钥,"address"为公钥对应的地址,"index"为账户索引 **
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| data | array | 公钥地址对数组 |
| pubkey | string | 公钥 |
| address | string | 地址 |
| index | integer | 地址索引 |
### 12. 根据对方公钥加密
接口名称:/api/v2/ecies_encrypt_by_address
请求方法:POST
响应类型:JSON
请求数据类型: application/json
状态:有效
接口描述:指定由参数所指定地址对应的私钥对明文加密加密数据,返回加密数据(base64编码), 此接口可用于提货信息的加密, 自己和拥有公钥双方都可以对加密串解密.
**请求参数**
~~~
{
"address":"AZSqDujzrpq--uXcD5dJgpDFWzYqmbV4rQ",
"to_pubkey": "cabb8a3a73ea4a03d025a6ac2ebbbb19a545e4fb10e791ec9b5c942d77aa20760f64e4604cdfbec665435a382a8c9bfd560c6f0fca8a2708cda302f658368b36",
"plain_text":"'{reply:"ok", orderNo: "238812132423"}'",
}
~~~
~~~[api:keeper]
post:/api/v2/ecies_encrypt_by_address
string:plain_text#待加密数据(utf8编码)
string:to_pubkey#对方的公钥(hex编码)
string:address#服务端使用该地址对应的私钥进行加密
<<<
success
{
"code": 0,
"data": {
"encrypted_base64_str": "UJNCe6+ewXCTNuQC9KOAnQR5GtrgTppdZYkpd8nTcgdZDdsqwnnmcPkl17aap+G/nmFRRK+5xQ8kNh5v2OAnvpymwaRP/TrzvN/8xo+a0HmKBLr9Z2aNfUd989RSidMJ2hQT6nivV8iMXzCyGDbnLcy0iVwAJ0aEPMQvCKynadZWC6YCq8MsncJeM0GSN+o3zkM5BvYQtbA33ZuHMFlCXvzCyRPZCrMin/qCOhz2HdxFYwWslh+eafIQMhyu6YAr4gzC+O+SgE7aDQAZUpI4107b7Tt3gclFw12ztDDeiD1bgA=="
}
}
<<<
error
{
code: 5000,
msg: '系统异常'
}
~~~
** 接口返回数据里"encrypted_base64_str"即为加密成功后的数据 **
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| encrypted_base64_str | string | 加密数据 |
### 13. 根据已加密信息加密
接口名称:/api/v2/ecies_encrypt_by_address_reply
请求方法:POST
响应类型:JSON
请求数据类型: application/json
状态:有效
接口描述:根据已经加密信息包含的上下文信息进行加,返回加密数据(base64编码), 此接口可用于商品发货后, 提货token的打回.
**请求参数**
~~~
{
"address":"AZSqDujzrpq--uXcD5dJgpDFWzYqmbV4rQ",
"old_data":"UJNCe6+ewXCTNuQC9KOAnQR5GtrgTppdZYkpd8nTcgdZDdsqwnnmcPkl17aap+G/nmFRRK+5xQ8kNh5v2OAnvpymwaRP/TrzvN/8xo+a0HmKBLr9Z2aNfUd989RSidMJ2hQT6nivV8iMXzCyGDbnLcy0iVwAJ0aEPMQvCKynadZWC6YCq8MsncJeM0GSN+o3zkM2dZw1NWruOFrCSqcVE5gpsRgp6axPLVt1jaeYRQqLKcXIQK/8VWleldytDV2MkknKxwtUqqD1PW4a6aYW0+yq/F2RXHIcgsjtqO58Wa3ptjJ5sQu90cK+tfNhL8DeVc77lSeD7DXYvnkNg0OrdbdtNb0vmdqTskMWaGWR3k0h2Q==",
"plain_text":"'{reply:"ok", orderNo: "238812132423"}'",
}
~~~
~~~[api:keeper]
post:/api/v2/ecies_encrypt_by_address_reply
string:plain_text#待加密数据(utf8编码)
string:old_data#原加密数据(base64编码)
string:address#服务端使用该地址对应的私钥进行加密
<<<
success
{
"code": 0,
"data": {
"encrypted_base64_str": "UJNCe6+ewXCTNuQC9KOAnQR5GtrgTppdZYkpd8nTcgdZDdsqwnnmcPkl17aap+G/nmFRRK+5xQ8kNh5v2OAnvpymwaRP/TrzvN/8xo+a0HmKBLr9Z2aNfUd989RSidMJ2hQT6nivV8iMXzCyGDbnLcy0iVwAJ0aEPMQvCKynadZWC6YCq8MsncJeM0GSN+o3zkM5BvYQtbA33ZuHMFlCXvzCyRPZCrMin/qCOhz2HdxFYwWslh+eafIQMhyu6YAr4gzC+O+SgE7aDQAZUpI4107b7Tt3gclFw12ztDDeiD1bgA=="
}
}
<<<
error
{
code: 5000,
msg: '系统异常'
}
~~~
** 接口返回数据里"encrypted_base64_str"即为加密成功后的数据 **
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| encrypted_base64_str | string | 加密数据 |
### 14. 解密
接口名称:/api/v2/ecies_decrypt_by_address
请求方法:POST
响应类型:JSON
请求数据类型: application/json
状态:有效
接口描述:指定由参数所指定地址对应的私钥对加密数据进行解密,返回解密密数据(utf8编码)
**请求参数**
~~~
{
"address":"AZSqDujzrpq--uXcD5dJgpDFWzYqmbV4rQ",
"encrypted_str":"UJNCe6+ewXCTNuQC9KOAnQR5GtrgTppdZYkpd8nTcgdZDdsqwnnmcPkl17aap+G/nmFRRK+5xQ8kNh5v2OAnvpymwaRP/TrzvN/8xo+a0HmKBLr9Z2aNfUd989RSidMJ2hQT6nivV8iMXzCyGDbnLcy0iVwAJ0aEPMQvCKynadZWC6YCq8MsncJeM0GSN+o3zkM2dZw1NWruOFrCSqcVE5gpsRgp6axPLVt1jaeYRQqLKcXIQK/8VWleldytDV2MkknKxwtUqqD1PW4a6aYW0+yq/F2RXHIcgsjtqO58Wa3ptjJ5sQu90cK+tfNhL8DeVc77lSeD7DXYvnkNg0OrdbdtNb0vmdqTskMWaGWR3k0h2Q==",
}
~~~
~~~[api:keeper]
post:/api/v2/ecies_decrypt_by_address
string:encrypted_str#原加密数据(base64编码)
string:address#服务端使用该地址对应的私钥进行解密
<<<
success
{
"code": 0,
"data": {
"decrypted_utf8_str": "{foo:\"aaaaaaaaaaaaaaa\",baz:10000, address: \"北京朝阳区望京西路15号楼7单元203\"}"
}
}
<<<
error
{
code: 5000,
msg: '系统异常'
}
~~~
** 接口返回数据里"decrypted_utf8_str"即为解密成功后的数据 **
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| decrypted_utf8_str | string | 解密数据 |
## shuttle接口封装
**封装提货、转账、发货、退货创建交易事务, keeper签名, 上链的接口调用**
### 1. 转账
<span id="api00"></span>
接口名称:/api/v2/tx/transfer_by_address
请求方法:POST
响应类型:JSON
状态:有效
接口描述: 构建转账事务并上链
**请求参数**
~~~
{
token_key:VCT1000
from:AcLO3hwkncntl9tTsO1-xUzEeP8SP-hYQw
to: AXhfvSAiXjSZaOqBC221BmeLGHbLLtwL5g
value:"1"
metadata:keeper transfer a token
to_pub_key:14c5fe881149bb3c79fe7012670a1106ed7e5d3745dcbea7e6687e25e38408ea0f451096bf99fe13006e7c56ad218e6e7fc20c20d2cc93ed6efeaf2d6090ff4c
}
~~~
~~~[api:keeper]
post:/api/v2/tx/transfer_by_address
*string:token_key#商品token
*string:from#token转账发起人
*string:to#token转账接收人
*string:value#token转账数量
string:metadata#交易meta信息
string:to_pub_key#加密meta所有的公钥, 该公钥需要和目标地址对应,否则转账接收者不能解密meta数据. 该参数为空,则meta信息不加密
<<<
success
{
"code": 0,
"data": {
"requestId": "5ce535a78329f30018da6bc6"
},
"msg": "create task success, the status of task will be notify"
}
~~~
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| requestId | string | 上链事务管理id |
### 2. 提货
<span id="api00"></span>
接口名称:/api/v2/tx/exchange_by_address
请求方法:POST
响应类型:JSON
状态:有效
接口描述: 构建提货事务并上链
**请求参数**
~~~
{
token_key:VCT1000
from:AcLO3hwkncntl9tTsO1-xUzEeP8SP-hYQw
value:"1"
metadata:{"out\_pickup\_no":"","consignee":"张三","cellphone":"13912345678","address":\["北京市","四环到五环之间","朝阳区","望京地区","望京SOHO T1 C座1915室"\],"zipcode":"100001"}
}
~~~
~~~[api:keeper]
post:/api/v2/tx/exchange_by_address
*string:token_key#商品token
*string:from#token提货发起人
*string:value#token提货数量
*string:metadata#提货地址信息
<<<
success
{
"code": 0,
"data": {
"requestId": "5ce535a78329f30018da6bc6"
},
"msg": "create task success, the status of task will be notify"
}
~~~
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| requestId | string | 上链事务管理id |
### 3. 发货
<span id="api00"></span>
接口名称:/api/v2/tx/deliver_by_address
请求方法:POST
响应类型:JSON
状态:有效
接口描述: 构建发货事务并上链
**请求参数**
~~~
{
token_key:VCT1000
from:AcLO3hwkncntl9tTsO1-xUzEeP8SP-hYQw
to: AXhfvSAiXjSZaOqBC221BmeLGHbLLtwL5g
value:"1"
metadata:keeper deliver a token
to_pub_key:14c5fe881149bb3c79fe7012670a1106ed7e5d3745dcbea7e6687e25e38408ea0f451096bf99fe13006e7c56ad218e6e7fc20c20d2cc93ed6efeaf2d6090ff4c,
split: 'false'
}
~~~
~~~[api:keeper]
post:/api/v2/tx/deliver_by_address
*string:token_key#商品token
*string:from#token发货发起人
*string:to#token发货接收人
*string:value#token发货数量
*string:split#是否生成新的token, 取值'true' 或者 'false'
string:metadata#交易meta信息
string:to_pub_key#加密meta所有的公钥, 该公钥需要和目标地址对应,否则发货接收者不能解密meta数据. 该参数为空,则meta信息不加密
<<<
success
{
"code": 0,
"data": {
"requestId": "5ce535a78329f30018da6bc6"
},
"msg": "create task success, the status of task will be notify"
}
~~~
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| requestId | string | 上链事务管理id |
### 4. 申请退货
<span id="api00"></span>
接口名称:/api/v2/tx/refunding_by_address
请求方法:POST
响应类型:JSON
状态:有效
接口描述: 构建客户申请退货事务并上链
**请求参数**
~~~
{
token_key:VCT1000
from:AcLO3hwkncntl9tTsO1-xUzEeP8SP-hYQw
to: AXhfvSAiXjSZaOqBC221BmeLGHbLLtwL5g
value:"1"
metadata:keeper deliver a token
to_pub_key:14c5fe881149bb3c79fe7012670a1106ed7e5d3745dcbea7e6687e25e38408ea0f451096bf99fe13006e7c56ad218e6e7fc20c20d2cc93ed6efeaf2d6090ff4c
}
~~~
~~~[api:keeper]
post:/api/v2/tx/refunding_by_address
*string:token_key#商品token
*string:from#token申请退货发起人
*string:value#token申请退货数量
string:metadata#交易meta信息
<<<
success
{
"code": 0,
"data": {
"requestId": "5ce535a78329f30018da6bc6"
},
"msg": "create task success, the status of task will be notify"
}
~~~
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| requestId | string | 上链事务管理id |
### 5. 退货
<span id="api00"></span>
接口名称:/api/v2/tx/refund_by_address
请求方法:POST
响应类型:JSON
状态:有效
接口描述: 构建退货事务并上链
**请求参数**
~~~
{
token_key:VCT1000
from:AcLO3hwkncntl9tTsO1-xUzEeP8SP-hYQw
to: AXhfvSAiXjSZaOqBC221BmeLGHbLLtwL5g
value:1
metadata:keeper deliver a token
to_pub_key:14c5fe881149bb3c79fe7012670a1106ed7e5d3745dcbea7e6687e25e38408ea0f451096bf99fe13006e7c56ad218e6e7fc20c20d2cc93ed6efeaf2d6090ff4c
}
~~~
~~~[api:keeper]
post:/api/v2/tx/refund_by_address
*string:token_key#商品token
*string:from#token退货发起人
*string:to#token退货接收人
*string:value#token退货数量
string:metadata#交易meta信息
string:to_pub_key#加密meta所有的公钥, 该公钥需要和目标地址对应,否则退货接收者不能解密meta数据. 该参数为空,则meta信息不加密
<<<
success
{
"code": 0,
"data": {
"requestId": "5ce535a78329f30018da6bc6"
},
"msg": "create task success, the status of task will be notify"
}
~~~
**返回值**
| 参数名 | 参数类型 | 描述 |
| --- | --- | --- |
| requestId | string | 上链事务管理id |
## 接口错误码汇总
```
4000: 接口请求参数错误
4100: keeper签名服务已关闭
4200: keeper签名地址不合法
4300: keeper签名公钥不合法
4400: keeper更新黑名单失败
4500: keeper更新白名单失败
4600: keeper使用错误种子生成批量生成地址
5000: 接口调用异常
```
## 接口使用示例
**获取密钥种子 seed**
该部署完成后,该接口只需要调用一次,一旦用该 seed 生成了地址后,除非恢复,后续将不能再修改,请妥善保存seed。
*使用我们提供的测试环境则不需要再调用了*
```
# curl http://127.0.0.1:8003/api/v2/generate_seed
# {
"code": 0,
"data": {
"mnemonic": "supply disagree case say pipe unit use raw test faith mistake hole",
"seed": "05e8585bb7d5f6a3a7059c17c6213a980a34619edfe46b858553556e2c79041e8a30f8e1abd23ed27b7b60f0c34b1575cab254c67b8e9d9fcbf9439c1516e59a"
}
}
```
**批量生成密钥对**
```
# curl -H "Content-Type: application/json" -X POST --data '{"seed":"6f21c9239acc5d127d9159d06bbfc656f6eba20bd3fb658105fba456f9eef4d4907e452bdc79b9f3fd0781a8375707f76270380788151866691604015e891151", "amount" : 1}' http://127.0.0.1:8003/api/v2/generate_keys
```
**返回公钥地址对, 这里生成的公钥对都是未分配的**
```
# {"code":0,"data":\[{"pubKey":"06032117d1367819cf010cdba9efd2f57c7f223c6e1fc5489e0e8cc8d547b25756ae03ca816fa9b8269f61f07915fa49b45c3f4577d8f71323f078212d4d4e61","address":"AYZe38fxK7bUivWOrBbGKb0EAraGP1I17A","index":38}\],"msg":"success"}
```
**申请一个未使用的地址**
```
# curl http://127.0.0.1:8003//api/v2/get_unused_key
```
**返回一个地址,系统内部标示其为已使用**
```
# {"code":0,"data":{"pubKey":"799f5e6ed68f90d7131ae7e82fde680cde039e705be88e34ee91b6c22974e1cb6d30ffc4d0c91657e0f530e86582935678c0f8111970a9818019b88c8343833e","address":"AWKgbWiyhRIh09PZ6-OBv46nJDEE6tTyOA","index":0}}
```
**使用公钥签名**
```
#curl -H "Content-Type: application/json" -X POST --data '{"hash":"D36BF29D562CF53F92727A8608C054D26F122611D9DF06EC923C6F7868813CC3", "pub_key" : "06032117d1367819cf010cdba9efd2f57c7f223c6e1fc5489e0e8cc8d547b25756ae03ca816fa9b8269f61f07915fa49b45c3f4577d8f71323f078212d4d4e61"}' http://127.0.0.1:8003//api/v2/sign_by_key
```
**签名后返回数据**
```
# {"code":0,"data":{"signed\_hash":"EC:01,06032117d1367819cf010cdba9efd2f57c7f223c6e1fc5489e0e8cc8d547b25756ae03ca816fa9b8269f61f07915fa49b45c3f4577d8f71323f078212d4d4e61,6dae86c6fe20af788167a53da6a0475542e65ed7362269e8d7ba7a96d235a13b2eeee041ca7d6d641714b99d67af036090b6871a4a165bcad1ca165ee461d0df:"}}
```
## Docker 容器
Keeper 服务需要部署在应用系统的服务器环境,我们提供 Keeper Docker 容器镜像。用户可在自己的服务器环境中启动一个 Keeper 容器,用户直接请求容器,Keeper 容器将提供如上的接口功能。
**如何启动一个 Keeper docker 容器(地址/私钥保存在docker容器对应外部存储中)**
```
docker run --name keeper -p 8003:8003 -d -v /opt/data:/var/lib/mysql -e PORT=8003 -e EGG_SERVER_ENV=test -e SHUTTLE_APIKEY=5a72327aafbb45fe9917938e1a9f1c4b -e SHUTTLE_SECKEY=3e2d7169f946458b92febf3140327014 -e SHUTTLE_BASE=https://shuttle.stringon.com -e MATRIX_BASE=https://matrix.stringon.com -e MYSQL_ROOT_PASSWORD=mypassword stringon/keeper:1.0.26 /apps/apj/setup.sh
```
**如何启动一个 Keeper docker 容器(地址/私钥不保存在docker容器)**
```
docker run --name keeper -p 8003:8003 -d -e PORT=8003 -e EGG_SERVER_ENV=test -e SHUTTLE_APIKEY=5a72327aafbb45fe9917938e1a9f1c4b -e SHUTTLE_SECKEY=3e2d7169f946458b92febf3140327014 -e SHUTTLE_BASE=https://shuttle.stringon.com -e MATRIX_BASE=https://matrix.stringon.com -e MYSQL_ROOT_PASSWORD=mypassword stringon/keeper:2.0.7 /apps/apj/setup.sh
```
- env:环境,test-测试环境,prod-生产环境
- /opt/data:数据保存目录(该目录自行指定)
- SHUTTLE_BASE: shuttle访问url
- SHUTTLE_APIKEY, SHUTTLE_SECKEY对应在matrix上申请
- MATRIX_BASE: matrix访问url