Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

开发者接入Mixin Network说明

步骤

1. 开发者自己创建一个mixin 账户

https://mixin.one

2. 开发者使用注册的mixin账户创建App并进行配置

访问 https://developers.mixin.one/dashboard , 使用Mixin App的摄像头扫描二维码登陆。

填写注册App需要的信息,包括callback URL,目前图标暂时不是必选的。

注册成功 App 之后,你就拥有了一个mixinapp里面的一个机器人账户,目前是7000开头的那一段数字。

点击相应 App 的 “Click to generate a new session”,会出现三组数据:请牢记在心, 因为私钥部分不会再显示一次。

第一行的 6 位数字是 api接入 的提现/转账PIN 码,此处也是机器人的提现/转账密码

第二行的 UUID 是 session ID,

第三行是PIN_TOKEN,

最后一部分 RSA PRIVATE KEY 是跟 API 进行交互时用来签名 JWT 的私钥。

3. 编程接入mixin网络

xin网络本身是一个公链,mixin app是这个公链开发团队维护的一个App。

因此使用xin公链有两种方式:

一种是获取mixin app的用户,通过mixin app 来完成转账和提现。

另一种是自己创建用户,管理用户数据库,仅仅通过mixin公链转账和支付。

接入mixin网络,需要使用JWT RSA token,并将 http header里面的字段设定为 Authorization: Bearer ACCESS_TOKEN

ACCESS_TOKEN 生成方式如下

API 认证方式为标准的 JWT RSA 签名,JWT claims 必须包含的信息为

		"uid": 注册的 App 的 ID(UUID 格式那个,不是7000开头的),
		"sid": 上一部分获取的 session ID,
		"iat": 签名时间,时间必须跟 Mixin 服务器时间基本一致,
		"exp": 过期时间,建议不要设置太长,3 分钟足够,
		"jti": 请求的唯一 ID,必须使用标准的 UUID 格式,
		"sig": sha256(method+URI+body),

3.1 获取某个Mixin app的用户

引导用户访问下面的网址,用户通过Mixin App摄像头扫码就可以登陆

https://mixin.one/oauth/authorize?client_id=CLIENT_ID&scope=SCOPE&code_challenge=PKCE

其中 CLIENT_ID是 dashboard里面显示的 UUID格式的那串文字

SCOPE可以是如下组合

PROFILE:READ
PROFILE:READ+PHONE:READ
PROFILE:READ+ASSETS:READ
PROFILE:READ+PHONE:READ+ASSETS:READ

以下是例子

https://mixin.one/oauth/authorize?client_id=3c5fd587-5ac3-4fb6-b294-423ba3473f7d&scope=PROFILE:READ
https://mixin.one/oauth/authorize?client_id=3c5fd587-5ac3-4fb6-b294-423ba3473f7d&scope=PROFILE:READ+ASSETS:READ

一旦用户使用Mixin app摄像头扫描二维码之后,mixin服务器会引导用户的浏览器访问在dashboard里面设置的callback URL 并且带有参数

{'code': u'a83f4424a205c36d9086ff751c2efc282766c92a3fb40aa1b26546b4187f95ba'}

使用这个参数访问 https://api.mixin.one/oauth/token

POST https://api.mixin.one/oauth/token
{
  "client_id": "CLIENT_ID",
  "code": "authorization code from step above",
  "client_secret": "optional client secret",
  "code_verifier": "optional PKCE code verifier"
}

会获得结果

{u'data': {u'access_token': u'eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJhaWQiOiI5NmMyNGI4Mi01MjY2LTQ5YWQtYjc4NS03MWZhYjE4Y2FiYTEiLCJleHAiOjE1NTU4NTc4MjEsImlhdCI6MTUyNDMyMTgyMSwiaXNzIjoiM2M1ZmQ1ODctNWFjMy00ZmI2LWIyOTQtNDIzYmEzNDczZjdkIn0.Hv78yzF40GeKxw4J0tIahd1tvYdlrmJw0YMZf8OTCZBclyr3Bi-nIAEZWnOej9YuQ3elyajI6UPBQdW22i4DHrSyDNt3i2d8YXfrOJ_F1h7Raq7whoLkVr2vAFuch-ZvVBEtTyv8RDkU8-36f4pgzdMSheb3gEQDtM1d904mNIc', u'scope': u'PROFILE:READ ASSETS:READ'}}

