Gifting Runtime and API

The Gifting module is a source-neutral runtime for native Payments gifts and post-purchase membership transfers. It intentionally keeps one canonical write owner and lets Payments, Bricks forms, and supported commerce integrations delegate into the same mutation contract.

Module Boundary

  • Owned by Gifting: gift mode resolution, gift writes, gift history reads, shared gift schema, claim flow, source-transfer markers, and recipient account provisioning handoff
  • Owned by Payments: native checkout UI, offer and provider configuration, normalized billing ingest, and provider webhook handling
  • Owned by source integrations: WooCommerce, SureCart, and FluentCart lifecycle hooks plus source-object metadata persistence
  • Not supported: generic webhook gifting

Canonical Owners

  • GiftWriteService — canonical write owner for native gift rows, gift claims, and non-native source transfers
  • GiftHistoryReadService — shared-table read owner for admin history and native lookup reads
  • GiftModeResolver — resolves lightweight transfer mode vs subscription and history mode and normalizes shared gifting settings
  • GiftSchemaService — creates and verifies the shared brm_gifts table when table mode is required
  • GiftClaimController — public adapter for the native claim route and login handoff only; it is not a second write owner
  • UserProvisioningService — duplicate-safe recipient account creation by email

Modes

The gifting runtime has two effective operating modes:

  • Lightweight transfer mode — Gifting active, Payments inactive, and brm_gifting_settings['subscription_history_mode'] disabled. One-time source transfers work without the shared gift table.
  • Subscription and history mode — Payments active or subscription_history_mode enabled. Native gifts, non-native subscription transfers, and stored transfer history all use wp_brm_gifts.

Do not add a third write path around these modes. Mode switching is a read of shared settings, not a different business contract.

Entry Points

  • BootstrapCoordinator to GiftingFeatureRegistrar::boot()
  • Settings save path to SettingsFormHandler to AdminSettingsService
  • Payments admin gifting settings to PaymentsAdminPage to SettingsFormHandler::handle_payments_admin_post() to AdminSettingsService::handle_payments_admin_action()
  • Native checkout request to PaymentsRestController, which validates the gift payload and later hands off to GiftWriteService after billing persistence
  • Bricks transfer action to GiftTransferFormIntegration to GiftWriteService::transfer_source_entitlement()
  • Public claim route to ?brm_action=claim_gift&gift_token=... to GiftClaimController to GiftWriteService::claim_native_gift()

Storage Contract

Shared settings and module flags:

  • brm_enable_gifting
  • brm_gifting_settings['subscription_history_mode']
  • brm_gifting_settings['create_recipient_users']
  • brm_gifting_settings['recipient_default_role']

Native Payments gifting also reads:

  • brm_payments_settings['gifting']
  • brm_payments_offers[$offer_key]['gifting']

Shared table: {$wpdb->prefix}brm_gifts

  • one current-state row per native gift or source transfer in table mode
  • gift_mode discriminates native_checkout vs source_transfer
  • query columns include source identity, payment or subscription refs, offer and level, purchaser, recipient, claim timestamps, transfer timestamps, and context_json
  • context_json is for non-query extras only and must not become canonical lookup truth

Source-object compatibility markers for non-native transfers:

  • _brm_gift_level_id
  • _brm_gift_recipient_user_id
  • _brm_gift_recipient_email
  • _brm_gift_transferred_at

Native Payments Handoff

Native checkout gifting is not a second storage system inside Payments. The runtime path is:

  1. PaymentsRestController validates the incoming gift payload on the hosted checkout route (POST /bricksmembers/v1/billing/checkout) and the embedded checkout route (POST /bricksmembers/v1/billing/create-embedded-checkout).
  2. The provider completes checkout and the billing adapters normalize the payment or subscription mutation.
  3. BillingOrchestratorService persists normalized billing data first.
  4. After that persistence succeeds, the gifting handoff calls GiftWriteService to create or update the native gift row.
  5. BillingAccessSyncService suppresses purchaser access for unclaimed native gifts until claim succeeds.

Do not move native gift schema or write ownership into BillingSchemaService. Payments is an adapter here, not the gift owner.

Non-Native Source Transfers

GiftWriteService::transfer_source_entitlement() is the canonical non-native transfer path.

  • It validates the current purchaser user.
  • It resolves the source object and requires exactly one mapped BRM level.
  • It rejects same-email transfers and duplicate transfers.
  • It finds or creates the recipient user through UserProvisioningService.
  • It adds the level to the recipient, removes the same level from the current holder, writes source markers, and optionally writes a shared history row in table mode.

Subscription-based source transfers are rejected when subscription and history mode is disabled.

Claim Flow

Native gift claims use one public route:

?brm_action=claim_gift&gift_token={token}

GiftClaimController owns route handling, login handoff, queued post-login redirects, and success or error redirect parameters. It does not own the claim mutation. The actual mutation is GiftWriteService::claim_native_gift().

Claim validation includes payment state, expiry, recipient-email matching, and gifted level resolution before the recipient level is granted.

Email and User Provisioning Rules

  • Native claim emails are sent from GiftWriteService through EmailTransportService.
  • When a recipient account is created automatically, wp_send_new_user_notifications() sends the standard WordPress user email.
  • UserProvisioningService is duplicate-safe and does not overwrite existing-user role or profile data unless explicitly asked.

Hooks and Side Effects

  • brm_gift_created
  • brm_gift_paid
  • brm_gift_claimed
  • brm_gift_transferred
  • brm_gift_claim_email_sent

Bricks Integration

The gifting-specific Bricks surface is intentionally small:

  • GiftTransferFormIntegration registers the brm_transfer_gift_level form action.
  • BillingCheckoutElement exposes native gift fields when gifting is available for the resolved offer and provider combination.

Neither surface owns business writes. They validate or collect input and then delegate into GiftWriteService.

Related

Early Bird Deal

Start Building Your Membership Site Today

Create, sell, and manage your content without limits. BricksMembers gives you everything you need to build membership and LMS sites with Bricks Builder.

Lifetime updates & bug fixes • Premium support • 0% transaction fees • 60-day money-back guarantee