PayPal

PayPal hesabı ve kartla ödeme. Orders API; müşteri PayPal'ın sayfasında onaylar, tahsilat webhook ile sunucudan yapılır.

Gereken bilgiler

developer.paypal.comApps & Credentials → uygulamanız (yoksa Create App):

  • client_id: uygulamanın Client ID'si
  • client_secret: uygulamanın Secret'ı (Show ile görünür)
  • webhook_secret: aynı uygulamanın Webhooks bölümünde oluşturduğunuz webhook'un Webhook ID'si (PayPal'da gizli bir imza anahtarı yoktur; doğrulama bu kimlikle PayPal'a sorularak yapılır, ayrıntı aşağıda)

Panelinizde Ayarlar → Ödemeler → Yöntem ekle → PayPal seçin, üç değeri girin.

Sandbox: PayPal'ın Sandbox sekmesindeki uygulama anahtarlarını girip sandbox (test) modu kutusunu işaretleyin; panel api-m.sandbox.paypal.com'a bağlanır ve test alıcı hesabıyla ödeme yapılır. Canlıya geçerken Live sekmesindeki anahtarları ve o uygulamanın webhook ID'sini girip kutuyu kaldırın. Sandbox ve Live uygulamalarının webhook'ları ayrıdır; ikisini de kendi anahtar takımıyla girin.

Webhook. PayPal tarafında ayarlanması zorunludur

Uygulamanızın sayfasında Webhooks → Add Webhook:

https://<panel-alan-adınız>/payments/paypal/callback

Event olarak en az şunları seçin:

  • CHECKOUT.ORDER.APPROVED: müşteri onayladı; tahsilatı bu olayda biz yaparız
  • PAYMENT.CAPTURE.COMPLETED: para hesabınıza geçti
  • PAYMENT.CAPTURE.PENDING: tahsilat beklemede (eCheck, inceleme, hesabınızda tutulmayan para birimi)
  • PAYMENT.CAPTURE.DENIED (listede PAYMENT.CAPTURE.DECLINED olarak da geçer), tahsilat reddedildi

"All events" seçmek de çalışır; ilgisiz olaylar doğrulanır, kaydedilir ve bakiyeye dokunmadan onaylanır. Kaydettikten sonra listedeki Webhook ID'yi kopyalayıp panelde webhook_secret alanına yapıştırın.

Webhook olmadan ödeme hiç tamamlanmaz: müşteri PayPal'da onaylasa bile para, biz sunucudan "capture" çağrısı yapana kadar çekilmez; bu çağrı CHECKOUT.ORDER.APPROVED webhook'unda yapılır. PayPal, 3 saat içinde tahsil edilmeyen onayı iptal eder (CHECKOUT.PAYMENT-APPROVAL.REVERSED).

Akış

  1. Müşteri tutarı girer, PayPal'ı seçer. Panel POST /v2/checkout/orders ile intent: CAPTURE bir sipariş açar; sipariş numaramız (publicRef) custom_id ve invoice_id alanlarına yazılır. Kargo yok, düğme "Pay Now", yalnız anında ödeme (IMMEDIATE_PAYMENT_REQUIRED).
  2. Müşteri PayPal'ın onay sayfasına (payer-action bağlantısı) yönlendirilir; PayPal hesabı ya da kartla öder.
  3. Onaydan sonra PayPal müşterinin tarayıcısını panelin dönüş adresine getirir (/payments/paypal/return?ref=…). Bu dönüş yalnız yönlendirir, bakiye yüklemez; müşteri "Bakiye yükle" sayfasına döner.
  4. PayPal aynı anda CHECKOUT.ORDER.APPROVED webhook'unu gönderir. Panel imzayı PayPal'a doğrulatır, ardından kendi anahtarıyla POST /v2/checkout/orders/{id}/capture çağırır. Dönen capture'ın durumu COMPLETED ise bakiye yüklenir.
  5. PAYMENT.CAPTURE.COMPLETED webhook'u da gelir; aynı capture numarasını taşıdığı için ikinci kez yükleme yapılmaz. CHECKOUT.ORDER.APPROVED'dan önce gelirse bakiyeyi o yükler, sonraki capture çağrısı "zaten tahsil edildi" cevabını alır ve sipariş yeniden okunur.

