<p>Öncelikle imzayı doğrulayın — BayarCash, her biri kendi doğrulayıcısına sahip <strong>üç yük biçimi</strong> gönderir. Bir işaret alanına göre yönlendirin:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="nv">$verified</span> <span class="o">=</span> <span class="k">match</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
<span class="k">isset</span><span class="p">(</span><span class="nv">$payload</span><span class="p">[</span><span class="s1>'record_status'</span><span class="p">])</span> <span class="o">=&gt;</span> <span class="nv">$sdk</span><span class="o">-&gt;</span><span class="nf">verifyPreTransactionCallbackData</span><span class="p">(</span><span class="nv">$payload</span><span class="p">,</span> <span class="nv">$secret</span><span class="p">),</span> <span class="c1">// DD kaydı</span>
<span class="k">isset</span><span class="p">(</span><span class="nv">$payload</span><span class="p">[</span><span class="s1>'status'</span><span class="p">])</span>        <span class="o">=&gt;</span> <span class="nv">$sdk</span><span class="o">-&gt;</span><span class="nf">verifyTransactionCallbackData</span><span class="p">(</span><span class="nv">$payload</span><span class="p">,</span> <span class="nv">$secret</span><span class="p">),</span>    <span class="c1">// ödeme</span>
<span class="k">default</span>                          <span class="o">=&gt;</span> <span class="nv">$sdk</span><span class="o">-&gt;</span><span class="nf">verifyReturnUrlCallbackData</span><span class="p">(</span><span class="nv">$payload</span><span class="p">,</span> <span class="nv">$secret</span><span class="p">),</span>      <span class="c1">// geri URL</span>

};
if ($verified !== true) { return null; } // arayıcı 401 döner

<p>Sonra, tamsayı durumunu kendi kelime dağarcığınıza bir kez dönüştürün — bu sayede tamsayılar asla dışarı çıkmaz:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="nv">$status</span> <span class="o">=</span> <span class="k">match</span> <span class="p">(</span><span class="n">int</span><span class="p">(</span><span class="nv">$payload</span><span class="p">[</span><span class="s1>'status'</span><span class="p">])</span> <span class="p">){</span>
<span class="mi">3</span> <span class="o">=&gt;</span> <span class="nc">PaymentStatus</span><span class="o">::</span><span class="nc">Completed</span><span class="p">,</span> <span class="c1">// umursadığınız</span>
<span class="k">default</span> <span class="o">=&gt;</span> <span class="nc">PaymentStatus</span><span class="o">::</span><span class="nc">Failed</span><span class="p">,</span>

};

 <blockquote>
    <p><strong>Unutmayın — durum haritanızı mevcut belgelere karşı doğrulayın.</strong> <code>3 = başarılı</code> sabittir; başarısız/pending/iptal sayıları SDK sürümleri arasında değişebilir. Haritanızı API sürümünüz için sabitleyin ve bir test ile kaplayın.</p>
</blockquote>

<h3>
    <a name="the-golden-webhook-rule" href="#the-golden-webhook-rule">
    </a>
    Altın webhook kuralı
</h3>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="k">public</span> <span class="k">function</span> <span class="n">webhook</span><span class="p">(</span><span class="kt">Request</span> <span class="nv">$request</span><span class="p">):</span> <span class="kt">JsonResponse</span>

{
$result = $this->gateway->handleWebhook($request);

<span class="k">if</span> <span class="p">(</span><span class="o">!</span> <span class="nv">$result</span><span class="o">-&gt;</span><span class="n">processed</span><span class="p">)</span> <span class="p">{</span>
    <span class="nc">Log</span><span class="o">::</span><span class="nf">channel</span><span class="p">(</span><span class="s1>'daily'</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">warning</span><span class="p">(</span><span class="s1>'BayarCash webhook ignored'</span><span class="p">,</span> <span class="p">[</span><span class="s1>'message'</span> <span class="o">=&gt;</span> <span class="nv">$result</span><span class="o">-&gt;</span><span class="n">message</span><span class="p">]);</span>
<span class="p">}</span>

<span class="c1">// Zayıf bir başarısızlık durumunda bile 200 döndürün. BayarCash, non-2xx üzerinde yeniden dener,</span>
<span class="c1">// bu yüzden 500 olursa 40 kez arttırır. Loglayın, OK döndürün, uzlaştırın.</span>
<span class="k">return</span> <span class="nf">response</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">json</span><span class="p">([</span><span class="s1>'processed'</span> <span class="o">=&gt;</span> <span class="nv">$result</span><span class="o">-&gt;</span><span class="n">processed</span><span class="p">]);</span>

}

<p>Bu alanın en önemli üretim dersi. <strong>Bir kez imzayı doğruladıktan sonra, 2xx ile yanıt verin.</strong> Kötü bir imza, 401'dir. Her şey — sipariş bulunamadı, beklenmedik durum, işleyicinizde hata — gürültülü bir biçimde loglanmalı ve tekrar 200 döndürmelidir, çünkü non-2xx olmak, BayarCash’in yeniden deneme döngüsüne girer ve bir problemi kargaşaya dönüştürür. Yan etkileri idempotent hale getirin (<code>updateOrCreate</code>, durum koruma) böylece bir yeniden deneme zararsız olur.</p>

<h2>
    <a name="the-recurringbilling-reality" href="#the-recurringbilling-reality">
    </a>
    Tekrar faturalandırma gerçeği
</h2>

<p>Plain <strong>FPX tek seferliktir</strong> — saklı kart yok, otomatik aylık ücret yok. Gerçek bir otomatik yenileme, <strong>FPX Doğrudan Borç yetkisi</strong> gerektirir, bu da ödiyenin NRIC ve telefonunu gerektirir — basit bir ödeme sayfasının genellikle topladığı veriler. İki dürüst seçenek var: doğrudan borç işlemi yapın (<code>createFpxDirectDebitEnrollment</code>) ve bu alanları toplayın ya da tek seferlik olarak ücretlendirin ve <strong>zamanlı yenileme işi</strong> ile birlikte döngü + hoşgörü süreleri yönetin. Her iki durumda da <code>supportsRecurring()</code> işlevinin <code>false</code> döndürdüğünden emin olun, ta ki DD gerçekten kaydedilene kadar. Ve<strong>iade</strong>: FPX'de otomatik yok — yüzeyde "manuel işleyin" yolu oluşturun, sessizce başarısız olan buton değil.</p>

<h2>
    <a name="testing-without-the-network" href="#testing-without-the-network">
    </a>
    Ağ olmadan test etme
</h2>

<p>Bir token ayarlanmadığında sözleşme bir sahte ile bağlandığından, tüm akış çevrimdışı test edilebilir:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="nf">it</span><span class="p">(</span><span class="s1>'aktif bir aboneliği başarılı bir webhook'ta etkinleştirir'</span><span class="p">,</span> <span class="k">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nv">$sub</span> <span class="o">=</span> <span class="nc">Subscription</span><span class="o">::</span><span class="nf">factory</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">pending</span><span class="p">()</span><span class="o">-&gt;</span><span class="nf">create</span><span class="p">([</span><span class="s1>'external_id'</span> <span class="o">=&gt;</span> <span class="s1>'wau-abc12345-business-m-a1b2c3'</span><span class="p">]);</span>

<span class="nf">post</span><span class="p">(</span><span class="nf">route</span><span class="p">(</span><span class="s1>'billing.bayarcash.webhook'</span><span class="p">),</span> <span class="p">[</span><span class="s1>'order_number'</span> <span class="o">=&gt;</span> <span class="nv">$sub</span><span class="o">-&gt;</span><span class="n">external_id</span><span class="p">,</span> <span class="s1>'status'</span> <span class="o">=&gt;</span> <span class="mi">3</span><span class="p">])</span>
    <span class="o">-&gt;</span><span class="nf">assertOk</span><span class="p">();</span>

<span class="nf">expect</span><span class="p">(</span><span class="nv">$sub</span><span class="o">-&gt;</span><span class="nf">fresh</span><span class="p">()</span><span class="o">-&gt;</span><span class="n">status</span><span class="p">)</span><span class="o">-&gt;</span><span class="nf">toBe</span><span class="p">(</span><span class="nc">SubscriptionStatus</span><span class="o">::</span><span class="nc">Active</span><span class="p">);</span>

});

it(<span class=”s1>’bir şekilde değiştirilmiş webhook’u 401 ile reddeder’, fn () =>
post(route(<span class=”s1>’billing.bayarcash.webhook’), [<span class=”s1>’status’ => 3, <span class=”s1>’checksum’ => <span class=”s1>’wrong’])->assertUnauthorized());

<p>Gerçek bir checkout rotası ekleyin ki, barındırılan sayfayı taklit etsin (üretimde 404) böylece <code>/billing → checkout → return</code> ile dolaşabileceksiniz ve sıfır kimlik bilgisi ile yerel olarak çalışabilirsiniz.</p>

<h2>
    <a name="production-checklist" href="#production-checklist">
    </a>
    Üretim kontrol listesi
</h2>

<ul>
    <li>
        <strong>Doğruladıktan sonra 2xx döndürün</strong> — başka bir şey yeniden deneme döngüsüne girer. 401 yalnızca kötü imzalar içindir.
    </li>
    <li>
        <strong>İdempotent yan etkiler</strong> — tekrar ve geri URL tekrarları iki kez işleyiciye geri dönebilir.
    </li>
    <li>
        <strong>CSRF'den muaf tutun</strong> geri çağrılan rotayı.
    </li>
    <li>
        <strong>Açık ulaşılabilir geri çağırma URL'si</strong> — localhost yok, temel kimlik doğrulama duvarı yok, "botları engelle" kenar kuralı yok.
    </li>
    <li>
        <strong>Her yükü kaydedin</strong> (bir bayrak arkasında) günlük kanala — uzlaştırma bunun olmadan imkansızdır.
    </li>
    <li>
        <strong>Ödeme sonrası yan etkileri kuyruklayın</strong> böylece webhook hızlı yanıt versin.
    </li>
    <li>
        <strong>SDK metod adı yakalaması:</strong> her iki <code>createPaymentIntentChecksumValue</code> (doğru) ve eski yazım hatası <code>createPaymentIntenChecksumValue</code> mevcuttur. İlkini kullanın.
    </li>
    <li>
        <strong>Kanal-sabit yakalaması:</strong> <code>DUITNOW_QR = 6</code>; <code>3 = FPX_DIRECT_DEBIT</code>. Tamsayıları manuel olarak haritalarsanız, birine yanlış yolla para alırsınız — <code>Bayarcash::*</code> sabitlerini kullanın.
    </li>
</ul>

<h2>
    <a name="wrapup" href="#wrapup">
    </a>
    Sonuç
</h2>

<p>SDK, BayarCash entegrasyonunun belki de %20'sini oluşturur. Geri kalan %80, mimaridir: bir kez çözüm sağlayan ince bir sargı, uygulamanızın zamanlama olmaksızın bir yükle temas etmeyeceği bir alan sözleşmesi, ağ geçidinin takas edilebilir olduğu bir fabrika ve her yeniden denemede ayakta kalan bir webhook yöneticisi. Bunları doğru yaparsanız, DuitNow QR eklemek, Stripe’ı eklemek veya tümünü yeniden kullanılabilir bir <code>cashier-bayarcash</code> tarzı pakete çıkartmak, yeniden yazmak değil, yeniden adlandırmak olur.</p>

<hr/>

<p><em>Ödeme entegrasyonları gerçek parayı etkiler — durum haritanızı, imza doğrulamanızı ve idempotansı en sert şekilde test edin ve her zaman BayarCash'ın mevcut resmi belgelerine karşı doğrulayın.</em></p>

Kaynak: Orijinal Makale

Bu Makaleyi Paylaş