### Install Pakasir SDK using Composer Source: https://github.com/fadhila36/pakasir-sdk/blob/main/README.md Install the Pakasir SDK package using Composer. Ensure your server meets the PHP and Laravel version requirements. ```bash composer require fadhila36/pakasir-sdk ``` -------------------------------- ### Facade Usage Example Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md Demonstrates how to use the Pakasir Facade for static access to its methods. This approach offers simpler syntax and is suitable for quick prototyping. ```php use Fadhila36\Pakasir\Facades\Pakasir; class OrderController extends Controller { public function store(Request $request) { $response = Pakasir::createPayment(...); } } ``` -------------------------------- ### Pakasir API Request and Response Log Example Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/configuration.md Example log output when PAKASIR_LOGGING_ENABLED is set to true, showing a POST request and its corresponding response. ```log [2025-01-01 12:00:00] local.INFO: Pakasir API Request: [POST] to https://app.pakasir.com/api/transactioncreate/qris {"payload":{"project":"my-project","order_id":"INV-001","amount":50000,"api_key":"sk_......"}} [2025-01-01 12:00:01] local.INFO: Pakasir API Response: Status 200 {"body":"{\"payment\":{\"fee\":350,\"total_payment\":50350,\"payment_number\":\"00020127...\",\"expired_at\":\"2025-01-02T...\",\"completed_at\":null}}"} ``` -------------------------------- ### Dependency Injection Usage Example Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md Illustrates the preferred method of using Dependency Injection to access the Pakasir service. This approach enhances testability and IDE support. ```php use Fadhila36\Pakasir\Contracts\PakasirInterface; class OrderController extends Controller { public function __construct( private PakasirInterface $pakasir ) {} public function store(Request $request) { $response = $this->pakasir->createPayment(...); } } ``` -------------------------------- ### Create Payment using Pakasir Facade Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md Example of creating a payment transaction using the Pakasir Facade, specifying the payment method, order ID, and amount. ```php use Fadhila36\Pakasir\Facades\Pakasir; use Fadhila36\Pakasir\Enums\PaymentMethod; $response = Pakasir::createPayment( paymentMethod: PaymentMethod::QRIS, orderId: 'INV-001', amount: 50000 ); ``` -------------------------------- ### Handle PaymentCompleted Event Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Events.md Example listener for the PaymentCompleted event. Use this to update the order status to 'paid' and log the completion. ```php use Fadhila36\Pakasir\Events\PaymentCompleted; public function handle(PaymentCompleted $event): void { $order = Order::findBy('order_id', $event->response->orderId); $order->update([ 'status' => 'paid', 'paid_at' => now(), ]); Log::info("Pembayaran berhasil: {$event->response->orderId}"); } ``` -------------------------------- ### Composer JSON Setup for Pakasir Facade Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md This JSON configuration snippet shows how the Pakasir Facade is automatically registered in the composer.json file for Laravel applications. ```json { "extra": { "laravel": { "aliases": { "Pakasir": "Fadhila36\\Pakasir\\Facades\\Pakasir" } } } } ``` -------------------------------- ### Handle WebhookReceived Event Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Events.md Example listener for the WebhookReceived event. Use this to log incoming webhook data. Note that this event is dispatched before the full API verification is complete. ```php use Fadhila36\Pakasir\Events\WebhookReceived; public function handle(WebhookReceived $event): void { Log::info("Webhook diterima", [ 'order_id' => $event->payload->orderId, 'status' => $event->payload->status->value, ]); } ``` -------------------------------- ### Handle TransactionCreated Event Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Events.md Example listener for the TransactionCreated event. Use this to log the new transaction and save notification details to the database. ```php use Fadhila36\Pakasir\Events\TransactionCreated; public function handle(TransactionCreated $event): void { Log::info("Transaksi baru dibuat: {$event->response->orderId}"); // Simpan notifikasi ke database Notification::create([ 'type' => 'transaction.created', 'data' => [ 'order_id' => $event->response->orderId, 'amount' => $event->response->amount, 'payment_url' => $event->response->paymentUrl, ] ]); } ``` -------------------------------- ### Setup API Route for Webhooks Source: https://github.com/fadhila36/pakasir-sdk/blob/main/docs/INTEGRATION.md Define a POST route in `routes/api.php` to receive incoming webhook requests from Pakasir. This route will direct requests to the `handle` method of your `WebhookController`. ```php use App\Http\Controllers\WebhookController; Route::post('/webhooks/pakasir', [WebhookController::class, 'handle']); ``` -------------------------------- ### Handling ApiException in Payment Creation Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/errors.md Example of catching an ApiException during payment creation. It logs the error details and provides specific responses based on the HTTP status code. ```php use Fadhila36\Pakasir\Exceptions\ApiException; use Fadhila36\Pakasir\Facades\Pakasir; use Fadhila36\Pakasir\Enums\PaymentMethod; try { $response = Pakasir::createPayment( paymentMethod: PaymentMethod::QRIS, orderId: 'INV-001', amount: 50000 ); } catch (ApiException $e) { Log::error('Pakasir API Error', [ 'message' => $e->getMessage(), 'status_code' => $e->getStatusCode(), 'response_body' => $e->getResponseBody(), ]); // Handle berdasarkan status code if ($e->getStatusCode() === 401) { return response()->json(['error' => 'API Key tidak valid'], 400); } elseif ($e->getStatusCode() === 400) { return response()->json(['error' => 'Parameter request tidak valid'], 400); } else { return response()->json(['error' => 'Gagal membuat pembayaran'], 500); } } ``` -------------------------------- ### Usage Example: Checking Transaction Status Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/DataObjects.md Demonstrates how to fetch transaction details and check its status using the TransactionDetailResponse object and its helper methods. It shows accessing status directly via property and using the isCompleted() method. ```php use Fadhila36\Pakasir\Facades\Pakasir; $detail = Pakasir::detailPayment( orderId: 'INV-001', amount: 50000 ); // Check status via property echo $detail->status->value; // 'completed', 'pending', 'expired', etc // Check with helper method if ($detail->isCompleted()) { // Process order as paid $order->update(['status' => 'paid', 'paid_at' => $detail->completedAt]); } ``` -------------------------------- ### Get Payment Data using Pakasir Facade Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md Retrieves payment data, including fees and total payment amount, using the Pakasir Facade. This method is recommended over getPaymentUrl. ```php $data = Pakasir::getPaymentData( paymentMethod: 'bni_va', orderId: 'INV-001', amount: 100000 ); echo $data->fee; // Rp 3.500 echo $data->totalPayment; // Rp 103.500 ``` -------------------------------- ### Handle Pakasir API Errors with ApiException Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Exceptions.md This example shows how to catch ApiException and access details like the HTTP status code and response body. It includes logic to handle specific error codes returned by the API. ```php use Fadhila36\Pakasir\Exceptions\ApiException; try { $response = Pakasir::createPayment( paymentMethod: PaymentMethod::QRIS, orderId: 'INV-001', amount: 50000 ); } catch (ApiException $e) { // Access HTTP status code $statusCode = $e->getStatusCode(); // Access raw response body $responseBody = $e->getResponseBody(); Log::error('Pakasir API Error', [ 'message' => $e->getMessage(), 'status_code' => $statusCode, 'response_body' => $responseBody, ]); // Handle by status code if ($statusCode === 401) { return response()->json(['error' => 'Invalid API Key'], 400); } elseif ($statusCode === 400) { return response()->json(['error' => 'Invalid request'], 400); } else { return response()->json(['error' => 'API Error'], 500); } } ``` -------------------------------- ### Overriding Pakasir Configuration Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/ServiceProvider.md This example shows how to override default configuration values in the Pakasir SDK. You can change settings like 'base_url' or 'timeout' based on your application's environment or specific needs. ```php env('PAKASIR_PROJECT'), 'api_key' => env('PAKASIR_API_KEY'), 'base_url' => env('APP_ENV') === 'production' ? 'https://app.pakasir.com/api' : 'https://sandbox.pakasir.com/api', 'timeout' => 60, // Override default 30 // ... rest ]; ``` -------------------------------- ### Using Pakasir Facade for Static Access Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md Demonstrates how to use the Pakasir Facade for static access to common SDK methods like creating payments, retrieving details, and verifying webhooks. ```php use Fadhila36\Pakasir\Facades\Pakasir; // Static access ke metode publik $response = Pakasir::createPayment(...); $detail = Pakasir::detailPayment(...); $webhook = Pakasir::verifyWebhook(...); ``` -------------------------------- ### Instalasi Pakasir SDK sebagai Dev Dependency Source: https://github.com/fadhila36/pakasir-sdk/blob/main/docs/DEVELOPMENT.md Jalankan perintah ini di terminal aplikasi host untuk menginstal paket dari source lokal. Opsi '@dev' memastikan versi pengembangan digunakan. ```bash composer require fadhila36/pakasir-sdk @dev ``` -------------------------------- ### Checking Transaction Status Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/types.md Example of how to check if a transaction has been completed using the TransactionStatus enum. ```php use Fadhila36\Pakasir\Enums\TransactionStatus; if ($detail->status === TransactionStatus::COMPLETED) { echo "Pembayaran berhasil!"; } $statusValue = TransactionStatus::PENDING->value; // 'pending' ``` -------------------------------- ### Get API Response Body Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/errors.md Retrieves the raw response body from the API. Returns null if not available. ```php public function getResponseBody(): ?string ``` -------------------------------- ### Configure Pakasir Credentials in .env Source: https://github.com/fadhila36/pakasir-sdk/blob/main/docs/INTEGRATION.md Tambahkan kredensial Project Slug dan API Key Anda ke file .env. Hindari hardcoding API Key langsung di kode. ```env PAKASIR_PROJECT=slug-proyek-anda PAKASIR_API_KEY=api-key-anda-yang-rahasia ``` -------------------------------- ### Mempublikasikan Ulang Konfigurasi Pakasir SDK Source: https://github.com/fadhila36/pakasir-sdk/blob/main/docs/DEVELOPMENT.md Jalankan perintah Artisan ini di aplikasi host jika Anda memodifikasi file konfigurasi 'config/pakasir.php' di dalam library. Opsi '--force' akan menimpa file konfigurasi yang ada. ```bash php artisan vendor:publish --tag=config --force ``` -------------------------------- ### Get API Status Code Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/errors.md Retrieves the HTTP status code from the API response. Returns null if not available. ```php public function getStatusCode(): ?int ``` -------------------------------- ### Publish Pakasir Configuration File Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/ServiceProvider.md The `boot` method publishes the `pakasir.php` configuration file to the application's config directory when the application is running in the console. This allows for selective publishing using the 'config' tag. ```php public function boot(): void { if ($this->app->runningInConsole()) { $this->publishes([ __DIR__.'/../config/pakasir.php' => config_path('pakasir.php'), ], 'config'); } } ``` -------------------------------- ### Membuat dan Mendorong Tag Versi Baru Source: https://github.com/fadhila36/pakasir-sdk/blob/main/docs/DEVELOPMENT.md Gunakan perintah Git ini untuk membuat tag versi baru mengikuti Semantic Versioning dan mendorongnya ke repositori remote. Packagist akan mendeteksi tag ini untuk pembaruan rilis. ```bash git tag v1.0.x git push origin v1.0.x ``` -------------------------------- ### Dependency Injection of Pakasir Interface Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/PakasirInterface.md Inject the PakasirInterface into your controllers or services for easy access to its functionalities. This example shows injection via the constructor. ```php namespace App\Http\Controllers; use Fadhila36\Pakasir\Contracts\PakasirInterface; class CheckoutController extends Controller { public function __construct( private PakasirInterface $pakasir ) {} public function store(Request $request) { // Gunakan $this->pakasir untuk semua operasi $response = $this->pakasir->createPayment( paymentMethod: $request->input('payment_method'), orderId: $request->input('order_id'), amount: $request->input('amount') ); return response()->json($response->toArray()); } } ``` -------------------------------- ### Handle TransactionCanceled Event Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Events.md Example listener for the TransactionCanceled event. Use this to update order status to 'canceled' and notify the user after a successful cancellation. ```php use Fadhila36\Pakasir\Events\TransactionCanceled; public function handle(TransactionCanceled $event): void { $order = Order::findBy('order_id', $event->response->orderId); $order->update([ 'status' => 'canceled', 'canceled_at' => now(), ]); // Kirim notifikasi ke user $order->user->notify(new OrderCanceledNotification($order)); } ``` -------------------------------- ### Accessing Pakasir Methods via Facade Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Pakasir.md Demonstrates how to use the Pakasir Facade to call public methods like createPayment, detailPayment, and verifyWebhook. This provides a convenient way to interact with the SDK's functionalities. ```php use Fadhila36\Pakasir\Facades\Pakasir; Pakasir::createPayment(...); Pakasir::detailPayment(...); Pakasir::verifyWebhook(...); ``` -------------------------------- ### Mocking Facade for Testing Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md Shows how to mock a Facade method for testing purposes using PHPUnit. This involves defining expected method calls and return values. ```php use Fadhila36\Pakasir\Facades\Pakasir; use Fadhila36\Pakasir\DataObjects\TransactionCreateResponse; use Tests\TestCase; class OrderControllerTest extends TestCase { public function test_checkout() { $mock = TransactionCreateResponse::fromArray([ 'project' => 'test', 'order_id' => 'INV-001', 'amount' => 50000, 'fee' => 350, 'total_payment' => 50350, 'payment_method' => 'qris', 'payment_url' => 'https://test.com', 'payment_number' => '000201...', 'expired_at' => '2025-01-02T12:00:00Z', ]); Pakasir::shouldReceive('createPayment') ->once() ->andReturn($mock); $response = $this->post('/checkout', [ 'order_id' => 'INV-001', 'amount' => 50000, ]); $response->assertJson(['order_id' => 'INV-001']); } } ``` -------------------------------- ### Get Payment URL using Pakasir Facade (Deprecated) Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md This method is deprecated and should be replaced by getPaymentData(). It was used to retrieve the payment URL for a transaction. ```php Pakasir::getPaymentUrl( string|PaymentMethod $paymentMethod, string $orderId, int|float $amount, ?string $redirectUrl = null ): string ``` -------------------------------- ### WebhookReceived Event Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Events.md This event is dispatched every time the SDK receives and starts processing a webhook from Pakasir. It includes the raw webhook payload. ```APIDOC ## WebhookReceived Event ### Description This event is dispatched every time the SDK receives and starts processing a webhook from Pakasir. It includes the raw webhook payload. ### Properties - **payload** (WebhookPayload) - Required - Data webhook yang diterima. ### Dispatched When - Inside `Pakasir::verifyWebhook()` before complete validation is performed. ### Important Note This event is dispatched *before* the double-check to the Pakasir API is completed. If you need data that is 100% verified, wait until `verifyWebhook()` completes without exceptions. ### Listener Example ```php use Fadhila36\Pakasir\Events\WebhookReceived; public function handle(WebhookReceived $event): void { Log::info('Webhook received', [ 'order_id' => $event->payload->orderId, 'status' => $event->payload->status->value, ]); } ``` ``` -------------------------------- ### Contoh Konfigurasi .env untuk Pakasir SDK Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/configuration.md Atur variabel lingkungan yang diperlukan dan opsional di file `.env` aplikasi Anda untuk mengonfigurasi SDK Pakasir. ```env # Required PAKASIR_PROJECT=my-store-slug PAKASIR_API_KEY=sk_live_abcd1234efgh5678ijkl90mn # Optional - gunakan default jika tidak diatur PAKASIR_BASE_URL=https://app.pakasir.com/api PAKASIR_TIMEOUT=30 PAKASIR_RETRY_ATTEMPTS=3 PAKASIR_RETRY_DELAY=100 PAKASIR_LOGGING_ENABLED=false # Production # PAKASIR_LOGGING_ENABLED=true (untuk staging/production dengan monitoring) ``` -------------------------------- ### WebhookReceived Event Class Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Events.md Defines the WebhookReceived event, dispatched when the SDK receives and starts processing a webhook from Pakasir. It contains the webhook payload. ```php namespace Fadhila36\Pakasir\Events; class WebhookReceived { public function __construct( public WebhookPayload $payload ) {} } ``` -------------------------------- ### Run Queue Worker Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/PaymentLinkNotification.md Ensure your queue worker is running to process notifications asynchronously. This command starts a worker that listens for pending jobs. ```bash php artisan queue:work ``` -------------------------------- ### Publikasi File Konfigurasi Pakasir Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/configuration.md Jalankan perintah ini untuk mempublikasikan file konfigurasi `config/pakasir.php` ke aplikasi Laravel Anda. ```bash php artisan vendor:publish --provider="Fadhila36\Pakasir\PakasirServiceProvider" --tag="config" ``` -------------------------------- ### QRISHelper::isValid() Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/QRISHelper.md Checks if a string is a valid QRIS payload according to the Indonesian EMVCo standard. It verifies if the payload starts with the consistent '000201' indicator. ```APIDOC ## QRISHelper::isValid() ### Description Memeriksa apakah string adalah valid QRIS payload berdasarkan standar EMVCo Indonesia. ### Method `static public function isValid(string $payload): bool` ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Parameters - **payload** (string) - Required - QRIS payload string untuk divalidasi ### Request Example ```php use Fadhila36\Pakasir\Support\QRISHelper; // Valid QRIS strings QRISHelper::isValid('000201010212...'); // true QRISHelper::isValid(' 000201010212...'); // false (whitespace tidak di-trim dulu) // Invalid QRISHelper::isValid('123456789'); // false QRISHelper::isValid(''); // false ``` ### Response #### Success Response (bool) - `true` jika payload dimulai dengan `000201` (payload format indicator EMVCo) - `false` untuk selain itu #### Response Example ```json { "example": true } ``` ### Error Handling - `TypeError` is thrown if the payload is not a string. ``` -------------------------------- ### Using TransactionCreateResponse in Payment Creation Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/DataObjects.md Demonstrates how to use the Pakasir facade to create a payment and access properties of the returned TransactionCreateResponse object. Imports the necessary facade. ```php use Fadhila36\Pakasir\Facades\Pakasir; $response = Pakasir::createPayment( paymentMethod: 'qris', orderId: 'INV-001', amount: 50000 ); // $response adalah TransactionCreateResponse echo $response->paymentUrl; echo $response->totalPayment; echo $response->paymentNumber; // Akses via enumeration echo $response->paymentMethod->value; // 'qris' ``` -------------------------------- ### Facades Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/INDEX.md Provides static access to Pakasir SDK functionality. ```APIDOC ## Facades ### Description Offers a static interface (`Pakasir`) to interact with the SDK's core functionalities, delegating calls to the underlying implementation. ### Facade Class `Pakasir` ### Usage Allows calling methods like `Pakasir::createPayment()` for convenient access. ``` -------------------------------- ### Konfigurasi Composer untuk Path Repository Lokal Source: https://github.com/fadhila36/pakasir-sdk/blob/main/docs/DEVELOPMENT.md Tambahkan definisi ini ke composer.json aplikasi host untuk menginstruksikan Composer agar memprioritaskan paket dari folder lokal. Pastikan 'symlink: true' diaktifkan untuk refleksi perubahan instan. ```json "repositories": [ { "type": "path", "url": "../pakasir-sdk", "options": { "symlink": true } } ], ``` -------------------------------- ### Configure Queue Database Driver Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/PaymentLinkNotification.md Set the queue connection to 'database' in your .env file to store queue jobs in the database. ```env QUEUE_CONNECTION=database ``` -------------------------------- ### Laravel Configuration File Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Pakasir.md Defines the SDK configuration parameters, including project ID, API key, base URL, and retry settings. These values are typically loaded from environment variables. ```php return [ 'project' => env('PAKASIR_PROJECT'), 'api_key' => env('PAKASIR_API_KEY'), 'base_url' => env('PAKASIR_BASE_URL', 'https://app.pakasir.com/api'), 'timeout' => (int) env('PAKASIR_TIMEOUT', 30), 'retry_attempts' => (int) env('PAKASIR_RETRY_ATTEMPTS', 3), 'retry_delay' => (int) env('PAKASIR_RETRY_DELAY', 100), 'logging_enabled' => (bool) env('PAKASIR_LOGGING_ENABLED', false), ]; ``` -------------------------------- ### Simulate Payment using Pakasir Facade Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md Simulates a payment transaction using the Pakasir Facade to test payment flows without actual processing. ```php $simulated = Pakasir::simulationPayment( orderId: 'INV-TEST-001', amount: 10000 ); echo $simulated->status->value; // 'completed' ``` -------------------------------- ### QRIS Payment Gateway Integration Workflow Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/QRISHelper.md This snippet demonstrates the complete workflow for creating a QRIS payment using the Pakasir SDK. It includes creating the payment, retrieving the QRIS payload, performing an optional validation using QRISHelper, and saving the QRIS code. This process is handled automatically by the SDK, abstracting away manual QRIS generation. ```php use Fadhila36\Pakasir\Facades\Pakasir; use Fadhila36\Pakasir\Support\QRISHelper; use Fadhila36\Pakasir\Enums\PaymentMethod; // 1. Create payment QRIS $response = Pakasir::createPayment( paymentMethod: PaymentMethod::QRIS, orderId: 'INV-001', amount: 50000 ); // 2. Response berisi QRIS string $qrisPayload = $response->paymentNumber; // '000201010212...' // 3. Validasi (optional) if (QRISHelper::isValid($qrisPayload)) { // 4. Simpan dan gunakan QRCode::generate($qrisPayload) ->saveTo($path); $order->qris_code = $qrisPayload; $order->save(); } // 5. User scan QRIS di smartphone → Pakasir handle pembayaran // 6. Webhook atau polling detailPayment() untuk check status ``` -------------------------------- ### Validate QRIS Payload Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/QRISHelper.md Checks if a string is a valid QRIS payload by verifying if it starts with the EMVCo Indonesia payload format indicator '000201'. Whitespace at the beginning of the payload will result in `false`. ```php use Fadhila36\Pakasir\Support\QRISHelper; // Valid QRIS strings QRISHelper::isValid('000201010212...'); // true QRISHelper::isValid(' 000201010212...'); // false (whitespace tidak di-trim dulu) // Invalid QRISHelper::isValid('123456789'); // false QRISHelper::isValid(''); // false QRISHelper::isValid(null); // throws TypeError (expect string) ``` -------------------------------- ### PHP Pakasir SDK Payment Operations Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/types.md Demonstrates creating a QRIS payment, checking its status, and verifying a webhook using the Pakasir SDK. Ensure necessary facades and enums are imported. ```php use Fadhila36\Pakasir\Facades\Pakasir; use Fadhila36\Pakasir\Enums\PaymentMethod; use Fadhila36\Pakasir\Enums\TransactionStatus; // Membuat pembayaran $response = Pakasir::createPayment( paymentMethod: PaymentMethod::QRIS, orderId: 'INV-001', amount: 50000 ); // response adalah TransactionCreateResponse // $response->totalPayment = 50650 // Mengecek status $detail = Pakasir::detailPayment('INV-001', 50000); // detail adalah TransactionDetailResponse if ($detail->status === TransactionStatus::COMPLETED) { // ... } // Memverifikasi webhook $webhook = Pakasir::verifyWebhook($request->all(), 50000); // webhook adalah WebhookPayload ``` -------------------------------- ### Simulate Payment Transaction (Sandbox) Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Pakasir.md This method simulates a successful payment in the Sandbox environment for testing purposes. It requires the order ID and amount of the transaction to be simulated. Note that this functionality is only available in the Sandbox environment. ```php public function simulationPayment( string $orderId, int|float $amount ): TransactionDetailResponse ``` ```php // Hanya bekerja di environment Sandbox $simulated = Pakasir::simulationPayment( orderId: 'INV-TEST-001', amount: 10000 ); echo "Status simulasi: {$simulated->status->value}"; // "completed" ``` -------------------------------- ### Handling WebhookValidationException in Laravel Route Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/errors.md Example of handling WebhookValidationException in a Laravel route. It demonstrates how to verify a webhook, process a paid order, and reject suspicious webhooks by logging the error and returning a 400 response. ```php use Fadhila36\Pakasir\Exceptions\WebhookValidationException; use Fadhila36\Pakasir\Facades\Pakasir; Route::post('/webhook/pakasir', function (Request $request) { try { // Ambil order dari database $order = Order::findOrFail($request->input('order_id')); // Verifikasi webhook dengan expected amount dari DB $webhook = Pakasir::verifyWebhook( $request->all(), $order->amount ); // Jika lolos semua validasi $order->markAsPaid($webhook->completedAt); return response()->json(['status' => 'ok']); } catch (WebhookValidationException $e) { // Log suspicious webhook Log::warning("Suspicious webhook detected: {$e->getMessage()}", [ 'request' => $request->all(), 'error' => $e->getMessage(), ]); // Reject dengan HTTP 400 - tidak proses order return response()->json( ['error' => 'Webhook validation failed'], 400 ); } }); ``` -------------------------------- ### Pakasir Configuration Loading Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/ServiceProvider.md The service provider loads configuration from `config/pakasir.php`. All environment variables are resolved using the `env()` helper. ```php [ 'project' => env('PAKASIR_PROJECT'), 'api_key' => env('PAKASIR_API_KEY'), 'base_url' => env('PAKASIR_BASE_URL', 'https://app.pakasir.com/api'), 'timeout' => (int) env('PAKASIR_TIMEOUT', 30), 'retry_attempts' => (int) env('PAKASIR_RETRY_ATTEMPTS', 3), 'retry_delay' => (int) env('PAKASIR_RETRY_DELAY', 100), 'logging_enabled' => (bool) env('PAKASIR_LOGGING_ENABLED', false), ] ``` -------------------------------- ### Get Payment URL (Deprecated) Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Pakasir.md Generates a direct payment URL for a specific payment method. This method is deprecated and users should use `getPaymentData()` instead to obtain a complete DTO with fee and transaction details. ```php public function getPaymentUrl( string|PaymentMethod $paymentMethod, string $orderId, int|float $amount, ?string $redirectUrl = null ): string ``` -------------------------------- ### simulationPayment() Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/PakasirInterface.md Performs a successful payment simulation in the Sandbox environment. This is useful for testing payment flows without actual transactions. ```APIDOC ## simulationPayment() ### Description Performs a successful payment simulation in the Sandbox environment. ### Method ```php public function simulationPayment( string $orderId, int|float $amount ): TransactionDetailResponse; ``` ### Parameters - **orderId** (string) - Required - The order identifier. - **amount** (int|float) - Required - The transaction amount. ### Return `TransactionDetailResponse` - The response object from the simulation. ### Throws `ApiException` - If an API error occurs during the simulation. ``` -------------------------------- ### Testing Pakasir Interface with Mocking Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/PakasirInterface.md Demonstrates how to mock the PakasirInterface for unit testing. This allows you to isolate your controller logic and verify interactions with the Pakasir service without making actual API calls. The mock is bound to the application container for the test. ```php use Fadhila36\Pakasir\Contracts\PakasirInterface; use Fadhila36\Pakasir\DataObjects\TransactionCreateResponse; use Fadhila36\Pakasir\Enums\PaymentMethod; use PHPUnit\Framework\TestCase; class CheckoutControllerTest extends TestCase { public function test_checkout_creates_payment() { // Mock interface $pakasirMock = $this->createMock(PakasirInterface::class); $response = TransactionCreateResponse::fromArray([ 'project' => 'test-project', 'order_id' => 'INV-001', 'amount' => 50000, 'fee' => 350, 'total_payment' => 50350, 'payment_method' => 'qris', 'payment_url' => 'https://test.com/pay', 'payment_number' => '000201...', 'expired_at' => '2025-01-02T12:00:00Z', ]); $pakasirMock ->expects($this->once()) ->method('createPayment') ->willReturn($response); // Bind mock ke container $this->app->bind(PakasirInterface::class, fn() => $pakasirMock); // Test controller $result = $this->post('/checkout', [ 'payment_method' => 'qris', 'order_id' => 'INV-001', 'amount' => 50000, ]); $result->assertJson(['order_id' => 'INV-001']); } } ``` -------------------------------- ### Get Local Payment Data Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/PakasirInterface.md This method generates local payment data without making an API call to the Pakasir server. It requires the payment method, order ID, amount, and an optional redirect URL, returning a TransactionCreateResponse object. ```php public function getPaymentData( string|PaymentMethod $paymentMethod, string $orderId, int|float $amount, ?string $redirectUrl = null ): TransactionCreateResponse; ``` -------------------------------- ### Register Pakasir SDK Singleton and Facade Alias Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/ServiceProvider.md The `register` method merges default configuration, registers a singleton instance of `PakasirInterface` with dependencies from configuration, and sets up an alias for the Facade. This method is called during application bootstrap. ```php public function register(): void { // Merge config default ke aplikasi $this->mergeConfigFrom(__DIR__.'/../config/pakasir.php', 'pakasir'); // Register singleton instance $this->app->singleton(PakasirInterface::class, function ($app) { $config = $app['config']['pakasir'] ?? []; return new Pakasir( project: (string) ($config['project'] ?? ''), apiKey: (string) ($config['api_key'] ?? ''), baseUrl: (string) ($config['base_url'] ?? 'https://app.pakasir.com/api'), timeout: (int) ($config['timeout'] ?? 30), retryAttempts: (int) ($config['retry_attempts'] ?? 3), retryDelay: (int) ($config['retry_delay'] ?? 100), loggingEnabled: (bool) ($config['logging_enabled'] ?? false) ); }); // Alias untuk Facade $this->app->alias(PakasirInterface::class, 'pakasir'); } ``` -------------------------------- ### Display Pending Payment Notifications in Blade Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/PaymentLinkNotification.md This example shows how to iterate through a user's notifications in a Blade template and display details for pending payment notifications, including a payment link. It checks the notification type and accesses data from the notification's data array. ```blade // Dalam Blade template untuk menampilkan notifikasi pending @forelse(auth()->user()->notifications as $notification) @if($notification->type === 'Fadhila36\Pakasir\Notifications\PaymentLinkNotification')

