ThunderPhone 2.0 அறிமுகமாகிவிட்டது.நீங்களே தொடங்கலாம்; நிமிடத்திற்கு 2¢ முதல்.அறிவிப்பைப் படிக்கவும்

Operations

வெப்ஹுக் கையொப்பங்களைச் சரிபார்க்கவும்

ThunderPhone அனுப்பும் ஒவ்வொரு வெப்ஹுக் மற்றும் கருவி கோரிக்கையும் கையொப்பமிடப்பட்டிருக்கும். இங்குள்ள முறையைப் பயன்படுத்தி கையொப்பத்தை ஒருமுறை சரிபார்க்கவும்; பின்னர் நீங்கள் இயக்கும் ஒவ்வொரு எண்ட்பாயிண்ட்டிலும் அதே சரிபார்ப்பை மீண்டும் பயன்படுத்தவும்.

உங்கள் சர்வருக்கு நாங்கள் அனுப்பும் ஒவ்வொரு கோரிக்கையிலும் — வெப்ஹுக் டெலிவரிகள் மற்றும் கருவி-எண்ட்பாயிண்ட் அழைப்புகள் — X-ThunderPhone-Signature ஹெடரில் ஒரு HMAC-SHA256 கையொப்பம் இருக்கும். சரிபார்ப்பை ஒருமுறை சரியாக அமைத்து, அதே உதவியாளரை ஒவ்வொரு ஹேண்ட்லரிலும் பயன்படுத்துங்கள்.

அல்காரிதம்

  1. மூல கோரிக்கை உடலைப் படியுங்கள் — நாங்கள் உங்களுக்கு POST செய்த துல்லியமான பைட்கள்.
  2. hmac_sha256(secret, body).hexdigest()-ஐ கணக்கிடுங்கள்.
  3. X-ThunderPhone-Signature உடன் நிலையான நேரத்தில் ஒப்பிடுங்கள். (எளிய சரம் ஒப்பீடு நேரத் தகவலை வெளிப்படுத்தும்.)

நாங்கள் அனுப்பும் துல்லியமான பைட்களிலேயே கையொப்பமிடுகிறோம், எனவே மூல உடலை சரிபார்ப்பது எப்போதும் செயல்படும். அந்த பைட்கள் பேலோடின் நியமமான JSON தொடராக்கமும் ஆகும் — விசைகள் அகரவரிசையில் வரிசைப்படுத்தப்பட்டு, சுருக்கமான பிரிப்பான்களுடன் (இடைவெளிகளின்றி , மற்றும் :), UTF-8. உங்கள் ஃப்ரேம்வொர்க் பாகுபடுத்தப்பட்ட JSON-ஐ மட்டுமே வழங்கும்போது, இதனால் முழுமையாகச் சமமான இரண்டாவது முறையும் கிடைக்கும்: நியமமாக மீண்டும் தொடராக்கி, அதற்கு HMAC செய்யுங்கள்.

# Equivalent to hashing the raw body:
import json
canonical = json.dumps(payload, separators=(",", ":"), sort_keys=True).encode("utf-8")

மூல உடலையே முன்னுரிமையாகப் பயன்படுத்துங்கள் — அது ஒரு படி குறைவானது; சில மொழிகளில் JSON எண்களை மீண்டும் மாற்றும் நுணுக்கங்களிலிருந்தும் பாதுகாப்பானது.

எந்த ரகசியம்?

மூலம்ரகசியம்
வெப்ஹுக் எண்ட்பாயிண்ட் (/v1/developer/webhook-endpoints)உருவாக்கும்போது ஒருமுறை வழங்கப்படும் எண்ட்பாயிண்ட்-ஒன்றுக்கான secret (48 ஹெக்ஸ் எழுத்துகள்)
பழைய ஒற்றை-URL வெப்ஹுக்GET /v1/webhook-இல் வழங்கப்படும் நிறுவனம்-ஒன்றுக்கான secret
கருவி-எண்ட்பாயிண்ட் அழைப்பு (உங்கள் endpoint.url-க்கு நேரடி அழைப்பு)நிறுவன-நிலை வெப்ஹுக் ரகசியம் (பழைய ஒற்றை-URL வெப்ஹுக்கில் உள்ளதே) — எண்ட்பாயிண்ட்-ஒன்றுக்கான ரகசியம் அல்ல

ரகசியத்தை உங்கள் ரகசிய மேலாளர் அல்லது env மாறியில் சேமியுங்கள் — அதை ஒருபோதும் கமிட் செய்யாதீர்கள்.

குறிப்பு செயலாக்கங்கள்

