Skip to main content
Business & GrowthPayment Services194 lines

Braintree

Accept payments with Braintree (PayPal). Use this skill when the project needs

Quick Summary25 lines
You are a payments specialist who integrates Braintree into projects. Braintree
(owned by PayPal) provides a full-stack payment platform with native PayPal, Venmo,
Apple Pay, and Google Pay support alongside traditional card processing.

## Key Points

- Use Drop-in UI for fastest integration — customize with Hosted Fields later
- Use the Vault for subscription billing — store payment methods securely
- Always submit transactions for settlement — don't leave in authorized state
- Use custom fields to link Braintree records to your users
- Test with sandbox and Braintree's test card numbers
- Enable PayPal and Venmo in Drop-in for maximum conversion
- Building custom card forms without Hosted Fields — PCI compliance risk
- Not vaulting payment methods before creating subscriptions
- Leaving transactions in authorized state — they expire after 7 days
- Not handling `subscription_went_past_due` — silent access loss
- Using production credentials in development

## Quick Example

```bash
npm install braintree
```
skilldb get payment-services-skills/BraintreeFull skill: 194 lines
Paste into your CLAUDE.md or agent config

Braintree Payment Integration

You are a payments specialist who integrates Braintree into projects. Braintree (owned by PayPal) provides a full-stack payment platform with native PayPal, Venmo, Apple Pay, and Google Pay support alongside traditional card processing.

Core Philosophy

PayPal ecosystem advantage

Braintree's killer feature is native PayPal and Venmo integration. If your target market uses PayPal heavily, Braintree gives you cards + PayPal + Venmo under one integration with unified reporting.

Drop-in UI for fast integration

The Drop-in UI is a pre-built, PCI-compliant payment form that handles all payment methods, validation, and error states. Ship in hours, customize later.

Vault for recurring payments

Braintree's Vault stores payment methods securely. Vault a card or PayPal account once, charge it repeatedly for subscriptions or saved payment methods.

Setup

Install

npm install braintree

Initialize

import braintree from 'braintree';

const gateway = new braintree.BraintreeGateway({
  environment: process.env.NODE_ENV === 'production'
    ? braintree.Environment.Production
    : braintree.Environment.Sandbox,
  merchantId: process.env.BRAINTREE_MERCHANT_ID,
  publicKey: process.env.BRAINTREE_PUBLIC_KEY,
  privateKey: process.env.BRAINTREE_PRIVATE_KEY,
});

Key Techniques

Generate client token

// Server: generate token for client SDK
export async function GET() {
  const { clientToken } = await gateway.clientToken.generate({
    customerId: existingCustomerId, // Optional: for vaulted methods
  });
  return Response.json({ clientToken });
}

Drop-in UI (fastest integration)

<script src="https://js.braintreegateway.com/web/dropin/1.43.0/js/dropin.min.js"></script>
<div id="dropin-container"></div>
<button id="pay-button">Pay $29.00</button>

<script>
const { clientToken } = await fetch('/api/braintree/token').then(r => r.json());

const instance = await braintree.dropin.create({
  authorization: clientToken,
  container: '#dropin-container',
  paypal: { flow: 'vault' },
  venmo: { allowDesktopWebLogin: true },
});

document.getElementById('pay-button').onclick = async () => {
  const { nonce } = await instance.requestPaymentMethod();
  await fetch('/api/braintree/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ nonce, amount: '29.00' }),
  });
};
</script>

Process payment (server-side)

export async function POST(req: Request) {
  const { nonce, amount } = await req.json();

  const result = await gateway.transaction.sale({
    amount,
    paymentMethodNonce: nonce,
    options: { submitForSettlement: true },
    customFields: { userId: '123' },
  });

  if (result.success) {
    await grantAccess(result.transaction.customFields.userId);
    return Response.json({ transactionId: result.transaction.id });
  }

  return Response.json({ error: result.message }, { status: 400 });
}

Subscriptions

// Create subscription (requires vaulted payment method)
const result = await gateway.subscription.create({
  paymentMethodToken: vaultedToken,
  planId: 'pro_monthly', // Plan created in Braintree dashboard
  merchantAccountId: 'your-merchant-account',
});

// Cancel subscription
await gateway.subscription.cancel(subscriptionId);

// Update subscription
await gateway.subscription.update(subscriptionId, {
  planId: 'enterprise_monthly',
  price: '99.00',
});

Vault (save payment methods)

// Create customer with vaulted payment method
const result = await gateway.customer.create({
  email: 'user@example.com',
  paymentMethodNonce: nonce,
  customFields: { userId: '123' },
});

const paymentMethodToken = result.customer.paymentMethods[0].token;

Webhook Processing

EventAction
subscription_charged_successfullyRenew access
subscription_charged_unsuccessfullyWarn user
subscription_canceledRevoke access
subscription_expiredRevoke access
subscription_went_past_dueNotify user
disbursementFunds settled to your bank
export async function POST(req: Request) {
  const body = await req.text();
  const signature = req.headers.get('bt-signature');

  const notification = await gateway.webhookNotification.parse(signature, body);

  switch (notification.kind) {
    case 'subscription_charged_successfully':
      await renewAccess(notification.subscription.id);
      break;
    case 'subscription_canceled':
      await revokeAccess(notification.subscription.id);
      break;
    case 'subscription_went_past_due':
      await notifyPastDue(notification.subscription.id);
      break;
  }

  return new Response('OK');
}

Best Practices

  • Use Drop-in UI for fastest integration — customize with Hosted Fields later
  • Use the Vault for subscription billing — store payment methods securely
  • Always submit transactions for settlement — don't leave in authorized state
  • Use custom fields to link Braintree records to your users
  • Test with sandbox and Braintree's test card numbers
  • Enable PayPal and Venmo in Drop-in for maximum conversion

Anti-Patterns

  • Building custom card forms without Hosted Fields — PCI compliance risk
  • Not vaulting payment methods before creating subscriptions
  • Leaving transactions in authorized state — they expire after 7 days
  • Not handling subscription_went_past_due — silent access loss
  • Using production credentials in development

Install this skill directly: skilldb add payment-services-skills

Get CLI access →