요약
Braintree API는 신용카드, PayPal, Venmo, 디지털 지갑을 통한 결제를 처리합니다. 서버 측 SDK(Node, Python, Ruby 등)를 통해 통합하고, 프런트엔드 보안을 위해 클라이언트 토큰을 생성하며, 거래, 환불, 구독을 처리합니다. 테스트를 위해, 실제 서비스 출시 전 샌드박스 데이터를 이용하여 웹훅 페이로드를 검증하고 통합을 테스트하려면 Apidog를 사용하세요.
서론
Braintree는 매년 수십억 달러의 결제를 처리합니다. Uber, Airbnb, GitHub와 같은 기업의 결제 처리 시스템입니다. 이 플랫폼은 신용카드, PayPal, Venmo, Apple Pay, Google Pay, ACH 송금을 지원합니다.
결제 API는 다른 API와 다릅니다. 제품 카탈로그의 실수는 번거롭지만, 결제의 실수는 실제 금전적 손실을 발생시키고 고객의 신뢰를 깨뜨립니다. 정확하게 처리해야 합니다.
Braintree는 두 가지 통합 경로를 제공합니다: 드롭인 UI (사전 구축된 결제 양식)와 커스텀 UI (완전한 제어). 둘 다 실제 결제 처리를 위해 동일한 서버 측 API를 사용합니다. 이 가이드는 고객이 "결제"를 클릭한 후에 발생하는 서버 측 작업을 다룹니다.
Apidog로 Braintree 웹훅 테스트하기 - 무료
Braintree 설정
Braintree 계정 생성
braintreepayments.com (Braintree는 이제 PayPal Enterprise Payments입니다)으로 이동하여 샌드박스 계정을 생성하세요. 다음 정보를 얻게 됩니다:
- 판매자 ID:
abc123xyz - 공개 키:
def456... - 개인 키:
ghi789...
이 정보들을 안전하게 보관하세요. 개인 키는 비밀번호와 같으므로 Git에 절대 커밋하지 마세요.

SDK 설치
Braintree는 대부분의 언어에 대한 서버 측 SDK를 제공합니다:
Node.js:
npm install braintree
Python:
pip install braintree
Ruby:
gem install braintree
게이트웨이 초기화:
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
})
클라이언트 토큰 생성
결제 양식을 표시하기 전에 클라이언트 토큰을 생성하세요. 이는 프런트엔드가 Braintree와 통신하도록 승인합니다.
app.get('/checkout/token', async (req, res) => {
const clientToken = await gateway.clientToken.generate()
res.json({ clientToken: clientToken.clientToken })
})
프런트엔드는 이 토큰을 사용하여 드롭인 UI 또는 사용자 정의 통합을 초기화합니다.
결제 처리
결제 흐름
- 프런트엔드가 결제 수단 논스를 서버로 전송합니다
- 서버가 논스를 사용하여 거래를 생성합니다
- Braintree가 결제를 처리합니다
- 서버가 성공/실패 응답을 수신합니다
- 주문을 이행하거나 오류를 표시합니다
신용카드 청구
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
})
}
})
저장된 결제 수단으로 청구
첫 거래 후에는 나중에 사용할 수 있도록 결제 수단을 저장할 수 있습니다:
// 결제 수단으로 고객 생성
const result = await gateway.customer.create({
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com',
paymentMethodNonce: nonce
})
// 결제 수단이 저장됨
const paymentMethodToken = result.customer.paymentMethods[0].token
// 나중에 저장된 결제 수단으로 청구
await gateway.transaction.sale({
amount: '49.99',
paymentMethodToken: paymentMethodToken,
options: {
submitForSettlement: true
}
})
PayPal 거래
Braintree는 PayPal을 카드와 동일하게 처리합니다. 프런트엔드는 PayPal로부터 논스를 받고, 이를 청구합니다:
const result = await gateway.transaction.sale({
amount: '99.00',
paymentMethodNonce: paypalNonce,
orderId: 'ORDER-123',
options: {
submitForSettlement: true
}
})
환불 및 취소
전체 환불
const result = await gateway.transaction.refund('transaction_id')
if (result.success) {
console.log('환불됨:', result.transaction.id)
}
부분 환불
const result = await gateway.transaction.refund('transaction_id', '50.00')
if (result.success) {
console.log('부분 환불 처리됨')
}
거래 취소
취소는 거래가 정산되기 전에 중단합니다. 승인되었지만 아직 청구되지 않은 결제에 사용하세요:
const result = await gateway.transaction.void('transaction_id')
if (result.success) {
console.log('거래 취소됨')
}
거래 상태 흐름
승인됨 → 정산 제출됨 → 정산 완료됨
↓
취소됨
정산 완료됨 → 환불됨
구독 및 정기 결제
Braintree는 정기 결제를 위한 구독을 처리합니다.
플랜 생성
먼저 Braintree 제어판 또는 API를 통해 플랜을 생성하세요:
const result = await gateway.plan.create({
id: 'monthly-premium',
name: 'Monthly Premium',
billingFrequency: 1,
currencyIsoCode: 'USD',
price: '29.99'
})
구독 생성
const result = await gateway.subscription.create({
paymentMethodToken: paymentMethodToken,
planId: 'monthly-premium',
firstBillingDate: new Date()
})
if (result.success) {
console.log('구독 생성됨:', result.subscription.id)
}
구독 취소
const result = await gateway.subscription.cancel('subscription_id')
if (result.success) {
console.log('구독 취소됨')
}
구독 업데이트
const result = await gateway.subscription.update('subscription_id', {
planId: 'annual-premium',
price: '299.99'
})
결제 이벤트용 웹훅
웹훅은 거래 이벤트에 대해 서버에 알림을 보냅니다. 이는 구독 및 분쟁 처리에 중요합니다.
웹훅 엔드포인트 생성
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('유효하지 않은 웹훅')
}
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')
}
)
})
Braintree에 웹훅 등록
Braintree 제어판에서 설정 → 웹훅으로 이동하여 엔드포인트 URL을 추가하세요. 개발 중에는 ngrok과 같은 터널링 서비스를 사용하여 로컬에서 웹훅을 수신할 수 있습니다.
Apidog로 테스트하기
결제 API는 철저한 테스트가 필요합니다. 실제 운영 데이터를 신뢰할 수 없습니다. Apidog는 위험 없이 테스트할 수 있도록 도와줍니다.

