项目文件夹

文件
wehub-resource-sync 4ce4204b6c
CI / Lint (push) Failing after 2s
CI / Build (push) Has been skipped
SDK CI / PHP SDK (push) Failing after 1s
Split PHP SDK / PHP SDK tests (push) Failing after 1s
CI / Test (push) Failing after 1s
CI / Dashboard (push) Failing after 0s
SDK CI / JavaScript SDK (push) Failing after 0s
SDK CI / Python SDK (push) Failing after 2s
SDK CI / Java SDK (push) Failing after 1s
Split PHP SDK / Mirror sdk/php -> rmyndharis/openwa-php (push) Has been skipped
CI / Test (PostgreSQL migrations) (push) Failing after 7m47s
CI / Docker Build (push) Has been skipped
chore: import upstream snapshot with attribution
2026-07-13 12:24:08 +08:00

194 行
8.2 KiB
Markdown

# OpenWA SDKs
Official client libraries for the [OpenWA](https://github.com/rmyndharis/OpenWA)
WhatsApp API Gateway.
All four SDKs are **hand-written** against the exact API surface (paths, DTOs,
response shapes) and **unit-tested with mocked HTTP transports** that assert on
the precise request URL, method, and body — so drift is caught at test time.
The wire types live in a dedicated module (`types.ts` / `types.py` / `model/`)
so they can later be regenerated by an OpenAPI codegen pass without touching the
hand-written resource methods.
| Language | Package | Notes |
| ----------------------- | ------------------------------- | --------------------------- |
| JavaScript / TypeScript | [`@rmyndharis/openwa`](javascript/) | dual ESM/CJS, bundled types |
| Python | [`rmyndharis-openwa`](python/) | sync (httpx), PEP 561 typed |
| PHP | [`rmyndharis/openwa`](php/) | sync (Guzzle, PHP 8.1+) |
| Java | [`com.rmyndharis:openwa`](java/) | sync (java.net.http + Gson, Java 17) |
## Coverage
All three SDKs expose the same fluent resource surface:
| Resource | Methods |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `sessions` | list, get, create, delete, start, stop, forceKill, getQrCode, requestPairingCode, stats |
| `messages` | list, sendText, sendImage/Video/Audio/Document/Sticker, sendLocation, sendContact, sendTemplate, reply, forward, react, delete, history, reactions, sendBulk, batchStatus, cancelBatch |
| `contacts` | list, get, check, profilePicture, phone, block, unblock |
| `groups` | list, get, create, add/remove/promote/demoteParticipants, setSubject, setDescription, leave, inviteCode, revokeInviteCode |
| `webhooks` | list, get, create, update, delete, test |
| `chats` | list, markRead, markUnread, delete, sendState |
| `labels` | list, get, forChat, addToChat, removeFromChat _(WhatsApp Business)_ |
| `channels` | list, get, messages, subscribe, unsubscribe _(Newsletters)_ |
| `catalog` | info, products, product, sendProduct, sendCatalog _(WhatsApp Business)_ |
| `status` | list, fromContact, sendText, sendImage, sendVideo, delete _(Stories)_ |
| `templates`| list, get, create, update, delete |
| `health` | check, live, ready |
> ⚠️ Endpoints requiring an `OPERATOR`-level API key are noted in the inline
> docs. Operator-only modules (`docker`, `metrics`, `infra`, `plugins`, `mcp`)
> are intentionally **not** exposed in the SDK; all user-facing resources are.
## JavaScript / TypeScript
```bash
npm install @rmyndharis/openwa
```
```typescript
import { OpenWAClient } from '@rmyndharis/openwa';
const client = new OpenWAClient({
baseUrl: 'http://localhost:2785',
apiKey: 'owa_k1_…',
});
await client.sessions.start('my-session');
const result = await client.messages.sendText('my-session', {
chatId: '628123456789@c.us',
text: 'Hello from the OpenWA SDK!',
});
console.log(result.messageId);
```
Errors are typed — branch with `instanceof`:
```typescript
import { OpenWANotFoundError, OpenWAConflictError } from '@rmyndharis/openwa';
try {
await client.messages.sendText(/* … */);
} catch (e) {
if (e instanceof OpenWAConflictError) {
/* engine not ready (409) */
}
}
```
> Requires Node 18+ (uses the global `fetch`). Pass a custom `fetch` to the
> client constructor to intercept or observability-wrap requests.
## Python
```bash
pip install rmyndharis-openwa
```
```python
from openwa import OpenWAClient, OpenWANotFoundError
client = OpenWAClient(
base_url="http://localhost:2785",
api_key="owa_k1_…",
)
client.sessions.start("my-session")
result = client.messages.send_text("my-session", {
"chatId": "628123456789@c.us",
"text": "Hello from the OpenWA Python SDK!",
})
print(result["messageId"])
```
Pass `transport=httpx.MockTransport(handler)` for testing — no global
monkey-patching required.
## PHP
```bash
composer require rmyndharis/openwa
```
```php
<?php
use OpenWA\Client;
$client = new Client([
'baseUrl' => 'http://localhost:2785',
'apiKey' => 'owa_k1_…',
]);
$client->sessions->start('my-session');
$result = $client->messages->sendText('my-session', [
'chatId' => '628123456789@c.us',
'text' => 'Hello from the OpenWA PHP SDK!',
]);
echo $result['messageId'];
```
Requires PHP 8.1+ and Guzzle 7. For testing, inject a Guzzle client whose
handler is a `MockHandler` — no global state, no network.
## Java
```xml
<dependency>
<groupId>com.rmyndharis</groupId>
<artifactId>openwa</artifactId>
<version>0.1.1</version>
</dependency>
```
```java
import com.rmyndharis.openwa.OpenWAClient;
import com.rmyndharis.openwa.model.MessageResponse;
import com.rmyndharis.openwa.model.SendTextRequest;
OpenWAClient client = new OpenWAClient("http://localhost:2785", "owa_k1_…");
client.sessions.start("my-session");
MessageResponse result = client.messages.sendText("my-session",
SendTextRequest.builder()
.chatId("628123456789@c.us")
.text("Hello from the OpenWA Java SDK!")
.build());
System.out.println(result.messageId());
```
Requires Java 17+. Errors are a typed, unchecked hierarchy — branch with
`instanceof OpenWANotFoundError` / `OpenWAConflictError`. For testing, inject a
custom `HttpTransport` that records the request — no network. See
[`java/README.md`](java/README.md) for the full guide.
## Reliability & security
- **Use HTTPS in production.** The API key is sent as `X-API-Key` on every
request and is bearer-equivalent — never send it over plaintext `http://`
outside local development.
- **No automatic retries.** A failed request raises/throws immediately; wrap
calls in your own backoff if you need retries (especially for `429`). The
injectable transport (`fetch` / `transport` / `httpClient`) is the extension
point for retry or observability middleware.
- **Redirects are never followed.** A `3xx` surfaces to the caller rather than
being followed, so the API key is never re-sent to a redirect target.
- **Default per-request timeout** is 30s (configurable). Path segments (chat /
message ids) are percent-encoded; a base-URL path prefix (e.g. behind a proxy
at `/v1`) is preserved.
## Development
```bash
# JavaScript
cd sdk/javascript && npm test && npm run build && npm run smoke
# Python
cd sdk/python && python -m pytest -q
# PHP
cd sdk/php && composer install && ./vendor/bin/phpunit
# Java
cd sdk/java && mvn -B verify
```
Each test suite mocks the HTTP layer and asserts on the exact path, so the
regression that originally shipped a broken `messages/text` path (the real path
is `messages/send-text`) can never recur silently.