云诊365-帮助中心云诊365-帮助中心
  • 云诊365入驻流程

    • 云诊365平台商家入驻协议
  • 用户协议

    • 用户协议
  • 隐私政策

    • 隐私政策
  • 购物指南

    • 商家会员入驻
    • 信息发布
    • 发票制度
    • 支付常见问题
  • 配送方式

    • 配送服务查询
    • 收费标准
    • 物流规则
    • 上门自提
  • 支付方式

    • 在线支付
    • 公司转账
    • 余额支付
    • 积分支付
  • 售后服务

    • 售后政策
    • 违规管理
    • 维权流程
  • 直播管理

    • 直播服务协议
    • 直播分级管理制度
  • 中金支付开户

    • 中金支付
  • 商城首页

    • 商城首页
  • 会员注册/登录

    • 会员注册
    • 会员登录
    • 忘记密码
  • 购物支付

    • 购物支付
  • 订单中心

    • 我的订单
    • 收货地址
    • 售后订单
  • 会员中心

    • 用户信息
    • 账户安全
    • 我的消息
    • 我的足迹
    • 我的收藏
    • 我的评论
    • 我的投诉
    • 我的积分
    • 我的反馈
  • 我的优惠券

    • 我的优惠券
  • 企业入驻

    • 企业入驻
  • 商家登录

    • 商家登录
  • App下载

    • App下载
  • 注册/登录

    • 注册/登录
  • 科研系统

    • 科研系统
  • 辅诊系统

    • 辅诊系统
  • 商家首页

    • 首页
  • 企业信息

    • 企业信息
  • 会员管理

    • 企业会员
    • 企业管理员
  • 网上旗舰店

    • 网上旗舰店
  • 店员权限

    • 店员管理
    • 部门管理
  • 首页装修

    • pc首页装修
    • APP首页装修
  • 快递配送

    • 配送设置
  • 内部消息

    • 内部消息
  • 电商数据

    • 商品统计
    • 订单统计
    • 流量统计
  • 企业二维码

    • 数据统计
  • 商品信息

    • 商品库
    • 初始库存量
  • 线下店管理

    • 线下店管理
    • 店铺收银台
  • 店铺商品上架

    • 店铺商品下架
    • 店铺商品库存
  • 云诊365装修

    • 店铺装修
  • 打印机管理

    • 打印机接单
  • 商品信息

    • 商品库
  • 分销商管理

    • 分销业务
    • 推广员审核
    • 推广员管理
    • 分销商管理
    • 分销点数
  • 线下店管理

    • 线下店管理
    • 店铺点数历史
  • 店铺商品管理

    • 店铺商品管理
  • 店铺会员

    • 店铺会员
  • 云诊365装修

    • 店铺装修
  • 打印机管理

    • 打印机接单
  • 订单管理

    • 商品订单
    • 虚拟订单
    • 同城配送订单
  • 评价管理

    • 评价管理
  • 售后管理

    • 退货管理
    • 退款管理
    • 线下售后反馈
    • 投诉管理
  • 发票管理

    • 发票申请
  • 商家活动

    • 满额活动
    • 优惠劵
  • 平台活动

    • 拼团活动
    • 秒杀活动
  • 核销记录

    • 核销列表
  • 订单流水数据

    • 收款流水
    • 退款流水
  • 结算账单数据

    • 结算单
  • 会员体检报告

    • 会员体检报告
  • 体检设备列表

    • 体检设备列表
  • 体检结论报告

    • 体检结论报告
  • 检测报告检索

    • 检测报告检索
  • 检测报告回调

    • 检测报告回调
  • 获取数据查询

    • 获取数据查询access_token
  • 第三方系统检测人查询接口

    • 第三方系统检测人查询接口
  • APP 单点登录

    • APP 单点登录
  • 团队管理

    • 团队管理
  • 团队查看 体检报告

    • 团队体检结论报告
  • 团队自定义结论模板

    • 团队自定义结论模板
  • 健康社区

    • 动态
    • 活动
    • 回收站
    • 课程
  • 健康直播

    • 健康直播
  • 医生信息

    • 医生信息
    • 医生考评
  • 名医咨询

    • 咨询记录
    • 订单统计
  • 处方管理

    • 处方审核
    • 处方订单
  • 药材价格库

    • 药材价格库
  • 简体中文
  • English
  • 云诊365入驻流程

    • 云诊365平台商家入驻协议
  • 用户协议

    • 用户协议
  • 隐私政策

    • 隐私政策
  • 购物指南

    • 商家会员入驻
    • 信息发布
    • 发票制度
    • 支付常见问题
  • 配送方式

    • 配送服务查询
    • 收费标准
    • 物流规则
    • 上门自提
  • 支付方式

    • 在线支付
    • 公司转账
    • 余额支付
    • 积分支付
  • 售后服务

    • 售后政策
    • 违规管理
    • 维权流程
  • 直播管理

    • 直播服务协议
    • 直播分级管理制度
  • 中金支付开户

    • 中金支付
  • 商城首页

    • 商城首页
  • 会员注册/登录

    • 会员注册
    • 会员登录
    • 忘记密码
  • 购物支付

    • 购物支付
  • 订单中心

    • 我的订单
    • 收货地址
    • 售后订单
  • 会员中心

    • 用户信息
    • 账户安全
    • 我的消息
    • 我的足迹
    • 我的收藏
    • 我的评论
    • 我的投诉
    • 我的积分
    • 我的反馈
  • 我的优惠券

    • 我的优惠券
  • 企业入驻

    • 企业入驻
  • 商家登录

    • 商家登录
  • App下载

    • App下载
  • 注册/登录

    • 注册/登录
  • 科研系统

    • 科研系统
  • 辅诊系统

    • 辅诊系统
  • 商家首页

    • 首页
  • 企业信息

    • 企业信息
  • 会员管理

    • 企业会员
    • 企业管理员
  • 网上旗舰店

    • 网上旗舰店
  • 店员权限

    • 店员管理
    • 部门管理
  • 首页装修

    • pc首页装修
    • APP首页装修
  • 快递配送

    • 配送设置
  • 内部消息

    • 内部消息
  • 电商数据

    • 商品统计
    • 订单统计
    • 流量统计
  • 企业二维码

    • 数据统计
  • 商品信息

    • 商品库
    • 初始库存量
  • 线下店管理

    • 线下店管理
    • 店铺收银台
  • 店铺商品上架

    • 店铺商品下架
    • 店铺商品库存
  • 云诊365装修

    • 店铺装修
  • 打印机管理

    • 打印机接单
  • 商品信息

    • 商品库
  • 分销商管理

    • 分销业务
    • 推广员审核
    • 推广员管理
    • 分销商管理
    • 分销点数
  • 线下店管理

    • 线下店管理
    • 店铺点数历史
  • 店铺商品管理

    • 店铺商品管理
  • 店铺会员

    • 店铺会员
  • 云诊365装修

    • 店铺装修
  • 打印机管理

    • 打印机接单
  • 订单管理

    • 商品订单
    • 虚拟订单
    • 同城配送订单
  • 评价管理

    • 评价管理
  • 售后管理

    • 退货管理
    • 退款管理
    • 线下售后反馈
    • 投诉管理
  • 发票管理

    • 发票申请
  • 商家活动

    • 满额活动
    • 优惠劵
  • 平台活动

    • 拼团活动
    • 秒杀活动
  • 核销记录

    • 核销列表
  • 订单流水数据

    • 收款流水
    • 退款流水
  • 结算账单数据

    • 结算单
  • 会员体检报告

    • 会员体检报告
  • 体检设备列表

    • 体检设备列表
  • 体检结论报告

    • 体检结论报告
  • 检测报告检索

    • 检测报告检索
  • 检测报告回调

    • 检测报告回调
  • 获取数据查询

    • 获取数据查询access_token
  • 第三方系统检测人查询接口

    • 第三方系统检测人查询接口
  • APP 单点登录

    • APP 单点登录
  • 团队管理

    • 团队管理
  • 团队查看 体检报告

    • 团队体检结论报告
  • 团队自定义结论模板

    • 团队自定义结论模板
  • 健康社区

    • 动态
    • 活动
    • 回收站
    • 课程
  • 健康直播

    • 健康直播
  • 医生信息

    • 医生信息
    • 医生考评
  • 名医咨询

    • 咨询记录
    • 订单统计
  • 处方管理

    • 处方审核
    • 处方订单
  • 药材价格库

    • 药材价格库
  • 简体中文
  • English
  • 会员体检报告

    • 会员体检报告
  • 体检设备列表

    • 体检设备列表
  • 体检结论报告

    • 体检结论报告
  • 检测报告检索

    • 检测报告检索
  • 检测报告回调

    • 检测报告回调
  • 获取数据查询

    • 获取数据查询access_token
  • 第三方系统检测人查询接口

    • 第三方系统检测人查询接口
  • APP 单点登录

    • APP 单点登录
  • 团队管理

    • 团队管理
  • 团队查看体检报告

    • 团队体检结论报告
  • 团队自定义结论模板

    • 团队自定义结论模板

