Skip to content
TilloTech Docs

GoGift v2 Processor and API

This reference is for operations and customer-service teams. It describes the GoGift v2 basket and webhook lifecycle, the fields required before a sale can complete, and the evidence to collect before retrying or escalating.

What GoGift v2 does

GoGift v2 is an asynchronous basket processor with catalogue support and webhook delivery. The application creates a basket, adds one product, finalises the basket, and stores the resulting order ID. GoGift v2 then sends fulfilment data to the configured webhook; retrieval reads that locally stored response.

PropertyBehaviour
Processor typeSKU per denomination with a brand-level product ID
ProcessingAsynchronous basket update and finalisation, followed by webhook-backed retrieval
DeliveryDigital gift-card URL with a PIN appended during mapping
Balance lookupUnsupported
CancellationUnsupported
CatalogueSupported through product list and product-by-ID operations
Provider completion evidenceA valid webhook payload containing orderId, giftcardUri, and pin

Order lifecycle

  1. The sale supplies the brand, face value, currency, transaction reference, and delivery method.
  2. The interaction reads the brand product_id attribute and the denomination SKU for the requested face value.
  3. A basket is created with sales channel ID 109. The returned id is required and is cached against the transaction reference for seven days.
  4. The basket is updated with the B2B department, product ID, SKU, currency, integer gift-card value, transaction reference, and the application confirmation webhook URL. The update clears existing basket products and adds one product with delivery method Webhook.
  5. The basket is finalised with payment method InvoiceByFinance. The returned orderId becomes the processor reference.
  6. GoGift v2 sends a signed webhook. The handler validates the request headers and signature, validates the first content item, finds the sale by processor reference, stores the encrypted payload, writes a response audit record, and dispatches asynchronous code retrieval.
  7. Retrieval validates the stored payload and maps its URL and PIN. After a successful sale response is produced, a cleanup job is delayed by 30 seconds before deleting the stored webhook response.

Example API order flow

The following examples use illustrative values. API keys, bearer tokens, webhook signatures, PINs, and live gift-card URLs are intentionally omitted.

Create, update, and finalise a basket

The API uses bearer authentication. Create sends POST baskets/:

json
{ "salesChannelId": 109 }

The response must contain a basket ID:

json
{ "id": "<basket-id>" }

Update sends PUT baskets/ with an idempotency key of <basket-id>-update:

json
{
  "id": "<basket-id>",
  "buyer": {
    "accountId": "<b2b-department-id>",
    "accountType": "B2BDepartment",
    "name": "Tillo",
    "email": "noreply@tillo.io",
    "phone": "[REDACTED]",
    "address": { "countryCode": "GB" }
  },
  "addProducts": {
    "deliveryMethod": "Webhook",
    "recipientName": "Tillo",
    "recipientWebhookUrl": "https://<application-host>/webhook/<processor>/confirmation",
    "stockKeepingUnit": "<denomination-sku>",
    "productId": "<product-id>",
    "quantity": 1,
    "valueCurrency": "GBP",
    "giftCardValue": 10,
    "productReference": "<transaction-reference>"
  },
  "doClearProducts": true,
  "reference": "<transaction-reference>"
}

Finalise sends POST baskets/finalize/ with idempotency key <basket-id>-finalize:

json
{
  "basketId": "<basket-id>",
  "paymentMethod": "InvoiceByFinance"
}

The finalisation response must contain the provider order ID:

json
{ "orderId": "<gogift-order-id>" }

Webhook and retrieval

The webhook request must contain Signature, X-Request-Datetime, X-Client-ID, and X-Request-ID. The signature header has a signature="..." value; the application verifies it using the request method, those headers, a SHA-256 body digest, and the configured webhook secret. A redacted body example is:

json
{
  "content": [
    {
      "orderId": "<gogift-order-id>",
      "giftcardUri": "https://<provider-host>/giftcard/<redacted>",
      "pin": "[REDACTED]",
      "expiresAt": "<provider-expiry-or-omitted>"
    }
  ]
}

The handler returns HTTP 200 after validation and processing. Retrieval then maps the stored payload to:

