HandyPay
HandyPay

Integration Recipes

Copy-paste examples for common integration patterns. All examples use the handypay helper from the Quick Start.

Next.js: Server-Side Product Listing

Fetch and render products in a Next.js App Router server component.

app/products/page.tsx
import { handypay } from "@/lib/handypay";

export default async function ProductsPage() {
  const { data: products, has_more } = await handypay("/products?limit=20");

  return (
    <div>
      {products.map((product: any) => (
        <div key={product.id}>
          <h2>{product.name}</h2>
          <p>{product.description}</p>
          {product.default_price && (
            <span>${(product.default_price.amount / 100).toFixed(2)}</span>
          )}
        </div>
      ))}
    </div>
  );
}
typescript

Next.js: Checkout Button (Server Action)

Create a server action that generates a checkout session and redirects the user.

app/actions/checkout.ts
"use server";

import { redirect } from "next/navigation";
import { handypay } from "@/lib/handypay";

export async function createCheckout(priceId: string) {
  const session = await handypay("/payment-sessions", {
    method: "POST",
    body: JSON.stringify({
      line_items: [{ price_id: priceId, quantity: 1 }],
      success_url: `${process.env.NEXT_PUBLIC_APP_URL}/success`,
      cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/pricing`,
    }),
  });

  redirect(session.url);
}
typescript

Call this from a client component with a form action or onClick.

React Native: Opening Checkout in Browser

Create a payment session and open the hosted checkout URL using Expo WebBrowser.

hooks/useCheckout.ts
import * as WebBrowser from "expo-web-browser";

const API_URL = "https://api.handypay.me/api/v1";
const API_KEY = "hp_live_..."; // Load from secure storage

export async function openCheckout(priceId: string) {
  const res = await fetch(`${API_URL}/payment-sessions`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      line_items: [{ price_id: priceId, quantity: 1 }],
      success_url: "https://yourapp.com/mobile-success",
      cancel_url: "https://yourapp.com/mobile-cancel",
    }),
  });

  const { data } = await res.json();
  await WebBrowser.openBrowserAsync(data.url);
}
typescript

Subscription Management Flow

End-to-end subscription lifecycle: create a plan, start a checkout, list active subs, and cancel.

TypeScript
// 1. Create a subscription product (do this once, e.g. in a seed script)
const plan = await handypay("/subscription-products", {
  method: "POST",
  body: JSON.stringify({
    name: "Pro Plan",
    amount: 1999,
    currency: "usd",
    interval: "monthly",
    trial_period_days: 7,
  }),
});

// 2. Create a subscription checkout session for a customer
const session = await handypay("/subscription-sessions", {
  method: "POST",
  body: JSON.stringify({
    price_id: plan.price.id,
    customer_email: "[email protected]",
    success_url: "https://yoursite.com/welcome",
    cancel_url: "https://yoursite.com/pricing",
  }),
});

// 3. Redirect to session.url

// 4. List active subscriptions
const { data: subs } = await handypay("/subscriptions?limit=10");

// 5. Cancel a subscription
await handypay(`/subscriptions/${subs[0].id}/cancel`, { method: "POST" });
typescript