Chuyển đến nội dung chính

Tổng Quan

Thanh toán inline cho phép bạn tạo ra những trải nghiệm thanh toán hoàn toàn tích hợp, hòa quyện một cách liền mạch với trang web hoặc ứng dụng của bạn. Khác với thanh toán overlay, mở dưới dạng modal trên trang của bạn, thanh toán inline nhúng biểu mẫu thanh toán trực tiếp vào bố cục trang của bạn. Sử dụng thanh toán inline, bạn có thể:
  • Tạo ra những trải nghiệm thanh toán hoàn toàn tích hợp với ứng dụng hoặc trang web của bạn
  • Để Dodo Payments an toàn thu thập thông tin khách hàng và thông tin thanh toán trong một khung thanh toán tối ưu
  • Hiển thị các mặt hàng, tổng số và thông tin khác từ Dodo Payments trên trang của bạn
  • Sử dụng các phương thức và sự kiện SDK để xây dựng những trải nghiệm thanh toán nâng cao
Hình ảnh bìa Thanh toán nội tuyến

Cách Hoạt Động

Thanh toán inline hoạt động bằng cách nhúng một khung Dodo Payments an toàn vào trang web hoặc ứng dụng của bạn. Khung thanh toán xử lý việc thu thập thông tin khách hàng và ghi lại chi tiết thanh toán. Trang của bạn hiển thị danh sách mặt hàng, tổng số và tùy chọn để thay đổi những gì có trên thanh toán. SDK cho phép trang của bạn và khung thanh toán tương tác với nhau. Dodo Payments tự động tạo một đăng ký khi một thanh toán hoàn tất, sẵn sàng để bạn cung cấp.
Khung thanh toán nội tuyến xử lý an toàn tất cả thông tin thanh toán nhạy cảm, đảm bảo tuân thủ PCI mà bạn không cần thêm chứng nhận nào nữa.

Điều Gì Tạo Nên Một Thanh Toán Inline Tốt?

Điều quan trọng là khách hàng biết họ đang mua từ ai, họ đang mua gì và họ phải trả bao nhiêu. Để xây dựng một thanh toán inline tuân thủ và tối ưu hóa cho chuyển đổi, việc triển khai của bạn phải bao gồm:
Ví dụ thanh toán nội tuyến với các phần tử bắt buộc được gắn nhãn
  1. Thông tin định kỳ: Nếu là định kỳ, tần suất và tổng số phải trả khi gia hạn. Nếu là dùng thử, thời gian dùng thử kéo dài bao lâu.
  2. Mô tả mặt hàng: Một mô tả về những gì đang được mua.
  3. Tổng giao dịch: Tổng giao dịch, bao gồm tổng phụ, thuế tổng và tổng cộng. Đảm bảo bao gồm cả loại tiền tệ.
  4. Chân trang Dodo Payments: Toàn bộ khung thanh toán inline, bao gồm chân trang thanh toán có thông tin về Dodo Payments, điều khoản bán hàng của chúng tôi và chính sách bảo mật của chúng tôi.
  5. Chính sách hoàn tiền: Một liên kết đến chính sách hoàn tiền của bạn, nếu nó khác với chính sách hoàn tiền tiêu chuẩn của Dodo Payments.
Luôn hiển thị đầy đủ khung thanh toán nội tuyến, bao gồm cả phần chân trang. Loại bỏ hoặc ẩn thông tin pháp lý sẽ vi phạm yêu cầu tuân thủ.

Hành Trình Khách Hàng

Luồng thanh toán được xác định bởi cấu hình phiên thanh toán của bạn. Tùy thuộc vào cách bạn cấu hình phiên thanh toán, khách hàng sẽ trải nghiệm một thanh toán có thể trình bày tất cả thông tin trên một trang duy nhất hoặc qua nhiều bước.
1

Customer opens checkout

Bạn có thể mở thanh toán inline bằng cách truyền các mặt hàng hoặc một giao dịch hiện có. Sử dụng SDK để hiển thị và cập nhật thông tin trên trang, và các phương thức SDK để cập nhật các mặt hàng dựa trên tương tác của khách hàng.Trang thanh toán ban đầu với danh sách mặt hàng và biểu mẫu thanh toán
2

