接口文档的正确使用-记录自己使用接口文档中的坑

昨天接口调试遇到的坑

下面是需求文档

调用地址
post 请求
https://apitest.bdc.abc.com/toilet/status/report
请求协议
参数名 必选 类型 说明
time Yes int 更新时间,Unix时间戳
male Yes Stat 男厕所状态信息
female Yes Stat 女厕所状态信息
third Yes Stat 第三卫生间
Stat节点
参数名 必选 类型 说明
in Yes int 入流量
out Yes int 出流量
stay Yes int 驻留人数
响应参数
参数名 类型 说明
code int64 返回码:0:成功,其他:失败
msg string 返回信息
data 对象 返回的数据对象
Data节点
参数名 必选 类型 说明
total Yes int 请求更新厕所数量
num Yes int 成功更新厕所数量

接口文档的正确使用-记录自己使用接口文档中的坑_第1张图片

这里要做的是根据公厕的使用情况,把数据推到服务端,好吧,我承认我是小白, 来来来,分析一下并且总结下

  1. 文档规范
    这里出现了一个节点的概念,也就是传入参数的多维数组的键值 , 转化为json也是一个属性名,只不过书面上没见过这种写法,所以不太懂了

  2. 鉴权问题
    这个问题是第二次遇见了,但是上次没有搞懂,这次也惨淡收场
    今天就好好分析下原因了
    首先是生成query_string值的问题,如上面所示, 要求query_string的格式为 path+ ‘?’ + url参数(参数进行url编码),为了必变出现特殊字符串
    这里使用的是rawurlencode进行编码的

    1. urlencode:返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。此编码与 WWW 表单 POST 数据的编码方式是一样的,同时与 application/x-www-form-urlencoded 的媒体类型编码方式一样。由于历史原因,此编码在将空格编码为加号(+)方面与 RFC1738 编码
    2. rawurlencode:返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数。这是在 RFC 1738 中描述的编码,是为了保护原义字符以免其被解释为特殊的 URL 定界符,同时保护 URL 格式以免其被传输媒体(像一些邮件系统)使用字符转换时弄乱。
  3. 包体
    说到这,可以看出我的基础有多差了,我对包体竟然不知道是什么东西,其实也就是post的数据,但是和对面的技术交流中,对面说包体,我说是不是传递的参数,我两个都都是一脸懵逼,好吧,是我的错.一会再好好看看http

  4. 生成sign值
    对传递的url参数的键值进行遍历编码,然后拼接包体(下面要讲),再进行base64编码生成一个sign值 , 是url参数编码之后,再拼接上包体生成一个sign值
  5. 请求的url
    请求的url是求口url拼接上上面的参数再额外拼接上sigin值 , 对其进行post请求
    1. 请求的包体
      也就是post过去的数据了啊 … 说这么专业不懂啊 , 但是这里遇到一个坑,以前curl post数据时,直接进行把数据以数组的形式传递就可以了,但是这次竟然不行,好吧 , 人家要的是json , 但是我发送的是数组,哎,肯定错了啊,昨天我才知道,curl post数据竟然还有两种情况 , 努力吧老年人,不知道的东西还是太多太多
    2. curl 的坑
      刚开始curl模拟请求的时候,没有任何结果,不知道怎么回事,请了个大神帮我调.他还是有经验,先是打印错误报告,我咋没想到呢…我是无脑的点击鼠标 ….
if (curl_errno($ch)) {
            echo '错误:'.curl_error($ch);
}

看到报错之后,发现了问题所在 php curl常见错误:SSL错误、bool(false)
我还以为没有装curl扩展呢,但是确认了下,是装了的,再仔细看原来是ssl证书的问题,所以要绕过ssl证书检测

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

好了,再请求接口终于能通了, 下面是总结的代码


public function actionLink()
    {
        $url            =   "https://apitest.bdc.***.com";
        $path           =   '/toilet/status/report';
        $id             =   1231644;
        $devid          =   '***';
        $device_secret  =   "**";
        $nonce = time() . rand(1000,9999);
        $time = time() ;

        $query = array(
            'mode'      =>  2,
            'id'        =>  $id,
            'devid'     =>  $devid,
            'nonce'     =>  $nonce,
            'timestamp' =>  $time,
        );


        $post_data           =   [
            'time'  => $time,
            'male'  =>  [
                'in'=>1,
                'out'=>2,
                'stay'=>66
            ],
            'female'  =>  [
                'in'=>1,
                'out'=>2,
                'stay'=>3
            ],
            'stay'  =>  [
                'in'=>1,
                'out'=>2,
                'stay'=>66
            ],
        ];


        ksort($query, SORT_STRING);
        $data = '';

        foreach($query as $key => $value) {
            $data .= rawurlencode($key).'='.rawurlencode($value).'&';
        }

        $data   = rtrim($data, '&');
        $param   = $path.'?'.$data . json_encode($post_data);
        $query['sign']  = base64_encode(hash_hmac('sha1', $data  , $device_secret, true));

        $url            = $url . $path.'?'.$data  . '&sign=' .urlencode($query['sign']);


        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $output = curl_exec($ch);


        if (curl_errno($ch)) {
            echo '错误:'.curl_error($ch);
        }

        curl_close($ch);
        print_r($output);
    }

你可能感兴趣的:(php学习)