1. 웹훅 페이로드 모의 테스트
Braintree가 웹훅을 보낼 때까지 기다리는 대신, 모의 페이로드를 생성하세요:
{
"bt_signature": "test_signature",
"bt_payload": "eyJraW5kIjoidHJhbnNhY3Rpb25fc2V0dGxlZCIsInRyYW5zYWN0aW9uIjp7ImlkIjoiYWJjMTIzIiwiYW1vdW50IjoiNDkuOTkiLCJzdGF0dXMiOiJzZXR0bGVkIn19"
}
이를 웹훅 엔드포인트로 전송하고 코드가 올바르게 처리하는지 확인하세요.
2. 환경 분리
별도의 환경을 생성하세요:
# 샌드박스
BRAINTREE_MERCHANT_ID: sandbox_merchant
BRAINTREE_PUBLIC_KEY: sandbox_public
BRAINTREE_PRIVATE_KEY: sandbox_private
BRAINTREE_ENVIRONMENT: sandbox
# 프로덕션
BRAINTREE_MERCHANT_ID: live_merchant
BRAINTREE_PUBLIC_KEY: live_public
BRAINTREE_PRIVATE_KEY: live_private
BRAINTREE_ENVIRONMENT: production
3. 웹훅 응답 검증
pm.test('웹훅이 성공적으로 처리됨', () => {
pm.response.to.have.status(200)
pm.response.to.have.body('OK')
})
pm.test('거래 ID가 기록됨', () => {
// 로그 또는 데이터베이스 확인
const transactionId = pm.environment.get('last_transaction_id')
pm.expect(transactionId).to.not.be.empty
})
Apidog로 Braintree 웹훅 테스트하기 - 무료
일반적인 오류 및 해결 방법
프로세서 거부됨
원인: 은행이 거래를 거부했습니다.
해결: 이는 종종 자금 부족 또는 사기 필터 때문입니다. 고객에게 일반적인 오류를 표시하고 다른 카드를 시도하도록 제안하세요. 디버깅을 위해 processorResponseCode를 기록하세요.
if (!result.success) {
if (result.transaction.processorResponseCode === '2000') {
// 은행 거부
return res.status(400).json({
error: '은행이 이 거래를 거부했습니다. 다른 카드를 사용해 보세요.'
})
}
}
게이트웨이 거부됨
원인: Braintree의 사기 방지 필터가 거래를 차단했습니다.
해결: gatewayRejectionReason을 확인하세요:
if (result.transaction.gatewayRejectionReason === 'cvv') {
// CVV 불일치
}
if (result.transaction.gatewayRejectionReason === 'avs') {
// 주소 인증 실패
}
if (result.transaction.gatewayRejectionReason === 'fraud') {
// 고급 사기 방지 도구가 차단함
}
정산 실패
원인: 승인 후 거래가 정산될 수 없었습니다.
해결: transaction_settlement_declined 웹훅을 모니터링하세요. 일반적인 원인은 다음과 같습니다:
- 승인과 정산 사이에 결제 수단이 만료됨
- 발급자가 거래를 차단함
- 자금 부족이 명백해짐
중복 거래
원인: 고객이 "결제"를 두 번 클릭했거나 코드가 재시도했습니다.
해결: orderId 매개변수를 사용하세요. Braintree는 지정된 시간 내의 중복 거래를 거부할 것입니다:
const result = await gateway.transaction.sale({
amount: '49.99',
paymentMethodNonce: nonce,
orderId: 'UNIQUE-ORDER-123', // 중복 방지
options: {
submitForSettlement: true
}
})
대안 및 비교
| 기능 | Braintree | Stripe | PayPal |
|---|---|---|---|
| 가격 | 2.9% + 30¢ | 2.9% + 30¢ | 2.9% + 30¢ |
| PayPal 지원 | 기본 지원 | 추가 기능 | 기본 지원 |
| 구독 | 예 | 예 | 제한적 |
| 국제 | 46개국 | 46개국 | 200개국 이상 |
| 사기 방지 도구 | 내장 | 내장 | 기본 |
| SDK 품질 | 우수 | 우수 | 양호 |
| 지급 | 예 | 예 | 예 |
Braintree의 주요 장점은 PayPal 및 Venmo의 기본 지원입니다. 카드 처리와 PayPal 모두가 필요하다면, Stripe + PayPal을 개별적으로 사용하는 것보다 더 간단한 경우가 많습니다.
실제 사용 사례
SaaS 구독 플랫폼. 한 프로젝트 관리 도구는 Braintree를 월별 구독에 사용합니다. 웹훅은 실패한 결제(카드 만료, 잔액 부족)를 이메일 알림을 통해 처리합니다. 사용자는 지원팀에 문의할 필요 없이 결제 수단을 업데이트할 수 있습니다.
마켓플레이스 결제. 한 프리랜서 플랫폼은 플랫폼 수수료와 프리랜서 간의 결제를 분할합니다. Braintree의 판매자 계정 및 서브 판매자 설정은 이러한 복잡성을 처리합니다.
PayPal을 이용한 전자상거래. 한 온라인 상점은 신용카드와 PayPal을 모두 제공합니다. Braintree의 통합 API는 하나의 통합으로 이 두 가지를 모두 처리할 수 있음을 의미합니다. 동일한 고객 객체가 모든 결제 수단에서 작동합니다.
결론
배운 내용은 다음과 같습니다:
- Braintree SDK는 서버 측 결제 처리를 담당합니다
- 클라이언트 토큰은 프런트엔드 통신을 승인합니다
- 거래 판매는 신용카드와 PayPal을 청구합니다
- 구독은 정기 결제를 처리합니다
- 웹훅은 결제 이벤트에 대해 알려줍니다
- 서비스 출시 전 Apidog로 철저히 테스트하세요
자주 묻는 질문
결제 수단 논스(nonce)란 무엇인가요?
논스(nonce)는 결제 수단을 나타내는 일회용 토큰입니다. 고객이 카드 정보를 입력한 후 프런트엔드에서 생성됩니다. 서버는 이 논스를 사용하여 카드를 청구합니다. 논스는 3시간 후에 만료됩니다.
승인(authorization)과 정산(settlement)의 차이점은 무엇인가요?
승인은 카드에 자금을 예약합니다. 정산은 실제로 카드를 청구합니다. 기본적으로 Braintree는 자동 정산됩니다. 사전 주문의 경우, 먼저 승인한 다음 배송 시 정산합니다:
// 승인만
await gateway.transaction.sale({
amount: '99.00',
paymentMethodNonce: nonce,
options: {
submitForSettlement: false // 승인만
}
})
// 나중에 정산
await gateway.transaction.submitForSettlement('transaction_id')
통화는 어떻게 처리하나요?
각 Braintree 판매자 계정에는 기본 통화가 있습니다. 다중 통화는 여러 판매자 계정을 필요로 합니다. 다중 통화 설정에 대해서는 Braintree 지원팀에 문의하세요.
어떤 테스트 카드 번호를 사용해야 하나요?
Braintree는 샌드박스에서 테스트 카드를 제공합니다:
4111111111111111- Visa (성공)4000111111111115- Visa (거절)5555555555554444- Mastercard (성공)378282246310005- Amex (성공)
분쟁/차지백은 어떻게 처리하나요?
dispute_opened, dispute_won, dispute_lost 웹훅을 수신하세요. Braintree 제어판을 통해 증거를 제공하세요. 고객 커뮤니케이션, 배송 확인, 서비스 약관 등 모든 것을 문서화하세요.
신용카드 번호를 저장할 수 있나요?
아니요. PCI 규정 준수는 원시 카드 번호 저장을 금지합니다. 대신 결제 수단 토큰을 저장하세요. Braintree가 PCI 범위를 처리합니다.
3D Secure란 무엇인가요?
3D Secure는 카드 부재 거래에 대한 추가 인증 단계를 추가합니다. Braintree는 이를 지원합니다. 제어판에서 활성화하고 authentication_required 응답을 처리하세요:
const result = await gateway.transaction.sale({
amount: '100.00',
paymentMethodNonce: nonce,
threeDSecure: {
required: true
}
})
환불에는 얼마나 걸리나요?
환불은 일반적으로 영업일 기준 3-5일 이내에 처리됩니다. 시간은 고객의 은행에 따라 다릅니다. 완료되면 transaction_refunded 웹훅을 수신하게 됩니다.