Customer enters their details

Thanh toán inline trước tiên yêu cầu khách hàng nhập địa chỉ email của họ, chọn quốc gia của họ và (nếu cần) nhập mã ZIP hoặc mã bưu chính của họ. Bước này thu thập tất cả thông tin cần thiết để xác định thuế và các tùy chọn thanh toán có sẵn.Bạn có thể tự động điền thông tin khách hàng và trình bày các địa chỉ đã lưu để đơn giản hóa trải nghiệm.
3

Customer selects payment method

Sau khi nhập thông tin của họ, khách hàng sẽ được trình bày các phương thức thanh toán có sẵn và biểu mẫu thanh toán. Các tùy chọn có thể bao gồm thẻ tín dụng hoặc thẻ ghi nợ, PayPal, Apple Pay, Google Pay và các phương thức thanh toán địa phương khác dựa trên vị trí của họ.Hiển thị các phương thức thanh toán đã lưu nếu có để tăng tốc độ thanh toán.Các phương thức thanh toán có sẵn và biểu mẫu chi tiết thẻ
4

Checkout completed

Dodo Payments định tuyến mọi thanh toán đến nhà cung cấp tốt nhất cho giao dịch đó để có cơ hội thành công tốt nhất. Khách hàng sẽ vào một quy trình thành công mà bạn có thể xây dựng.Màn hình thành công với dấu kiểm xác nhận
5

Dodo Payments creates subscription

Dodo Payments tự động tạo một đăng ký cho khách hàng, sẵn sàng để bạn cung cấp. Phương thức thanh toán mà khách hàng đã sử dụng sẽ được lưu giữ để gia hạn hoặc thay đổi đăng ký.Đăng ký đã được tạo với thông báo webhook

Bắt đầu nhanh

Bắt đầu với Dodo Payments Inline Checkout chỉ với vài dòng mã:
import { DodoPayments } from "dodopayments-checkout";

// Initialize the SDK for inline mode
DodoPayments.Initialize({
  mode: "test",
  displayType: "inline",
  onEvent: (event) => {
    console.log("Checkout event:", event);
  },
});

// Open checkout in a specific container
DodoPayments.Checkout.open({
  checkoutUrl: "https://test.dodopayments.com/session/cks_123",
  elementId: "dodo-inline-checkout" // ID of the container element
});
Đảm bảo bạn có một phần tử chứa với id tương ứng trên trang của mình: <div id="dodo-inline-checkout"></div>.

Hướng dẫn tích hợp từng bước

1

Install the SDK

Cài đặt Dodo Payments Checkout SDK:
npm install dodopayments-checkout
2

Initialize the SDK for Inline Display

Khởi tạo SDK và chỉ định displayType: 'inline'. Bạn cũng nên lắng nghe sự kiện checkout.breakdown để cập nhật giao diện người dùng với các tính toán thuế và tổng tiền theo thời gian thực.
import { DodoPayments } from "dodopayments-checkout";

DodoPayments.Initialize({
  mode: "test",
  displayType: "inline",
  onEvent: (event) => {
    if (event.event_type === "checkout.breakdown") {
      const breakdown = event.data?.message;
      // Update your UI with breakdown.subTotal, breakdown.tax, breakdown.total, etc.
    }
  },
});
3

Create a Container Element

Thêm một phần tử vào HTML của bạn nơi khung thanh toán sẽ được chèn vào:
<div id="dodo-inline-checkout"></div>
4

Open the Checkout

Gọi DodoPayments.Checkout.open() với checkoutUrlelementId của phần tử chứa của bạn:
DodoPayments.Checkout.open({
  checkoutUrl: "https://test.dodopayments.com/session/cks_123",
  elementId: "dodo-inline-checkout"
});
5

Test Your Integration

  1. Khởi động máy chủ phát triển của bạn:
