链克兑换开发指南

1. 文档说明

1.1 阅读对象

本文档适用于基于迅雷区块链技术,接入链克兑换的应用的企业或者个人开发人员。

1.2 版本说明

20180406 v1.0

2. 新手指南

2.1 迅雷链介绍

2.1.1 什么是迅雷链?

迅雷链(ThunderChain)是迅雷旗下网心科技创新打造了具备百万tps高并发、秒级确认能力的高性能区块链,并在此基础上,搭建了迅雷链开放平台,助力开发者快速开发、部署智能合约,企业或个人可以轻松将自己的产品和服务上链,更加便捷地开发区块链应用。

2.1.2 什么是迅雷链开放平台?

迅雷链开放平台是网心科技基于“迅雷链”倾力打造的区块链服务开放平台。开放迅雷十余年的分布式技术沉淀和上亿用户基础,共享链克生态数百万活跃人群,以高起点领跑行业,共同构建全球领先的区块链生态。

2.1.3 什么是链克兑换?

让链克口袋用户通过扫一扫或者在商户APP中跳转的方式,调起链克口袋兑换模块,轻松兑换相应服务。

2.1.4 什么是合约开放平台?

基于迅雷链,提供稳定、快速、低成本的智能合约区块链服务,支持金融、电商、游戏、社交等各种行业应用场景。助力开发者快速部署智能合约,企业可以轻松将自己的产品和服务上链,更加便捷地开发区块链应用。

2.2 如何注册账号及认证

2.2.1 开发者注册登录

个人或者企业开发者要使用链克兑换、智能合约功能前,必须先注册为平台的用户。手机号码是用户唯一标识。注册成功后,可以绑定邮箱。登录

注册流程如下:

用户注册流程

2.2.2 邮箱绑定

绑定邮箱后,方便接收消息通知,方便与官方联系。在忘记密码的情况下,可以通过邮箱重置密码。立即绑定

2.2.3 忘记密码

用户忘记密码后,无法登陆系统。可以通过手机号或者邮箱地址重置密码。

通过手机号验证重置密码

通过邮箱验证重置密码

2.2.4 个人认证

个人开发者要提交合约或者使用链克兑换功能,必须先进行个人信息认证。在进行个人认证前,请先注册为平台用户。请准备好身份证,以及身份证正反面照片(必须包含本人头像,照片清晰)。

立即认证

2.2.5 企业认证

企业开发者需要进行企业认证,认证信息包括企业名称、营业执照扫描件、法人代表身份证扫描件或者授权书扫描件。企业认证通过后,可以进行链克兑换、智能合约功能使用。

立即认证

2.3 如何创建应用

链克兑换、智能合约是和应用关联的,在使用这些功能之前,必须创建一个应用,否则不能使用这些功能。用户需要将应用信息提交开放平台审核。
应用分为两种类型,移动应用和web应用。移动应用需要提供可下载或验证的软件包。web应用必须提供可访问的网址以及网站注册信息。

创建移动应用

创建web应用

2.4 如何接入链克兑换

链克兑换

3. 开发者指南

3.1 功能说明

链克口袋APP兑换功能:接入方的移动端应用APP中调起链克兑换系统模块完成兑换的模式。 链克口袋APP扫码兑换功能:合作方自身交易系统按链克兑换协议生成兑换二维码,用户再用链克口袋应用中的“扫一扫”完成兑换的模式。 目前支持手机系统有:iOS(苹果)、Android(安卓)。

3.2 产品流程

3.2.1 综述

接入方需要按照链克口袋APP协议,由自己的后台生成订单信息,以及按照规则生成签名(该签名用于保护订单不被篡改);链克口袋将此转换成区块链上的交易信息,用户完成兑换后则该信息永久的记录到区块链上;同时为了优化接入方接入方流程,我司提供后台回调流程,用于快速通知接入方兑换流程的状态。

