iap

package
v1.9.0 Latest Latest
Warning

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

Go to latest
Published: Sep 29, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package iap holds the Apple and Google in-app-purchase verifiers. They live outside the cashier package so their heavier crypto and HTTP dependencies do not weigh on callers who only use card gateways.

Index

Constants

View Source
const (
	// FreeTierMicros is the tracked transaction volume that is free, in micros
	// (2000 * 1_000_000). Past this, transactions are billable.
	FreeTierMicros int64 = 2000 * 1_000_000
	// FeeRatePerMille is the fee beyond the free tier, in parts per thousand:
	// 10‰ = 1%.
	FeeRatePerMille int64 = 10
)
View Source
const AppleRootCAG3PEM = `` /* 847-byte string literal not displayed */

AppleRootCAG3PEM is Apple Root CA - G3, the root every StoreKit 2 JWS and App Store Server Notification V2 chains to. Pass it as AppleConfig's RootCertsPEM.

Source: https://www.apple.com/certificateauthority/AppleRootCA-G3.cer SHA-256: 63:34:3A:BF:B8:9A:6A:03:EB:B5:7E:9B:3F:5F:A7:BE:7C:4F:5C:75:6F:30:17:B3:A8:C4:88:C3:65:3E:91:79 Valid until 30 Apr 2039.

Variables

This section is empty.

Functions

func Metered

Metered wraps a verifier so its entitlements are gated by a meter. Registering the result with IAPManager is what turns a raw verifier into the paid feature.

Types

type AppleConfig

type AppleConfig struct {
	BundleID     string
	AllowSandbox bool
	// RootCertsPEM is Apple's root certificate(s) in PEM. Required: without a
	// pinned root there is nothing to anchor the chain to. AppleRootCAG3PEM is
	// the one Apple uses.
	RootCertsPEM []byte
}

AppleConfig configures the Apple verifier.

type AppleServerAPI added in v1.9.0

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

AppleServerAPI reads subscription state from Apple.

func NewAppleServerAPI added in v1.9.0

func NewAppleServerAPI(cfg AppleServerAPIConfig) (*AppleServerAPI, error)

NewAppleServerAPI builds the client.

func (*AppleServerAPI) SubscriptionStatus added in v1.9.0

func (a *AppleServerAPI) SubscriptionStatus(ctx context.Context, originalTransactionID string) (*contracts.IAPEntitlement, error)

SubscriptionStatus returns the current state of the subscription that originalTransactionID started, trying production first and then sandbox (Apple answers 404 on the wrong environment).

type AppleServerAPIConfig added in v1.9.0

type AppleServerAPIConfig struct {
	IssuerID string
	KeyID    string
	// PrivateKeyPEM is the .p8 file's contents.
	PrivateKeyPEM []byte
	// Verifier checks the signed payloads the API returns (and supplies the
	// bundle id).
	Verifier *AppleVerifier
	// HTTPClient overrides the client; BaseURL and SandboxBaseURL override
	// Apple's hosts (tests).
	HTTPClient     *http.Client
	BaseURL        string
	SandboxBaseURL string
}

AppleServerAPIConfig configures the App Store Server API client.

type AppleVerifier

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

AppleVerifier verifies StoreKit 2 JWS transactions and V2 notifications.

func NewApple

func NewApple(cfg AppleConfig) (*AppleVerifier, error)

NewApple builds the Apple verifier.

func (*AppleVerifier) ParseNotification

func (a *AppleVerifier) ParseNotification(payload []byte) (*contracts.StoreNotification, error)

ParseNotification verifies an App Store Server Notification V2 and reduces it to the canonical shape, including the purchase state it vouches for.

func (*AppleVerifier) Platform

func (a *AppleVerifier) Platform() contracts.IAPPlatform

func (*AppleVerifier) VerifyReceipt

VerifyReceipt verifies a StoreKit 2 signed transaction (and, when the app sends it, the signed renewal info) and returns the entitlement it proves.

type CloudMeter

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

CloudMeter reports transactions to Nimbus Cloud and enforces its decisions.

func NewCloudMeter

func NewCloudMeter(cfg CloudMeterConfig) (*CloudMeter, error)

NewCloudMeter builds a meter backed by Nimbus Cloud.

func (*CloudMeter) Authorize

func (m *CloudMeter) Authorize(ctx context.Context, t MeteredTransaction) (Decision, error)

Authorize reports a transaction and returns Cloud's decision.

type CloudMeterConfig

