Eklentileri çağırma
Bu sayfa, bir eklentinin komut ve sorgularını HTTP ile nasıl çağıracağınızı anlatır: başlıklar, sürüm denetimi, tekrar güvenliği, sonuç sorgusu ve hata zarfı. SDK kullanıyorsanız çoğunu SDK sizin yerinize yapar; yine de ne olduğunu bilmek hata ayıklamayı kolaylaştırır.
Not
Eklentiler için ortak bir
/openapi.jsonyoktur; eklentinin kendi şema belgesi (artifact)GET /v1/plugins/{plugin_id}/schemaucundan alınır. Kullanabileceğiniz işlemlerin listesi oradadır (bağlamalar).
Uçlar
| Yöntem ve yol | Amaç |
|---|---|
POST /v1/plugins/{plugin_id}/commands/{message_type} | Komutu çalıştırır |
GET /v1/plugins/{plugin_id}/commands/{message_type}/result | Komutun sonucunu idempotency anahtarıyla sorgular |
GET /v1/plugins/{plugin_id}/queries/{message_type} | Sorguyu çalıştırır (parametreler sorgu dizesinde) |
POST /v1/plugins/{plugin_id}/queries/{message_type} | Sorguyu çalıştırır (parametreler gövdede) |
GET /v1/plugins/{plugin_id}/schema | Eklentinin şema belgesini verir |
{plugin_id} eklenti kimliğidir (ör. package-ride). {message_type} işlemin istek mesaj türüdür (ör. package-ride.progression-missions.login-bonus.input); işlemin adı (claimLoginBonus) değildir. Tam yol ve mesaj türü şema belgesindeki her işlemin path ve requestMessageType alanında yazar. Hangi yöntemin (GET ya da POST) kullanılacağını da işlemin method alanı söyler: bazı sunucu sorguları POST ile çağrılır.
Kimlik
| Çağıran | Gönderilecek |
|---|---|
| Oyuncu (çerez) | Cookie (__Secure-crx.session) + x-crx-env: <ortam uuid>; değiştirici (POST) isteklerde ayrıca x-csrf-token + __Secure-crx.csrf çerezi |
| Oyuncu (Bearer) | Authorization: Bearer <oturum jetonu> + x-crx-env: <ortam uuid>. Eklenti ucu değiştirici isteklerde Bearer ile de CSRF çiftini (__Secure-crx.csrf çerezi + x-csrf-token) ister; çerezsiz istemci çifti GET /v1/auth/csrf ile alıp kendisi taşır (oturumlar ve CSRF) |
| Sunucu | Authorization: Bearer crx_live_<önek>_<gizli> (sunucu anahtarı). x-crx-env gönderirseniz anahtarın ortamıyla aynı olmalı, aksi halde 401. CSRF ve Origin denetimi uygulanmaz |
| Herkese açık sorgu | Yalnız x-crx-env; yalnız GET ve yalnız şema belgesinde access: public olan sorgular |
crx_ ile başlayan ama sunucu türünde olmayan (istemci) anahtar 401 unauthorized alır. Oyuncu isteklerinde Origin başlığı varsa ortamın izinli kökenlerinden biri olmalıdır (tarayıcı kendisi ekler); aksi halde 403 forbidden. Değiştirici bir çağrı başarılı olduğunda yanıt yeni CSRF çiftini (Set-Cookie ve x-csrf-token başlığı) döndürür; bir sonraki değiştirici istekte bunu kullanın.
Komut çağırma
POST /v1/plugins/package-ride/commands/package-ride.progression-missions.login-bonus.input HTTP/1.1
Host: oyun.example.com
Origin: https://oyun.example.com
Cookie: __Secure-crx.session=<oturum>; __Secure-crx.csrf=<csrf-çerezi>
x-crx-env: 0192a3b4-0000-7000-8000-000000000001
x-csrf-token: <csrf-jetonu>
x-crx-schema-version: 1
Idempotency-Key: 5d1f2c88-4f0b-4c8f-9f1e-9a3f6b0c1d22
If-Match: "3"
Content-Type: application/json
{"expectedVersion":"3"}
HTTP/1.1 200 OK
Content-Type: application/json
x-crx-message-type: package-ride.progression-missions.login-bonus.output
x-crx-schema-version: 1
{"version":"4","rewardMinor":"250","streak":"2","day":"19300","walletBalanceMinor":"1250","claimEventId":"0192a3b4-0000-7000-8000-0000000000c1","ledgerCorrelationId":"0192a3b4-0000-7000-8000-0000000000c2"}
| Başlık | Zorunlu | Anlam |
|---|---|---|
Idempotency-Key | komutlarda evet | Mantıksal tekrar anahtarı; boş olamaz. Kurallar |
x-crx-schema-version | evet | Gönderdiğiniz yükün şema sürümü (pozitif tam sayı); işlemin schemaVersion değeriyle eşleşmelidir. Sorgularda da zorunludur |
If-Match | hayır | Beklenen kaynak sürümü (iyimser kilit, optimistic lock). Ondalık tam sayı, tırnaklı ya da tırnaksız; * ve W/ önekli değerler 400 alır. Gerçek sürüm farklıysa 409 |
Content-Type: application/json | evet | Gövde JSON’dur ve işlemin istek şemasına uyar |
Not
Gövde alanlarındaki
int64değerler ondalık metin olarak gider ("expectedVersion":"3"), JSON sayısı olarak değil; yanıt da aynı biçimdedir. Ayrıntı: sayılar ve kodlama.int32veuint32alanlar JSON sayısıdır.
Başarılı yanıtın gövdesi, işlemin yanıt şemasına uyan JSON’dur; x-crx-message-type ve x-crx-schema-version yanıt başlıkları çıktı mesajını belirtir.
Aynı anahtarla tekrar
Ağ koparsa ya da yanıtı alamazsanız aynı Idempotency-Key ve aynı gövdeyle tekrar gönderin; sunucu işlemi ikinci kez uygulamaz, kayıtlı sonucu döner.
| Durum | Yanıt |
|---|---|
| İlk istek | İşlenir, 200 |
| Aynı anahtar, aynı gövde | Kayıtlı sonuç döner |
| Aynı anahtar, farklı gövde | 422 ve idempotency_mismatch |
| Aynı anahtarlı istek hâlâ işleniyor | 409 ve idempotency_in_flight (retryable: true); biraz sonra tekrar deneyin |
Kayıt süresi doldu (işlemin receiptRetentionSeconds değeri, örnekte 86 400 sn) | 410 ve idempotency_expired |
Yeni bir anahtar üretmek yeni bir işlem demektir; belirsiz sonuçlu bir komutu yeni anahtarla yeniden göndermeyin.
Sonuç sorgusu
Yanıtı hiç alamadığınız bir komutun sonucunu, tekrar göndermeden öğrenin:
GET /v1/plugins/package-ride/commands/package-ride.progression-missions.login-bonus.input/result?idempotency_key=5d1f2c88-4f0b-4c8f-9f1e-9a3f6b0c1d22&output_message_type=package-ride.progression-missions.login-bonus.output&output_schema_version=1 HTTP/1.1
x-crx-env: 0192a3b4-0000-7000-8000-000000000001
Cookie: __Secure-crx.session=<oturum>
Üç sorgu parametresi de zorunludur: idempotency_key, output_message_type ve output_schema_version. Yol, işlemin resultPath alanıyla aynıdır.
| Yanıt | Anlam | Ne yapmalı |
|---|---|---|
200 + gövde | Komut kesinleşmişti; gövde çıktıdır | Sonucu kullanın |
202 (boş gövde) | Henüz işleniyor | Kısa süre sonra tekrar sorgulayın |
404 | Bu anahtarla kayıt yok: komut hiç uygulanmamış | Yalnız bu durumda aynı anahtar ve gövdeyle komutu gönderebilirsiniz |
422 + reason | Komut işlendi ve iş kuralı tarafından reddedildi | Gönderme; reason makine kodudur |
410 | Kayıt süresi doldu | Sonuç bilinmiyor; durumu sorguyla yeniden okuyun |
Sorgu çağırma
GET ile parametreler sorgu dizesinde gider. Her değer önce JSON olarak ayrıştırılır; olmazsa metin sayılır; null değeri null olur. Aynı parametreyi iki kez vermek 400 alır.
GET /v1/plugins/package-ride/queries/package-ride.delivery-trip.active.input HTTP/1.1
x-crx-env: 0192a3b4-0000-7000-8000-000000000001
x-crx-schema-version: 1
Cookie: __Secure-crx.session=<oturum>
POST ile aynı alanlar JSON gövdesinde gider. Karmaşık ya da uzun girdiler için POST uygundur; hangi yöntemin geçerli olduğunu işlemin method alanından okuyun. Herkese açık sorgu örneği:
GET /v1/plugins/package-ride/queries/package-ride.world-catalog.get.input HTTP/1.1
x-crx-env: 0192a3b4-0000-7000-8000-000000000001
x-crx-schema-version: 1
Şema ucu
GET /v1/plugins/{plugin_id}/schema eklentinin şema belgesini (JSON) verir (Cache-Control: no-store). Oyuncu oturumu ya da sunucu anahtarı gerekir. Eklenti ortamınız için etkin değilse ya da grant sürümü uyuşmuyorsa 404’tür. Belgenin alanlarını ve schemaSha256 değerinin kullanımını bağlamalar sayfasında bulursunuz.
Hata zarfı
Eklenti uçları JSON hata zarfı döner (çekirdek REST uçlarının düz metin hatalarından farklı olarak; karşılaştırma için hatalar):
{"code":"conflict","message":"version conflict: expected 3, actual 5","retryable":false,"requestId":"0192a3b4-0000-7000-8000-0000000000d1"}
Yanıtta ayrıca x-request-id başlığı bulunur; destek talebinde bu kimliği iletin.
code | HTTP | retryable | Ne zaman |
|---|---|---|---|
unauthorized | 401 | hayır | Oturum/anahtar yok, geçersiz, istemci anahtarı ya da ortam uyuşmazlığı |
forbidden | 403 | hayır | CSRF ya da Origin reddi; eklenti etkin değil ya da sürüm uyuşmuyor; yasaklı hesap (message: account banned) |
module_disabled | 404 | hayır | plugins modülü kapalı (module alanı modül adını taşır) |
not_found | 404 | hayır | Bilinmeyen eklenti ya da mesaj türü; kayıt yok |
invalid_argument | 400 | hayır | Eksik/bozuk başlık, bilinmeyen şema sürümü, şemaya uymayan yük, kopya sorgu parametresi |
conflict | 409 | hayır | If-Match sürümü gerçekle uyuşmuyor |
idempotency_in_flight | 409 | evet | Aynı anahtarlı istek hâlâ işleniyor |
idempotency_mismatch | 422 | hayır | Aynı anahtar, farklı gövde |
unprocessable | 422 | hayır | İş kuralı reddi; reason alanı makine kodunu taşır |
idempotency_expired | 410 | hayır | Kayıt süresi doldu |
rate_limited | 429 | evet | Oran sınırı; Retry-After: 60 (hız sınırları) |
tenant_unavailable | 503 | evet | Ortamın yerleşimi geçici kullanılamıyor; Retry-After: 30 |
internal | 500 | evet | Sunucu hatası |
reason alanı yalnız iş kuralı reddinde (unprocessable) bulunur (ör. street_reset_too_early) ve eklentiye özgüdür; anlamı eklentinin belgesindedir. Sürüm uyuşmazlığında (conflict) mesaj beklenen ve gerçek sürümü içerir: durumu yeniden okuyup yeni sürümle tekrar deneyin.
Uyarı
Eklenti uçlarında yasaklı hesap
account_bannedkoduyla gelmez:403vecode: "forbidden",message: "account banned"döner.account_bannedkodu oyuncu kimlik uçlarına (giriş, kayıt) aittir (hatalar). İstemciniz bu iki durumu ayırt edecekse mesaja değil oturum durumuna bakın.
Örnek: komutu belirsiz sonuca karşı güvenle çağırmak
Aşağıdaki TypeScript örneği, SDK bağlamasıyla komutu hazırlar (tek Idempotency-Key üretilir), gönderir; sonuç belirsizse yeni komut üretmeden sonucu sorgular ve yalnız notFound yanıtında aynı anahtarla yeniden gönderir. demo-game eklentisi bu örnek için hazırlanmış bir kurgudur: gerçek eklentinizde işlem adlarını ve alanları kendi şema belgenizden alırsınız (bağlamalar).
import { CrxError, ErrorKind, type PlayerClient } from "@ferdiunal/open-play-ts";
import { DemoGameBinding } from "./generated/demo-game.js";
/**
* Günlük hediyeyi alır. `prepare` tek `Idempotency-Key` üretir; ağ hatasında sonuç belirsizse yeni komut üretilmez:
* önce sonuç sorgulanır, yalnız "kayıt yok" yanıtında AYNI anahtarla yeniden gönderilir.
*/
export async function claimDailyGift(client: PlayerClient, expectedVersion: bigint): Promise<bigint> {
const demo = client.plugin(DemoGameBinding);
const command = await demo.commands.claimDailyGift.prepare({ giftKey: "daily" }, { expectedVersion });
try {
const output = await command.send();
return output.walletBalanceMinor; // int64 alanlar bigint gelir
} catch (error) {
if (!(error instanceof CrxError) || error.kind !== ErrorKind.UnknownOutcome) throw error;
const outcome = await command.lookup();
if (outcome.status === "committed") return outcome.result.walletBalanceMinor;
if (outcome.status === "notFound") return (await command.resume()).walletBalanceMinor; // aynı anahtar, aynı gövde
throw error; // pending, rejected ya da expired: kör tekrar yok
}
}
/** Salt-okunur sorgu: tekrar güvenlidir, anahtar gerekmez. */
export async function hasClaimedToday(client: PlayerClient): Promise<boolean> {
const demo = client.plugin(DemoGameBinding);
const status = await demo.queries.getGiftStatus({ includeHistory: false });
return status.claimedToday;
}
Sıradaki adım
- Tipli istemci ve şema sabitleme: bağlamalar.
- Tekrar güvenliği ve sürüm denetimi kuralları: idempotency ve eşzamanlılık.