# **1** 温馨提示


!>常见问题
- Q: 为什么传了customUrl没有跳转还提示系统错误？
- A: 如果需要传customUrl，请确保url里没有#等特殊字符
- Q: 为什么老是报token已失效？
- A: token是全局的，2个小时会自动失效。新的token生成老的会立即失效。
    token的管理： 建议贵方最好单独起个线程去管理，每隔一小时50分钟来取一次token，然后存到数据库或者缓存里，每次有用到直接去数据库或缓存里取
- Q: 为什么唤醒app方式没有跳转支付宝app?
- A: 主要有以下几种可能：1.用户手机未安装支付宝  2.app没有正确配置scheme,alipayqr 3.用户手机系统有拦截等未知情况 4.app修改了默认的useragent导致无法识别手机系统

!>注意事项
请勿通过检测最后重定向页面地址做逻辑判断处理，我方可能多渠道，每个渠道的customUrl可能不同，为了合作方不会受影响，建议合作方传入customUrl，或者等待服务端通知在做逻辑处理

- 如问题还未解决，请联系技术支持
 

!>在开始接口调用之前请先确保完成以下事项：
>1. 完成 `合作方入驻` 流程，并已经完成本产品`签约`；
2. 你需要获取一个 `appKey` 和 `appSecret`；
3. 通信协议只支持 `HTTPS`
4. 整个流程可以分为`用户授权`和`获取数据`, `用户授权`支持`H5`和`APP`, `获取数据`只支持`API`
5. `订单号（order_id）`是合作方与我方数据服务系统产生业务交互的唯一凭证，生成规则参考 `4.2`；




# **2** 开始接入

## **2.1** H5接入
!> 访问之前需要生成订单号，生成过程见附录。

 <table>
   <tr>
      <td>DOMAIN</td>
      <td colspan=4>网关</td>
   </tr>
   <tr>
      <td>PATH</td>
      <td  colspan=4>zmop/index</td>
   </tr>
   <tr>
      <td>METHOD</td>
      <td colspan=4>GET</td>
   </tr>
   <tr>
      <td rowspan=15>GET参数</td>
      <td>参数名</td>
      <td>参数类型</td>
      <td>参数描述</td>
      <td>可空</td>
   </tr>
   <tr>
         <td>appKey</td>
         <td>string</td>
         <td>平台发放给开发者的标识开发者身份的标识符</td>
         <td>NO</td>
     </tr>
   <tr>
      <td>order_id</td>
      <td>string</td>
      <td>订单号</td>
      <td>NO</td>
   </tr>
   <tr>
      <td>redirect</td>
      <td>string</td>
      <td>用户授权结束之后, 接收授权结果的异步回调地址, 须urlEncode,</td>
      <td>NO</td>
   </tr>
   <tr>
      <td>extras</td>
      <td>string</td>
      <td>合作方自定义数据, 会作为异步回调地址的参数返回给合作方</td>
      <td>YES</td>
   </tr>
   <tr>
      <td>channel</td>
      <td>string</td>
      <td>默认使用`唤醒APP`的方式进行授权, 传入`H5`将只跳转到支付宝的H5页面进行授权 `强烈建议非微信内的应用，使用唤醒APP的方式。H5授权方式有可能芝麻信用后续不再提供支持。`</td>
      <td>YES</td>
   </tr>
   <tr>
      <td>cert_no</td>
      <td>string</td>
      <td>用户的身份证号</td>
      <td>YES</td>
   </tr>
   <tr>
      <td>cert_name</td>
      <td>string</td>
      <td>用户的姓名</td>
      <td>YES</td>
   </tr>
   <tr>
      <td>cert_phone</td>
      <td>string</td>
      <td>用户的手机号</td>
      <td>YES</td>
   </tr>
   <tr>
      <td>readonly</td>
      <td>string</td>
      <td>默认为`0`, 当值为`1`时, 传入的用户三要素不能被用户修改</td>
      <td>YES</td>
   </tr>
      <tr>
      <td>customUrl</td>
      <td>string</td>
      <td>用户授权结束展示的页面, 默认为我方的结果页, 须urlEncode </td>
      <td>YES</td>
   </tr>
   <tr>
      <td>modify_no</td>
      <td>string</td>
      <td>不管readonly是否为1, 该值为1, 表示用户可以修改身份证</td>
      <td>YES</td>
   </tr>
         <tr>
      <td>modify_name</td>
      <td>string</td>
      <td>不管readonly是否为1, 该值为1, 表示用户可以修改姓名</td>
      <td>YES</td>
   </tr>
         <tr>
      <td>modify_phone</td>
      <td>string</td>
      <td>不管readonly是否为1, 该值为1, 表示用户可以修改手机号</td>
      <td>YES</td>
   </tr>
            <tr>
      <td>desensitized</td>
      <td>string</td>
      <td>该值为`1`, 表示在页面上显示的用户三要素是脱敏的(当用户自己修改或输入是不脱敏的)</td>
      <td>YES</td>
   </tr>
