用户数据推送同步相关接口文档
目录
1概述
1.1请求规则
| 规则名称 | 描述 |
|---|---|
| 请求地址(测试环境) | 由接收分发数据系统提供 |
| 请求方式 | GET/POST |
| 参数格式 | application/json |
| 字符编码 | 统一采用UTF-8字符编码 |
1.2安全控制
系统采用如下方式保证产品需求方平台的安全性
- 平台各接口支持HTTPS协议。
- 访问任意接口都需要验证签名才能访问。
2接口说明
2.1新增-编辑用户信息同步
- 接口地址
/api/datapush/userUpdate
功能说明
当系统在平台用户新增、修改时,分发推送到相关业务系统请求方式
请求方法: POST
Content-Type: application/json
编码方式: UTF-8
- 请求参数
| 参数名称 | 参数类型 | 是否必须 | 示例值 | 描述 |
|---|---|---|---|---|
| userId | string | 是 | oUdulwb0saPji7MF_PpJLDhQ8oYM | 用户ID |
| userType | int | 是 | 0 | 用户类型 -1-游客(访客-非白名单) 0-普通白名单用户) |
| orgId | int | 是 | 项目 ID | |
| orgName | string | 是 | 项目名称 | |
| orgCode | string | 是 | 项目编码 | |
| openid | string | 是 | 微信OPENDID | |
| userMobile | string | 是 | 用户号码 | |
| userName | string | 是 | 用户姓名 | |
| virtCode | string | 是 | 企业编码 | |
| virtId | int | 是 | 企业ID | |
| virtName | string | 是 | 所属企业名称 (用户为游客时,企业信息为空) | |
| departmentId | int | 是 | 部门ID | |
| departmentName | string | 是 | 部门名称 | |
| cardNo | string | 否 | 实体卡号 | |
| cardStatus | int | 是 | 0 | 0:未绑卡 1:正常 2:已挂失 |
| cardExpiration | string | 否 | 2030-07-31 | 卡有效期 |
| userNo | string | 是 | 123123 | 用户工号 |
- 返回值
| 参数名称 | 参数类型 | 是否必须 | 示例值 | 描述 |
|---|---|---|---|---|
| code | int | 是 | 200 | 响应状态码 |
| msg | string | 是 | 签名错误 | 返回状态码信息 |
2.2用户信息删除
- 接口地址
/api/datapush/userDelete
功能说明
当系统在平台用户删除时,分发推送到相关业务系统请求方式
请求方法: POST
Content-Type: application/json
编码方式: UTF-8
- 请求参数
| 参数名称 | 参数类型 | 是否必须 | 示例值 | 描述 |
|---|---|---|---|---|
| userId | string | 是 | oUdulwb0saPji7MF_PpJLDhQ8oYM | 用户ID |
- 返回值
| 参数名称 | 参数类型 | 是否必须 | 示例值 | 描述 |
|---|---|---|---|---|
| code | int | 是 | 200 | 响应状态码 |
| msg | string | 是 | 签名错误 | 返回状态码信息 |
2.3用户信息查询
- 接口地址
/api/opendata/openinfo/userQuery
功能说明
接口由平台提供,由业务系统查询平台用户数据请求方式
请求方法: POST
Content-Type: application/json
编码方式: UTF-8
- 请求参数
| 参数名称 | 参数类型 | 是否必须 | 示例值 | 描述 |
|---|---|---|---|---|
| userId | string | 否 | oUdulwb0saPji7MF_PpJLDhQ8oYM | 用户ID |
| orgId | int | 是 | 615 | 项目id |
| startTime | string | 否 | 2023-12-01 15:00:00 | 用户最后修改开始时间 |
| endTime | string | 否 | 2024-03-01 15:00:00 | 用户最后修改结束时间 |
| pageNo | int | 否 | 1 | 第几页 默认第一页 |
| userMobile | string | 否 | 15299999999 | 手机号码 |
| cardNo | string | 否 | 9362713 | 卡号 |
- 返回值
| 参数名称 | 参数类型 | 是否必须 | 示例值 | 描述 |
|---|---|---|---|---|
| code | int | 是 | 200 | 响应状态码 |
| msg | string | 是 | 签名错误 | 返回状态码信息 |
| data | object | 否 | 返回结果,用户信息数组 |
data返回值说明
| 参数名称 | 参数类型 | 是否必须 | 示例值 | 描述 |
|---|---|---|---|---|
| totalPage | int | 是 | 5 | 总页数 |
| totalNumber | int | 是 | 52 | 总条数 |
| dataInfos | Array | 是 | 用户信息数组 |
dataInfos返回值说明
| 参数名称 | 参数类型 | 是否必须 | 示例值 | 描述 |
|---|---|---|---|---|
| userId | string | 是 | oUdulwb0saPji7MF_PpJLDhQ8oYM | 用户ID |
| userType | int | 是 | 0 | 用户类型 -1-游客(访客-非白名单) 0-普通白名单用户) |
| orgId | int | 是 | 项目 ID | |
| orgName | string | 是 | 项目名称 | |
| orgCode | string | 是 | 项目编码 | |
| openid | string | 是 | 微信OPENDID | |
| userMobile | string | 是 | 用户号码 | |
| userName | string | 是 | 用户姓名 | |
| virtCode | string | 是 | 企业编码 | |
| virtId | int | 是 | 企业ID | |
| virtName | string | 是 | 所属企业名称 (用户为游客时,企业信息为空) | |
| cardNo | string | 否 | 实体卡号 | |
| cardStatus | int | 是 | 0 | 0:未绑卡 1:正常 2:已挂失 |
| cardExpiration | string | 否 | 2030-07-31 | 卡有效期 |
3签名规则
3.1签名介绍
调用接口都需要携带签名,服务端会根据请求参数,对签名进行校验,签名不合法的请求将会被拒绝。
3.2签名方法
以接口`/api/opendata/openinfo/userQuery为例
请求的参数如下
appKey:
fwzc8EtxzIfX9Ql3Hmghtimestamp:
1680580829000userId:
ZZGX20230404173443981
平台方提供的密钥secretKey为77f44bf82004154f763a2eb4fa096487a017fe9c
- 将请求参数中除appKey、sign外的多个键值对,根据键按照字典序排序,并按照
key1=value1&key2=value2...的格式拼成一个字符串。
string str = "userId=ZZGX20230404173443981×tamp=1680580829000";- 将secretKey拼接在第一步中排序后的字符串后面得到待签名字符串。
string signTemp = str + "&secretKey=77f44bf82004154f763a2eb4fa096487a017fe9c";
//userId=ZZGX20230404173443981×tamp=1680580829000&secretKey=77f44bf82004154f763a2eb4fa096487a017fe9c- 对待签名字符串求MD5摘要并转为大写即为sign:
4CC2EB02383141C666F14D0EE681FB7A
需要注意以下规则
请求参数的值为空值(null)则不参与签名,请求参数的值为空字符串(“”)则会参与签名
参数名区分大小写
appKey、sign参数不参与签名
签名示附
public static void main(String[] args) { String url = "域名+请求接口"; Map<String, Object> json = new TreeMap<>(); json.put("timestamp", String.valueOf(new Date().getTime())); json.put("orgId", "615"); json.put("pageNo", 1); json.put("userMobile", "18106955235"); JSON.parseObject(JSON.toJSONString(json), TreeMap.class); Set<Map.Entry<String, Object>> entries = json.entrySet(); StringBuilder sb = new StringBuilder(); for (Map.Entry<String, Object> entry : entries) { String k = String.valueOf(entry.getKey()); String v = String.valueOf(entry.getValue()); if (entry.getValue() != null) { sb.append(k).append("=").append(v).append("&"); } } String signTemp = sb.append("secretKey=").append("xxxxx").toString(); json.put("appKey", "xxxxxx"); json.put("sign", DigestUtils.md5Hex(signTemp).toUpperCase()); HttpResponse response = HttpRequest.post(url) .body(JSON.toJSONString(json)) .contentType("application/json") .execute(); System.out.println(response.getStatus()); System.out.println(response.body()); }解析示例
public static boolean verifyParamSign(Map<String, Object> param, String secretKey) { log.info("SystemSignRuleVerifyUtil-verifyParamSign param:{},secretKey:{}", JsonUtils.toJson(param), secretKey); if (param == null || param.isEmpty()) { return false; } TreeMap<String, Object> objectObjectTreeMap = new TreeMap<>(); param.forEach((key, value) -> { if (key.equals("appKey") || key.equals("sign")) { } else { objectObjectTreeMap.put(key, value); } }); if (objectObjectTreeMap.isEmpty()) { return false; } StringBuilder sb = new StringBuilder(); Set<Map.Entry<String, Object>> entries = objectObjectTreeMap.entrySet(); for (Map.Entry<String, Object> entry : entries) { String k = String.valueOf(entry.getKey()); String v = String.valueOf(entry.getValue()); if (entry.getValue() != null) { sb.append(k).append("=").append(v).append("&"); } } String signTemp = sb.append("secretKey=").append(secretKey).toString(); log.info("---verifyParamSign- pre sign:{}", signTemp); String sign = Objects.requireNonNull(MD5.MD5(signTemp)).toUpperCase(); String paramSign = param.get("sign").toString(); log.info("---verifyParamSign- param-sign:{},analysis-sign:{}", paramSign, sign); if (!paramSign.equals(sign)) { return false; } return true; }
附录:结果码code说明
| code状态码 | 说明 |
|---|---|
| 200 | 成功 |
| 500 | 失败 |
文档更新时间: 2025-01-16 15:07 作者:吴长福