第三方系统检测人查询接口

本文档定义第三方系统向平台提供检测人数据查询能力的统一接口规范。
第三方只需按照本规范实现接口,云诊平台侧即可通过配置参数完成数据接入。

1. 接口开通及业务流程说明

第三方系统检测人查询接口需要与商务员联系申请开通。
开通接口前需要先提供客户侧查询接口(依据本文档描述实现)地址。
开通成功后,云诊技术对接负责人会提供接口相应秘钥。

第三方系统检测人查询接口!

2. 设计目标

  • 标准第三方检测人数据查询接口
  • 云诊平台侧仅通过配置(URL / AppKey / Secret)完成对接
  • 支持鉴权、防篡改、防重放
  • 支持条件查询与分页
  • 支持稳定扩展与版本演进

3. 接口基本信息

项目说明
协议HTTP / HTTPS(强烈建议 HTTPS)
编码UTF-8
数据格式JSON
传参方式使用body传参

4. 接口描述

请求方法

POST

平台侧请求接口预设最大超时时间5秒,超时后设备显示超时提醒。

请求地址(建议使用)

POST /yzapi/checkperson/query

5. 鉴权机制

5.1 请求头定义

Header 名称是否必填说明
Content-Type是application/json
YZ-Timestamp是当前时间戳(毫秒)
YZ-Nonce是随机字符串(防重放)
YZ-Signature是请求签名