3.2.2 接入方APP发起兑换流程

  • 用户已安装链克口袋APP时
  1. 用户在接入方应用中选择相应服务,进入兑换环节,选择确认兑换,如图1;
  2. 进入到链克页面,调起链克兑换,出现确认兑换界面,如图2;
  3. 用户确认收款方和金额,点击立即兑换后出现输入密码界面,如图3;
  4. 输入正确密码后,链克端显示兑换结果,如图4;
  5. 点击完成,自动跳转回接入方应用中,并根据结果个性化展示订单结果。

  • 用户没有链克口袋APP时
  1. 用户在接入方应用中选择相应服务,进入兑换环节,选择确认兑换,如图5;
  2. 弹窗提示用户尚未下载链克口袋无法完成兑换,引导用户下载,如图6;
  3. 跳转至链克口袋下载页面(https://red.xunlei.com/html/guider.html)

3.2.3 链克扫码兑换功能

  1. 合作方根据自身接入方需求按链克兑换协议生成二维码,如图8;
  2. 用户打开链克口袋,使用扫码功能,扫描后进入确认兑换界面,如图9;
  3. 用户确认收款方和金额后选择兑换,输入正确密码后展示兑换结果;

3.3 接入方APP发起兑换的时序图

  1. 接入方app发起
  2. 获取prepay_id(详见链克兑换接口章节)
  3. 详见3.10如何计算签名
  4. 计算好的sign, prepay_id, callback返回给接入方app
  5. 接入方app唤起链克口袋app,协议见下面章节
  6. 链克口袋app将交易数据加密,发送到区块链后台
  7. 成功时区块链后台返回交易结果给链克口袋app
  8. 交易成功,链克口袋app把结果返回给接入方app,这里是否返回取决用户行为(用户可能按了home键)
  9. 接入方后台定期查询区块链后台
  10. 交易系统回调步骤4传过来的callback,通知交易结果,有限次回调,时间间隔递增

3.4 链克扫码兑换的时序图

  1. 业务方生成二维码
  2. 链克口袋扫描二维码获取action参数请求订单信息
  3. 业务后台返回tx-data订单信息
  4. 链克app进行兑换
  5. 区块链后台回调业务后台交易结果
  6. 业务后台主动查询交易结果

3.5 二维码格式定义

http://red.xunlei.com/html/guider.html?action= 参数 action :业务方提供,需url编码 用于链克口袋请求交易信息

3.6 回包结构

链克口袋访问action所指的url后,接入方返回的结构

// Result
{
"iRet":0,
"sMsg": "ok",
"data": {
    "tx_data": ""
  }
}

tx_data的接口如下表:

参数 类型 说明
desc string 支付标题
callback string 做url编码,后台回调链接
to string 转出链克口袋地址(全部小写)
value string 链克数量(单位 wei)
prepay_id string 预支付订单号,从区块链接口获取
service_id string 业务id,需要向网心申请service_id和签名秘钥
sign string 签名值

需要对tx_data整体做base64编码 示例:

callback=http%3A%2F%2F47.91.153.110%3A3000&desc=极速竞拍拍点充值&prepay_id=201712111442180000000377203337907978&service_id=3&sign=3b82f2275d9f84bbda82eae9bdf32fb7&to=0x8cfa8ab1ff90aa86714ffe731021f899a5ce4f35&value=10000000000000000000

对tx-data整体做base64编码

{
"iRet":0,
"sMsg": "ok",
"data": {
    "tx_data": 
      "Y2FsbGJhY2s9aHR0cCUzQSUyRiUyRjQ3LjkxLjE1My4xMTAlM0EzMDAwJmRlc2M95p6B6YCf56ue5ouN5ouN54K55YWF5YC8Jm9yZGVyX2lkPTMmcHJlcGF5X2lkPTIwMTcxMjExMTQ0MjE4MDAwMDAwMDM3NzIwMzMzNzkwNzk3OCZzZXJ2aWNlX2lkPTMmc2lnbj0zYjgyZjIyNzVkOWY4NGJiZGE4MmVhZTliZGYzMmZiNyZ0bz0weDhjZmE4YWIxZmY5MGFhODY3MTRmZmU3MzEwMjFmODk5YTVjZTRmMzUmdmFsdWU9MTAwMDAwMDAwMDAwMDAwMDAwMDA="
  }
}

3.7 接入方Android APP唤起链克口袋APP流程

  • 软件流程
  1. 添加 otcpay.jarlibs 目录.
  2. AndroidManifest.xml 中添加 PayEntryActivity
    <activity android:name="onething.otcpay.PayEntryActivity"
              android:configChanges="keyboardHidden|orientation|screenSize"
              android:exported="false"
              android:screenOrientation="portrait"
              android:launchMode="singleTop"
              android:theme="@android:style/Theme.Translucent.NoTitleBar" />
  1. 在需要支付的 Activity / Fragment 中调用 OtcPayManager.getInstance().callOtcPay(Activity context, byte[] tx_data, byte[] resource)
  2. 在对应的 Activity / Fragment 中重写 onActivityResult() 处理回调.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    OtcPayManager.OtcPayCallBack(requestCode, resultCode, data, new OtcResultCallback() {
        @Override
        public void onOtcTransferSuccess() {

        }
        @Override
        public void onOtcPaySuccess() {

        }
        @Override
        public void onOtcPayFail(int errorCode) {

        }
        @Override
        public void onOtcPayCancel() {

        }
    });
}
  • 参数说明
