PayPal
Integrate PayPal payments with proper webhook verification, OAuth handling, and security validation for checkout flows and subscriptions.
MIT-0 · Free to use, modify, and redistribute. No attribution required.
⭐ 0 · 538 · 5 current installs · 5 all-time installs
byIván@ivangdavila
MIT-0
Security Scan
OpenClaw
Suspicious
medium confidencePurpose & Capability
The name/description and instructions are consistent with a PayPal integration. However, the skill does not declare any required environment variables or primary credential even though the SKILL.md and code patterns repeatedly reference clientId, secret, WEBHOOK_ID, YOUR_MERCHANT_ID, and an access token. That omission is disproportionate and unexplained.
Instruction Scope
The runtime instructions stay within PayPal integration scope (OAuth token management, webhook verification, order capture, subscriptions, dispute handling). They reference DB operations (db.webhooks, db.orders) and external tooling (ngrok) which are reasonable for server integration, but the instructions assume a datastore and secret configuration that the skill metadata does not request.
Install Mechanism
Instruction-only skill with no install spec and no code files — lowest install risk. Nothing is downloaded or written to disk by the skill package itself.
Credentials
The content requires sensitive values (PayPal client ID and secret, webhook_id, merchant ID, likely DB credentials) but the registry entry lists no required environment variables or primary credential. That mismatch makes it unclear what the operator must provide and where secrets will be used, increasing risk of misconfiguration or accidental leakage.
Persistence & Privilege
The skill is not always-included and does not request persistent system privileges. Autonomous invocation (model can call the skill) is allowed but is platform default and not by itself alarming here.
What to consider before installing
This skill contains detailed, standard PayPal integration guidance, but the package metadata omits the credentials and config it actually needs. Before installing or using it: 1) Ask the publisher for the source code or homepage and a list of required environment variables (client ID, client secret, WEBHOOK_ID, merchant ID, DB connection info). 2) Do not paste secrets into chat — store PayPal credentials in a secure secret store and bind them only to the runtime you control. 3) Verify webhook verification is implemented exactly as shown (verify-webhook-signature) and point webhooks to an authenticated, HTTPS endpoint. 4) Confirm how the skill expects to access your database (what DB, schema, and credentials) and restrict those credentials to minimal privileges. 5) Prefer testing in PayPal sandbox(s) before production. If the publisher updates the registry metadata to explicitly declare the required env vars and credential scope, and provides a trusted source or repo, re-evaluate — that would reduce the concerns.Like a lobster shell, security has layers — review code before you run it.
Current versionv1.0.0
Download ziplatest
License
MIT-0
Free to use, modify, and redistribute. No attribution required.
Runtime requirements
💳 Clawdis
OSLinux · macOS · Windows
SKILL.md
When to Use
User needs to integrate PayPal REST API for payments, subscriptions, or payouts. Agent handles checkout flows, webhook verification, OAuth token management, and dispute workflows.
Quick Reference
| Topic | File |
|---|---|
| Code patterns | patterns.md |
| Webhook events | webhooks.md |
Core Rules
1. Environment URLs are Different
- Sandbox:
api.sandbox.paypal.com - Production:
api.paypal.com - Ask which environment BEFORE generating code
- Credentials are environment-specific — never mix
2. OAuth Token Management
// Token expires ~8 hours — handle refresh
const getToken = async () => {
const res = await fetch('https://api.paypal.com/v1/oauth2/token', {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(`${clientId}:${secret}`).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'grant_type=client_credentials'
});
return res.json(); // { access_token, expires_in }
};
Never hardcode tokens. Implement refresh logic.
3. Webhook Verification is Mandatory
PayPal webhooks MUST be verified via API call — not simple HMAC:
// POST /v1/notifications/verify-webhook-signature
const verification = await fetch('https://api.paypal.com/v1/notifications/verify-webhook-signature', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
auth_algo: headers['paypal-auth-algo'],
cert_url: headers['paypal-cert-url'],
transmission_id: headers['paypal-transmission-id'],
transmission_sig: headers['paypal-transmission-sig'],
transmission_time: headers['paypal-transmission-time'],
webhook_id: WEBHOOK_ID,
webhook_event: body
})
});
// verification_status === 'SUCCESS'
4. CAPTURE vs AUTHORIZE — Ask First
| Intent | Behavior |
|---|---|
CAPTURE | Charges immediately on approval |
AUTHORIZE | Reserves funds, capture later (up to 29 days) |
Changing intent after integration breaks the entire flow.
5. Server-Side Validation — Never Trust Client
// After client approves, VERIFY on server before fulfillment
const order = await fetch(`https://api.paypal.com/v2/checkout/orders/${orderId}`, {
headers: { 'Authorization': `Bearer ${token}` }
}).then(r => r.json());
// Validate ALL of these:
if (order.status !== 'APPROVED') throw new Error('Not approved');
if (order.purchase_units[0].amount.value !== expectedAmount) throw new Error('Amount mismatch');
if (order.purchase_units[0].amount.currency_code !== expectedCurrency) throw new Error('Currency mismatch');
if (order.purchase_units[0].payee.merchant_id !== YOUR_MERCHANT_ID) throw new Error('Wrong merchant');
6. Idempotency in Webhooks
PayPal may send the same webhook multiple times:
const processed = await db.webhooks.findOne({ eventId: body.id });
if (processed) return res.status(200).send('Already processed');
await db.webhooks.insert({ eventId: body.id, processedAt: new Date() });
// Now process the event
7. Currency Decimal Rules
Some currencies have NO decimal places:
| Currency | Decimals | Example |
|---|---|---|
| USD, EUR | 2 | "10.50" |
| JPY, TWD | 0 | "1050" (NOT "1050.00") |
Sending "10.50" for JPY = API error.
Common Traps
- IPN vs Webhooks — IPN is legacy. Use Webhooks for new integrations. Never mix.
- Order states — CREATED → APPROVED → COMPLETED (or VOIDED). Handle ALL states, not just happy path.
- Decimal confusion — PayPal uses strings for amounts ("10.50"), not floats. Some currencies forbid decimals.
- Sandbox rate limits — Lower than production. Don't assume prod will fail the same way.
- Payout vs Payment — Payouts API is separate. Don't confuse sending money (Payouts) with receiving (Orders).
Files
3 totalSelect a file
Select a file to preview.
Comments
Loading comments…
