/songshu-openapi

松鼠数据平台互通 OpenAPI

松鼠数据平台互通 OpenAPI

松鼠数据平台用于第三方小说平台数据互通,用于公众号内的用户精准运维。

Note
小说平台提供 API,URL 前缀可自行决定,例如 https://api.example.com/v1/,剩余部分请尽量按指定格式提供。

请使用随机 32 位字符当作接口 Secret 并同步给我们

用户查询

/${appid}/users?openid=${openid},${openid}&time=${time}

公共参数

time

当前的时间戳

业务参数

appid

公众号的微信开发者 AppId

openid

用户在公众号内的openid。查询多个用户时,使用半角 , 分隔。

返回内容

JSON Array 数组,每一项包含一个用户信息

Warning
如果 openid 不存在,不需要返回该用户信息。

示例

[
  {
    "openid": "oP7TW1X--NjWFwpApzzsS75vVHuI",
    "balance": 1.23, // 书币余额
    "ticket": 23, // 书券余额
    "charged": 2300, // 充值过的总金额
    "reg_time": "2019-08-01 12:43:23", //注册时间
    "last_read_book": "都市极品医神",
    "last_read_time": "2019-11-01 12:43:23"
},
{
    "openid": "oP7TW1Q2eC0T-p3TI5j5cQakwbcs",
    "balance": 32,
    "ticket": 23,
    "charged": 2300,
    "reg_time": "2019-08-01 12:43:23",
    "last_read_book": "都市极品医神",
    "last_read_time": "2019-11-01 12:43:23"
 }
]

字段解释

Table 1. 用户查询接口字段
字段 含义 类型 示例值

openid

用户 OpenId

string

"oP7TW1X—​NjWFwpApzzsS75vVHuI"

balance

书币余额

浮点

21.23

ticket

书券余额

浮点

23.00

charged

充值过的总金额

浮点

400.00

reg_time

注册时间

`string `

"2019-08-01 12:43:23"

last_read_book

最后阅读记录书名

string

"都市极品医神"

last_read_time

最后阅读时间

string

"2019-11-01 12:43:23"

Tip
时间的格式为 Y-m-d H:i:s

订单查询

/${appid}/orders?page=${page}&begin=${datetime}&end=${datetime}&time=${time}

例如

公共参数

time

当前的时间戳

业务参数

appid

公众号的微信开发者 AppId

page

当前页数。省略时默认值:1

begin

开始时间,格式 Y-m-d H:i:s,例如 2019-12-01 00:00:00

end

结束时间,格式 Y-m-d H:i:s,例如 2019-12-01 23:59:59

pay_status

可选项。10-1

  • -1 为全部(默认值)

  • 0 待支付

  • 1 已支付

openid

可选项。指定用户的 openid,留空时查询所有用户订单。

Tip
返回订单数量建议大于 100,小于 1000。查询接口主要用于历史数据初始化和每日订单核对,不会频繁查询。

返回示例

{
    "page": 1,
    "total": 10490,
    "page_size": 100,
    "orders": [
        {
            "amount": 80.00,
            "order_id":"4200000429201912071609677638",
            "create_time": "2019-12-07 23:59:41",
            "pay_time": "2019-12-07 23:59:46",
            "pay_status": 1,
            "openid":"oBHx1s775pANd1HWQ-aS-ou49kNA",
            "book":"他与星辰皆璀璨"
        }
    ]
}
page

当前页数

total

当前条件下的订单总数

page_size

每页订单数

orders

订单列表数组

orders 字段解释

Table 2. orders字段
字段 含义 类型 示例值

amount

订单金额

float

80.00

order_id

平台唯一订单号

string

"4200000429201912071609677638"

create_time

订单创建时间

string

"2019-12-07 23:59:41"

pay_time

订单支付时间

string

"2019-12-07 23:59:46"

pay_status

支付状态,0:未支付,1:已支付

int

1

openid

用户的OpenId

string

"oBHx1s775pANd1HWQ-aS-ou49kNA"

book

订单关联的图书,无时留空

string

"他与星辰皆璀璨"

Caution
一部分平台在支付成功时才有订单号,可留空。

主动推送通知

订单创建/支付通知(接近实时推送)

  • 需要推送的结构和订单查询中的单条订单数据一致

  • 订单在创建时、支付时分别推送一次

{
    "amount": 80.00,
    "order_id":"4200000429201912071609677638",
    "create_time": "2019-12-07 23:59:41",
    "pay_time": "2019-12-07 23:59:46",
    "pay_status": 1,
    "openid":"oBHx1s775pANd1HWQ-aS-ou49kNA",
    "book":"他与星辰皆璀璨"
}
Caution
通知推送不需要完全实时,例如每五分钟推送一次亦可。

