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 ¶
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 )
Variables ¶
This section is empty.
Functions ¶
func Metered ¶
func Metered(v contracts.IAPVerifier, m Meter) contracts.IAPVerifier
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. Apple publishes the
// "Apple Root CA - G3" certificate for this.
RootCertsPEM []byte
}
AppleConfig configures the Apple verifier.
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.
func (*AppleVerifier) Platform ¶
func (a *AppleVerifier) Platform() contracts.IAPPlatform
func (*AppleVerifier) VerifyReceipt ¶
func (a *AppleVerifier) VerifyReceipt(ctx context.Context, p contracts.ReceiptParams) (*contracts.IAPEntitlement, error)
VerifyReceipt verifies a StoreKit 2 signed transaction 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) 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.
func (*GoogleVerifier) Platform ¶
func (g *GoogleVerifier) Platform() contracts.IAPPlatform
func (*GoogleVerifier) VerifyReceipt ¶
func (g *GoogleVerifier) VerifyReceipt(ctx context.Context, p contracts.ReceiptParams) (*contracts.IAPEntitlement, error)
VerifyReceipt looks a purchase up against the Android Publisher API.
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 ¶
func (m *LocalMeter) Authorize(_ context.Context, t MeteredTransaction) (Decision, error)
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.