Gamend.Payments.Provider behaviour (gamend_core v1.0.1296)

Copy Markdown View Source

Behaviour for a store adapter — Apple, Google, Steam, or a host's own.

A host swaps one out through config:

config :gamend_core, :payment_provider_adapters, apple: MyGame.AppleStub

That seam existed before this behaviour did, which meant the contract was whatever Gamend.Payments happened to call, discoverable only by reading it. The symptom was function_exported?(module, :config_status, 0) guarding every call to an optional callback: a runtime probe standing in for a declaration.

Required

validate_purchase/2 is the one every adapter implements: given the attributes a client submitted, confirm with the store that the purchase is real, and answer with the normalised fields ("environment", "provider_transaction_id", and whatever else the provider knows).

Optional

The rest are per-provider. Steam has a two-step init/finalize flow that the others do not; Apple verifies signed notifications where Google verifies a bearer token on the webhook. Declare only what your store actually does — Gamend.Payments checks before calling, and now checks against this list.

Summary

Payments hooks

Verifies a purchase with the store and returns its normalised fields.

Callbacks

Whether this adapter has the credentials it needs, for the admin console.

Completes a checkout started by init_transaction/3.

Starts a provider-hosted checkout (Steam's init/finalize flow).

Reads back one transaction's current state from the store.

Verifies a signed store notification (Apple's App Store Server V2).

Verifies a webhook's authenticity from its authorization header.

Payments hooks

validate_purchase(user, attrs)

@callback validate_purchase(user :: struct() | nil, attrs()) :: result()

Verifies a purchase with the store and returns its normalised fields.

Types

attrs()

@type attrs() :: map()

result()

@type result() :: {:ok, map()} | {:error, term()}

Callbacks

config_status()

(optional)
@callback config_status() :: %{:configured => boolean(), optional(atom()) => term()}

Whether this adapter has the credentials it needs, for the admin console.

Assumed configured when not implemented.

finalize_transaction(purchase, attrs)

(optional)
@callback finalize_transaction(purchase :: struct(), attrs()) :: result()

Completes a checkout started by init_transaction/3.

init_transaction(purchase, provider_product, attrs)

(optional)
@callback init_transaction(purchase :: struct(), provider_product :: struct(), attrs()) ::
  result()

Starts a provider-hosted checkout (Steam's init/finalize flow).

query_transaction(attrs)

(optional)
@callback query_transaction(attrs()) :: result()

Reads back one transaction's current state from the store.

verify_notification(raw_body)

(optional)
@callback verify_notification(raw_body :: binary()) :: result()

Verifies a signed store notification (Apple's App Store Server V2).

verify_webhook(raw_body, authorization)

(optional)
@callback verify_webhook(raw_body :: binary(), authorization :: String.t() | nil) ::
  result()

Verifies a webhook's authenticity from its authorization header.