Download the PHP package rewloy/rewloy-php without Composer
On this page you can find all versions of the php package rewloy/rewloy-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download rewloy/rewloy-php
More information about rewloy/rewloy-php
Files in rewloy/rewloy-php
Package rewloy-php
Short Description Rewloy API için resmî PHP kütüphanesi / The official PHP library for the Rewloy API
License MIT
Homepage https://github.com/Rewloy/rewloy-php
Informations about the package rewloy-php
Rewloy PHP
Rewloy API'nin resmî PHP kütüphanesi.
Durum: önizleme (0.x), Packagist'te yayımlandı. API kararlı; kütüphane arayüzü 1.0'a kadar değişebilir.
Rewloy, işletmelerin dijital sadakat kartlarını müşterinin telefonuna koyar. Kart türleri damga, puan, VIP, cashback, hediye kartı, kupon ve indirimdir:
- iPhone'da Apple Cüzdan;
- Android'de Rewloy Cüzdan ve Google Cüzdan;
- her yerde web kartı.
Kasada QR okutulur; bakiye, ödül ve kampanyalar kartın kendisinde güncellenir. Panelde yapılabilen her şey Rewloy API v1 ile de yapılabilir; bu kütüphane onu PHP'den kullanır. Geliştirici belgeleri: https://rewloy.com/gelistiriciler.
- Tipli. API'nin her işlemi,
operationIdadıyla bir metottur. Argümanlar ve yanıtlar, OpenAPI belgesinden (openapi.json) üretilen PHPDoc dizi şekilleriyle (array shape) gelir. PhpStorm, Intelephense ve PHPStan anahtarları tanır. CI belgeyi her gün okur ve değişince yeniden üretir. - Bağımlılıksız. PHP 8.2 ve üstü;
curl,jsonvehasheklentileri yeter. - Güvenli tekrar. Geçici hatalarda ölçülü yeniden deneme; satışta, kasa
işleminde ve kampanyada
Idempotency-Key. - Ötesi: sayfalama, canlı akış (SSE), webhook imzası doğrulama, kullanımdan kalkma uyarıları.
Kurulum
PHP 8.2 ya da üstü ve curl eklentisi gerekir:
Başlarken
Her işlem, adı operationId olan bir metottur
(API referansı). Tek bir dizi alır,
işlemin gerektirdikleriyle:
params: adresteki parametreler ({serial},{id}…);query: sorgu parametreleri;body: JSON gövde;merchant:Rewloy-Merchantbaşlığı;idempotencyKey:Idempotency-Keybaşlığı (satış, kasa işlemi, kampanya ve mağaza iadesinde zorunlu);timeout(saniye) vemaxRetries.
Metot yanıttaki datayı dizi olarak döndürür. Sayfalı listelerde
['data' => …, 'meta' => …] döner. Gövdesiz yanıtta (204) dönüş değeri
yoktur. Dosyada (QR, harita, CSV, .pkpass) baytları taşıyan bir string
döner.
Her metodun PHPDoc'u, argümanların ve yanıtın şeklini, API'nin açıklamasını
ve referanstaki yerini taşır. İşlemin almadığı bir anahtar (örneğin yanlış
yazılmış idempotency_key) InvalidArgumentException atar. İşlem tablosu da
açıktır: Rewloy\Generated\Operations::get('passAction') →
['method' => 'POST', 'path' => …, 'auth' => …, 'idempotency' => 'required', …].
Kimlik
| İstemci | Ne için |
|---|---|
new Client(apiKey: 'rwk_…') |
API anahtarı: kasa, e-ticaret, kendi sisteminiz |
new Client(staffSession: 'rws_…', merchant: $isletmeId) |
ekip oturumu: bir kişinin işletme uygulaması |
new Client(holderSession: 'rwh_…') |
kart sahibi oturumu: Rewloy Cüzdan gibi müşteri uygulamaları |
new Client() |
kimlik istemeyen uç noktalar: giriş, katılım, kod |
merchant, ekip oturumu birden fazla işletmede koltuk taşıyorsa hangi işletme
için çalıştığını söyler (Rewloy-Merchant). Her çağrıda merchant ile
değiştirilebilir. Oturumlar kimliksiz bir istemciyle açılır:
Bir işlem istemcinin kimlik türünü kabul etmiyor ama kimliksiz de çalışıyorsa
(örneğin login), istemci onu kimliksiz çağırır. API, işlemin kabul etmediği
bir kimliği reddeder (CREDENTIAL_NOT_ALLOWED).
Diğer seçenekler:
baseUrl(varsayılanhttps://app.rewloy.com; sonuna/v1eklemeniz ya da eklememeniz fark etmez:https://app.rewloy.com/v1de olur, kütüphane/v1i kendisi ekler);timeout: bir denemeye verilen süre, saniye (60);maxRetries(2);transport: kendi HTTP katmanınız (aşağıda);userAgent: gönderilenUser-Agenta eklenir, örneğin'KasaPOS/4.2'.
Başka bir adres (staging)
API'nin başka bir kopyasına (kendi staging ortamınız ya da bir vekil sunucu)
baseUrl ile bağlanılır:
Gerçek müşterilere dokunmadan denemek için adres değiştirmeniz gerekmez: test modu aynı adreste, ayrı bir test ortamıyla çalışır.
Kart vermek ve kasada işlem
Satış: recordSale
Kasa ya da kendi yazılımınız için en kolay yol recordSaledir: "bu satış
oldu, sen yaz". Ödenen toplamı (kartın para biriminde, kuruş) gönderirsiniz;
ne yazılacağına kartın türü ve programın kendi kuralı karar verir. Kartın
türünü bilmeniz gerekmez.
actions[].ready, kartın kendi durumuna göre işlemin şimdi yapılıp
yapılamayacağıdır (damga ödülü hazır mı, puan bir ödüle yetiyor mu, bakiye var
mı, kupon kullanılmamış mı, VIP ziyareti bu pencerede sayılmış mı). rewardReady
aynen kalır ama türe göre anlam değiştirir: damga ve puanda "ödül hazır";
cashback ve hediye kartında bakiye sıfırdan büyükse; VIP'te her zaman
true. Kasa ekranında "Ödül hazır" yazısını yalnız damga ve puanda gösterin.
GET /v1/passes/{serial} ayrıca actions (kartın aldığı kasa işlemleri ve
şimdi yapılıp yapılamayacakları) ve sale (bir satışın bu kartta ne
yazacağı) alanlarını verir.
İade. reverseSale bir satışın karta yazdığını geri alır; satışı
yazarken gönderdiğiniz anahtarla (saleKey) ya da referencela bulur:
Bir satış bir kez geri alınır (tekrar duplicate: true döner). Kazanılan
kullanılmışsa (ödüle ya da harcamaya gitmişse) 409 SALE_ALREADY_SPENT gelir ve
hiçbir şey yazılmaz.
Çevrimdışı kasa kuyruğu: occurredAt. Bağlantı koptuğunda satışı sonra
yazıyorsanız occurredAt ile satışın gerçekten olduğu anı (ISO 8601, saat
dilimiyle) gönderin; kartın geçmişinde o anla görünür. Gelecekte olamaz (2
dakikalık saat farkı kabul edilir). idempotencyKey kuyruktaki kayıtla birlikte
saklanır, tekrar gönderilince satış ikinci kez yazılmaz.
Kasa işlemini iptal etmek: reverseAction. passAction ile yapılan bir
harcama, ödül ya da kullanım yanlışlıkla yapıldıysa (spend, spend-points,
redeem-stamps, redeem-reward, use) reverseAction tamamını geri verir.
İşlemi, yaparken gönderdiğiniz Idempotency-Key (actionKey) ya da işlemin
reference değeriyle bulur (passAction artık isteğe bağlı bir reference
alır). reverseAction bir Idempotency-Key istemez: bir işlem bir kez geri
alınır, tekrar duplicate: true döner.
passActionın yanıtı kart türüne göre iki biçimdedir (PHPDoc'ta iki dizi
şeklinin birleşimi): bakiyeli kartlarda balance (damga, puan, VIP, cashback,
hediye kartı), kupon ve indirim kartında status, uses ve usesLeft
(isset($sonuc['uses']) ile ayırın; PHPStan bunu daraltır).
Kazanımlar (earn-stamps, earn-points, visit) reverseActionla değil
reverseSalela geri alınır.
Yazımın yanıtında kartın durumu: card. recordSale, passAction,
reverseSale ve reverseAction yanıtları card taşır: yazımdan sonraki kart,
getPass'in customer hariç aynı alanlarıyla (programName, currency,
stamps/points/money, actions…). Yazımla aynı işlemde okunur, yanıtın
balance'ıyla aynı anı söyler. Tekrarda (duplicate: true) kartın
şimdiki durumudur. Kimliğin kartın programında passes.read yetkisi yoksa
(yalnız kasa yetkisi olan bir eklenti anahtarı) card nulldır. recordSale
yanıtındaki reversed: true, bu anahtarla yazılan satışın sonradan geri
alındığını söyler (yalnız bir tekrarda olabilir; credited ilk isteğin
yazdığıdır, kart onu artık taşımaz): fişi yeniden yazmak için yeni bir anahtar
gönderin.
Kartın işlemleri: listPassOperations. Kartın defterindeki işlemler,
yeniden eskiye, sayfalı ($rewloy->paginate('listPassOperations', ['params' => ['serial' => $seri]])):
bir kasa ekranındaki "son işlemler" listesi ve her birinin İade düğmesi için;
kasanın kendi anahtar günlüğünü tutması gerekmez. Her işlemde undoWith hangi
uç noktanın geri aldığını ('sale/reverse' ya da 'actions/reverse'),
reversible bu kimliğin şimdi geri alıp alamayacağını söyler; bu kimliğin kendi
işlemlerinde saleKey ya da actionKey de gelir.
occurredAt reddedilirse 400 VALIDATION gelir ve
$e->details[0]['reason'] nedeni söyler: in_future, too_old (72 saatten
eski), before_issue (kart o anda yoktu: occurredAt olmadan yeniden
gönderin), invalid. Tanımadığınız bir reason'ı invalid gibi ele alın.
Fiş satırları ve kazanım kuralları (API 1.3)
recordSale fişin satırlarını da alabilir (lines, en çok 500: lineId, name,
sku, category bir metin ya da yol, quantity üç ondalıkla, unit,
unitPriceMinor, discountMinor, totalMinor, kind, tags; fiş indirimi
receiptDiscountMinor). İşletmenin kuralı yoksa kazanım eskisi gibidir. Kural varsa
yanıt earn taşır: her satırın durumu (earned, no_rule, excluded,
below_unit_price, refunded…), hangi gruplarda ve hangi kuralda olduğu ve toplam,
adım adım (sınırlar, kampanya, credited). Satırların toplamı ödenenle tutmazsa
422 LINES_TOTAL_MISMATCH, 500'den fazlaysa 422 TOO_MANY_LINES.
LINE_NOT_FOUND (satışta öyle bir satır yok) ve LINE_ALREADY_REFUNDED yalnız
satırla iadede gelir. Ürün grupları (createEarnGroup, listEarnGroups…, bir
grup kategorilerden, SKU'lardan, adlardan ya da etiketlerden kurulur) ve bir
programın kuralları (getEarnRules, putEarnRules ve tek kural işlemleri;
her kayıt bir sürümdür ve revision ile karşılaştırılıp yazılır:
409 REVISION_CONFLICT) de API'dedir. Kuralları denemek için ayrıca
listEarnTemplates.
Şube QR'ı ve şube dondurma (API 1.3)
Her şubenin kalıcı bir QR'ı vardır (listLocations ve getLocation'da qr:
code, url, state). publicBranch o sayfanın verisini kimlik göndermeden
okur; QR'ın kendisi ve basılacak sayfalar bayt dizisi olarak gelir:
QR'daki kartların listesi getLocationQrItems / putLocationQrItems (listenin
versionı ile; başkası değiştirmişse 409 QR_LIST_CHANGED), addQrItems ve
previewLocationQr ile düzenlenir. Kart sahibinin işlemleri (holderBranch,
joinHolderBranch) Rewloy Cüzdan oturumu ister, API anahtarı değil.
Şube dondurma: freezeLocation ekip oturumu ve kişinin şifresi ister (API
anahtarı 403 CREDENTIAL_NOT_ALLOWED alır); notu değiştirmek
(updateLocationFreeze), başlamamış dondurmayı iptal etmek
(cancelLocationFreeze) ve şubeyi açmak (unfreezeLocation) locations.freeze
yetkili anahtarla da olur. Donuk şubenin kasası 409 LOCATION_FROZEN der; her
şubesi donuk olan işletme 409 BUSINESS_FROZEN der. Ücretsiz gün hakkı
listLocationFreezes'ta. Yeni webhook olayları: pass.extended, location.frozen,
location.unfrozen, business.paused, business.resumed.
copyProgram yalnız hediye kartı, kupon ve indirim kartını kopyalar; bir
sadakat kartı 422 NOT_AN_INSTRUMENT alır.
Idempotency-Key
recordSale, passAction, sendCampaign ve refundShopRedemption bir
Idempotency-Key ister: API'nin tanımında (OpenAPI) bu başlık bu işlemlerde
zorunludur, bu yüzden idempotencyKey bu metotlarda zorunlu bir argümandır.
Verilmezse (ya da null ise) kütüphane istek göndermeden
InvalidArgumentException atar; sizin yerinize anahtar üretmez. Üretilmiş
rastgele bir anahtar yalnızca tek çağrının yeniden denemelerini korurdu:
uygulama çöküp yeniden başlarsa yeni bir anahtar çıkar ve satış ikinci kez
yazılabilirdi. Anahtarı kendiniz üretip satışla birlikte saklayın. Anahtar
8–64 karakterlik görünür ASCII olmalıdır (0x21–0x7E: harf, rakam ve noktalama;
boşluk, Türkçe harf ya da fiş gibi ASCII dışı karakter olmaz); aksi halde
kütüphane yine istek göndermeden InvalidArgumentException atar. Başlığın
isteğe bağlı olduğu işlemlerde (örneğin issuePass) anahtar verilmezse
kütüphane bir UUID üretir ve aynı çağrının her denemesinde aynısını gönderir.
- Anahtar bir kimlik için kalıcı olarak tekildir (8–64 karakter; defterden
hiç silinmez). Aynı anahtarla aynı isteğin tekrarı ikinci kez yazmaz ve
ilk sonucu
duplicate: trueile döndürür. Aynı anahtar başka bir gövdeyle422 IDEMPOTENCY_KEY_REUSEDalır. - Fiş numarası tek başına anahtar olamaz: yazarkasa fiş numaraları Z
raporundan sonra yeniden başlar. Kasa + Z no + fiş no birleşimi
(
kasa3-z0187-fis0042) ya da satışla birlikte saklanıp tekrarda yeniden gönderilen bir UUID kullanın. - Fiş numarası
referencealanına yazılır; müşterinin geçmişinde ve işlem dökümünde görünür.
Sayfalama
paginate sayfalı her listeyi (page/limit ve meta) öğe öğe dolaşır ve
son sayfada durur. Döngüden çıkınca sonraki sayfayı istemez. Tek bir sayfa
için metodun kendisi yeter:
Canlı akış
liveFeed (işletmenin tezgâh akışı) ve holderCardEvents (kart sahibinin
kartındaki değişiklik) sunucu olayları (text/event-stream) yayınlar.
$rewloy->stream('liveFeed', $argumanlar) aynı işi görür. Her olay
(Rewloy\ServerSentEvent) event, data ve id taşır; json() veriyi
çözer.
- Yeniden bağlanma. Bağlantı koparsa akış kendiliğinden yeniden bağlanır:
sunucunun
retry:süresi kadar bekler, bir olayidtaşıdıysaLast-Event-IDgönderir.'reconnect' => falsebunu kapatır. - Sessiz bağlantı. API 25 saniyede bir
: hbgönderir; 60 saniye hiç veri gelmezse bağlantı kopmuş sayılır (idleTimeout). - Durdurmak: döngüden
breakile çıkın; bağlantı hemen kapanır. Akışı bir değişkende tutuyorsanızunset()ile bırakın. - Bitiren hatalar. Yeniden bağlanmanın düzeltemeyeceği bir hata (
401,403,404) akışı birRewloyExceptionile bitirir. - Nerede çalışır. Akış uzun sürer. Onu bir web isteğinde değil, komut satırında sürekli çalışan bir işçide okuyun (supervisor, systemd). PHP-FPM isteklerinin süre sınırı vardır.
Webhook doğrulama
Rewloy her teslimi imzalar:
Rewloy\Webhook::verify() imzayı ham gövdeyle ve webhook oluşturulurken
bir kez gösterilen sırla (whsec_…) doğrular:
- karşılaştırmayı sabit sürede yapar (
hash_equals); tşimdiden 300 saniyeden ($tolerance) uzaksa reddeder;- gövdeyi çözülmüş bir dizi olarak döndürür.
Webhook'u panelden ya da API'den ekleyebilirsiniz. webhooks.manage yetkili
bir API anahtarı createWebhook, listWebhooks, getWebhook,
setWebhookStatus, testWebhook ve listWebhookDeliveriesyi çağırabilir;
webhookEvents abone olunabilecek olayları söyler. Sır (secret) yalnız
createWebhook yanıtında gelir, saklayın:
Adres herkese açık bir https adresi olmalıdır (test ortamında da);
yerelde bir tünel kullanın.
Sırrı yenilemek. Kaybolan ya da sızan bir sır için rotateWebhookSecret
webhook'a yeni bir sır verir (yeni secret yalnız o yanıtta döner); webhook'u
silip yeniden eklemek gerekmez. Eski sır 24 saat daha yeninin yanında imzalar:
o sürede Rewloy-Signature iki v1 taşır ve teslimler
Rewloy-Signature-Rotating: 1 başlığıyla gelir. Webhook::verify() her v1'i ve
$secret olarak verilen birden çok sırrı dener; yenilemeden önce alıcınızı
[$yeni, $eski] ile güncelleyin. deleteWebhook webhook'u teslim geçmişiyle
birlikte kalıcı siler (204).
Tutmazsa WebhookSignatureException atar: 400 ile yanıtlayın ve hiçbir işlem
yapmayın. Gövde mutlaka ham olmalıdır. JSON olarak çözülüp yeniden yazılan bir
gövde imzayı tutturmaz.
Düz PHP:
Laravel (routes/api.php; buradaki yollar CSRF jetonu istemez):
Laravel 11 ve üstünde routes/api.php dosyasını php artisan install:api
ekler. Yolu routes/web.php'ye koyarsanız bootstrap/app.php içinde CSRF
denetiminden çıkarın: $middleware->validateCsrfTokens(except: ['rewloy/webhook']).
Symfony:
İki çerçevede de getContent() ham gövdeyi verir. $request->all(),
$request->toArray() ya da json_decode sonrası yeniden yazılan bir gövde
imzayı tutturmaz.
Başlıklar:
Rewloy-Event: olay türü (pass.issued,pass.activity,pass.voided,webhook.test); gövdedekitypeile aynı.Rewloy-Delivery: teslimin kimliği. Teslim "en az bir kez"dir: çift gelen teslimi bununla ayıklayın.
Gövde kişinin iletişim bilgisini taşımaz; kişiyi customer_id ile API'den
okuyun. 2xx ile yanıtlanmayan bir teslim yaklaşık 45 saat içinde toplam 8 kez
denenir ve her deneme yeni bir t ile imzalanır. Yeni olay türleri gelebilir:
type'a göre seçerken bir varsayılan dal bırakın. Kendi işleyicinizi test
etmek için Webhook::sign($govde, $sir) aynı başlığı üretir.
Webhook'un durumu. Webhook nesnesinde (listWebhooks, getWebhook,
setWebhookStatus, createWebhook ve rotateWebhookSecret'ın webhook'u)
iki tarih alanı hep vardır, ikisi de boş olabilir (string|null, bir tarih):
pausedUntil: alıcınız art arda iki kez5xx,429verdi ya da yanıt vermedi; açık webhook'un teslimleri bu ana kadar bekler, sonra kendiliğinden yeniden denenir (60 saniye). Bekletilmiyorsa ya da webhook kapalıysa boştur.resumableUntil: webhook'u kurallar kapattı ve bekleyen teslimleri saklanıyor (kapanıştan 24 saat sonrasına kadar). Bu andan öncesetWebhookStatus(['params' => ['id' => $id], 'body' => ['active' => true]])ile açarsanız kaldığı yerden devam eder: saklananlar hemen gider, kapalıyken olan olaylar da gelir. Açıksa, bir kişi ya da anahtar kapattıysa ya da süre geçtiyse boştur.
Hatalar ve yeniden deneme
RewloyException şunları taşır:
status: HTTP durumu (yanıt gelmediyse 0);getCode()de bunu verir;errorCode: API'nin sabit kodu (hata kodları); kodunuz buna göre davranmalı. HepsiRewloy\Generated\ErrorCodesabitleridir. PHP'ningetCode()'u bir tam sayı döndürdüğü için adıcodedeğilerrorCode'dur;title: kodun katalogdaki başlığı;detail: API'nin açıklaması (Türkçe, değişebilir);details: varsa ayrıntı; doğrulama hatasında[['field' => …, 'rule' => …, 'message' => …]];requestId:x-request-id; destek talebinde bunu verin;body,headers,docsveoperation.
Alt sınıflar:
RateLimitException:429;retryAftersaniye. Her istisna (bu dahil) yanıtınRateLimit-*başlıklarını$e->rateLimit()ile verir (Rewloy\RateLimit:limit,remaining,reset; başlık yoksanull);ConnectionException: yanıt gelmedi (status0,errorCodeCONNECTION_ERROR);TimeoutException: zaman aşımı (TIMEOUT); birConnectionException'dır.
Rewloy'un olmayan bir hata gövdesi (örneğin bir vekil sunucunun 502 sayfası)
HTTP_502 gibi bir kodla gelir; JSON olmayan bir başarılı yanıt
INVALID_RESPONSE ile.
Yeniden deneme. Şunlar en çok maxRetries kez (varsayılan 2) yeniden
denenir: bağlantı hatası, zaman aşımı, 429, 502, 503, 504 ve
Cloudflare'in 520–524 hataları.
- Bekleme: üstel ve rastgele (0,5 sn, 1 sn, 2 sn… en çok 8 sn); yanıt
Retry-Aftertaşıyorsa o kadar.Retry-After60 saniyeden uzunsa beklenmez, hata size gelir. - Yalnız tekrarı güvenli istekler:
GET,PUT,DELETEveIdempotency-KeytaşıyanPOST. İlk istek hâlâ işlenirken gelen409 IDEMPOTENCY_IN_PROGRESSde beklenip yeniden denenir. DiğerPOSTvePATCHistekleri hiç tekrar edilmez. - Süre: her deneme
timeout(varsayılan 60 sn) içinde bitmelidir.
Kullanımdan kalkma
Kalkacak bir uç nokta en az 180 gün önceden duyurulur. O süre boyunca her
yanıtı Deprecation, Sunset ve Link başlıklarını taşır.
- Uyarı. Kütüphane her işlem için bir kez
trigger_error()ile birE_USER_DEPRECATEDbildirimi verir. Bildirim işlemi,Sunsettarihini ve değişiklik günlüğündeki kaydı söyler. - Nereye gider. PHP onu hata günlüğüne yazar. Laravel,
LOG_DEPRECATIONS_CHANNELile seçilen kanala yazar (seçilmezse atar); Symfony kendi günlüğüne alır. - Kapatmak:
error_reporting(E_ALL & ~E_USER_DEPRECATED). - Bildirim çağrıyı bozmaz. Hata işleyiciniz bildirimleri istisnaya
çevirse de çağrı yanıtını döndürür; bildirim o zaman
error_log()a gider. - PHPDoc. Kalkacak metot
@deprecatedolarak işaretlenir; editörünüz üstünü çizer. Kalkacak yanıt alanları da metodun açıklamasında listelenir.
Yanıtın tamamı ve test modu
request($islem, $argumanlar) her işlemi çağırır ve yanıtın tamamını
(Rewloy\Response) döndürür: data, sayfalı listede meta, status,
headers, requestId, mode ve replayed (rateLimit() istek sınırı
başlıklarını okur).
mode, yanıtın Rewloy-Mode başlığıdır: live ya da test. Başlık yoksa
null.
Test modu
Gerçek müşterilere dokunmadan denemek için işletmenizin bir test ortamı
vardır: ona bağlı ayrı bir işletme (adı "· Test" ile biter); kendi
programları, müşterileri, kartları, anahtarları ve webhook'ları. Panel →
Geliştirici → "Test ortamını aç" ya da POST /v1/test/environment. Orada
oluşturulan anahtar rwk_test_ ile başlar ve aynı adreste, aynı yollarla
çalışır:
- Test ortamı hiçbir şey göndermez (e-posta, bildirim, SMS); kartlar
cüzdanlara eklenmez. Gönderilmeyenler
GET /v1/test/messagesile okunur. - Webhook'lar teslim edilir ve
Rewloy-Test: 1başlığıyla"test": truetaşır. - Gerçek müşteri verisini test ortamına girmeyin.
resetTestEnvironment(1.2.0'dan beri) müşterileri, kartları, kodları ve kayıtları siler; ortamın kimliği, programları, şubeleri, anahtarları ve webhook'ları kalır, entegrasyonunuz aynı anahtarla sürer. Bir anahtar sızdıysa'body' => ['revokeKeys' => true]anahtarları da geçersiz kılar ve webhook'ları kapatır. Yanıtdeletedvekeptsayılarını verir;closedartık hepnulldır.- POS için anahtar:
createApiKey(['body' => ['kind' => 'pos', 'locationId' => $subeId, 'register' => 'Kasa 1', 'password' => $sifre]])hazır Kasa rolüyle yalnız o şubede çalışan bir anahtar oluşturur; yanıttakibaseUrlPOS'a yazılacak adrestir. listAllBatchesişletmenin bütün hediye kartı, kupon ve indirim kodlarını sayfalar (status:open,full,expired,closedya daarchived: kodun programı arşivde, bağlantısı kart vermez). Arşivdeki bir programa kod oluşturmak409 PROGRAM_ARCHIVEDverir.sendBatchLinkkodun bağlantısını yalnız kod kart verirken e-postayla gönderir: durdurulmuş kod410 BATCH_CLOSED, süresi dolmuş410 BATCH_EXPIRED, kartları bitmiş410 BATCH_FULL, programı arşivde olan409 PROGRAM_ARCHIVEDverir ve e-posta gitmez (1.2.0'dan önce son üçünde de giderdi). KodlarıRewloy\Generated\ErrorCodesabitleri (ErrorCode::BATCH_FULL…) içindedir.
Ayrıntı: https://rewloy.com/gelistiriciler#test-ortamı
HTTP katmanı
Varsayılan katman Rewloy\Http\CurlTransport'tur: bağlantıları çağrılar
arasında açık tutar, yönlendirme izlemez. Vekil sunucu ya da kendi sertifika
deponuz için ona curl seçenekleri verin:
Kendi katmanınız için Rewloy\Http\Transport arayüzünü (send() ve
stream()) uygulayın. Kendi testlerinizde ağa çıkmadan yanıt vermenin yolu
da budur.
Geliştirme
src/Generated/elle düzenlenmez; üreteçscripts/Generator.php'dir.- Testler ağa çıkmaz. API sahte bir katmandır; curl katmanı 127.0.0.1'deki PHP sunucusuyla sınanır.
- CI her gün canlı belgeyi okur ve bir değişiklik varsa bir pull request açar.
- Kararlar: docs/DECISIONS.md.
Canlı testler
tests/Live, kütüphaneyi çalışan bir geliştirme (dev) Rewloy'una karşı uçtan uca sınar:
bir sürüm adayı canlıya çıkmadan önce her istemci kütüphanesi bu testten geçer.
Normal composer test bunları çalıştırmaz.
| Değişken | Anlamı |
|---|---|
REWLOY_BASE_URL |
Dev sunucusunun adresi. Biri eksikse testler atlanır (hata değildir). |
REWLOY_API_KEY |
Test ortamının anahtarı: rwk_test_…. Başka her anahtar reddedilir. |
REWLOY_STAFF_SESSION ya da REWLOY_STAFF_EMAIL + REWLOY_STAFF_PASSWORD |
İsteğe bağlı: test ortamında koltuğu olan birinin ekip oturumu (ikinci faktörsüz). resetTestEnvironment API anahtarıyla çalışmaz, ekip oturumu ister; yoksa sıfırlama atlanır ve özet bunu söyler. |
REWLOY_STAFF_PASSWORD |
İsteğe bağlı: aynı kişinin şifresi. Şube dondurma (freezeLocation) şifre ister; yoksa dondurma testleri atlanır ve özet bunu söyler. |
REWLOY_WEBHOOK_URL |
İsteğe bağlı: webhook testi için herkese açık bir https adresi (yalnız sunucu çözülemeyen adresi reddederse kullanılır; varsayılan https://example.com/rewloy-live-tests). |
Önce GET /v1/meta sorulur (anahtar gönderilmeden); environment "dev" değilse
ya da alan yoksa hiçbir şey çalışmaz (çıkış kodu 2). Canlıya karşı çalışmaz.
Kapsam: meta ve işletme; programlar (damga ve hediye kartı, güncelle, arşivle, sil);
kart verme, kasa görünümü, damga/ödül/harcama; satış (fiş numarasıyla ve numarasız),
reverseSale, reverseAction, işlem listesi; müşteri araması; kodlar
(listAllBatches, gönderme ve reddedilme durumları); webhook (oluştur, listele, sırrı
yenile, sil); Idempotency-Key; istek sınırı başlıkları; hata nesnesi (404 ve
doğrulama); sayfalama; 1.3.0'dan: ürün grupları ve kazanım kuralları (kaydetme,
sürüm çakışması, tek kural), previewEarn, previewSale, satırlı recordSale ve
earn açıklaması, tek satır iadesi, şube QR'ı (herkese açık sayfa, SVG, PNG, PDF
sayfaları, liste), şube dondurma (ekip oturumu ve şifreyle; test için ayrı bir şube
açılır, sonunda açılır), copyProgram ve NOT_AN_INSTRUMENT; en sonda test ortamının
sıfırlanması. Özet, alan başına
geçen/kalan sayısını yazar; herhangi bir hatada çıkış kodu sıfırdan farklıdır.
Test ortamı günde en fazla 5 kez sıfırlanır. Yapılmayanlar (BUSINESS_FROZEN, kod
kartlı şube QR'ı, Rewloy Cüzdan işlemleri…): tests/Live/TODO.md.
Belgeler
| Başlarken | https://rewloy.com/gelistiriciler |
| API referansı | https://rewloy.com/gelistiriciler/api |
| OpenAPI 3.1 | https://app.rewloy.com/v1/openapi.json |
| Hata kodları | https://rewloy.com/gelistiriciler/hatalar |
| API'nin değişiklik günlüğü | https://rewloy.com/gelistiriciler/degisiklikler |
| Bu kütüphanenin değişiklikleri | CHANGELOG.md |
Sürümler:
- Kütüphane anlamsal sürümleme (SemVer) kullanır. 1.0'a kadar arayüzü değişebilir.
- API'ye alan eklemek geriye uyumludur; kütüphanenin tipleri her gün güncellenir.
- Kalkacak bir uç nokta en az 180 gün önce duyurulur ve bu süre boyunca
DeprecationveSunsetbaşlıklarını taşır.
Güvenlik
Bir güvenlik açığı bulursanız SECURITY.md dosyasındaki yoldan özel olarak bildirin. Lütfen herkese açık issue açmayın.
Lisans
MIT
English
Developer docs (in Turkish): https://rewloy.com/gelistiriciler.
The official PHP library for the Rewloy API.
Status: preview (0.x), published on Packagist. The API is stable; the library's interface may change until 1.0.
The documentation of the API itself is in Turkish (links above). In short:
- Every operation of the API is a method named by its
operationId. Its arguments and answer are typed with PHPDoc array shapes generated from the OpenAPI document, which CI reads daily and regenerates from. - No dependencies: PHP 8.2 or later with the
curl,jsonandhashextensions. - Safe retries,
Idempotency-Keyhandling, pagination, server-sent events, webhook signature verification and deprecation notices.
Install
PHP 8.2 or later with curl:
Use
- Till.
recordSalewrites a completed sale to a card (the card type and the programme's own rule decide what is written);getPassreturns the card's structured fields (programName,currency,stamps,points,money,customer);reverseSaletakes a refunded sale back:$rewloy->reverseSale(['params' => ['serial' => $serial], 'body' => ['saleKey' => $key]]). A void isreverseAction: it takes back apassActionthat was a mistake (spend,spend-points,redeem-stamps,redeem-reward,use), found by theIdempotency-Keyyou sent with it (actionKey) or itsreference; it needs noIdempotency-Keyof its own, and a repeat answersduplicate: true:$rewloy->reverseAction(['params' => ['serial' => $serial], 'body' => ['actionKey' => $key]]). A till that queues sales while offline sendsoccurredAt(ISO 8601 with the UTC offset, not in the future) withrecordSale, so the card's history shows when the sale really happened; the queuedidempotencyKeymakes the resend safe.passActiontakes an optionalreferencetoo, and its answer is the union of two array shapes: the balance-card answer (balance) or the coupon / discount-card answer (status,uses,usesLeft;isset($answer['uses'])narrows it). cardon write answers.recordSale,passAction,reverseSaleandreverseActionanswer withcard: the card after the write, the fields ofgetPassexceptcustomer, read in the same transaction (on a replay,duplicate: true, it is the card's current state). A key withoutpasses.readin the card's programme getscard: null.recordSale'sreversed: true(replays only) says the sale written under that key was taken back since: send a new key to write the receipt again. For "can I act now" readcard['actions'][]['ready'];rewardReadymeans "reward ready" only for stamp and points cards (alwaystrueon VIP, any balance on cashback and gift cards).- Recent operations.
listPassOperationslists a card's ledger operations, newest first and paged, for a till's "last operations" screen:undoWith('sale/reverse'or'actions/reverse'),reversibleand, for this credential's own operations,saleKey/actionKeyto pass straight toreverseSale/reverseAction. - Rejected
occurredAtis a400 VALIDATIONwhose$e->details[0]['reason']isin_future,too_old,before_issueorinvalid(treat an unknown reason asinvalid). - Idempotency keys.
recordSale,passAction,sendCampaignandrefundShopRedemptionneed anIdempotency-Key: the API's OpenAPI document marks the header required for them, soidempotencyKeyis a required argument and the client throws anInvalidArgumentExceptionbefore sending if it is missing ornull. It never makes one up for you (a generated key would not survive a restart of your app). The key must be 8–64 printable ASCII characters (0x21–0x7E); a non-ASCII key such asfiş-0042is refused client-side, with anInvalidArgumentException, before anything is sent. Where the header is optional (for exampleissuePass) the client still generates a UUID and reuses it on every retry of the call. A key is unique for good per credential: do not use the receipt number alone (fiscal receipt numbers restart after the Z report) but register + Z number + receipt number, or a UUID stored with the sale. The receipt number goes inreference. - Base URL.
new Client(apiKey: …, baseUrl: 'https://staging.example.com')orbaseUrl: 'https://staging.example.com/v1': with or without a trailing/v1(and trailing slashes), the client appends/v1/...itself. Defaulthttps://app.rewloy.com. - Test mode. Open the test environment (panel → Developer, or
POST /v1/test/environment) and use itsrwk_test_key at the same address: a separate test business that sends nothing and never reaches real customers. Webhooks are delivered withRewloy-Test: 1. - Arguments. Each method takes one array:
params,queryandbodyas the operation needs, plusmerchant,idempotencyKey,timeout(seconds) andmaxRetries. A key the operation does not take throwsInvalidArgumentException. - Results. It returns the answer's
dataas an array:['data' => …, 'meta' => …]for paged lists, nothing for 204, a string of bytes for files. - The whole answer.
$rewloy->request($id, $args)returns aRewloy\Responsewithstatus,headers,requestId,mode(theRewloy-Modeheader:liveortest),replayed(Idempotent-Replayed) andrateLimit()(Rewloy\RateLimitwithlimit,remaining,resetfrom theRateLimit-*headers; null when absent). - Pagination.
$rewloy->paginate('listCustomers', $args)is a generator over the items of every page. - Streams.
$rewloy->liveFeed()(or$rewloy->stream('liveFeed', $args)) is a generator of server-sent events (event,data,id,json()). It reconnects withLast-Event-IDunless'reconnect' => false;breakends it and closes the connection.
Webhooks
Verify the raw body (file_get_contents('php://input'), or
$request->getContent() in Laravel and Symfony) with the secret shown when
the webhook was created:
- Check.
Rewloy-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>is compared in constant time, andtmust be within 300 seconds. - Refusal. On failure it throws
WebhookSignatureException: answer 400. - Headers.
Rewloy-Eventis the event type.Rewloy-Deliveryis the same on every retry of a delivery: deduplicate on it. Delivery is at least once. - Tests.
Webhook::sign($body, $secret)makes the header the platform would send.
rotateWebhookSecret gives a webhook a new secret (returned only in that
answer); the old one keeps signing for 24 hours, so Rewloy-Signature carries
two v1 values and the delivery has Rewloy-Signature-Rotating: 1.
Webhook::verify() tries every v1 and every secret you pass:
[$newSecret, $oldSecret]. deleteWebhook removes a webhook and its delivery
history for good.
A webhook object (listWebhooks, getWebhook, setWebhookStatus, and the
webhook of createWebhook and rotateWebhookSecret) always carries two
fields, each string|null (a date-time), null when it does not apply:
pausedUntil: your receiver failed twice in a row (5xx,429, a connection error or no answer), so the open webhook's deliveries wait until this moment and are then retried on their own (60 seconds). Null when it is not paused or the webhook is off.resumableUntil: the rules turned the webhook off and its pending deliveries are kept (until 24 hours after it closed). Turn it on before this moment (setWebhookStatus(['params' => ['id' => $id], 'body' => ['active' => true]])) and it carries on where it stopped: the kept deliveries go at once and the events that happened meanwhile arrive too. Null while it is on, when a person or a key turned it off, or once the time has passed.
Also in Rewloy 1.2.0 (library 0.2.4): createApiKey(['body' => ['kind' => 'pos', 'locationId' => …, 'register' => …, 'password' => …]])
(a till key bound to one branch); resetTestEnvironment(['body' => ['revokeKeys' => true]])
(keeps the test business, programmes and keys; revokes keys only when asked);
listAllBatches (every gift-card, coupon and discount code of the business,
with the archived state); 409 PROGRAM_ARCHIVED when creating a code for an
archived programme.
sendBatchLink e-mails a code's link only while the code issues a card:
410 BATCH_CLOSED (stopped), 410 BATCH_EXPIRED (past its date),
410 BATCH_FULL (every card given) and 409 PROGRAM_ARCHIVED (its programme is
archived) refuse it and no mail goes; before 1.2.0 the last three were sent
anyway. The codes are in the Rewloy\Generated\ErrorCode constants (ErrorCode::BATCH_FULL…).
Also in Rewloy 1.3.0 (library 0.3.0), all additive:
-
Receipt lines.
recordSaleand the newpreviewSale(noIdempotency-Key, nothing written) takelines(up to 500) andreceiptDiscountMinor; with lines the answer carriesearn, the line-by-line explanation (status, groups, rules, the total step by step).previewEarnasks the same of a programme with no card, optionally against a draftruleSet. A programme without earn rules earns as before.Refusals that come only with lines:
LINES_TOTAL_MISMATCH,LINE_AMOUNT_INVALID,TOO_MANY_LINES, and on a line refundLINE_NOT_FOUNDandLINE_ALREADY_REFUNDED. - Groups and rules.
createEarnGroup,listEarnGroups,updateEarnGroup… (a group is the business's name for what it sells), and a programme'sgetEarnRules,putEarnRules,createEarnRule,updateEarnRule,deleteEarnRule,listEarnRuleRevisions,listEarnTemplates. Every save is a revision written compare-and-set onrevision(REVISION_CONFLICT). - Branch QR.
qron every branch;publicBranch(no credential),locationQrSvg/locationQrPng/locationQrSheetPdf/locationQrSheetSvg(files as strings of bytes), the list (getLocationQrItems,putLocationQrItemswith itsversion,addQrItems,previewLocationQr);holderBranchandjoinHolderBranchneed a Rewloy Cüzdan session. - Branch freeze.
freezeLocationneeds a team session and the person's password (an API key getsCREDENTIAL_NOT_ALLOWED);updateLocationFreeze,cancelLocationFreezeandunfreezeLocationalso work with a key holdinglocations.freeze. A frozen branch's till answersLOCATION_FROZEN, a business with every branch frozenBUSINESS_FROZEN. New webhook eventspass.extended,location.frozen,location.unfrozen,business.paused,business.resumed. - Code cards.
copyProgramcopies only a gift card, coupon or discount card (NOT_AN_INSTRUMENTfor a loyalty card),extendProgramCards,updateBatch.
Errors, retries, deprecations
- Errors. Failures throw
RewloyExceptionwithstatus,errorCode(the API's stable code; constants inRewloy\Generated\ErrorCode),title,detail,details,requestId,rateLimit()andbody. Subclasses:RateLimitException(retryAfter),ConnectionExceptionandTimeoutException. - What is retried. Network errors, timeouts, 429, 502–504 and
Cloudflare's 520–524, up to
maxRetries(default 2), with exponential backoff and jitter, honouringRetry-Afterup to 60 seconds. - Only when safe. Only GET, PUT, DELETE, and POST with an
Idempotency-Key, are retried. - Deprecations. A deprecated operation's answers carry
Deprecation,SunsetandLink. The client raises oneE_USER_DEPRECATEDper operation per process, and the generated method is marked@deprecated.
Live tests
tests/Live tests the library end to end against a running dev Rewloy: a release
candidate passes every client library's live suite before it goes live. The normal
composer test does not run them.
REWLOY_BASE_URL,REWLOY_API_KEY: the dev server and the test business's key (rwk_test_…; any other key is refused). If either is missing the tests skip.- Optional:
REWLOY_STAFF_SESSION, orREWLOY_STAFF_EMAILandREWLOY_STAFF_PASSWORD(a team session with a seat in the test business, no second factor).resetTestEnvironmentrefuses an API key, so without a session the reset is skipped and the summary says so.REWLOY_STAFF_PASSWORD: that person's password; freezing a branch (freezeLocation) asks for it, so without it the freeze tests skip and the summary says so.REWLOY_WEBHOOK_URL: a public https address for the webhook tests, used only if the server refuses the unresolvable one (defaulthttps://example.com/rewloy-live-tests). - It first asks
GET /v1/meta(no key is sent) and stops with exit code 2 unlessenvironmentis"dev". It never runs against live. - Covers: meta and business; programs (stamp and gift card; update, archive, delete);
issuing, the till view, stamp, redeem and spend; sales with and without a receipt
reference,
reverseSale,reverseAction, the operations list; customer search; codes (listAllBatches, send-link refusals); webhooks (create, list, rotate the secret, delete, the 1.3.0 events);Idempotency-Key; rate-limit headers; the error object (404 and validation); pagination. From 1.3.0: product groups and earn rules (save, revision conflict, single rules),previewEarn,previewSale,recordSalewith receipt lines and theearnexplanation, a line refund, the branch QR (public page, SVG, PNG, PDF sheets, the list), branch freeze (needs the team session and password; each test freezes a branch of its own and opens it again),copyProgramandNOT_AN_INSTRUMENT. Last comes the test reset. It prints passed/failed per area and exits non-zero on any failure. A test business resets at most 5 times a day. What is not covered yet (BUSINESS_FROZEN, codes on a branch QR, the Rewloy Cüzdan operations…): tests/Live/TODO.md.
Security and licence
Report vulnerabilities privately, as SECURITY.md says. MIT licensed.
Yeni sürüm yayımlamak / Releasing
Client::VERSION'ı ve CHANGELOG'u güncelleyin, commit'leyin, v<sürüm> etiketini gönderin. Packagist etiketi kendiliğinden alır.
Bump Client::VERSION and the changelog, commit, and push a v<version> tag. Packagist picks the tag up by itself.
All versions of rewloy-php with dependencies
ext-curl Version *
ext-hash Version *
ext-json Version *