Skip to content

Repository files navigation

WikiBroker OpenAPI

WikiBroker是一个SaaS服务,它提供了大量OpenAPI以便于定制开发客户端,开发者可以通过这里提供的SDK实现接入。

接入说明

WikiBroker的OpenAPI接口都会校验请求

  1. 应用认证:请求必须包含合法有效的应用认证标识ApiKey。
  2. 请求限流:每个ApiKey的请求频率不能超过50/秒。
  3. 防延时:请求时间戳与服务端时间戳的偏差必须小于一定阈值。
  4. 防重放:相同唯一标识的重复请求会被拦截。
  5. 防篡改:参数与签名不匹配的请求会被拦截。

接入方式

在进行客户端接入前,你需要先成为WikiBroker的客户,然后联系我们为你创建专属的API Key,然后API Key会发送到你开通服务使用的邮箱中。

通过SDK接入(推荐)

根据你使用的编程语言,按需选用本仓库提供的SDK。

TypeScript/JavaScript接入

安装

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"],
        },
    },
);

Golang接入

安装

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()

Python接入

安装

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()

Java接入

安装

maven

  1. 第一步:安装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
  2. 第二步:声明maven依赖

    <dependency>
        <groupId>com.wikiglobal</groupId>
        <artifactId>wikibroker-openapi-sdk</artifactId>
        <version>0.1.0-alpha</version>
        <scope>compile</scope>

gradle

  1. 方式一:使用Groovy声明依赖

    build.gradle

    dependencies {
        implementation files('./wikibroker-openapi-sdk-0.1.0-alpha.jar')
    }
  2. 方式二:使用Kotlin声明依赖

    build.gradle.kts

    dependencies {
        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
}

PHP接入

安装

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);

C# 接入

安装

# 把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" })
);

Dart 接入

安装

  1. 第一步:解压tgz包

    tar zxf wikibroker-openapi-dart-sdk-0.1.0-alpha.tgz
  2. 第二步:声明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"},
);

Swift 接入

安装

  1. 第一步:解压zip包

    unzip wikibroker-openapi-swift-sdk-0.1.0-alpha.zip
  2. 第二步:在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

Ruby 接入

安装

// TODO

示例

# TODO

Kotlin 接入

安装

maven

  1. 第一步:安装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
  2. 第二步:声明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
}

Rust 接入

安装

  1. 第一步:解压tgz包

    tar zxf wikibroker-openapi-rust-sdk-0.1.0.tgz
  2. 第二步:在 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 发送请求
}

通过API接入

如果你使用的编程语言没有可用的SDK,可以按照以下方式自行编写接入代码。

  1. 添加自定义请求头

    1. X-Api-Key:应用访问令牌,是一个uuid格式的字符串。
    2. X-Timestamp:请求绝对时间戳毫秒数,是一个整数。
    3. X-Nonce:请求唯一标识,是一个uuid格式的随机字符串。
    4. X-Signature:请求数字签名,根据指定算法生成。
  2. 签名生成算法

    1. 将请求查询参数按key的字典序升序排列,对于相同key则再按value的字典序升序排列,然后按{key}={value}的格式用&拼接,构成规范化查询字符串canonical_query
    2. 计算请求体的sha256哈希并转换为16进制编码字符串body_hash
    3. 用换行符拼接大写请求方法、请求相对路径、canonical_queryX-Api-KeyX-TimestampX-Noncebody_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

About

WikiBroker OpenAPI SDKs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages