pancake

package module
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 18 Imported by: 0

README

github.com/waffo-com/waffo-pancake-sdk-go

Go SDK for the Waffo Pancake Merchant of Record (MoR) payment platform.

  • Zero runtime dependencies, Go >= 1.22
  • Automatic RSA-SHA256 request signing with deterministic idempotency keys
  • Full type definitions (20 enums, 40+ structs)
  • Webhook verification with embedded public keys (test/prod)
  • Feature parity with @waffo/pancake-ts@0.14.x

Installation

go get github.com/waffo-com/waffo-pancake-sdk-go

Requires Go 1.22 or newer.

Quick Start

Most merchants create stores and products in the Dashboard. The SDK is primarily used for checkout integration — redirecting customers from your site to the Waffo checkout page.

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/waffo-com/waffo-pancake-sdk-go"
)

func main() {
    client, err := pancake.New(pancake.Config{
        MerchantID: os.Getenv("WAFFO_MERCHANT_ID"), // "MER_..." Short ID
        PrivateKey: os.Getenv("WAFFO_PRIVATE_KEY"), // RSA PEM
    })
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()

    // Create a checkout session — one call handles token + session + URL.
    result, err := client.Checkout.Authenticated.Create(ctx, pancake.AuthenticatedCheckoutParams{
        CreateCheckoutSessionParams: pancake.CreateCheckoutSessionParams{
            ProductID:  "PROD_xxx",
            Currency:   "USD",
            BuyerEmail: pancake.Ptr("customer@example.com"),
        },
        BuyerIdentity: "user-123", // your user's identity
    })
    if err != nil {
        log.Fatal(err)
    }

    // Redirect the customer to result.CheckoutURL (includes #token=...).
    fmt.Println(result.CheckoutURL)
}

Configuration

Field Type Required Description
MerchantID string yes Merchant ID in MER_{base62} format
PrivateKey string yes RSA private key in PEM format (auto-normalized)
BaseURL string no API base URL override (default: https://api.waffo.ai)
HTTPClient *http.Client no Custom HTTP client (default: http.DefaultClient)
WebhookPublicKey pancake.WebhookPublicKeys no Custom webhook public key(s) — overrides the built-in defaults

The SDK auto-normalizes PEM input variants: standard PEM, PKCS#1, PKCS#8, literal \n from env vars, Windows line endings, and raw base64.

Checkout Integration

Two flows, mirroring the TypeScript SDK:

Mode Method Customer identity Form state Use case
Authenticated Checkout.Authenticated.Create(...) Merchant-provided Pre-filled Sites with user accounts (recommended)
Anonymous Checkout.Anonymous.Create(...) None Empty Template stores, one-time purchase links
// Authenticated (recommended): identity binds the order to a stable
// merchant-controlled ID even if the customer changes the email on the form.
res, err := client.Checkout.Authenticated.Create(ctx, pancake.AuthenticatedCheckoutParams{
    CreateCheckoutSessionParams: pancake.CreateCheckoutSessionParams{
        ProductID:  "PROD_...",
        Currency:   "USD",
        BuyerEmail: pancake.Ptr("customer@example.com"),
        PriceSnapshot: &pancake.PriceInfo{
            Amount:      "19.99",
            TaxCategory: pancake.TaxCategoryDigitalGoods,
        },
        OrderMerchantExternalID: pancake.Ptr("ORDER-2026-00891"), // optional, see Business-Side Identifiers below
    },
    BuyerIdentity: "user-123",
})

// Anonymous: customer fills the form themselves.
res, err := client.Checkout.Anonymous.Create(ctx, pancake.AnonymousCheckoutParams{
    ProductID: "PROD_...",
    Currency:  "USD",
})

Opening the URL in a new tab is recommended so customers can return to your site without losing page state.

Webhook Verification

Use the raw request body. Parsing and re-serializing breaks the signature.

Standalone function
import "io"

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    body, _ := io.ReadAll(r.Body)
    sig := r.Header.Get("X-Waffo-Signature")

    event, err := pancake.VerifyWebhook(string(body), sig, nil)
    if err != nil {
        http.Error(w, "Invalid signature", http.StatusUnauthorized)
        return
    }
    w.WriteHeader(http.StatusOK)

    switch pancake.WebhookEventType(event.EventType) {
    case pancake.WebhookEventTypeOrderCompleted:
        var data pancake.WebhookEventData
        _ = json.Unmarshal(event.Data, &data)
        fmt.Println("Order completed for", data.BuyerEmail)
    }
}
Typed verification
event, err := pancake.VerifyWebhookTyped[pancake.WebhookEventData](
    string(body),
    sig,
    &pancake.VerifyWebhookOptions{Environment: pancake.EnvironmentProd},
)
// event.Data is pancake.WebhookEventData (struct, not raw bytes)
// refund.* events carry both event.Data.OrderMerchantExternalID and
// event.Data.RefundTicketMerchantExternalID — see Business-Side Identifiers below.
Client-instance method
client, _ := pancake.New(pancake.Config{
    MerchantID: "MER_...",
    PrivateKey: privateKey,
    WebhookPublicKey: pancake.WebhookPublicKeys{
        Test: os.Getenv("WAFFO_TEST_PUB_KEY"),
        Prod: os.Getenv("WAFFO_PROD_PUB_KEY"),
    },
})
event, err := client.Webhooks.Verify(string(body), sig, nil)
Public key resolution chain

For each environment, public keys are resolved in priority order:

  1. VerifyWebhookOptions.PublicKey — per-call override
  2. Config.WebhookPublicKey (Shared first, then per-env)
  3. WAFFO_WEBHOOK_TEST_PUBLIC_KEY / WAFFO_WEBHOOK_PROD_PUBLIC_KEY env var
  4. WAFFO_WEBHOOK_PUBLIC_KEY env var
  5. Built-in hardcoded PEM key

Replay protection: timestamps outside a 5-minute window are rejected. Set VerifyWebhookOptions.ToleranceMS to a negative value to disable.

Customer Self-Service

// Issue a session token on your backend.
tok, err := client.Auth.IssueSessionToken(ctx, pancake.IssueSessionTokenParams{
    StoreID:       pancake.Ptr("STO_..."),
    BuyerIdentity: "user-123",
})

// Hand off to the customer session.
customer := client.Customer(tok.Token)

// Cancel a subscription.
res, err := customer.CancelSubscription(ctx, pancake.CancelSubscriptionParams{
    OrderID: "ORD_...",
})

// Submit a refund request.
refund, err := customer.CreateRefundTicket(ctx, pancake.CreateRefundTicketParams{
    PaymentID: "PAY_...",
    Reason:    "Product not as described",
    RequestedAmount: pancake.RequestedAmount{
        Amount:   "29.00",
        Currency: "USD",
    },
    RefundTicketMerchantExternalID: pancake.Ptr("REF-2026-00012"), // optional, see Business-Side Identifiers below
})

The token is scoped to the issuing store and customer identity. TTL is 5 minutes and auto-refreshes on each call.

Business-Side Identifiers

Attach your own internal references to a checkout or a refund ticket so cross-system reconciliation does not require Waffo IDs. Two flat keys, both optional (max 128 chars):

Field Attach at Inherited by
OrderMerchantExternalID Checkout.{Authenticated,Anonymous}.Create Order, Payment (incl. subscription renewals), Refund
RefundTicketMerchantExternalID Customer.CreateRefundTicket RefundTicket, Refund

The JSON key (orderMerchantExternalId / refundTicketMerchantExternalId) is the same at every layer it surfaces: REST request body, response entity, webhook payload (data.orderMerchantExternalId / data.refundTicketMerchantExternalId), and every GraphQL type that carries the value. A refund.* webhook event carries both keys (order key inherited from the originating order). Query by either key via GraphQL filters — see the GraphQL Guide.

GraphQL

Both raw and typed access are supported. The raw form is useful for one-off queries; the typed form is type-safe.

// Raw — Data is json.RawMessage; unmarshal into your own struct.
resp, err := client.GraphQL.Query(ctx, pancake.GraphQLParams{
    Query: `query { stores { id name status } }`,
})

var data struct {
    Stores []pancake.Store `json:"stores"`
}
_ = json.Unmarshal(resp.Data, &data)

// Typed — Data is your struct.
type StoresQuery struct {
    Stores []pancake.Store `json:"stores"`
}
typed, err := pancake.GraphQLQuery[StoresQuery](ctx, client, pancake.GraphQLParams{
    Query: `query { stores { id name status } }`,
})
fmt.Println(typed.Data.Stores[0].Name)

For customer-scoped queries, use customer.GraphQL.Query or pancake.CustomerGraphQLQuery[T].

// Look up by your business-side identifier (see Business-Side Identifiers above)
type PaymentsByRef struct {
    Payments []struct {
        ID                      string  `json:"id"`
        OrderID                 string  `json:"orderId"`
        Status                  string  `json:"status"`
        OrderMerchantExternalID *string `json:"orderMerchantExternalId"`
    } `json:"payments"`
}
res, _ := pancake.GraphQLQuery[PaymentsByRef](ctx, client, pancake.GraphQLParams{
    Query: `query ($ref: String!) {
        payments(filter: { orderMerchantExternalId: { eq: $ref } }) {
            id orderId status orderMerchantExternalId
        }
    }`,
    Variables: map[string]any{"ref": "ORDER-2026-00891"},
})

Warnings (Migration Notices)

Every successful REST action and GraphQL query may carry a Warnings slice alongside the data. Warnings describe non-fatal advisories the server wants you to act on — typically deprecated parameters, fields scheduled for removal, or new APIs you should switch to. Each Notice carries Message (human-readable), Layer (which service produced it), and AIHint (a structured migration instruction aimed at LLM consumers).

// REST action — warnings sit on the typed Result struct
res, err := client.Stores.Update(ctx, pancake.UpdateStoreParams{
    ID: "STO_xxx",
    // ... may carry deprecated fields the server warns about
})
if err != nil { /* handle */ }
for _, w := range res.Warnings {
    log.Printf("[%s] %s — %s", w.Layer, w.Message, w.AIHint)
    // e.g. Layer=store, AIHint="Switch to client.Webhooks.Add / Update / Remove"
}