</table>


## **2.2** 用户授权结束通知

**通知说明**
>-当用户授权结束之后, 采用`服务端通知`到合作方, `只通知一次, 需返回状态码为200的http响应`
-通知地址为传入的redirect。注意：`redirect`里不要有`#`等特殊字符，且要包含协议名（`http`或`https`）

**请求方式：**
- Method: POST
- Content-type: application/json
- Charset: UTF-8

**参数：**

|参数名|必选|类型|说明|
|:----    |:---|:----- |-----   |
|status |是  |string |订单号对应状态(success/fail)   |
|msg  |是  |string | 任务结果的描述|
|order_id |是  |string | 任务订单号    |
|extras |否  |string |  合作方自定义数据|

 **请求示例**
```json
    {
        "status": "success",
        "msg": "操作成功",
        "order_id": "20180************tfLVD232",
        "extras": "esljdsd"
    }
```

## **2.3** 用户授权结束页面

**说明**
>当用户授权结束之后, 默认结果页为我方的页面, 如需自定义页面, 可在进入H5时传入`customUrl`。注意：`customUrl`里不要有`#`等特殊字符，且要包含协议名（`http`或`https`）

**`customUrl`上拼接以下参数:**

|参数名|必选|类型|说明|
|:----    |:---|:----- |-----   |
|status |是  |string |订单号对应状态(success/fail)   |
|msg  |是  |string | 任务结果的描述|
|order_id |是  |string | 任务订单号    |
|extras |否  |string |  合作方自定义数据|



# **3**  获取用户数据

**简要描述：**

- 根据订单号获取用户数据
- 需要签名，签名参数为params里面的参数，签名算法见`附录`

## **3.1** 获取访问令牌token

>**请求URL：** 
- ` zmop/getToken `
  
------------

>**请求方式：**


>- Method: POST
- Content-Type: application/json
- Charset: UTF-8

------------


> **参数：** 
>
|参数名|必选|类型|说明|
|:----    |:---|:----- |-----   |
|sign |是  |String |签名   |
|appKey |是  |String |公钥   |
|timestamp |是  |String | 时间戳 （单位：ms）北京时间正负一分钟有效   |

------------

 >**请求示例**


``` json

{
	"sign":"SDSKKL5KJJKLL6JK1L",
	"params":{
		"appKey":"3FD179425381644F95424B66BE06E3E4",
		"timestamp":"1494828184314"
	}
}
```


 >**返回示例1**

``` json
{
  "code": 0,
  "data": {
    "token": "cd4283827366490eb037bf1b4b28dadc"
  }
}
```

 >**返回示例2**

``` json
{
  "code": -1,
  "msg": "参数错误"
}
```

 >**返回参数说明** 

>|参数名|类型|说明|
|:-----  |:-----|-----                           |
|token |String   |访问令牌(Token的有效期为2小时，当Token未失效时调用该接口，则返回新的Token，有效期重新计算，老的Token同时失效) |
|code |String   |状态码 |
|msg |String   |错误信息 |


------------



## **3.2** 获取芝麻分数据


**请求URL：**
- `zmop/data/score `

**请求方式：**
- Method: POST
- Content-type: application/json
- Charset: UTF-8

**参数：**

