PayPal integration usually means the Orders API for one-off payments or Subscriptions for recurring billing. The server creates and captures the order; the browser only approves it. Webhooks keep your database in sync.
Key takeaways
- Create the order on the server with the amount and currency you control.
- The client approves; the server captures and verifies the result.
- Use the sandbox and test both success and failure paths.
- Prefer the simplest boundary that keeps data and authorisation on the server.
What matters in practice
- Webhooks handle asynchronous events such as refunds and disputes.
- PayPal supports multiple currencies, but your pricing and settlement currency need a deliberate policy.
How to implement it
- Create a sandbox app. Get the client ID and secret for the sandbox environment.
- Create the order. Resolve the cart server-side and create the order with the correct currency.
- Approve on the client. Render the PayPal button and capture the approval.
- Capture on the server. Verify the order status and amount before fulfilling.
- Subscribe to webhooks. Verify the signature and handle refunds, disputes and subscription changes.
- Test. Declines, cancelled approvals, duplicate captures and currency mismatches.
A working example
// Server route: create an order
const response = await fetch("https://api-m.paypal.com/v2/checkout/orders", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Basic ${Buffer.from(`${id}:${secret}`).toString("base64")}`,
},
body: JSON.stringify({
intent: "CAPTURE",
purchase_units: [{ amount: { currency_code: "GBP", value: total } }],
}),
});
Production checklist
| Area | Check |
|---|---|
| Environment | Sandbox and live credentials separated |
| Amount | Resolved server-side and matched at capture |
| Currency | Pricing and settlement policy defined |
| Webhook | Signature verification and idempotency |
| Testing | Declines, cancellations, duplicates and refunds |
| Reconciliation | Daily check between PayPal and your orders |
Common mistakes
- Capturing an amount sent by the client.
- Fulfilling before verifying the capture response.
- Using the live environment for testing.
- Ignoring currency conversion and settlement fees.
When this is the wrong tool
Every tool has a boundary. If the team is small, the use case is simple and the operational cost is high, a simpler stack may be better. The right choice is the one you can debug, secure and hand over without the original author.
Rollout plan
- Prove one slice. Use PayPal integration for one real route or feature, not the whole product.
- Set the boundary. Write down what stays on the server, what runs on the client and how data crosses the boundary.
- Add the safety net. Types, validation, tests and error handling around the new slice.
- Measure. Check bundle size, latency, error rate and the developer experience before expanding.
- Document and hand over. Record the pattern, the pitfalls and the version constraints.
Testing strategy
| Layer | What to test | Why |
|---|---|---|
| Types | Strict compile and no unjustified any | Catches contract drift early |
| Unit | Pure logic, validation and state transitions | Fast feedback |
| Integration | API, database and auth boundaries | Most production failures live here |
| End-to-end | The critical user journey | Proves the wiring |
| Operations | Logs, errors, retries and rollback | A release is not finished at deploy |
Operational checklist
- Pin the runtime and dependency versions; test upgrades in a branch.
- Keep secrets on the server and validate every external payload.
- Add structured logs with a request ID, but never log tokens or personal data.
- Set a performance or bundle budget and check it in CI.
- Write a short runbook for the most likely failure.
Frequently asked questions
Stripe often gives more control over the checkout UI and a broader product suite. PayPal can be useful when your customers prefer it or you need a specific market. Both should be server-verified.
Yes for refunds, disputes, subscription changes and reliable fulfilment. The capture response is not enough for every asynchronous event.
Yes. Use the Subscriptions API, store the subscription ID and handle the webhook events. Test plan changes and failed payments.
Refund through the API or dashboard and update your order state from the webhook. Reconcile the refund against the original capture.
Sources and further reading
- PayPal REST APIs (developer.paypal.com)
- PayPal webhooks (developer.paypal.com)
- PCI Security Standards Council (pcisecuritystandards.org)
Related reading
Need an implementation review?
Send the repository or the design. I will review the boundary, the failure modes and the parts that will be expensive to change later.
How to cite this guide: Nur Hossain Repon, “PayPal integration: complete developer guide (2026)”, Nhrepon Portfolio, reviewed October 2026, https://nhrepon.com/posts/paypal-integration-complete-developer-guide-2026.





Comments
No comments yet.