id:BSN_2021 公众号:BSN 研习社 作者:中移信息
2021年10月,BSN 提出搭建 BSN-DDC 基础网络,区块链团队自主研发中移链(CMBaaS)DDC 并与 BSN 开展合作,面向存在 DDC 业务需求的各行业客户提供接入服务,使其可便捷管理 DDC 操作,从而灵活升级产品模式,助力客户业务创新。
本文档是关于中移链 DDC-SDK 技术在对接全流程中,如何调用BSN-DDC门户OpenAPI接口的生成公私钥对、创建链账户、接入官方DDC合约、分配资源、业务费充值以及对应查询的操作指南,适用于 BSN 开放联盟链–中移链 DDC-SDK 开发者,帮助读者了解如何以平台方的角色集成中移链 DDC-SDK。
BSN-DDC门户 OpenAPI 是用于与中移链交互的 API 服务,主要功能可参考《BSN-DDC门户OpenAPI接口文档》。在中移链 RPC API手册的基础上,为中移链系统合约提供可访问的服务入口,方便平台方通过 OpenAPI 实现对系统合约的远程调用。
BSN-DDC门户 OpenAPI 主要包含四个部分:开放联盟链框架、项目管理、DDC链账户管理、官方DDC查询。以下是各个部分的功能介绍:
开放联盟链框架:负责开放联盟链框架的列表查询和支持的链账户类型查询,例如中移链的opbChainId为9,支持的链账户类型为上传公钥。
项目管理:负责项目的创建、列表查询和状态更新,平台方使用项目ID和项目key接入OPB网关,并发起合约交易,默认不开启项目key。
DDC链账户管理:提供完整的DDC链账户管理流程,主要包括:生成链账户公私钥对、创建链账户、接入官方DDC合约、分配资源和业务费充值等。
官方DDC查询:提供官方DDC的发行明细和交易列表查询,同时支持官方DDC的生成、授权、转移、销毁等完整流转记录的查询。
开放联盟链:用于部署和运行各类区块链应用的一站式区块链服务运行环境。开放联盟链的应用共享记账节点资源和区块链数据账本;链外业务系统可以通过节点网关简单、快速接入区块链网络进行交易处理。
BSN DID:平台方的链上身份凭证标识,关联平台方的业务开通凭证、链账户以及其下终端用户的链账户,是平台方开展DDC应用和管理业务的基础标识。平台方需要妥善保存和备份好BSN DID的控制私钥。
DID-SDK:包含注册DID、更新密钥、验证DID三个方法,平台方只需注册一次DID即可,所以需妥善保存和备份好BSN DID的控制私钥,如私钥丢失或泄漏,通过更新密钥方法重新生成BSN DID的控制私钥。
门户OpenAPI:BSN联盟面向平台方开放的一套官方DDC管理服务接口。平台方按照官方门户OpenAPI开发资料进行接口对接,将官方DDC的管理侧功能和查询类功能集成到自己的业务门户内。
官方DDC合约:所有DDC开放联盟链上,部署完全一致的BSN官方DDC合约,可以生成和管理BSN官方DDC(支持ERC-721和ERC-1155)。也允许平台方部署自己的DDC合约,该类DDC由相关平台方自行负责。
BSN官方DDC:通过BSN官方DDC合约生成的官方DDC。BSN联盟为每条开放联盟链都推出一套功能一致,但实现过程不尽相同的官方DDC合约,同一条链上的每个官方DDC都由这个官方DDC合约生成,且都由BSN联盟进行背书。
apitoken:平台方调用门户OpenAPI的每个接口,都需在请求头填写apitoken,服务侧会对apitoken的值进行有效性验证,同时根据此值将请求报文关联到对应的平台方,所以平台方需妥善管理自己的apitoken。
1、登录DDC官网门户网站,点击去注册,网站地址:https://ddc.bsnbase.com/
2、注册时需提供企业名称、法人姓名、企业营业执照、邮箱及手机号等信息
3、DDC网络运营人员在3个工作日内对注册信息进行审核,审核结果将以邮件方式进行通知
1、注册成功后,平台方人员登录官方门户,在“业务开通”页面填写备案网站和申请说明后提交业务开通申请
2、DDC网络运营人员在3个工作日内联系平台方沟通业务开通相关事宜
3、平台方的业务开通申请经BSN联盟审核通过后,DDC网络运营人员联系平台方签署线下协议
注意: 所填写的网站备案信息必须与所提交的注册企业名称一致。此处所说的备案网站不一定是DDC业务的平台,任何注册企业名下的备案网站均可。
1)测试用例
@Test
public void generateDidtest() {
DidClient didClient = this.getDidClient();
DidDataWrapper didDataWrapper = didClient.createDid();
System.out.println(JSONObject.toJSONString(didDataWrapper));
assertNotNull(didDataWrapper);
assertNotNull(didDataWrapper.getDid());
assertNotNull(didDataWrapper.getDocument());
assertNotNull(didDataWrapper.getAuthKeyInfo());
assertNotNull(didDataWrapper.getRecyKeyInfo());
}
2)输出结果
{
"address":"0x6b48f123fe493a144df5cfc24e74d8639622d452",
"authKeyInfo":{
"privateKey":"73352081742544535007412511358750380682016965583404841637572340950252082648181",
"publicKey":"9784207274559734436040166487546186979629799048299924533536969953181115829508641603663755398772837199880448005621139241901177149041470382540707320562016661",
"type":"Secp256k1"
},
"did":"did:bsn:4Qc1ZMwJ2kCDEiZaoW86gbCDopY8",
"didSign":"P6yJGMe9O3HQZ/yXlUdsp/fAZAtqUwI1JbjJG9Xik5MVdWseWay6IaRYj2A27+wGuOeLYBbUO5aNfS+9zI1nTgA=",
"document":{
"authentication":{
"publicKey":"9784207274559734436040166487546186979629799048299924533536969953181115829508641603663755398772837199880448005621139241901177149041470382540707320562016661",
"type":"Secp256k1"
},
"created":"2022-09-08 10:39:52",
"did":"did:bsn:4Qc1ZMwJ2kCDEiZaoW86gbCDopY8",
"proof":{
"creator":"did:bsn:4Qc1ZMwJ2kCDEiZaoW86gbCDopY8",
"signatureValue":"qGSQGQ3LsZWzwKPjXSFpc6QNEyX3hLk4jruhKNMRB1pCh7AujHS0R8TN2HYzdan7HigqMD2RBQW8I0g50xQDZgA=",
"type":"Secp256k1"
},
"recovery":{
"publicKey":"11269225430181361242836691470083240698588912504999066036334383939658125900799001159485142543525883167181641171521691885487531759310220878775219494602416230",
"type":"Secp256k1"
},
"updated":"2022-09-08 10:39:52",
"version":"1"
},
"recyKeyInfo":{
"privateKey":"108084336084494583976203572769842945795131580451324537320160683149905374350774",
"publicKey":"11269225430181361242836691470083240698588912504999066036334383939658125900799001159485142543525883167181641171521691885487531759310220878775219494602416230",
"type":"Secp256k1"
}
}
注意: 平台方仅需注册一次DID,所以建议平台方单独使用DID SDK,无需将其集成到业务系统内。
注意: 门户资金账户充值后,平台方可通过官方门户或门户OpenAPI,将资金账户余额充值到自己的任何DDC开放联盟链上的任何链账户内,以保证这些链账户在相应的链上发起的区块链交易能正常执行。
注意: 项目创建完成后不允许修改开放链框架,参考链接:https://bsnbase.com/static/tmpFile/bzsc/openper/7-2-4.html
平台方可通过OpenAPI对所属DDC链账户进行在线生成公私钥对,哪些框架支持可通过'开放联盟链框架-列表查询'接口返回值中opcOnlineCreate为0表示。
apitoken:eyJ0eXAiOi**********************************************UG9VHWZFBg
| 参数名称 | 参数说明 | 是否必须 | 数据类型 |
|---|---|---|---|
| opbChainId | 开放联盟链框架 | 是 | integer |
| 参数名称 | 参数说明 | 类型 |
|---|---|---|
| code | 成功:0,失败:-1 | integer |
| errorLogCode | 错误日志编码 | string |
| errorLogMessage | 错误日志说明 | string |
| message | 消息编码 | string |
| data | 结果对象 | object |
| portalToken | 凭此token可以访问共享接口,返回空则表示无法使用 | string |
1)测试用例
private String baseUrl = "https://openapi-ddc.bsnbase.com";
private String apiToken = "eyJ0eXAiOi**********************************************UG9VHWZFBg";
@Test
public void testCreateKeyPair() {
String url = baseUrl + "/ddcoai/sys/v1/opb/account/create/publicprivatekey";
CreateKeyPair request = CreateKeyPair.builder()
.opbChainId(9)
.build();
String result = HttpRequest.post(url)
.header("apitoken", apiToken)
.body(JSONUtil.toJsonStr(request))
.execute().body();
System.out.println(result);
}
2) 响应结果
{
"code":0,
"errorLogCode":null,
"errorLogMessage":"",
"message":"MSG_00000",
"data":"Public key:\nEOS83Vsg9nooWLoEJNvAtAmr8en5UQMdoU7ztdrjxiL4UGytFUQnB\n\nPrivate key:\n5KbkeSYfXgBWYQsv1NoQsp1nRcYBpGe5BnvucmJcUAR1E4ALYV6\n\nChain account address:\n\n\nMnemonic:\n[calm, cram, relief, inside, pistol, blood, merit, monitor, parade, aspect, network, buffalo]\n\nAlgorithm:\nsecp256k1",
"portalToken":null
}
生成链账户后,平台方通过官方门户OpenAPI登记注册链账户。只有接入官方DDC合约的链账户才能启用BSN-DDC业务功能。新建时可以不接入官方DDC合约,可调“接入官方DDC合约”接口接入。
apitoken:eyJ0eXAiOi**********************************************UG9VHWZFBg
| 参数名称 | 参数说明 | 是否必须 | 数据类型 |
|---|---|---|---|
| opbChainClientName | 链账户名称 | 是 | string |
| opbChainClientType | 用户类型(1=平台方 2=平台方的用户) | 否 | integer |
| opbChainId | 开放联盟链框架ID(调用接口:开放联盟链-框架列表查询) | 是 | integer |
| opbKeyType | 链账户类型(调用接口:开放联盟链-框架支持的链账户类型) | 是 | integer |
| opbPublicKey | 上传公钥(根据链账户类型为2,值必填) | 否 | string |
| openDdc | 是否接入官方DDC合约 1=不接入 5=接入 | 是 | integer |
| proof | DDC业务开通凭证 内容需要通过json转义 | 是 | string |
| 参数名称 | 参数说明 | 类型 |
|---|---|---|
| code | 成功:0,失败:-1 | integer |
| errorLogCode | 错误日志编码 | string |
| errorLogMessage | 错误日志说明 | string |
| message | 消息编码 | string |
| data | 结果对象 | object |
| opbChainClientAddress | 链账户地址 | string |
| portalToken | 凭此token可以访问共享接口,返回空则表示无法使用 | string |
1)测试用例
private String baseUrl = "https://openapi-ddc.bsnbase.com";
private String apiToken = "eyJ0eXAiOi**********************************************UG9VHWZFBg";
private String proof = "{\"claim\":{\"entName\":\"******\",\"domain\":\"http://www.chinamobilesz.com/\",\"loginName\":\"******\",\"did\":\"******\"},\"context\":\"https://www.w3.org/2018/credentials/v1\",\"cptId\":\"882201251518080013\",\"created\":\"2022-08-19 03:14:15\",\"expirationDate\":\"2042-08-19\",\"id\":\"1560465138044243968\",\"issuerDid\":\"******\",\"proof\":{\"creator\":\"******\",\"type\":\"Secp256k1\",\"signatureValue\":\"******\"},\"shortDesc\":\"DDC业务凭证模板\",\"type\":\"Proof\",\"userDid\":\"******\"}";
@Test
public void testSaveAccount() {
String url = baseUrl + "/ddcoai/sys/v1/opb/account/create/save";
SaveAccount request = SaveAccount.builder()
.opbChainClientName("ddctest11112")
.opbChainClientType(1)
.opbChainId(9)
.opbKeyType(2)
.opbPublicKey("EOS6R3jYqb3uZsVgzJz4HVLcYV94CLkr3u9unEzm5rpuAqUos7fqK")
.openDdc("1")
.proof(proof)
.build();
String result = HttpRequest.post(url)
.header("apitoken", apiToken)
.body(JSONUtil.toJsonStr(request))
.execute().body();
System.out.println(result);
}
2) 响应结果
{
"code":0,
"errorLogCode":null,
"errorLogMessage":"",
"message":"MSG_00000",
"data":{
"opbChainClientAddress":"ddctest11112"
},
"portalToken":null
}
基于已有的链账户地址接入官方DDC合约。
apitoken:eyJ0eXAiOi**********************************************UG9VHWZFBg
| 参数名称 | 参数说明 | 是否必须 | 数据类型 |
|---|---|---|---|
| opbChainClientAddress | 链账户地址 | 是 | string |
| opbChainClientType | 用户类型(1=平台方 2=平台方的用户) | 否 | integer |
| opbChainId | 开放联盟链框架ID(调用接口:开放联盟链-框架列表查询) | 是 | integer |
| proof | DDC业务开通凭证 内容需要通过json转义 | 是 | string |
| 参数名称 | 参数说明 | 类型 |
|---|---|---|
| code | 成功:0,失败:-1 | integer |
| errorLogCode | 错误日志编码 | string |
| errorLogMessage | 错误日志说明 | string |
| message | 消息编码 | string |
| data | 结果对象 | object |
| opbChainClientAddress | 链账户地址 | string |
| portalToken | 凭此token可以访问共享接口,返回空则表示无法使用 | string |
1)测试用例
private String baseUrl = "https://openapi-ddc.bsnbase.com";
private String apiToken = "eyJ0eXAiOi**********************************************UG9VHWZFBg";
private String proof = "{\"claim\":{\"entName\":\"******\",\"domain\":\"http://www.chinamobilesz.com/\",\"loginName\":\"******\",\"did\":\"******\"},\"context\":\"https://www.w3.org/2018/credentials/v1\",\"cptId\":\"882201251518080013\",\"created\":\"2022-08-19 03:14:15\",\"expirationDate\":\"2042-08-19\",\"id\":\"1560465138044243968\",\"issuerDid\":\"******\",\"proof\":{\"creator\":\"******\",\"type\":\"Secp256k1\",\"signatureValue\":\"******\"},\"shortDesc\":\"DDC业务凭证模板\",\"type\":\"Proof\",\"userDid\":\"******\"}";
@Test
public void testSaveOfficial() {
String url = baseUrl + "/ddcoai/sys/v1/opb/account/access/official/save";
SaveOfficial request = SaveOfficial.builder()
.opbChainClientAddress("ddctest11112")
.opbChainClientType(1)
.opbChainId(9)
.proof(proof)
.build();
String result = HttpRequest.post(url)
.header("apitoken", apiToken)
.body(JSONUtil.toJsonStr(request))
.execute().body();
System.out.println(result);
}
2) 响应结果
{
"code":0,
"errorLogCode":null,
"errorLogMessage":"",
"message":"MSG_00000",
"data":{
"opbChainClientAddress":"ddctest11112"
},
"portalToken":null
}
查看DDC链账户的基本信息。
apitoken:eyJ0eXAiOi**********************************************UG9VHWZFBg
| 参数名称 | 参数说明 | 是否必须 | 数据类型 |
|---|---|---|---|
| opbChainClientAddress | DDC链账户地址 | 是 | string |
| opbChainId | 开放联盟链框架ID | 是 | integer |
| 参数名称 | 参数说明 | 类型 |
|---|---|---|
| code | 成功:0,失败:-1 | integer |
| errorLogCode | 错误日志编码 | string |
| errorLogMessage | 错误日志说明 | string |
| message | 消息编码 | string |
| data | 结果对象 | object |
| business | 官方DDC业务费余额(分) | integer |
| createDate | 创建时间 | string |
| did | DID | string |
| gasNum | 能量值余额(最大50长度8个小数点) | string |
| opbChainClientAddress | 链账户地址 | string |
| opbChainClientName | 链账户名称 | string |
| opbChainClientType | 用户类型(1=平台方,2=平台方的用户) | integer |
| opbChainName | 开放联盟链框架 | string |
| opbChainType | 链账户类型 | string |
| openDdcYn | 是否已接入官方DDC合约:1=未接入(只开通OPB没有上DDC合约)5=已接入 | integer |
| opsPlatformState | 运营方设置状态(0=未接入官方DDC合约 1=冻结 2=已启用(未冻结) 3=冻结中 4=解冻中) | integer |
| platformSetState | 平台方设置状态(0=未接入官方DDC合约 1=冻结 2=已启用(未冻结) 3=冻结中 4=解冻中) | integer |
| portalToken | 凭此token可以访问共享接口,返回空则表示无法使用 | string |
1)测试用例
private String baseUrl = "https://openapi-ddc.bsnbase.com";
private String apiToken = "eyJ0eXAiOi**********************************************UG9VHWZFBg";
@Test
public void testQueryAccount() {
String url = baseUrl + "/ddcoai/sys/v1/opb/account/check/details/search";
SearchAccount request = SearchAccount.builder()
.opbChainClientAddress("ddctest11112")
.opbChainId(9)
.build();
String result = HttpRequest.post(url)
.header("apitoken", apiToken)
.body(JSONUtil.toJsonStr(request))
.execute().body();
System.out.println(result);
}
2) 响应结果
{
"code":0,
"errorLogCode":null,
"errorLogMessage":"",
"message":"MSG_00000",
"data":{
"did":"did:bsn:49oahBPHZ41zqCbzUPkqRMdqBGvb",
"opbChainClientName":"ddctest11112",
"opbChainClientType":1,
"business":100,
"createDate":"2022-09-05 17:11:22",
"opbChainName":"中移链(基于EOS v2.1)",
"opbChainClientAddress":"ddctest11112",
"opbChainType":"2",
"openDdcYn":5,
"gasNum":"NET:1808172 bytes,CPU:688319 us,RAM:10247 bytes",
"platformSetState":2,
"opsPlatformState":2
},
"portalToken":null
}
平台方可通过OpenAPI对所属DDC链账户进行分配资源。链账户分配资源所需总金额可通过EOS分配资源价格计算接口进行预览。
apitoken:eyJ0eXAiOi**********************************************UG9VHWZFBg
| 参数名称 | 参数说明 | 是否必须 | 数据类型 |
|---|---|---|---|
| cpuValue | 充值cpu数量(SYS) | 是 | integer |
| netValue | 充值net数量(SYS) | 是 | integer |
| opbChainClientAddress | 链账户地址 | 是 | string |
| opbChainId | 开放联盟链框架 | 是 | integer |
| proof | DDC业务开通凭证 内容需要通过json转义 | 是 | string |
| ramValue | 充值ram数量(KB) | 是 | integer |
| reqTransactionSn | 第三方流水号 | 是 | string |
| validDate | 资源有效期(30天起售)(格式:yyyy-MM-dd) | 是 | string(date-time) |
| 参数名称 | 参数说明 | 类型 |
|---|---|---|
| code | 成功:0,失败:-1 | integer |
| errorLogCode | 错误日志编码 | string |
| errorLogMessage | 错误日志说明 | string |
| message | 消息编码 | string |
| data | 结果对象 | object |
| portalToken | 凭此token可以访问共享接口,返回空则表示无法使用 | string |
1)测试用例
private String baseUrl = "https://openapi-ddc.bsnbase.com";
private String apiToken = "eyJ0eXAiOi**********************************************UG9VHWZFBg";
private String proof = "{\"claim\":{\"entName\":\"******\",\"domain\":\"http://www.chinamobilesz.com/\",\"loginName\":\"******\",\"did\":\"******\"},\"context\":\"https://www.w3.org/2018/credentials/v1\",\"cptId\":\"882201251518080013\",\"created\":\"2022-08-19 03:14:15\",\"expirationDate\":\"2042-08-19\",\"id\":\"1560465138044243968\",\"issuerDid\":\"******\",\"proof\":{\"creator\":\"******\",\"type\":\"Secp256k1\",\"signatureValue\":\"******\"},\"shortDesc\":\"DDC业务凭证模板\",\"type\":\"Proof\",\"userDid\":\"******\"}";
@Test
public void testSaveResource() {
String url = baseUrl + "/ddcoai/sys/v1/opb/eos/resource/save";
SaveResource request = SaveResource.builder()
.cpuValue(1)
.netValue(1)
.opbChainClientAddress("ddctest11112")
.opbChainId(9)
.proof(proof)
.ramValue(10)
.reqTransactionSn("8950jg89j0fi94i")
.validDate("2022-10-06")
.build();
String result = HttpRequest.post(url)
.header("apitoken", apiToken)
.body(JSONUtil.toJsonStr(request))
.execute().body();
System.out.println(result);
}
2) 响应结果
{
"code": 0,
"errorLogCode": null,
"errorLogMessage": "",
"message": "MSG_00000",
"data": null,
"portalToken": null
}
平台方可通过OpenAPI对所属DDC链账户的EOS分配资源结果进行查询。
apitoken:eyJ0eXAiOi**********************************************UG9VHWZFBg
| 参数名称 | 参数说明 | 是否必须 | 数据类型 |
|---|---|---|---|
| opbChainClientAddress | 链账户地址 | 是 | string |
| reqTransactionSn | 第三方流水号 | 是 | string |
| 参数名称 | 参数说明 | 类型 |
|---|---|---|
| code | 成功:0,失败:-1 | integer |
| errorLogCode | 错误日志编码 | string |
| errorLogMessage | 错误日志说明 | string |
| message | 消息编码 | string |
| data | 结果对象 | object |
| opbChainClientAddress | 链账户地址 | string |
| rechargeState | GAS充值状态 1-充值中 5-充值失败 10=充值成功 | integer |
| reqTransactionSn | 第三方流水号 | string |
| portalToken | 凭此token可以访问共享接口,返回空则表示无法使用 | string |
1)测试用例
private String baseUrl = "https://openapi-ddc.bsnbase.com";
private String apiToken = "eyJ0eXAiOi**********************************************UG9VHWZFBg";
@Test
public void testQueryResource() {
String url = baseUrl + "/ddcoai/sys/v1/opb/eos/resource/search";
SearchResource request = SearchResource.builder()
.opbChainClientAddress("ddctest11111")
.reqTransactionSn("8950jg89j0fi94i")
.build();
String result = HttpRequest.post(url)
.header("apitoken", apiToken)
.body(JSONUtil.toJsonStr(request))
.execute().body();
System.out.println(result);
}
2) 响应结果
{
"code":0,
"errorLogCode":null,
"errorLogMessage":"",
"message":"MSG_00000",
"data":{
"opbChainClientAddress":"ddctest11111",
"reqTransactionSn":"8950jg89j0fi94i",
"rechargeState":10
},
"portalToken":null
}
如果使用官方合约发起DDC交易则需要官方DDC业务费,因此可通过OpenAPI给平台方所属DDC链账户进行充值。
apitoken:eyJ0eXAiOi**********************************************UG9VHWZFBg
| 参数名称 | 参数说明 | 是否必须 | 数据类型 |
|---|---|---|---|
| businessMoney | 充值官方DDC业务费金额(单位:分) | 是 | integer |
| opbChainClientAddress | 链账户地址 | 是 | string |
| opbChainId | 开放联盟链框架 | 是 | integer |
| proof | DDC业务开通凭证 内容需要通过json转义 | 是 | string |
| reqTransactionSn | 第三方流水号(数字字母下划线组成) | 是 | string |
| 参数名称 | 参数说明 | 类型 |
|---|---|---|
| code | 成功:0,失败:-1 | integer |
| errorLogCode | 错误日志编码 | string |
| errorLogMessage | 错误日志说明 | string |
| message | 消息编码 | string |
| data | 结果对象 | object |
| portalToken | 凭此token可以访问共享接口,返回空则表示无法使用 | string |
1)测试用例
private String baseUrl = "https://openapi-ddc.bsnbase.com";
private String apiToken = "eyJ0eXAiOi**********************************************UG9VHWZFBg";
private String proof = "{\"claim\":{\"entName\":\"******\",\"domain\":\"http://www.chinamobilesz.com/\",\"loginName\":\"******\",\"did\":\"******\"},\"context\":\"https://www.w3.org/2018/credentials/v1\",\"cptId\":\"882201251518080013\",\"created\":\"2022-08-19 03:14:15\",\"expirationDate\":\"2042-08-19\",\"id\":\"1560465138044243968\",\"issuerDid\":\"******\",\"proof\":{\"creator\":\"******\",\"type\":\"Secp256k1\",\"signatureValue\":\"******\"},\"shortDesc\":\"DDC业务凭证模板\",\"type\":\"Proof\",\"userDid\":\"******\"}";
@Test
public void testSaveBusiness() {
String url = baseUrl + "/ddcoai/sys/v1/opb/account/business/save";
SaveBusiness request = SaveBusiness.builder()
.businessMoney(100)
.opbChainClientAddress("ddctest11112")
.opbChainId(9)
.proof(proof)
.reqTransactionSn("8950jg89j0fi901")
.build();
String result = HttpRequest.post(url)
.header("apitoken", apiToken)
.body(JSONUtil.toJsonStr(request))
.execute().body();
System.out.println(result);
}
2) 响应结果
{
"code": 0,
"errorLogCode": null,
"errorLogMessage": "",
"message": "MSG_00000",
"data": null,
"portalToken": null
}
平台方可通过OpenAPI对所属DDC链账户的官方DDC业务费充值结果进行查询。
apitoken:eyJ0eXAiOi**********************************************UG9VHWZFBg
| 参数名称 | 参数说明 | 是否必须 | 数据类型 |
|---|---|---|---|
| opbChainClientAddress | 链账户地址 | 是 | string |
| reqTransactionSn | 第三方流水号(数字字母下划线组成) | 是 | string |
| 参数名称 | 参数说明 | 类型 |
|---|---|---|
| code | 成功:0,失败:-1 | integer |
| errorLogCode | 错误日志编码 | string |
| errorLogMessage | 错误日志说明 | string |
| message | 消息编码 | string |
| data | 结果对象 | object |
| opbChainClientAddress | 链账户地址 | string |
| rechargeState | 官方DDC业务费充值状态 1-充值中 5-充 值失败 10=充值成功 | integer |
| reqTransactionSn | 第三方流水号 | string |
| portalToken | 凭此token可以访问共享接口,返回空则表示无法使用 | string |
1)测试用例
private String baseUrl = "https://openapi-ddc.bsnbase.com";
private String apiToken = "eyJ0eXAiOi**********************************************UG9VHWZFBg";
@Test
public void testQueryBusiness() {
String url = baseUrl + "/ddcoai/sys/v1/opb/account/business/result/search";
SearchBusiness request = SearchBusiness.builder()
.opbChainClientAddress("ddctest11112")
.reqTransactionSn("8950jg89j0fi901")
.build();
String result = HttpRequest.post(url)
.header("apitoken", apiToken)
.body(JSONUtil.toJsonStr(request))
.execute().body();
System.out.println(result);
}
2) 响应结果
{
"code":0,
"errorLogCode":null,
"errorLogMessage":"",
"message":"MSG_00000",
"data":{
"opbChainClientAddress":"ddctest11112",
"reqTransactionSn":"8950jg89j0fi901",
"rechargeState":10
},
"portalToken":null
}
MSG_20010005:apitoken 授权认证失败,原因是请求头中的apitoken传参错误,可以从业务开通信息页面的门户OpenAPI Token获取;
MSG_10021005:链账户不存在,原因是该链账户没有创建,或者该链账户没有接入官方DDC合约;
MSG_10021029:充值流水号重复,原因是第三方流水号重复了,需要保持第三方流水号全局唯一,同时需要留存以供查询使用;
MSG_10022013:找不到平台方DID,原因是暂未注册DID标识,或者DID标识还在注册中,需要注册成功后请求;
MSG_10027007:购买的资源有效期必须大于30天,原因是资源有效期设置必须大于30天,暂不支持小于30天的资源有效期;
MSG_10021059:链账户名称格式错误,原因是中移链的链账户格式要求:12个字符,只能包括【12345和26个小写字母】。
目前是同一个账户下链账户名称不可以重复,不可以修改;平台方账户可以管理终端账户的状态,可以在DDC-SDK里对终端用户进行充值。
门户的业务费、能量值、DDC的显示都不是实时的,是链上同步至链下,链下定时排队去更新的,建议用户使用OpenAPI操作创建链账户,接入官方DDC,业务费充值,账户状态变更后都直接调用DDC-SDK中的方法去链上确认结果。
使用官方DDC合约生成DDC时,sender账户要支付本次交易所需要消耗的能量值(5分钱左右)和DDC业务费(生成1元,转移、销毁3毛)。
ddcURI字段为DDC标识符,该字段为String类型,长度限制是1000,内容BSN不做限制,用户可根据自己的业务场景自行传值,例如:{“amount”:5000,“id”:“001”,“name”:“name”,“company”:“公司”,“seq”:1710,“url”:“https://xxxx/upload/file/xx.jpg”}。
DDC授权是用户将名下的某个DDC授权给第三方,账户授权是用户将名下的所有DDC授权给第三方,DDC授权在DDC被转移后授权失效,账户授权取消授权后才会失效。
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
我刚刚看到whitehouse.gov正在使用drupal作为CMS和门户技术。drupal的优点之一似乎是很容易添加插件,而且编程最少,即重新发明轮子最少。这实际上正是Ruby-on-Rails的DRY理念。所以:drupal的缺点是什么?Rails或其他基于Ruby的技术有哪些不符合whitehouse.org(或其他CMS门户)门户技术的资格? 最佳答案 Whatarethedrawbacksofdrupal?对于Ruby和Rails,这确实是一个相当主观的问题。Drupal是一个可靠的内容管理选项,非常适合面向社区的站点。它
当音乐碰上区块链技术,会擦出怎样的火花?或许周杰伦已经给了我们答案。8月29日下午,B站独家首发周杰伦限定珍藏Demo独家访谈VCR,周杰伦在VCR里分享了《晴天》《青花瓷》《搁浅》《爱在西元前》四首经典歌曲Demo背后的创作故事,并首次公布18年前未发布的神秘作品《纽约地铁》的Demo。在VCR中,方文山和杰威尔音乐提及到“多亏了区块链技术,现在我们可以将这些Demos,变成独一无二具有收藏价值的艺术品,这些Demos可以在薄盒(国内数藏平台)上听到。”如何将音乐与区块链技术相结合,薄盒方面称:“薄盒作为区块链技术服务方,打破传统对于区块链技术只能作为数字收藏的理解。聚焦于区块链技术赋能,在
三分钟集成Tap防沉迷SDK(Unity版)一、SDK介绍基于国家对上线所有游戏必须增加防沉迷功能的政策下,TapTap推出防沉迷SDK,供游戏开发者进行接入;允许未成年用户在周五、六、日以及法定节假日晚上8:00-9:00进行游戏,防沉谜时间段进入游戏会弹窗进行提示!开发环境要求:Unity2019.4或更高版本iOS10或更高版本Android5.0(APIlevel21)或更高版本🔗Unity集成Demo参考链接🔗UnityTapSDK功能体验APK下载链接二、集成前准备1.创建应用进入开发者后台,按照提示开始创建应用;2.开通服务在使用TDS实名认证和防沉迷服务之前,需要在上面创建的应
EC2会在实例停止然后重新启动时为其提供新的IP地址,因此我需要能够自动管理route53记录集,以便我可以一致地访问内容。遗憾的是,sdk的route53部分的文档远不如ec2的文档那么健壮(可以理解),所以我有点卡住了。到目前为止,从我所看到的情况来看,似乎change_resource_record_sets(link)是可行的方法,但我对:chages需要什么感到困惑>因为它提到了一个Change对象,但没有提供指向所述对象描述的链接。这是我的代码目前的样子:r53.client.change_resource_record_sets(:hosted_zone_id=>'MY_
我感到有点困惑——大约24小时以来,我一直在考虑在我的项目中使用哪种组播技术。基本上,我需要的是:创建组(通过一些后端进程)任意客户端广播消息(1:N,N:N)(可能)直接消息(1:1)(重要)使用我自己的后端(例如,通过某种HTTPAPI)对客户端进行身份验证/授权能够通过后端进程(或服务器插件)踢出特定的客户端这是我要的:Ruby或Haxe中的后端相关流程JS+Haxe(Flash9)中的前端—在浏览器中,因此理想情况下通过80/443进行通信,但不一定。因此,这项技术必须能够在HaxeforFlash中轻松访问,最好是Ruby。我一直在考虑:RabbitMQ(或OpenAMQ)、
在aws-s3中,有一种方法(AWS::S3::S3Object.stream)可让您将S3上的文件流式传输到本地文件。我无法在aws-sdk中找到类似的方法。即在aws-s3中,我这样做:File.open(to_file,"wb")do|file|AWS::S3::S3Object.stream(key,region)do|chunk|file.writechunkendendAWS::S3:S3Object.read方法确实将block作为参数,但似乎没有对其执行任何操作。 最佳答案 aws-sdkgem现在支持S3中对象的分
文章目录概述背景为何要存算分离优势**应用场景**存算分离产品技术流派华为JuiceFSHashDataXSKY概述背景Hadoop一出生就是奔存算一体设计,当时设计思想就是存储不动而计算(code也即是代码程序)动,负责调度Yarn会把计算任务尽量发到要处理数据所在的实例上,这也是与传统集中式存储最大的不同。为何当时Hadoop设计存算一体的耦合?要知道2006年服务器带宽只有100Mb/s~1Gb/s,但是HDD也即是磁盘吞吐量有50MB/s,这样带宽远远不够传输数据,网络瓶颈尤为明显,无奈之举只好把计算任务发到数据所在的位置。众观历史常言道天下分久必合合久必分,随着云计算技术的发展,数据