npm run dev
  1. Kiểm tra quy trình thanh toán:
    • Nhập email và địa chỉ của bạn trong khung inline.
    • Xác minh rằng tóm tắt đơn hàng tùy chỉnh của bạn cập nhật theo thời gian thực.
    • Kiểm tra quy trình thanh toán bằng cách sử dụng thông tin xác thực thử nghiệm.
    • Xác nhận rằng các chuyển hướng hoạt động chính xác.
Bạn sẽ thấy sự kiện checkout.breakdown được ghi lại trong bảng điều khiển trình duyệt nếu bạn thêm một console log trong callback onEvent.
6

Go Live

Khi bạn đã sẵn sàng cho sản xuất:
  1. Thay đổi chế độ thành 'live':
DodoPayments.Initialize({
  mode: "live",
  displayType: "inline",
  onEvent: (event) => {
    // Handle events
  }
});
  1. Cập nhật các URL thanh toán của bạn để sử dụng các phiên thanh toán trực tiếp từ backend của bạn.
  2. Kiểm tra quy trình hoàn chỉnh trong sản xuất.

Ví dụ hoàn chỉnh về React

Ví dụ này minh họa cách triển khai một tóm tắt đơn hàng tùy chỉnh bên cạnh thanh toán nội tuyến, giữ chúng đồng bộ bằng cách sử dụng sự kiện checkout.breakdown.
"use client";

import { useEffect, useState } from 'react';
import { DodoPayments, CheckoutBreakdownData } from 'dodopayments-checkout';