5.2 签名算法

查询条件(queryContent)标准原文Canonical String拼接规则

原始值类型Canonical 中的值
null空字符串 ""
""空字符串 ""
数值类型String.valueOf(value)

说明:

  • null 与 "" 在 Canonical 中等价
  • 不进行 trim
  • 不进行 URL Encode
  • 使用 UTF-8 编码,不包含 BOM
pageNumber=1&pageSize=20&userNo=U10001&mobile=188000000000&name=张三

存在null或者 ""时:

pageNumber=1&pageSize=20&userNo=&mobile=&name=张三

签名字符串拼接规则

签名字符串拼接时,各参数前后不要拼接空格/连接符等特殊符号。

appKey + timestamp + nonce + queryContent

标准查询条件原文构造 示例

    /**
     * 构造标准签名原文
     * 形如:
     * <pre>pageNumber=1&pageSize=20&userNo=U10001&mobile=1880000000000&name=张三</pre>
     *
     * @return 签名原文
     */
    public static String getSignCanonicalString(UserQueryRequest request) {

        if (request == null) {
            return "";
        }

        // 固定顺序(TreeMap 按 key 排序)
        Map<String, String> sortedParams = new TreeMap<>();

        // 注意:null → ""
        sortedParams.put("pageNumber", valueOf(request.getPageNumber()));
        sortedParams.put("pageSize", valueOf(request.getPageSize()));
        sortedParams.put("userNo", valueOf(request.getUserNo()));
        sortedParams.put("mobile", valueOf(request.getMobile()));
        sortedParams.put("name", valueOf(request.getName()));

        StringBuilder canonical = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
            canonical.append(entry.getKey())
                    .append("=")
                    .append(entry.getValue())
                    .append("&");
        }

        // 去掉最后一个 &
        canonical.deleteCharAt(canonical.length() - 1);

        return canonical.toString();
    }

    private static String valueOf(Object value) {
        return value == null ? "" : String.valueOf(value);
    }

签名Java 示例

    /**
     * 签名
     *
     * @param appKey    key(开通接口后平台侧提供)
     * @param appSecret 秘钥(开通接口后平台侧提供)
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @param body      查询参数
     * @return 签名
     */
    public static String sign(String appKey,
                              String appSecret,
                              String timestamp,
                              String nonce,
                              String body) {

        String content = appKey + timestamp + nonce + body;
        return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, appSecret)
                .hmacHex(content);
    }

6. 请求参数定义

6.1 请求体结构

{
    "pageNumber": 1,
    "pageSize": 20,
    "userNo": "123456",
    "mobile": "13800000000",
    "name": "张三"
}

6.2 分页参数说明

字段类型必填说明
pageNumberint是页码,从 1 开始
pageSizeint是每页条数(默认传递20)

6.3 查询条件说明

第三方可按自身能力支持其中部分字段。

未识别字段应忽略,不得报错。

字段类型说明
userNoString用户编号(唯一标识)
mobileString手机号
nameString用户姓名

7. 返回结果定义

7.1 成功返回示例

