# Payment Method

> Payment method with card details, type, and billing address.

- Name: `payment-method`
- Categories: ecommerce
- Depends on: `@open-types/address`
- Detail page: https://open-types.dev/types/payment-method

## Install

```bash
# Types only
npx shadcn add @open-types/payment-method

# Types + Zod v4 validators
npx shadcn add @open-types/payment-method-zod

# Types + real-world examples
npx shadcn add @open-types/payment-method-examples
```

## Types

```typescript
import type { Address } from "./address";

export interface PaymentCard {
  brand: string;
  last4: string;
  exp_month: number;
  exp_year: number;
}

export type PaymentMethodType = "card" | "bank_account" | "paypal";

export interface PaymentMethodBillingDetails {
  name?: string;
  email?: string;
  phone?: string;
  address?: Address;
}

export interface PaymentMethod {
  id: string;
  type: PaymentMethodType;
  card?: PaymentCard;
  billing_details?: PaymentMethodBillingDetails;
}
```

## Zod validator

```typescript
import * as z from "zod";
import type {
  PaymentCard,
  PaymentMethod,
  PaymentMethodBillingDetails,
  PaymentMethodType,
} from "../types/payment-method";
import { addressSchema } from "./address";

export const paymentMethodTypeSchema = z.enum(["card", "bank_account", "paypal"]) satisfies z.ZodType<PaymentMethodType>;

export const paymentCardSchema = z.object({
  brand: z.string().min(1, { error: "Card brand is required" }),
  last4: z.string().regex(/^\d{4}$/, { error: "Last 4 digits must be exactly 4 numbers" }),
  exp_month: z.number().int({ error: "Expiration month must be a whole number" }).min(1, {
    error: "Expiration month must be between 1 and 12",
  }).max(12, { error: "Expiration month must be between 1 and 12" }),
  exp_year: z.number().int({ error: "Expiration year must be a whole number" }).min(2020, {
    error: "Expiration year must be 2020 or later",
  }),
}) satisfies z.ZodType<PaymentCard>;

export const paymentMethodBillingDetailsSchema = z.object({
  name: z.string().optional(),
  email: z.string().email({ error: "Billing email must be a valid email address" }).optional(),
  phone: z.string().optional(),
  address: addressSchema.optional(),
}) satisfies z.ZodType<PaymentMethodBillingDetails>;

export const paymentMethodSchema = z.object({
  id: z.string().min(1, { error: "Payment method ID is required" }),
  type: paymentMethodTypeSchema,
  card: paymentCardSchema.optional(),
  billing_details: paymentMethodBillingDetailsSchema.optional(),
}) satisfies z.ZodType<PaymentMethod>;

export type {
  PaymentCard,
  PaymentMethod,
  PaymentMethodBillingDetails,
  PaymentMethodType,
} from "../types/payment-method";
```

## Examples

```typescript
// Source: hand-crafted
import type {
  PaymentCard,
  PaymentMethodType,
  PaymentMethodBillingDetails,
  PaymentMethod,
} from "../types/payment-method";
import { addressExamples } from "./address.examples";

export const paymentMethodTypeExamples = {
  card: "card",
  bankAccount: "bank_account",
  paypal: "paypal",
} as const satisfies Record<string, PaymentMethodType>;

const visaCard = {
  brand: "visa",
  last4: "4242",
  exp_month: 12,
  exp_year: 2028,
} as const satisfies PaymentCard;

export const paymentCardExamples = {
  visa: visaCard,
  mastercard: {
    brand: "mastercard",
    last4: "5454",
    exp_month: 3,
    exp_year: 2027,
  } satisfies PaymentCard,
  amex: {
    brand: "amex",
    last4: "8431",
    exp_month: 6,
    exp_year: 2026,
  } satisfies PaymentCard,
} as const;

const fullBilling = {
  name: "Jenny Rosen",
  email: "jenny@example.com",
  phone: "+14155551234",
  address: addressExamples.minimal,
} as const satisfies PaymentMethodBillingDetails;

export const paymentMethodBillingDetailsExamples = {
  full: fullBilling,
  nameOnly: { name: "Jenny Rosen" } satisfies PaymentMethodBillingDetails,
  empty: {} satisfies PaymentMethodBillingDetails,
} as const;

const cardMethod = {
  id: "pm_01HABCDEF0123456789ABCDE",
  type: "card",
  card: visaCard,
  billing_details: fullBilling,
} as const satisfies PaymentMethod;

export const paymentMethodExamples = {
  cardFull: cardMethod,
  cardMinimal: {
    id: "pm_min_001",
    type: "card",
    card: visaCard,
  } satisfies PaymentMethod,
  bankAccount: {
    id: "pm_bank_002",
    type: "bank_account",
    billing_details: { name: "Acme Corp", email: "billing@acme.example" },
  } satisfies PaymentMethod,
  paypal: {
    id: "pm_paypal_003",
    type: "paypal",
    billing_details: { email: "jenny@example.com" },
  } satisfies PaymentMethod,
} as const;
```
