From 163efafa81f8ac04838c8834500cc296f0db06e9 Mon Sep 17 00:00:00 2001 From: alec <93971719+0xAlec@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:24:09 -0500 Subject: [PATCH] docs: `Checkout` polish (#1690) --- site/docs/pages/checkout/checkout.mdx | 186 ++++++++++++++------------ 1 file changed, 98 insertions(+), 88 deletions(-) diff --git a/site/docs/pages/checkout/checkout.mdx b/site/docs/pages/checkout/checkout.mdx index 527dd058ef..0dcf8ba474 100644 --- a/site/docs/pages/checkout/checkout.mdx +++ b/site/docs/pages/checkout/checkout.mdx @@ -8,7 +8,7 @@ import App from '../../components/App'; # `` -The `Checkout` component provides a one-click checkout experience for onchain commerce. +The `Checkout` component provides a one-click checkout experience for onchain commerce - all for free. Our all-in-one solution simplifies payment processing for onchain developers, removing complex integrations, high fees, and onboarding friction. Whether you're selling digital goods, services, or in-game items, this tool is for you. @@ -20,12 +20,15 @@ Our all-in-one solution simplifies payment processing for onchain developers, re - **Plug-and-Play Integration:** Add our `Checkout` button with just a few lines of code. No backend required. - **Seamless Onboarding:** Support Passkey wallets to eliminate onboarding drop-offs. - **Real-time Merchant Tooling:** Get instant payment tracking, analytics, and reporting. +- **Dynamic Payment Flows:** Generate charges on the fly, handle variable pricing, and pass in custom metadata. ## Prerequisites Before using the `Checkout` component, ensure you've completed the [Getting Started](/getting-started) steps. -To use the `Checkout` component, you'll need to provide an API Key in `OnchainKitProvider`. You can get one following our [Getting Started](/getting-started#get-your-public-api-key) steps. +::::tip +To use the `Checkout` component, you'll need to provide a Client API Key in `OnchainKitProvider`. You can get one following our [Getting Started](/installation/nextjs#get-your-client-api-key) steps. +::::: ### Starting a new project @@ -63,18 +66,15 @@ Wrap the `` around your app, following the steps in [Getti ## Quickstart +### Option 1: Simple Product Checkout +Ideal for fixed-price items. Get started with minimal setup. + ::::steps ### Sign up for a Coinbase Commerce account -Create a product Head to [Coinbase Commerce](https://beta.commerce.coinbase.com/) and sign up. This is where you’ll manage transactions, view reports, and configure payments. ### Create a product and copy the `productId` - Copy productId In the Coinbase Commerce dashboard, create a new product and copy the `productId`. ### Import the component @@ -89,17 +89,44 @@ import { Checkout, CheckoutButton, CheckoutStatus } from '@coinbase/onchainkit/c ``` :::: +### Option 2: Dynamic Charges +For variable pricing, custom metadata, or multi-product checkouts, use backend-generated charges. + +::::steps + +### Sign up for a Coinbase Commerce account +Head to [Coinbase Commerce](https://beta.commerce.coinbase.com/) and sign up. This is where you’ll manage transactions, view reports, and configure payments. + +### Create a Coinbase Commerce API Key +In the [Coinbase Commerce dashboard](https://beta.commerce.coinbase.com/settings/security), create a new API Key under `Security` in `Settings`. + +### Set up a backend to create charges dynamically using the Coinbase Commerce API. +See [Using chargeHandler](/checkout/checkout#using-chargehandler) for a code example. + +### Pass the chargeID into Checkout via the chargeHandler prop. + +```tsx +const chargeHandler = async () => { + const response = await fetch('/createCharge', { method: 'POST' }); + const { id } = await response.json(); + return id; // Return charge ID +}; + + + + +``` +:::: + That's it! Starting selling onchain with just a few lines of code. ## Usage ### Configuring a checkout -You can create products on the Coinbase Commerce Portal and use them in the `Checkout` component through the `productId` prop. - -If you'd like to create product metadata programmatically or implement a multi-product checkout, please see [Advanced Usage](/checkout/checkout#advanced-usage). +#### Using `productId` -Coinbase Commerce charges a [1% fee](https://help.coinbase.com/en/commerce/getting-started/fees) associated with all payments. +You can create products on the Coinbase Commerce Portal and use them in the `Checkout` component through the `productId` prop. ```tsx twoslash import { Checkout, CheckoutButton } from '@coinbase/onchainkit/checkout'; @@ -121,6 +148,63 @@ export default function PayComponents() { +#### Using `chargeHandler` + +Alternatively, you can create charges dynamically using the Coinbase Commerce API [Create Charge](https://docs.cdp.coinbase.com/commerce-onchain/reference/creates-a-charge) endpoint by passing the chargeID into Checkout via the `chargeHandler` prop. + +This function must have the signature `() => Promise` and must return a valid chargeId created by the create charge endpoint. + +:::tip +To create charges, you'll need a Coinbase Commerce [API Key](https://docs.cdp.coinbase.com/commerce-onchain/docs/getting-started). +::: + +:::danger[⚠️ Warning] +You should protect your Coinbase Commerce API Key by only creating charges server-side. +::: + +:::code-group +```ts [backend.ts] +// This backend endpoint should create a charge and return the response. +app.post('/createCharge', async (req: Request, res: Response) => { + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'X-CC-Api-Key': 'your_api_key_here' // Replace this with your Coinbase Commerce API Key + }, + body: JSON.stringify({ + local_price: { amount: '1', currency: 'USDC' }, + pricing_type: 'fixed_price', + metadata: { some_field: "some_value" } // Optional: Attach metadata like order ID or customer details + }), + }; + + const response = await fetch('https://api.commerce.coinbase.com/charges', options); + const data = await response.json(); + + res.json(data); +}); + +``` + +```tsx twoslash [frontend.tsx] +import { Checkout, CheckoutButton } from '@coinbase/onchainkit/checkout'; + +const chargeHandler = async () => { + const response = await fetch('https://your-backend.com/createCharge', { method: 'POST' }); + const { id } = await response.json(); + return id; // Return charge ID +}; + + + + +``` +::: + +Note that `productId` and `chargeHandler` are mutually exclusive and only one can be provided as a prop to Checkout. + ### Handling a successful checkout To handle successful checkouts, use the `onStatus` prop to listen for the `success` callback. @@ -163,8 +247,8 @@ const statusHandler = async (status: LifecycleStatus) => { // [!code focus] // ---cut-after--- ``` -:::tip[Coinbase Commerce API] -This is an authenticated endpoint. To verify charges, you'll need a Coinbase Commerce [API Key](https://docs.cdp.coinbase.com/commerce-onchain/docs/getting-started). +:::tip +To verify charges, you'll need a Coinbase Commerce [API Key](https://docs.cdp.coinbase.com/commerce-onchain/docs/getting-started). ::: :::danger[⚠️ Warning] @@ -313,80 +397,6 @@ export default function PayComponents() { ## Advanced Usage -### Shopping Carts and Multi-Product Checkout - -You can accept payments for arbitrary product metadata using the Coinbase Commerce [create charge](https://docs.cdp.coinbase.com/commerce-onchain/reference/creates-a-charge) endpoint. This is useful if you have an existing inventory management system or want to implement custom features like multi-product checkouts, carts, etc. - -:::tip[Coinbase Commerce API] -This is an authenticated endpoint. To create charges, you'll need a Coinbase Commerce [API Key](https://docs.cdp.coinbase.com/commerce-onchain/docs/getting-started). -::: - -#### Example server side code - -This Typescript example uses [Express](https://expressjs.com/) and [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). - -```tsx twoslash [server.ts] -import express, { Request, Response } from 'express'; -const fetch = require('node-fetch'); - -const app = express(); -const port = 3000; - -app.use(express.json()); - -// ---cut-before--- -// This endpoint should create a charge and return the response. -app.post('/createCharge', async (req: Request, res: Response) => { - const options = { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'X-CC-Api-Key': 'your_api_key_here' // Replace this with your Coinbase Commerce API Key - } - }; - - const response = await fetch('https://api.commerce.coinbase.com/charges', options); - const data = await response.json(); - - res.json(data); -}); -// ---cut-after--- -app.listen(port, () => { - console.log(`Server running at http://localhost:${port}`); -}); -``` - -:::danger[⚠️ Warning] -Charges should only be created server-side. If you create charges on the client, users will be able to create charges associated with your Commerce Merchant account. -::: - -We expose a `chargeHandler` prop on the `Checkout` component which takes a callback that is invoked every time the Checkout button is clicked. - -This function **must** have the signature `() => Promise` and **must** return a valid `chargeId` created by the create charge endpoint. - -Note that `productId` and `chargeHandler` are mutually exclusive and only one can be provided as a prop to `Checkout`. - -```tsx twoslash -import { Checkout, CheckoutButton } from '@coinbase/onchainkit/checkout'; - - -// ---cut-before--- -const chargeHandler = async () => { // [!code focus] - // Create a charge on your backend server using the Create Charge API // [!code focus] - // Replace this URL with your backend endpoint // [!code focus] - const res = await fetch('api.merchant.com/createCharge'); // [!code focus] - const data = await res.json(); // [!code focus] - return data.id; // Return the chargeId // [!code focus] -} // [!code focus] - - // [!code focus] - - -// ---cut-after--- -``` - - ### Listening to the component lifecycle You can use our Checkout [`LifecycleStatus`](/checkout/types#lifecyclestatus) and the `onStatus` prop to listen to transaction states.