StoreKitdocs
Concepts

Payments

The redirect-and-reconcile payment flow, and how the cart clears itself afterward.

StoreKit uses a hosted redirect payment flow (PhonePe). You never handle card data — you redirect the shopper to the provider and reconcile when they come back.

The flow

Create the checkout. checkout.create() returns a redirectUrl to the payment provider.

Redirect the shopper to redirectUrl.

The provider redirects back to your storefront's return page (configured via STOREFRONT_URL), with ?orderId=... in the URL.

Confirm the order on your return page. The SDK polls/reconciles the payment and tells you success, pending, or failure.

The return URL

The provider needs to know where to send the shopper back. That origin comes from your STOREFRONT_URL (or initStorekit({ baseURL })). The API builds the return URL as <your-origin>/payment/callback?orderId=<id>.

If STOREFRONT_URL is unset, the Next.js adapter warns and payment returns may land on the wrong origin. Always set it in production.

Confirming on the return page

In a Next.js client component, usePaymentConfirmation() does the work:

app/payment/callback/page.tsx
"use client";

import { useSearchParams } from "next/navigation";
import { storefront } from "@/lib/storekit-client";

export default function PaymentCallback() {
  const orderId = useSearchParams().get("orderId");
  const { status, order, message, retry } =
    storefront.usePaymentConfirmation(orderId);

  switch (status) {
    case "processing":
      return <p>Confirming your payment…</p>;
    case "success":
      return <p>Thanks! Order {order?.id} is confirmed.</p>;
    case "pending":
      return <p>{message} <button onClick={retry}>Check again</button></p>;
    default:
      return <p>{message ?? "Payment failed."} <button onClick={retry}>Retry</button></p>;
  }
}

The status can be:

StatusMeaning
processingAwaiting the first confirmation response.
successPayment confirmed.
pendingProvider webhook still settling — offer a "Check again" button.
failedPayment was rejected.
errorThe confirmation call itself failed (network) after retries.

The cart clears itself

On a successful payment, the API clears the customer's cart. The usePaymentConfirmation hook also refreshes the shared cart state, so a header cart badge drops to zero without any extra code.

Confirming without React

Outside React, call checkout.confirm(orderId) yourself:

const { data, error } = await storekit.checkout.confirm(orderId);
// data → { success, status, order, error? }

It's safe to call more than once. If the provider's webhook hasn't landed yet, status is pending; retry shortly.

Webhooks (server-to-server)

The provider also calls your API directly via webhooks to settle the order authoritatively, independent of the browser redirect. You don't build these — they're part of the API. See API → Webhooks.

On this page