# Terima bayaran dengan PHP SDK

> Install PHP SDK Bayarcash, cipta bayaran pada API v3, sahkan callback dan semak transaksi dari laman web PHP anda.
>
> Source: https://docs.bayarcash.com/ms/php-sdk/

Dengan PHP SDK Bayarcash, laman web PHP anda boleh mencipta bayaran, mengesahkan callback dan menyemak transaksi. Anda tidak perlu menulis HTTP call sendiri. Panduan ini menggunakan API v3, iaitu versi terkini. [README SDK di GitHub](https://github.com/bayarcash/php-sdk) menyenaraikan setiap method.

Jika anda menggunakan Laravel, guna [pakej Laravel](https://github.com/bayarcash/laravel). Pakej ini dibina atas SDK ini, dan menambah route serta konfigurasi. Lihat [Pilih SDK Bayarcash](/ms/sdks/).

## Sebelum anda mula

Sediakan perkara ini dahulu:

- PHP 7.4 atau lebih baru dengan extension `json`, dan Composer.
- Personal Access Token (PAT), API Secret Key dan satu portal key dari merchant dashboard. Guna keys sandbox semasa anda membina integrasi.

## Install SDK

Jalankan arahan ini dalam folder projek anda:

```bash
composer require bayarcash/php-sdk
```

Nama lama pakej ini ialah `webimpian/bayarcash-php-sdk`. Projek yang menggunakan pakej lama masih berfungsi, tetapi guna `bayarcash/php-sdk` untuk projek baru.

## Cipta client

Cipta satu client dengan token anda, kemudian tukar client itu kepada API v3. SDK bermula pada v2, dan v2 sudah deprecated.

```php
use Bayarcash\Bayarcash;

$bayarcash = new Bayarcash(getenv('BAYARCASH_PAT'));
$bayarcash->setApiVersion('v3');
$bayarcash->useSandbox(); // remove this line in production

$apiSecretKey = getenv('BAYARCASH_API_SECRET_KEY');
```

Panggil `setApiVersion()` dan `useSandbox()` sebelum anda membuat sebarang request.

## Terima bayaran

Untuk menerima bayaran, bina request, tandatangani request itu, dan hantar pelanggan ke page bayaran:

1. Bina request dengan portal key, butiran pesanan dan URL anda.
2. Tambah checksum yang ditandatangani dengan API Secret Key anda.
3. Cipta payment intent dan redirect pelanggan ke `url` payment intent itu.

```php
$data = [
    'portal_key'             => 'your_portal_key',
    'payment_channel'        => Bayarcash::FPX,
    'order_number'           => 'INV-1001',
    'amount'                 => '10.00',
    'payer_name'             => 'Ahmad bin Abdullah',
    'payer_email'            => 'ahmad@example.com',
    'payer_telephone_number' => '0123456789',
    'return_url'             => 'https://your-site.com/payment/return',
    'callback_url'           => 'https://your-site.com/payment/callback',
];

$data['checksum'] = $bayarcash->createPaymentIntentChecksumValue($apiSecretKey, $data);

$paymentIntent = $bayarcash->createPaymentIntent($data);

header('Location: ' . $paymentIntent->url);
exit;
```

Field utama dalam request:

| Field | Wajib | Nota |
|---|---|---|
| `portal_key` | Ya | Portal yang menerima bayaran. |
| `order_number` | Ya | Rujukan anda, maksimum 30 aksara. |
| `amount` | Ya | String dengan maksimum 2 tempat perpuluhan, contohnya `'10.00'`. |
| `payer_name`, `payer_email` | Ya | Nama dan e-mel pelanggan. |
| `payment_channel` | Tidak | Satu constant `Bayarcash::*` atau array constant. Jika anda tidak menghantar field ini, pelanggan memilih saluran sendiri. |
| `payer_telephone_number` | Tidak | Diperlukan untuk saluran e-wallet dan DuitNow. |
| `callback_url`, `return_url` | Tidak | URL untuk Bayarcash memaklumkan server anda, dan URL untuk Bayarcash menghantar pelanggan kembali. |

Checksum dibina daripada `payment_channel`, `order_number`, `amount`, `payer_name` dan `payer_email`. Jadi, tambah checksum selepas nilai field itu muktamad. Untuk menghantar semula request yang timeout dengan selamat, hantar UUID sebagai argumen kedua: `createPaymentIntent($data, $idempotencyKey)`.

## Sahkan callback

Apabila bayaran mencapai status akhir, Bayarcash menghantar keputusan ke `callback_url` anda sebagai POST. Sahkan callback itu sebelum anda mengemas kini pesanan:

```php
use Bayarcash\Fpx;

$callbackData = $_POST;

if (! $bayarcash->verifyTransactionCallbackData($callbackData, $apiSecretKey)) {
    http_response_code(403);
    exit;
}

if ((int) $callbackData['status'] === Fpx::STATUS_SUCCESS) {
    // Mark the order with $callbackData['order_number'] as paid.
}

http_response_code(200);
```

Guna `verifyReturnUrlCallbackData()` pada page `return_url` anda. Pada v3, pelanggan kembali dengan field dalam query string, jadi hantar `$_GET`. Paparkan keputusan kepada pelanggan, tetapi kemas kini pesanan daripada callback sahaja. Sebabnya ada dalam [Sahkan callback dan checksum](/ms/callbacks-and-checksum/).

## Semak bayaran & transaksi

Panggilan ini membaca data yang Bayarcash rekodkan:

```php
$intent      = $bayarcash->getPaymentIntent('payment_intent_id');
$transaction = $bayarcash->getTransaction('transaction_id');

$byOrder = $bayarcash->getTransactionByOrderNumber('INV-1001');

$result = $bayarcash->getAllTransactions([
    'status'          => '3',
    'payment_channel' => Bayarcash::FPX,
]);
// $result['data'] holds the transactions, $result['meta'] the pagination.
```

Untuk membatalkan payment intent yang pelanggan belum bayar, panggil `$bayarcash->cancelPaymentIntent('payment_intent_id')`.

## Urus ralat

Jika panggilan gagal, SDK akan throw exception dari `Bayarcash\Exceptions`:

| Exception | Status HTTP | Apa yang perlu dibuat |
|---|---|---|
| `ValidationException` | 422 | Betulkan request. `$e->errors()` menyenaraikan field yang salah. |
| `FailedActionException` | 400 | Baca `$e->getMessage()` untuk mengetahui sebabnya. |
| `NotFoundException` | 404 | Semak ID yang anda minta. |
| `RateLimitExceededException` | 429 | Tunggu. `$e->rateLimitResetsAt` memberikan masa reset. |

## Tips

- **Uji keseluruhan aliran dalam sandbox dahulu.** Cipta bayaran dan bayar. Kemudian pastikan callback anda menandakan pesanan itu sebagai sudah dibayar, sebelum anda tukar kepada keys production.
- **Jangan letak token dan API Secret Key dalam kod anda.** Ambil keys itu dari environment variable atau secret store framework anda, seperti dalam contoh di atas.
- **Guna constant saluran dan bukan nombor.** `Bayarcash::FPX` lebih mudah dibaca berbanding `1`, dan README menyenaraikan setiap constant saluran.

## Isu biasa

### Kenapa saya dapat ralat Class "Webimpian\BayarcashSdk\Bayarcash" not found selepas update SDK?

Versi 3 SDK menukar namespace kepada Bayarcash. Tukar import anda kepada use Bayarcash\Bayarcash; (serta Bayarcash\Fpx dan Bayarcash\FpxDirectDebit). Untuk projek baru, install bayarcash/php-sdk. Jangan guna pakej lama webimpian/bayarcash-php-sdk.

### Kenapa saya dapat ralat "The getTransactionByOrderNumber method is only available for API version v3."?

SDK bermula pada API v2. Panggil $bayarcash->setApiVersion('v3') sejurus selepas anda mencipta client, sebelum sebarang request.

### Bagaimana saya tahu punca ValidationException daripada createPaymentIntent?

Panggil $e->errors() pada exception itu. Method ini menyenaraikan setiap field yang API tolak, contohnya amaun di luar julat yang dibenarkan atau nombor pesanan yang lebih daripada 30 aksara.
