DEV Community

Cover image for Cách Sử Dụng API Braintree Hiệu Quả Nhất
Sebastian Petrus
Sebastian Petrus

Posted on • Originally published at apidog.com

Cách Sử Dụng API Braintree Hiệu Quả Nhất

Tóm tắt

API của Braintree xử lý thanh toán qua thẻ tín dụng, PayPal, Venmo và ví điện tử. Bạn tích hợp thông qua SDK phía máy chủ (Node, Python, Ruby, v.v.), tạo client token để bảo mật frontend, và xử lý giao dịch, hoàn tiền cũng như đăng ký. Để kiểm thử, sử dụng Apidog để xác thực payload webhook và kiểm tra tích hợp với dữ liệu sandbox trước khi triển khai thực tế.

Dùng thử Apidog ngay hôm nay

Giới thiệu

Braintree xử lý hàng tỷ giao dịch mỗi năm, là nền tảng thanh toán đứng sau Uber, Airbnb, GitHub. Hỗ trợ thẻ tín dụng, PayPal, Venmo, Apple Pay, Google Pay, ACH...

API thanh toán yêu cầu độ chính xác cao: lỗi tích hợp có thể gây mất tiền thật và phá vỡ niềm tin khách hàng. Có hai dạng tích hợp: giao diện Drop-in (mẫu dựng sẵn) và giao diện tùy chỉnh (kiểm soát hoàn toàn). Cả hai dùng chung API phía máy chủ để xử lý thanh toán. Hướng dẫn này tập trung vào công việc phía server sau khi khách hàng nhấn “Thanh toán”.

💡 Nếu bạn xây dựng tích hợp thanh toán, Apidog giúp kiểm thử webhook handler và xác thực phản hồi thanh toán. Bạn có thể mô phỏng webhook Braintree tại môi trường local, kiểm tra các trường hợp thành công, thất bại, biên… trước khi giao dịch thật.

Kiểm thử webhook Braintree với Apidog - miễn phí

Thiết lập Braintree

Tạo tài khoản Braintree

  • Truy cập braintreepayments.com
  • Đăng ký tài khoản sandbox.
  • Lưu lại:
    • Merchant ID: abc123xyz
    • Public Key: def456...
    • Private Key: ghi789...

Bảo mật: Không lưu private key trong Git hoặc repo công khai.

Braintree Dashboard

Cài đặt SDK

Cài đặt SDK phía server phù hợp với ngôn ngữ bạn dùng:

Node.js:

npm install braintree
Enter fullscreen mode Exit fullscreen mode

Python:

pip install braintree
Enter fullscreen mode Exit fullscreen mode

Ruby:

gem install braintree
Enter fullscreen mode Exit fullscreen mode

Khởi tạo gateway:

const braintree = require('braintree')

const gateway = new braintree.BraintreeGateway({
  environment: braintree.Environment.Sandbox,
  merchantId: process.env.BRAINTREE_MERCHANT_ID,
  publicKey: process.env.BRAINTREE_PUBLIC_KEY,
  privateKey: process.env.BRAINTREE_PRIVATE_KEY
})
Enter fullscreen mode Exit fullscreen mode

Tạo client token

Trước khi render form thanh toán, tạo client token để frontend giao tiếp với Braintree:

app.get('/checkout/token', async (req, res) => {
  const clientToken = await gateway.clientToken.generate()
  res.json({ clientToken: clientToken.clientToken })
})
Enter fullscreen mode Exit fullscreen mode

Frontend sẽ dùng token này để khởi tạo Drop-in UI hoặc tích hợp tùy chỉnh.

Xử lý thanh toán

Luồng thanh toán

  1. Frontend gửi payment method nonce đến backend
  2. Backend tạo giao dịch với nonce này
  3. Braintree xử lý thanh toán
  4. Backend nhận kết quả thành công/thất bại
  5. Xử lý đơn hàng hoặc báo lỗi cho user

Tính phí thẻ tín dụng

app.post('/checkout', async (req, res) => {
  const { paymentMethodNonce, amount, orderId } = req.body

  const result = await gateway.transaction.sale({
    amount: amount,
    paymentMethodNonce: paymentMethodNonce,
    orderId: orderId,
    options: {
      submitForSettlement: true
    }
  })

  if (result.success) {
    res.json({
      success: true,
      transactionId: result.transaction.id
    })
  } else {
    res.status(400).json({
      success: false,
      message: result.message
    })
  }
})
Enter fullscreen mode Exit fullscreen mode