|参数名|必选|类型|说明|
|:----    |:---|:----- |-----   |
|appKey |是  |string |公钥   |
|timestamp |是  |string | 时间戳 （单位：ms） 北京时间正负一分钟有效   |
|sign     |是  |string | 签名    |
|token     |是  |string | 访问令牌    |
|order_id |是  |string | 任务订单号    |


 **请求示例1**
 ``` json
  {
    "sign":"89D89A1D07E875C649D6A2D03F8E650A",
    "params":{
        "appKey": "88A03809137291F333BF2689AB85850E",
        "timestamp":"3412xxxxxx01234567",
        "token":"xx",
        "order_id":"20180408121212555qwe23qwe1232sde"
    }
  }
```

 **请求示例2**
 ``` json
  {
    "sign":"89D89A1D07E875C649D6A2D03F8E650A",
    "refresh":"1",
    "params":{
        "appKey": "88A03809137291F333BF2689AB85850E",
        "timestamp":"3412xxxxxx01234567",
        "token":"xx",
        "order_id":"20180408121212555qwe23qwe1232sde"
    }
  }
```

 **返回示例1**

``` json
  {
    "code": "0",
    "data": {
		//此处参考附录 4.3
		...
		
	}
  }
```
 **返回示例2**

``` json
  {
    "code": -1,
    "msg": "无此订单数据"
  }
```

 **返回参数说明**

|参数名|类型|说明|
|:-----  |:-----|-----                           |
|data |String   |数据结构参照4.3 |
|code |String   |状态码  |
|msg |String   |错误信息  |


 >**备注**

 >  状态码对应的错误信息
- 0   -> 成功
- -1  -> 系统异常
- -1  -> 参数错误
- -1  -> 时间戳超时
- -1  -> 无效的appKey
- -1  -> 签名错误
- -1  -> 您未开通权限
- -1  -> 无此订单号
- -1  -> 鉴权失败
- -1  -> token已失效

## **3.3** 获取行业关注名单数据


**请求URL：**
- `zmop/data/watch_list `

**请求方式：**
- Method: POST
- Content-type: application/json
- Charset: UTF-8

**参数：**

|参数名|必选|类型|说明|
|:----    |:---|:----- |-----   |
|appKey |是  |string |公钥   |
|timestamp |是  |string | 时间戳 （单位：ms）北京时间正负一分钟有效    |
|sign     |是  |string | 签名    |
|token     |是  |string | 访问令牌    |
|order_id |是  |string | 任务订单号    |


 **请求示例1**
 ``` json
  {
    "sign":"89D89A1D07E875C649D6A2D03F8E650A",
    "params":{
        "appKey": "88A03809137291F333BF2689AB85850E",
        "timestamp":"3412xxxxxx01234567",
        "token":"xx",
        "order_id":"20180408121212555qwe23qwe1232sde"
    }
  }
```


 **返回示例1**

``` json
  {
    "code": "0",
    "data": {
		//此处参考附录 4.4
		...
		
	}
  }
```
 **返回示例2**

``` json
  {
    "code": -1,
    "msg": "无此订单数据"
  }
```

 **返回参数说明**

|参数名|类型|说明|
|:-----  |:-----|-----                           |
|data |String   |数据结构参照4.4 |
|code |String   |状态码  |
|msg |String   |错误信息  |

 >**备注**

 >  状态码对应的错误信息
- 0   -> 成功
- -1  -> 系统异常
- -1  -> 参数错误
- -1  -> 时间戳超时
- -1  -> 无效的appKey
- -1  -> 签名错误
- -1  -> 您未开通权限
- -1  -> 无此订单号
- -1  -> 鉴权失败
- -1  -> token已失效



# **4** 附录

## **4.1** 签名算法

签名生成的通用步骤如下：

第一步，设所有发送或者接收到的数据为集合M，将集合M内非空参数值的参数按照参数名ASCII码从小到大排序（字典序），使用URL键值对的格式（即key1=value1&key2=value2…）拼接成字符串stringA。

特别注意以下重要规则：

- 参数名ASCII码从小到大排序（字典序）；
- 如果参数的值为空不参与签名；
- 参数名区分大小写；

第二步，在stringA最后拼接上appSecret得到stringSignTemp字符串，并对stringSignTemp进行MD5运算，再将得到的字符串所有字符转换为大写，得到sign值signValue。