Tagihan {{ $notification->data['order_id'] }}

Total: Rp {{ number_format($notification->data['total_payment']) }}

Waktu Kadaluarsa: {{ $notification->data['expired_at'] }}

Bayar Sekarang
@endif @empty

Tidak ada notifikasi pembayaran

@endforelse ``` -------------------------------- ### Publish Pakasir Configuration Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/ServiceProvider.md Use this command to publish the Pakasir SDK's configuration file to your application. This allows you to modify the default settings. ```bash php artisan vendor:publish --provider="Fadhila36\Pakasir\PakasirServiceProvider" --tag="config" php artisan config:clear ``` -------------------------------- ### Simulate Payment Success Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/PakasirInterface.md This method simulates a successful payment in the Sandbox environment. It requires the order ID and amount, returning a TransactionDetailResponse object and may throw an ApiException. ```php public function simulationPayment( string $orderId, int|float $amount ): TransactionDetailResponse; ``` -------------------------------- ### Enum PaymentMethod Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/types.md Mendefinisikan semua metode pembayaran yang didukung oleh Pakasir, termasuk Virtual Accounts dan metode pembayaran lainnya. ```php enum PaymentMethod: string { case ALL = 'all'; case QRIS = 'qris'; case PAYPAL = 'paypal'; // Virtual Accounts case CIMB_NIAGA_VA = 'cimb_niaga_va'; case BNI_VA = 'bni_va'; case BNC_VA = 'bnc_va'; case MAYBANK_VA = 'maybank_va'; case PERMATA_VA = 'permata_va'; case ATM_BERSAMA_VA = 'atm_bersama_va'; case BRI_VA = 'bri_va'; // Other VAs case SAMPOERNA_VA = 'sampoerna_va'; case ARTHA_GRAHA_VA = 'artha_graha_va'; } ``` -------------------------------- ### Simulate Payment Success (Sandbox) Source: https://github.com/fadhila36/pakasir-sdk/blob/main/README.md Performs a simulated successful payment. This function is only available in Sandbox/testing mode and requires the order ID and amount. ```php Pakasir::simulationPayment(string $orderId, int|float $amount): TransactionDetailResponse; ``` -------------------------------- ### Payment Methods (Enum) Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/README.md List of all supported payment methods, their enums, codes, and fees. ```APIDOC ## Payment Methods Enum ### All Methods - **Enum**: `PaymentMethod::ALL` - **Code**: `all` - **Fee**: 0 ### QRIS - **Enum**: `PaymentMethod::QRIS` - **Code**: `qris` - **Fee**: 0.7% - 1% ### PayPal - **Enum**: `PaymentMethod::PAYPAL` - **Code**: `paypal` - **Fee**: 1% (min Rp 3.000) ### BNI VA - **Enum**: `PaymentMethod::BNI_VA` - **Code**: `bni_va` - **Fee**: Rp 3.500 ### BRI VA - **Enum**: `PaymentMethod::BRI_VA` - **Code**: `bri_va` - **Fee**: Rp 3.500 ### CIMB Niaga VA - **Enum**: `PaymentMethod::CIMB_NIAGA_VA` - **Code**: `cimb_niaga_va` - **Fee**: Rp 3.500 ### Maybank VA - **Enum**: `PaymentMethod::MAYBANK_VA` - **Code**: `maybank_va` - **Fee**: Rp 3.500 ### Permata VA - **Enum**: `PaymentMethod::PERMATA_VA` - **Code**: `permata_va` - **Fee**: Rp 3.500 ### BNC VA - **Enum**: `PaymentMethod::BNC_VA` - **Code**: `bnc_va` - **Fee**: Rp 3.500 ### ATM Bersama VA - **Enum**: `PaymentMethod::ATM_BERSAMA_VA` - **Code**: `atm_bersama_va` - **Fee**: Rp 3.500 ### Sampoerna VA - **Enum**: `PaymentMethod::SAMPOERNA_VA` - **Code**: `sampoerna_va` - **Fee**: Rp 2.000 ### Artha Graha VA - **Enum**: `PaymentMethod::ARTHA_GRAHA_VA` - **Code**: `artha_graha_va` - **Fee**: Rp 2.000 ``` -------------------------------- ### Struktur File Konfigurasi Pakasir Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/configuration.md Ini adalah struktur default dari file konfigurasi `config/pakasir.php`. Pengaturan diambil dari variabel lingkungan `.env`. ```php env('PAKASIR_PROJECT'), 'api_key' => env('PAKASIR_API_KEY'), 'base_url' => env('PAKASIR_BASE_URL', 'https://app.pakasir.com/api'), 'timeout' => (int) env('PAKASIR_TIMEOUT', 30), 'retry_attempts' => (int) env('PAKASIR_RETRY_ATTEMPTS', 3), 'retry_delay' => (int) env('PAKASIR_RETRY_DELAY', 100), 'logging_enabled' => (bool) env('PAKASIR_LOGGING_ENABLED', false), ]; ``` -------------------------------- ### Verify Environment Variables in Tinker Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/ServiceProvider.md This command can be used within `php artisan tinker` to verify that your environment variables are being correctly loaded into the Pakasir configuration. ```bash echo config('pakasir.project') ``` -------------------------------- ### Configure Pakasir Credentials in .env Source: https://github.com/fadhila36/pakasir-sdk/blob/main/README.md Set your Pakasir project credentials and other settings in the .env file. This includes the project slug, API key, timeout, retry attempts, and logging status. ```env PAKASIR_PROJECT=slug-proyek-anda PAKASIR_API_KEY=api-key-rahasia-anda PAKASIR_TIMEOUT=30 PAKASIR_RETRY_ATTEMPTS=3 PAKASIR_LOGGING_ENABLED=true ``` -------------------------------- ### simulationPayment() Source: https://github.com/fadhila36/pakasir-sdk/blob/main/README.md Simulates a successful payment, intended for Sandbox/testing modes. ```APIDOC ## simulationPayment() ### Description Simulates a successful payment. This method is intended for Sandbox/testing modes only. ### Method Signature ```php Pakasir::simulationPayment(string $orderId, int|float $amount): TransactionDetailResponse ``` ### Parameters - **orderId** (string) - Required - The unique identifier for the order. - **amount** (int|float) - Required - The transaction amount. ### Returns - **TransactionDetailResponse** - The response object containing the transaction details. ``` -------------------------------- ### Webhook Methods Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/README.md Method for verifying incoming webhooks. ```APIDOC ## verifyWebhook() ### Description Verifikasi & double-check webhook. ### Method `verifyWebhook()` ### Return `WebhookPayload` ``` -------------------------------- ### Handle General API and SDK Errors in PHP Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/errors.md Implement try-catch blocks to handle both general API errors (ApiException) and other SDK-specific errors (PakasirException). Log detailed information for API errors, including status codes and response bodies. ```php use Fadhila36\Pakasir\Exceptions\ApiException; use Fadhila36\Pakasir\Exceptions\PakasirException; try { $response = Pakasir::createPayment(...); } catch (ApiException $e) { // Handle API-specific errors Log::error("Pakasir API failed: {$e->getMessage()}", [ 'status_code' => $e->getStatusCode(), 'body' => $e->getResponseBody(), ]); return response()->json(['error' => 'Payment gateway error'], 500); } catch (PakasirException $e) { // Handle other SDK errors Log::error("Pakasir error: {$e->getMessage()}"); return response()->json(['error' => 'Payment error'], 500); } ``` -------------------------------- ### verifyWebhook() Source: https://github.com/fadhila36/pakasir-sdk/blob/main/_autodocs/api-reference/Facades.md Verifies incoming webhook payloads. This facade method delegates to PakasirInterface::verifyWebhook(). ```APIDOC ## verifyWebhook() ### Description Facade delegate to `PakasirInterface::verifyWebhook()`. ### Method Signature ```php Pakasir::verifyWebhook( array $payload, int|float $expectedAmount ): WebhookPayload ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```php use Fadhila36\Pakasir\Exceptions\WebhookValidationException; try { $webhook = Pakasir::verifyWebhook( $request->all(), $order->amount ); $order->markAsPaid($webhook->completedAt); } catch (WebhookValidationException $e) { Log::warning("Webhook validation failed"); } ``` ### Response #### Success Response - **WebhookPayload**: The validated webhook payload object. #### Response Example None provided in source. ``` -------------------------------- ### Webhook Controller Implementation Source: https://github.com/fadhila36/pakasir-sdk/blob/main/docs/INTEGRATION.md Implement the `WebhookController` to handle incoming payment notifications. This includes receiving the payload, verifying the transaction with Pakasir's API for security, and updating the transaction status. ```php all(); $orderId = $payload['order_id'] ?? null; if (!$orderId) return response()->json(['message' => 'Invalid Payload'], 400); // 2. Cari Transaksi $transaction = Transaction::where('order_id', $orderId)->first(); if (!$transaction) return response()->json(['message' => 'Not Found'], 404); if ($transaction->status === 'paid') { return response()->json(['message' => 'Already Paid']); } // 3. SECURITY CHECK: Verifikasi ulang ke Pakasir (Double Check) // Jangan langsung percaya payload webhook mentah, cek status aslinya ke server Pakasir try { $check = Pakasir::detailPayment($orderId, $transaction->amount); // Pastikan nominal yang dibayar sesuai tagihan $apiAmount = $check['amount'] ?? 0; if ($apiAmount != $transaction->amount) { return response()->json(['message' => 'Invalid Amount'], 400); } $status = $check['status'] ?? 'pending'; } catch ( Exception $e) { return response()->json(['message' => 'Verification failed'], 500); } // 4. Update Status Transaksi if ($status === 'completed') { $transaction->update(['status' => 'paid', 'paid_at' => now()]); // TODO: Kirim email sukses / buka akses produk user disini } elseif (in_array($status, ['expired', 'failed', 'canceled'])) { $transaction->update(['status' => $status]); } return response()->json(['status' => 'ok']); } } ```