Tính phí bằng phương thức thanh toán đã lưu

Lưu phương thức thanh toán sau giao dịch đầu tiên để dùng về sau:

// Tạo customer với payment method
const result = await gateway.customer.create({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
  paymentMethodNonce: nonce
})

// Lấy token phương thức thanh toán đã lưu
const paymentMethodToken = result.customer.paymentMethods[0].token

// Dùng token để thu tiền sau này
await gateway.transaction.sale({
  amount: '49.99',
  paymentMethodToken: paymentMethodToken,
  options: {
    submitForSettlement: true
  }
})
Enter fullscreen mode Exit fullscreen mode

Giao dịch PayPal

Xử lý PayPal như thẻ tín dụng, chỉ cần payment nonce:

const result = await gateway.transaction.sale({
  amount: '99.00',
  paymentMethodNonce: paypalNonce,
  orderId: 'ORDER-123',
  options: {
    submitForSettlement: true
  }
})
Enter fullscreen mode Exit fullscreen mode

Hoàn tiền và hủy

Hoàn tiền đầy đủ

const result = await gateway.transaction.refund('transaction_id')

if (result.success) {
  console.log('Đã hoàn tiền:', result.transaction.id)
}
Enter fullscreen mode Exit fullscreen mode

Hoàn tiền một phần

const result = await gateway.transaction.refund('transaction_id', '50.00')

if (result.success) {
  console.log('Đã xử lý hoàn tiền một phần')
}
Enter fullscreen mode Exit fullscreen mode

Hủy giao dịch

Hủy giao dịch chưa settle (chỉ mới ủy quyền):

const result = await gateway.transaction.void('transaction_id')

if (result.success) {
  console.log('Giao dịch đã bị hủy')
}
Enter fullscreen mode Exit fullscreen mode

Luồng trạng thái giao dịch

được ủy quyền → được gửi để thanh toán → đã thanh toán
                    ↓
                   đã hủy

đã thanh toán → đã hoàn tiền
Enter fullscreen mode Exit fullscreen mode

Đăng ký và thanh toán định kỳ

Tạo một gói

Tạo plan mới trong dashboard hoặc qua API:

const result = await gateway.plan.create({
  id: 'monthly-premium',
  name: 'Monthly Premium',
  billingFrequency: 1,
  currencyIsoCode: 'USD',
  price: '29.99'
})
Enter fullscreen mode Exit fullscreen mode

Tạo một đăng ký

const result = await gateway.subscription.create({
  paymentMethodToken: paymentMethodToken,
  planId: 'monthly-premium',
  firstBillingDate: new Date()
})

if (result.success) {
  console.log('Đã tạo đăng ký:', result.subscription.id)
}
Enter fullscreen mode Exit fullscreen mode

Hủy đăng ký

const result = await gateway.subscription.cancel('subscription_id')

if (result.success) {
  console.log('Đăng ký đã bị hủy')
}
Enter fullscreen mode Exit fullscreen mode

Cập nhật đăng ký

const result = await gateway.subscription.update('subscription_id', {
  planId: 'annual-premium',
  price: '299.99'
})
Enter fullscreen mode Exit fullscreen mode

Webhooks cho các sự kiện thanh toán

Webhooks rất quan trọng để cập nhật trạng thái giao dịch, quản lý đăng ký, tranh chấp...

Tạo endpoint webhook

app.post('/webhooks/braintree', (req, res) => {
  const signature = req.body.bt_signature
  const payload = req.body.bt_payload

  gateway.webhookNotification.parse(
    signature,
    payload,
    (err, webhookNotification) => {
      if (err) {
        return res.status(400).send('Webhook không hợp lệ')
      }

      switch (webhookNotification.kind) {
        case 'subscription_charged_successfully':
          handleSuccessfulCharge(webhookNotification.subscription)
          break
        case 'subscription_charged_unsuccessfully':
          handleFailedCharge(webhookNotification.subscription)
          break
        case 'dispute_opened':
          handleDispute(webhookNotification.dispute)
          break
        case 'transaction_settled':
          handleSettledTransaction(webhookNotification.transaction)
          break
      }

      res.status(200).send('OK')
    }
  )
})
Enter fullscreen mode Exit fullscreen mode

