技術 6 分鐘閱讀

Laravel + 綠界金流串接全攻略:信用卡與超商代碼

Laravel + 綠界金流串接全攻略:信用卡與超商代碼

前言

根據我的經驗,金流串接是台灣接案最常遇到的需求之一。這篇文章以綠界 ECPay 為例,分享信用卡和超商代碼兩種付款方式的串接方式。

事前準備

  1. 註冊綠界測試帳號
  2. 取得測試用的 MerchantID、HashKey、HashIV
  3. 安裝套件
composer require ecpay/sdk

環境設定

ECPAY_MERCHANT_ID=3002607
ECPAY_HASH_KEY=pwFHCqoQZGmho4w6
ECPAY_HASH_IV=EkRm7iFT261dpevs
ECPAY_URL=https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5
// config/ecpay.php
return [
    'merchant_id' => env('ECPAY_MERCHANT_ID'),
    'hash_key' => env('ECPAY_HASH_KEY'),
    'hash_iv' => env('ECPAY_HASH_IV'),
    'url' => env('ECPAY_URL'),
];

建立訂單

資料庫設計

Schema::create('orders', function (Blueprint $table) {
    $table->id();
    $table->string('order_no')->unique();
    $table->string('customer_name');
    $table->string('customer_email');
    $table->integer('total_amount');
    $table->string('payment_method'); // credit, cvs
    $table->string('payment_status')->default('pending');
    $table->string('trade_no')->nullable();
    $table->timestamps();
});

Controller

class PaymentController extends Controller
{
    public function checkout(Request $request)
    {
        $order = Order::create([
            'order_no' => 'OD' . now()->format('YmdHis') . rand(100, 999),
            'customer_name' => $request->name,
            'customer_email' => $request->email,
            'total_amount' => $request->amount,
            'payment_method' => $request->payment_method,
        ]);

        return $this->createEcpayForm($order);
    }

    private function createEcpayForm(Order $order)
    {
        $ecpay = new ECPayAllInOne();
        $ecpay->ServiceURL = config('ecpay.url');
        $ecpay->MerchantID = config('ecpay.merchant_id');
        $ecpay->HashKey = config('ecpay.hash_key');
        $ecpay->HashIV = config('ecpay.hash_iv');

        $ecpay->Send['MerchantTradeNo'] = $order->order_no;
        $ecpay->Send['MerchantTradeDate'] = now()->format('Y/m/d H:i:s');
        $ecpay->Send['TotalAmount'] = $order->total_amount;
        $ecpay->Send['TradeDesc'] = '商品訂單';
        $ecpay->Send['ChoosePayment'] = $order->payment_method === 'credit'
            ? ECPayPaymentMethod::Credit
            : ECPayPaymentMethod::CVS;
        $ecpay->Send['ReturnURL'] = route('payment.callback');
        $ecpay->Send['ClientBackURL'] = route('payment.result');

        array_push($ecpay->Send['Items'], [
            'Name' => '商品訂單',
            'Price' => $order->total_amount,
            'Currency' => 'NTD',
            'Quantity' => 1,
        ]);

        return $ecpay->CheckOutString('前往付款');
    }
}

處理回呼(Callback)

public function callback(Request $request)
{
    $ecpay = new ECPayAllInOne();
    $ecpay->HashKey = config('ecpay.hash_key');
    $ecpay->HashIV = config('ecpay.hash_iv');

    $result = $ecpay->CheckOutFeedback($request->all());

    if (!empty($result)) {
        $order = Order::where('order_no', $result['MerchantTradeNo'])->first();

        if ($order && $result['RtnCode'] === '1') {
            $order->update([
                'payment_status' => 'paid',
                'trade_no' => $result['TradeNo'],
            ]);
        }
    }

    return '1|OK';
}

路由設定

Route::post('/payment/checkout', [PaymentController::class, 'checkout']);
Route::post('/payment/callback', [PaymentController::class, 'callback'])
    ->name('payment.callback')
    ->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class]);
Route::get('/payment/result', [PaymentController::class, 'result'])
    ->name('payment.result');

注意 callback 路由要排除 CSRF 檢查,因為是綠界伺服器打過來的。

上線注意事項

  • 切換正式環境的金鑰和 URL
  • 確認 callback URL 是外網可存取的
  • 做好錯誤處理和日誌記錄

更多關於金流比較可以參考 台灣電子支付完全比較,了解各家的手續費差異。搭配 API 設計 的最佳實踐能讓整體架構更穩健。

如果你需要類似的系統,歡迎聯繫討論。

#Laravel #綠界 #金流串接
Thousand Lab

Thousand Lab