Faturalama Sisteminizi Bir Öğleden Sonrada Bağlayın
Bu sayfa, merchant-provider/v1 entegrasyonunun kısa yoludur: neyi, hangi sırayla geliştireceğinizi, her parçayı kendi makinenizde nasıl test edeceğinizi ve nasıl canlıya geçeceğinizi anlatır. Şirketinin müşterileri, ödemeleri ve abonelikleri kendi faturalama sisteminde (ya da bu sistemin bağlı olduğu birkaç ödeme sağlayıcısında) tutulan mühendisler için hazırlanmıştır. Kuralların tamamı Kendi faturalama sisteminizi bağlamak sayfasında, tüm istek ve yanıtlar da Örneklerle REST bağlantısı sayfasındadır.
Ne Geliştiriyorsunuz
Faturalama sisteminizin önünde duran küçük bir HTTPS API'si. Bu API'yi Chargeless çağırır; API'niz ise Chargeless'ı hiçbir zaman çağırmaz (sonuç bildirimleri, yani callback'ler hariç; onlar da isteğe bağlıdır).
customer ──► Chargeless ──(signed HTTPS)──► your API ──► your billing system
decides by reads facts,
your policy executes approved
refunds and cancellations- Kararı Chargeless verir. Her iade ve iptal kararını, Chargeless'ta tanımladığınız politika (süre sınırları, tutar üst sınırları, hız sınırları, kendi kurallarınız) belirler. API'niz hiçbir zaman karar vermez; bilgileri bildirir ve onaylanan işlemi uygular.
- Her çağrı imzalıdır; imza, yalnızca sizin ve Chargeless'ın bildiği bir gizli anahtarla atılır. Her iade ve iptal bir idempotency anahtarı taşır; böylece yeniden denenen bir çağrı hiçbir zaman iki kez ödeme yapmaz.
- API'nizi hiçbir dil modeli çağırmaz. Çağrılar, karar kaydedildikten sonra Chargeless'ın kendi kodundan gelir.
API on operasyondan oluşur; başlamak için yedisi yeterlidir:
| Sıra | Operasyon | REST | Ne yapar |
|---|---|---|---|
| 1 | describe |
GET /v1/describe |
Neleri ve hangi para birimlerinde desteklediğinizi bildirir |
| 2 | find_customers |
POST /v1/customers/search |
Müşterileri e-posta, telefon, sipariş, ödeme ya da kartın son dört hanesiyle bulur |
| 2 | get_customer |
GET /v1/customers/{customer_ref} |
Tek bir müşteriyi son iadeleri ve ters ibrazlarıyla döndürür |
| 2 | list_transactions |
GET /v1/customers/{customer_ref}/transactions |
Bir müşterinin son ödemelerini ve aboneliklerini döndürür |
| 2 | get_transaction |
GET /v1/transactions/{transaction_ref} |
Tek bir ödemeyi iadeleriyle döndürür |
| 3 | refund |
POST /v1/refunds |
Onaylanan tutarı orijinal ödeme yöntemine iade eder |
| 3 | get_operation |
GET /v1/operations/{idempotency_key} |
Chargeless'ın gönderdiği bir anahtarla ne yapıldığını bildirir |
| 4 | get_subscription |
GET /v1/subscriptions/{subscription_ref} |
Tek bir aboneliği döndürür (yalnızca iptal destekleniyorsa) |
| 4 | cancel_subscription |
POST /v1/subscriptions/{subscription_ref}/cancel |
Onaylanan bir aboneliği iptal eder (isteğe bağlı) |
| sonra | list_payment_attempts |
POST /v1/payment-attempts/list |
İçgörüler sayfası için kartla ödeme denemelerini listeler (isteğe bağlı) |
Sisteminiz zaten MCP kullanmıyorsa REST'i seçin: düz HTTP'dir ve curl ile test edebilirsiniz. MCP bağlantısı aynı operasyonları ve kuralları araç (tool) olarak sunar.
Başlamadan Önce
- Sözleşme dosyaları. merchant-provider-v1-contract.zip dosyasını indirin: OpenAPI tanımı, her nesne için bir JSON Schema, her nesnenin geçerli örnekleri ve MCP profili bu dosyadadır. Şemaları testlerinize yükleyin: örnekler, Chargeless'ın kabul ettiği yanıtlardır.
- Uyumluluk kiti. Bilgisayarınıza uygun
providercheckdosyasını providercheck sayfasından indirin. - Faturalama sisteminizin bir sandbox'ı (test ortamı); orada iade ve iptal hiçbir maliyet doğurmaz.
- Aşağıdaki örnek sunucuyu çalıştırmak istiyorsanız Node 18 veya üzeri; imzalı istekler için
curlveopenssl.
Beş Dakikada: Çalışan Bir Sunucunun Kontrollerden Geçişini İzleyin
Kontrollerden zaten geçen bir sunucuyla başlayın; böylece başarılı bir çalıştırmanın neye
benzediğini görürsünüz. Örneklerle REST bağlantısı
sayfasındaki eksiksiz sunucuyu server.mjs olarak kaydedin ve uydurma bir sandbox imzalama
anahtarıyla çalıştırın:
SIGNING_SECRET=srmps_local_0123456789abcdef PORT=8080 node server.mjsBaşka bir terminalde kiti bu sunucuya karşı çalıştırın (-allow-private, kitin localhost'ta düz
http kullanmasına izin verir):
export PROVIDERCHECK_SANDBOX_SIGNING_SECRET=srmps_local_0123456789abcdef
./providercheck -sandbox -allow-private -base-url http://localhost:8080 \
-tenant 0199a3c1-0a0b-7c0d-8e0f-101112131415 \
-customer cus_1001 -transaction ch_1001 -subscription sub_1001Kit her kontrol için bir satır yazar ve PASSED ile biter. Yeniden çalıştırmadan önce sunucuyu
yeniden başlatın: kit gerçekten iade ve iptal yapar. Bu sunucuyu geliştirerek kendi sunucunuza
dönüştürebilir (bellekteki depoyu faturalama sisteminize yapılan çağrılarla değiştirip kuralları
koruyarak) ya da istediğiniz bir dilde kendi sunucunuzu yazabilirsiniz.
İmzalı İstek Gönderen curl
Her istek imzalı olmalıdır; bu yüzden düz curl 401 alır. Aşağıdaki kabuk fonksiyonu bir isteği
Chargeless'ın imzaladığı şekilde imzalar; bash ve zsh'de çalışır:
# srcurl METHOD PATH [BODY] [IDEMPOTENCY_KEY]: one call to your endpoint, signed as Chargeless signs it.
# Set SR_BASE to your base URL (https://billing.example.com/supportroute, or http://localhost:8080)
# and SR_SECRET to the signing secret your endpoint verifies with.
srcurl() {
local method=$1 target=$2 body=${3-} key=${4-}
local rest=${SR_BASE#*://}
local host=${rest%%/*}
local prefix=${rest#"$host"}; prefix=${prefix%/}
local ts sig
local -a extra=()
[ -n "$key" ] && extra+=(-H "Idempotency-Key: $key")
[ -n "$body" ] && extra+=(-H 'Content-Type: application/json' --data-binary "$body")
ts=$(date +%s)
sig=$(printf '%s\n%s\n%s\n%s\n%s\n%s' "$ts" "$method" "$host" "$prefix$target" "$key" "$body" \
| openssl dgst -sha256 -hmac "$SR_SECRET" -hex | sed 's/^.*= *//')
curl -sS -X "$method" "${SR_BASE%%://*}://$host$prefix$target" \
-H "X-SupportRoute-Timestamp: $ts" -H "X-SupportRoute-Signature: v1=$sig" "${extra[@]}" \
-w '\nHTTP %{http_code}\n'
}
export SR_BASE=http://localhost:8080 SR_SECRET=srmps_local_0123456789abcdefHer yanıtı görmek için bu fonksiyonu önce örnek sunucuya, sonra kendi sunucunuza karşı kullanın.
Adım 1: İmzaları Doğrulayın, describe Çağrısını Yanıtlayın
İşe bununla başlayın: imzalı bir describe çağrısı yanıtlanana kadar başka hiçbir çağrı
yapılmaz.
- Önce ham istek baytlarını okuyup imzayı doğrulayın: herhangi bir şeyi ayrıştırmadan (parse)
önce
X-SupportRoute-Signaturebaşlığını doğrulayın. İmza, altı satırın (zaman damgası, yöntem, host, yol, idempotency anahtarı, gövde) HMAC-SHA256 değeridir; sabit zamanlı (constant time) olarak karşılaştırılır ve zaman damgası saatinizden en fazla beş dakika sapabilir. Adım adım imzalama bölümünde imzalanan dizenin tam hali, iki test vektörü ve bir Node doğrulayıcısı bulunur. Yanlış imzaya401dönün. describeçağrısını desteklediklerinizle yanıtlayın. Az ve gerçeğe uygun bildirerek başlayın:partial_refundsdeğerini yalnızca bir ödemenin bir kısmını iade edebiliyorsanız bildirin; 4. adıma kadarcancel_subscription: falseolarak bırakın.
Test edin:
srcurl GET /v1/describe # 200 and your describe
SR_SECRET=wrong srcurl GET /v1/describe # 401 credentials_rejectedBir proxy ya da yük dengeleyicinin (load balancer) arkasındaysanız imzayı, sunucunuzun gördüğü iç host adıyla değil, Chargeless'ın çağırdığı herkese açık host adıyla doğrulayın; yolu da gönderildiği haliyle, taban yol (base path) dahil kullanın.
Adım 2: Okuma Operasyonları
find_customers, get_customer, list_transactions ve get_transaction operasyonlarını
uygulayın. Müşteri sohbette, bir talepte ya da portalda size ulaştığında okunan veriler bunlardır;
bu yüzden her birinin yanıt süresini bir saniyenin altında tutun (sözleşme kontrolü 2,5 sn'den uzun
süren bir okumayı başarısız sayar).
Sözleşme kontrolünün en sık yakaladığı hatalar:
- Tutar, para birimiyle birlikte en küçük birim (minor unit) cinsinden bir tamsayıdır:
{"amount_minor": 4999, "currency": "USD"}. Asla49.99,4999.0ya da"4999"değil. JPY'nin alt birimi yoktur, KWD'nin ise üç basamaklı alt birimi vardır. - Her anahtar (key) yanıtta yer alır; değeri bilmiyorsanız
nullgönderin. Eksik bir anahtar yanıtın tamamını geçersiz kılar ve kontrol eksik anahtarın adını verir:`amount.amount_minor` is missing. - Referanslar harf, rakam,
.,_,:ve-karakterlerinden oluşur, 1 ile 128 karakter uzunluğundadır ve hiçbir zaman ardışık 13 veya daha fazla rakam içermez; böyle bir dizi kart numarasına benzer. Sayısal kimlikleri kodlayın (ord_2026101500012reddedilir;ord-2026-10-15-0001uygundur). Bkz. Referanslar. - Eşleşme bulunmaması hata değildir:
find_customers,{"candidates": []}gövdesiyle200döner. Diğer okuma operasyonlarında bilinmeyen bir müşteri ya da ödeme için404 not_founddönülür. - Bir ödeme, gerçekleşen tüm iadelerini listeler; her iadeyi Chargeless yaptıysa Chargeless'ın
idempotency anahtarıyla, yapmadıysa
nullile.
Test edin:
srcurl POST /v1/customers/search '{"email":"[email protected]"}'
srcurl GET /v1/customers/cus_1001
srcurl GET /v1/customers/cus_1001/transactions
srcurl GET /v1/transactions/ch_1001
srcurl GET /v1/transactions/does_not_exist # 404 not_foundHer yanıtı sözleşme zip'indeki ilgili örnekle (schemas/merchant-provider/examples/v1/)
karşılaştırın ya da kullandığınız teknolojinin JSON Schema kütüphanesiyle (draft 2020-12, biçim
(format) denetimi açık) doğrulayın; bunun için schemas/merchant-provider/v1/ altındaki her
dosyayı kendi $id değeriyle yükleyin.
Adım 3: İadeler ve get_operation
Para hareketi bu adımda gerçekleşir; bu yüzden kuralların çoğu buradadır.
- Deneme çalıştırmaları (dry run).
"dry_run": trueiçeren bir gövde idempotency anahtarı taşımaz. Gerçek bir iadede yapacağınız tüm kontrolleri yapın vewould_succeedya da vereceğiniz reddi döndürün. Hiçbir şeyi değiştirmeyin, hiçbir şey saklamayın. - Anahtarlar. Gerçek bir iade isteği
Idempotency-Keybaşlığıyla gelir. Anahtarı, isteği ve sonucunu ödeme işlemcinizi (processor) çağırmadan önce, tek bir veritabanı işleminde (transaction) saklayın ve en az 30 gün tutun.- Aynı anahtar aynı gövdeyle yeniden gelirse saklanan sonucu döndürün; hiçbir zaman iki kez iade yapmayın.
- Aynı anahtar farklı bir tutar ya da ödemeyle gelirse
409 idempotency_conflictdönün ve hiçbir işlem yapmayın. - İlk çağrı hâlâ sürerken aynı anahtar gelirse
409 in_progressdönün.
- Fazla iadeyi siz de kontrol edin. Ödemede kalan tutardan fazlasını, Chargeless bunu
kontrol etmiş olsa bile
422 amount_exceeds_refundableile reddedin: bu arada ödeme başka bir kanaldan iade edilmiş olabilir. - Retler.
422, bu anahtarla işlemi hiçbir zaman yürütmeyeceğiniz anlamına gelir. Kayıtlarınız istekle çeliştiğinde durum kodlarını (already_refunded,not_refundable, …), işlemi kendi kuralınız durdurduğunda ise bir koruma (guard) kodunu ya da kendix_…kodunuzu kullanın. Bkz. Retler. get_operation, aldığınız her anahtar için yanıt verir:succeeded,pending,failed(ret bilgisiyle) ve yalnızca hiç almadığınız bir anahtar içinunknown. Hiçbir zaman404dönmez.- Anahtarı ödemede gösterin. İadeden sonra
get_transaction, iadeyirefunds[]içinde anahtarıyla, bayt bayt aynı olarak listeler.
Test edin:
REFUND='{"transaction_ref":"ch_1001","amount":{"amount_minor":150,"currency":"USD"},"reason":"duplicate","dry_run":false}'
KEY=0199a3c1-0a0b-7c0d-8e0f-101112131415:walkthrough:refund:1
srcurl POST /v1/refunds "${REFUND/false/true}" # a dry run: 200 would_succeed, nothing changes
srcurl POST /v1/refunds "$REFUND" "$KEY" # 200 succeeded (or pending)
srcurl POST /v1/refunds "$REFUND" "$KEY" # the same result again, no second refund
srcurl POST /v1/refunds "${REFUND/150/250}" "$KEY" # 409 idempotency_conflict
srcurl GET "/v1/operations/$KEY" # 200 succeeded, with the result
srcurl GET /v1/transactions/ch_1001 # refunds[] lists it under $KEYAdım 4: İptaller (İsteğe Bağlı)
Müşterileriniz aboneliklerini iptal edebiliyorsa get_subscription ve cancel_subscription
operasyonlarını uygulayın, ardından describe yanıtında cancel_subscription: true bildirin
(dönem sonunda iptal edebiliyorsanız cancel_at_period_end: true de). Anahtarlar, deneme
çalıştırmaları, tekrar gönderimler (replay) ve çakışmalar iadelerdekiyle tamamen aynı şekilde
işler; zaten iptal edilmiş bir abonelik için 422 already_canceled dönülür.
srcurl GET /v1/subscriptions/sub_1001
srcurl POST /v1/subscriptions/sub_1001/cancel '{"at_period_end":true,"reason":"forgot_to_cancel","dry_run":true}'Adım 5: Kiti Sandbox'ınıza Karşı Çalıştırın
API'nizi faturalama sisteminizin sandbox'ının önüne kurun, iade edilebilir bir ödemesi (iptal
destekliyorsanız etkin bir aboneliği de) olan yeni bir sandbox müşterisi seçin ve kiti
providercheck sayfasında anlatıldığı gibi çalıştırın. Kit gerçekten en küçük
birimden 1 birim iade eder ve aboneliği iptal eder; canlı bir sistemde bunlar para hareketi
olmadan gösterilemez. Kit, bağlantınızı ilk kez kaydettiğinizde Chargeless'ın gösterdiği sandbox
imzalama anahtarını (srmps_…) kullanır (6. adım); bu yüzden önce 6. adımı tamamlayıp buraya geri
dönebilirsiniz.
Başarısız her satırda kontrolün adı, bir hata kodu ve istek kimliği (request id) yer alır; böylece
çağrıyı kendi günlüklerinizde bulabilirsiniz. Hatayı düzeltin, yeni test verileri (fixture) seçin,
çalıştırma PASSED ile bitene kadar tekrarlayın ve rapor dosyasını saklayın.
Adım 6: Bağlantıyı Panelde Kurun
- Bağlantıyı ekleyin. Chargeless panelinde Ayarlar → Entegrasyonlar'ı açın ve Ödemeler altındaki Kendi ödeme sisteminiz kartında Bağlan'ı seçin. Bağlantıya bir ad verin ve sisteminizin mutabakat para birimini seçin.
- Canlı uç noktanızı girin. Taban URL'yi (443 portunda
https://…, herkese açık bir sertifikayla, yönlendirme (redirect) olmadan), REST ya da MCP seçimini ve gerekiyorsa ağ geçidinizin (gateway) istediği bearer token'ı ya da edge başlıklarını girin. Siz yazarken panel, Chargeless'ın çağıracağı tüm URL'leri listeler. - İmzalama anahtarlarını kaydedin. İlk kayıtta iki anahtar yalnızca bir kez gösterilir:
srmp_…, imzalama anahtarı: canlı API'niz imzaları bununla doğrular;srmps_…, sandbox imzalama anahtarı: bununla yalnızca sandbox'ınız doğrulama yapar; canlı API'niz bu anahtarı reddetmelidir. Kit istekleri bu anahtarla imzalar.
- Chargeless'ın adreslerine izin verin. Güvenlik duvarınız yalnızca izin listesindeki (allowlist) adreslerden gelen çağrıları kabul ediyorsa, aynı sayfadaki Çıkış (Egress) bölümünde listelenen tüm adresleri ekleyin.
- Test nesnelerini seçin. Canlı sisteminizden az işlem gören bir müşteri, iade edilebilir bir ödeme ve iptal destekliyorsanız etkin bir abonelik seçin. Sözleşme kontrolü bunları okur ve yalnızca deneme çalıştırmaları gönderir: hiçbir şey iade ya da iptal edilmez.
- Bağlantıyı test edin. "Bağlantıyı Test Et", sözleşme kontrolünü Chargeless'ın kendi ağından canlı uç noktanıza karşı çalıştırır. Başarısız her satırda uç nokta, hatalı bir yanıtta da ilgili alan belirtilir: düzeltin ve yeniden test edin.
- Kitin raporunu Uyumluluk kiti bölümüne yükleyin: 5. adımdaki dosyayı değiştirmeden.
- Canlıya geçin. Bir politika yayımlayın, devredilen vakaların nereye gideceğini seçin ve kurulum kontrol listesinden canlıya geçin. Canlıya geçiş sırasında sözleşme kontrolü bir kez daha çalışır.
Sık Karşılaşılan Hatalar
| Gördüğünüz | Nedeni | Çözüm |
|---|---|---|
describe, signature_not_verified ile başarısız oluyor |
Yanlış imzalı isteği kabul ediyorsunuz | Her isteğin imzasını, başka her şeyden önce doğrulayın |
Proxy arkasında her çağrı 401 alıyor |
Proxy Host başlığını ya da yolu değiştiriyor |
Herkese açık host adıyla ve yolu gönderildiği haliyle doğrulayın |
`amount.amount_minor` must be an integer, not a string ile schema_invalid |
Ondalıklı ya da tırnak içinde yazılmış bir tutar | En küçük birim cinsinden bir tamsayı gönderin |
`…` is missing ile schema_invalid |
Yanıtta eksik bir anahtar var | Her anahtarı gönderin; değer bilinmiyorsa null |
card_number_in_field |
Ardışık 13 veya daha fazla rakam içeren bir referans | Sayısal kimlikleri kodlayın (base32, base62) |
fixture_not_found |
Test nesnesi, Chargeless'ın çağırdığı sistemde yok | Sözleşme kontrolü için canlı sistemdeki, kit için sandbox'taki nesneleri kullanın |
refunds_exceed_amount, fixture_not_refundable |
Test ödemesi iade edilmiş, itiraz edilmiş ya da başarısız olmuş | İade edilebilir tutarı kalan, başarılı bir ödeme seçin |
over_refund_not_refused |
API'niz kalan tutardan fazlasını iade edecekti | 422 amount_exceeds_refundable ile reddedin |
dry_run_changed_state |
Bir deneme çalıştırması gerçekten yürütüldü | Deneme çalıştırmasını hiçbir zaman yürütmeyin ve saklamayın |
retryable_mismatch |
Bir hatanın retryable değeri durum koduyla çelişiyor |
400, 401, 403, 404, çakışma için 409 ve 422'de false; işlem sürerken dönen 409, 429 ve 5xx'te true |
not_unknown |
get_operation, hiç gönderilmemiş bir anahtar için 404 döndü |
"status": "unknown" ile 200 dönün |
latency_budget_exceeded |
Bir okuma 2,5 sn'den, bir deneme çalıştırması 10 sn'den uzun sürdü | Yanıtı hızlandırın; soğuk başlangıç (cold start) bir kez başarısız olabilir, yeniden test edin |
Canlıya Geçtikten Sonra
- Müşteriler sohbetten, e-postayla, yardım sitenizden ya da yardım masanız üzerinden başvurur;
Chargeless API'nizden bilgileri okur, politikanıza göre karar verir ve
refundya dacancel_subscriptionçağrısını yalnızca onayladığı işlemler için yapar. - Politikanızın izin vermediği ve API'nizin bir koruma koduyla reddettiği her işlem, ilgili bilgilerle birlikte ekibinize devredilir.
- Ayarlar → bağlantınız → Sağlayıcı Durumu ve çağrı kaydı, her çağrıyı istek kimliğiyle gösterir. Çağrılar reddedildiğinde ya da başarısız olduğunda Chargeless çalışma alanınızın sahiplerine, yöneticilerine ve geliştiricilerine e-posta gönderir.