Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.4 KiB
@suaveplan/payment-provider-paypal - PayPal payment provider for @suaveplan/payment-providers. Implements the PaymentProvider interface against the PayPal Orders v2 + Payments Captures Refund APIs, with an OAuth2 client-credentials token cache, injectable now/base64Encode/FetchLike seams, sandbox-endpoint shortcut, MoneyLike bigint marshalling, and structured PaymentProviderError surfaces. Universal — runs unchanged on Node, Bun, browsers, and Web Workers.
PayPal sibling adapter for the slim
@suaveplan/payment-providers foundation.
Ships PayPalProvider — a PaymentProvider implementation against the
PayPal Orders v2 + Payments Captures Refund APIs, with an OAuth2
client-credentials token cache, injectable now / base64Encode /
FetchLike seams, a sandbox shortcut, MoneyLike bigint marshalling,
and structured PaymentProviderError surfaces. Universal — runs
unchanged on Node, Bun, browsers, and Web Workers.
Documentation tree
- paypal —
PayPalProvideris the PayPal-flavoured implementation of thePaymentProvidercontract exported by `@suaveplan/payme…
Install
bun add @suaveplan/payment-provider-paypal @suaveplan/payment-providers @suaveplan/payment
Quick start
import { ProviderRegistry } from "@suaveplan/payment-providers";
import { PayPalProvider } from "@suaveplan/payment-provider-paypal";
const registry = new ProviderRegistry();
registry.register(
new PayPalProvider({
clientId: process.env.PAYPAL_CLIENT_ID ?? "",
clientSecret: process.env.PAYPAL_CLIENT_SECRET ?? "",
sandbox: true,
})
);
const paypal = registry.get("paypal");
const intent = await paypal.createIntent({
amount: { amount: 5000n, currency: "USD" },
description: "Order #1234",
captureMethod: "automatic",
idempotencyKey: "order-1234",
});
console.log(intent.id, intent.status);
Features
class PayPalProvider implements PaymentProviderwith literal-typedname: "paypal"- OAuth2 client-credentials token cache with 60 s clock-skew buffer, refreshed transparently on expiry
- Injectable
now: NowFn,base64Encode: Base64EncodeFn, andfetch: FetchLikefor universal determinism and testability sandboxflag →https://api-m.sandbox.paypal.com; explicitbaseUrlalways winsMoneyLikebigint minor-unit amounts marshalled to PayPal's major-unit decimal-string formatPayPal-Request-Ididempotency-header support oncreateIntentandrefund- Exhaustive PayPal-status →
PaymentStatus/RefundStatusmapping; unknown statuses map tofailed - Structured
PaymentProviderError(from@suaveplan/payment-providers) on every failure path —OAUTH_TOKEN_FAILURE,HTTP_ERROR,TIMEOUT,PARSE_ERROR— always withprovider: "paypal" - Universal: zero Node / browser / React imports;
sideEffects: false - 100% Istanbul coverage; sibling
.mdper implementation file
Modules
src/paypal/paypal.md—PayPalProviderclass,PayPalConfiginterface, lifecycle methods, OAuth token cachesrc/paypal/mapping.md— pure helpers:mapStatus,mapRefundStatus,parseAmount,formatAmount,mapOrder
Foundation
This package depends on
@suaveplan/payment-providers for:
httpRequest,composeAbortSignal,FetchLikeOAuthConfig,NowFn,Base64EncodeFnPaymentProviderError,PAYMENT_PROVIDER_CODES,oauthTokenFailure
and on @suaveplan/payment for the structural
PaymentProvider, PaymentIntent, Refund, PaymentStatus,
RefundStatus, CreatePaymentIntentInput, and RefundInput types.
Related sibling packages
@suaveplan/payment-provider-stripe@suaveplan/payment-provider-square@suaveplan/payment-provider-mollie@suaveplan/payment-provider-adyen
All four follow the same pattern: depend on the slim core, expose a
single *Provider class, register cleanly into ProviderRegistry.
License
MIT