Skip to content
TilloTech Docs

Diggecard processor reference

This guide describes the implemented Diggecard issuance and account-balance integration, including brand mapping, response validation, audit evidence, and operational risks. Examples show request and response shapes with credentials, URLs, identifiers, and card data redacted.

Processing model

Diggecard is a synchronous processor with a non-vault issuer record. The processor creates one digital gift card through the giftcard endpoint and maps either a claim URL or card number and PIN from the response.

PropertyImplemented behaviour
IssuerDiggecard
Asynchronous processingDisabled in the issuer migration
Processor typesSKU per denomination for fixed brands and SKU per product for open-value brands
Issuance endpointPOST {DIGGECARD_ENDPOINT}giftcard
Balance endpointGET {DIGGECARD_ENDPOINT}account_balance
Accepted success stateHTTP 200 and giftCard.status of active or ACTIVE
Delivery mappingClaim URL when both card number and PIN are empty; otherwise card number, PIN, and claim URL
Cancellation, reissue, and top-upNot implemented by this processor's request builder and response parser

Issuance lifecycle

  1. The synchronous processor receives the brand, partner, face value, currency, and internal sale record.
  2. For a fixed-denomination brand, it looks up diggecard-sku-{amount}. For an open-value brand, it looks up diggecard-sku.
  3. The sale UUID becomes both auditNumber and purchaseOrderNumber.
  4. The processor posts the request to the giftcard endpoint using Basic authentication and a JSON body.
  5. The raw response is written to the processor interaction audit. A non-200 response is treated as an external processor failure.
  6. The JSON response must contain a giftCard object whose status is active or ACTIVE.
  7. If cardExpiry is absent, the application generates an expiry using the brand's expiry-months attribute. If both cardNumber and cardPin are empty, the claim URL is used for delivery; otherwise a non-empty card number is required for code delivery.
  8. The resulting card uses transactionId as the processor reference. The audit record is completed only after response parsing and card creation succeed.

HTTP contract

The endpoint is DIGGECARD_ENDPOINT with giftcard appended. The client sends Accept: application/json, Content-Type: application/json, and an Authorization header of the form Basic <base64-redacted-credentials>. The request timeout is 20 seconds.

Gift-card request

The request body contains the internal sale UUID in both transaction fields:

json
{
  "auditNumber": "<sale-uuid>",
  "purchaseOrderNumber": "<sale-uuid>",
  "vendorCode": "<redacted-brand-code>",
  "cardAmount": "<face-value>",
  "currency": "GBP",
  "delivery": {
    "deliveryType": "api"
  }
}

The repository does not document a provider idempotency key separate from these transaction fields. auditNumber and purchaseOrderNumber are correlation values generated from the sale UUID, not proof that a repeated request is safe.

Gift-card response

A URL-delivery response in the tests has empty card number and PIN values. A code-delivery response has a card number, PIN, and claim URL. Both use the following relevant shape:

json
{
  "transactionId": "<provider-transaction-id>",
  "giftCard": {
    "status": "ACTIVE",
    "cardNumber": "<redacted-or-empty>",
    "cardPin": "<redacted-or-empty>",
    "claimUrl": "<redacted-claim-url>",
    "cardExpiry": "<provider-expiry-or-null>"
  }
}

Do not copy cardNumber, cardPin, claim URLs, or complete provider responses into tickets or chat. The examples are structural and are not reusable card data.

Response mapping and validation

The parser first requires a JSON object. For a create request it then validates giftCard.status as a required string with value active or ACTIVE.

Response pathRule or fallbackInternal card field
transactionIdConverted to a stringprocessor_reference
giftCard.statusRequired; must be active or ACTIVEDetermines whether parsing may continue
giftCard.cardExpiryUsed when presentExpiration date
Missing giftCard.cardExpiryGenerated from the brand expiry-months attributeExpiration date
Empty giftCard.cardNumber and giftCard.cardPinTreated as URL deliveryEmpty code and PIN; claimUrl becomes the URL
Non-empty card datacardNumber must be non-emptyCode, PIN, and claimUrl are mapped