这个access token是后面一些操作需要设置在http header里面的

personinfo = requests.get('https://api.mixin.one/me', headers = {"Authorization":"Bearer " + access_token})

使用上面的参数里面的数据可以访问到客户的一些基本信息

GET -H "Authorization: Bearer ACCESS_TOKEN" https://api.mixin.one/me

=>

{
  "data": {
    "type": "user",
    "user_id": "773e5e77-4107-45c2-b648-8fc722ed77f5",
    "name": "Team Mixin",
    "identity_number": "7000"
  }
}

3.2 获取mixin app用户的资产列表

GET -H "Authorization: Bearer ACCESS_TOKEN" https://api.mixin.one/assets

=>

{
  "data": {
    "type": "user",
    "user_id": "773e5e77-4107-45c2-b648-8fc722ed77f5",
    "name": "Team Mixin",
    "identity_number": "7000"
  }
}
    personinfo = requests.get('https://api.mixin.one/me', headers = {"Authorization":"Bearer " + access_token})

3.3 获取mixin app用户的某个资产余额

GET -H "Authorization: Bearer ACCESS_TOKEN" https://api.mixin.one/assets/asset-uuid

=>

{
  "data": {
    "type": "user",
    "user_id": "773e5e77-4107-45c2-b648-8fc722ed77f5",
    "name": "Team Mixin",
    "identity_number": "7000"
  }
}

3.1.1 使用自己的机器人转账给用户

注意:ACCESS_TOKEN 需要使用JWT token,而且trace_id不能是使用过的

curl -X POST -H "Authorization: Bearer ACCESS_TOKEN" -H "Content-Type: application/json" https://api.mixin.one/transfers

{ "asset_id": "", // 默认值是空 "counter_user_id": UUID, // 主播的 "amount": "amount", "pin": "encrypted_pin", // 加密的 pin "trace_id": UUID, // 可以随时用这个 id 来查询转帐的记录 "memo": "备注", }

=>

{ "type": "transfer", "snapshot_id": UUID, "trace_id": UUID, ... }

3.1.2 引导用户给别的用户转账

3.2 自己拥有用户,仅仅使用mixin网络来转账

这种使用场景需要使用标准的JWT RSA token, 此后对所有的 API 访问包含上面签名过的 JWT token 做为一个 Bearer Authorization HTTP header。

1. 通过上面 APP 的 JWT RSA (ACCESS_TOKEN)签名, 创建用户(主播或者土豪)

*注意:这里是 APP 的 ACCESS_TOKEN *

每个用户都是由一个标准的 RSA 密钥代表的,首先需要在本地生成一对 RSA 的密钥,并保存好 PRIVATE KEY,然后将 PUBLIC KEY 以 Base64 Encode 的形式做为相应参数(session_secret)发送给 Mixin 服务器节点,同时可选的发送一个用户名字来方便区分用户。

curl -X POST -H "Authorization: Bearer ACCESS_TOKEN" -H "Content-Type: application/json" https://api.mixin.one/users

{ "session_secret": Base64 of RSA PUBLIC KEY, "full_name": 可选的用来方便区分用户的名字, }

=>

{ "data": { "type": "user", "user_id": UUID, "session_id": UUID, "pin_token": RSA PRIVATE KEY, ... } }

2. 为主播或土豪准备转帐需要的 PIN (支付密码)

每个 Mixin 的用户都需要有一个 PIN 码,转帐要用。创建新用户的时候是不包含这个密码的,所以需要更新。

注意:这里的 ACCESS_TOKEN 跟 1 中的加密方式一致,但是是用 2 中用户的信息(相当于对每个独立的用户进行的操作)

curl -X POXT -H "Authorization: Bearer ACCESS_TOKEN" -H "Content-Type: application/json" https://api.mixin.one/pin/update

{ "old_pin": "", // 默认值是空 "pin": "encrypted_pin", // 加密的 pin }

在post请求中使用的pin如何获得?

在开发者dashboard中获得的pin_token 是一个经过base64 编码字符串,并且经过了公钥加密,

我们需要首先对pin_token 以base64进行解码,然后用获取的私钥对字符进行解密,获得加密的key

然后组织待加密的内容:

dashboard获取的pin + timestamp + (8字节计数器)

用key对内容用AES加密算法加密。 如何得到加密的 PIN

  1. 服务器返回的 pin_token 解密,得到 key
  2. 得到一个 pin + LittleEndian(time) + iterator (每次加密都要加 1)
  3. 进行 AES 加密
func testEncryptPIN(ctx context.Context, pin, pinToken, sessionId string, key *rsa.PrivateKey, iterator uint64) string {
	token, _ := base64.StdEncoding.DecodeString(pinToken)
	keyBytes, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, key, token, []byte(sessionId))
	if err != nil {
		return ""
	}
	pinByte := []byte(pin)
	timeBytes := make([]byte, 8)
	binary.LittleEndian.PutUint64(timeBytes, uint64(time.Now().Unix()))
	pinByte = append(pinByte, timeBytes...)
	iteratorBytes := make([]byte, 8)
	binary.LittleEndian.PutUint64(iteratorBytes, iterator)
	pinByte = append(pinByte, iteratorBytes...)
	padding := aes.BlockSize - len(pinByte)%aes.BlockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	pinByte = append(pinByte, padtext...)
	block, _ := aes.NewCipher(keyBytes)
	ciphertext := make([]byte, aes.BlockSize+len(pinByte))
	iv := ciphertext[:aes.BlockSize]
	io.ReadFull(rand.Reader, iv)
	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext[aes.BlockSize:], pinByte)
	return base64.StdEncoding.EncodeToString(ciphertext)
}