Đăng ký webhook trong Braintree

Truy cập dashboard Braintree → Cài đặt → Webhooks → Thêm endpoint. Trong môi trường dev, dùng ngrok để nhận webhook từ internet về local.

Kiểm thử với Apidog

API thanh toán phải kiểm thử kỹ, không phụ thuộc dữ liệu thật. Apidog giúp mô phỏng và xác thực các luồng webhook an toàn, hiệu quả.

Apidog Test

1. Mô phỏng payload webhook

Tạo payload mô phỏng và gửi về endpoint webhook để xác thực handler:

{
  "bt_signature": "test_signature",
  "bt_payload": "eyJraW5kIjoidHJhbnNhY3Rpb25fc2V0dGxlZCIsInRyYW5zYWN0aW9uIjp7ImlkIjoiYWJjMTIzIiwiYW1vdW50IjoiNDkuOTkiLCJzdGF0dXMiOiJzZXR0bGVkIn19"
}
Enter fullscreen mode Exit fullscreen mode

2. Phân tách môi trường

Quản lý biến môi trường rõ ràng giữa sandbox và production:

# Sandbox
BRAINTREE_MERCHANT_ID: sandbox_merchant
BRAINTREE_PUBLIC_KEY: sandbox_public
BRAINTREE_PRIVATE_KEY: sandbox_private
BRAINTREE_ENVIRONMENT: sandbox

# Production
BRAINTREE_MERCHANT_ID: live_merchant
BRAINTREE_PUBLIC_KEY: live_public
BRAINTREE_PRIVATE_KEY: live_private
BRAINTREE_ENVIRONMENT: production
Enter fullscreen mode Exit fullscreen mode

3. Xác thực phản hồi webhook

Kiểm tra phản hồi API và ghi nhận transaction ID:

pm.test('Webhook đã xử lý thành công', () => {
  pm.response.to.have.status(200)
  pm.response.to.have.body('OK')
})

pm.test('ID giao dịch đã được ghi lại', () => {
  const transactionId = pm.environment.get('last_transaction_id')
  pm.expect(transactionId).to.not.be.empty
})
Enter fullscreen mode Exit fullscreen mode

Kiểm thử webhook Braintree với Apidog - miễn phí

Các lỗi và cách khắc phục thường gặp

Bộ xử lý từ chối

Nguyên nhân: Ngân hàng từ chối giao dịch (thường do không đủ tiền, nghi ngờ gian lận).

Khắc phục: Hiển thị thông báo chung, đề xuất thử thẻ khác, ghi lại processorResponseCode để debug.

if (!result.success) {
  if (result.transaction.processorResponseCode === '2000') {
    return res.status(400).json({
      error: 'Ngân hàng của bạn đã từ chối giao dịch này. Vui lòng thử một thẻ khác.'
    })
  }
}
Enter fullscreen mode Exit fullscreen mode

Gateway từ chối

Nguyên nhân: Bị chặn bởi anti-fraud của Braintree.

Khắc phục: Kiểm tra lý do qua gatewayRejectionReason:

if (result.transaction.gatewayRejectionReason === 'cvv') {
  // CVV không khớp
}
if (result.transaction.gatewayRejectionReason === 'avs') {
  // Xác minh địa chỉ thất bại
}
if (result.transaction.gatewayRejectionReason === 'fraud') {
  // Anti-fraud nâng cao chặn
}
Enter fullscreen mode Exit fullscreen mode

Lỗi thanh toán

Nguyên nhân: Giao dịch bị từ chối khi settle (sau ủy quyền).

Khắc phục: Theo dõi webhook transaction_settlement_declined. Các nguyên nhân thường gặp:

  • Thẻ hết hạn giữa lúc ủy quyền và settle
  • Nhà phát hành chặn giao dịch
  • Không đủ tiền

Giao dịch trùng lặp

Nguyên nhân: Người dùng bấm “Thanh toán” nhiều lần, hoặc backend retry.

Khắc phục: Dùng orderId để tránh duplicate:

const result = await gateway.transaction.sale({
  amount: '49.99',
  paymentMethodNonce: nonce,
  orderId: 'UNIQUE-ORDER-123',
  options: {
    submitForSettlement: true
  }
})
Enter fullscreen mode Exit fullscreen mode

