liharsw/midtrans-php

Midtrans支付API的PHP包装器。

2.5.2 2022-10-19 15:06 UTC

This package is auto-updated.

Last update: 2024-09-19 19:48:10 UTC


README

PHP version Latest Stable Version Monthly Downloads Total Downloads

Midtrans ❤️ PHP!

这是Midtrans支付API的官方PHP包装器/库,兼容Composer。访问https://midtrans.com获取更多产品信息,并在http://docs.midtrans.com查看更多技术细节。

1. 安装

1.a Composer安装

如果您使用Composer,您可以通过composer CLI进行安装

composer require liharsw/midtrans-php

或者

将此require行添加到您的composer.json文件中

{
    "require": {
        "midtrans/midtrans-php": "2.*"
    }
}

然后在您的终端上运行composer install

注意:如果您使用Laravel框架,在某些情况下,您还需要运行composer dumpautoload

/Midtrans将随后在您的Laravel项目中可用(自动加载)。

1.b 手动安装

如果您不使用Composer,您可以克隆或下载此存储库。

然后您应该在您的代码中引入autoload Midtrans.php文件。

require_once dirname(__FILE__) . '/pathofproject/Midtrans.php';

// my code goes here

2. 使用方法

2.1 通用设置

// Set your Merchant Server Key
\Midtrans\Config::$serverKey = '<your server key>';
// Set to Development/Sandbox Environment (default). Set to true for Production Environment (accept real transaction).
\Midtrans\Config::$isProduction = false;
// Set sanitization on (default)
\Midtrans\Config::$isSanitized = true;
// Set 3DS transaction for credit card to true
\Midtrans\Config::$is3ds = true;

覆盖通知URL

您可以选择在每个交易中更改或添加自定义通知URL。这可以通过在请求中加入额外的HTTP头部来实现。

// Add new notification url(s) alongside the settings on Midtrans Dashboard Portal (MAP)
Config::$appendNotifUrl = "https://example.com/test1,https://example.com/test2";
// Use new notification url(s) disregarding the settings on Midtrans Dashboard Portal (MAP)
Config::$overrideNotifUrl = "https://example.com/test1";

更多详情

注意:当同时使用appendNotifUrloverrideNotifUrl时,则只使用overrideNotifUrl

这两个头部只能接收最多3个URL

Idempotency-Key

您可以在交易中添加idempotency key。这可以通过在请求中加入额外的HTTP头部来实现。这是一个唯一的值,用于API请求的头部。Midtrans API接受Idempotency-Key头部以安全地处理重试请求,避免执行相同的操作两次。这在商户因为网络问题或其他意外错误没有收到响应时非常有用。

Config::$paymentIdempotencyKey = "Unique-ID";

更多详情

2.2 选择产品/方法

我们有3种不同的支付产品可供使用

选择最适合您独特需求的一个。

2.2.a Snap

您可以在这里看到Snap示例。

获取Snap令牌

$params = array(
    'transaction_details' => array(
        'order_id' => rand(),
        'gross_amount' => 10000,
    )
);

$snapToken = \Midtrans\Snap::getSnapToken($params);

当客户点击支付按钮时初始化Snap JS

<html>
  <body>
    <button id="pay-button">Pay!</button>
    <pre><div id="result-json">JSON result will appear here after payment:<br></div></pre> 

<!-- TODO: Remove ".sandbox" from script src URL for production environment. Also input your client key in "data-client-key" -->
    <script src="https://app.sandbox.midtrans.com/snap/snap.js" data-client-key="<Set your ClientKey here>"></script>
    <script type="text/javascript">
      document.getElementById('pay-button').onclick = function(){
        // SnapToken acquired from previous step
        snap.pay('<?=$snapToken?>', {
          // Optional
          onSuccess: function(result){
            /* You may add your own js here, this is just example */ document.getElementById('result-json').innerHTML += JSON.stringify(result, null, 2);
          },
          // Optional
          onPending: function(result){
            /* You may add your own js here, this is just example */ document.getElementById('result-json').innerHTML += JSON.stringify(result, null, 2);
          },
          // Optional
          onError: function(result){
            /* You may add your own js here, this is just example */ document.getElementById('result-json').innerHTML += JSON.stringify(result, null, 2);
          }
        });
      };
    </script>
  </body>
