Introduction
Transaction webhooks are synchronous webhooks that allow delegating the transaction's action to the Saleor App.
Synchronous means that these webhooks expect a response of a particular shape to be returned from the App to continue processing in Saleor.
Transaction webhooks only support the HTTP(S) protocol; they are sent as POST requests with the application/json
body and expect the
response of the same content type.
Key concepts
The HANDLE_PAYMENTS
permission is required for the App to receive transaction webhooks.
The webhook notification is only sent to a specific app connected to a given transaction.
The usage of the webhook is strictly related to the payment flow handled by transactions. You can find more details about the transaction flow in the Payments documentation.
Transaction charge
TRANSACTION_CHARGE_REQUESTED
This feature was introduced in Saleor 3.13.
A synchronous webhook called inside a Celery task. It is triggered when a staff user requests the charge action.
The webhook expects to return at least the pspReference
in the response. The pspReference
will be attached to TransactionEvent
with request details. When pspReference
is attached to the request
object, it means the app has successfully processed the webhook.
Optionally the result data can be provided. The data is
used to provide the final status of the requested action, and it will be used to create a new TransactionEvent
object. The new TransactionEvent
object will have provided pspReference
, and will be used in the
recalculation of the transaction's amount process.
Request
Saleor will send a
TRANSACTION_CHARGE_REQUESTED
webhook by using the TransactionChargeRequested
subscription type or with a pre-defined payload in case of a missing subscription query.
You can find more details about building webhook subscription query here.
The example below shows a sample webhook subscription defined to handle charge requests:
subscription {
event {
__typename
... on TransactionChargeRequested {
action {
actionType
amount
}
transaction {
id
pspReference
authorizedAmount {
amount
currency
}
order {
id
}
}
}
}
}
The example below shows the pre-defined payload that will be used in the case when a subscription query is not provided:
{
"action": { "currency": "USD", "type": "charge", "value": "5.00" },
"meta": {
"issued_at": "2022-06-28T10:50:00+00:00",
"issuing_principal": { "id": "Sample app objects", "type": "app" },
"version": "3.13.0-a"
},
"transaction": {
"authorized_value": "10.00",
"available_actions": ["capture", "void"],
"canceled_value": "0.00",
"charged_value": "0.00",
"checkout_id": null,
"created_at": "2022-06-28T10:50:00Z",
"currency": "USD",
"message": "",
"modified_at": "2022-06-28T10:50:00Z",
"name": "Credit card",
"order_id": "T3JkZXI6YjE1YzdlZTgtMzUxNy00MTczLWEzNWYtMmQxMDdkMWI4Yzhk",
"psp_reference": "PSP ref",
"reference": "PSP ref",
"refunded_value": "0.00",
"status": "Authorized",
"type": "Credit card",
"voided_value": "0.00"
}
}
Response
Async flow
App needs to at least return the pspReference
of the requested action. This is a common case
when the payment provider doesn't return a status of the requested action in the response.
In this situation, the status of the action is delivered by an asynchronous notification that
should be handled by App, and passed to Saleor by using the
transactionEventReport
mutation.
The response in this case should have the following structure:
{
"pspReference": "<psp reference received from payment provider>"
}
Sync flow
The app has the possibility to report the status of the requested action immediately.
This is a common case when the payment provider returns the status of the action in
response to the requested action.
The payload response has to contain at least pspReference
(optional for CHARGE_FAILURE
), result
(
CHARGE_SUCCESS
or CHARGE_FAILURE
),
and amount
fields.
The response in this case should have the following structure:
{
"pspReference": "<[Optional for CHARGE_FAILURE] psp reference recieved from payment provider>",
"result": "<CHARGE_SUCCESS or CHARGE_FAILURE>",
"amount": "<Decimal amount of the processed action>",
"time": "<[Optional] time of the action>",
"externalUrl": "<[Optional] external url with action details>",
"message": "<[Optional] message related to the action>",
"actions": "<[Optional] list of actions available for the transaction. Possible items: CHARGE, REFUND, CANCEL>"
}
In the case when one of result
, amount
is provided and the second one is missing,
the response will not be processed, and Saleor will create the failure event.
Transaction cancelation
TRANSACTION_CANCELATION_REQUESTED
This feature was introduced in Saleor 3.13.
A synchronous webhook called inside a Celery task. They are called when a staff user requests the cancelation action.
The webhook expects to return at least the pspReference
in the response. The pspReference
will
be attached to TransactionEvent
with request details. When pspReference
is attached to the request
object, it means the app has successfully processed the webhook. Optionally the result data can be provided. The data is
used to provide the final status of the requested action, and it will be used to create a new
TransactionEvent
object. The new
TransactionEvent
object will have
provided pspReference
, and will be used in the
recalculation of the transaction's amount process.
Request
Saleor will send a
TRANSACTION_CANCEL_REQUESTED
webhook by using the TransactionCancelationRequested
subscription type or with a pre-defined payload in case of a missing subscription query.
You can find more details about building webhook subscription query
here.
The example below shows a sample webhook subscription defined to handle cancelation requests:
subscription {
event {
__typename
... on TransactionCancelationRequested {
action {
actionType
amount
}
transaction {
id
pspReference
authorizedAmount {
amount
currency
}
order {
id
}
}
}
}
}
The example below shows the pre-defined payload that will be used in the case when a subscription query is not provided:
{
"action": { "currency": "USD", "type": "cancel", "value": "0.00" },
"meta": {
"issued_at": "2022-06-28T10:50:00+00:00",
"issuing_principal": { "id": "Sample app objects", "type": "app" },
"version": "3.13.0-a"
},
"transaction": {
"authorized_value": "10.00",
"available_actions": ["capture", "void"],
"canceled_value": "0.00",
"charged_value": "0.00",
"checkout_id": null,
"created_at": "2022-06-28T10:50:00Z",
"currency": "USD",
"message": "",
"modified_at": "2022-06-28T10:50:00Z",
"name": "Credit card",
"order_id": "T3JkZXI6YWEzYzVhOTMtN2NlYS00OGZkLWJmYWUtMWFkYjI5YTRjMmY1",
"psp_reference": "PSP ref",
"reference": "PSP ref",
"refunded_value": "0.00",
"status": "Authorized",
"type": "Credit card",
"voided_value": "0.00"
}
}
Response
Async flow
App needs to at least return the pspReference
of the requested action. This is a common case
when the payment provider doesn't return a status of the requested action in the response.
In this situation, the status of the action is delivered by an asynchronous notification that
should be handled by App, and passed to Saleor by using the
transactionEventReport
mutation.
The response in this case should have the following structure:
{
"pspReference": "<psp reference received from payment provider>"
}
Sync flow
The app has the possibility to report the status of the requested action immediately.
This is a common case when the payment provider returns the status of the action in
response to the requested action.
The payload response has to contain at least pspReference
(optional for CANCEL_FAILURE
), result
(
CANCEL_SUCCESS
or CANCEL_FAILURE
),
and amount
fields.
The response in this case should have the following structure:
{
"pspReference": "<[Optional for CANCEL_FAILURE] psp reference recieved from payment provider>",
"result": "<CANCEL_SUCCESS or CANCEL_FAILURE>",
"amount": "<Decimal amount of the processed action>",
"time": "<[Optional] time of the action>",
"externalUrl": "<[Optional] external url with action details>",
"message": "<[Optional] message related to the action>",
"actions": "<[Optional] list of actions available for the transaction. Possible items: CHARGE, REFUND, CANCEL>"
}
In the case when one of result
, amount
is provided and the second one is missing,
the response will not be processed, and Saleor will create the failure event.
Transaction refund
TRANSACTION_REFUND_REQUESTED
This feature was introduced in Saleor 3.13.
A synchronous webhook called inside a Celery task. They are called when a staff user requests the refund action.
The webhook expects to return at least the pspReference
in the response. The pspReference
will be attached to TransactionEvent
with request details. When pspReference
is attached to the request
object, it means the app has successfully processed the webhook. Optionally the result data can be provided. The data is
used to provide the final status of the requested action, and it will be used to create a new TransactionEvent
object. The new TransactionEvent
object will have provided pspReference
, and will be used in the
recalculation of the transaction's amount process.
Request
Saleor will send a
TRANSACTION_REFUND_REQUESTED
webhook by using the TransactionRefundRequested
subscription type or with a pre-defined payload in case of a missing subscription query.
More details about building webhook subscription query can be found here.
The example below shows a sample webhook subscription defined to handle refund requests:
subscription {
event {
__typename
... on TransactionRefundRequested {
action {
actionType
amount
}
transaction {
id
pspReference
chargedAmount {
amount
currency
}
order {
id
}
}
grantedRefund {
id
amount {
amount
}
lines {
id
quantity
orderLine {
unitPrice {
gross {
amount
}
}
}
}
}
}
}
}
grantedRefund
- This field was introduced in Saleor 3.15. It contains the details about OrderGrantedRefund
related to the the refund request action.
The field will contain OrderGrantedRefund when a refund request was triggered by calling transactionRequestRefundForGrantedRefund
mutation.
The example below shows the pre-defined payload that will be used in the case when a subscription query is not provided:
{
"action": { "currency": "USD", "type": "refund", "value": "9.00" },
"meta": {
"issued_at": "2022-06-28T10:50:00+00:00",
"issuing_principal": { "id": "Sample app objects", "type": "app" },
"version": "3.13.0-a"
},
"transaction": {
"authorized_value": "10.00",
"available_actions": ["capture", "void"],
"canceled_value": "0.00",
"charged_value": "0.00",
"checkout_id": null,
"created_at": "2022-06-28T10:50:00Z",
"currency": "USD",
"message": "",
"modified_at": "2022-06-28T10:50:00Z",
"name": "Credit card",
"order_id": "T3JkZXI6NjdlYTYxNDAtMzEwZi00YTRlLThmODktNTU2NjliMjk4NjU5",
"psp_reference": "PSP ref",
"reference": "PSP ref",
"refunded_value": "0.00",
"status": "Authorized",
"type": "Credit card",
"voided_value": "0.00"
}
}
Response
Async flow
App needs to at least return the pspReference
of the requested action. This is a common case
when the payment provider doesn't return a status of the requested action in the response.
In this situation, the status of the action is delivered by an asynchronous notification that
should be handled by App, and passed to Saleor by using the
transactionEventReport
mutation.
The response in this case should have the following structure:
{
"pspReference": "<psp reference received from payment provider>"
}
Sync flow
The app has the possibility to report the status of the requested action immediately.
This is a common case when the payment provider returns the status of the action in
response to the requested action.
The payload response has to contain at least pspReference
(optional for REFUND_FAILURE
), result
(
REFUND_SUCCESS
or REFUND_FAILURE
),
and amount
fields.
The response in this case should have the following structure:
{
"pspReference": "<[Optional for REFUND_FAILURE] psp reference recieved from payment provider>",
"result": "<REFUND_SUCCESS or REFUND_FAILURE>",
"amount": "<Decimal amount of the processed action>",
"time": "<[Optional] time of the action>",
"externalUrl": "<[Optional] external url with action details>",
"message": "<[Optional] message related to the action>",
"actions": "<[Optional] list of actions available for the transaction. Possible items: CHARGE, REFUND, CANCEL>"
}
In the case when one of result
, amount
is provided and the second one is missing,
the response will not be processed, and Saleor will create the failure event.
Initialize payment gateway session
PAYMENT_GATEWAY_INITIALIZE_SESSION
This feature was introduced in Saleor 3.13.
The synchronous PAYMENT_GATEWAY_INITIALIZE_SESSION
webhook is called when a customer requests payment gateway initialization by calling the paymentGatewayInitialize
mutation. The webhook contains details about the object (Order
/Checkout
)
for which the payment gateway initialization was requested, the requested amount, and the data
received from the frontend.
As a response, the webhook expects the data
field with all initialization details that will be passed to the storefront.
Request
Saleor will send a
PAYMENT_GATEWAY_INITIALIZE_SESSION
webhook by using the PaymentGatewayInitializeSession
subscription type or with a pre-defined payload in case of a missing subscription query.
More details about building webhook subscription query can be found here.
The example below shows a sample webhook subscription defined to handle payment gateway initialization requests:
subscription PaymentGatewayInitialize {
event {
... on PaymentGatewayInitializeSession {
sourceObject {
__typename
... on Checkout {
id
totalPrice {
gross {
amount
}
}
}
... on Order {
id
total {
gross {
amount
}
}
}
}
data
amount
}
}
}
The example below shows the pre-defined payload that will be used in the case when a subscription query is not provided:
{
"id": "T3JkZXI6NGI2ZjEzMDctMTA1Yi00NGU4LWFlZjAtYWNjMGJmYjUwMjY1",
"data": {
"some": "request-data"
},
"amount": "10.00"
}
Response
The app needs to return the data
field. The data
received from the webhook will be returned as a paymentGatewayInitialize
mutation response.
{
"data": {
"some": "init-data"
}
}
Initialize transaction session
TRANSACTION_INITIALIZE_SESSION
This feature was introduced in Saleor 3.13.
The synchronous TRANSACTION_INITIALIZE_SESSION
webhook
is called when a customer begins processing a payment by calling the transactionInitialize
mutation. The webhook contains details about the object (Order
/Checkout
) related to this action, the transactionItem
object, details related to the
requested action, and the data
passed in the mutation input. Saleor expects the response to be in the proper format. Based on the response, the transactionItem
's amount can be marked as fully covered
or marked as a transaction that requires additional actions from the customer, such as processing 3D secure action.
The idempotencyKey
should be passed to the payment provider to recognize the retries of the same request.
Request
Saleor will send a
TRANSACTION_INITIALIZE_SESSION
webhook by using the TransactionInitializeSession
subscription type or with a pre-defined payload in case of a missing subscription query.
More details about building webhook subscription query can be found here.
The example below shows a sample webhook subscription defined to handle transaction initialization requests:
subscription TransactionInitialize {
event {
... on TransactionInitializeSession {
sourceObject {
__typename
... on Checkout {
id
totalPrice {
gross {
amount
}
}
}
... on Order {
id
total {
gross {
amount
}
}
}
}
idempotencyKey
data
customerIpAddress
merchantReference
action {
amount
currency
actionType
}
transaction {
id
}
}
}
}
The example below shows the pre-defined payload that will be used in the case when a subscription query is not provided:
{
"id": "Q2hlY2tvdXQ6Mjk2OWFkNTAtZTQwYS00ZThkLTgwNWItYjk5ZDI0ZGYwOTdm",
"data": {
"some": "request-data"
},
"amount": "10.00",
"currency": "USD",
"action_type": "CHARGE",
"transaction_id": "VHJhbnNhY3Rpb25JdGVtOjNiZDUyNjQ2LTUxM2YtNGE1Ni1hOWUzLWY3NzEwN2Y2NTAxNA=="
}
Response
The app must return a response in a specified format. Based on the payload, Saleor will determine the current status of the transaction.
If the format is incorrect or the response is missing, Saleor will create either a CHARGE_FAILURE
or AUTHORIZATION_FAILURE
event, depending on the type of action that was requested.
The response in this case should have the following structure:
{
"pspReference": "<[Optional for some results, see details below] psp reference recieved from payment provider>",
"result": "CHARGE_SUCCESS or CHARGE_FAILURE or CHARGE_REQUEST or AUTHORIZATION_SUCCESS or AUTHORIZATION_FAILURE or AUTHORIZATION_REQUEST or AUTHORIZATION_ACTION_REQUIRED or CHARGE_ACTION_REQUIRED>",
"amount": "<Decimal amount of the processed action>",
"data": "<[Optional] JSON data tha will be returned to storefront>",
"time": "<[Optional] time of the action>",
"externalUrl": "<[Optional] external url with action details.",
"message": "<[Optional] message related to the action>",
"actions": "<[Optional] list of actions available for the transaction. Possible items: CHARGE, REFUND, CANCEL>"
}
Below are the possible result
values and their explanations:
result:CHARGE_SUCCESS
: The funds have been successfully charged. The event amount will be added totransaction.chargedAmount
.result:AUTHORIZATION_SUCCESS
: The funds have been successfully authorized. The event amount will be added totransaction.authorizedAmount
.result:CHARGE_REQUEST
: A charge has been requested. The event amount will be added totransaction.chargePendingAmount
.result:AUTHORIZATION_REQUEST
: An authorization has been requested. The event amount will be added totransaction.authorizePendingAmount
.result:AUTHORIZATION_ACTION_REQUIRED
: Additional actions are required from the customer to authorize the payment. Before finalizing these additional actions, the payment is treated as not processed.result:CHARGE_ACTION_REQUIRED
: Additional actions are required from the customer to charge the payment. Before finalizing these additional actions, the payment is treated as not processed.result:CHARGE_FAILURE
: Charging the payment has failed.result:AUTHORIZATION_FAILURE
: Authorizing the payment has failed.
The pspReference
is required for the following results
:
result:CHARGE_SUCCESS
result:AUTHORIZATION_SUCCESS
result:CHARGE_REQUEST
result:AUTHORIZATION_REQUEST
The pspReference
is optional for the following results
:
result:AUTHORIZATION_ACTION_REQUIRED
result:CHARGE_ACTION_REQUIRED
result:CHARGE_FAILURE
result:AUTHORIZATION_FAILURE
Process transaction session
TRANSACTION_PROCESS_SESSION
This feature was introduced in Saleor 3.13.
The TRANSACTION_PROCESS_SESSION
webhook is called synchronously when
a customer needs to process additional actions received as a response from either
the transactionInitialize
or transactionProcess
mutations. This webhook is triggered when the customer calls the
transactionProcess
mutation.
It contains details about the Order
or Checkout
object related to this action, the transactionItem
object, details related to the requested action, and the data
passed in the mutation input.
Saleor expects the response to be in the proper format. Based on the response, the amount of the transactionItem
can be marked as fully covered or marked as a transaction
that requires additional actions from the customer, such as processing a 3D secure action.
Request
Saleor will send a
TRANSACTION_PROCESS_SESSION
webhook by using the TransactionProcessSession
subscription type or with a pre-defined payload in case of a missing subscription query.
More details about building webhook subscription query can be found here.
The example below shows a sample webhook subscription defined to handle transaction process requests:
subscription TransactionProcess {
event {
... on TransactionProcessSession {
sourceObject {
__typename
... on Checkout {
id
totalPrice {
gross {
amount
}
}
}
... on Order {
id
total {
gross {
amount
}
}
}
}
data
customerIpAddress
merchantReference
action {
amount
currency
actionType
}
transaction {
id
}
}
}
}
The example below shows the pre-defined payload that will be used in the case when a subscription query is not provided:
{
"id": "Q2hlY2tvdXQ6NzMyNGJlMWMtMjg3Yy00NDQxLTkwOWYtMDhmYjg0YjNhYjNl",
"data": {
"some": "request-data"
},
"amount": "10.00",
"currency": "USD",
"action_type": "CHARGE",
"transaction_id": "VHJhbnNhY3Rpb25JdGVtOjRhODMxNThkLTU0NTAtNDU2Mi04MDE5LTAzYzY4NjMyZjA1Mg=="
}
Response
The app must return a response in a specified format. Based on the payload, Saleor will determine the current status of the transaction.
If the format is incorrect or the response is missing, Saleor will create either a CHARGE_FAILURE
or AUTHORIZATION_FAILURE
event, depending on the type of action that was requested.
The response in this case should have the following structure:
{
"pspReference": "[Optional for some results, see details below] <psp reference recieved from payment provider>",
"result": "CHARGE_SUCCESS or CHARGE_FAILURE or CHARGE_REQUEST or AUTHORIZATION_SUCCESS or AUTHORIZATION_FAILURE or AUTHORIZATION_REQUEST or AUTHORIZATION_ACTION_REQUIRED or CHARGE_ACTION_REQUIRED>",
"amount": "<Decimal amount of the processed action>",
"data": "<[Optional] JSON data tha will be returned to storefront>",
"time": "<[Optional] time of the action>",
"externalUrl": "<[Optional] external url with action details.",
"message": "<[Optional] message related to the action>",
"actions": "<[Optional] list of actions available for the transaction. Possible items: CHARGE, REFUND, CANCEL>"
}
Below are the possible result
values and their explanations:
result:CHARGE_SUCCESS
: The funds have been successfully charged. The event amount will be added totransaction.chargedAmount
.result:AUTHORIZATION_SUCCESS
: The funds have been successfully authorized. The event amount will be added totransaction.authorizedAmount
.result:CHARGE_REQUEST
: A charge has been requested. The event amount will be added totransaction.chargePendingAmount
.result:AUTHORIZATION_REQUEST
: An authorization has been requested. The event amount will be added totransaction.authorizePendingAmount
.result:AUTHORIZATION_ACTION_REQUIRED
: Additional actions are required from the customer to authorize the payment. Before finalizing these additional actions, the payment is treated as not processed.result:CHARGE_ACTION_REQUIRED
: Additional actions are required from the customer to charge the payment. Before finalizing these additional actions, the payment is treated as not processed.result:CHARGE_FAILURE
: Charging the payment has failed.result:AUTHORIZATION_FAILURE
: Authorizing the payment has failed.
The pspReference
is required for the following results
:
result:CHARGE_SUCCESS
result:AUTHORIZATION_SUCCESS
result:CHARGE_REQUEST
result:AUTHORIZATION_REQUEST
The pspReference
is optional for the following results
:
result:AUTHORIZATION_ACTION_REQUIRED
result:CHARGE_ACTION_REQUIRED
result:CHARGE_FAILURE
result:AUTHORIZATION_FAILURE