// GraphQL — warnings sit on the envelope alongside Data and Errors
resp, _ := client.GraphQL.Query(ctx, pancake.GraphQLParams{
    Query: `query { stores { id } }`,
})
for _, w := range resp.Warnings {
    log.Printf("%s — %s", w.Message, w.AIHint)
}

LLM/agent consumers: always inspect AIHint on every warning — it is the canonical migration instruction (Go module path, version, method name, endpoint path) the platform team intends for you to follow when the underlying API evolves.

Programmatic Store, Product, and Webhook Management

// Stores
storeRes, _ := client.Stores.Create(ctx, pancake.CreateStoreParams{Name: "My Store"})

// Products
prodRes, _ := client.OnetimeProducts.Create(ctx, pancake.CreateOnetimeProductParams{
    StoreID: storeRes.Store.ID,
    Name:    "E-Book",
    Prices: pancake.Prices{
        "USD": {Amount: "29.00", TaxCategory: pancake.TaxCategoryDigitalGoods},
    },
})
_, _ = client.OnetimeProducts.Publish(ctx, pancake.PublishOnetimeProductParams{ID: prodRes.Product.ID})

// Subscription products
subRes, _ := client.SubscriptionProducts.Create(ctx, pancake.CreateSubscriptionProductParams{
    StoreID:       storeRes.Store.ID,
    Name:          "Pro Plan",
    BillingPeriod: pancake.BillingPeriodMonthly,
    Prices: pancake.Prices{
        "USD": {Amount: "9.99", TaxCategory: pancake.TaxCategorySaaS},
    },
})

// Webhooks
_, _ = client.Webhooks.Add(ctx, pancake.AddWebhookParams{
    StoreID:  storeRes.Store.ID,
    Channel:  pancake.WebhookChannelHTTP,
    URL:      "https://example.com/webhooks",
    Events:   []pancake.WebhookEventType{pancake.WebhookEventTypeOrderCompleted},
    TestMode: false,
})

To list configured webhooks, query GraphQL Store.storeWebhooks via client.GraphQL.Query.

Content Safety

Scan a user's prompt for content-safety compliance before AIGC generation — continue only when Action is pancake.ScanActionAllow. The check is stateless (prompt text is never stored); it fails closed to pancake.ScanActionReview if the safety service is briefly unavailable.

verdict, _ := client.ContentSafety.ScanPrompt(ctx, pancake.ScanPromptParams{
    Prompt: "a cat riding a bike",
})
if verdict.Action != pancake.ScanActionAllow {
    // do not generate — verdict.Action is "review" or "block"
}

Error Handling

import "errors"

if _, err := client.Stores.Create(ctx, pancake.CreateStoreParams{Name: ""}); err != nil {
    var perr *pancake.Error
    if errors.As(err, &perr) {
        fmt.Println(perr.Status)            // 400
        fmt.Println(perr.Errors[0].Message) // "name cannot be empty"
        fmt.Println(perr.Errors[0].Layer)   // pancake.ErrorLayerSDK
    }
}

Client-side validation failures use Layer: ErrorLayerSDK so they can be distinguished from server-returned errors.

Resource Reference

Field Methods
client.Auth IssueSessionToken
client.Stores Create, Update, Delete
client.StoreMerchants Add, Remove, UpdateRole (coming soon — endpoints return 501)
client.OnetimeProducts Create, Update, Publish, UpdateStatus
client.SubscriptionProducts Create, Update, Publish, UpdateStatus
client.SubscriptionProductGroups Create, Update, Delete, Publish
client.Orders CancelSubscription
client.Checkout CreateSession, Anonymous.Create, Authenticated.Create
client.GraphQL Query (also pancake.GraphQLQuery[T])
client.Webhooks Add, Update, Remove, Verify (also pancake.VerifyWebhook / pancake.VerifyWebhookTyped[T])
client.ContentSafety ScanPrompt (AIGC prompt content-safety scan)
client.Customer(token) CancelSubscription, CancelOnetimeOrder, ReactivateSubscription, CreateRefundTicket, ResubmitRefundTicket, GraphQL.Query

Optional fields

TypeScript signature Go representation
description?: string Description *string \json:"description,omitempty"``
logo?: string | null Logo *pancake.Nullable[string] \json:"logo,omitempty"``
prices: Record<string, ...> Prices pancake.Prices

Helpers: pancake.Ptr(v), pancake.NullValuePtr(v), pancake.ExplicitNullPtr[T]().

Development

go test ./...
go test -race -cover ./...
go vet ./...
golangci-lint run

See examples/ for runnable sample programs.

License

MIT

Documentation

Overview

Package pancake is the official Go SDK for the Waffo Pancake Merchant of Record (MoR) payment platform.

All merchant API requests are auto-signed with RSA-SHA256 and carry deterministic idempotency keys derived from the merchant ID, path, and body. Webhook verification, GraphQL queries, and customer self-service flows are supported out of the box. The SDK has zero external runtime dependencies — only the Go standard library.

Quickstart

client, err := pancake.New(pancake.Config{
    MerchantID: os.Getenv("WAFFO_MERCHANT_ID"), // MER_{base62}
    PrivateKey: os.Getenv("WAFFO_PRIVATE_KEY"), // RSA PEM
})
if err != nil {
    log.Fatal(err)
}

ctx := context.Background()

storeRes, err := client.Stores.Create(ctx, pancake.CreateStoreParams{
    Name: "My Store",
})

checkout, err := client.Checkout.Authenticated.Create(ctx, pancake.AuthenticatedCheckoutParams{
    CreateCheckoutSessionParams: pancake.CreateCheckoutSessionParams{
        ProductID: "PROD_...",
        Currency:  "USD",
    },
    BuyerIdentity: "customer@example.com",
})

event, err := pancake.VerifyWebhook(rawBody, signatureHeader, nil)

Feature parity with @waffo/pancake-ts@0.14.x.

Index

Constants

View Source
const DefaultBaseURL = "https://api.waffo.ai"

DefaultBaseURL is the production API base URL applied when Config.BaseURL is empty.

View Source
const DefaultWebhookToleranceMS = 5 * 60 * 1000

DefaultWebhookToleranceMS is the default replay-protection window applied when VerifyWebhookOptions.ToleranceMS is zero.

Variables

This section is empty.

Functions

func Ptr

func Ptr[T any](v T) *T

Ptr returns a pointer to v. Useful for optional struct fields modeled as *T:

UpdateStoreParams{Name: pancake.Ptr("New name")}

Types

type APIError deprecated

type APIError = Notice

APIError is the legacy name for {@link Notice}. Kept as a type alias for backwards compatibility with existing imports.

Deprecated: use Notice.

type AddMerchantParams

type AddMerchantParams struct {
	StoreID string `json:"storeId"`
	Email   string `json:"email"`
	Role    string `json:"role"`
}

AddMerchantParams is the input to StoreMerchants.Add.

type AddMerchantResult

type AddMerchantResult struct {
	StoreID    string   `json:"storeId"`
	MerchantID string   `json:"merchantId"`
	Email      string   `json:"email"`
	Role       string   `json:"role"`
	Status     string   `json:"status"`
	AddedAt    string   `json:"addedAt"`
	Warnings   []Notice `json:"warnings,omitempty"`
}

AddMerchantResult is the response of StoreMerchants.Add.

type AddWebhookParams

type AddWebhookParams struct {
	StoreID  string             `json:"storeId"`
	Channel  WebhookChannel     `json:"channel"`
	URL      string             `json:"url"`
	Events   []WebhookEventType `json:"events"`
	TestMode bool               `json:"testMode"`
	Secret   *string            `json:"secret,omitempty"`
}

AddWebhookParams is the input to Webhooks.Add.

type AddWebhookResult

type AddWebhookResult struct {
	Webhook  StoreWebhook `json:"webhook"`
	Warnings []Notice     `json:"warnings,omitempty"`
}

AddWebhookResult wraps the response of Webhooks.Add / Update / Remove.

type AnonymousCheckoutParams

type AnonymousCheckoutParams = CreateCheckoutSessionParams

AnonymousCheckoutParams is the input to Checkout.Anonymous.Create. The checkout form is left blank unless BuyerEmail or BillingDetail are supplied.

type AuthResource

type AuthResource struct {
	// contains filtered or unexported fields
}

AuthResource issues session tokens for customers.

func (*AuthResource) IssueSessionToken

func (r *AuthResource) IssueSessionToken(ctx context.Context, p IssueSessionTokenParams) (*SessionToken, error)

IssueSessionToken mints a customer session JWT. Provide either StoreID or ProductID — when only ProductID is given the server derives the store from the product.

Example:

tok, err := client.Auth.IssueSessionToken(ctx, pancake.IssueSessionTokenParams{
    StoreID:       pancake.Ptr("STO_..."),
    BuyerIdentity: "customer@example.com",
})

type AuthenticatedCheckoutParams

type AuthenticatedCheckoutParams struct {
	CreateCheckoutSessionParams
	// BuyerIdentity is encoded into the JWT for merchant-side customer
	// identification. Use BuyerEmail to pre-fill the checkout form's email
	// input; the two fields are independent.
	BuyerIdentity string `json:"-"`
}

AuthenticatedCheckoutParams is the input to Checkout.Authenticated.Create. It extends CreateCheckoutSessionParams with BuyerIdentity, which is routed to the issue-session-token endpoint while the remaining fields go to the create-session endpoint.

type AuthenticatedCheckoutResult

type AuthenticatedCheckoutResult struct {
	SessionID      string   `json:"sessionId"`
	CheckoutURL    string   `json:"checkoutUrl"`
	ExpiresAt      string   `json:"expiresAt"`
	Token          string   `json:"token"`
	TokenExpiresAt string   `json:"tokenExpiresAt"`
	Warnings       []Notice `json:"warnings,omitempty"`
}

AuthenticatedCheckoutResult is the response of Checkout.Authenticated.Create — session and token data merged into one struct.

type BillingDetail

type BillingDetail struct {
	Country      string  `json:"country"`
	IsBusiness   bool    `json:"isBusiness"`
	Postcode     *string `json:"postcode,omitempty"`
	State        *string `json:"state,omitempty"`
	BusinessName *string `json:"businessName,omitempty"`
	TaxID        *string `json:"taxId,omitempty"`
}

BillingDetail captures customer billing information for checkout.

type BillingPeriod

type BillingPeriod string

BillingPeriod is the recurrence cadence of a subscription product.

const (
	BillingPeriodWeekly    BillingPeriod = "weekly"
	BillingPeriodMonthly   BillingPeriod = "monthly"
	BillingPeriodQuarterly BillingPeriod = "quarterly"
	BillingPeriodYearly    BillingPeriod = "yearly"
)

type BuyerGraphQLResource deprecated

type BuyerGraphQLResource = CustomerGraphQLResource

BuyerGraphQLResource is an alias for CustomerGraphQLResource.

Deprecated: Use CustomerGraphQLResource instead.

type BuyerSession deprecated

type BuyerSession = CustomerSession

BuyerSession is an alias for CustomerSession.

Deprecated: Use CustomerSession instead.

type CancelOnetimeOrderParams

type CancelOnetimeOrderParams struct {
	OrderID string `json:"orderId"`
}

CancelOnetimeOrderParams is the input to CustomerSession.CancelOnetimeOrder.

type CancelOnetimeOrderResult

type CancelOnetimeOrderResult struct {
	OrderID  string   `json:"orderId"`
	Status   string   `json:"status"`
	Warnings []Notice `json:"warnings,omitempty"`
}

CancelOnetimeOrderResult is the response of CancelOnetimeOrder.

type CancelSubscriptionParams

type CancelSubscriptionParams struct {
	OrderID string `json:"orderId"`
}

CancelSubscriptionParams is the input to Orders.CancelSubscription and to CustomerSession.CancelSubscription.

type CancelSubscriptionResult

type CancelSubscriptionResult struct {
	OrderID  string                  `json:"orderId"`
	Status   SubscriptionOrderStatus `json:"status"`
	Warnings []Notice                `json:"warnings,omitempty"`
}

CancelSubscriptionResult is the response of CancelSubscription.

type CheckoutAnonymousResource

type CheckoutAnonymousResource struct {
	// contains filtered or unexported fields
}

CheckoutAnonymousResource creates checkout sessions without a customer identity. The form on the checkout page is left blank unless BuyerEmail or BillingDetail are supplied.

func (*CheckoutAnonymousResource) Create

Create creates an anonymous checkout session.

Example:

res, err := client.Checkout.Anonymous.Create(ctx, pancake.AnonymousCheckoutParams{
    ProductID: "PROD_...",
    Currency:  "USD",
})

type CheckoutAuthenticatedResource

type CheckoutAuthenticatedResource struct {
	// contains filtered or unexported fields
}

CheckoutAuthenticatedResource creates checkout sessions with a merchant- provided customer identity. It issues a session token in parallel with the session creation and appends "#token=..." to the returned URL.

func (*CheckoutAuthenticatedResource) Create

Create issues a customer session token and creates a checkout session concurrently, then returns a unified result whose CheckoutURL carries the token as a URL fragment.

BuyerIdentity is sent only to the issue-session-token endpoint; every other field is forwarded to the create-session endpoint unchanged.

Example:

res, err := client.Checkout.Authenticated.Create(ctx, pancake.AuthenticatedCheckoutParams{
    CreateCheckoutSessionParams: pancake.CreateCheckoutSessionParams{
        ProductID:  "PROD_...",
        Currency:   "USD",
        BuyerEmail: pancake.Ptr("customer@example.com"),
    },
    BuyerIdentity: "user-123",
})

type CheckoutResource

type CheckoutResource struct {
	// Anonymous creates checkout sessions without a customer identity.
	Anonymous *CheckoutAnonymousResource
	// Authenticated creates checkout sessions that include a customer-session
	// token for post-purchase self-service.
	Authenticated *CheckoutAuthenticatedResource
	// contains filtered or unexported fields
}

CheckoutResource creates checkout sessions and offers two convenience sub-resources (Anonymous and Authenticated) for the most common flows.

func (*CheckoutResource) CreateSession

CreateSession is the low-level checkout-session endpoint. Most callers should prefer Checkout.Anonymous.Create or Checkout.Authenticated.Create.

Example:

session, err := client.Checkout.CreateSession(ctx, pancake.CreateCheckoutSessionParams{
    ProductID: "PROD_...",
    Currency:  "USD",
})
// Redirect the customer to session.CheckoutURL.

type CheckoutSessionResult

type CheckoutSessionResult struct {
	SessionID   string   `json:"sessionId"`
	CheckoutURL string   `json:"checkoutUrl"`
	ExpiresAt   string   `json:"expiresAt"`
	Warnings    []Notice `json:"warnings,omitempty"`
}

CheckoutSessionResult is the response of Checkout.CreateSession and Checkout.Anonymous.Create.

type CheckoutSettings

type CheckoutSettings struct {
	DefaultDarkMode bool                  `json:"defaultDarkMode"`
	Light           CheckoutThemeSettings `json:"light"`
	Dark            CheckoutThemeSettings `json:"dark"`
}

CheckoutSettings holds light and dark theme settings for the checkout page.

type CheckoutThemeSettings

type CheckoutThemeSettings struct {
	CheckoutColorPrimary    string  `json:"checkoutColorPrimary"`
	CheckoutColorBackground string  `json:"checkoutColorBackground"`
	CheckoutColorCard       string  `json:"checkoutColorCard"`
	CheckoutColorText       string  `json:"checkoutColorText"`
	CheckoutBorderRadius    string  `json:"checkoutBorderRadius"`
}

CheckoutThemeSettings holds checkout page styling for a single theme.

type Client

type Client struct {
	// Auth issues customer session tokens.
	Auth *AuthResource
	// Stores manages stores.
	Stores *StoresResource
	// StoreMerchants manages store membership (coming soon — endpoints return 501).
	StoreMerchants *StoreMerchantsResource
	// OnetimeProducts manages one-time products.
	OnetimeProducts *OnetimeProductsResource
	// SubscriptionProducts manages subscription products.
	SubscriptionProducts *SubscriptionProductsResource
	// SubscriptionProductGroups manages subscription groups.
	SubscriptionProductGroups *SubscriptionProductGroupsResource
	// Orders manages orders.
	Orders *OrdersResource
	// Checkout creates checkout sessions.
	Checkout *CheckoutResource
	// GraphQL runs GraphQL queries at merchant scope.
	GraphQL *GraphQLResource
	// Webhooks manages webhook endpoints and verifies inbound signatures.
	Webhooks *WebhooksResource
	// ContentSafety scans user prompts before AIGC generation.
	ContentSafety *ContentSafetyResource
	// contains filtered or unexported fields
}

Client is the main Waffo Pancake SDK entry point. Construct it with New and access resource namespaces through its exported fields. Methods that perform I/O take a context.Context first parameter.

func New

func New(c Config) (*Client, error)

New constructs a Client. It validates MerchantID format, normalizes the RSA private key, and wires every resource namespace.

func (*Client) Buyer deprecated

func (c *Client) Buyer(token string) *CustomerSession

Buyer returns a CustomerSession backed by the given session token.

Deprecated: Use Customer instead.

func (*Client) Customer added in v0.5.0

func (c *Client) Customer(token string) *CustomerSession

Customer returns a CustomerSession backed by the given session token. The token is issued by Auth.IssueSessionToken and is sent as a Bearer Authorization header on every customer request. No I/O is performed by this call.

type Config

type Config struct {
	// MerchantID in MER_{base62} format (sent as X-Merchant-Id).
	MerchantID string
	// PrivateKey is the RSA private key in PEM format. The SDK normalizes
	// common input variants (literal "\n", Windows line endings, raw base64,
	// PKCS#1, PKCS#8) before use.
	PrivateKey string
	// BaseURL overrides the API host. Defaults to DefaultBaseURL.
	BaseURL string
	// HTTPClient overrides the underlying *http.Client. Defaults to
	// http.DefaultClient.
	HTTPClient *http.Client
	// WebhookPublicKey configures keys for webhook signature verification.
	// When unset, built-in test/prod keys are used.
	WebhookPublicKey WebhookPublicKeys
}

Config configures a Client.

type ContentSafetyResource added in v0.6.0

type ContentSafetyResource struct {
	// contains filtered or unexported fields
}

ContentSafetyResource scans user prompts for content-safety compliance before AIGC generation.

func (*ContentSafetyResource) ScanPrompt added in v0.6.0

ScanPrompt scans a user's text prompt for content-safety compliance before AIGC generation. Call this before invoking your image/video model and continue only when the returned Action is ScanActionAllow.

The check is stateless — prompt text is never stored. If the safety service is briefly unavailable, the verdict fails closed to ScanActionReview so an unmoderated prompt is never let through.

Example:

verdict, err := client.ContentSafety.ScanPrompt(ctx, pancake.ScanPromptParams{
    Prompt: "a cat riding a bike",
})
if err != nil {
    // handle error
}
if verdict.Action != pancake.ScanActionAllow {
    // do not generate — verdict.Action is "review" or "block"
}

type CreateCheckoutSessionParams

type CreateCheckoutSessionParams struct {
	ProductID        string            `json:"productId"`
	Currency         string            `json:"currency"`
	PriceSnapshot    *PriceInfo        `json:"priceSnapshot,omitempty"`
	WithTrial        *bool             `json:"withTrial,omitempty"`
	BuyerEmail       *string           `json:"buyerEmail,omitempty"`
	BillingDetail    *BillingDetail    `json:"billingDetail,omitempty"`
	SuccessURL       *string           `json:"successUrl,omitempty"`
	ExpiresInSeconds *int              `json:"expiresInSeconds,omitempty"`
	DarkMode         *bool             `json:"darkMode,omitempty"`
	Metadata         map[string]string `json:"metadata,omitempty"`
	// OrderMerchantExternalID is the order-side business identifier (max 128 chars); inherited by orders, payments, refunds.
	OrderMerchantExternalID *string `json:"orderMerchantExternalId,omitempty"`
}

