Stripe & Laravel: Xây Dựng Cổng Thanh Toán Mạnh Mẽ
Lavarel

Stripe & Laravel: Xây Dựng Cổng Thanh Toán Mạnh Mẽ

Author

Admin System

@root

Ngày xuất bản

20 Mar, 2026

Lượt xem

2 Lượt

Stripe_Laravel

Chào các bạn, tôi là Creyt đây! Hôm nay chúng ta sẽ cùng nhau mổ xẻ một chủ đề 'nóng' mà bất cứ ai làm web cũng cần phải biết: Tích hợp Stripe vào Laravel. Nghe có vẻ phức tạp như giải mã công thức bí mật của vũ trụ, nhưng tin tôi đi, với Laravel và Stripe, mọi thứ lại đơn giản như pha một ly cà phê vậy.

1. Stripe & Laravel: Cặp Đôi Hoàn Hảo cho Tài Chính Số

Bạn cứ hình dung thế này: Laravel chính là bộ não của ứng dụng web của bạn. Nó thông minh, có cấu trúc, và biết cách tổ chức mọi thứ một cách khoa học. Còn Stripe? À, Stripe chính là hệ thống ngân hàng riêng của bạn, một người gác cổng tài chính cực kỳ uy tín và bảo mật, chuyên lo việc thu chi, chuyển khoản, và đảm bảo tiền bạc của bạn luôn an toàn.

Vậy tại sao chúng ta lại muốn ghép đôi bộ não thông minh này với người gác cổng tài chính kia? Đơn giản thôi: để ứng dụng của bạn có thể tự động hóa mọi giao dịch tiền bạc! Từ việc thu phí dịch vụ hàng tháng (subscription), bán hàng một lần, cho đến xử lý hoàn tiền – tất cả đều diễn ra mượt mà, nhanh chóng, và không cần bạn phải 'đếm tiền' bằng tay.

2. Giải Phẫu "Stripe_Laravel": Cashier và Sức Mạnh Tiềm Ẩn

Khi nói đến việc tích hợp Stripe vào Laravel, có hai cách chính:

  • Dùng Stripe PHP Library trực tiếp: Cách này giống như bạn tự tay xây từng viên gạch một. Nó linh hoạt tuyệt đối, cho phép bạn kiểm soát mọi ngóc ngách của Stripe API. Phù hợp cho các giao dịch phức tạp, một lần hoặc những thứ Cashier không hỗ trợ.
  • Dùng Laravel Cashier: Đây mới là 'ngôi sao' của buổi hôm nay! Cashier là một gói (package) chính thức của Laravel, được thiết kế đặc biệt để đơn giản hóa việc quản lý các gói đăng ký (subscription billing) với Stripe. Nó giống như một 'người quản lý tài chính' chuyên nghiệp, lo liệu mọi thứ từ việc tạo đăng ký, quản lý hóa đơn, gia hạn, cho đến xử lý hoàn tiền, mà bạn không cần phải viết quá nhiều code. Cashier giúp bạn tập trung vào logic kinh doanh thay vì đau đầu với các chi tiết nhỏ của Stripe API.

Khi nào dùng Cashier? Khi bạn có các dịch vụ theo gói đăng ký, thành viên VIP, hoặc bất kỳ mô hình kinh doanh nào cần thu phí định kỳ. Nó sẽ tiết kiệm cho bạn cả tấn thời gian và công sức.

Illustration

3. Bắt Tay Vào Việc: Tích Hợp Stripe với Laravel (Có Code!)

Nào, hãy cùng nhau 'xắn tay áo' và biến lý thuyết thành hành động. Tôi sẽ hướng dẫn bạn các bước cơ bản để tích hợp Cashier cho một hệ thống đăng ký (subscription).

Bước 1: Cài đặt và Cấu hình Cashier

Đầu tiên, chúng ta cần cài đặt Cashier và cấu hình nó cho ứng dụng Laravel của mình.

composer require laravel/cashier

Sau đó, bạn cần chạy migration để Cashier tạo các bảng cần thiết trong database của bạn (như subscriptions, billing_items, v.v.).

php artisan migrate

Tiếp theo, thêm Billable trait vào User model của bạn. Trait này sẽ cung cấp cho model của bạn các phương thức cần thiết để tương tác với Cashier/Stripe.

// app/Models/User.php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Cashier\Billable; // <-- Thêm dòng này

class User extends Authenticatable
{
    use HasFactory, Notifiable, Billable; // <-- Thêm Billable ở đây

    // ... các thuộc tính và phương thức khác
}

Cuối cùng, cấu hình khóa API của Stripe trong file .env của bạn. Bạn sẽ tìm thấy các khóa này trong Dashboard của Stripe (Developer -> API keys).

STRIPE_KEY=pk_test_YOUR_STRIPE_PUBLIC_KEY
STRIPE_SECRET=sk_test_YOUR_STRIPE_SECRET_KEY
STRIPE_WEBHOOK_SECRET=whsec_YOUR_STRIPE_WEBHOOK_SECRET
STRIPE_CURRENCY=usd # Hoặc vnd nếu bạn muốn

