@plantagoai/payments
Braintree payment processing, Apple Pay, Google Pay, and subscription lifecycle management.
Consumers: Foundation, MarketHub
Installation
"@plantagoai/payments": "file:../../shared/packages/payments"
Exports
| Entry Point | Description |
|---|---|
@plantagoai/payments |
Server-side: Braintree gateway, payment processing, subscriptions |
@plantagoai/payments/client |
Client-side: Drop-in UI, Apple Pay / Google Pay checks |
Server-Side: Braintree Gateway
Create Gateway
import { createGateway } from "@plantagoai/payments";
const gateway = createGateway({
merchantId: process.env.BRAINTREE_MERCHANT_ID,
publicKey: process.env.BRAINTREE_PUBLIC_KEY,
privateKey: process.env.BRAINTREE_PRIVATE_KEY,
sandbox: true, // false for production
});
Generate Client Token
import { getClientToken } from "@plantagoai/payments";
const token = await getClientToken(gateway, "customer-123", "user@example.com");
// Returns token string for client-side Drop-in UI
Process Payment
import { processPayment } from "@plantagoai/payments";
const result = await processPayment(gateway, {
nonce: "tokenization-nonce-from-client",
amount: 29.99,
customerId: "customer-123",
orderId: "order-456", // optional
submitForSettlement: true, // default: true
});
if (result.success) {
console.log("Transaction:", result.transactionId, result.status, result.amount);
} else {
console.error("Payment failed:", result.error);
}
PaymentResult
interface PaymentResult {
success: boolean;
transactionId?: string;
status?: string;
amount?: string;
error?: string;
}
Client-Side: Drop-in UI
Create Drop-in
import { createDropIn, requestPayment, isApplePayAvailable, isGooglePayAvailable } from "@plantagoai/payments/client";
const instance = await createDropIn(clientToken, "#payment-container", {
applePay: {
merchantName: "Foundation",
merchantId: "merchant.com.foundation", // optional
},
googlePay: {
merchantId: "BCR2DN...",
merchantName: "Foundation",
environment: "TEST", // "TEST" | "PRODUCTION"
},
card: {
overrides: { /* Braintree field overrides */ },
},
vaultManager: false,
threeDSecure: false,
});
Request Payment Nonce
const { nonce, type } = await requestPayment(instance);
// nonce: "tokencc_bf_..." — send to server for processPayment
// type: "CreditCard" | "ApplePayCard" | "AndroidPayCard" | ...
Check Mobile Pay Availability
if (isApplePayAvailable()) {
// Show Apple Pay option
}
if (isGooglePayAvailable()) {
// Show Google Pay option
}
Teardown
await instance.teardown();
Subscriptions
Activate Trial
import { activateTrial } from "@plantagoai/payments";
const result = await activateTrial("user-123", "pro-monthly", "Pro Plan");
// {
// subscriptionId: "sub_abc...",
// trialDaysRemaining: 14,
// trialEndsAt: "2026-05-01T00:00:00.000Z"
// }
Activate Subscription
import { activateSubscription } from "@plantagoai/payments";
const result = await activateSubscription("user-123", "pro-monthly", "Pro Plan", {
tenantId: "org-1", // optional
aiCredits: 1000, // optional: AI usage credits
});
// { subscriptionId: "sub_abc...", trial: false }
Cancel & Query
import { cancelSubscription, getSubscription } from "@plantagoai/payments";
await cancelSubscription("sub_abc...");
const sub = await getSubscription("user-123");
// {
// id: "sub_abc...",
// userId: "user-123",
// planId: "pro-monthly",
// planName: "Pro Plan",
// status: "active", // "trial" | "active" | "cancelled" | "expired"
// startedAt: Date,
// expiresAt: Date,
// trialEndsAt: Date, // only if trial
// }
Types Reference
GatewayConfig
interface GatewayConfig {
merchantId: string;
publicKey: string;
privateKey: string;
sandbox?: boolean;
}
DropInConfig
interface DropInConfig {
applePay?: { merchantName: string; merchantId?: string };
googlePay?: { merchantId: string; merchantName: string; environment?: "TEST" | "PRODUCTION" };
card?: { overrides?: Record<string, unknown> };
vaultManager?: boolean;
threeDSecure?: boolean;
}
SubscriptionInfo
interface SubscriptionInfo {
id: string;
userId: string;
planId: string;
planName: string;
status: "trial" | "active" | "cancelled" | "expired";
trialEndsAt?: Date;
expiresAt?: Date;
startedAt: Date;
}