4. 用户获取充值地址

每个用户都拥有所有货币 asset 的充值地址,必须通过下面的 API 访问来获取相应 asset 的信息,其中的 public_key 字段为用户的充值地址。

*注意:这里是用户的 ACCESS_TOKEN *

curl -H "Authorization: Bearer ACCESS_TOKEN" -H "Content-Type: application/json" https://api.mixin.one/assets/UUID

=>

{ "data": { "type": "asset", "asset_id": UUID, "public_key": Adress, ... } }

现在支持的 asset UUID 有两种,BTC 和 ETH,其中 ETH 的地址可以自动支持所有 ERC20 资产的充值。

BTC c6d0c728-2624-429b-8e0d-d9d19b6592fa ETH 43d61dcd-e413-450d-80b8-101d5e903357

5. 转帐(土豪给主播打赏)

注意:ACCESS_TOKEN 是土豪的

curl -X POST -H "Authorization: Bearer ACCESS_TOKEN" -H "Content-Type: application/json" https://api.mixin.one/transfers

{ "asset_id": "", // 默认值是空 "counter_user_id": UUID, // 主播的 "amount": "amount", "pin": "encrypted_pin", // 加密的 pin "trace_id": UUID, // 可以随时用这个 id 来查询转帐的记录 "memo": "备注", }

=>

{ "type": "transfer", "snapshot_id": UUID, "trace_id": UUID, ... }

6. 添加提现地址

注意: ACCESS_TOKEN 属于用户

curl -X POST -H "Authorization: Bearer ACCESS_TOKEN" -H "Content-Type: application/json" https://api.mixin.one/addresses

{ "asset_id" : UUID, "public_key": "ETH OR BTC", "label": "备注", "pin": "encrypted_pin", // 加密的 pin }

=>

{ "type": "address", "address_id": UUID, "asset_id": UUID, "public_key": "ETH OR BTC", ... }

7. 提现

注意: ACCESS_TOKEN 属于用户

curl -X POST -H "Authorization: Bearer ACCESS_TOKEN" -H "Content-Type: application/json" https://api.mixin.one/withdrawals

{ "address_id": UUID, // 提现的地址 "amount": "amount", "pin": "encrypted_pin", // 加密的 pin "trace_id": UUID, // 可以随时用这个 id 来查询转帐的记录 "memo": "备注", }

=>

{ "type": "withdrawal", "snapshot_id": UUID, "trace_id": UUID, ... }

@duzechao

This comment has been minimized.

Copy link

duzechao commented May 4, 2018

你好,sig这个字段加密前的格式是怎样的,body的格式是json吗,我试了下各种格式都验证失败

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.