type CloudMeterConfig struct {
	// APIKey authenticates the developer's Nimbus Cloud account. Required —
	// without it there is no account to meter, so the gate fails closed.
	APIKey string
	// Endpoint overrides the metering URL. Defaults to Nimbus Cloud.
	Endpoint string
	// HTTPClient overrides the client (tests point it at a mock server).
	HTTPClient *http.Client
	// FailClosed makes a Cloud outage deny access instead of granting it. Off
	// by default; see the failure policy above before turning it on.
	FailClosed bool
}

CloudMeterConfig configures the Cloud meter.

type Decision

type Decision struct {
	// Allowed is whether the entitlement may be returned to the app.
	Allowed bool
	// Reason explains a denial, for logs and errors.
	Reason string
	// TrackedVolumeMicros is the account's cumulative tracked volume after this
	// transaction, as the meter understands it.
	TrackedVolumeMicros int64
	// FeeMicros is what this transaction cost (0 within the free tier).
	FeeMicros int64
	// OverFreeTier is whether the account has exhausted the free allowance.
	OverFreeTier bool
	// Reconcile is set when the decision was made locally after a Cloud outage
	// and must be re-reported later. The entitlement was still granted.
	Reconcile bool
}

Decision is the meter's ruling on a transaction.

type GoogleConfig

type GoogleConfig struct {
	// PackageName is the app's package; a purchase is looked up under it.
	PackageName string
	// ServiceAccountJSON is the Google Cloud service-account key with access to
	// the Play Developer API, as downloaded from the console.
	ServiceAccountJSON []byte
}

GoogleConfig configures the Google verifier.

type GoogleVerifier

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

GoogleVerifier verifies Google Play purchases via the Android Publisher API.

func NewGoogle

func NewGoogle(cfg GoogleConfig) (*GoogleVerifier, error)

NewGoogle builds the Google verifier.

func (*GoogleVerifier) Acknowledge added in v1.9.0

func (g *GoogleVerifier) Acknowledge(ctx context.Context, productID, token string, subscription bool) error

Acknowledge confirms a purchase to Google. Google refunds and revokes any purchase left unacknowledged for three days, so a server that grants access must acknowledge it. Acknowledging an acknowledged purchase is harmless.

func (*GoogleVerifier) ParseNotification

func (g *GoogleVerifier) ParseNotification(payload []byte) (*contracts.StoreNotification, error)

ParseNotification decodes a Real-time Developer Notification.

Google's RTDNs are not signed the way Apple's are — authenticity comes from the Pub/Sub push being authenticated at the transport, not from a signature in the body — so this decodes and canonicalises rather than verifying a signature. The entitlement itself must still be confirmed by calling VerifyReceipt with the token inside, which is why a forged notification can at worst make the server re-read the truth from Google.

func (*GoogleVerifier) Platform

func (g *GoogleVerifier) Platform() contracts.IAPPlatform

func (*GoogleVerifier) VerifyReceipt

VerifyReceipt looks a purchase up against the Android Publisher API.

The purchase token is the stable identity of a Google purchase — every renewal keeps it, and every notification names it — so it is returned as OriginalTransactionID; the order id of the latest charge is TransactionID.

type LocalMeter

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

LocalMeter is a process-local Meter: it applies the exact tier and fee rules without a network call. It is the default for development and the reference the Cloud meter is tested against, and it always allows — enforcement of an unpaid account is Nimbus Cloud's job, not a local cache's.

func NewLocalMeter

func NewLocalMeter() *LocalMeter

NewLocalMeter builds an in-memory meter for one tenant.

func (*LocalMeter) Authorize

Authorize records the transaction locally and computes its fee.

func (*LocalMeter) TrackedVolume

func (m *LocalMeter) TrackedVolume() int64

TrackedVolume returns the tenant's accumulated volume, for tests and reports.

type Meter

type Meter interface {
	// Authorize records a transaction and rules on whether its entitlement may
	// be granted. It must fail open on transient errors (see the package note).
	Authorize(ctx context.Context, t MeteredTransaction) (Decision, error)
}

Meter authorises and records IAP transactions for billing.

type MeteredTransaction

type MeteredTransaction struct {
	Platform      contracts.IAPPlatform
	TransactionID string
	ProductID     string
	Subject       string
	PriceMicros   int64
	Currency      string
	Environment   string // "sandbox" transactions are never metered
}

MeteredTransaction is one verified purchase reported for metering.

func (MeteredTransaction) Billable

func (t MeteredTransaction) Billable() bool

Billable reports whether a transaction counts toward volume and fees at all. A sandbox purchase or a zero-price event never does.

Jump to

Keyboard shortcuts

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