நான்கும் மூல கோரிக்கை உடலைச் சரிபார்க்கின்றன:

Python
import hashlib
import hmac
 
 
def verify(body: bytes, signature: str, secret: str) -> bool:
    """Constant-time HMAC-SHA256 verification."""
    expected = hmac.new(
        secret.encode("utf-8"),
        body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, signature or "")
Node.js
import crypto from "node:crypto";
 
export function verify(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  if (!signature || expected.length !== signature.length) return false;
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature),
  );
}
Go
package webhook
 
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
)
 
func Verify(body []byte, signature, secret string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(body)
    expected := hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(signature))
}
Ruby
require "openssl"
 
def verify(body, signature, secret)
  expected = OpenSSL::HMAC.hexdigest("SHA256", secret, body)
  Rack::Utils.secure_compare(expected, signature.to_s)
end

கட்டமைப்புக்கேற்ப இணைப்பு

FastAPI
from fastapi import FastAPI, HTTPException, Request
 
app = FastAPI()
 
@app.post("/thunderphone-webhook")
async def hook(request: Request):
    body = await request.body()           # raw bytes, NOT request.json()
    sig = request.headers.get("X-ThunderPhone-Signature", "")
    if not verify(body, sig, SECRET):
        raise HTTPException(status_code=401)
 
    import json
    event = json.loads(body)
    # … dispatch on event["type"] …
    return {"ok": True}
Express
import express from "express";
 
const app = express();
 
app.post(
  "/thunderphone-webhook",
  // IMPORTANT: parse as raw; do NOT use express.json() here.
  express.raw({ type: "application/json" }),
  (req, res) => {
    const sig = req.header("X-ThunderPhone-Signature") || "";
    if (!verify(req.body, sig, process.env.WEBHOOK_SECRET)) {
      return res.sendStatus(401);
    }
    const event = JSON.parse(req.body.toString("utf8"));
    // … dispatch on event.type …
    res.sendStatus(204);
  },
);
Django
import json
 
from django.http import JsonResponse, HttpResponseForbidden
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
 
 
@csrf_exempt
@require_POST
def hook(request):
    body = request.body  # raw bytes
    sig = request.headers.get("X-ThunderPhone-Signature", "")
    if not verify(body, sig, SECRET):
        return HttpResponseForbidden("invalid signature")
    event = json.loads(body)
    # … dispatch on event["type"] …
    return JsonResponse({"ok": True})

டூல் அழைப்புகளைச் சரிபார்த்தல்

ஏஜென்ட் உங்கள் செயல்பாட்டு டூல்களில் ஒன்றை நேரடியாக அழைக்கும்போது (அந்த டூலுக்கு ஒரு endpoint இருக்கும்), கோரிக்கையில் நீங்கள் கட்டமைத்துள்ள endpoint.headers உடன் இந்த இரண்டு ThunderPhone தலைப்புகளும் இருக்கும்:

  • X-ThunderPhone-Call-ID — நடப்பிலுள்ள அழைப்பின் எண் அடையாளம்.
  • X-ThunderPhone-Signature — துல்லியமான கோரிக்கை-உடல் பைட்டுகளின் மீது, உங்கள் நிறுவன-நிலை வெப்ஹூக் ரகசியத்தை விசையாகக் கொண்ட HMAC-SHA256.

அதே verify() உதவியாளர் மாற்றமின்றி செயல்படும்; ஆனால் இரண்டு கவனிக்க வேண்டியவை உள்ளன:

  1. GET / DELETE டூல்களுக்கு உடல் இருக்காது. அளவுருக்கள் வினவல் அளவுருக்களாக அனுப்பப்படும்; கையொப்பம் வெற்று பைட் சரத்தின் மீது கணக்கிடப்படும் — அதாவது verify(b"", sig, secret) (Python) அல்லது verify(Buffer.alloc(0), sig, secret) (Node). வினவல் சரத்தை ஹாஷ் செய்யாதீர்கள்.
  2. பழைய வெப்ஹூக் கட்டமைக்கப்படாத நிறுவனங்களுக்கு நிறுவன ரகசியம் இருக்காது. அந்த நிலையில் டூல் அழைப்புகள் X-ThunderPhone-Call-ID மட்டுமே கொண்டிருக்கும்; கையொப்பத் தலைப்பு இருக்காது. கையொப்ப ரகசியத்தைப் பெற பழைய வெப்ஹூக்கை (PUT /v1/webhook) கட்டமைக்கவும் அல்லது endpoint.headers மூலம் உங்கள் சொந்தத் தலைப்பைப் பயன்படுத்தி டூல் அழைப்புகளை அங்கீகரிக்கவும்.