{
  "code": 200,
  "message": "success",
  "success": true,
  "timestamp": 1768794238380,
  "result": {
    "current": 1,
    "size": 20,
    "total": 105,
    "records": [
      {
        "userNo": "123456",
        "name": "张三",
        "mobile": "13800000000",
        "gender": "M",
        "birthday": "1995-01-01",
        "address": "",
        "allergyMedication": "",
        "medicalHistory": "",
        "idNumber": "342423199510014996",
        "height": "180.00",
        "weight": "80.00"
      }
    ]
  }
}

7.2 返回字段说明

顶层字段

字段类型说明
codeInteger状态码,200 表示成功,其他为失败
messageString状态描述
successbool接口调用成功标志:true/false
timestampLong时间戳
resultObject分页数据

result 对象

字段类型说明
currentint当前页码
sizeint每页大小
totallong总记录数
recordsarray用户数据列表

8. 检测人数据字段规范

字段类型是否必填说明
userNoString否用户唯一标识
nameString是姓名
mobileString否手机号
genderString是M-男性 / F-女性
birthdayString是yyyy-MM-dd
allergyMedicationString否过敏药物
medicalHistoryString否现病史
heightString否身高(cm)
weightString否体重(kg)
idNumberString否身份证号
addressString否住址

9. 错误码规范

9.1 错误返回示例

{
  "code": "40101",
  "message": "签名错误",
  "success": false,
  "timestamp": 1768802522287,
  "result": null
}

9.2 错误码定义

code含义
200成功
40001参数错误
40101签名错误
40102时间戳过期
40103重复请求
40104其他错误描述

10. 第三方服务端示例(Java)

/**
 * 第三方系统检测人查询接口  demo
 *
 * @author yzkj
 * @date 2026/1/19 14:42
 */
@RestController
@AllArgsConstructor
@RequestMapping("/yzapi")
public class demo {
    
    /**
     * 宽容时间
     */
    private static final long ALLOWED_TIME_WINDOW = 5 * 60 * 1000L;


    private static final String YZ_APP_KEY = "appKey";
    private static final String YZ_APP_SECRET = "appSecret";

    /**
     * 生产建议使用redis
     * 添加 TTL
     */
    private final Set<String> nonceKeyCache = ConcurrentHashMap.newKeySet();


    @PostMapping(value = "/checkperson/query")
    public ResultObj query(@RequestHeader("YZ-Timestamp") String timestamp,
                               @RequestHeader("YZ-Nonce") String nonce,
                               @RequestHeader("YZ-Signature") String signature,
                               @RequestBody UserQueryRequest requestRawBody) {

        // 1~4 步:统一鉴权
        // 1. 校验 timestamp
        long requestTime = Long.parseLong(timestamp);
        long now = System.currentTimeMillis();
        if (Math.abs(now - requestTime) > ALLOWED_TIME_WINDOW) {
            return ResultObj.error(40102, "时间戳过期");
        }

        // 2. 校验 nonce
        String nonceKey = YZ_APP_KEY + ":" + nonce;
        if (nonceKeyCache.contains(nonceKey)) {
            return ResultObj.error(40103, "重复请求");
        }
        // 生产系统建议添加 TTL 避免缓存过多随机码
        nonceKeyCache.add(nonceKey);

        // 3. 重新计算签名
        // 3.1 构造标准签名原文 Canonical String
        String signCanonicalString = getSignCanonicalString(requestRawBody);
        String expectedSignature = sign(YZ_APP_KEY, YZ_APP_SECRET, timestamp, nonce, signCanonicalString);

        // 4. 对比签名
        if (!expectedSignature.equals(signature)) {
            return ResultObj.error(40101, "签名错误");
        }

        // 5. 执行条件查询,返回分页数据
        // 自行处理业务数据查询
        List<ThirdPartyUserDTO> list = new ArrayList<>();
        // 模拟数据查询结果
        ThirdPartyUserDTO u1 = new ThirdPartyUserDTO("U10001", "张三", "13800000001", "M", "1990-01-15");
        ThirdPartyUserDTO u2 = new ThirdPartyUserDTO("U10002", "张四", "13800000002", "F", "1990-01-15");
        ThirdPartyUserDTO u3 = new ThirdPartyUserDTO("U10003", "王五", "13800000003", "M", "1990-01-15");

        list.add(u1);
        list.add(u2);
        list.add(u3);

        RecordResult recordResult = new RecordResult(1, 3, 3L, list);


        return ResultObj.data(recordResult);
    }