参数 类型 说明
tx-data byte[] Base64编码 主要包含支付的订单信息,key=value形式,以&连接
resource byte[] Base64编码 来源app, 支付成功后提示[返回XXX]
  • 参数说明
参数 类型 说明
desc string 支付标题
callback string 需要 URLEncode , 后台回调链接
to string 转入链克口袋地址
value string 链克数量 (单位 wei)
prepay_id string 预支付订单号
service_id string 业务 id, 找交易中心申请 service_id 和签名密钥 (后台获取). 预留字段
sign string 签名值
  • APP回调说明 在区块链系统中, 转账操作是流程是
发起转账 -> 转账成功(己方扣除金额) -> 写入到区块 -> 同步区块 -> 区块验证成功(对方收到金额, 支付成功)

由于区块的同步需要不定时间, 所以需要不同的回调来记录用户的操作状态.

  1. 如果支付成功后立刻返回 App 收到的回调为 onOtcTransferSuccess(), 表明用户已经成功发起转账操作, 扣费成功等待区块验证, 此后不会再收到 onOtcPaySuccess() 的回调.
  2. 如果等待数秒后, 区块验证成功, 那么返回 App 会收到回调 onOtcPaySuccess(), 表明对方已经成功收到转账, 这笔交易成功结束. 此时不会收到 onOtcTransferSuccess() 回调.
  3. 支付失败回调为 onOtcPayFail(int errorCode), 目前 errorCode 仅为 OtcPayManager#OTC_ERROR_CODE_INVALID_ARGUMENT , 即调起支付时参数校验错误.
  4. 支付取消回调为 onOtcPayCancel().

3.8 scheme接口调起链克口袋APP流程(iOS与Android通用)

  • 唤起协议

链克口袋唤起协议为scheme://host?

  • 请求参数说明
参数 类型 必须 说明
scheme string 链克口袋scheme otst
host string 链克口袋host值为:payment
tx-data byte[] Base64编码 主要包含支付的订单信息,key=value形式,以&连接
resource byte[] Base64编码 来源app
cb-data byte[] Base64编码(可选)支付调起者需要链克口袋回传的额外信息
x-source string 源app scheme eg. wky-app(可选 iOS调用回调,安卓不处理)
x-success string 成功时回调。不填则不返回源app(可选 iOS调用回调,安卓不处理)
x-error string 失败时回调。不填则不返回源app。包含参数:error-Code和errorMessage(可选 iOS调用回调,安卓不处理)
x-cancel string 取消时回调。不填则不返回源app(可选 iOS调用回调,安卓不处理)
  • tx-data参数说明
参数 类型 必须 说明
desc string 合约执行描述,必须带上“合约执行-”前缀
callback string 做url编码,后台回调链接
to string 转出链克口袋地址
value string 链克数量(单位 wei)
prepay_id string 预支付订单号
service_id string 业务id,找交易中心申请service_id和签名秘钥(向后台获取) 预留字段(app提交到geth时转化为整形)
data string 执行的合约代码,十六进制字符串,以0x开头。包含函数地址和调用参数。只发起转账,这个内容为空。
gas_limit string 最大的支付Gas,用于计算合约执行手续费
tx_type string 交易类型,取值contract标识合约,第三方交易tx_third,第三方交易支持缺失默认值,兼容已有的客户端。
sign string 交易签名 sign=md5(sha512(callback=xxx&prepay_id=xxx&service_id=xxx&to=xxx&value=xxx&key=私钥))
  • 响应
  1. 成功