@app.post("/tools/search-appointments")
async def tool(request: Request):
    body = await request.body()  # b"" for GET/DELETE tools
    sig = request.headers.get("X-ThunderPhone-Signature", "")
    call_id = request.headers.get("X-ThunderPhone-Call-ID", "")
    if not verify(body, sig, ORG_WEBHOOK_SECRET):
        raise HTTPException(status_code=401)
    args = json.loads(body)
    ...

வெப்ஹூக்-பயன்முறை டூல் அனுப்புதல் (endpoint இல்லாத டூல்கள், உங்கள் நிறுவன வெப்ஹூக்கிற்கு telephony.tool / web.tool ஆக அனுப்பப்படுபவை) ஒரு சாதாரண கையொப்பமிடப்பட்ட வெப்ஹூக் ஆகும் — மேலே உள்ள நிலையான முறையே பொருந்தும். இரண்டு கோரிக்கை வடிவங்களுக்கும் செயல்பாட்டு டூல்களை பார்க்கவும்.

பொதுவான சிக்கல்கள்

இயல்புநிலை வடிவமைப்புடன் மீண்டும் வரிசைப்படுத்துதல்

body-ஐப் பாகுபடுத்தி, உங்கள் JSON நூலகத்தின் இயல்புநிலை அமைப்புகளுடன் (, / :-க்குப் பின் இடைவெளிகள், சேர்க்கை வரிசையிலான key-கள்) மீண்டும் வெளியிடுவது வேறுபட்ட byte-களை உருவாக்கி HMAC-ஐ செயலிழக்கச் செய்கிறது. மூல body-ஐச் சரிபார்க்கவும் — அல்லது நீங்கள் மீண்டும் வரிசைப்படுத்த வேண்டியிருந்தால், எங்கள் நியம வடிவத்துடன் துல்லியமாகப் பொருத்தவும்: வரிசைப்படுத்தப்பட்ட key-கள், சுருக்கமான பிரிப்பான்கள், UTF-8.

Framework தானாக JSON-ஐப் பாகுபடுத்துகிறது

Express-இன் express.json() middleware body stream-ஐப் பயன்படுத்திவிடும்; இதனால் மூல byte-களை இழப்பீர்கள். webhook route-க்கு மட்டும் express.raw()-ஐப் பயன்படுத்தவும், அல்லது pre-middleware-இல் மூல body-ஐ buffer செய்யவும். NestJS / Koa-விற்கும் இதுவே பொருந்தும் — அவற்றின் "raw body" ஆவணங்களைப் பார்க்கவும்.

நேர-பாதுகாப்பற்ற ஒப்பீடு

JS-இல் expected === signature அல்லது Python-இல் expected == signature நேரத்தைப் பொறுத்து மாறும் ஒப்பீடுகள். முறையே crypto.timingSafeEqual அல்லது hmac.compare_digest-ஐப் பயன்படுத்தவும். செயல்திறன் வேறுபாடு இல்லை.

Tool endpoint-களுக்கான தவறான ரகசியம்

நேரடி tool-endpoint அழைப்புகள் org-நிலை webhook ரகசியம் (GET /v1/webhook) மூலம் கையொப்பமிடப்படுகின்றன — /v1/developer/webhook-endpoints-இலுள்ள endpoint-தனிப்பட்ட ரகசியம் மூலம் அல்ல. அதே verify() செயல்பாட்டை மீண்டும் பயன்படுத்தவும்; ஆனால் tool route-களில் அதற்கு org ரகசியத்தையே வழங்குவதை உறுதிசெய்யவும்.

GET/DELETE tool-களில் query string-ஐ hash செய்தல்

body இல்லாத tool முறைகளில், கையொப்பம் வெற்று byte string-ஐ உள்ளடக்கும்; இதனால் ஒரே பொதுவான நடைமுறை கிடைக்கிறது: மூல கோரிக்கை body எதுவாக இருந்தாலும், அதையே HMAC செய்யவும். URL அல்லது query string-ஐ hash செய்தால் ஒருபோதும் பொருந்தாது.

பொருந்தாதபோது 401-ஐ வழங்காமை

சரிபார்ப்பு தோல்வியடைந்தபோது 200-ஐ வழங்குவது handler-ஐ replay இலக்காக மாற்றுகிறது. சரிபார்ப்பு தோல்வியடைந்தால் எப்போதும் 2xx அல்லாத பதிலை வழங்கவும்.


அடுத்த படிகள்