Các lựa chọn thay thế và so sánh

Tính năng Braintree Stripe PayPal
Giá 2.9% + 30¢ 2.9% + 30¢ 2.9% + 30¢
Hỗ trợ PayPal Bản địa Add-on Bản địa
Đăng ký Hạn chế
Quốc tế 46 quốc gia 46 quốc gia 200+ quốc gia
Công cụ chống gian lận Tích hợp sẵn Tích hợp sẵn Cơ bản
Chất lượng SDK Tuyệt vời Tuyệt vời Tốt
Thanh toán

Lợi thế của Braintree là hỗ trợ PayPal/Venmo gốc. Nếu bạn cần cả thẻ và PayPal, một API Braintree đơn giản hơn Stripe + PayPal riêng biệt.

Các trường hợp sử dụng thực tế

  • Nền tảng SaaS: Quản lý đăng ký hàng tháng, xử lý thẻ hết hạn qua webhook, gửi email tự động.
  • Marketplace: Chia tiền giữa phí nền tảng và freelancer qua merchant/sub-merchant account của Braintree.
  • E-commerce hỗ trợ PayPal: Một tích hợp, xử lý đồng thời thẻ và PayPal.

Kết luận

Tóm lại, bạn cần thực hiện:

  • Tích hợp SDK server-side của Braintree
  • Tạo client token cho frontend
  • Xử lý giao dịch thẻ/PayPal qua API
  • Đăng ký thanh toán định kỳ với subscription
  • Lắng nghe webhook để cập nhật trạng thái
  • Kiểm thử kỹ lưỡng với Apidog trước khi triển khai

Câu hỏi thường gặp

Nonce phương thức thanh toán là gì?

Nonce là token dùng một lần đại diện cho phương thức thanh toán, do frontend tạo sau khi người dùng nhập thông tin thẻ. Backend dùng nonce này để thu tiền. Nonce hết hạn sau 3 giờ.

Sự khác biệt giữa ủy quyền và thanh toán là gì?

  • Ủy quyền: Đặt giữ tiền trên thẻ, chưa thu về.
  • Thanh toán: Thực sự thu tiền.
  • Mặc định Braintree sẽ thanh toán luôn. Nếu cần pre-order, chỉ ủy quyền rồi submit for settlement sau:
// Chỉ ủy quyền
await gateway.transaction.sale({
  amount: '99.00',
  paymentMethodNonce: nonce,
  options: {
    submitForSettlement: false // Chỉ ủy quyền
  }
})

// Thanh toán sau
await gateway.transaction.submitForSettlement('transaction_id')
Enter fullscreen mode Exit fullscreen mode

Làm sao xử lý đa tiền tệ?

Mỗi merchant account có một loại tiền tệ. Nếu cần đa tiền tệ, liên hệ Braintree để tạo nhiều merchant account.

Thẻ kiểm thử nào nên dùng?

  • 4111111111111111 – Visa (thành công)
  • 4000111111111115 – Visa (từ chối)
  • 5555555555554444 – Mastercard (thành công)
  • 378282246310005 – Amex (thành công)

Làm sao xử lý tranh chấp/hoàn trả?

Lắng nghe webhook dispute_opened, dispute_won, dispute_lost. Cung cấp bằng chứng qua dashboard Braintree. Lưu mọi thông tin: giao tiếp khách hàng, xác nhận giao hàng, điều khoản.

Tôi có được lưu số thẻ tín dụng không?

Không. Theo PCI, không được lưu số thẻ thô. Lưu token phương thức thanh toán (do Braintree cung cấp) thay vì số thẻ.

3D Secure là gì?

3D Secure thêm một lớp xác thực cho thanh toán online. Braintree hỗ trợ. Bật trong dashboard, xử lý response authentication_required:

const result = await gateway.transaction.sale({
  amount: '100.00',
  paymentMethodNonce: nonce,
  threeDSecure: {
    required: true
  }
})
Enter fullscreen mode Exit fullscreen mode

Hoàn tiền mất bao lâu?

Thường từ 3-5 ngày làm việc, tùy ngân hàng. Nhận webhook transaction_refunded khi hoàn tất.

Top comments (0)