帮助中心  /  API接口规范及签名算法

API接口规范及签名算法

API接口开通

使用人人秀API服务,需要在人人秀平台申请开通该服务,

管理地址:人人秀平台(rrx.cn/open)—>设置—>API对接。联系在线客服申请开通后,系统会自动分配一个AppKey和AppSecret。

image.png


人人秀API接口必须含有下面3个参数

参数名

类型

说明

app_key

string(32)

人人秀平台分配的AppKey

time_stamp

string(14)

1970-01-01开始的时间戳,精确到毫秒

sign

string(32)

根据签名算法计算所得


签名算法

计算步骤:

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

  • 第2步,在stringA最后拼接上AppSecret得到stringSignTemp字符串,并对stringSignTemp进⾏MD5运算,再将得到的字符串所有字符转换为⼤写,得到sign值signValue。


特别注意以下重要规则:  

  • 参数名ASCII码从小到⼤排序(字典序);  

  • 如果调用接口的参数值为空则不参与签名计算;  

  • 参数名区分小写;

  • 计算签名,参数值不需要urlencode处理;

  • ⼈⼈秀平台主动发起的请求时,传送的sign参数不参与签名,将⽣成的签名与该sign值作校验;

  • ⼈⼈秀平台接⼝可能更新增加字段,签名验证必须遍历所有参数 ;

  • 人人秀平台使用PHP语言作为签名系统生成算法,使用Java等不同语言在处理汉字编码、MD5加密可能有差异导致签名不一致,MD5位数为32位;



实例演示:

假设已经开通人人秀API功能,并且获得以下信息:

AppKey=96c84928b1dce057d110ea3b3880fc83

AppSecret=eRdLi88c6I6L95PFSX1Nq69Y84xLcD3T


假设某接口需要传送如下信息:

openid:   ot1UbuBBzlE6IjEDWfyXQW3dy2S4

transaction_no:  69201704060281699381

time_stamp:  1543999047492

nonce_str:  ibuaiVcKdpRxkhJA

order_no:  19201704060281699381


按照API接口规范,实际需要传递信息为:

app_key:  96c84928b1dce057d110ea3b3880fc83

time_stamp:  1543999047492

sign: 待计算

openid:   ot1UbuBBzlE6IjEDWfyXQW3dy2S4

transaction_no:  69201704060281699381

nonce_str:  ibuaiVcKdpRxkhJA

order_no:  19201704060281699381


按照签名算法计算sign:

  • 第1步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:stringA="app_key=96c84928b1dce057d110ea3b3880fc83&nonce_str= ibuaiVcKdpRxkhJA&openid=ot1UbuBBzlE6IjEDWfyXQW3dy2S4&order_no= 19201704060281699381&time_stamp=1543999047492&transaction_no=69201704060281699381";

  • 第2步:拼接AppSecret: stringSignTemp=stringA+"&app_secret=eRdLi88c6I6L95PFSX1Nq69Y84xLcD3T"

    sign=MD5(stringSignTemp).toUpperCase() //得到C17482AB45EA3C724CB648223ED8E2D2


最后得到最终发送的数据:

app_key:  96c84928b1dce057d110ea3b3880fc83

time_stamp:  1543999047492

sign: C17482AB45EA3C724CB648223ED8E2D2

openid:   ot1UbuBBzlE6IjEDWfyXQW3dy2S4

transaction_no:  69201704060281699381

nonce_str:  ibuaiVcKdpRxkhJA

order_no:  19201704060281699381


