InComm Processor and API
This reference describes the active asynchronous InComm issuer and the deprecated synchronous issuer that can still appear in historical sales. It covers the provider calls, card mapping, retry states, configuration, audit evidence, and operational tools implemented in the repository.
Processor modes and scope
InCommAsyncProcessor is the active issuer. The issuer migration marks it as asynchronous, and a later migration moves brands from InCommSyncProcessor to it. InCommSyncProcessor is marked deprecated and is retained because its side effects are not known.
| Capability | Async issuer | Legacy sync issuer |
|---|---|---|
| Create call | POST /orders | POST /orders/immediate |
| Card retrieval | Queue-driven getByOrder(orderUri) | In-process polling of /orders/{orderUri}/cards |
| Processor reference | orderUri from the Location header | orderUri from the create response |
| Balance | Supported; requires a PIN at the processor interface | Supported |
| Cancellation | Supported through card lookup and void | Supported through card lookup and void |
| Cashout | No implementation in the async class | cashoutGC() returns false |
The HTTP client accepts CAD, USD, AUD, and NZD environments. The legacy constructor resolves program IDs for CAD, USD, and AUD; the active async constructor resolves all four.
Async lifecycle
- The sale is assigned to
InCommAsyncProcessorand the processor resolves the SKU from the brand and face value. requestCode()sends an order with the sale UUID as bothcustomerorderidandpurchaseordernumber. The partner database ID is included in JSONmetadata.- InComm normally returns
202 Acceptedwith aLocationheader. The wrapper extracts the final path segment asorderUri, stores it asprocessor_ref, and returns a pending card. - A returned card with a provider reference is handed to
AsyncFetchCode; a pending card without a usable reference is requeued for another issue attempt. A duplicate response for the same customer order supplies the existingorderUri, after which the job schedulesAsyncFetchCode. retrieveCode()callsGET /cards/order/{orderUri}and uses the first returned card. A successful response is mapped to the application card and completes the sale.- Balance lookup first finds the original sale by gift-card code, retrieves its order card, then calls
GET /cards/{cardUri}/balance. Cancellation retrieves the card URI and callsPOST /Cards/{cardUri}/void.
The legacy sync path calls the provider create operation and then polls /orders/{orderUri}/cards up to 10 times, sleeping one second between attempts. It maps the first returned card in the same call rather than handing retrieval to AsyncFetchCode.
!WARNING Do not create a replacement order while the sale is pending. A request timeout can occur after InComm accepts the order, and a replacement can create a second provider purchase unless the existing
orderUriis checked first.
Redacted request and response examples
The async request is JSON. Values below are synthetic or redacted; they are not suitable for a live order.
{
"customerorderid": "sale-uuid-example",
"purchaseordernumber": "sale-uuid-example",
"metadata": "{\"partner_id\":12345}",
"recipients": [
{
"firstname": "Application",
"lastname": "Gift Card",
"emailaddress": "redacted@example.invalid",
"deliveremail": false,
"products": [
{
"sku": "SKU-EXAMPLE",
"quantity": 1,
"value": 25
}
]
}
]
}
For 202 Accepted, the provider response used by the wrapper is represented by its relevant header:
HTTP/1.1 202 Accepted
Location: https://provider.example/orders/order-uri-example
The card lookup returns an array. The processor consumes the first item and maps the relevant fields as follows:
[
{
"CertificateLink": "https://provider.example/cert/redacted",
"CardNumber": "[REDACTED]",
"Pin": "[REDACTED]",
"Auxiliary": "[REDACTED]",
"ExpirationDate": "2030-12-31T23:59:59Z",
"CardUri": "card-uri-example",
"Sku": "SKU-EXAMPLE"
}
]
CardNumber becomes the application code, Pin becomes the PIN, ExpirationDate is formatted as an ISO-8601 string, and CertificateLink becomes the third-party URL. CardUri is required for balance and void operations. Card numbers, PINs, auxiliary values, and certificate links must be redacted in tickets and examples.
Response mapping and validation
The async create response is considered successful only when the provider wrapper receives 202; the body exposed to the processor contains the extracted orderUri. A 409 Conflict is not treated as a new order: the wrapper extracts the existing order URI from Location into response headers, and the processor records the sale as requested so retrieval can continue.
The retrieval response must be a successful card array with a first card. The processor sets application status to success, then maps cardNumber, pin, expirationDate, and certificateLink. If the brand has use_auxiliary_as_barcode_string and a barcode URL was generated, auxiliary replaces the barcode string and a new barcode URL is generated.
The provider resource also exposes orderStatus, programId, customerOrderId, totalFaceValue, and related order fields, but the async issue path stores the extracted order URI and the first card fields rather than interpreting a separate order-state field. A missing SKU fails before the provider request. An empty or malformed provider response can fail during card selection or mapping and must remain an error, not be presented as a successful card.
Provider outcomes, retries, and duplicate risk
| Provider outcome | Async handling | Operational meaning |
|---|---|---|
202 Accepted | Store orderUri; leave the card requested/pending | The order was accepted, but card details are obtained separately |
409 Conflict | Read the existing orderUri from Location; continue to retrieval | The customer order ID already exists; do not create another order |
400–499, except 409 | The processor raises an API error instead of returning a retry card; outer job handling leaves the sale retryable | Check SKU, authorization, program access, URI, inventory, and reseller balance |
500–599 | Retry the issue job with a five-minute step and a five-hour maximum delay, up to MAX_RETRIES | Treat as a provider or gateway failure, while checking whether the original order was accepted |
| Other issue failure | Retry with the processor backoff and a five-minute maximum delay while attempts remain | Inspect the recorded status and response |
| Retrieval failure | Keep the card pending and retry with retrieval backoff while attempts remain | Card details are not yet available or the lookup failed |
The async processor sets MAX_RETRIES to 10. Issue attempts and retrieval attempts use separate card metadata counters. The queue job also avoids processing a sale already marked successful. These controls reduce duplicate work, but they cannot prove that a network failure happened before or after provider acceptance; sale UUID, purchaseordernumber, and orderUri are the idempotency investigation keys.
Audit and reconciliation fields
Compare the following fields without copying sensitive card data into a ticket:
| Local or audit field | InComm value to compare |
|---|---|
| Sale UUID | customerorderid; also async purchaseordernumber |
| Legacy client request ID | Sync purchaseordernumber |
| Partner ID | JSON metadata.partner_id |
| Face value and currency | Product value and the selected currency environment |
| Brand mapping | Product sku and the matching incomm-sku attribute |
| Entity/program context | ProgramId request header and the resolved currency/entity program ID |
| Processor reference | orderUri from Location, stored as processor_ref |
| Card identity | cardUri; compare only a masked card number or last four digits if policy permits |
| Completion data | Expiry, presence of PIN, certificate-link presence, and barcode source |
For provider calls that return or throw an InComm response, the async client records each request/response sequence in its API history and labels authentication traffic separately for /auth/token. The sync implementation records only the last request and response for each call. Processor interaction logs and the sale audit record therefore need to be read together, especially after a retry or duplicate response.
Settings and brand mappings
config/incomm.php reads these environment-backed settings:
| Setting | Environment variable | Purpose |
|---|---|---|
| Application base URL | INCOMM_APP_URL | Base URI for program and catalogue calls |
| API base URL | INCOMM_API_URL | Base URI for order and card calls |
| Shared client credentials | INCOMM_CLIENT_ID, INCOMM_CLIENT_SECRET | Client identity and secret |
| Reward Cloud program IDs | INCOMM_CAD_PROGRAM_ID, INCOMM_USD_PROGRAM_ID, INCOMM_AUD_PROGRAM_ID, INCOMM_NZD_PROGRAM_ID | Default program per currency |
| Tillo entity overrides | INCOMM_*_TILLOINC_PROGRAM_ID | tilloinc program per currency |
| Asset-update notification | SLACK_INCOMM_CARD_IMAGE_UPDATE_WEBHOOK | Slack destination for changed card images |
The processor first resolves a program for the sale owner’s Tillo entity and currency, then falls back to the Reward Cloud program for that currency when the override is empty. Each brand uses incomm-sku for an open-value product or incomm-sku-<denomination> for a fixed-denomination product. The fixed-denomination key uses the denomination formatted as a float. use_auxiliary_as_barcode_string is optional and affects barcode generation only.
API operations and operational tools
| Operation | Endpoint or command | Use |
|---|---|---|
| Authenticate | POST /auth/token | Client-credentials token; form fields include client_id, client_secret, and grant_type |
| Async order | POST /orders | Create the provider order; 202 uses Location |
| Legacy sync order | POST /orders/immediate | Create and return an order with card links in the synchronous flow |
| Async order cards | GET /cards/order/{orderUri} | Retrieve cards for async completion and balance lookup |
| Legacy order cards | GET /orders/{orderUri}/cards | Poll cards in the sync flow and find a card for cancellation |
| Card balance | GET /cards/{cardUri}/balance | Retrieve current balance |
| Card void | POST /Cards/{cardUri}/void | Deactivate a card |
| Programs | GET /programs/programs | List programs for a currency environment |
| Catalogues | GET /programs/programs/{programId}/catalogs | List program catalogues |
| Catalogue assets | GET /programs/programs/{programId}/catalogs/{catalogId}/assets | Refresh retailer assets |
| Retailer refresh | php artisan rewardcloud:check-incomm-retailers | Update redemption instructions, terms, descriptions, and recent card-image attributes for matching SKUs |
Investigation checklist
- Confirm the issuer:
incomm-asyncfor current issuance orincomm-syncfor a historical sale. - Record the sale UUID, client request ID, sale status, currency, amount, delivery method, brand slug, and
processor_ref. - Confirm the selected SKU and program ID, including the owner’s Tillo entity and the Reward Cloud fallback.
- Compare the audited create request with the provider status and
Locationheader. For409, use the existing order URI rather than a new order. - Follow the order URI through the card lookup and check the first card’s card URI, expiry, PIN presence, certificate-link presence, and barcode source without exposing the raw values.
- For balance, verify that the original sale was found by code and that the order lookup returned a card URI before checking
/balance. - For cancellation, verify the original processor reference, the cancellation sale’s partner audit context, and the
/voidresponse. - Check async authentication, request, response, and exception audit records; for sync calls, check the last request/response pair.
- Check retry metadata and whether a timeout could have occurred after provider acceptance.
Limitations and support
The active async issuer does not expose a cashout operation. Balance lookup is provider-card based and requires a code and PIN at the processor interface. The repository’s InComm issuer onboarding migration does not define a support-contact attribute, so no InComm email address is documented here. Use the approved internal processor escalation route and include identifiers, timestamps, status codes, safe field comparisons, and audit evidence; never include credentials, full card numbers, PINs, auxiliary values, or live certificate links.
Related code
app/Processors/InCommAsyncProcessor.php— active async issue, retrieval, balance, cancellation, mapping, and retry handling.app/Processors/InCommSyncProcessor.php— deprecated synchronous issue, polling, balance, and cancellation behavior.app/Processors/Api/InComm/InComm.php— selects program, order, card, and fulfilment API resources.app/Processors/Api/InComm/Http/Order.php— async and sync order endpoints andLocation/Linkextraction.app/Processors/Api/InComm/Http/Card.php— card retrieval, balance, and void endpoints.app/Processors/Api/InComm/Http/HttpClient.php— currency environments, token caching, program headers, and API history.config/incomm.php— API URLs, credentials, program IDs, and Slack notification configuration.app/Console/Commands/UpdateInCommRetailersCommand.php— retailer asset and metadata refresh.app/Jobs/AsyncProcessRequest.phpandapp/Jobs/AsyncFetchCode.php— pending, duplicate, and retrieval queue transitions.tests/Feature/Processors/IncommAsyncProcessorTest.php— async accepted, conflict, authentication, retrieval, barcode, balance, and audit scenarios.database/migrations/2021_11_01_122948_r_c_c-9119-move-incomm-sync-brands-to-async.php— migration of existing brands to the async issuer.