    /**
     * 构造查询条件标准签名原文
     * 形如:
     * <pre>pageNumber=1&pageSize=20&userNo=U10001&mobile=1880000000000&name=张三</pre>
     *
     * @return 签名原文
     */
    public static String getSignCanonicalString(UserQueryRequest request) {

        if (request == null) {
            return "";
        }

        // 固定顺序(TreeMap 按 key 排序)
        Map<String, String> sortedParams = new TreeMap<>();

        // 注意:null → ""
        sortedParams.put("pageNumber", valueOf(request.getPageNumber()));
        sortedParams.put("pageSize", valueOf(request.getPageSize()));
        sortedParams.put("userNo", valueOf(request.getUserNo()));
        sortedParams.put("mobile", valueOf(request.getMobile()));
        sortedParams.put("name", valueOf(request.getName()));

        StringBuilder canonical = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
            canonical.append(entry.getKey())
                    .append("=")
                    .append(entry.getValue())
                    .append("&");
        }

        // 去掉最后一个 &
        canonical.deleteCharAt(canonical.length() - 1);

        return canonical.toString();
    }

    private static String valueOf(Object value) {
        return value == null ? "" : String.valueOf(value);
    }

    /**
     * 签名
     *
     * @param appKey    key(开通接口后平台侧提供)
     * @param appSecret 秘钥(开通接口后平台侧提供)
     * @param timestamp 时间戳
     * @param nonce     随机数
     * @param body      查询参数
     * @return 签名
     */
    public static String sign(String appKey,
                              String appSecret,
                              String timestamp,
                              String nonce,
                              String body) {

        String content = appKey + timestamp + nonce + body;
        return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, appSecret).hmacHex(content);
    }


    /**
     * 查询参数
     */
    @Data
    public static class UserQueryRequest {
        /**
         * 当前页码,从 1 开始
         */
        private Integer pageNumber;
        /**
         * 每页条数(默认传递20)
         */
        private Integer pageSize;
        /**
         * 用户编号(唯一标识)
         */
        private String userNo;
        /**
         * 手机号
         */
        private String mobile;
        /**
         * 用户姓名
         */
        private String name;

    }

    /**
     * 检测人对象
     */
    @Data
    @AllArgsConstructor
    public static class ThirdPartyUserDTO implements Serializable {

        /**
         * 用户唯一标识
         */
        private String userNo;

        /**
         * 姓名
         */
        private String name;

        /**
         * 手机号
         */
        private String mobile;

        /**
         * 性别:M-男性 / F-女性
         */
        private String gender;

        /**
         * 生日,格式 yyyy-MM-dd
         */
        private String birthday;
        
        /**
         * 过敏药物
         */
        private String allergyMedication;

        /**
         * 现病史
         */
        private String medicalHistory;

        /**
         * 身高(cm)
         */
        private BigDecimal height;

        /**
         * 体重(kg)
         */
        private BigDecimal weight;

        /**
         * 身份证号
         */
        private String idNumber;

        /**
         * 住址
         */
        private String address;


        public ThirdPartyUserDTO(String userNo, String name, String mobile, String gender, String birthday) {
            this.userNo = userNo;
            this.name = name;
            this.mobile = mobile;
            this.gender = gender;
            this.birthday = birthday;
        }


    }


    /**
     * 分页查询返回
     */
    @Data
    @AllArgsConstructor
    public static class RecordResult implements Serializable {

        /**
         * 当前页码
         */
        private Integer current;

        /**
         * 每页大小
         */
        private Integer size;

        /**
         * 总记录数
         */
        private Long total;

        /**
         * 用户数据列表
         */
        private List<ThirdPartyUserDTO> records;

    }


    @Data
    public static class ResultObj implements Serializable {

        private static final long serialVersionUID = 1L;

        /**
         * 成功标志
         */
        private boolean success;

        /**
         * 消息
         */
        private String message;

        /**
         * 返回代码
         */
        private Integer code;

        /**
         * 时间戳
         */
        private long timestamp = System.currentTimeMillis();

        /**
         * 结果对象
         */
        private RecordResult result;


        /**
         * 返回失败
         *
         * @param code 状态码
         * @param msg  返回消息
         * @return 消息
         */
        public static ResultObj error(Integer code, String msg) {
            ResultObj resultObj = new ResultObj();
            resultObj.setSuccess(false);
            resultObj.setMessage(msg);
            resultObj.setCode(code);
            resultObj.setResult(null);

            return resultObj;
        }

        /**
         * 返回成功
         *
         * @return 消息
         */
        public static ResultObj data(RecordResult result) {
            ResultObj resultObj = new ResultObj();
            resultObj.setSuccess(true);
            resultObj.setMessage("");
            resultObj.setCode(200);
            resultObj.setResult(result);

            return resultObj;
        }


    }

}

11. 接口变更说明

2026.1.20

第三方系统检测人查询接口API上线。

最近更新: 2026/2/9 14:49
Contributors: zjx