How to integrate Indonesia Payment Service with PHP?

使用PHP集成印尼支付服务指南

在印尼市场,有多种流行的本地支付方式可供选择。以下是使用PHP集成这些服务的步骤和注意事项:

主要印尼支付选项

  1. OVO
  2. DANA
  3. LinkAja
  4. GoPay (现为GoTo Financial)
  5. bank transfer (Mandiri, BCA, BRI等)
  6. Convenience Store Payments (Alfamart, Indomaret)

通用集成步骤

1. 选择支付网关提供商

考虑以下服务商:

  • Midtrans (最受欢迎)
  • Xendit
  • Doku
  • iPay88

2. PHP集成示例(Midtrans为例)

// 安装Midtrans PHP库: composer require midtrans/midtrans-php

require_once(dirname(__FILE__) . '/vendor/autoload.php');

// Set your Merchant Server Key
\Midtrans\Config::$serverKey = 'YOUR_SERVER_KEY';
// Set to Development/Sandbox Environment (default). Set to true for Production Environment.
\Midtrans\Config::$isProduction = false;
// Enable sanitization
\Midtrans\Config::$isSanitized = true;
// Enable idempotency-key to prevent duplicate transaction
\Midtrans\Config::$isIdempotencyKeyEnabled = true;

$params = [
'transaction_details' => [
'order_id' => rand(),
'gross_amount' => 100000,
],
'payment_type' => 'gopay', // or other payment methods like bank_transfer, ewallet etc.
'customer_details' => [
'first_name' => "John",
'last_name' => "Doe",
'email' => "[email protected]",
// Indonesian phone number format required (+62)
// Example: +6281234567890 - remove the first zero from mobile number and add +62 prefix
// Important for OTP verification on some payment methods like GoPay/DANA/etc.
//

API调用示例(Xendit)

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "https://api.xendit.co/v2/invoices");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);

curl_setopt($ch,CURLOPT_POSTFIELDS,'{
"external_id": "demo_147580196270",
"amount":10000,
"description":"Invoice Demo #123",
/* For Indonesian payments */
/* For OVO */
/*"payer_email":"[email protected]",*/

});

/* Add headers */

/* Execute request */

/* Handle response */

Webhook处理(以Xendit为例)


if($_SERVER['REQUEST_METHOD'] === POST){

$callbackToken= $_SERVER['HTTP_X_CALLBACK_TOKEN'];
if ($callbackToken !== YOUR_CALLBACK_TOKEN){
http_response_code(403); exit(); }

$json= file_get_contents('php://input');
$data= json_decode($json);

switch ($data->status) {
case PAID: processPaidInvoice(); break;
case EXPIRED: handleExpiredPayment(); break;
}

} else { http_response_code(405); }

Laravel Package Recommendations

对于Laravel开发者:

composer require veritrans/veritrans-laravel # MidTrans官方包   
composer require xendit/xendit-laravel # XendIT官方包

或者通用的Guzzle HTTP客户端实现。

希望这个指南对您有所帮助!根据您的具体业务需求选择合适的支付方式和API提供商。

继续PHP集成印尼支付服务指南

3. 处理不同支付方式的特殊要求

OVO支付集成

// Midtrans中的OVO设置示例
$params = [
'payment_type' => 'ewallet',
'ewallet' => [
'channel_code' => 'ovo', // OVO的渠道代码
'channel_properties' => [
// 必须使用印尼手机号格式(+628...)
// 注意: +62替换0,如08123456789 → +628123456789
'mobile_number' => '+6281234567890'
]
],
// ...其他交易参数...
];

try {
$response = \Midtrans\CoreApi::charge($params);
} catch (\Exception $e) {
echo $e->getMessage();
}

DANA支付集成注意事项

  1. 需要商户注册:需先在DANA商户平台注册获取API密钥
  2. 回调验证:必须实现DANA的回调URL以验证付款状态
// DANA回调处理示例(简化版)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$rawData = file_get_contents('php://input');

if (!empty($rawData)) {
try {
require_once('dana_sdk.php'); // DANA官方SDK

$danaClient = new DanaClient([
'clientId' => YOUR_CLIENT_ID,
'secretKey' => YOUR_SECRET_KEY,
// ...
]);

if ($danaClient->validateCallback($rawData)) {
http_response_code(200);

/*
* 业务逻辑:
* :: - Update order status to paid
* - 发货或提供服务等后续操作
*/

} else { throw new Exception("Invalid callback signature"); }

} catch (Exception $e) { error_log($e); http_response_code(400); }
}
}

GoPay/GoTo Financial的特殊配置

由于GoPay现在属于GoTo生态系统:

  1. sandbox testing:

    \Midtrans\Config::$isProduction = false;   
    \Midtrans\Config::$serverKey = "SB-Mid-server-...";
  2. 生产环境:

    \Midtrans\Config::$isProduction = true;    
    /* GoPay可能需要额外资质审核 */
  3. 用户手机号格式(重要): PHP预处理函数示例:

function formatIndonesianPhone(string $phone): string     
{
/*
* Convert local formats like:
* - "08123456789" → "+628123456789"
*/
return preg_replace('/^0/', '+62', ltrim($phone));
}

$customerPhone= formatIndonesianPhone($_POST['phone']);

/* Then use in payment params */
$params['customer_details']['phone']= validatedNumber;

Alfamart/Indomaret便利店支付

适用于无银行账户的用户群体。核心流程是生成付款码→用户线下扫码完成交易。

// Midtrans便利店支付请求示例片段    

$convenienceStoreParams= [
"store"=> "alfamart", // or indomaret
];

$response= \Midtrans\CoreApi::charge([
...常规订单参数...,
"payment_type"=>"cstore",
"cstore"=> convenienceStoreParams,
]);

/* Response将包含供打印的付款码和过期时间*/
echo json_encode([
payment_code=> response->payment_code,
]);

接下来您可能想了解:

  • Webhook安全验证的最佳实践(签名校验等)
  • Laravel特定框架下的优雅实现方式(Service Provider设计)
  • Rupiah货币格式化与小数位处理的PHP技巧