使用x-success为支付成功后返回的参数。字段由payment业务定义。

参数名 类型 必须 说明
hash string 发起transaction成功后的hash,可拥有后续状态查询
  1. 失败

使用x-error的url返回。字段由x-callback-url定义

参数名 类型 必须 说明
error-Code string 错误码。注意是error-Code
errorMessage string 错误信息。
  1. 取消

使用x-cancel的url返回

  • 示例: 请求/响应模式

从玩客云调用链克口袋

otst://contract/?tx-data=ZGVzYz3nlLXlvbFYWFhYJnRvPTB4MTIzNDU2Nzg5MDEyMzQ1Njc4OTAmdmFsdWU9MTIzLjQwJmdhc2xpbWl0PTUwMDAwJmRhdGE9MHgwMTAyMDMwNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEmc2lnbj0wNEI3QTU1QzQ3NDQwRDk4NUE0NDgzNkZENTVFQkVCNw==&resource=d2t5&x-source=wky&x-success=wky://x-callback-url/contractSuccess&x-error=wky://x-callback-url/contractError&x-cancel=wky://x-callback-url/contractCancel&&cb-data=base64编码后的回调透传参数

具体解析

  1. 合约执行业务 otst://contract
  2. 源app名字,resource=d2t5, 解码后是wky
  3. 源app回调前缀,x-source=wky
  4. 成功回调 &x-success=wky://x-callback-url/contractSuccess
  5. 失败回调 &x-error=wky://x-callback-url/contractError
  6. 取消回调 &x-cancel=wky://x-callback-url/contractCancel
  7. 回调时,直接回传 &cb-data=abcdefg
  8. 交易信息tx-data=ZGVzYz3nlLXlvbFYWFhYJnRvPTB4MTIzNDU2Nzg5MDEyMzQ1Njc4OTAmdmFsdWU9MTIzLjQwJmdhc2xpbWl0PTUwMDAwJmRhdGE9MHgwMTAyMDMwNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEmc2lnbj0wNEI3QTU1QzQ3NDQwRDk4NUE0NDgzNkZENTVFQkVCNw==

解码后包含如下信息

  1. 支付地址 &to=0x12345678901234567890
  2. 支付链克数量 &value=123.4
  3. 最大支付费用 &gaslimit=50000
  4. 调用代码 &data=0x010203040000000000000000000000000000000000000000000000000000000000000001
  5. 用于标题 &desc=电影XXXX
  6. sign交易签名 &sign=04B7A55C47440D985A44836FD55EBEB7

返回(成功)

wky://x-callback-url/contractSuccess?cb-data=abcdefg&hash=0x12345678901234567890123456789012&data=base64编码后的回调透传参数

返回(失败)

wky://x-callback-url/contractError?x-source=otc&errorCode=1&errorMessage=message&data=base64编码后的回调透传参数

返回(取消)

wky://x-callback-url/contractCancel?x-source=otc&data=base64编码后的回调透传参数

3.9 常见错误

ErrParams             = Error{Code: -3001, Message: "参数错误"}
ErrTxEmpty            = Error{Code: -3002, Message: "交易为空"}
ErrTxSign             = Error{Code: -3003, Message: "交易签名不合法"}
ErrTxFail             = Error{Code: -3004, Message: "交易失败"}
Err3rdSignErr         = Error{Code: -3016, Message: "签名校验失败"}
ErrInvalidServiceID   = Error{Code: -3017, Message: "service_id非法"}

3.10 如何计算签名

sign由业务侧逻辑server生成

传递路径

业务后台->业务前端->链克口袋app->区块链接入->区块链

签名算法:

sign=md5(sha512(callback=xxx&prepay_id=xxx&service_id=xxx&to=xxx&value=xxx&key=私钥)), 将xxx替换成参数值。

4. API列表

4.1 获取prepay_id

请求方式: post