Webhook genellikle saniyeler içinde gelir; müşteri sayfaya döndüğünde bakiye kısa süre içinde görünür.

Doğrulama

Panel hiçbir webhook'a kendi başına güvenmez: PayPal'ın PAYPAL-TRANSMISSION-ID, PAYPAL-TRANSMISSION-TIME, PAYPAL-TRANSMISSION-SIG, PAYPAL-CERT-URL, PAYPAL-AUTH-ALGO başlıklarını, gövdeyi ve sizin Webhook ID'nizi POST /v1/notifications/verify-webhook-signature ile PayPal'a gönderir; PayPal SUCCESS demezse istek reddedilir (HTTP 400, PayPal yeniden dener). Her API çağrısı POST /v1/oauth2/token ile alınan Bearer token'la yapılır.

Durumlar

PayPal capture durumu Panelde
COMPLETED tamamlandı, bakiye yüklendi
PENDING (ECHECK, PENDING_REVIEW, RECEIVING_PREFERENCE_MANDATES_MANUAL_ACTION …) beklemede; neden ödeme notunda. Temizlenince gelen PAYMENT.CAPTURE.COMPLETED yükler
DECLINED, FAILED başarısız
REFUNDED, PARTIALLY_REFUNDED tamamlanmış ödemeye dokunulmaz; iadeyi Admin → Ödemeler'den elle işleyin

Capture çağrısı ağ hatasıyla başarısız olursa webhook 400 ile reddedilir ve PayPal olayı yeniden gönderir; ödeme o zamana kadar "bekliyor" kalır.

Para birimleri

PayPal REST API'si şu birimleri kabul eder: AUD, BRL, CAD, CNY, CZK, DKK, EUR, HKD, HUF, ILS, JPY, MYR, MXN, TWD, NZD, NOK, PHP, PLN, GBP, RUB, SGD, SEK, CHF, THB, USD. TRY listede yoktur; Türk lirası panelde PayPal yöntemini USD ya da EUR para birimiyle tanımlayın. HUF, JPY ve TWD ondalık kabul etmez; tutar tam sayıya yuvarlanır.

Hesabınızda tutmadığınız bir birimde ödeme alırsanız PayPal, Payment Receiving Preferences ayarınıza göre tahsilatı beklemeye alabilir; böyle bir ödeme panelde beklemede görünür ve PayPal hesabınızda kabul edince yüklenir.

Sık sorunlar

  • Müşteri ödedi, bakiye yok, ödeme "bekliyor": webhook ID'si girilmemiş ya da webhook PayPal'da tanımlı değil / yanlış adrese bakıyor. Developer Dashboard → Webhooks → Events'te teslimat durumuna bakın; panel 400 döndürüyorsa ID uyuşmuyordur.
  • Sandbox'ta "AUTHENTICATION_FAILURE" / "invalid_client": Live anahtarlarla sandbox modu (ya da tersi) karışmış. Anahtarlar hangi sekmedense mod da o olmalı.
  • "CURRENCY_NOT_SUPPORTED": yöntemin para birimi PayPal listesinde değil (çoğunlukla TRY). Yöntemi USD/EUR ile yeniden tanımlayın.
  • "DUPLICATE_INVOICE_ID": PayPal hesabınızda "Block duplicate invoice IDs" açık ve aynı sipariş numarası daha önce tahsil edilmiş. Panel her ödeme için yeni bir numara üretir; bu hata yalnızca aynı ödeme için iki sipariş açıldığında görülür, müşteri yeni bir ödeme başlatsın.
  • Onaydan 3 saat sonra "CHECKOUT.PAYMENT-APPROVAL.REVERSED": capture çağrısı hiç yapılamamış (webhook yoktu ya da sürekli hata aldı). Para müşteriye iade edilmiştir; webhook ayarını düzeltip müşteriden yeniden ödeme isteyin.