CreateCheckoutSessionParams is the input to Checkout.CreateSession.

type CreateOnetimeProductParams

type CreateOnetimeProductParams struct {
	StoreID     string         `json:"storeId"`
	Name        string         `json:"name"`
	Prices      Prices         `json:"prices"`
	Description *string        `json:"description,omitempty"`
	Media       []MediaItem    `json:"media,omitempty"`
	SuccessURL  *string        `json:"successUrl,omitempty"`
	Metadata    map[string]any `json:"metadata,omitempty"`
}

CreateOnetimeProductParams is the input to OnetimeProducts.Create.

type CreateRefundTicketParams

type CreateRefundTicketParams struct {
	PaymentID       string          `json:"paymentId"`
	Reason          string          `json:"reason"`
	RequestedAmount RequestedAmount `json:"requestedAmount"`
	Metadata        map[string]any  `json:"metadata,omitempty"`
	// RefundTicketMerchantExternalID is the refund-ticket business identifier (max 128 chars); inherited by the executed refund on PSP success.
	RefundTicketMerchantExternalID *string `json:"refundTicketMerchantExternalId,omitempty"`
}

CreateRefundTicketParams is the input to CustomerSession.CreateRefundTicket.

type CreateStoreParams

type CreateStoreParams struct {
	Name string `json:"name"`
}

CreateStoreParams is the input to Stores.Create.

type CreateStoreResult

type CreateStoreResult struct {
	Store    Store    `json:"store"`
	Warnings []Notice `json:"warnings,omitempty"`
}

CreateStoreResult wraps the response of Stores.Create / Update / Delete.

type CreateSubscriptionProductGroupParams

type CreateSubscriptionProductGroupParams struct {
	StoreID     string      `json:"storeId"`
	Name        string      `json:"name"`
	Description *string     `json:"description,omitempty"`
	Rules       *GroupRules `json:"rules,omitempty"`
	ProductIDs  []string    `json:"productIds,omitempty"`
}

CreateSubscriptionProductGroupParams is the input to SubscriptionProductGroups.Create.

type CreateSubscriptionProductParams

type CreateSubscriptionProductParams struct {
	StoreID       string         `json:"storeId"`
	Name          string         `json:"name"`
	BillingPeriod BillingPeriod  `json:"billingPeriod"`
	Prices        Prices         `json:"prices"`
	Description   *string        `json:"description,omitempty"`
	Media         []MediaItem    `json:"media,omitempty"`
	SuccessURL    *string        `json:"successUrl,omitempty"`
	Metadata      map[string]any `json:"metadata,omitempty"`
}

CreateSubscriptionProductParams is the input to SubscriptionProducts.Create.

type CustomerGraphQLResource added in v0.5.0

type CustomerGraphQLResource struct {
	// contains filtered or unexported fields
}

CustomerGraphQLResource runs customer-scoped GraphQL queries.

func (*CustomerGraphQLResource) Query added in v0.5.0

Query executes a GraphQL query scoped to the customer's data.

type CustomerSession added in v0.5.0

type CustomerSession struct {
	// GraphQL runs customer-scoped GraphQL queries.
	GraphQL *CustomerGraphQLResource
	// contains filtered or unexported fields
}

CustomerSession exposes the customer self-service API surface backed by a session token. Construct via Client.Customer. All HTTP methods use Bearer authentication.

func (*CustomerSession) CancelOnetimeOrder added in v0.5.0

CancelOnetimeOrder cancels a one-time order whose payment is still pending.

func (*CustomerSession) CancelSubscription added in v0.5.0

CancelSubscription cancels a customer's subscription order.

  • pending -> canceled
  • active -> canceling (the PSP cancellation is confirmed asynchronously)

func (*CustomerSession) CreateRefundTicket added in v0.5.0

CreateRefundTicket submits a refund request for a payment.

func (*CustomerSession) ReactivateSubscription added in v0.5.0

ReactivateSubscription reactivates a subscription currently in the "canceling" state.

func (*CustomerSession) ResubmitRefundTicket added in v0.5.0

ResubmitRefundTicket resubmits a previously rejected refund ticket with updated details.

type DeleteStoreParams

type DeleteStoreParams struct {
	ID string `json:"id"`
}

DeleteStoreParams is the input to Stores.Delete (soft delete).

type DeleteStoreResult

type DeleteStoreResult = CreateStoreResult

DeleteStoreResult mirrors CreateStoreResult; aliased for ergonomics.

type DeleteSubscriptionProductGroupParams

type DeleteSubscriptionProductGroupParams struct {
	ID string `json:"id"`
}

DeleteSubscriptionProductGroupParams is the input to SubscriptionProductGroups.Delete (hard delete).

type EntityStatus

type EntityStatus string

EntityStatus is the lifecycle state of a store entity.

const (
	EntityStatusActive    EntityStatus = "active"
	EntityStatusInactive  EntityStatus = "inactive"
	EntityStatusSuspended EntityStatus = "suspended"
)

type Environment

type Environment string

Environment identifies which side of the test/prod boundary a resource belongs to.

const (
	EnvironmentTest Environment = "test"
	EnvironmentProd Environment = "prod"
)

type Error

type Error struct {
	Status int
	Errors []APIError
}

Error is thrown when the API returns a non-success response, and is also the error type produced by client-side validation failures (status 400 with Layer == ErrorLayerSDK). Use errors.As to extract it from a returned error.

var perr *pancake.Error
if errors.As(err, &perr) {
    fmt.Println(perr.Status, perr.Errors[0].Message)
}

func (*Error) Error

func (e *Error) Error() string

Error returns the deepest error message in the chain, or a generic message when the chain is empty.

type ErrorLayer

type ErrorLayer string

ErrorLayer identifies the layer where an API error originated. SDK-side validation failures carry the special value ErrorLayerSDK.

const (
	ErrorLayerGateway  ErrorLayer = "gateway"
	ErrorLayerUser     ErrorLayer = "user"
	ErrorLayerStore    ErrorLayer = "store"
	ErrorLayerProduct  ErrorLayer = "product"
	ErrorLayerOrder    ErrorLayer = "order"
	ErrorLayerTicket   ErrorLayer = "ticket"
	ErrorLayerGraphQL  ErrorLayer = "graphql"
	ErrorLayerResource ErrorLayer = "resource"
	ErrorLayerEmail    ErrorLayer = "email"
	ErrorLayerSDK      ErrorLayer = "sdk"
)

type GraphQLError deprecated

type GraphQLError = Notice

GraphQLError is the legacy name for {@link Notice}. Same shape (the unified Notice already includes Locations / Path for graphql-js errors). Kept as a type alias for backwards compatibility with existing imports.

Deprecated: use Notice.

type GraphQLErrorLocation

type GraphQLErrorLocation struct {
	Line   int `json:"line"`
	Column int `json:"column"`
}

GraphQLErrorLocation marks a position in the query string for diagnostics.

type GraphQLParams

type GraphQLParams struct {
	Query     string         `json:"query"`
	Variables map[string]any `json:"variables,omitempty"`
}

GraphQLParams is a GraphQL query string with optional variables.

type GraphQLResource

type GraphQLResource struct {
	// contains filtered or unexported fields
}

GraphQLResource runs GraphQL queries at the merchant scope (Query only, no Mutations).

func (*GraphQLResource) Query

Query executes a GraphQL query. Data is returned as raw JSON bytes; pass it through json.Unmarshal or use GraphQLQuery for static-typed access.

Example:

resp, err := client.GraphQL.Query(ctx, pancake.GraphQLParams{
    Query: `query { stores { id name status } }`,
})
var data struct {
    Stores []pancake.Store `json:"stores"`
}
_ = json.Unmarshal(resp.Data, &data)

type GraphQLResponse

type GraphQLResponse struct {
	Data     json.RawMessage `json:"data"`
	Errors   []Notice        `json:"errors,omitempty"`
	Warnings []Notice        `json:"warnings,omitempty"`
}

GraphQLResponse is the untyped GraphQL response — Data is left as raw bytes so callers can unmarshal into whichever struct they prefer.

type GraphQLWarning deprecated

type GraphQLWarning = Notice

GraphQLWarning is the legacy name for {@link Notice}. Kept as a type alias.

Deprecated: use Notice.

type GroupRules

type GroupRules struct {
	SharedTrial bool `json:"sharedTrial"`
}

GroupRules controls cross-product behavior within a subscription group.

type IssueSessionTokenParams

type IssueSessionTokenParams struct {
	// BuyerIdentity is encoded into the JWT payload for merchant-side
	// customer identification. Accepts an email or any merchant-provided identifier
	// string. To pre-fill the checkout page's email input use BuyerEmail on
	// Checkout.Authenticated.Create instead.
	BuyerIdentity string  `json:"buyerIdentity"`
	StoreID       *string `json:"storeId,omitempty"`
	ProductID     *string `json:"productId,omitempty"`
}

IssueSessionTokenParams names the customer for whom a session token should be minted. Provide either StoreID or ProductID — when only ProductID is given the server derives the store from the product.

type MediaItem

type MediaItem struct {
	Type      MediaType `json:"type"`
	URL       string    `json:"url"`
	Alt       *string   `json:"alt,omitempty"`
	Thumbnail *string   `json:"thumbnail,omitempty"`
}

MediaItem is a single image or video attached to a product.

type MediaType

type MediaType string

MediaType is the kind of a product media asset.

const (
	MediaTypeImage MediaType = "image"
	MediaTypeVideo MediaType = "video"
)

type Notice added in v0.2.0

type Notice struct {
	Message string     `json:"message"`
	Layer   ErrorLayer `json:"layer,omitempty"`
	AIHint  string     `json:"aiHint,omitempty"`
	// GraphQL-only fields. omitempty so REST callers don't see them in output.
	Locations []GraphQLErrorLocation `json:"locations,omitempty"`
	Path      []string               `json:"path,omitempty"`
}

Notice is a single entry of the call-stack-ordered errors / warnings arrays returned by the API. The deepest layer is at index 0; outermost at the last index. Same shape across REST and GraphQL — GraphQL-specific fields (Locations, Path) are populated only by graphql-js resolver errors.

