WikiBroker是一个SaaS服务,它提供了大量OpenAPI以便于定制开发客户端,开发者可以通过这里提供的SDK实现接入。
WikiBroker的OpenAPI接口都会校验请求
- 应用认证:请求必须包含合法有效的应用认证标识ApiKey。
- 请求限流:每个ApiKey的请求频率不能超过50/秒。
- 防延时:请求时间戳与服务端时间戳的偏差必须小于一定阈值。
- 防重放:相同唯一标识的重复请求会被拦截。
- 防篡改:参数与签名不匹配的请求会被拦截。
在进行客户端接入前,你需要先成为WikiBroker的客户,然后联系我们为你创建专属的API Key,然后API Key会发送到你开通服务使用的邮箱中。
根据你使用的编程语言,按需选用本仓库提供的SDK。
安装
npm
npm install ./wikibroker-openapi-js-sdk-1.0.1.tgz
yarn
yarn add ./wikibroker-openapi-js-sdk-1.0.1.tgz
pnpm
pnpm add ./wikibroker-openapi-js-sdk-1.0.1.tgz
示例
fetch
import { wrappedFetch } from "wikibroker-openapi-sdk";
const apiKey = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b";
const apiSecret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
const fetch = wrappedFetch(apiKey, apiSecret);
const req = new Request("https://api.example.com/test?q1=c&q2=b&q1=a", {
method: "POST",
body: JSON.stringify({
key: "value",
}),
});
fetch(req);axios
import { axiosHook } from "wikibroker-openapi-sdk";
const apiKey = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b";
const apiSecret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
axios.interceptors.request.use(axiosHook(apiKey, apiSecret));
axios.post(
"https://api.example.com",
{
key: "value",
},
{
params: {
q1: ["c", "a"],
q2: ["b"],
},
},
);安装
tar zxf wikibroker-openapi-go-sdk-1.0.1.tgz
go mod edit -replace=wikibroker_openapi_sdk=./wikibroker_openapi_sdk
go get wikibroker_openapi_sdk示例
net/http
import sdk "wikibroker_openapi_sdk"
const apiKey = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
const apiSecret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
rawClient := &http.Client{}
client := sdk.NewHttpClient(rawClient, apiKey, apiSecret)
client.Post(
"https://api.example.com/test?q1=c&q2=b&q1=a",
map[string]any{
"key": "value",
},
)resty
import (
"bytes"
"encoding/json"
"io"
sdk "wikibroker_openapi_sdk"
)
const apiKey = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
const apiSecret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
client := resty.New()
m := sdk.NewRestyRequestMiddleware(
apiKey,
apiSecret,
func(body any) (io.ReadCloser, error) {
data, err := json.Marshal(body)
if err != nil {
return nil, err
}
return io.NopCloser(bytes.NewBuffer(data)), nil
},
)
client.AddRequestMiddleware(m)
client.R().SetBody(
map[string]any{
"key": "value",
},
).SetQueryParamsFromValues(
url.Values{
"q1": []string{"c", "a"},
"q2": []string{"b"},
},
).Post("https://api.example.com/test")grequests
import sdk "wikibroker_openapi_sdk"
const apiKey = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
const apiSecret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
data, _ := json.Marshal(
map[string]any{
"key": "value",
},
)
body := grequests.RequestBody(bytes.NewReader(data))
auth := sdk.GRequestsAuthOption(apiKey, apiSecret)
grequests.Post(
context.TODO(),
"https://api.example.com/test?q1=c&q2=b&q1=a",
body,
auth,
)gorequest
import sdk "wikibroker_openapi_sdk"
const apiKey = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
const apiSecret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
agent := gorequest.New()
sdk.LoadGorequestInterceptor(agent, apiKey, apiSecret)
data, _ := json.Marshal(
map[string]any{
"key": "value",
},
)
body := string(data)
agent.Post("https://api.example.com/test?q1=c&q2=b&q1=a").Send(body).End()安装
pip
pip install ./wikibroker_openapi_sdk-1.0.1-py3-none-any.whl
poetry
poetry add ./wikibroker_openapi_sdk-1.0.1-py3-none-any.whl
uv
uv add ./wikibroker_openapi_sdk-1.0.1-py3-none-any.whl
示例
requests
import requests
from wikibroker_openapi_sdk import build_requests_auth
API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
auth = build_requests_auth(api_key=API_KEY, api_secret=API_SECRET)
requests.post(
url="https://api.example.com/test",
params={"q1": ["c", "a"], "q2": ["b"]},
json={"key": "value"},
auth=auth,
)httpx
import httpx
from wikibroker_openapi_sdk import build_httpx_auth
API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
auth = build_httpx_auth(api_key=API_KEY, api_secret=API_SECRET)
httpx.post(
url="https://api.example.com/test",
params={"q1": ["c", "a"], "q2": ["b"]},
json={"key": "value"},
auth=auth,
)aiohttp
import aiohttp
from wikibroker_openapi_sdk import build_aiohttp_auth
API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
auth = build_aiohttp_auth(api_key=API_KEY, api_secret=API_SECRET)
async def send_request():
async with aiohttp.ClientSession() as session:
await session.post(
url="https://api.example.com/test",
params={"q1": ["c", "a"], "q2": ["b"]},
data={"key": "value"},
auth=auth,
)
send_request()安装
maven
-
第一步:安装jar包
mvn install:install-file \ -Dfile=./wikibroker-openapi-sdk-0.1.0-alpha.jar \ -DgroupId=com.wikiglobal \ -DartifactId=wikibroker-openapi-sdk \ -Dversion=0.1.0-alpha \ -Dpackaging=jar
-
第二步:声明maven依赖
<dependency> <groupId>com.wikiglobal</groupId> <artifactId>wikibroker-openapi-sdk</artifactId> <version>0.1.0-alpha</version> <scope>compile</scope>
gradle
-
方式一:使用Groovy声明依赖
build.gradledependencies { implementation files('./wikibroker-openapi-sdk-0.1.0-alpha.jar') } -
方式二:使用Kotlin声明依赖
build.gradle.ktsdependencies { implementation(files('./wikibroker-openapi-sdk-0.1.0-alpha.jar')) }
示例
java.net.http
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.wikiglobal.wikibroker.openapi.WikiBrokerOpenApi.RequestBuilderFactory;
// ...
final String API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b";
final String API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
final var factory = new RequestBuilderFactory<HttpRequest>(
API_KEY,
API_SECRET,
RequestBuilderFactory.Type.Native
);
try (var client = HttpClient.newHttpClient()) {
var builder = factory.create();
var req = builder.method("POST")
.url("https://api.example.com/test?q1=c&q2=b&q1=a")
.body("{\"key\":\"value\"")
.build();
client.send(req, HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
// Handle Exception
}okhttp
import okhttp3.OkHttpClient;
import okhttp3.Request;
import com.wikiglobal.wikibroker.openapi.WikiBrokerOpenApi.RequestBuilderFactory;
// ...
final String API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b";
final String API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
final var factory = new RequestBuilderFactory<Request>(
API_KEY,
API_SECRET,
RequestBuilderFactory.Type.OkHttp
);
var client = new OkHttpClient();
try {
var builder = factory.create();
var req = builder.method("POST")
.url("https://api.example.com/test?q1=c&q2=b&q1=a")
.body("{\"key\":\"value\"")
.build();
try (var resp = client.newCall(req).execute()) {
// Handle Response
}
} catch (Exception e) {
// Handle Exception
}apache httpclient
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ClassicHttpRequest;
import com.wikiglobal.wikibroker.openapi.WikiBrokerOpenApi.RequestBuilderFactory;
// ...
final String API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b";
final String API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
final var factory = new RequestBuilderFactory<ClassicHttpRequest>(
API_KEY,
API_SECRET,
RequestBuilderFactory.Type.Apache
);
try (var client = HttpClients.createDefault()) {
var builder = factory.create();
var req = builder.method("POST")
.url("https://api.example.com/test?q1=c&q2=b&q1=a")
.body("{\"key\":\"value\"")
.build();
client.execute(
req, resp -> {
// Handle Response
return null;
}
);
} catch (Exception e) {
// Handle Exception
}安装
mv wikibroker-openapi-php-sdk-0.1.0-alpha.zip ./
composer config repositories.local artifact ./
composer require wikiglobal/wikibroker-openapi-sdk:0.1.0-alpha示例
guzzle
use GuzzleHttp\Client;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\HandlerStack;
use WikibrokerOpenapiSdk\Api;
const API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b";
const API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());
$middleware = Api::createGuzzleSignMiddleware(API_KEY, API_SECRET);
$stack->push($middleware);
$client = new Client(['handler' => $stack]);
$client->post(
"https://api.example.com/test?q1=c&q2=b&q1=a",
[
'query' => [
"q1" => ["c", "a"],
"q2" => ["b"]
],
'json' => [
"key" => "value"
]
]
);symfony/http-client
use Symfony\Component\HttpClient\Psr18Client;
use WikibrokerOpenapiSdk\Api;
const API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b";
const API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
$rawClient = new Psr18Client();
$client = Api::createPsrHttpClientWithSign(API_KEY, API_SECRET)->setClient($rawClient);
$body = $rawClient->createStream(json_encode(["key" => "value"]));
$request = $rawClient->createRequest(
"POST",
"https://api.example.com/test?q1=c&q2=b&q1=a"
)->withBody($body);
$client->sendRequest($request);安装
# 把WikiBroker.OpenApi.Sdk.0.1.0-alpha.nupkg放在项目根目录下并执行以下命令
dotnet add package WikiBroker.OpenApi.Sdk --source ./ --version 0.1.0-alpha示例
System.Net.Http
using System.Net.Http;
using System.Net.Http.Json;
using WikiBroker.OpenApi.Sdk;
var ApiKey = Guid.Parse("ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b");
var ApiSecret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
var withSign = WikiBrokerOpenApi.CreateDelegatingHandlerConstructor(ApiKey, ApiSecret);
var client = new HttpClient(withSign(new HttpClientHandler()));
client.PostAsync(
"https://api.example.com/test?q1=c&q2=b&q1=a",
JsonContent.Create(new { key = "value" })
);安装
-
第一步:解压tgz包
tar zxf wikibroker-openapi-dart-sdk-0.1.0-alpha.tgz
-
第二步:声明pubspec依赖
dependencies: # ...其它依赖项 wikibroker_openapi_sdk: path: ./wikibroker_openapi_sdk
示例
http
import 'package:http/http.dart' as http;
import 'package:wikibroker_openapi_sdk/wikibroker_openapi_sdk.dart';
const apiKey = 'ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b';
const apiSecret = '4ae4bf20-0afa-4122-ade8-c0beca7bd5e4';
final client = createHttpClient(http.Client(), apiKey, apiSecret);
client.post(
Uri.parse("https://api.example.com/test?q1=c&q2=b&q1=a"),
body: {"key": "value"},
);dio
import 'package:dio/dio.dart';
import 'package:wikibroker_openapi_sdk/wikibroker_openapi_sdk.dart';
const apiKey = 'ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b';
const apiSecret = '4ae4bf20-0afa-4122-ade8-c0beca7bd5e4';
final client = Dio();
final interceptor = createDioRequestInterceptor(
apiKey,
apiSecret,
jsonEncode,
);
client.interceptors.add(interceptor);
client.post(
"https://api.example.com/test?q1=c&q2=b&q1=a",
data: {"key": "value"},
);安装
-
第一步:解压zip包
unzip wikibroker-openapi-swift-sdk-0.1.0-alpha.zip
-
第二步:在XCode中将解压后目录作为项目依赖包添加
示例
URLSession
import Foundation
import WikibrokerOpenapiSdk
let apiKey = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
let apiSecret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
let s = URLSession.shared
s.setAuth(apiKey: apiKey, apiSecret: apiSecret)
var req = URLRequest(URL("https://api.example.com/test?q1=c&q2=b&q1=a"))
req.httpMethod = "POST"
req.httpBody = try JSONSerialization.data(withJSONObject: [
"key": "value"
])
s.dataWithAuth(for: &req)Alamofire
import Alamofire
import Foundation
import WikibrokerOpenapiSdk
let apiKey = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
let apiSecret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
let interceptor = makeAlamofireAuthInterceptor(
apiKey: apiKey,
apiSecret: apiSecret
)
let s = Session(interceptor: interceptor)
let resp = s.request(
"https://api.example.com/test?q1=c&q2=b&q1=a",
method: HTTPMethod(rawValue: "POST"),
parameters: ["key": "value"],
encoding: JSONEncoding.default
).response安装
// TODO示例
# TODO安装
maven
-
第一步:安装jar包
mvn install:install-file \ -Dfile=./wikibroker-openapi-kotlin-sdk-0.1.0.jar \ -DgroupId=com.wikiglobal \ -DartifactId=wikibroker-openapi-kotlin-sdk \ -Dversion=0.1.0 \ -Dpackaging=jar
-
第二步:声明maven依赖
<dependency> <groupId>com.wikiglobal</groupId> <artifactId>wikibroker-openapi-kotlin-sdk</artifactId> <version>0.1.0</version> <scope>compile</scope> </dependency>
gradle
build.gradle.kts
dependencies {
implementation(files('./wikibroker-openapi-kotlin-sdk-0.1.0.jar'))
}示例
okhttp
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import com.wikiglobal.wikibroker.openapi.createOkHttpInterceptor
const val API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
const val API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
val interceptor = createOkHttpInterceptor(API_KEY, API_SECRET)
val client = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
val body = """{"key":"value"}""".toRequestBody("application/json".toMediaType())
val req = Request.Builder()
.url("https://api.example.com/test?q1=c&q2=b&q1=a")
.method("POST", body)
.build()
try {
client.newCall(req).execute().use { response ->
// Handle Response
}
} catch (e: Exception) {
// Handle Exception
}ktor
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.HttpSend
import io.ktor.client.plugins.plugin
import io.ktor.client.request.request
import io.ktor.client.request.setBody
import io.ktor.http.ContentType
import io.ktor.http.contentType
import io.ktor.http.HttpMethod
import com.wikiglobal.wikibroker.openapi.createKtorInterceptor
const val API_KEY = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b"
const val API_SECRET = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4"
val client = HttpClient(CIO)
val interceptor = createKtorInterceptor(API_KEY, API_SECRET)
client.plugin(HttpSend).intercept(interceptor)
try {
client.request {
url("https://api.example.com/test?q1=c&q2=b&q1=a")
method = HttpMethod.Post
contentType(ContentType.Application.Json)
setBody("""{"key":"value"}""")
}
} catch (e: Exception) {
// Handle Exception
}安装
-
第一步:解压tgz包
tar zxf wikibroker-openapi-rust-sdk-0.1.0.tgz
-
第二步:在
Cargo.toml中声明依赖[dependencies] wikibroker_openapi_sdk = { path = "./rust-sdk" }
示例
reqwest
use wikibroker_openapi_sdk::*;
use serde_json::json;
#[tokio::main]
async fn main() {
let api_key = "ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b";
let api_secret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
let inner = reqwest::Client::new();
let client = reqwest_client_with_auth(inner, api_key, api_secret).unwrap();
let req = inner
.post("https://api.example.com/test?q1=c&q2=b&q1=a")
.json(&json!({"key": "value"}))
.build()
.unwrap();
let resp = client.execute(req).await.unwrap();
}http
use http::{Method, Request};
use wikibroker_openapi_sdk::*;
use serde_json::json;
use uuid::Uuid;
use chrono::Utc;
use std::str::FromStr;
fn main() {
let api_key = Uuid::from_str("ef05e5b0-9daf-49e3-a0f4-9a3c13f55c3b").unwrap();
let api_secret = "4ae4bf20-0afa-4122-ade8-c0beca7bd5e4";
let mut req = Request::builder()
.method(Method::POST)
.uri("https://api.example.com/test?q1=c&q2=b&q1=a")
.body(json!({"key": "value"}))
.unwrap();
add_x_headers(&mut req, api_key, Utc::now(), Uuid::new_v4());
sign::<Request<serde_json::Value>, serde_json::Value>(&mut req, api_secret).unwrap();
// 使用 req 发送请求
}如果你使用的编程语言没有可用的SDK,可以按照以下方式自行编写接入代码。
-
添加自定义请求头
X-Api-Key:应用访问令牌,是一个uuid格式的字符串。X-Timestamp:请求绝对时间戳毫秒数,是一个整数。X-Nonce:请求唯一标识,是一个uuid格式的随机字符串。X-Signature:请求数字签名,根据指定算法生成。
-
签名生成算法
- 将请求查询参数按
key的字典序升序排列,对于相同key则再按value的字典序升序排列,然后按{key}={value}的格式用&拼接,构成规范化查询字符串canonical_query。 - 计算请求体的
sha256哈希并转换为16进制编码字符串body_hash。 - 用换行符拼接大写请求方法、请求相对路径、
canonical_query、X-Api-Key、X-Timestamp、X-Nonce、body_hash,然后生成hmac-sha256哈希并转换为16进制编码字符串,得到请求签名X-Signature。
- 将请求查询参数按
| SDK包 | 开发语言版本 |
|---|---|
| JavaScript SDK | Node 22 + TypeScript 5.9 |
| Python SDK | Python 3.12 |
| Golang SDK | Go 1.23 |
| Java SDK | Java 21 |
| PHP SDK | PHP 8.3 |
| .NET SDK | C# 12 |
| Dart SDK | Dart 3.11 |
| Swift SDK | Swift 6.3 |
| Ruby SDK | 待定 |
| Rust SDK | Rust 1.96 |
| Kotlin SDK | Java 21 + Kotlin 2.4 |