json
{
  "processor_reference": "<gogift-order-id>",
  "url": "https://<provider-host>/giftcard/<redacted>/[REDACTED]",
  "expiration_date": "<ISO-8601-or-null>"
}

The URL above is illustrative only. Do not place a real provider URL or PIN in an incident record.

Response mapping and validation

Provider response or recordApplication result
Create basket idCached as go-gift-v2-basket-id-<transaction-reference>; missing id prevents issuance
Finalise response orderIdReturned as processor_reference; missing orderId prevents issuance
Webhook content.0.orderIdUsed to locate the sale and returned as processor_reference; required
Webhook content.0.giftcardUriMust be a URL; concatenated with / and content.0.pin to form the returned url
Webhook content.0.pinRequired and appended to the provider URI; never copy it into support notes
Webhook content.0.expiresAtOptional; when present it is converted to an ISO-8601 expiration_date
Webhook payloadStored against sale_uuid in go_gift_v2_webhook_responses and encrypted by the model cast

Only the first item, content.0, is validated and mapped. Update-basket response content is not parsed for completion; finalisation and the later webhook provide the required evidence. A missing or invalid webhook field raises webhook handling or response validation failure rather than producing a partial voucher response.

Provider states and retry behaviour

ConditionIntegration behaviourOperational consequence
Network failure, HTTP 429, or unexpected server-side failure during create, update, or finaliseRaises RetryableRequestExceptionRetry the same operation only after checking the existing basket and audit trail
Other HTTP client failures, such as authentication, malformed request, not found, or resource conflictRaises ProcessorInteractionExceptionCorrect configuration or data, or escalate; do not blindly repeat the sale
Create response missing idResponse validation failureNo basket ID is available to continue; inspect the raw response
Finalise response missing orderIdResponse validation failureThe basket outcome is uncertain; check the basket and provider audit before any new order
Valid webhook for a processing saleStores or updates the response, audits it, and dispatches AsyncFetchCodeRetrieval can process the voucher payload
Webhook for SUCCESS, ERROR, or CANCELLED saleReturns HTTP 200 without storing a new payloadA duplicate or late callback is acknowledged and ignored
No stored webhook response during retrievalRaises WebhookResponseNotFoundExceptionTreat fulfilment as unresolved; there is no API status fallback in this interaction

The basket ID cache lasts 604800 seconds (one week). Update and finalise use idempotency keys derived from that basket ID, so a retry with the same cached basket can be correlated to the original provider actions. A manual re-order or a retry after the cache has expired can create a new basket and duplicate fulfilment; resolve the original basket and order first.

Audit comparison fields

Compare the following values across application and provider records:

  1. Internal sale UUID and transaction reference against productReference, reference, and the cache key used for the basket.
  2. Brand product_id, denomination SKU, currency, integer gift-card value, and basket ID against the update payload.
  3. Update and finalise idempotency keys against the basket ID and operation (<basket-id>-update and <basket-id>-finalize).
  4. Finalise orderId against the stored processor reference and webhook content.0.orderId.
  5. Webhook X-Request-ID, request timestamp, sale UUID, webhook-response record ID, and the response-audit timestamp.
  6. Sale status and the presence of a stored payload before retrying retrieval. Inspect voucher-field presence without copying the URL or PIN into a ticket.

The webhook handler writes the received body to the processor interaction response audit. Treat that audit and the encrypted database payload as sensitive evidence; record field names, identifiers, states, and timestamps rather than voucher values.

Settings

Processor settings

config/go-gift-v2.php reads these environment-backed settings:

SettingEnvironment variable
API base URIGO_GIFT_V2_API_URI
OAuth/token base URIGO_GIFT_V2_AUTH_URI
API secretGO_GIFT_V2_API_SECRET
OAuth client IDGO_GIFT_V2_CLIENT_ID
B2B department/client IDGO_GIFT_V2_B2B_DEPARTMENT_ID
HTTP timeoutGO_GIFT_V2_TIMEOUT
Webhook signature secretGO_GIFT_V2_WEBHOOK_SIGNATURE

The API client obtains an OAuth client-credentials token from <auth-base-uri>/connect/token, caches the access token, and sends it as a bearer token. Never expose the token, API secret, client ID, or webhook secret in an audit or escalation.