Bước 2: Tạo Form Thanh Toán An Toàn (Client-side với Stripe Elements)

Để thu thập thông tin thẻ tín dụng một cách an toàn, chúng ta sẽ sử dụng Stripe Elements. Nó giúp bạn tạo một UI đẹp mắt và đảm bảo dữ liệu thẻ không bao giờ chạm vào server của bạn.

Thêm Stripe.js vào file layout của bạn (thường là resources/views/layouts/app.blade.php hoặc tương tự):

<head>
    <!-- Các thẻ head khác -->
    <script src="https://js.stripe.com/v3/"></script>
</head>

Sau đó, tạo một form thanh toán đơn giản. Ví dụ, resources/views/billing.blade.php:

<form id="payment-form" action="/subscribe" method="POST">
    @csrf
    <div id="card-element">
        <!-- Stripe Elements sẽ tạo các trường nhập thẻ ở đây -->
    </div>
    <button id="card-button" data-secret="{{ $intent->client_secret ?? '' }}">
        Đăng ký
    </button>
    <div id="card-errors" role="alert"></div>
</form>

<script>
    const stripe = Stripe('{{ config('cashier.key') }}'); // Khóa Public Key
    const elements = stripe.elements();
    const cardElement = elements.create('card');
    cardElement.mount('#card-element');

    const form = document.getElementById('payment-form');
    const cardButton = document.getElementById('card-button');
    const clientSecret = cardButton.dataset.secret;

    form.addEventListener('submit', async (e) => {
        e.preventDefault();
        cardButton.disabled = true;

        const { setupIntent, error } = await stripe.confirmCardSetup(
            clientSecret, {
                payment_method: {
                    card: cardElement,
                    billing_details: { name: '{{ Auth::user()->name }}' }
                }
            }
        );

        if (error) {
            const displayError = document.getElementById('card-errors');
            displayError.textContent = error.message;
            cardButton.disabled = false;
        } else {
            // Gửi payment_method_id về server để tạo đăng ký
            let token = document.createElement('input');
            token.setAttribute('type', 'hidden');
            token.setAttribute('name', 'payment_method');
            token.setAttribute('value', setupIntent.payment_method);
            form.appendChild(token);

            form.submit();
        }
    });
</script>

Lưu ý: $intent->client_secret này được lấy từ một SetupIntent mà bạn tạo ở backend để chuẩn bị cho việc thu thập thông tin thanh toán. Bạn có thể tạo nó trong controller khi hiển thị form.

// Trong controller khi hiển thị view billing.blade.php
public function showBillingForm()
{
    $user = Auth::user();
    $intent = $user->createSetupIntent();

    return view('billing', compact('intent'));
}

Bước 3: Xử Lý Giao Dịch Ở Backend (Server-side với Cashier/Stripe)

Sau khi người dùng gửi thông tin payment_method_id về server, chúng ta sẽ dùng Cashier để tạo đăng ký.

Gợi Ý Đọc Tiếp
Hướng dẫn Service_Container - Lavarel

6 Lượt xem

Ví dụ: Tạo gói đăng ký (subscription) với Cashier.

Giả sử bạn có một gói premium được định nghĩa trong Stripe.

// app/Http/Controllers/SubscriptionController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class SubscriptionController extends Controller
{
    public function store(Request $request)
    {
        $user = Auth::user();

        try {
            // Cập nhật phương thức thanh toán mặc định cho người dùng
            $user->updateDefaultPaymentMethod($request->payment_method);

            // Tạo đăng ký mới cho gói 'premium'
            $user->newSubscription('default', 'price_premium_monthly_id') // 'default' là tên gói đăng ký nội bộ, 'price_...' là ID giá từ Stripe
                 ->create($request->payment_method);

            return redirect('/dashboard')->with('success', 'Bạn đã đăng ký gói Premium thành công!');

        } catch (\Exception $e) {
            return back()->withErrors(['stripe_error' => $e->getMessage()]);
        }
    }
}

Đừng quên định tuyến cho nó trong routes/web.php:

Route::post('/subscribe', [SubscriptionController::class, 'store'])->middleware('auth');
Route::get('/billing', [SubscriptionController::class, 'showBillingForm'])->middleware('auth');

Ví dụ: Thanh toán một lần (dùng Stripe API trực tiếp).

Nếu bạn chỉ muốn thực hiện một giao dịch một lần (ví dụ: bán một sản phẩm), bạn có thể dùng Stripe API trực tiếp.

// app/Http/Controllers/PaymentController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Stripe\Stripe; // <-- Nhớ import Stripe

class PaymentController extends Controller
{
    public function charge(Request $request)
    {
        Stripe::setApiKey(config('cashier.secret')); // Lấy Secret Key từ config

        try {
            $charge = \Stripe\Charge::create([
                'amount' => 1000, // 10.00 USD (Stripe tính bằng cent)
                'currency' => 'usd',
                'source' => $request->stripeToken, // Token từ Stripe Checkout hoặc Elements
                'description' => 'Thanh toán cho sản phẩm X',
            ]);

            // Xử lý thành công
            return redirect('/success')->with('success', 'Thanh toán thành công!');

        } catch (\Stripe\Exception\CardException $e) {
            // Lỗi thẻ
            return back()->withErrors(['stripe_error' => $e->getMessage()]);
        } catch (\Exception $e) {
            // Các lỗi khác
            return back()->withErrors(['error' => 'Đã xảy ra lỗi: ' . $e->getMessage()]);
        }
    }
}

Bước 4: Lắng Nghe Sự Kiện với Webhooks (Người Đưa Tin Trung Thành)

Webhooks là 'tai mắt' của ứng dụng bạn. Stripe sẽ gửi thông báo đến URL webhook của bạn mỗi khi có một sự kiện quan trọng xảy ra (ví dụ: thanh toán thành công, đăng ký bị hủy, thẻ hết hạn...). Việc này cực kỳ quan trọng để giữ cho dữ liệu của bạn luôn đồng bộ và xử lý các tình huống bất đồng bộ.

  • Cấu hình trong Stripe: Trong Dashboard của Stripe, vào Developers -> Webhooks, thêm một endpoint mới và trỏ đến URL của bạn (ví dụ: https://your-domain.com/stripe/webhook). Đừng quên chọn các sự kiện bạn muốn lắng nghe.

  • Cấu hình trong Laravel: Cashier đã cung cấp một route và controller mặc định để xử lý webhooks. Bạn chỉ cần thêm nó vào routes/web.php (hoặc routes/api.php):

    Route::post('/stripe/webhook', '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook');
    

    Bạn cũng cần thêm STRIPE_WEBHOOK_SECRET vào .env để Cashier xác minh tính hợp lệ của webhook.

    Cashier sẽ tự động xử lý nhiều sự kiện quan trọng. Nếu bạn muốn xử lý các sự kiện tùy chỉnh, bạn có thể tạo một class listener hoặc ghi đè phương thức handleWebhook trong controller của riêng bạn.

4. Mẹo Từ Thầy Creyt: "Đừng Để Tiền Rơi!" (Best Practices)

Như một giảng viên lập trình lão luyện, tôi luôn có vài mẹo vặt bỏ túi để bạn không 'làm rơi tiền' hay gặp rắc rối:

  • HTTPS là BẮT BUỘC: Đừng bao giờ xử lý thanh toán trên HTTP. Luôn luôn dùng HTTPS để mã hóa dữ liệu. Stripe sẽ 'nhăn mặt' và không cho bạn làm đâu!
  • Không lưu thông tin thẻ: Tuyệt đối không lưu trữ thông tin thẻ tín dụng nhạy cảm trên server của bạn. Hãy để Stripe Elements và Stripe lo việc đó. Đây là quy tắc vàng của bảo mật PCI DSS.
  • Dùng Webhooks như một người bạn thân: Đừng cố gắng 'đoán' trạng thái thanh toán bằng cách gọi API liên tục. Webhooks là cơ chế chính xác và đáng tin cậy nhất để cập nhật trạng thái giao dịch. Hãy lắng nghe chúng!
  • Kiểm thử cẩn thận: Stripe cung cấp chế độ test (với các khóa API pk_test_sk_test_) và các thẻ thử nghiệm đặc biệt. Hãy dùng chúng để kiểm tra mọi kịch bản trước khi đẩy lên môi trường thật. Đừng bao giờ thử nghiệm với tiền thật!
  • Xử lý lỗi một cách duyên dáng: Luôn bắt lỗi (try-catch) và cung cấp thông báo rõ ràng, thân thiện cho người dùng khi có sự cố xảy ra. Không ai muốn thấy một trang trắng với thông báo lỗi 'khó hiểu' cả.
  • Biến môi trường cho API Keys: Luôn đặt các khóa API của Stripe vào file .env và không bao giờ commit chúng lên Git. Bảo mật là trên hết!

5. Ứng Dụng Thực Tế: "Ai Đã Dùng Rồi?"

Stripe và Laravel là bộ đôi được hàng ngàn công ty và dự án lớn nhỏ tin dùng. Bạn có thể thấy chúng trong:

  • Các nền tảng SaaS (Software as a Service): Như Slack, Notion, Zoom, hay hàng ngàn ứng dụng quản lý dự án, CRM khác. Họ dùng Stripe Cashier để quản lý các gói đăng ký hàng tháng/năm.
  • Các trang thương mại điện tử (E-commerce): Từ các cửa hàng nhỏ đến các sàn lớn, Stripe giúp xử lý thanh toán một lần cho sản phẩm.
  • Các trang thành viên/nội dung trả phí: Các website cung cấp nội dung độc quyền, khóa học online (Udemy, Coursera), hoặc các cộng đồng có phí thành viên đều có thể dùng Stripe để quản lý việc thu phí.

Vậy đó, các bạn! Tích hợp Stripe vào Laravel không hề đáng sợ như bạn nghĩ, đặc biệt là với sự trợ giúp đắc lực của Laravel Cashier. Hãy bắt đầu xây dựng hệ thống thanh toán của riêng bạn và biến ứng dụng của mình thành một cỗ máy kiếm tiền tự động nhé!

Thuộc Series: Lavarel

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!