Learn how to integrate with payment providers.
Payment extensions allow you to connect InStore to your payment providers. Use the information below to set up connections for credit cards, stored-value cards, digital wallet, and pay on account.
About asynchronous payment processing
200 acknowledgment and continue the payment flow asynchronously.statusUrl, which you can use to send intermediate updates and client messages, and callbackUrl, which you use to send the final payment result. As your payment provider returns updates during processing, your Integration Server can forward that information to InStore by calling these URLs. You can optionally display the updates for users to see throughout the payment process, for example as stepper messages. For some payment types, you can include prompts to collect additional information from the user.At the end of processing, use the callback URL to send the payment provider's final result, which is whether the payment was successful or failed.
Prepare to receive requests from InStore
Details of setting up a custom extension and verifying the signature may vary depending on the programming language, framework, and server setup you are using.
To set up a payment extension, do the following:
-
Set up endpoints on your integration server to receive the payment extension data. You need to create a script or program that listens for incoming requests at a specific URL and supports all endpoints defined for the payment type of the particular extension. You can do this using a variety of programming languages and frameworks, depending on your server setup. InStore sends HTTP POST and GET requests to the URL you specify.
-
Make sure your endpoints can handle the request format used by each action. POST actions use JSON-formatted request and response bodies. GET actions use route or query parameters, as documented for that action.
-
Configure all endpoints to verify the HMAC-SHA256 signature that InStore sends with each request. This signature is a security measure that ensures the data being sent to your endpoint is actually coming from InStore and has not been tampered with in transit.
-
To verify the signature, you'll need to perform the following steps:
- Extract the signature from the incoming proxy request headers. The header key for the signature is
X-Signature. - Compute an HMAC-SHA256 hash over the JSON-stringified request payload, using the
apiKeyvalue that you configured for the extension in the InStore Center. - Compare the generated hash to the signature included in the incoming request headers. If they match, the data has not been tampered with and can be safely processed by your endpoint.
- Once you've verified the signature, you can process the incoming data as needed. This may involve storing it in a database, triggering other actions in your system, or sending a
200response back to acknowledge receipt of the request.
- Extract the signature from the incoming proxy request headers. The header key for the signature is
-
Review the header information, shared request fields, and processor webhook paths below. Ensure that your endpoints are set up to receive and process this data correctly.
-
View the section Send InStore the final result of an asynchronous payment to see the specific data that your payment provider must send back to InStore via the callback URL. Ensure that your payment provider is prepared to return this data in the correct format.
The API key is a symmetric secret, not an asymmetric private key. Both InStore and your extension must hold the same key.
Header information that you receive in all InStore payment requests
| Name | Purpose |
|---|---|
X-Signature | Sends a hash that verifies the current payload value with the API key assigned to the payment processor. |
X-Correlation-Id | Sends an identifier to track the process from all applications: InStore Core, InStore API, and the webhook service. |
X-Transaction-Id | Sends an identifier to track the full checkout transaction from all applications: InStore Core, InStore API, and the webhook service. |
X-API-Key | Sends a key to authenticate the InStore API call to the payment processor service. |
Fields that you receive in all InStore payment requests
| Field | Purpose |
|---|---|
payload_url | Identifies the services to call and always matches the webhook URL payload. |
payload | Sends the request data, which varies with the payment process type. |
verification_signature | Sends a hash that verifies the authenticity of the request. This serves to sign the current payload value with the API key that was assigned to the payment processor. |
tenant_id | Identifies the tenant that is being called. |
requestId | Identifies the current process. |
callbackUrl | Specifies the webhook service you call to send the messages to InStore. |
statusUrl | Specifies the webhook service you call to update status and send messages to the client. |
Processor webhook paths that we provide for specific payment types
| Payment Type | Processor Webhook Path | Purpose |
|---|---|---|
| BankCard | initialize_credit_processor | Requests that your service initialize the payment provider. |
connect_card_reader | Requests that your service connect to the credit reader. | |
capture_payment | Requests the capture of payment. Only applies if the provider supports payment capture before collecting payment. | |
collect_credit_payment | Requests the collection of the payment through a pin entry device (PED). | |
create_credit_refund | Requests a credit refund. | |
cancel_credit_payment | Requests that your service cancel a previous credit payment request. | |
user_response | Sends information that was provided by the user. | |
| GiftCard | storedvaluecard | Requests the creation of a new stored-value card payment. |
storedvaluecard_process | Sends instructions for processing this stored-value card's information. | |
| Wallet | initialize_wallet | Requests the processing of a digital wallet payment. |
pay_wallet | Sends information for processing this wallet payment. | |
cancel_wallet | Requests that your service cancel the wallet payment. | |
refund_wallet | Requests a refund for the wallet payment. | |
| Pay on Account (POA) | pay_on_account | Requests the processing of a pay-on-account payment. |
payonaccount/process | Sends instructions for processing this POA payment's information. | |
payonaccount/create_account | Requests that your service create an account record for this pay-on-account payment. | |
payonaccountlog | Directs your Integration Server to log information about this pay-on-account payment. |
Respond asynchronously to InStore requests
InStore stops accepting messages and updates after receiving the final result of the payment process.
Use the status callback to send updates during an asynchronous payment
statusUrl callback.Use this callback to send optional messages and other updates:
/webhook/payment/:requestId/statusSend intermediate messages and updates to InStore
status callback:{
message: string
severity: string
properties?: object
}
Where
| Field | Purpose |
|---|---|
message | The content of the message to display to the user. For example, "Processing payment...". |
severity | The importance of the message, which can be Info, Warning, or Error. InStore uses this value to determine how to display the message. |
properties | An optional object that contains any additional information that the retailer can use with downstream processing. |
Add user prompts during payment processing
Prompts that require user input during payment are available for select payment types, specifically:
- payments of type Credit
- the
redeemaction for stored-value card payments. No prompts are available for the stored-value card number-retrieval action.
status callback. See Send user prompts.Dynamically replace the timeout for an asynchronous payment
status callback to dynamically replace the default timeout by specifying a different value in the keepAliveMs field within a message block. Use this body:{
"message": "Common.messages.authorizingCard",
"severity": "Info",
"keepAliveMs": 10000
}
keepAliveMs field is set to 10000 milliseconds (10 seconds).Send InStore the final result of an asynchronous payment
The final result of the payment process is sent to InStore using the callback URL. The callback path is the same for all asynchronous payment types, but the payload varies by payment type. Depending on the payment type, the response can use different field names and status values.
After InStore receives the final callback payload, no further updates are accepted.
Use this callback path to send the final result of the payment process:
/webhook/payment/:requestIdMany payment types use a payload shape similar to the following:
{
result: string
data?: object
method?: string
}
Where:
| Field | Purpose |
|---|---|
result | Indicates the final status for payment types that use the result field. Supported values vary by payment type. |
data | Contains payment-type-specific response fields. Some payment types return those fields at the top level instead of inside data. |
method | Is the value that your payment service uses to identify the payment method. If not specified in your result, InStore assigns the method from the payment processor payload. |
Review the examples for your payment type and return the payload shape documented for that payment type.
Sample credit result
collect_credit_payment request through the callback URL:collect_credit_payment{
result: Success | Failed
data: {
cartKey: "123e4567-e89b-12d3-a456-426614174000"
processor: "Brand-X Debit Card"
processor_id: "213121111"
last4: "4242"
brand: "visa"
account_type: "credit"
application_preferred_name: null
dedicated_file_name: null
authorization_response_code: "3030"
application_cryptogram: null
terminal_verification_results: null
transaction_status_information: null
amount: {
amount: 123
currency: "USD"
precision: 2
timestamp: "2024-06-02T14:20:55.488Z"
}
}
}
Where
| Attribute | Type | Description |
|---|---|---|
cartKey | String | Unique identifier for the cart, which was generated by InStore. |
processor | String | The label that represents this payment method in the Total area of the payment page. |
processor_id | String | The identifier for the payment processor that was used for the transaction. |
last4 | String | Last four digits of the credit card number. |
brand | String | Brand of the credit card. |
account_type | String | Type of card account, such as credit or debit. |
application_preferred_name | String | Cardholder's name as displayed on their credit or debit card. |
dedicated_file_name | String | Identifier used by the card issuer. |
authorization_response_code | String | Code that indicates the status of the transaction request sent to the card issuer. |
application_cryptogram | String | Digital signature generated by the card’s embedded chip. |
terminal_verification_results | String | Series of bits set by the PED for deciding how to respond to the request for payment. |
transaction_status_information | String | Status of the transaction, which is returned by the card issuer. |
amount | Object | Amount object that contains the following fields: amount, currency, precision, timestamp |
Sample stored-value inquiry result and redemption result
storedvaluecard/{cardNumber}, and the second part returns the payment result for storedvaluecard_process.storedvaluecard/{cardNumber}{
result?: "Success" | "Failed"
balance?: { amount: number, currency: string, precision: number }
cardType?: string
issuer?: string
number?: string
pinRequired?: boolean
reason?: string
}
storedvaluecard_processRedeem{
result?: "Success" | "Failed"
reason?: string
balance?: { amount: number, currency: string, precision: number }
number?: string
issuer?: string
method?: string
transaction_id?: string
payment_id?: string
}
Where:
| Attribute | Type | Description |
|---|---|---|
number | String | Identifies the stored-value card number that is being redeemed or whose validity is being checked. |
result | String | Indicates the status of the card information retrieval or redemption attempt. Value can be Success or Failed. |
balance | Object | Provides the current balance amount, currency, and precision. |
cardType | String | Retailer's configuration for card type. |
issuer | String | Retailer's configuration for issuer. |
pinRequired | Boolean | If true, InStore prompts the user for a PIN during the transaction. |
reason | String | Retailer's configuration for supporting information. For example, this could be an error code for a result of Failed. |
method | String | The payment method used for the transaction. |
transaction_id | String | Identifier returned by the payment provider for the transaction. |
payment_id | String | Identifier returned by the payment provider for the payment. |
Sample pay-on-account result
payonaccount/process request through the callback URL.payonaccount/process{
status: succeeded | failed
reason?: string
balance: { amount: number, currency: string, precision: number }
credit_limit: { amount: number, currency: string, precision: number }
account_number: string
company_name: string
authorized_user_id?: string
transaction_id: string
payment_id: string
method: string
}
Where the following are the fields that InStore uses:
| Attribute | Type | Description |
|---|---|---|
status | String | Indicates the result of the pay-on-account payment attempt. Value can be succeeded or failed. |
transaction_id | String | The transaction ID that will be passed to Composable Commerce. |
payment_id | String | The payment servicer's identifier for this payment. |
method | String | The payment method used for the transaction. |
Sample wallet result
pay_wallet request through the callback URL.pay_wallet{
code?: string
result: string
error_message?: string
transaction_id?: string
merchant_id?: string
terminal_id?: string
method?: string
total?: number
}
Where
| Attribute | Type | Description |
|---|---|---|
code | String | Applies only when the result is "failed". Options are "A2" (timeout) or "A7" (declined). |
result | String | Indicates the result of the wallet payment attempt. Value can be "success" or "failed". |
Sample cancel wallet request and result
cancel_wallet:{
transactionId: "dc3bcf40-b8dc-4ad6-a6df-fb7733a3ca67"
paymentProcessorId: "6a0453a27d9e46013347f552"
requestId: "c2ef250c-32c7-4ea6-8c70-a715c579b6e1"
}
requestId from the earlier pay_wallet process as the transactionId.Expected result shape:
{
result: "success"
error_message: ""
code: "00"
timestamp: "2026-06-02T14:20:55.488Z"
}
result field in the success response.pay_wallet cancel request:{
code: "A10"
error_message: "Payment Cancel"
result: "failed"
timestamp: "2026-06-02T14:20:58.811Z"
}
code value except A2 or A7 in the failure response.