Documentation
¶
Overview ¶
Package server provides the generic challenge-or-verify flow for Payment authentication on the server side.
Examples import this package by its bare name. The Tempo charge package uses the alias `charge`, so there is no conflict.
Package server provides the server-side MPP payment handler.
It implements the HTTP 402 challenge/credential flow: when a request arrives without payment credentials, it returns a 402 with a WWW-Authenticate challenge. When valid credentials are provided, it verifies them and returns a receipt.
Index ¶
- func ChargeMiddleware(m *Mpp, params ChargeParams) func(http.Handler) http.Handler
- func CredentialFromContext(ctx context.Context) *mpp.Credential
- func DetectRealm() string
- func DetectSecretKey() (string, error)
- func ReceiptFromContext(ctx context.Context) *mpp.Receipt
- type ChargeParams
- type ChargeRequestBuilder
- type ChargeResult
- type Intent
- type Method
- type Mpp
- type VerifyParams
- type VerifyResult
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ChargeMiddleware ¶
ChargeMiddleware creates an http.Handler middleware for the charge intent.
It calls Mpp.Charge with the provided ChargeParams, injects the incoming Authorization header automatically, returns a 402 challenge when payment is required, and stores the verified Credential and Receipt in the request context on success.
func CredentialFromContext ¶
func CredentialFromContext(ctx context.Context) *mpp.Credential
CredentialFromContext extracts the Credential from the request context.
func DetectRealm ¶
func DetectRealm() string
DetectRealm auto-detects the server realm from environment variables. It checks MPP_REALM, FLY_APP_NAME, HEROKU_APP_NAME, RAILWAY_PUBLIC_DOMAIN, RENDER_EXTERNAL_HOSTNAME, VERCEL_URL, WEBSITE_HOSTNAME, HOST, and HOSTNAME in that order. Returns "MPP Payment" if none are set.
func DetectSecretKey ¶
DetectSecretKey reads the MPP_SECRET_KEY environment variable. Returns an error if it is not set.
Types ¶
type ChargeParams ¶
type ChargeParams struct {
// Authorization is the incoming Authorization header value.
Authorization string
// Amount is the human-readable charge amount.
Amount string
// Currency overrides the method's default currency.
Currency string
// Recipient overrides the method's default recipient.
Recipient string
// ExternalID is copied into the request and echoed back in the Receipt.
ExternalID string
// Expires overrides the default Challenge expiry.
Expires string
// Description is exposed in the server-generated Challenge.
Description string
// Memo sets a Tempo transfer memo when the method supports it.
Memo string
// Splits adds Tempo split-payment transfers under methodDetails.splits.
Splits []tempo.SplitParams
// FeePayer requests the sponsored Tempo flow when the method supports it.
FeePayer bool
// FeePayerURL points at a remote fee-payer signer.
FeePayerURL string
// SupportedModes advertises the Tempo submission modes allowed for this challenge.
SupportedModes []tempo.ChargeMode
// ChainID overrides the method's default Tempo chain ID.
ChainID int
// Meta stores opaque Challenge metadata.
Meta map[string]string
}
ChargeParams contains the parameters for a charge operation.
type ChargeRequestBuilder ¶
type ChargeRequestBuilder interface {
BuildChargeRequest(params ChargeParams) (map[string]any, error)
}
ChargeRequestBuilder lets a method provide a canonical request shape for the generic charge helper. Tempo uses this to normalize human amounts and nest method-specific fields under methodDetails.
type ChargeResult ¶
type ChargeResult struct {
// Challenge is returned when the client still needs to satisfy the payment.
Challenge *mpp.Challenge
// Credential is the verified client credential on success.
Credential *mpp.Credential
// Receipt acknowledges a successfully verified payment.
Receipt *mpp.Receipt
}
ChargeResult is either a Challenge or a verified (Credential, Receipt) pair.
func (*ChargeResult) IsChallenge ¶
func (r *ChargeResult) IsChallenge() bool
IsChallenge returns true if the result is a 402 challenge.
type Intent ¶
type Intent interface {
Name() string
Verify(ctx context.Context, credential *mpp.Credential, request map[string]any) (*mpp.Receipt, error)
}
Intent is the interface for payment intents (server-side verification).
type Mpp ¶
type Mpp struct {
// contains filtered or unexported fields
}
Mpp is the server-side payment handler.
func (*Mpp) Charge ¶
func (m *Mpp) Charge(ctx context.Context, params ChargeParams) (*ChargeResult, error)
Charge handles a charge intent with human-readable amounts.
type VerifyParams ¶
type VerifyParams struct {
// Authorization is the incoming Authorization header value.
Authorization string
// Intent verifies Credentials for this request.
Intent Intent
// Request is the canonical request shape the Challenge binds to.
Request map[string]any
// Realm is the expected server realm.
Realm string
// SecretKey signs and verifies Challenge IDs.
SecretKey string
// Method is the payment method token, for example "tempo".
Method string
// Description is copied into a newly issued Challenge.
Description string
// Meta stores opaque Challenge metadata.
Meta map[string]string
// Expires overrides the default Challenge expiry.
Expires string
}
VerifyParams contains the parameters for VerifyOrChallenge.
type VerifyResult ¶
type VerifyResult struct {
// Challenge is returned when the server needs the client to pay first.
Challenge *mpp.Challenge
// Credential is the parsed client credential on success.
Credential *mpp.Credential
// Receipt acknowledges successful verification.
Receipt *mpp.Receipt
}
VerifyResult is either a Challenge or a verified (Credential, Receipt) pair.
func VerifyOrChallenge ¶
func VerifyOrChallenge(ctx context.Context, params VerifyParams) (*VerifyResult, error)
VerifyOrChallenge checks for a valid payment credential or generates a new challenge. Returns a Challenge if payment is required, or (Credential, Receipt) if verified.
Logic:
- If no authorization header, create new challenge
- Extract "Payment" scheme from Authorization header
- Parse credential
- Recompute expected challenge ID from echoed parameters via HMAC
- Constant-time compare IDs
- Verify echoed fields match (realm, method, intent name, request)
- Check expiry
- Call intent.Verify
- Return result