type NotificationSettings

type NotificationSettings struct {
	EmailOrderConfirmation        *bool `json:"emailOrderConfirmation,omitempty"`
	EmailSubscriptionConfirmation *bool `json:"emailSubscriptionConfirmation,omitempty"`
	EmailSubscriptionCycled       *bool `json:"emailSubscriptionCycled,omitempty"`
	EmailSubscriptionCanceled     *bool `json:"emailSubscriptionCanceled,omitempty"`
	EmailSubscriptionRevoked      *bool `json:"emailSubscriptionRevoked,omitempty"`
	EmailSubscriptionPastDue      *bool `json:"emailSubscriptionPastDue,omitempty"`
	EmailTrialStarted             *bool `json:"emailTrialStarted,omitempty"`
	EmailTrialEnding              *bool `json:"emailTrialEnding,omitempty"`
	NotifyNewOrders               *bool `json:"notifyNewOrders,omitempty"`
	NotifyNewSubscriptions        *bool `json:"notifyNewSubscriptions,omitempty"`
	NotifySubscriptionCanceled    *bool `json:"notifySubscriptionCanceled,omitempty"`
	NotifySubscriptionEnded       *bool `json:"notifySubscriptionEnded,omitempty"`
	NotifySubscriptionPastDue     *bool `json:"notifySubscriptionPastDue,omitempty"`
	NotifySubscriptionRenewed     *bool `json:"notifySubscriptionRenewed,omitempty"`
	NotifySubscriptionUncanceled  *bool `json:"notifySubscriptionUncanceled,omitempty"`
	NotifySubscriptionUpdated     *bool `json:"notifySubscriptionUpdated,omitempty"`
	NotifyChargeback              *bool `json:"notifyChargeback,omitempty"`
	NotifyPayoutCompleted         *bool `json:"notifyPayoutCompleted,omitempty"`
	NotifyPayoutFailed            *bool `json:"notifyPayoutFailed,omitempty"`
}

NotificationSettings holds the merchant's email and dashboard notification preferences. All fields are optional on input (omit to keep server-side value); the response always carries the full set.

Email* toggles (Email…) are managed by the PANCAKE platform (admin-only via DB) and are silently dropped if passed to the merchant update-store endpoint. Only Notify* toggles are merchant-writable.

type Nullable

type Nullable[T any] struct {
	Value T
	// Valid reports whether the field is present on the wire. When false the
	// field is omitted entirely (works with `json:",omitempty"` on the
	// containing struct).
	Valid bool
	// Null, when Valid is true, emits the literal JSON null.
	Null bool
}

Nullable expresses a tri-state JSON field: absent, explicit null, or a concrete value. Use it for fields that distinguish "leave unchanged" from "clear to null" — for example UpdateStoreParams.Logo.

// Absent (do not send the field)
var x pancake.Nullable[string]

// Explicit null (send "logo": null to clear)
x := pancake.ExplicitNull[string]()

// Concrete value
x := pancake.NullValue("https://example.com/logo.png")

func ExplicitNull

func ExplicitNull[T any]() Nullable[T]

ExplicitNull returns a Nullable that emits literal JSON null on the wire — the way to clear a server-side field.

func ExplicitNullPtr

func ExplicitNullPtr[T any]() *Nullable[T]

ExplicitNullPtr is a convenience for `*Nullable[T]` request fields. Returns a pointer to a Nullable that emits literal JSON null.

UpdateStoreParams{Logo: pancake.ExplicitNullPtr[string]()}

func NullValue

func NullValue[T any](v T) Nullable[T]

NullValue wraps v in a Nullable that emits the value on the wire.

func NullValuePtr

func NullValuePtr[T any](v T) *Nullable[T]

NullValuePtr is a convenience for `*Nullable[T]` request fields. Returns a pointer to a Nullable carrying v.

UpdateStoreParams{Logo: pancake.NullValuePtr("https://example.com/logo.png")}

func (Nullable[T]) IsZero

func (n Nullable[T]) IsZero() bool

IsZero reports whether the Nullable is unset; used by encoding/json when the field is tagged with `omitempty` (Go 1.24+ via IsZero) and by direct callers.

func (Nullable[T]) MarshalJSON

func (n Nullable[T]) MarshalJSON() ([]byte, error)

MarshalJSON emits null when Null is set, the wrapped value when not, and returns the JSON "null" token when the wrapper itself is invalid (omitempty at the parent struct will keep the field off the wire).

func (*Nullable[T]) UnmarshalJSON