参数 类型 说明
service_id int 业务号,网心分配
sign string 签名,签名算法:md5(sha512("service_id=业务号&key=私钥")), 私钥网心分配
timeout int 生成的prepay_id的超时时间,单位为秒

请求格式与示例:

//为了保持和以太坊格式一致,请求post body数据要按照以下格式:
{
    "jsonrpc": "2.0",
    "method": "getPrepayId",
    "params": {
        "service_id": 0,
        "sign": "f93d2813227b68f77bf0db84c62011ca",
        "timeout": 1800
    }
}
  • Timeout字段以秒为单位
  • Timeout字段如果不输入或者输入负值,则生成的prepay_id默认超时时间为2小时[可配置]
  • Timeout字段如果输入了超过默认最大的时间[可配置],则生成的prepay_id有效期为配置的最大时间,目前默认为一天

响应参数:

参数 类型 说明
iRet int 0 成功
sMsg int 返回描述
data array 返回数据,json编码的字符串

返回示例:

{
"iRet":0,
"sMsg": "ok",
"data": {\"prepay_id\":\"201711291656030000000101431771972107\"}
}

4.2 查询订单状态

请求url 测试环境:https://sandbox-walletapi.onethingpcs.com/getOrderStatusByPrepayId 正式环境:https://walletapi.onethingpcs.com:443/getOrderStatusByPrepayId

参数 类型 说明
service_id int 业务号,网心分配
prepay_id string 订单提交时获取的

请求格式与示例:

{"jsonrpc":"2.0","method":"getOrderStatusByPrepayId","params":{"service_id":1,"prepay_id":"20171019xxxxxxxxxxxx"}}

响应参数:

参数 类型 说明
iRet int 0 成功
sMsg int 返回描述
data array 返回数据,json编码的字符串

data格式:

参数 类型 说明
from string 付款地址
to string 收款地址
value string 链克金额,string,单位:wei, 例如:"1000000000000000000"
status string 订单状态,0初始,1成功,2失败
ctime string 交易时间,例:2017-10-19 15:37:00

返回示例:

{
"iRet":0,
"sMsg": "ok",
"data": {\"from\":\"0x06782c096abf210f86c6d3ee4bfa9ebb6da39c58\",\”to\”:\”0xyyyyyyyyyyyyyyyyyyyyyyyyyyyy\”, \“value\”:3.5, \“status\”:1, \“ctime\”:\”  2017-10-19 15:37:00\”}
}
  • 如果Prepay_id未失效,同时查询不到订单信息,那么获取订单信息返回”订单未支付”
  • 如果Prepay_id已失效,同时查询不到订单信息,那么获取订单信息返回”Prepay_id无效”
  • 如果查询到订单信息则正常返回

4.3 回调协议

交易成功后,区块链通知模块会把prepay_id回调接入方,接入方需要接收处理,并返回应答。 对后台通知交互时,如果区块链通知模块收到接入方的应答不是成功或超时,区块链通知模块认为通知失败,区块链通知模块会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但区块链通知模块不保证通知最终能成功。 (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)

注意:同样的通知可能会多次发送给接入方系统。接入方系统必须能够正确处理重复的通知。

推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。 特别提醒:接入方系统对于交易结果通知的内容一定要做签名验证,防止数据泄漏导致出现“假通知”。

区块链通知模块回调协议(post):

参数 类型 说明
prepay_id string 预支付ID
from string 付款地址
to string 收款地址
value string 链克金额,string,单位:wei, 例如:"1000000000000000000"
status string 订单状态,0初始,1成功,2失败
timestamp string unix时间戳

示例:

from=xxxxxx&prepay_id=xxxxxxxxxxxxx&status=1&timestamp=1512893272&to=xxxxx&value=100000000000000&sign=4124bc0a9335c2xxxxxxxxxxxxxx

其中的sign=md5(sha512(from=xxxxxx&prepay_id=xxxxxxxxxxxxx&status=1&timestamp=1512893272&to=xxxxx&value=xxxx&key=私钥))

接入方收到回调后,需要给区块链通知模块回应(post): return_code=0&return_msg=ok

5. 常见FAQ

5.1 如何下载链克口袋手机APP

扫码下载安装

app下载

5.2 如何获得区块链账号

用户下载安装APP后,即可通过APP生成账户。