注意事项


  • 必须在服务器端计算签名

    客户端⽣成签名地址,可能会导致以下问题:

    1.客户端易被破解,AppSecret有外泄的⻛险,危害严重!

    2.如果⽤户的⼿机端时钟不准,或者不在北京时区,会导致时间验证过期,⽆法访问。 因此签名地址务必在服务器端⽣成。

    3.如不按要求,由此导致的损失,⼈⼈秀概不负责!

  • 签名过期检查

    由⼈⼈秀对商户平台发起的请求,请求参数⾥会有time_stamp(时间戳字段),请商户平台务必根据此字段对请求的签名做过期处理,⼈⼈秀平台建议过期时间为10分钟

  • 签名失败的问题排查

    1.是否为编码异常导致。⼈⼈秀的请求部分参数会带有中⽂字符,第三方开发者需要先对请求参数做URLDecode 解码,可以在签名时遍历签名参数排查是否有字符乱码。

    2.时间戳是否精确到毫秒,部分平台代码⽣成的时间戳是精确到秒的,需要转换⼀下 


PHP示例代码

// 计算签名类

class RrxAPI

{

    protected $values = array();


    public function __construct($data=array())

    {

        foreach ($data as &$d){

            // 参数解码

            $d = urldecode($d);

        }

        $this->values = $data;

    }


    /**

     * 签名生成算法

     * @param string $secret API密钥

     * @return string 签名

     */

    public function makeSign($secret){

        //签名步骤一:按字典序排序参数

        ksort($this->values);

        $string = $this->ToUrlParams();

        //签名步骤二:在string后加入app_secret

        $string = $string . "&app_secret=".$secret;

        //签名步骤三:MD5加密

        $string = md5($string);

        //签名步骤四:所有字符转为大写

        $result = strtoupper($string);

        return $result;

    }


    /**

     * 格式化参数格式化成url参数

     */

    private function ToUrlParams()

    {

        $buff = "";

        foreach ($this->values as $k => $v)

        {

            // 排除签名参数sign 、空值 、 数组

            if($k != "sign" && $v != "" && !is_array($v)){

                $buff .= $k . "=" . $v . "&";

            }

        }


        $buff = trim($buff, "&");

        return $buff;

    }

}


// 调用签名方法,计算签名

$query_data=[

    'app_key'=>'test_app_key',

    'openid'=>'test_openid',

    'time_stamp'=>'1543999047492',

    'name'=>'张飞'

];


$apiSdk = new RrxAPI($query_data);

$secret = 'test_secret';

$sign=$apiSdk->makeSign($secret);


得到签名为 8F4CC38010A6F917E788ED99518BD589



JAVA示例代码

import cn.hutool.core.collection.CollUtil;

import cn.hutool.crypto.SecureUtil;

import cn.hutool.json.JSONObject;

import java.util.TreeMap;

public class RrxAPI {

    // 开通API,获取key

    private static final String appKey = "test_app_key";

    // 开通API,获取Secret

    private static final String appSecret = "test_secret";

    public static void main(String[] args) {

        JSONObject paramObj = new JSONObject();

        String timestamp = "1543999047492";

        String openid = "test_openid";

        String name = "张飞";

        String emptyStr = "";

        paramObj.putOnce("app_key", appKey);

        paramObj.putOnce("time_stamp", timestamp);

        paramObj.putOnce("openid", openid);

        paramObj.putOnce("name", name);

        paramObj.putOnce("emptyStr", emptyStr);

        paramObj.putOnce("sign", "sign");

        String sign = makeSign(paramObj);

        System.out.println("最终的签名字符串:" + sign);

    }

    private static String makeSign(JSONObject paramObj) {

        //排除按字典序排序参数 

        TreeMap<String, Object> sortedParamObj = CollUtil.sort(paramObj, String::compareTo);

        StringBuilder signString = new StringBuilder();

        sortedParamObj.forEach((key, value) -> {

            // 排除签名参数sign 、空值 、 数组

            if (key != "sign" && value != "") {

                signString.append(key).append("=").append(value).append("&");

            }

        });

        String fullSignString = signString + "app_secret=" + appSecret;

        System.out.println("完整的签名字符串:" + fullSignString);

        String sign = SecureUtil.md5(fullSignString);

        System.out.println("md5加密后:" + sign);

        return sign.toUpperCase();  // 转换为大写

    }

}

此代码执行结果为   8F4CC38010A6F917E788ED99518BD589


相关文档