เข้ารหัสแบบ programmatic — เฉพาะสมาชิก Ultra สร้างคีย์ที่ บัญชี → API key แล้ววางคีย์ใน URL ของ endpoint ด้านล่างได้เลย
| แผน | ไฟล์ละสูงสุด | API access | ต้อง multipart ไหม? |
|---|---|---|---|
| Free | 5 KB | — | — |
| Pro | 100 MB | — | ไม่ต้อง (PUT ครั้งเดียวพอ) |
| Ultra | 300 MB | มี | ไฟล์ >100 MB ต้อง multipart |
Cloudflare edge จำกัด request body เดียวที่ 100 MB ไฟล์ที่ใหญ่กว่านั้นต้องตัดเป็น part ละ 50 MB แล้วใช้ endpoint multipart ด้านล่าง
POST https://webhook.binaryphp.com/upload/<api_key>
X-BPHP-Filename: plugin.php # บังคับ extension เป็น .php หรือ .zip
X-BPHP-Domain: app.example.com,*.example.com
X-BPHP-Mac: aa:bb:cc:dd:ee:ff # ทางเลือก
X-BPHP-Expire: 2027-12-31 # ทางเลือก
X-BPHP-Webhook: https://you.example.com/wh # ทางเลือก สำหรับการแจ้งเตือนแบบ async
<binary ของไฟล์เป็น request body>
→ 200 {
"job_id": "...",
"download_url": "https://...presigned R2 URL...",
"expires_at": "2026-05-09T...",
"size": 12345,
"license": { "domains": [...], ... }
}
curl บรรทัดเดียว:
curl -X POST https://webhook.binaryphp.com/upload/$API_KEY \
-H "X-BPHP-Filename: plugin.php" \
-H "X-BPHP-Domain: app.example.com" \
--data-binary @plugin.php
3 ขั้น: init → PUT แต่ละ part → complete
POST https://webhook.binaryphp.com/upload/<api_key>/init
X-BPHP-Filename: bigplugin.zip
X-BPHP-Total-Size: 200000000
→ 200 {
"job_id": "...",
"upload_id": "...", # R2 multipart opaque id
"r2_key": "uploads/<job_id>.zip",
"part_size": 52428800, # แนะนำ 50 MB ต่อ part
"part_count": 4,
"max_part_size": 104857600, # 100 MB hard limit
"parts": [
{ "part_no": 1, "upload_url": "https://...presigned PUT..." },
{ "part_no": 2, "upload_url": "..." },
{ "part_no": 3, "upload_url": "..." },
{ "part_no": 4, "upload_url": "..." }
]
}
upload_urlpresigned URL เหล่านี้ยิงตรง R2 ไม่กิน Worker bandwidth
ต้องเก็บ ETag header ของแต่ละ PUT response ไว้ ส่งพร้อมในขั้น complete:
PUT <upload_url>
<อ่าน part_size byte จาก offset (part_no-1)*part_size ของไฟล์>
← 200 OK
ETag: "abc123def456..."
แต่ละ part ต้อง ≥5 MB (part สุดท้ายเล็กกว่าได้) และ ≤100 MB
POST https://webhook.binaryphp.com/upload/<api_key>/complete
Content-Type: application/json
{
"upload_id": "...",
"r2_key": "uploads/<job_id>.zip",
"filename": "bigplugin.zip",
"parts": [
{ "part_no": 1, "etag": "\"abc...\"" },
{ "part_no": 2, "etag": "\"def...\"" },
{ "part_no": 3, "etag": "\"ghi...\"" },
{ "part_no": 4, "etag": "\"jkl...\"" }
],
"domain": "app.example.com",
"mac": "",
"expire": "2027-12-31",
"plugin": "",
"webhook": ""
}
→ 200 { "job_id", "download_url", "expires_at", "size", "license" }
ถ้า upload part ระหว่างทางล้มเหลว ให้เรียก /upload/<api_key>/abort
พร้อม { upload_id, r2_key } เพื่อกัน part ที่เหลือค้างใน R2 และโดนคิดเงิน
ตั้ง X-BPHP-Webhook (หรือ "webhook" ใน complete body)
เพื่อรับ event encode.completed การแจ้งเตือนส่งจาก Cloudflare edge IP
ไม่เปิดเผย IP ของ host เรา body ลงนาม HMAC-SHA256 โดยใช้ API key ของคุณเป็น shared secret:
POST <webhook URL ของคุณ>
X-BinaryPHP-Signature: t=1736208000,v1=<hex>
X-BinaryPHP-Event: encode.completed
Content-Type: application/json
{
"event": "encode.completed",
"job_id": "...",
"download_url": "...",
"expires_at": "...",
"size": 12345,
"license": { ... }
}
ตัวอย่างการตรวจสอบ (PHP):
$sig_h = $_SERVER['HTTP_X_BINARYPHP_SIGNATURE'] ?? '';
[$tpart, $vpart] = array_pad(explode(',', $sig_h, 2), 2, '');
$ts = (int) substr($tpart, 2);
$got = substr($vpart, 3);
if (abs(time() - $ts) > 300) http_response_code(401);
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', "$ts.$body", $YOUR_API_KEY);
if (!hash_equals($expected, $got)) http_response_code(401);
ext-curl เลือก single หรือ multipart flow ตามขนาดไฟล์อัตโนมัติ
ถ้าระหว่างทางล้มเหลว abort R2 multipart ให้กัน part เหลือเสียเงิน
API_KEY=bphp_live_xxx php upload.php big.zip --domain=app.example.com
requests ตัดสินใจอัตโนมัติ + abort cleanup เหมือนกัน
| status code | ความหมาย | วิธีจัดการ |
|---|---|---|
| 401 | คีย์ผิดหรือถูกเพิกถอน | สร้างใหม่ที่「บัญชี → API key」 |
| 402 | แผนไม่รองรับ operation นี้ (เช่น Free upload zip) | upgrade แผน |
| 413 | ไฟล์ / Content-Length เกินขีดจำกัดของแผน | เปลี่ยนเป็น multipart หรือ upgrade Pro→Ultra (300 MB) |
| 400 | ขาด field หรือรูปแบบผิด (filename, parts ฯลฯ) | ดู response body จะระบุว่า field ไหนขาด |
| 502 | operation R2 multipart ล้มเหลว | ลอง init ใหม่ R2 ล้มเหลว <1% เป็นบางครั้ง |