export default function CheckoutPage() {
  const [breakdown, setBreakdown] = useState<Partial<CheckoutBreakdownData>>({});

  useEffect(() => {
    // 1. Initialize the SDK
    DodoPayments.Initialize({
      mode: 'test',
      displayType: 'inline',
      onEvent: (event) => {
        // 2. Listen for the 'checkout.breakdown' event
        if (event.event_type === "checkout.breakdown") {
          const message = event.data?.message as CheckoutBreakdownData;
          if (message) setBreakdown(message);
        }
      }
    });

    // 3. Open the checkout in the specified container
    DodoPayments.Checkout.open({
      checkoutUrl: 'https://test.dodopayments.com/session/cks_123',
      elementId: 'dodo-inline-checkout'
    });

    return () => DodoPayments.Checkout.close();
  }, []);

  const format = (amt: number | null | undefined, curr: string | null | undefined) => 
    amt != null && curr ? `${curr} ${(amt/100).toFixed(2)}` : '0.00';

  const currency = breakdown.currency ?? breakdown.finalTotalCurrency ?? '';

  return (
    <div className="flex flex-col md:flex-row min-h-screen">
      {/* Left Side - Checkout Form */}
      <div className="w-full md:w-1/2 flex items-center">
        <div id="dodo-inline-checkout" className='w-full' />
      </div>

      {/* Right Side - Custom Order Summary */}
      <div className="w-full md:w-1/2 p-8 bg-gray-50">
        <h2 className="text-2xl font-bold mb-4">Order Summary</h2>
        <div className="space-y-2">
          {breakdown.subTotal && (
            <div className="flex justify-between">
              <span>Subtotal</span>
              <span>{format(breakdown.subTotal, currency)}</span>
            </div>
          )}
          {breakdown.discount && (
            <div className="flex justify-between">
              <span>Discount</span>
              <span>{format(breakdown.discount, currency)}</span>
            </div>
          )}
          {breakdown.tax != null && (
            <div className="flex justify-between">
              <span>Tax</span>
              <span>{format(breakdown.tax, currency)}</span>
            </div>
          )}
          <hr />
          {(breakdown.finalTotal ?? breakdown.total) && (
            <div className="flex justify-between font-bold text-xl">
              <span>Total</span>
              <span>{format(breakdown.finalTotal ?? breakdown.total, breakdown.finalTotalCurrency ?? currency)}</span>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

Tài liệu API

Cấu hình

Tùy chọn khởi tạo

interface InitializeOptions {
  mode: "test" | "live";
  displayType: "inline"; // Required for inline checkout
  onEvent: (event: CheckoutEvent) => void;
}
Tùy chọnLoạiBắt buộcMô tả
mode"test" | "live"Chế độ môi trường.
displayType"inline" | "overlay"Phải được đặt thành "inline" để nhúng thanh toán.
onEventfunctionHàm callback để xử lý sự kiện thanh toán.

Tùy chọn thanh toán

export type FontSize = "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
export type FontWeight = "normal" | "medium" | "bold" | "extraBold";

interface CheckoutOptions {
  checkoutUrl: string;
  elementId: string; // Required for inline checkout
  options?: {
    showTimer?: boolean;
    showSecurityBadge?: boolean;
    manualRedirect?: boolean;
    payButtonText?: string;
    fontSize?: FontSize;
    fontWeight?: FontWeight;
  };
}
Tùy chọnKiểuBắt buộcMô tả
checkoutUrlstringYesURL phiên thanh toán.
elementIdstringYesid của phần tử DOM nơi checkout nên được hiển thị.
options.showTimerbooleanNoHiển thị hoặc ẩn bộ đếm thời gian checkout. Mặc định là true. Khi bị vô hiệu, bạn sẽ nhận được sự kiện checkout.link_expired khi phiên hết hạn.
options.showSecurityBadgebooleanNoHiển thị hoặc ẩn biểu tượng bảo mật. Mặc định là true.
options.manualRedirectbooleanNoKhi được bật, checkout sẽ không tự động chuyển hướng sau khi hoàn thành. Thay vào đó, bạn sẽ nhận được sự kiện checkout.statuscheckout.redirect_requested để xử lý chuyển hướng.
options.payButtonTextstringNoVăn bản tùy chỉnh để hiển thị trên nút thanh toán.
options.fontSizeFontSizeNoKích thước phông chữ toàn cục cho checkout.
options.fontWeightFontWeightNoĐộ đậm phông chữ toàn cục cho checkout.

Phương thức

Mở thanh toán

Mở khung thanh toán trong phần tử được chỉ định.
DodoPayments.Checkout.open({
  checkoutUrl: "https://test.dodopayments.com/session/cks_123",
  elementId: "dodo-inline-checkout"
});
Bạn cũng có thể truyền thêm tùy chọn để tùy chỉnh hành vi thanh toán:
DodoPayments.Checkout.open({
  checkoutUrl: "https://test.dodopayments.com/session/cks_123",
  elementId: "dodo-inline-checkout",
  options: {
    showTimer: false,
    showSecurityBadge: false,
    manualRedirect: true,
    payButtonText: "Pay Now",
  },
});
Khi sử dụng manualRedirect, xử lý hoàn tất thanh toán trong callback onEvent của bạn:
DodoPayments.Initialize({
  mode: "test",
  displayType: "inline",
  onEvent: (event) => {
    if (event.event_type === "checkout.status") {
      const status = event.data?.message?.status;
      // Handle status: "succeeded", "failed", or "processing"
    }
    if (event.event_type === "checkout.redirect_requested") {
      const redirectUrl = event.data?.message?.redirect_to;
      // Redirect the customer manually
      window.location.href = redirectUrl;
    }
    if (event.event_type === "checkout.link_expired") {
      // Handle expired checkout session
    }
  },
});

Đóng Thanh Toán

Loại bỏ khung thanh toán theo cách lập trình và dọn dẹp các trình lắng nghe sự kiện.
DodoPayments.Checkout.close();

Kiểm Tra Trạng Thái

Trả về liệu khung thanh toán hiện đang được chèn hay không.
const isOpen = DodoPayments.Checkout.isOpen();
// Returns: boolean

Sự Kiện

SDK cung cấp sự kiện thời gian thực thông qua callback onEvent. Đối với thanh toán nội tuyến, checkout.breakdown đặc biệt hữu ích để đồng bộ giao diện người dùng của bạn.
Loại sự kiệnMô tả
checkout.openedKhung thanh toán đã được tải.
checkout.form_readyBiểu mẫu thanh toán sẵn sàng nhận thông tin người dùng. Hữu ích để ẩn trạng thái tải và hiển thị giao diện thanh toán.
checkout.breakdownĐược kích hoạt khi giá cả, thuế hoặc giảm giá được cập nhật.
checkout.customer_details_submittedThông tin khách hàng đã được gửi.
checkout.pay_button_clickedĐược kích hoạt khi khách hàng nhấn nút thanh toán. Hữu ích cho phân tích và theo dõi kênh chuyển đổi.
checkout.redirectThanh toán sắp chuyển hướng (ví dụ: đến trang ngân hàng).
checkout.errorĐã xảy ra lỗi trong quá trình thanh toán.
checkout.link_expiredĐược kích hoạt khi phiên thanh toán hết hạn. Chỉ nhận khi showTimer được đặt thành false.
checkout.statusĐược kích hoạt khi manualRedirect được bật. Chứa trạng thái thanh toán (succeeded, failed hoặc processing).
checkout.redirect_requestedĐược kích hoạt khi manualRedirect được bật. Chứa URL để chuyển hướng khách hàng.

Dữ Liệu Phân Tích Thanh Toán

Sự kiện checkout.breakdown cung cấp các dữ liệu sau:
interface CheckoutBreakdownData {
  subTotal?: number;          // Amount in cents
  discount?: number;         // Amount in cents
  tax?: number;              // Amount in cents
  total?: number;            // Amount in cents
  currency?: string;         // e.g., "USD"
  finalTotal?: number;       // Final amount including adjustments
  finalTotalCurrency?: string; // Currency for the final total
}

Dữ Liệu Sự Kiện Trạng Thái Thanh Toán

Khi manualRedirect được bật, bạn nhận được sự kiện checkout.status với các dữ liệu sau:
interface CheckoutStatusEventData {
  message: {
    status?: "succeeded" | "failed" | "processing";
  };
}

Dữ Liệu Sự Kiện Yêu Cầu Chuyển Hướng Thanh Toán

Khi manualRedirect được bật, bạn nhận được sự kiện checkout.redirect_requested với các dữ liệu sau:
interface CheckoutRedirectRequestedEventData {
  message: {
    redirect_to?: string;
  };
}

Hiểu Sự Kiện Phân Tích

Sự kiện checkout.breakdown là cách chính để giữ giao diện ứng dụng của bạn đồng bộ với trạng thái thanh toán Dodo Payments. Khi nó xảy ra:
  • Khi khởi tạo: Ngay sau khi khung thanh toán được tải và sẵn sàng.
  • Khi thay đổi địa chỉ: Bất cứ khi nào khách hàng chọn một quốc gia hoặc nhập mã bưu chính dẫn đến việc tính toán thuế lại.
Chi tiết trường:
TrườngMô tả
subTotalTổng của tất cả các mục trong phiên trước khi áp dụng giảm giá hoặc thuế.
discountTổng giá trị của tất cả các mã giảm giá đã áp dụng.
taxSố tiền thuế được tính. Trong chế độ inline, giá trị này cập nhật động khi người dùng tương tác với các trường địa chỉ.
totalKết quả toán học của subTotal - discount + tax theo đơn vị tiền tệ cơ sở của phiên.
currencyMã tiền tệ ISO (ví dụ: "USD") cho các giá trị phụ, giảm giá và thuế chuẩn.
finalTotalSố tiền thực tế khách hàng bị tính. Có thể bao gồm điều chỉnh ngoại hối bổ sung hoặc phí phương thức thanh toán địa phương không nằm trong bảng giá cơ bản.
finalTotalCurrencyTiền tệ mà khách hàng thực sự thanh toán. Có thể khác với currency nếu đang áp dụng tỷ giá theo sức mua hoặc chuyển đổi tiền tệ địa phương.
Mẹo tích hợp chính:
  1. Định dạng tiền tệ: Giá luôn trả về dưới dạng số nguyên ở đơn vị nhỏ nhất của tiền tệ (ví dụ: xu cho USD, yên cho JPY). Để hiển thị, hãy chia cho 100 (hoặc lũy thừa phù hợp của 10) hoặc sử dụng thư viện định dạng như Intl.NumberFormat.
  2. Xử lý trạng thái ban đầu: Khi thanh toán mới tải, taxdiscount có thể là 0 hoặc null cho đến khi người dùng cung cấp thông tin thanh toán hoặc nhập mã. Giao diện của bạn nên xử lý các trạng thái này một cách mềm mại (ví dụ: hiển thị gạch ngang hoặc ẩn dòng).
  3. “Tổng cuối cùng” và “Tổng”: Trong khi total cung cấp phép tính giá chuẩn, finalTotal mới là nguồn sự thật cho giao dịch. Nếu finalTotal tồn tại, nó phản ánh chính xác số tiền sẽ bị trừ khỏi thẻ khách hàng, bao gồm mọi điều chỉnh động.
  4. Phản hồi thời gian thực: Sử dụng trường tax để cho người dùng thấy thuế đang được tính toán theo thời gian thực. Điều này tạo cảm giác “trực tiếp” cho trang thanh toán và giảm ma sát khi nhập địa chỉ.

Tùy Chọn Triển Khai

Cài Đặt Qua Trình Quản Lý Gói

Cài đặt qua npm, yarn hoặc pnpm như được hiển thị trong Hướng Dẫn Tích Hợp Từng Bước.

Triển Khai CDN

Để tích hợp nhanh mà không cần bước xây dựng, bạn có thể sử dụng CDN của chúng tôi:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dodo Payments Inline Checkout</title>
    
    <!-- Load DodoPayments -->
    <script src="https://cdn.jsdelivr.net/npm/dodopayments-checkout@latest/dist/index.js"></script>
    <script>
        // Initialize the SDK
        DodoPaymentsCheckout.DodoPayments.Initialize({
            mode: "test",
            displayType: "inline",
            onEvent: (event) => {
                console.log('Checkout event:', event);
            }
        });
    </script>
</head>
<body>
    <div id="dodo-inline-checkout"></div>

    <script>
        // Open the checkout
        DodoPaymentsCheckout.DodoPayments.Checkout.open({
            checkoutUrl: "https://test.dodopayments.com/session/cks_123",
            elementId: "dodo-inline-checkout"
        });
    </script>
</body>
</html>

Cập nhật phương thức thanh toán

Inline checkout hỗ trợ cập nhật phương thức thanh toán cho các đăng ký. Khi khách hàng cần cập nhật phương thức thanh toán — cho đăng ký đang hoạt động hoặc để kích hoạt lại đăng ký đang tạm ngưng — bạn có thể hiển thị luồng cập nhật ngay trong bố cục trang của mình.

Cách thức hoạt động

  1. Gọi Update Payment Method API để lấy một payment_link:
const response = await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'new',
  return_url: 'https://example.com/return'
});
  1. Truyền payment_link nhận được làm checkoutUrl để mở inline checkout:
DodoPayments.Checkout.open({
  checkoutUrl: response.payment_link,
  elementId: "dodo-inline-checkout"
});
Khung inline chỉ hiển thị biểu mẫu thu thập phương thức thanh toán. Khách hàng có thể nhập thông tin thẻ mới hoặc chọn phương thức đã lưu mà không rời khỏi trang của bạn.

Đối với các đăng ký đang tạm ngưng

Khi cập nhật phương thức thanh toán cho một đăng ký ở trạng thái on_hold, Dodo Payments tự động tạo một khoản phí cho bất kỳ khoản còn lại nào. Theo dõi webhook payment.succeededsubscription.active để xác nhận việc kích hoạt lại.
const response = await client.subscriptions.updatePaymentMethod('sub_123', {
  type: 'new',
  return_url: 'https://example.com/return'
});

if (response.payment_id) {
  // Charge created for remaining dues
  // Open inline checkout for payment collection
  DodoPayments.Checkout.open({
    checkoutUrl: response.payment_link,
    elementId: "dodo-inline-checkout"
  });
}
Bạn cũng có thể sử dụng phương thức thanh toán đã lưu sẵn thay vì thu thập thông tin mới bằng cách truyền type: 'existing' với một payment_method_id đến Update Payment Method API.

Xử lý lỗi

SDK cung cấp thông tin lỗi chi tiết thông qua hệ thống sự kiện. Luôn triển khai xử lý lỗi thích hợp trong callback onEvent của bạn:
DodoPayments.Initialize({
  mode: "test",
  displayType: "inline",
  onEvent: (event: CheckoutEvent) => {
    if (event.event_type === "checkout.error") {
      console.error("Checkout error:", event.data?.message);
      // Handle error appropriately
    }
  }
});
Luôn xử lý sự kiện checkout.error để mang lại trải nghiệm người dùng tốt khi xảy ra sự cố.

Thực hành tốt nhất

  1. Thiết kế đáp ứng: Đảm bảo phần tử chứa của bạn có đủ chiều rộng và chiều cao. Iframe thường sẽ mở rộng để lấp đầy phần chứa.
  2. Đồng bộ hóa: Sử dụng sự kiện checkout.breakdown để giữ bản tóm tắt đơn hàng hoặc bảng giá tùy chỉnh của bạn đồng bộ với những gì người dùng thấy trong khung thanh toán.
  3. Trạng thái skeleton: Hiển thị chỉ báo đang tải trong phần chứa của bạn cho đến khi sự kiện checkout.opened xảy ra.
  4. Dọn dẹp: Gọi DodoPayments.Checkout.close() khi component của bạn bị hủy để dọn dẹp iframe và các trình lắng nghe sự kiện.
Đối với các triển khai chế độ tối, nên sử dụng #0d0d0d làm màu nền để tích hợp trực quan tối ưu với khung inline checkout.

Xác thực trạng thái thanh toán

Đừng chỉ dựa vào sự kiện inline checkout để xác định thành công hay thất bại. Luôn triển khai xác thực phía máy chủ bằng webhook và/hoặc polling.

Tại sao xác thực phía máy chủ là điều thiết yếu

Trong khi các sự kiện inline checkout như checkout.status cung cấp phản hồi theo thời gian thực, chúng không nên là nguồn duy nhất cho trạng thái thanh toán. Sự cố mạng, trình duyệt bị treo hoặc người dùng đóng trang có thể khiến sự kiện bị bỏ lỡ. Để đảm bảo xác thực thanh toán đáng tin cậy:
  1. Máy chủ của bạn nên lắng nghe các sự kiện webhook - Dodo Payments gửi webhook khi trạng thái thanh toán thay đổi
  2. Triển khai cơ chế polling - Giao diện của bạn nên liên tục truy vấn máy chủ để cập nhật trạng thái
  3. Kết hợp cả hai cách tiếp cận - Sử dụng webhook làm nguồn chính và polling làm phương án dự phòng

Kiến trúc khuyến nghị

Các bước triển khai

1. Lắng nghe các sự kiện checkout - Khi người dùng nhấn thanh toán, bắt đầu chuẩn bị để xác minh trạng thái:
onEvent: (event) => {
  if (event.event_type === 'checkout.status') {
    // Start polling your server for confirmed status
    startPolling();
  }
}
2. Poll máy chủ của bạn - Tạo một endpoint kiểm tra cơ sở dữ liệu của bạn để lấy trạng thái thanh toán (được webhook cập nhật):
// Poll every 2 seconds until status is confirmed
const interval = setInterval(async () => {
  const { status } = await fetch(`/api/payments/${paymentId}/status`).then(r => r.json());
  if (status === 'succeeded' || status === 'failed') {
    clearInterval(interval);
    handlePaymentResult(status);
  }
}, 2000);
3. Xử lý webhook phía máy chủ - Cập nhật cơ sở dữ liệu của bạn khi Dodo gửi webhook payment.succeeded hoặc payment.failed. Xem Tài liệu Webhooks để biết chi tiết.

Xử lý chuyển hướng (3DS, Google Pay, UPI)

Khi sử dụng manualRedirect: true, một số phương thức thanh toán yêu cầu chuyển hướng người dùng khỏi trang của bạn để xác thực:
  • 3D Secure (3DS) - Xác thực thẻ
  • Google Pay - Xác thực ví trong một số luồng
  • UPI - Chuyển hướng phương thức thanh toán của Ấn Độ
Khi cần chuyển hướng, bạn sẽ nhận được sự kiện checkout.redirect_requested. Chuyển hướng người dùng tới URL được cung cấp:
if (event.event_type === 'checkout.redirect_requested') {
  const redirectUrl = event.data?.message?.redirect_to;
  // Save payment ID before redirect, then redirect
  sessionStorage.setItem('pendingPaymentId', paymentId);
  window.location.href = redirectUrl;
}
Sau khi xác thực hoàn tất (thành công hoặc thất bại), người dùng quay lại trang của bạn. Đừng cho rằng giao dịch thành công chỉ vì người dùng trở lại. Thay vào đó:
  1. Kiểm tra xem người dùng có quay lại từ một chuyển hướng hay không (ví dụ: thông qua sessionStorage)
  2. Bắt đầu polling máy chủ để lấy trạng thái thanh toán được xác nhận
  3. Hiển thị trạng thái “Đang xác minh thanh toán…” trong khi polling
  4. Hiển thị giao diện thành công/thất bại dựa trên trạng thái được xác nhận bởi máy chủ
Luôn xác minh trạng thái thanh toán phía máy chủ sau khi chuyển hướng. Người dùng quay lại trang của bạn chỉ có nghĩa là xác thực hoàn tất — không báo hiệu thanh toán thành công hay thất bại.

Khắc phục sự cố

  • Xác minh rằng elementId khớp với id của một div thực sự tồn tại trong DOM.
  • Đảm bảo displayType: 'inline' đã được truyền tới Initialize.
  • Kiểm tra rằng checkoutUrl là hợp lệ.
  • Đảm bảo bạn đang lắng nghe sự kiện checkout.breakdown.
  • Thuế chỉ được tính sau khi người dùng nhập quốc gia và mã bưu chính hợp lệ trong khung thanh toán.

Kích hoạt ví kỹ thuật số

Để biết thông tin chi tiết về cách thiết lập Apple Pay, Google Pay và các ví kỹ thuật số khác, xem trang Ví kỹ thuật số.

Thiết lập nhanh cho Apple Pay

1

Download domain association file

2

Request activation

Gửi email support@dodopayments.com kèm URL miền sản xuất của bạn và yêu cầu kích hoạt Apple Pay.
3

Test after confirmation

Sau khi xác nhận, kiểm tra Apple Pay hiển thị trong checkout và thử nghiệm toàn bộ luồng.
Apple Pay yêu cầu xác minh miền trước khi xuất hiện trong môi trường production. Liên hệ bộ phận hỗ trợ trước khi ra mắt nếu bạn dự định cung cấp Apple Pay.

Hỗ trợ trình duyệt

SDK Dodo Payments Checkout hỗ trợ các trình duyệt sau:
  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)
  • IE11+

Inline và Overlay Checkout

Chọn loại checkout phù hợp với trường hợp sử dụng của bạn:
Tính năngInline CheckoutOverlay Checkout
Độ sâu tích hợpNhúng hoàn toàn vào trangModal phủ lên trên trang
Kiểm soát bố cụcToàn quyền kiểm soátHạn chế
Thương hiệuLiền mạchTách biệt khỏi trang
Nỗ lực triển khaiCao hơnThấp hơn
Phù hợp choTrang thanh toán tùy chỉnh, luồng chuyển đổi caoTích hợp nhanh, các trang hiện có
Sử dụng inline checkout khi bạn muốn kiểm soát tối đa trải nghiệm checkout và branding liền mạch. Dùng overlay checkout để tích hợp nhanh với ít thay đổi cho các trang hiện có.

Tài nguyên liên quan

Để được trợ giúp thêm, hãy truy cập cộng đồng Discord hoặc liên hệ đội ngũ hỗ trợ nhà phát triển của chúng tôi.