PayPal
PayPal payment integration — accept card payments and PayPal wallet payments globally.
Installation
npm install @foxses/pay-paypal
How It Works
PayPal uses OAuth 2.0 + Orders API v2:
- Get Token — exchange clientId/clientSecret for OAuth token (auto-handled)
- Create Order — POST to PayPal → get approval
checkoutUrl - Redirect user to PayPal checkout
- User approves payment on PayPal
- Capture — foxses-pay automatically captures after redirect
- Verify — retrieve order to confirm completion
Configuration
gateway.use("paypal", {
clientId: "YOUR_CLIENT_ID", // required
clientSecret: "YOUR_CLIENT_SECRET", // required
successUrl: "https://yoursite.com/success", // required
failureUrl: "https://yoursite.com/cancel", // required
sandbox: true, // true = sandbox, false = production
});
| Field | Type | Description |
|---|---|---|
clientId | string | PayPal app Client ID |
clientSecret | string | PayPal app Client Secret |
successUrl | string | Redirect after user approves |
failureUrl | string | Redirect when user cancels |
sandbox | boolean | true = sandbox, false = production |
Getting Credentials
- Go to developer.paypal.com
- Apps & Credentials → Create App
- Copy Client ID and Client Secret
- Use Sandbox credentials for testing, Live for production
Create Payment
const payment = await gateway.createPayment("paypal", {
amount: 29.99,
currency: "USD",
orderId: "ORDER-001",
customerEmail: "user@example.com", // optional
});
Response:
{
transactionId: "8MD12345XY678901A", // PayPal Order ID
provider: "paypal",
amount: 29.99,
currency: "USD",
status: "pending",
checkoutUrl: "https://www.sandbox.paypal.com/checkoutnow?token=8MD12345XY678901A",
}
Verify Payment
Call after PayPal redirects to your successUrl with ?token=ORDER_ID:
// successUrl receives: /success?token=8MD12345XY678901A&PayerID=XXXXX
const orderId = req.query.token as string;
const result = await gateway.verifyPayment("paypal", {
transactionId: orderId,
});
console.log(result.status); // "completed"
console.log(result.transactionId); // capture ID (for refunds)
Get Payment Status
const status = await gateway.getPaymentStatus("paypal", "ORDER_ID");
Refund Payment
Requires Capture ID — from verifyPayment response transactionId.
// Full refund
const refund = await gateway.refundPayment("paypal", {
transactionId: "CAPTURE_ID",
});
// Partial refund
const refund = await gateway.refundPayment("paypal", {
transactionId: "CAPTURE_ID",
amount: 15.00,
reason: "Customer requested",
});
Status Mapping
| PayPal Status | foxses-pay Status |
|---|---|
CREATED | pending |
SAVED | pending |
APPROVED | pending |
COMPLETED | completed |
VOIDED | cancelled |
PAYER_ACTION_REQUIRED | pending |
Webhook Handling
app.post("/paypal/webhook", express.json(), async (req, res) => {
const { event_type, resource } = req.body;
if (event_type === "PAYMENT.CAPTURE.COMPLETED") {
const orderId = resource.supplementary_data?.related_ids?.order_id;
await fulfillOrder(orderId);
}
res.sendStatus(200);
});
Supported Currencies
PayPal supports 25+ currencies. Common ones:
| Currency | Code |
|---|---|
| US Dollar | USD |
| Euro | EUR |
| British Pound | GBP |
| Canadian Dollar | CAD |
| Australian Dollar | AUD |
Full list: developer.paypal.com/docs/reports/reference/currencies
Test Accounts (Sandbox)
- Go to developer.paypal.com → Sandbox → Accounts
- Use the pre-created buyer sandbox account to test payments