</html>

实现通知处理器

请参考本节

2.2.b Snap Redirect

您可以在这里查看一些Snap Redirect的示例。

获取支付页面的重定向URL

$params = array(
    'transaction_details' => array(
        'order_id' => rand(),
        'gross_amount' => 10000,
    )
);

try {
  // Get Snap Payment Page URL
  $paymentUrl = \Midtrans\Snap::createTransaction($params)->redirect_url;
  
  // Redirect to Snap Payment Page
  header('Location: ' . $paymentUrl);
}
catch (Exception $e) {
  echo $e->getMessage();
}

实现通知处理器

请参考本节

2.2.c 核心API (VT-Direct)

您可以在这里查看一些核心API的示例。

设置客户端密钥

MidtransNew3ds.clientKey = "<your client key>";

结账页面

请参阅此文件

结账流程

1. 创建交易详情
$transaction_details = array(
  'order_id'    => time(),
  'gross_amount'  => 200000
);
2. 创建商品详情、账单地址、配送地址和客户详情(可选)
// 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
);
3. 从结账页面获取Token ID
// Token ID from checkout page
$token_id = $_POST['token_id'];
4. 创建交易数据
// 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
);
5. 充值
$response = \Midtrans\CoreApi::charge($transaction_data);
6. 信用卡3DS身份验证

信用卡充值结果可能包含用于3DS身份验证的redirect_url。3DS身份验证应在前端处理,请参阅API文档

有关信用卡3DS交易的完整示例,请参阅

7. 处理交易状态
// 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>";
}

8. 实现通知处理程序

请参考本节

2.3 处理HTTP通知

创建单独的Web端点(通知URL)以接收HTTP POST通知回调/钩子。每当交易状态改变时,都会发送HTTP通知。示例也在这里提供

$notif = new \Midtrans\Notification();

$transaction = $notif->transaction_status;
$fraud = $notif->fraud_status;

error_log("Order ID $notif->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'
}

2.4 处理交易

获取交易状态

$status = \Midtrans\Transaction::status($orderId);
var_dump($status);

批准交易

如果交易欺诈状态==挑战,您可以从商户仪表板或API批准交易

$approve = \Midtrans\Transaction::approve($orderId);
var_dump($approve);

取消交易

您可以通过fraud_status == CHALLENGE取消交易,或通过transaction_status == CAPTURE(在它成为SETTLEMENT之前)取消信用卡交易

$cancel = \Midtrans\Transaction::cancel($orderId);
var_dump($cancel);

过期交易

您可以通过transaction_status == PENDING(在它成为SETTLEMENT或EXPIRE之前)取消交易

$cancel = \Midtrans\Transaction::cancel($orderId);
var_dump($cancel);

退款交易

退款交易(并非所有支付渠道都允许通过API进行退款)您可以通过transaction_status == settlement退款交易

$params = array(
    'refund_key' => 'order1-ref1',
    'amount' => 10000,
    'reason' => 'Item out of stock'
);
$refund = \Midtrans\Transaction::refund($orderId, $params);
var_dump($refund);

直接退款交易

通过直接退款API退款交易您可以通过transaction_status == settlement退款交易

$params = array(
    'refund_key' => 'order1-ref1',
    'amount' => 10000,
    'reason' => 'Item out of stock'
);
$direct_refund = \Midtrans\Transaction::refundDirect($orderId, $params);
var_dump($direct_refund);

单元测试

集成测试(沙盒真实交易)

请将phpunit.xml中的服务器密钥和客户端密钥更改为您自己的。

所有测试

vendor/bin/phpunit

特定测试

vendor/bin/phpunit tests/integration/CoreApiIntegrationTest.php

贡献

开发电子商务插件

在开发新插件时,必须注意以下几项指南。

  1. 处理除IDR以外的货币。 Midtrans v1v2 目前只接受印尼盾的支付。作为一个推论,服务器上有验证来检查商品价格是否为整数。尽管您可能想四舍五入价格,但请不要这样做!当您的系统使用IDR以外的货币时,请相应地将其转换为IDR,然后在四舍五入价格。

  2. 考虑使用自动清理功能。