Brand settings

Each enabled brand requires the GoGift v2 product_id brand attribute and a denomination-level SKU mapping. The processor type migration changed the fixed type to SKU per denomination. Check both values for the requested face value; a valid product ID with a missing or incorrect SKU can produce a basket that does not represent the requested product.

API operations

Client operationProvider pathMethodPurpose
createBasketbaskets/POSTCreate a basket with sales channel ID 109
updateBasketbaskets/PUTReplace basket products with one webhook-delivered item
finalizeBasketbaskets/finalize/POSTFinalise the basket using invoice finance
listAllProductsproducts/filter/POSTCatalogue product listing
getProductByIdproducts/<product-id>/GETRetrieve one catalogue product
Webhook confirmation/webhook/<processor>/confirmationPOSTReceive signed fulfilment data; the application stores it locally

Customer-service investigation

For a delayed or failed sale, collect the internal sale UUID, transaction reference, brand product_id, requested denomination and SKU, currency, basket ID, processor reference/order ID, sale status, and timestamps. Review the ordered create, update, finalise, webhook, and retrieval evidence. For webhook failures, also check the four required headers, client-ID match, signature verification result, and X-Request-ID without recording their secret values.

Before retrying, determine whether create returned a basket ID, whether update and finalise used the expected idempotency keys, and whether finalise may already have returned or created an order. Check the webhook-response record and its sale_uuid before dispatching another retrieval. Do not start a new order until the original basket and provider order have been reconciled.

If the webhook is absent, check provider delivery evidence and the local sale status; retrieval cannot query GoGift v2 for the voucher as a fallback. If the webhook exists but validation fails, compare only the required field names, order ID, URL validity, expiration presence, and audit timestamps. Keep the URI and PIN redacted.

Limitations

Escalations should include the internal sale UUID, transaction reference, basket ID, provider order ID, idempotency keys, webhook request ID and timestamp, sale status, and redacted audit evidence. Do not include bearer tokens, API secrets, webhook signatures, gift-card URLs, or PINs.

  • app/Processors/GoGiftV2/GoGiftV2Processor.php — asynchronous processor and webhook capability.
  • app/Processors/Interaction/Integrations/GoGiftV2/GoGiftV2ProcessorInteraction.php — basket issue flow, cache, idempotency keys, webhook retrieval, validation, and cleanup dispatch.
  • app/Processors/GoGiftV2/GoGiftV2WebhookHandler.php — webhook authentication, sale lookup, storage, auditing, and retrieval dispatch.
  • app/Http/Clients/GoGiftV2/GoGiftV2Api.php — OAuth token handling, transport, headers, and provider operations.
  • app/Http/Clients/GoGiftV2/Requests/CreateBasketRequestData.php — create payload.
  • app/Http/Clients/GoGiftV2/Requests/UpdateBasketRequestData.php — basket update payload.
  • app/Http/Clients/GoGiftV2/Requests/FinalizeBasketRequestData.php — finalisation payload.
  • app/Http/Clients/GoGiftV2/Requests/ListAllProductsRequestData.php — catalogue listing request.
  • app/Http/Clients/GoGiftV2/Requests/GetProductByIdRequestData.php — catalogue product request.
  • config/go-gift-v2.php — API, OAuth, B2B, timeout, and webhook settings.
  • database/migrations/2024_11_11_205846_create_go_gift_v2_processor.php — processor capabilities and technical contact.
  • database/migrations/2024_11_13_095635_rcc-15266_create_go_gift_v2_webhook_responses_table.php — webhook-response storage schema.
  • database/migrations/2025_02_13_141933_modify_go_gift_v2_fixed_processor_type_column.php — denomination SKU processor type.
  • tests/Unit/Processors/Interaction/Integrations/GoGiftV2/GoGiftV2ProcessorInteractionTest.php — basket, retrieval, validation, and retry scenarios.
  • tests/Unit/Processors/GoGiftV2/GoGiftV2WebhookHandlerTest.php — webhook header, signature, payload, sale-state, storage, and dispatch scenarios.