用户信息变更通知(每日推送)

当用户如下信息在当天发生变化时,次日凌晨需要把此类用户推送至此接口,推送的内容和用户查询返回的结构完全一致。释义见上面表格。

[
  {
    "openid": "oP7TW1X--NjWFwpApzzsS75vVHuI",
    "balance": 1.23, // 书币余额
    "ticket": 23, // 书券余额
    "charged": 2300, // 充值过的总金额
    "reg_time": "2019-08-01 12:43:23", //注册时间
    "last_read_book": "都市极品医神",
    "last_read_time": "2019-11-01 12:43:23"
},
{
    "openid": "oP7TW1Q2eC0T-p3TI5j5cQakwbcs",
    "balance": 32,
    "ticket": 23,
    "charged": 2300,
    "reg_time": "2019-08-01 12:43:23",
    "last_read_book": "都市极品医神",
    "last_read_time": "2019-11-01 12:43:23"
 }
]
Caution
当用户信息变化后,请确保至少每日推送一次。如有更高的频率亦可,接口不作频率限制。

如需测试以上推送接口,可在查询参数中设置 ?test=1,服务端将正常校验,但不保存数据。

签名校验

GET 请求需要检验的参数

  • 用户查询

  • 订单查询

    QueryString 中的 time 参数

    我们会在请求接口时附带 time 参数,为当前服务器 Unix 时间戳。如果超过一定时间,接口需要返回错误信息。

    请求的 Header 中会附带 X-Hub-Signature

    这不是标准的 X-Hub-Signature,签名对象为 URL 中的路径、查询参数部分。 使用 hmac_hash .[1] 签名 PHP 中的 $_SERVER['REQUEST_URI'],例如:/v1/wx570bc396a51b8ff8/users?time=1575883879&openid=oP7TW1X—​NjWFwpApzzsS75vVHuI,oP7TW1Q2eC0T-p3TI5j5cQakwbcs

verify_get.php
<?php

function isLegalRequest($uri, $signature, $secret)
{
    return 'sha1='.hash_hmac('sha1', $uri, $secret) === $signature;
}

function isExpired($time)
{
    return ($time + 300) < time();
}

$secret = '394d5e7337578e17a7fc5e6bd5cfb2640950d054';
$uri = $_SERVER['REQUEST_URI'];
$signature = $_SERVER['HTTP_X_HUB_SIGNATURE'];
$time = filter_input(INPUT_GET, 'time');
if (isLegalRequest($uri, $signature, $secret)) {
    // 签名错误
}
if (isExpired($time)) {
    // 请求已过期
}

POST 请求

签名方法为标准 X-Hub-Signature 签名。需要对 Post 的字符串 Body 进行签名,即 X-Hub-Signature 签名。

推送数据的 PHP 示例

push.php
<?php
$secret = "394d5e7337578e17a7fc5e6bd5cfb2640950d054";
$appid = 'wx570bc396a51b8ff8';
$notifyUrl = "https://mp-notify-api.sdpku.com/v1/${appid}/users";

$body = json_encode([
    [
        "openid" => "oP7TW1X--NjWFwpApzzsS75vVHuI",
        "balance" => 1.23, // 书币余额
        "ticket" => 23.3, // 书券余额
        "charged" => 300.00, // 充值过的总金额
        "reg_time" => "2019-08-01 12:43:23", //注册时间
        "last_read_book" => "都市极品医神",
        "last_read_time" => "2019-11-01 12:43:23"
    ]
], JSON_UNESCAPED_UNICODE);

$algo = "sha1";
$signature = hash_hmac($algo, $body, $secret);
$ch = curl_init();
$headers = [
  'Content-Type: application/json',
    'Accept: application/json',
    "X-Hub-Signature: ${algo}=${signature}"
];
curl_setopt_array($ch, [
  CURLOPT_URL => $notifyUrl,
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => 'gzip,deflate',
  CURLOPT_HTTPHEADER => $headers,
  CURLOPT_POSTFIELDS => $body
]);

$content = curl_exec($ch);
var_dump(json_decode($content));

参考错误代码

正确时直接返回结果数据结构,失败时返回如下结构的 json 数据:

  • errcode 为 int 类型错误代码,必须不等于 0

  • msg 为错误的具体解释

{
    "errcode": 401000,
    "msg": "签名错误"
}

错误代码示例

40100

签名错误

41000

时间戳过期

40000

缺少参数

Note
错误代码参考 http status code,4开头为请求有误,5开头为服务器出错。接口需要保证幂等性.[2] ,当出现非 4 开头的错误代码时,支持延时后重试。

1. Node.Js可参考 x-hub-signature库,Java 可参考 xhub4j 库