# [@root/paypal-checkout](https://git.rootprojects.org/root/paypal-checkout.js) In contrast to the official PayPal Checkout SDK - which is auto-generated code with lots of abstraction without much value - this is very little abstraction, but specificially designed to be (mostly) idiomatic JavaScript / Node.js. \ (excuse the `snake_case` - that's how the PayPal REST API is designed). ![](https://i.imgur.com/brFTseM.png "PayPal Checkout API Flow") Check out with PayPal The Good Documentation™ for the PayPal API (a.k.a. PayPal Checkout SDK) is the "REST API". See - (one-time payments) - (recurring subscriptions) - (the buttons) # Install ```bash npm install --save @root/paypal-checkout ``` # Usage ```js "use strict"; require("dotenv").config({ path: ".env" }); let PPC = require("@root/paypal-checkout"); PPC.init({ client_id: "xxxx", client_secret: "****", }); PPC.Subscriptions.createRequest({ // See https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions }); ``` # API ```txt PayPal.init(client_id, client_secret, 'sandbox|live', defaults); PayPal.request({ method, url, headers, json }); ``` ### Subscrptions (Recurring Payments) ```txt // Webhook 'event_type': PayPal.Product.create({ ... }); // CATALOG.PRODUCT.CREATED PayPal.Product.list(); PayPal.Product.details(id); PayPal.Product.update(id, { description }); // CATALOG.PRODUCT.UPDATED PayPal.Plan.create({ ... }); // BILLING.PLAN.CREATED PayPal.Plan.list(); PayPal.Plan.details(id); PayPal.Plan.update(id, { description }); // BILLING.PLAN.UPDATED PayPal.Subscription.createRequest({ ... }); // BILLING.SUBSCRIPTION.CREATED // subscription.links[rel="approve"].href // BILLING.SUBSCRIPTION.ACTIVATED // PAYMENT.SALE.COMPLETED PayPal.Subscription.details(id); PayPal.Subscription.cancel(id, { reason }); ``` ### Orders (One-Time Payments) ```txt // Webhook 'event_type': PayPal.Order.createRequest({ purchase_units }); // CHECKOUT.ORDER.APPROVED PayPal.Order.capture(id, { final_capture }); // PAYMENT.CAPTURE.COMPLETED ``` See also: - - - # Redirects - `return_url` - `cancel_url` #### `return_url` **_Order_** and **_Subscription_** requests have a return `return_url` will be called with some or all of the following params: ```txt # Order https://example.com/redirects/paypal-checkout/return ?token=XXXXXXXXXXXXXXXXX &PayerID=XXXXXXXXXXXXX ``` - `token` is the **_Order ID_** - `PayerID` is... exactly what it seems (no idea how you can access the Payer object though) ```txt # Subscrption https://example.com/redirects/paypal-checkout/return ?subscription_id=XXXXXXXXXXXXXX &ba_token=BA-00000000000000000 &token=XXXXXXXXXXXXXXXXX ``` - `subscription_id` refers to both the **_Subscription ID_** and the `billing_agreement_id` of the corresponding **_Payments_**. - `ba_token` (deprecated) refers to `/v1/payments/billing-agreements/:ba_token` - `token` refers to the **_Order ID_** (perhaps created as part of the setup fee or first billing cycle payment). #### `cancel_url` The `cancel_url` will have the same query params as the `return_url`. Also, PayPal presents the raw `cancel_url` and will NOT update the order or subscription status. It's up to you to confirm with the user and change the status to `CANCELLED`. # Webhooks Webhooks can be set up in the Application section of the Dashboard: - You'll see a list of applications. Click on one to access the webhooks. **Security**: You must put a `secret` or `token` or your webhook URLs - PayPal provides no measure of authentication (and otherwise an attacker could just send random crap to your webhooks making it look like they've paid for all sorts of things). # Security #### User email addresses Emails addresses available through the PayPal Checkout API guaranteed to have been verified by PayPal. See: - [Is `resource.subscriber.email_address` verified by PayPal?](https://twitter.com/paypaldev/status/1448238655743488008) - [How do I receive money through PayPal?](https://www.paypal.com/us/smarthelp/article/how-do-i-receive-money-through-paypal-faq1750) # Notes My discussions with Twitter Support (@paypaldev): - Note: Just about everything in the PayPal SDK that uses `ALL_CAPS` is a `constant`/`enum` representing an option you can pick from limited number of options. Sandbox accounts (for creating fake purchases) can be managed at: ## Auth vs Capture > Authorization and capture enables you to authorize fund availability but delay > fund capture. This can be useful for merchants who have a delayed order > fulfillment process. Authorize & Capture also enables merchants to change the > original authorization amount in case the order changes due to shipping, > taxes, or gratuity. > > For any payment type, you can capture less than or the full original > authorized amount. You can also capture up to 115% of or $75 USD more than the > original authorized amount, whichever is less. > > See > > - > - You can auth once and capture multiple times (unless you set `final_capture`). ## PayPal Checkout Buttons - <== THE ONE YOU WANT - Check out with PayPal - - # Glossary ## Webhook Event: CHECKOUT.ORDER.APPROVED ```json { "id": "WH-1V203642KU442722T-3S346483MF8733038", "event_version": "1.0", "create_time": "2021-10-17T05:04:22.404Z", "resource_type": "checkout-order", "resource_version": "2.0", "event_type": "CHECKOUT.ORDER.APPROVED", "summary": "An order has been approved by buyer", "resource": { "create_time": "2021-10-17T05:03:26Z", "purchase_units": [ { "reference_id": "{purchase-unit-id}", "amount": { "currency_code": "USD", "value": "10.00" }, "payee": { "email_address": "sb-a9xvi8075587@business.example.com", "merchant_id": "4RXRQC77UD53U", "display_data": { "brand_name": "Bliss via The Root Group, LLC" } }, "description": "1 year of pure Bliss", "custom_id": "{my-local-db-purchase-id}", "soft_descriptor": "Bliss" } ], "links": [ { "href": "https://api.sandbox.paypal.com/v2/checkout/orders/4K5112848U951142F", "rel": "self", "method": "GET" }, { "href": "https://api.sandbox.paypal.com/v2/checkout/orders/4K5112848U951142F", "rel": "update", "method": "PATCH" }, { "href": "https://api.sandbox.paypal.com/v2/checkout/orders/4K5112848U951142F/capture", "rel": "capture", "method": "POST" } ], "id": "4K5112848U951142F", "intent": "CAPTURE", "payer": { "name": { "given_name": "John", "surname": "Doe" }, "email_address": "sb-ka5d18075586@personal.example.com", "payer_id": "YTENGYR8PAF9A", "address": { "country_code": "US" } }, "status": "APPROVED" }, "links": [ { "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1V203642KU442722T-3S346483MF8733038", "rel": "self", "method": "GET" }, { "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-1V203642KU442722T-3S346483MF8733038/resend", "rel": "resend", "method": "POST" } ] } ``` ## Webhook Event: PAYMENT.CAPTURE.COMPLETED ```json { "id": "WH-3UT90572MR669760L-7LL94124G5389840D", "event_version": "1.0", "create_time": "2021-10-17T05:05:03.389Z", "resource_type": "capture", "resource_version": "2.0", "event_type": "PAYMENT.CAPTURE.COMPLETED", "summary": "Payment completed for $ 10.0 USD", "resource": { "amount": { "value": "10.00", "currency_code": "USD" }, "seller_protection": { "dispute_categories": ["ITEM_NOT_RECEIVED", "UNAUTHORIZED_TRANSACTION"], "status": "ELIGIBLE" }, "supplementary_data": { "related_ids": { "order_id": "4K5112848U951142F" } }, "update_time": "2021-10-17T05:04:29Z", "create_time": "2021-10-17T05:04:29Z", "final_capture": true, "seller_receivable_breakdown": { "paypal_fee": { "value": "0.84", "currency_code": "USD" }, "gross_amount": { "value": "10.00", "currency_code": "USD" }, "net_amount": { "value": "9.16", "currency_code": "USD" } }, "custom_id": "{my-local-db-purchase-id}", "links": [ { "method": "GET", "rel": "self", "href": "https://api.sandbox.paypal.com/v2/payments/captures/5VK462069F664902F" }, { "method": "POST", "rel": "refund", "href": "https://api.sandbox.paypal.com/v2/payments/captures/5VK462069F664902F/refund" }, { "method": "GET", "rel": "up", "href": "https://api.sandbox.paypal.com/v2/checkout/orders/4K5112848U951142F" } ], "id": "5VK462069F664902F", "status": "COMPLETED" }, "links": [ { "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-3UT90572MR669760L-7LL94124G5389840D", "rel": "self", "method": "GET" }, { "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-3UT90572MR669760L-7LL94124G5389840D/resend", "rel": "resend", "method": "POST" } ] } ```