func (n *Nullable[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON parses null into Null=true and any other value into Value.

type OnetimeOrderStatus

type OnetimeOrderStatus string

OnetimeOrderStatus is the lifecycle state of a one-time order.

const (
	OnetimeOrderStatusPending   OnetimeOrderStatus = "pending"
	OnetimeOrderStatusCompleted OnetimeOrderStatus = "completed"
	OnetimeOrderStatusCanceled  OnetimeOrderStatus = "canceled"
)

type OnetimeProductDetail

type OnetimeProductDetail struct {
	ID          string               `json:"id"`
	StoreID     string               `json:"storeId"`
	Name        string               `json:"name"`
	Description *string              `json:"description"`
	Prices      Prices               `json:"prices"`
	Media       []MediaItem          `json:"media"`
	SuccessURL  *string              `json:"successUrl"`
	Metadata    map[string]any       `json:"metadata"`
	Status      ProductVersionStatus `json:"status"`
	CreatedAt   string               `json:"createdAt"`
	UpdatedAt   string               `json:"updatedAt"`
}

OnetimeProductDetail is the API shape of a one-time product.

type OnetimeProductResult

type OnetimeProductResult struct {
	Product  OnetimeProductDetail `json:"product"`
	Warnings []Notice             `json:"warnings,omitempty"`
}

OnetimeProductResult wraps the response of one-time product endpoints.

type OnetimeProductsResource

type OnetimeProductsResource struct {
	// contains filtered or unexported fields
}

OnetimeProductsResource manages one-time (non-subscription) products.

func (*OnetimeProductsResource) Create

Create creates a one-time product with multi-currency pricing.

func (*OnetimeProductsResource) Publish

Publish promotes a one-time product's test version to production.

func (*OnetimeProductsResource) Update

Update creates a new immutable version of the product and skips when the request would not change anything.

func (*OnetimeProductsResource) UpdateStatus

UpdateStatus flips a one-time product between active and inactive.

type OrdersResource

type OrdersResource struct {
	// contains filtered or unexported fields
}

OrdersResource manages orders. Currently only subscription cancellation is exposed; one-time order management is performed by customers via CustomerSession.

func (*OrdersResource) CancelSubscription

CancelSubscription cancels a subscription order.

  • pending -> canceled (immediate)
  • active/past_due -> canceling (PSP cancel; webhook updates the status)

Example:

res, err := client.Orders.CancelSubscription(ctx, pancake.CancelSubscriptionParams{
    OrderID: "ORD_...",
})

type PaymentStatus

type PaymentStatus string

PaymentStatus is the lifecycle state of a payment.

const (
	PaymentStatusPending   PaymentStatus = "pending"
	PaymentStatusSucceeded PaymentStatus = "succeeded"
	PaymentStatusFailed    PaymentStatus = "failed"
	PaymentStatusCanceled  PaymentStatus = "canceled"
)

type PriceInfo

type PriceInfo struct {
	Amount      string      `json:"amount"`
	TaxCategory TaxCategory `json:"taxCategory"`
}

PriceInfo is the per-currency price expressed in display units (for example "9.99" for USD, "1000" for JPY).

type Prices

type Prices map[string]PriceInfo

Prices is the multi-currency price map keyed by ISO 4217 currency code.

type ProductVersionStatus

type ProductVersionStatus string

ProductVersionStatus is the lifecycle state of a product version.

const (
	ProductVersionStatusActive   ProductVersionStatus = "active"
	ProductVersionStatusInactive ProductVersionStatus = "inactive"
)

type PublishOnetimeProductParams

type PublishOnetimeProductParams struct {
	ID string `json:"id"`
}

PublishOnetimeProductParams promotes the test version to production.

type PublishSubscriptionProductGroupParams

type PublishSubscriptionProductGroupParams struct {
	ID string `json:"id"`
}

PublishSubscriptionProductGroupParams promotes a test group to production.

type PublishSubscriptionProductParams

type PublishSubscriptionProductParams struct {
	ID string `json:"id"`
}

PublishSubscriptionProductParams promotes the test version to production.

type ReactivateSubscriptionParams

type ReactivateSubscriptionParams struct {
	OrderID string `json:"orderId"`
}

ReactivateSubscriptionParams is the input to CustomerSession.ReactivateSubscription.

type ReactivateSubscriptionResult

type ReactivateSubscriptionResult struct {
	OrderID  string   `json:"orderId"`
	Status   string   `json:"status"`
	Warnings []Notice `json:"warnings,omitempty"`
}

ReactivateSubscriptionResult is the response of ReactivateSubscription.

type RefundStatus

type RefundStatus string

RefundStatus is the final state of a refund execution.

const (
	RefundStatusSucceeded RefundStatus = "succeeded"
	RefundStatusFailed    RefundStatus = "failed"
)

type RefundTicket

type RefundTicket struct {
	ID               string                   `json:"id"`
	Type             string                   `json:"type"`
	Status           string                   `json:"status"`
	SubjectID        string                   `json:"subjectId"`
	SubmitterID      string                   `json:"submitterId"`
	SubmitterType    string                   `json:"submitterType"`
	CurrentVersionID *string                  `json:"currentVersionId"`
	ReviewerID       *string                  `json:"reviewerId"`
	ReviewedAt       *string                  `json:"reviewedAt"`
	ReviewNote       *string                  `json:"reviewNote"`
	RejectReason     *string                  `json:"rejectReason"`
	ExecutedAt       *string                  `json:"executedAt"`
	Metadata         map[string]any           `json:"metadata"`
	VersionNumber    *int                     `json:"versionNumber"`
	VersionData      *RefundTicketVersionData `json:"versionData"`
	// RefundTicketMerchantExternalID is the refund-ticket business identifier (max 128 chars, immutable across resubmits).
	RefundTicketMerchantExternalID *string `json:"refundTicketMerchantExternalId"`
	CreatedAt                      string  `json:"createdAt"`
	UpdatedAt                      string  `json:"updatedAt"`
}

RefundTicket is the entity returned by refund ticket create / resubmit.

type RefundTicketResult

type RefundTicketResult struct {
	Ticket   RefundTicket `json:"ticket"`
	Warnings []Notice     `json:"warnings,omitempty"`
}

RefundTicketResult wraps the refund ticket response envelope.

type RefundTicketStatus

type RefundTicketStatus string

RefundTicketStatus is the lifecycle state of a refund request ticket.

const (
	RefundTicketStatusPending     RefundTicketStatus = "pending"
	RefundTicketStatusUnderReview RefundTicketStatus = "under_review"
	RefundTicketStatusApproved    RefundTicketStatus = "approved"
	RefundTicketStatusRejected    RefundTicketStatus = "rejected"
	RefundTicketStatusReturned    RefundTicketStatus = "returned"
	RefundTicketStatusProcessing  RefundTicketStatus = "processing"
	RefundTicketStatusSucceeded   RefundTicketStatus = "succeeded"
	RefundTicketStatusFailed      RefundTicketStatus = "failed"
	RefundTicketStatusCancelled   RefundTicketStatus = "cancelled"
)

type RefundTicketVersionData

type RefundTicketVersionData struct {
	Reason          string           `json:"reason"`
	RequestedAmount *RequestedAmount `json:"requestedAmount"`
}

RefundTicketVersionData holds the per-submission data of a refund ticket.

type RemoveMerchantParams

type RemoveMerchantParams struct {
	StoreID    string `json:"storeId"`
	MerchantID string `json:"merchantId"`
}

RemoveMerchantParams is the input to StoreMerchants.Remove.

type RemoveMerchantResult

type RemoveMerchantResult struct {
	Message   string   `json:"message"`
	RemovedAt string   `json:"removedAt"`
	Warnings  []Notice `json:"warnings,omitempty"`
}

RemoveMerchantResult is the response of StoreMerchants.Remove.

type RemoveWebhookParams

type RemoveWebhookParams struct {
	ID string `json:"id"`
}

RemoveWebhookParams is the input to Webhooks.Remove.

type RemoveWebhookResult

type RemoveWebhookResult = AddWebhookResult

RemoveWebhookResult mirrors AddWebhookResult.

type RequestedAmount

type RequestedAmount struct {
	Amount   string `json:"amount"`
	Currency string `json:"currency"`
}

RequestedAmount specifies the amount and currency for a refund request.

type ResubmitRefundTicketParams

type ResubmitRefundTicketParams struct {
	TicketID        string          `json:"ticketId"`
	PaymentID       string          `json:"paymentId"`
	Reason          string          `json:"reason"`
	RequestedAmount RequestedAmount `json:"requestedAmount"`
}

ResubmitRefundTicketParams is the input to CustomerSession.ResubmitRefundTicket.

type ScanAction added in v0.6.0

type ScanAction string

ScanAction is the final content-safety verdict — continue to generation only when ScanActionAllow.

const (
	ScanActionAllow  ScanAction = "allow"
	ScanActionReview ScanAction = "review"
	ScanActionBlock  ScanAction = "block"
)

type ScanPolicyCategory added in v0.6.0

type ScanPolicyCategory string

ScanPolicyCategory is a matched content-safety policy category.

const (
	ScanPolicyCategoryCsamMinor                   ScanPolicyCategory = "csam_minor"
	ScanPolicyCategorySexualViolenceNonconsensual ScanPolicyCategory = "sexual_violence_nonconsensual"
	ScanPolicyCategoryUndressTransform            ScanPolicyCategory = "undress_transform"
	ScanPolicyCategoryFaceSwapIdentity            ScanPolicyCategory = "face_swap_identity"
	ScanPolicyCategoryBestialityRestricted        ScanPolicyCategory = "bestiality_restricted"
	ScanPolicyCategoryAdultNsfw                   ScanPolicyCategory = "adult_nsfw"
)

type ScanPromptParams added in v0.6.0

type ScanPromptParams struct {
	Prompt   string           `json:"prompt"`
	Locale   string           `json:"locale,omitempty"`
	Semantic ScanSemanticMode `json:"semantic,omitempty"`
}

ScanPromptParams is the input to ContentSafety.ScanPrompt.

type ScanReasonCode added in v0.6.0

type ScanReasonCode string

ScanReasonCode is the stable machine-readable reason for a scan verdict.

const (
	ScanReasonCodeAllowed           ScanReasonCode = "allowed"
	ScanReasonCodeReviewRequired    ScanReasonCode = "review_required"
	ScanReasonCodeRestrictedContent ScanReasonCode = "restricted_content"
	ScanReasonCodeServiceDegraded   ScanReasonCode = "service_degraded"
)

type ScanResult added in v0.6.0

type ScanResult struct {
	Action            ScanAction           `json:"action"`
	ReasonCode        ScanReasonCode       `json:"reasonCode"`
	MatchedCategories []ScanPolicyCategory `json:"matchedCategories"`
	RequestID         string               `json:"requestId"`
	SemanticStatus    ScanSemanticStatus   `json:"semanticStatus"`
	Warnings          []Notice             `json:"warnings,omitempty"`
}

ScanResult is the redacted verdict of ContentSafety.ScanPrompt — no scores, thresholds, or keyword text. Continue to generation only when Action is ScanActionAllow.

type ScanSemanticMode added in v0.6.0

type ScanSemanticMode string

ScanSemanticMode controls how the external semantic channel participates in a scan.

const (
	ScanSemanticModeOff     ScanSemanticMode = "off"
	ScanSemanticModeShadow  ScanSemanticMode = "shadow"
	ScanSemanticModeEnforce ScanSemanticMode = "enforce"
)

type ScanSemanticStatus added in v0.6.0

type ScanSemanticStatus string

ScanSemanticStatus reports whether/how the semantic channel contributed to a scan.

const (
	ScanSemanticStatusDisabled          ScanSemanticStatus = "disabled"
	ScanSemanticStatusScored            ScanSemanticStatus = "scored"
	ScanSemanticStatusShadowScored      ScanSemanticStatus = "shadow_scored"
	ScanSemanticStatusSkippedRulesBlock ScanSemanticStatus = "skipped_rules_block"
	ScanSemanticStatusSkippedBudget     ScanSemanticStatus = "skipped_budget"
	ScanSemanticStatusProviderTimeout   ScanSemanticStatus = "provider_timeout"
	ScanSemanticStatusProviderError     ScanSemanticStatus = "provider_error"
)

type SessionToken

type SessionToken struct {
	Token     string   `json:"token"`
	ExpiresAt string   `json:"expiresAt"`
	Warnings  []Notice `json:"warnings,omitempty"`
}

SessionToken is the issued JWT plus its absolute expiration timestamp.

type Store

type Store struct {
	ID                   string                `json:"id"`
	Name                 string                `json:"name"`
	Status               EntityStatus          `json:"status"`
	SupportEmail         *string               `json:"supportEmail"`
	Website              *string               `json:"website"`
	Slug                 *string               `json:"slug"`
	ProdEnabled          bool                  `json:"prodEnabled"`
	NotificationSettings *NotificationSettings `json:"notificationSettings"`
	CheckoutSettings     *CheckoutSettings     `json:"checkoutSettings"`
	DeletedAt            *string               `json:"deletedAt"`
	CreatedAt            string                `json:"createdAt"`
	UpdatedAt            string                `json:"updatedAt"`
}

Store is the store entity returned by Stores.Create / Update / Delete.

type StoreMerchantsResource

type StoreMerchantsResource struct {
	// contains filtered or unexported fields
}

StoreMerchantsResource manages store membership.

Coming soon — the underlying endpoints currently return HTTP 501.

func (*StoreMerchantsResource) Add

Add invites a merchant to a store with the given role ("admin" or "member").

func (*StoreMerchantsResource) Remove

Remove removes a merchant from a store.

func (*StoreMerchantsResource) UpdateRole

UpdateRole changes a merchant's role within a store.

type StoreRole

type StoreRole string

StoreRole is a store membership role.

const (
	StoreRoleOwner  StoreRole = "owner"
	StoreRoleAdmin  StoreRole = "admin"
	StoreRoleMember StoreRole = "member"
)

type StoreWebhook

type StoreWebhook struct {
	ID        string             `json:"id"`
	StoreID   string             `json:"storeId"`
	Channel   WebhookChannel     `json:"channel"`
	URL       string             `json:"url"`
	Events    []WebhookEventType `json:"events"`
	TestMode  bool               `json:"testMode"`
	Secret    *string            `json:"secret"`
	CreatedAt string             `json:"createdAt"`
	UpdatedAt string             `json:"updatedAt"`
}

StoreWebhook is a configured webhook endpoint as stored in store_webhooks.

type StoresResource

type StoresResource struct {
	// contains filtered or unexported fields
}

StoresResource manages stores: create, update, and soft-delete.

func (*StoresResource) Create

Create creates a new store. Slug is generated server-side from Name.

Example:

res, err := client.Stores.Create(ctx, pancake.CreateStoreParams{Name: "My Store"})
fmt.Println(res.Store.ID) // "STO_..."

func (*StoresResource) Delete

Delete soft-deletes a store. Only the store owner can delete.

Example:

res, err := client.Stores.Delete(ctx, pancake.DeleteStoreParams{ID: "STO_..."})

func (*StoresResource) Update

Update updates an existing store's settings. Only provided fields are changed; NotificationSettings and CheckoutSettings accept partial updates with Nullable used to distinguish "leave unchanged" from "clear to null".

Example:

res, err := client.Stores.Update(ctx, pancake.UpdateStoreParams{
    ID:           "STO_...",
    Logo:         pancake.ExplicitNullPtr[string](),
    SupportEmail: pancake.NullValuePtr("help@example.com"),
})

type SubscriptionOrderStatus

type SubscriptionOrderStatus string

SubscriptionOrderStatus is the lifecycle state of a subscription order.

State machine:

  • pending -> active, canceled, closed
  • active -> canceling, past_due, canceled, expired
  • canceling -> active, canceled
  • past_due -> active, canceled
  • closed -> terminal
  • canceled -> terminal
  • expired -> terminal
const (
	SubscriptionOrderStatusPending   SubscriptionOrderStatus = "pending"
	SubscriptionOrderStatusActive    SubscriptionOrderStatus = "active"
	SubscriptionOrderStatusCanceling SubscriptionOrderStatus = "canceling"
	SubscriptionOrderStatusPastDue   SubscriptionOrderStatus = "past_due"
	SubscriptionOrderStatusClosed    SubscriptionOrderStatus = "closed"
	SubscriptionOrderStatusCanceled  SubscriptionOrderStatus = "canceled"
	SubscriptionOrderStatusExpired   SubscriptionOrderStatus = "expired"
)

type SubscriptionProductDetail

type SubscriptionProductDetail struct {
	ID            string               `json:"id"`
	StoreID       string               `json:"storeId"`
	Name          string               `json:"name"`
	Description   *string              `json:"description"`
	BillingPeriod BillingPeriod        `json:"billingPeriod"`
	Prices        Prices               `json:"prices"`
	Media         []MediaItem          `json:"media"`
	SuccessURL    *string              `json:"successUrl"`
	Metadata      map[string]any       `json:"metadata"`
	Status        ProductVersionStatus `json:"status"`
	CreatedAt     string               `json:"createdAt"`
	UpdatedAt     string               `json:"updatedAt"`
}

SubscriptionProductDetail is the API shape of a subscription product.

type SubscriptionProductGroup

type SubscriptionProductGroup struct {
	ID          string      `json:"id"`
	StoreID     string      `json:"storeId"`
	Name        string      `json:"name"`
	Description *string     `json:"description"`
	Rules       GroupRules  `json:"rules"`
	ProductIDs  []string    `json:"productIds"`
	Environment Environment `json:"environment"`
	CreatedAt   string      `json:"createdAt"`
	UpdatedAt   string      `json:"updatedAt"`
}

SubscriptionProductGroup is the API shape of a subscription product group.

type SubscriptionProductGroupResult

type SubscriptionProductGroupResult struct {
	Group    SubscriptionProductGroup `json:"group"`
	Warnings []Notice                 `json:"warnings,omitempty"`
}

SubscriptionProductGroupResult wraps the response of group endpoints.

type SubscriptionProductGroupsResource

type SubscriptionProductGroupsResource struct {
	// contains filtered or unexported fields
}

SubscriptionProductGroupsResource manages groups of related subscription products (shared trial, plan switching).

func (*SubscriptionProductGroupsResource) Create

Create creates a subscription product group.

func (*SubscriptionProductGroupsResource) Delete

Delete hard-deletes a subscription product group.

func (*SubscriptionProductGroupsResource) Publish

Publish promotes a test-environment group to production (upsert).

func (*SubscriptionProductGroupsResource) Update

Update updates a subscription product group. ProductIDs is a full replacement, not a merge.

type SubscriptionProductResult

type SubscriptionProductResult struct {
	Product  SubscriptionProductDetail `json:"product"`
	Warnings []Notice                  `json:"warnings,omitempty"`
}

SubscriptionProductResult wraps the response of subscription endpoints.

type SubscriptionProductsResource

type SubscriptionProductsResource struct {
	// contains filtered or unexported fields
}

SubscriptionProductsResource manages recurring subscription products.

func (*SubscriptionProductsResource) Create

Create creates a subscription product with billing period and pricing.

func (*SubscriptionProductsResource) Publish

Publish promotes a subscription product's test version to production.

func (*SubscriptionProductsResource) Update

Update creates a new immutable subscription product version.

func (*SubscriptionProductsResource) UpdateStatus

UpdateStatus flips a subscription product between active and inactive.

type TaxCategory

type TaxCategory string

TaxCategory classifies a product for tax computation purposes.

const (
	TaxCategoryDigitalGoods        TaxCategory = "digital_goods"
	TaxCategorySaaS                TaxCategory = "saas"
	TaxCategorySoftware            TaxCategory = "software"
	TaxCategoryEbook               TaxCategory = "ebook"
	TaxCategoryOnlineCourse        TaxCategory = "online_course"
	TaxCategoryConsulting          TaxCategory = "consulting"
	TaxCategoryProfessionalService TaxCategory = "professional_service"
)

type TypedGraphQLResponse

type TypedGraphQLResponse[T any] struct {
	Data     T                `json:"data"`
	Errors   []GraphQLError   `json:"errors,omitempty"`
	Warnings []GraphQLWarning `json:"warnings,omitempty"`
}

TypedGraphQLResponse is the typed GraphQL response produced by GraphQLQuery / CustomerGraphQLQuery.

func BuyerGraphQLQuery deprecated

func BuyerGraphQLQuery[T any](ctx context.Context, s *CustomerSession, p GraphQLParams) (*TypedGraphQLResponse[T], error)

BuyerGraphQLQuery executes a customer-scoped GraphQL query and unmarshals the response data into a caller-provided struct type T.

Deprecated: Use CustomerGraphQLQuery instead.

func CustomerGraphQLQuery added in v0.5.0

func CustomerGraphQLQuery[T any](ctx context.Context, s *CustomerSession, p GraphQLParams) (*TypedGraphQLResponse[T], error)

CustomerGraphQLQuery executes a customer-scoped GraphQL query and unmarshals the response data into a caller-provided struct type T.

Example:

type OrdersQuery struct {
    Orders []struct {
        ID     string `json:"id"`
        Status string `json:"status"`
    } `json:"orders"`
}
resp, err := pancake.CustomerGraphQLQuery[OrdersQuery](ctx, customer, pancake.GraphQLParams{
    Query: `query { orders { id status } }`,
})

func GraphQLQuery

func GraphQLQuery[T any](ctx context.Context, c *Client, p GraphQLParams) (*TypedGraphQLResponse[T], error)

GraphQLQuery executes a merchant-scoped GraphQL query and unmarshals the response data into a caller-provided struct type T.

Example:

type StoresQuery struct {
    Stores []pancake.Store `json:"stores"`
}
resp, err := pancake.GraphQLQuery[StoresQuery](ctx, client, pancake.GraphQLParams{
    Query: `query { stores { id name status } }`,
})
fmt.Println(resp.Data.Stores[0].Name)

type TypedWebhookEvent

type TypedWebhookEvent[T any] struct {
	ID        string      `json:"id"`
	Timestamp string      `json:"timestamp"`
	EventType string      `json:"eventType"`
	EventID   string      `json:"eventId"`
	StoreID   string      `json:"storeId"`
	StoreName string      `json:"storeName"`
	Mode      Environment `json:"mode"`
	Data      T           `json:"data"`
}

TypedWebhookEvent is the typed envelope produced by VerifyWebhookTyped.

func VerifyWebhookTyped

func VerifyWebhookTyped[T any](payload, signatureHeader string, opts *VerifyWebhookOptions) (*TypedWebhookEvent[T], error)

VerifyWebhookTyped is VerifyWebhook with the event payload unmarshaled into a caller-provided struct type T.

Example:

event, err := pancake.VerifyWebhookTyped[pancake.WebhookEventData](body, sig, nil)

type UpdateOnetimeProductParams

type UpdateOnetimeProductParams struct {
	ID          string         `json:"id"`
	Name        *string        `json:"name,omitempty"`
	Prices      Prices         `json:"prices,omitempty"`
	Description *string        `json:"description,omitempty"`
	Media       []MediaItem    `json:"media,omitempty"`
	SuccessURL  *string        `json:"successUrl,omitempty"`
	Metadata    map[string]any `json:"metadata,omitempty"`
}

UpdateOnetimeProductParams is the input to OnetimeProducts.Update. The server creates a new immutable version and skips when nothing has changed.

type UpdateOnetimeStatusParams

type UpdateOnetimeStatusParams struct {
	ID     string               `json:"id"`
	Status ProductVersionStatus `json:"status"`
}

UpdateOnetimeStatusParams flips between active and inactive.

type UpdateRoleParams

type UpdateRoleParams struct {
	StoreID    string `json:"storeId"`
	MerchantID string `json:"merchantId"`
	Role       string `json:"role"`
}

UpdateRoleParams is the input to StoreMerchants.UpdateRole.

type UpdateRoleResult

type UpdateRoleResult struct {
	StoreID    string   `json:"storeId"`
	MerchantID string   `json:"merchantId"`
	Role       string   `json:"role"`
	UpdatedAt  string   `json:"updatedAt"`
	Warnings   []Notice `json:"warnings,omitempty"`
}

UpdateRoleResult is the response of StoreMerchants.UpdateRole.

type UpdateStoreParams

type UpdateStoreParams struct {
	ID                   string                          `json:"id"`
	Name                 *string                         `json:"name,omitempty"`
	Status               *EntityStatus                   `json:"status,omitempty"`
	SupportEmail         *Nullable[string]               `json:"supportEmail,omitempty"`
	Website              *Nullable[string]               `json:"website,omitempty"`
	NotificationSettings *Nullable[NotificationSettings] `json:"notificationSettings,omitempty"`
	CheckoutSettings     *Nullable[CheckoutSettings]     `json:"checkoutSettings,omitempty"`
}

UpdateStoreParams is the input to Stores.Update. Settings objects accept partial updates — omitted sub-fields keep their existing values, an explicit null clears the whole group.

type UpdateStoreResult

type UpdateStoreResult = CreateStoreResult

UpdateStoreResult mirrors CreateStoreResult; aliased for ergonomics.

type UpdateSubscriptionProductGroupParams

type UpdateSubscriptionProductGroupParams struct {
	ID          string      `json:"id"`
	Name        *string     `json:"name,omitempty"`
	Description *string     `json:"description,omitempty"`
	Rules       *GroupRules `json:"rules,omitempty"`
	ProductIDs  []string    `json:"productIds,omitempty"`
}

UpdateSubscriptionProductGroupParams is the input to SubscriptionProductGroups.Update. ProductIDs is a full replacement, not a merge.

type UpdateSubscriptionProductParams

type UpdateSubscriptionProductParams struct {
	ID            string         `json:"id"`
	Name          *string        `json:"name,omitempty"`
	BillingPeriod *BillingPeriod `json:"billingPeriod,omitempty"`
	Prices        Prices         `json:"prices,omitempty"`
	Description   *string        `json:"description,omitempty"`
	Media         []MediaItem    `json:"media,omitempty"`
	SuccessURL    *string        `json:"successUrl,omitempty"`
	Metadata      map[string]any `json:"metadata,omitempty"`
}

UpdateSubscriptionProductParams is the input to SubscriptionProducts.Update.

type UpdateSubscriptionStatusParams

type UpdateSubscriptionStatusParams struct {
	ID     string               `json:"id"`
	Status ProductVersionStatus `json:"status"`
}

UpdateSubscriptionStatusParams flips between active and inactive.

type UpdateWebhookParams

type UpdateWebhookParams struct {
	ID     string             `json:"id"`
	URL    *string            `json:"url,omitempty"`
	Events []WebhookEventType `json:"events,omitempty"`
	Secret *Nullable[string]  `json:"secret,omitempty"`
}

UpdateWebhookParams is the input to Webhooks.Update. Channel and TestMode are immutable; remove and re-add the webhook to change them.

type UpdateWebhookResult

type UpdateWebhookResult = AddWebhookResult

UpdateWebhookResult mirrors AddWebhookResult.

type VerifyWebhookOptions

type VerifyWebhookOptions struct {
	// Environment forces verification against the named environment's key.
	// When zero, both prod and test keys are tried (prod first).
	Environment Environment
	// ToleranceMS is the replay-protection window in milliseconds. Set to a
	// negative value to disable timestamp checking. Zero (default) is treated
	// as the default 5-minute window.
	ToleranceMS int64
	// PublicKey, when non-empty, overrides all resolution chains and is used
	// directly for verification.
	PublicKey string
	// PublicKeys injects config-level keys into the resolution chain.
	// When using Webhooks.Verify this is set automatically from the client
	// config; standalone callers can pass it directly.
	PublicKeys *WebhookPublicKeys
}

VerifyWebhookOptions tunes VerifyWebhook. The zero value is valid.

type WebhookChannel

type WebhookChannel string

WebhookChannel is the delivery channel of a configured webhook endpoint.

const (
	WebhookChannelHTTP     WebhookChannel = "http"
	WebhookChannelFeishu   WebhookChannel = "feishu"
	WebhookChannelDiscord  WebhookChannel = "discord"
	WebhookChannelTelegram WebhookChannel = "telegram"
	WebhookChannelSlack    WebhookChannel = "slack"
)

type WebhookEvent

type WebhookEvent struct {
	ID        string          `json:"id"`
	Timestamp string          `json:"timestamp"`
	EventType string          `json:"eventType"`
	EventID   string          `json:"eventId"`
	StoreID   string          `json:"storeId"`
	StoreName string          `json:"storeName"`
	Mode      Environment     `json:"mode"`
	Data      json.RawMessage `json:"data"`
}

WebhookEvent is the verified envelope returned by VerifyWebhook. Data is kept as raw bytes so callers may unmarshal it into either WebhookEventData or a custom struct via VerifyWebhookTyped.

func VerifyWebhook

func VerifyWebhook(payload, signatureHeader string, opts *VerifyWebhookOptions) (*WebhookEvent, error)

VerifyWebhook is the standalone webhook verifier. Use it when the surrounding code does not have access to a *Client — for example a small webhook-only service.

Example:

event, err := pancake.VerifyWebhook(string(body), r.Header.Get("X-Waffo-Signature"), nil)

type WebhookEventData

type WebhookEventData struct {
	OrderID                       string  `json:"orderId"`
	OrderStatus                   *string `json:"orderStatus,omitempty"`
	BuyerEmail                    string  `json:"buyerEmail"`
	MerchantProvidedBuyerIdentity *string `json:"merchantProvidedBuyerIdentity,omitempty"`
	// OrderMerchantExternalID is the order business identifier; present on order/payment + refund events (inherited from order).
	OrderMerchantExternalID *string `json:"orderMerchantExternalId,omitempty"`
	// RefundTicketMerchantExternalID is the refund-ticket business identifier; only on refund.* events.
	RefundTicketMerchantExternalID *string           `json:"refundTicketMerchantExternalId,omitempty"`
	Currency                       string            `json:"currency"`
	BillingDetail                  map[string]any    `json:"billingDetail,omitempty"`
	OrderMetadata                  map[string]string `json:"orderMetadata,omitempty"`

	Amount    string   `json:"amount"`
	TaxAmount string   `json:"taxAmount"`
	TaxRate   *float64 `json:"taxRate,omitempty"`
	TaxName   *string  `json:"taxName,omitempty"`
	Subtotal  *string  `json:"subtotal,omitempty"`
	Total     *string  `json:"total,omitempty"`

	ProductName        string            `json:"productName"`
	ProductDescription *string           `json:"productDescription,omitempty"`
	ProductMetadata    map[string]string `json:"productMetadata,omitempty"`

	PaymentID            *string `json:"paymentId,omitempty"`
	PaymentStatus        *string `json:"paymentStatus,omitempty"`
	PaymentMethod        *string `json:"paymentMethod,omitempty"`
	PaymentLast4         *string `json:"paymentLast4,omitempty"`
	PaymentFailureReason *string `json:"paymentFailureReason,omitempty"`
	PaymentDate          *string `json:"paymentDate,omitempty"`

	BillingPeriod      *string `json:"billingPeriod,omitempty"`
	CurrentPeriodStart *string `json:"currentPeriodStart,omitempty"`
	CurrentPeriodEnd   *string `json:"currentPeriodEnd,omitempty"`
	CanceledAt         *string `json:"canceledAt,omitempty"`

	RefundStatus    *string `json:"refundStatus,omitempty"`
	RefundReason    *string `json:"refundReason,omitempty"`
	RefundCreatedAt *string `json:"refundCreatedAt,omitempty"`
}

WebhookEventData is the canonical payload shape of a webhook event. Many fields are conditional on the event type — for example refund.* events populate the refund.* fields while leaving the subscription.* fields nil.

type WebhookEventType

type WebhookEventType string

WebhookEventType is the kind of business event delivered by a webhook.

const (
	WebhookEventTypeOrderCompleted               WebhookEventType = "order.completed"
	WebhookEventTypeSubscriptionActivated        WebhookEventType = "subscription.activated"
	WebhookEventTypeSubscriptionPaymentSucceeded WebhookEventType = "subscription.payment_succeeded"
	WebhookEventTypeSubscriptionCanceling        WebhookEventType = "subscription.canceling"
	WebhookEventTypeSubscriptionUncanceled       WebhookEventType = "subscription.uncanceled"
	WebhookEventTypeSubscriptionUpdated          WebhookEventType = "subscription.updated"
	WebhookEventTypeSubscriptionCanceled         WebhookEventType = "subscription.canceled"
	WebhookEventTypeSubscriptionPastDue          WebhookEventType = "subscription.past_due"
	WebhookEventTypeRefundSucceeded              WebhookEventType = "refund.succeeded"
	WebhookEventTypeRefundFailed                 WebhookEventType = "refund.failed"
)

type WebhookPublicKeys

type WebhookPublicKeys struct {
	// Shared is the single key used for both environments. Mutually exclusive
	// with Test/Prod.
	Shared string
	Test   string
	Prod   string
}

WebhookPublicKeys configures the public key(s) used to verify webhook signatures. A single string is shared between test and prod; the struct variant is used to set keys per environment.

func (WebhookPublicKeys) IsZero

func (k WebhookPublicKeys) IsZero() bool

IsZero reports whether no keys are configured.

type WebhooksResource

type WebhooksResource struct {
	// contains filtered or unexported fields
}

WebhooksResource manages webhook configuration (Add / Update / Remove) and verifies inbound webhook signatures (Verify). Verification is a local cryptographic operation and does not perform any I/O.

func (*WebhooksResource) Add

Add registers a webhook endpoint on a store.

Example:

res, err := client.Webhooks.Add(ctx, pancake.AddWebhookParams{
    StoreID:  "STO_...",
    Channel:  pancake.WebhookChannelHTTP,
    URL:      "https://example.com/webhooks",
    Events:   []pancake.WebhookEventType{pancake.WebhookEventTypeOrderCompleted},
    TestMode: false,
})

func (*WebhooksResource) Remove

Remove hard-deletes a webhook. Historical delivery records are retained with a nulled-out webhook reference for audit purposes.

func (*WebhooksResource) Update

Update updates a webhook's mutable fields (URL, events, secret). Channel and TestMode are immutable — remove and re-add to change them.

func (*WebhooksResource) Verify

func (r *WebhooksResource) Verify(payload, signatureHeader string, opts *VerifyWebhookOptions) (*WebhookEvent, error)

Verify validates the X-Waffo-Signature header against payload using the configured public key chain. Config-level public keys are merged into the resolution chain automatically.

Example:

event, err := client.Webhooks.Verify(rawBody, r.Header.Get("X-Waffo-Signature"), nil)

Directories

Path Synopsis
examples
basic command
Basic example: create a client and a store, then create a one-time product.
Basic example: create a client and a store, then create a one-time product.
checkout command
Checkout example: create an authenticated checkout session.
Checkout example: create an authenticated checkout session.
customer command
Customer example: issue a session token and use CustomerSession to cancel a subscription and submit a refund request.
Customer example: issue a session token and use CustomerSession to cancel a subscription and submit a refund request.
webhook command
Webhook example: HTTP handler that verifies an inbound Waffo Pancake event.
Webhook example: HTTP handler that verifies an inbound Waffo Pancake event.
internal
signing
Package signing implements RSA-SHA256 request signing and PEM key normalization.
Package signing implements RSA-SHA256 request signing and PEM key normalization.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL