# 接口说明



# 调用方法

<table id="bkmrk-%E5%86%85%E5%AE%B9-%E8%AF%B4%E6%98%8E-%E9%80%9A%E8%AE%AF%E6%96%B9%E5%BC%8F-%E9%87%87%E7%94%A8-https-" style="width: 603px;"><thead><tr><th style="width: 206px;">内容</th><th style="width: 397px;">说明</th></tr></thead><tbody><tr><td style="width: 206px;">通讯方式</td><td style="width: 397px;">采用 HTTPS 方式访问</td></tr><tr><td style="width: 206px;">提交方法</td><td style="width: 397px;">POST (application/json)</td></tr><tr><td style="width: 206px;">交互数据格式</td><td style="width: 397px;">JSON</td></tr><tr><td style="width: 206px;">字符编码</td><td style="width: 397px;">UTF-8</td></tr><tr><td style="width: 206px;">签名算法</td><td style="width: 397px;">MD5</td></tr><tr><td style="width: 206px;">签名验证</td><td style="width: 397px;">提交和返回数据都需要验证签名</td></tr></tbody></table>

# 报文结构

### **请求报文和返回报文都采用如下的报文结构**

<table id="bkmrk-%E5%BA%8F%E5%8F%B7-%E5%8F%82%E6%95%B0-%E7%B1%BB%E5%9E%8B-%E5%8F%82%E8%80%83%E6%95%B0%E6%8D%AE-%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E-%E5%A4%87"><thead><tr><th>序号</th><th>参数</th><th>类型</th><th>参考数据</th><th>参数说明</th><th>备注</th></tr></thead><tbody><tr><td>1</td><td>action</td><td>String</td><td>inquiry</td><td>交易类型</td><td>具体接口有详细说明</td></tr><tr><td>2</td><td>deviceNo</td><td>String(8)</td><td>POS01</td><td>收银机编号</td><td>用于区别本次交易请求的收银机</td></tr><tr><td>3</td><td>shopNo</td><td>String(15)</td><td>CN123456</td><td>门店编号</td><td>用于区别本次交易请求的门店</td></tr><tr><td>4</td><td>brand</td><td>String</td><td>663</td><td>品牌编号</td><td>用于区别本次交易请求的品牌，易百分配</td></tr><tr><td>5</td><td>body</td><td>String</td><td>BASE64</td><td>报文内容</td><td>具体接口有详细说明，本域需要采用BASE64编码</td></tr><tr><td>6</td><td>mwVersion</td><td>String</td><td>20161010</td><td>中间件版本号</td><td>用于兼容不同的中间件对应后台不同的处理方式</td></tr><tr><td>7</td><td>ptlVersion</td><td>String</td><td>20161010</td><td>协议版本号</td><td>用于兼容不同的报文协议对应后台不同的处理方式</td></tr><tr><td>8</td><td>posVersion</td><td>String</td><td>20161010</td><td>易百POS版本号</td><td>用于兼容不同的易百POS对应后台不同的处理方式</td></tr><tr><td>9</td><td>timestamp</td><td>String</td><td>1483372334</td><td>Unix时间戳</td><td>单位：秒，中间件需要在收到返回时同步该时间</td></tr><tr><td>10</td><td>sign</td><td>String</td><td>7E65B60DCFA42B04</td><td>数据签名</td><td>详见：签名算法</td></tr></tbody></table>

#### **报文举例**

```
 {
     "action" : "inquiry",
     "deviceNo" : "POS01",
     "shopNo" : "CN123456",
     "brand" : "663",
     "body" : "ewogICAgICAgICAidHJhY2VObyI6ICI5OTAwMDAwOTEwMDAxMDEwMTczMjEyMyIsCiAgICAgICAgICJvcmlnaW5hbFRyYWNlTm8iOiAiOTkwMDAwMDkxMDAwMTAxMDE3MzIxMjQiCiAgICAgfQ==",
     "mwVersion" : "20161010",
     "ptlVersion" : "20161010",
     "posVersion" : "20161010",
     "timestamp" : "1483372334",
     "sign" : "7E65B60DCFA42B04"
 }

```

<footer class="page-footer" id="bkmrk-"></footer>

# 签名算法

#### **签名过程**

- 拼接报文参数  
    除sign参数外的所有参数按照ASCII顺序排序后，以"参数名1=参数值1&amp;参数名2=参数值2"的方式拼接所有参数
- 拼接签名 mwMacKey  
    最后在尾部拼接双方约定的密钥"KEY=xxxxx"，  
    因调用downloadKey接口前，并未获得mwMacKey，故使用指定KEY签名  
    因调用signin接口前，并未获得mwMacKey，故使用mwTmk签名
- 签名值计算  
    MD5-32加密后再转成HEX大写格式，即为签名值，并赋给sign参数。
- 注  
    当参数值为null或为空时不参与签名串拼接

#### **示例报文**

```
 {
     "action" : "inquiry",
     "deviceNo" : "POS01",
     "shopNo" : "CN123456",
     "brand" : "663",
     "body" : "ewogICAgICAgICAidHJhY2VObyI6ICI5OTAwMDAwOTEwMDAxMDEwMTczMjEyMyIsCiAgICAgICAgICJvcmlnaW5hbFRyYWNlTm8iOiAiOTkwMDAwMDkxMDAwMTAxMDE3MzIxMjQiCiAgICAgfQ==",
     "mwVersion" : "20161010",
     "ptlVersion" : "20161010",
     "posVersion" : "20161010",
     "timestamp" : "1483372334",
     "sign" : "F38545F4D74B5C10A9EBBC053ED9D1CF"
 }

```

#### **签名mwMacKey密钥**

```
94365019BBF9CEEAB0DF658E67754A70

```

#### **拼接报文参数**

```
action=inquiry&body=ewogICAgICAgICAidHJhY2VObyI6ICI5OTAwMDAwOTEwMDAxMDEwMTczMjEyMyIsCiAgICAgICAgICJvcmlnaW5hbFRyYWNlTm8iOiAiOTkwMDAwMDkxMDAwMTAxMDE3MzIxMjQiCiAgICAgfQ==&brand=663&deviceNo=POS01&mwVersion=20161010&posVersion=20161010&ptlVersion=20161010&shopNo=CN123456&timestamp=1483372334

```

#### **拼接签名KEY**

```
action=inquiry&body=ewogICAgICAgICAidHJhY2VObyI6ICI5OTAwMDAwOTEwMDAxMDEwMTczMjEyMyIsCiAgICAgICAgICJvcmlnaW5hbFRyYWNlTm8iOiAiOTkwMDAwMDkxMDAwMTAxMDE3MzIxMjQiCiAgICAgfQ==&brand=663&deviceNo=POS01&mwVersion=20161010&posVersion=20161010&ptlVersion=20161010&shopNo=CN123456&timestamp=1483372334&KEY=94365019BBF9CEEAB0DF658E67754A70

```

#### **签名值计算**  
F38545F4D74B5C10A9EBBC053ED9D1CF

#### **Java代码示例**

```

Map<String, String> map = new TreeMap<>();
map.put("action", "downloadKey");
map.put("deviceNo", "CN999999");
map.put("shopNo", "CN999999");
map.put("brand", "1458");
map.put("body", "JXU2RDRCJXU4QkQ1JXU1MTg1JXU1QkI5JTIwJXU2RDRCJXU4QkQ1JXU1MTg1JXU1QkI5");
map.put("mwVersion", "20170214");
map.put("ptlVersion", "20170214");
map.put("posVersion", "20170214");
map.put("timestamp", "1483372334");

StringBuilder buffer = new StringBuilder();
for (Map.Entry<String, String> item : map.entrySet()) {
    buffer.append(item.getKey()).append("=").append(item.getValue()).append("&");
}
buffer.append("KEY=").append("F42616614BDC0000161EF06C04061484");
String checkSign = DESCoder.getInstance().encryptMD5(buffer.toString(), "UTF-8").toUpperCase();
System.out.println(buffer.toString());
System.out.println(checkSign);

输出:
action=downloadKey&body=JXU2RDRCJXU4QkQ1JXU1MTg1JXU1QkI5JTIwJXU2RDRCJXU4QkQ1JXU1MTg1JXU1QkI5&brand=1458&deviceNo=CN999999&mwVersion=20170214&posVersion=20170214&ptlVersion=20170214&shopNo=CN999999&timestamp=1483372334&KEY=F42616614BDC0000161EF06C04061484

824AE098F6135CF50A824BAE220379C6

```

<footer class="page-footer" id="bkmrk-"></footer>

# 数据加密算法

#### **3DES介绍**

- 3DES（或称为Triple DES）是三重数据加密算法（TDEA，Triple Data Encryption Algorithm）块密码的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强，原版DES密码的密钥长度变得容易被暴力破解；3DES即是设计用来提供一种相对简单的方法，即通过增加DES的密钥长度来避免类似的攻击，而不是设计一种全新的块密码算法。

#### **加解密过程**

- 设Ek()和Dk()代表DES算法的加密和解密过程，K代表DES算法使用的密钥，M代表明文，C代表密文，这样：
- 3DES加密过程为：C=Ek3(Dk2(Ek1(M)))
- 3DES解密过程为：M=Dk1(EK2(Dk3(C)))
- K1、K2、K3决定了算法的安全性，易百采用K1等于K3，并且使用ECB/NoPadding填充模式。

#### **加密举例**

设pinKey为: `9D93D15D6A3913AB4151C456A80841EF`，则:

```
K1 = 9D93D15D6A3913AB
K2 = 4151C456A80841EF
K3 = 9D93D15D6A3913AB

```

原始数据M表示HEX为：`3132333435363738`，加密如下：

```
DES1_RESULT = Ek(M，K1)
DES2_RESULT = Dk(DES1_RESULT，K2)
C = Ek(DES2_RESULT，K3)

```

最终加密结果C为：`C63AABF759BDE968`

#### **解密举例**

设pinKey为: `9D93D15D6A3913AB4151C456A80841EF`，则:

```
K1 = 9D93D15D6A3913AB
K2 = 4151C456A80841EF
K3 = 9D93D15D6A3913AB

```

密文数据C表示HEX为：`C63AABF759BDE968`，解密如下：

```
DES1_RESULT = Dk(C，K3)
DES2_RESULT = Ek(DES1_RESULT，K2)
M = Dk(DES2_RESULT，K1)

```

最终解密结果M为：`3132333435363738`

# 密码加密算法

#### **ANSI X9.8 Format（带主帐号信息）**

- PIN BLOCK 格式：等于 PIN 按位异或主帐号
- PIN 格式：（个人识别码 Personal Identity Number）总共有8个byte长度，分为两个部分;（类似数据包的格式）
    
    ```
    Byte 1 PIN的长度
    Byte 2 – Byte 3/4/5/6/7    4--12个PIN(每个PIN占4个BIT)
    Byte4/5/6/7/8 – Byte 8 FILLER “F” (每个“F“占4个BIT)
    
    ```
- PAN（主帐号 Primary Account Number）同样包含8个byte，格式如下：
    
    ```
    Byte 1 — Byte 2 0x00 0x00
    Byte 3 — Byte 8 12个主帐号字符（最后一位为校验位）
    12位字符主帐号的取法：取主帐号的右12位（不包括最右边的校验位），不足12位左补“0X00”。
    
    ```

#### **加密举例**

- 明文 PIN：`123456`
- 主帐号 PAN：`123456789012345678`
- 截取下的主帐号为：`678901234567` （最后一位校验位8的前12位字符为截取的主帐号）
- 则用于PIN加密的主帐号为：`0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67`
- 则 PIN BLOCK （PIN按位异或主帐号PAN） ```
    即是为：  0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF
    异或上：  0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67
    结果为：  0x06 0x12 0x53 0xDF 0xFE 0xDC 0xBA 0x98
    ```

# 密钥使用流程

#### **一般调用流程:**

- 当做 DownloadKey 时，使用 rootKey 来生成签名，返回报文中得到中间件主密钥 mwTmk 的密文，使用 rootKey 对该密文做3DES解密，得到 mwTmk 的明文。

- 当做 SignIn 时，使用上一步中获得的 mwTmk 明文来生成签名，返回报文中得到中间件Mac秘钥(工作秘钥) mwMacKey 的密文，使用 mwTmk 明文对此密文做3DES解密，得到mwMacKey 的明文。

- 当做交易时，使用上一步中获得的 mwMacKey 明文来生成签名。