举例：
假设传送的参数如下：
``` json
appKey : 88A03809137291F333BF2689AB85850E,
order_id : 426ea0df-7f1b-4491-8989-5c130291e892,
timestamp : 1494649888152
token : 0eaeb00afcc4448da724d9179a50abe7
```


第一步：对参数按照key=value的格式，并按照参数名ASCII字典序排序如下：
``` javascript
stringA="appKey=092217B6B52ED02D46EFFFA7CFA20940&order_id=3e993890-ff08-4af5-bb9b-04fda6dd2b78&phone=15658117723&timestamp=1494669826683&token=8731de2cd2604f4a856f210703541326";
```
第二步：拼接API密钥：
``` javascript
stringSignTemp=stringA+"&appSecret=192006250b4c09247ec02edce69f6a2d"
sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7"
```


## **4.2** 订单号


 释义
>`订单号（order_id）`是合作方（或机构）与我方数据服务系统产生业务交互的唯一凭证，具体表现为一个长度为 `32` 位的字符串，仅能包含 `0-9A-Za-z_-` 等字符。每一个订单号（order_id）表明了合作方（或机构）与我方数据服务系统产生了一次确定的业务交互，我方数据服务系统给出了一个确定的返回结果，并以此作为与我方数据服务系统明细对账的唯一依据



生成规则
>订单号（order_id）:前 `17` 位为精确到`毫秒`的时间值（yyyyMMddHHmmssSSS）作为前缀，以合作方（或机构）自行生成的不重复字符串作为后缀，组成 `32` 位的字符串。


## **4.3** 芝麻分数据结构


**数据字典**

|参数名|类型|说明|
|:-----  |:-----|-----                           |
|order_id |String   |订单号 |
|create_time |String   |从芝麻信用获取芝麻分的时间  |
|which_month |String   |最新芝麻分所属月|
|score |String   |芝麻分  |


### 数据样例

```json
{
    "score": "746",
    "which_month": "2018-04",
    "create_time": "2018-04-28 11:26:02",
    "order_id": "2018042710535*****QcPMRFLn8b7qYb"
  }
```


## **4.4** 行业关注名单数据结构

**数据字典**

|名称|类型|描述|
|:----    |:--- |-----   |
|order_id |String   |订单号 |
|create_time |String   |从芝麻信用获取数据的时间  |
|details |Array | 行业关注名单信息列表，由芝麻信用进行维护和升级    |
|isMatched |Boolean | true=命中 在关注名单中 false=未命中     |

**行业关注名单详细(details)信息详情:**

|名称|类型|描述|
|:----    |:---- |:-----   |
|biz_code |String   | 风险信息行业编码 |
|level |string   | 风险等级    |
|type     |String   | 	行业名单风险类型    |
|code     |String   | 风险编码     |
|refresh_time |Date | 数据刷新时间     |
|settlement |Boolean | 结清状态     |
|status     |String  | 用户本人对该条负面记录有异议时，表示该异议处理流程的状态     |
|statement |String | 当用户进行异议处理，并核查完毕之后，仍有异议时，给出的声明|
|extend_info     |Array | 扩展信息     |

**扩展信息(extend_info)信息详情:**

|名称|类型|描述|
|:----    |:--- |-----   |
|key |String | 补充信息字段的英文编码 |
|value |String | 	补充信息字段的信息内容    |
|description |String | 补充信息字段的中文描述     |


### 数据样例

```json
{
  "create_time": "2018-04-28 11:26:02",
  "order_id": "2018042710535*****QcPMRFLn8b7qYb",
  "details": [{   //行业关注名单信息列表，由芝麻信用进行维护和升级
    "biz_code": "AH",  //风险信息行业编码
    "code": "AH001002",  //风险编码
    "extend_info": [{    //扩展信息
      "description": "编号", //补充信息字段的中文描述
      "key": "id",  //	补充信息字段的英文编码
      "value": "testlwztestlwz0d090d794bd563ba6053244b35fb2ccc" //补充信息字段的信息内容
    }],
    "level": 0,  //风险等级
    "refresh_time": 1465488000000,  //	数据刷新时间
    "settlement": true, //结清状态
    "type": "AH001"  //行业名单风险类型
  }],
  "is_matched": true    //true=命中 在关注名单中 false=未命中
}

```