An invalid JSON body, missing or inactive status, or an empty card number in a response that is not the URL-only shape produces an external processor error. The parser does not define meanings for provider statuses other than the two accepted active spellings. For example, the feature test uses PROCESSING as a failure case; it must not be treated as a completed sale.

Provider states and error handling

The application distinguishes the following observable states:

Observable stateApplication behaviour
HTTP 200 with active gift cardParse and complete the card
HTTP 200 with another statusReject with the message that the gift card was not active
HTTP non-200Log the response and raise an external processor error
HTTP 400 with an errors arrayPreserve the response in the audit and expose a generic external error to the API caller
Connection, timeout, or request exceptionConvert to an external processor error after logging available details
Missing vendor codeFail before sending because brand mapping is incomplete
Missing partner credentialsFail while generating the Basic authorization header

Provider error-code semantics are not enumerated in the implementation. The errors payload and HTTP status are evidence, not a documented state machine.

Retry and duplicate risks

SyncProcessorCommon defaults maxAttempts to 1, and DiggecardProcessor does not override it. Issuance therefore has no automatic retry in this integration. A timeout or connection failure after the provider receives the giftcard request leaves the outcome unknown; submitting the same sale again can create a second card unless the provider confirms idempotency or reconciles the original auditNumber and purchaseOrderNumber.

Do not retry an uncertain issuance blindly. First compare the audit request and response, search for a provider transactionId, and escalate the sale UUID and timestamps to the internal processor owner or Diggecard account team. A non-active response is not evidence that no card was created; it only means this parser did not complete the sale.

Authentication, settings, and brand mappings

config/diggecard.php defines these environment-backed values:

Configuration areaValues
Global accountDIGGECARD_USERNAME, DIGGECARD_PASSWORD, and DIGGECARD_ENDPOINT
Balance alertsEnable flag, GBP and EUR thresholds, and recipient setting
Partner accountsreward-gateway, giftcloud, and epay-youchoose, each with username, password, and useOwnAccount

For reward-relationship partners, the processor uses the global account unless the partner configuration explicitly selects its own account. Otherwise it uses the configured partner credentials when both are present. The balance operation falls back to the global account. Credentials must remain in environment configuration and must be redacted from operational evidence.

Brand attributes

The vendor-code lookup is database-backed:

Brand modeAttribute readRequired setup
Fixed denominationsdiggecard-sku-{amount}One vendor code for each supported amount
Open valuediggecard-skuOne product vendor code plus the brand's open-value limits
Expiry fallbackexpiry-monthsUsed only when Diggecard omits cardExpiry

The migrations provide these onboarding facts:

  • River Island was moved to Diggecard as open value with limits of 2 to 250.
  • The Body Shop, TK Maxx, Arsenal, River Island, HomeSense, National Trust, and Eurostar were configured as open-value examples with limits recorded in the onboarding migration.
  • ASK Italian, Waterstones, Zizzi, Hobbycraft, Jojo Maman Bébé, and Virgin Wines were configured as fixed-denomination examples.
  • IKEA UK was configured as URL-only with fixed GBP denominations of 5, 10, 15, 20, 25, 50, 75, 100, 150, 200, 250, 500, and 1000 in the onboarding migration.
  • Mango was configured as URL-only with fixed denominations of 25 and 50 GBP. Its historical vendor-code migration records denomination codes for 20, 25, 50, 75, 100, 150, and 200.
  • A later migration moved vendor codes into brand attributes. The current processor reads those attributes rather than a diggecard.brands configuration block.
  • The November 2025 migration removed returnsUrl attributes. The current parser uses the returned claimUrl for the URL-only response shape and does not read returnsUrl.

The onboarding migrations are historical records, not a guarantee that every listed brand is currently active. Verify the live brand row, issuer, delivery method, denomination, and attribute before issuing.

Account-balance operation and command

DiggecardProcessor::getAvailableCreditLimit() sends a credentialed GET request to account_balance. It requires HTTP 200 and returns the raw response body. The implementation does not validate the shape in this method; the scheduled command decodes the body and reads accountBalances.

The command is:

text
rewardcloud:check-available-diggecard-credit-limit

It exits with failure without calling Diggecard when DIGGECARD_LOW_CREDIT_ALERT_ENABLED is false. With alerts enabled, it records a FileExportCommand, reads each returned account balance, applies the configured GBP or EUR threshold, and sends the low-balance alert only in production or sandbox unless --override-recipient-email is supplied. --no-send generates the report path without sending email. The command has no option to change the provider account or threshold.

Audit comparison fields

The processor writes the request and response to ProcessorInteractionAuditLog and also maintains the normal processor audit record. Compare the following values without exposing secrets or card data:

EvidenceFields to compare
Internal saleSale UUID, partner, brand, face value, currency, delivery method, and request timestamp
Gift-card requestauditNumber, purchaseOrderNumber, vendorCode, cardAmount, currency, and delivery.deliveryType
Gift-card responseHTTP status, transactionId, giftCard.status, expiry presence, and whether the URL-only or code shape was returned
Completed cardProcessor reference, delivery URL presence, expiry, and completion state
Error pathHTTP status/reason, provider errors or error description, exception log message, and attempt number
Balance checkCommand run, account-balance currency and amount, threshold, environment, recipient mode, and --no-send state

The audit model encrypts stored content and supports redaction when a redactor is attached. Support extracts should still be manually checked before sharing; encryption is not a reason to publish live voucher or card values.

Investigation checklist

  1. Confirm the sale UUID, partner slug, brand slug, face value, currency, and requested delivery method.
  2. Confirm whether the brand is fixed or open value and check the exact diggecard-sku-{amount} or diggecard-sku attribute.
  3. Confirm the issuer is Diggecard and that the requested delivery method is enabled for the brand and partner.
  4. Check partner financial relationship and the effective credential source: global account or partner account.
  5. Compare the redacted request fields, especially both transaction fields, vendor code, amount, and currency.
  6. Check the HTTP status and response body shape. An active status must be exactly active or ACTIVE.
  7. If the response is URL-only, verify that both card number and PIN are empty and that claimUrl is present. If it is code delivery, verify that cardNumber is non-empty.
  8. Check whether cardExpiry was returned or generated from the brand expiry-months attribute.
  9. For an uncertain timeout, search the audit for transactionId and do not issue a replacement until the original outcome is reconciled.
  10. For a balance alert, check the command log, accountBalances, currency threshold, environment, and recipient override; do not include credentials or balances in an external ticket unless required and approved.
  11. Escalate with the sale UUID, provider transaction reference if known, vendor code, UTC timestamps, HTTP status, and redacted audit excerpts.

Limitations and support contacts

The repository implements synchronous issuance and a balance check, but it does not provide a Diggecard status/reconciliation endpoint, cancellation flow, retry-safe idempotency mechanism, or named provider support contact. The parser does not document provider lifecycle states beyond an accepted active status. Escalate unresolved issuance and balance issues through the internal processor owner or Diggecard account team using the evidence in the checklist.

  • app/Processors/DiggecardProcessor.php — issuance, response parsing, authentication selection, expiry fallback, and balance request.
  • app/Exceptions/Diggecard/DiggecardException.php — Diggecard external error type.
  • app/Processors/SyncProcessorCommon.php — synchronous request lifecycle, audit completion, and default attempt count.
  • config/diggecard.php — global, partner, and balance-alert settings.
  • app/Console/Commands/CheckAvailableDiggecardCreditLimit.php — account-balance command and alert handling.
  • app/ProcessorInteractionAuditLog.php — encrypted processor request and response audit records.
  • database/migrations/2023_05_09_093426_qrf-733_move_diggecard_vendor_codes_into_brand_attributes.php — migration of vendor codes into brand attributes.
  • database/migrations/2023_05_09_110643_qrf-733_update_diggecard_processor_type.php — fixed and open processor types.
  • database/migrations/2025_11_19_132500_rcc_16844_remove_diggecard_returnsUrl_attributes.php — removal of obsolete URL attributes.
  • tests/Feature/Processors/DiggecardProcessorTest.php — URL and code delivery, audit, error, and status validation cases.