Services via PayPal
For uncle-z products that sell services (productized human work) — not digital products. Polar’s AUP rejects services; PayPal accepts them.
When this applies
Section titled “When this applies”- You’re selling time / human work: a dev sprint, a design review, a consulting hour. Examples in scope: book.uncle-z.com.
- Buyer pays in USD/EUR/GBP — not IDR. (For IDR services, use QRIS via NICEPAY.)
If you’re a SaaS / digital product / one-time license, you want Polar instead.
Why PayPal and not Polar / Paddle
Section titled “Why PayPal and not Polar / Paddle”Polar’s Acceptable Use Policy explicitly rejects services. So does Paddle’s. Both are MoR (Merchant of Record) and aggressive about category compliance. Putting service revenue through them risks account freeze + 90-180 day fund hold + AUP flags propagating to other MoR vendors.
PayPal accepts services without category objection. Trade-off: PayPal is NOT a MoR, so:
- VAT / sales tax is the seller’s responsibility (you, not PayPal).
- Disputes go through PayPal’s resolution flow, not a MoR safety net.
- Currency conversion charges are visible to the buyer (PayPal shows the FX cost).
For book.uncle-z.com’s volume + a single-jurisdiction seller, those trade-offs are fine.
Step 1: PayPal setup (operator-side, one-time)
Section titled “Step 1: PayPal setup (operator-side, one-time)”The operator does this once at gateway provisioning. You don’t have to repeat it per product. Listed for context:
- PayPal merchant account exists for uncle-z.
- App registered at developer.paypal.com with the Orders API enabled.
- Webhook subscription created at developer.paypal.com pointing to
https://payment.uncle-z.com/webhooks/paypal. Events:CHECKOUT.ORDER.APPROVED,PAYMENT.CAPTURE.COMPLETED,PAYMENT.CAPTURE.DENIED,PAYMENT.CAPTURE.REFUNDED. - Webhook ID copied into gateway env (
PAYPAL_*_WEBHOOK_ID). The gateway needs this to call PayPal’sverify-webhook-signatureAPI on each inbound delivery.
Step 2: Issue a payment
Section titled “Step 2: Issue a payment”POST /v1/paymentsX-PAY-Key: pk_<your app's public key>X-PAY-Timestamp: <unix seconds>X-PAY-Signature: <hex hmac>Content-Type: application/json
{ "external_user_id": "<your user id>", "email": "buyer@example.com", "amount_minor": 5000, "currency": "USD", "method": "paypal", "return_url": "https://<your-domain>/booking/return?id=...", "invoice_prefix": "BOOK", "metadata": { "service_slug": "lite-engagement", "scope_id": "<your scope id>" }}method=paypal is a method override — wins over currency-based routing. You can use it for any non-IDR currency PayPal supports.
Response:
{ "payment_id": "abc123…", "status": "initiated", "checkout_url": "https://www.sandbox.paypal.com/checkoutnow?token=...", "invoice_number": "BOOK-000042"}Redirect the buyer to checkout_url. PayPal handles the buyer-facing card / wallet UI, including authorization + 3DS.
Step 3: Webhook
Section titled “Step 3: Webhook”PayPal’s signing scheme is async — the gateway POSTs the headers + body to PayPal’s /v1/notifications/verify-webhook-signature endpoint and reads verification_status: "SUCCESS" before accepting. This requires the gateway-side PAYPAL_*_WEBHOOK_ID env to match the webhook subscription’s ID. If it doesn’t, every inbound event 401s.
Your product side just receives the canonical payment.succeeded / payment.failed from the gateway via the standard outbound webhook. Same scheme as every other rail — see Verifying webhooks.
Refunds
Section titled “Refunds”POST /v1/refunds works for PayPal. PayPal supports partial refunds; the gateway forwards amount_minor to PayPal’s capture-refund API. Refund webhook fires refund.succeeded once PayPal confirms.
PayPal-specific quirks:
- Refunds before settlement (within 24h of capture) are free.
- Refunds after settlement carry PayPal’s standard transaction fee on both legs.
- Refund window: ~180 days from capture.
What’s NOT wired today
Section titled “What’s NOT wired today”- PayPal Subscriptions API — the gateway uses the Orders API (one-time charges) only. Subscriptions are a separate PayPal API surface; if you need them, talk to ops.
- PayPal advanced credit card processing (embedded card form on your site) — outside the gateway’s scope. The gateway uses PayPal’s hosted checkout only.