firmantr3 / laravel-midtrans
Laravel 的 Midtrans 支付 API 包装器。
Requires
- illuminate/container: ^5.0|^6.0
- illuminate/contracts: ^5.0|^6.0
- midtrans/midtrans-php: ^2.0
Requires (Dev)
- orchestra/testbench: ^4.0
- phpunit/phpunit: ^8.0
README
Midtrans-PHP 库包装,适用于 Laravel。
功能
- Laravel 5/6 集成。
- 所有 Midtrans 服务的 Facade:Snap、VT-Direct。使用更方便,并创建测试的模拟。
安装
composer require firmantr3/laravel-midtrans
Laravel <= 5.4
将以下内容添加到您的 config/app.php
文件中的 Providers 部分数组中
<?php return [ 'providers': [ // Other Providers above Firmantr3\Midtrans\Providers\MidtransServiceProvider::class, ], ];
Laravel 5.5+ / 6
通过包发现自动添加。
发布配置
运行 artisan vendor:publish
命令发布迁移
php artisan vendor:publish --provider=Firmantr3\\Midtrans\\Providers\\MidtransServiceProvider
配置
更新您的 Laravel Midtrans 配置:/config/midtrans.php
或将其追加到您的 .env
文件中
MIDTRANS_SERVER_KEY="My Midtrans Server Key" MIDTRANS_CLIENT_KEY="My Midtrans Client Kye" MIDTRANS_ENV=development MIDTRANS_SANITIZE=true MIDTRANS_3DS=false
如果您想使用 Facade,请将其添加到您的 /config/app.php
文件中的 Facades 中
'Midtrans' => Firmantr3\Midtrans\Facade\Midtrans::class,
用法
使用提供的 Facade Firmantr3\Midtrans\Facade\Midtrans::snapOrVtDirectMethods()
或 app('midtrans')->snapOrVtDirectMethods()
,但您也可以直接使用官方类。
官方文档可在此处找到 这里
SNAP 示例
获取 Snap 令牌
<?php use Firmantr3\Midtrans\Facade\Midtrans; $params = array( 'transaction_details' => array( 'order_id' => rand(), 'gross_amount' => 10000, ) ); $snapToken = Midtrans::getSnapToken($params);
Snap 重定向
<?php use Firmantr3\Midtrans\Facade\Midtrans; // somewhere in your controller $params = array( 'transaction_details' => array( 'order_id' => rand(), 'gross_amount' => 10000, ) ); try { // Get Snap Payment Page URL $paymentRedirectUrl = Midtrans::createTransaction($params)->redirect_url; // Redirect to Snap Payment Page return redirect($paymentRedirectUrl); } catch (Exception $e) { echo $e->getMessage(); }
核心 API (VT-Direct)
获取前端客户端密钥
<?php use Firmantr3\Midtrans\Facade\Midtrans; $clientKey = Midtrans::clientKey();
后端完整示例
<?php use Firmantr3\Midtrans\Facade\Midtrans; // somewhere in your controller // Populate items $items = array( array( 'id' => 'item1', 'price' => 100000, 'quantity' => 1, 'name' => 'Adidas f50' ), array( 'id' => 'item2', 'price' => 50000, 'quantity' => 2, 'name' => 'Nike N90' ) ); // Populate customer's billing address $billing_address = array( 'first_name' => "Andri", 'last_name' => "Setiawan", 'address' => "Karet Belakang 15A, Setiabudi.", 'city' => "Jakarta", 'postal_code' => "51161", 'phone' => "081322311801", 'country_code' => 'IDN' ); // Populate customer's shipping address $shipping_address = array( 'first_name' => "John", 'last_name' => "Watson", 'address' => "Bakerstreet 221B.", 'city' => "Jakarta", 'postal_code' => "51162", 'phone' => "081322311801", 'country_code' => 'IDN' ); // Populate customer's info $customer_details = array( 'first_name' => "Andri", 'last_name' => "Setiawan", 'email' => "test@test.com", 'phone' => "081322311801", 'billing_address' => $billing_address, 'shipping_address' => $shipping_address ); // Create transaction summary $transaction_details = array( 'order_id' => time(), 'gross_amount' => 200000 ); // Token ID from checkout page $token_id = app('request')->token_id; // Transaction data to be sent $transaction_data = array( 'payment_type' => 'credit_card', 'credit_card' => array( 'token_id' => $token_id, 'authentication'=> true, // 'bank' => 'bni', // optional to set acquiring bank // 'save_token_id' => true // optional for one/two clicks feature ), 'transaction_details' => $transaction_details, 'item_details' => $items, 'customer_details' => $customer_details ); // do charge $response = Midtrans::charge($transaction_data); // Success if($response->transaction_status == 'capture') { echo "<p>Transaksi berhasil.</p>"; echo "<p>Status transaksi untuk order id $response->order_id: " . "$response->transaction_status</p>"; echo "<h3>Detail transaksi:</h3>"; echo "<pre>"; var_dump($response); echo "</pre>"; } // Deny else if($response->transaction_status == 'deny') { echo "<p>Transaksi ditolak.</p>"; echo "<p>Status transaksi untuk order id .$response->order_id: " . "$response->transaction_status</p>"; echo "<h3>Detail transaksi:</h3>"; echo "<pre>"; var_dump($response); echo "</pre>"; } // Challenge else if($response->transaction_status == 'challenge') { echo "<p>Transaksi challenge.</p>"; echo "<p>Status transaksi untuk order id $response->order_id: " . "$response->transaction_status</p>"; echo "<h3>Detail transaksi:</h3>"; echo "<pre>"; var_dump($response); echo "</pre>"; } // Error else { echo "<p>Terjadi kesalahan pada data transaksi yang dikirim.</p>"; echo "<p>Status message: [$response->status_code] " . "$response->status_message</p>"; echo "<pre>"; var_dump($response); echo "</pre>"; }
处理传入通知(Web Hook)
为处理来自 Midtrans 的传入通知更新设置您自己的路由和控制器,然后
<?php use Firmantr3\Midtrans\Facade\Midtrans; // somewhere in your controller $notification = Midtrans::notification(); /** * $notificationArray = $notification->toArray(); * $notificationObject = $notification->toObject(); **/ $transaction = $notification->transaction_status; $fraud = $notification->fraud_status; error_log("Order ID $notification->order_id: "."transaction status = $transaction, fraud staus = $fraud"); if ($transaction == 'capture') { if ($fraud == 'challenge') { // TODO Set payment status in merchant's database to 'challenge' } else if ($fraud == 'accept') { // TODO Set payment status in merchant's database to 'success' } } else if ($transaction == 'cancel') { if ($fraud == 'challenge') { // TODO Set payment status in merchant's database to 'failure' } else if ($fraud == 'accept') { // TODO Set payment status in merchant's database to 'failure' } } else if ($transaction == 'deny') { // TODO Set payment status in merchant's database to 'failure' }
处理交易
获取交易状态
<?php use Firmantr3\Midtrans\Facade\Midtrans; // somewhere in your controller $status = Midtrans::status($orderId); var_dump($status);
批准交易
如果交易 fraud_status == CHALLENGE,您可以从商家仪表板或 API 中批准交易
<?php use Firmantr3\Midtrans\Facade\Midtrans; // somewhere in your controller $approve = Midtrans::approve($orderId); var_dump($approve);
取消交易
您可以在 fraud_status == CHALLENGE
时取消交易,或使用信用卡交易 transaction_status == CAPTURE
(在它成为 SETTLEMENT 之前)
<?php use Firmantr3\Midtrans\Facade\Midtrans; // somewhere in your controller $cancel = Midtrans::cancel($orderId); var_dump($cancel);
过期交易
您可以在 transaction_status == PENDING
时过期交易(在它成为 SETTLEMENT 或 EXPIRE 之前)
<?php use Firmantr3\Midtrans\Facade\Midtrans; // somewhere in your controller $cancel = Midtrans::cancel($orderId); var_dump($cancel);
VT 代表什么
如果您像我一样好奇 VT 是什么,答案是:Midtrans 的前身为 Veritrans ;)
测试
Mocking Midtrans 示例
<?php use Firmantr3\Midtrans\Facade\Midtrans; Midtrans::shouldReceive('getSnapToken') ->once() ->with(['parameters']) ->andReturn('My Token'); $myToken = Midtrans::getSnapToken(['parameters'])); // returns "My Token"
官方 Laravel 文档: https://laravel.net.cn/docs/5.8/mocking#mocking-facades
更好的自动完成
如果您需要更好的 IDE Facade 自动完成,您可以通过 Barry 安装此良好的包: Laravel IDE Helper Generator
运行测试
vendor/bin/phpunit