Lifecycle
Payment status
Payment status represents the combined payment and refund status of the order. It's calculated based on:
order.total
value- status of the payments
- refunds granted for the order
When no refunds are created, the status is one of the following:
PENDING
: waiting for the response from the payment gatewayREFUSED
: payment refused by the payment gatewayCANCELLED
: payment has been canceledNOT_CHARGED
: the amount is authorized but not chargedPARTIALLY_CHARGED
: the charged amount does not cover the order totalFULLY_CHARGED
: charged funds fully cover the order total
Creating the refund will change the status to:
PARTIALLY_REFUNDED
: the refunded amount does not cover the order totalFULLY_REFUNDED
: refunded funds fully cover the order total
Authorize status
Authorize status depends on:
- the sum of charged transactions
- the sum of authorized transactions
- the
order.totalGrantedRefund
value - the
order.total
value
The difference between total
and totalGrantedRefund
is compared with the sum of charged and authorized transactions. The result is one of the statuses: PARTIAL
, FULL
. If no transaction has been authorized, the status is NONE
.
Authorization status calculation for Checkout
The status is calculated based on all TransactionItem
's assigned to the Checkout
.
For a checkout, authorization means that funds have been either authorized or charged (or a combination of partially charged and partially authorized).
The status takes into account the following fields: authorizedAmount
, chargedAmount
, authorizePendingAmount
, and chargePendingAmount
:
- NONE: No funds have been authorized.
- PARTIAL: The available funds do not fully cover the checkout's total amount.
- FULL: The funds fully cover the checkout's total amount. At this point,
checkoutComplete
can be called to convert the checkout into an order.
Note that pending amounts (success or failure) will be confirmed later by the payment app. This means the system can create an order that may remain unpaid if the pending amounts eventually fail.
Available transitions
- Status is updated when Checkout's
totalAmount
is changed. - Status is updated when Checkout's
TransactionItem
's amounts are updated.
Authorization status calculation for Order
The status is calculated based on all transactions assigned to the Order
.
Authorization means that funds have been either fully or partially authorized or charged.
It uses the fields authorizedAmount
and chargedAmount
, and the calculation is adjusted by subtracting order.totalGrantedRefund
from the total.
Unlike checkout, this status does not consider pending amounts.
- NONE: No funds have been authorized.
- PARTIAL: The authorized and charged funds do not fully cover the amount of
order.total - order.totalGrantedRefund
. - FULL: The authorized and charged funds fully cover the amount of
order.total - order.totalGrantedRefund
.
Available transitions
- Status is updated when Order's
totalAmount
is changed. - Status is updated when Order's
TransactionItem
's amounts are updated. - Status is updated when
Order.grantedRefunds
are updated.
Charge status
Charge status depends on:
- the sum of charged transactions
- the
order.totalGrantedRefund
value - the
order.total
value
The difference between total
and totalGrantedRefund
is compared with charged transactions, and the result is one of the statuses: PARTIAL
, FULL
, OVERCHARGED
. If no transaction has been charged, the status is NONE
.
Charge status calculations for Checkout
The status is calculated based on all transactions assigned to the checkout.
It takes into account the fields: chargedAmount
and chargePendingAmount
.
- NONE: No funds have been charged.
- PARTIAL: The charged funds do not fully cover the checkout's total amount.
- FULL: The charged funds fully cover the checkout's total. At this point,
the
CHECKOUT_FULLY_PAID
webhook event is sent, andcheckoutComplete
can be called to convert the checkout into an order. - OVERCHARGED: The charged funds exceed the checkout's total. In this case,
the
CHECKOUT_FULLY_PAID
webhook event is sent as well, andcheckoutComplete
can still be called to convert the checkout into an order.
When the checkout chargeStatus
is either FULL
or OVERCHARGED
, the authorizeStatus
also changes to FULL
, allowing the checkout to be completed.
However, any pending amounts (whether successful or failed) will be confirmed later
by the payment application. This means that even though the order is created,
it may still remain unpaid if the pending amounts fail to process.
Available transitions
- Status is updated when Checkout's
totalAmount
is changed. - Status is updated when Checkout's
TransactionItem
's amounts are updated.
Charge status calculations for Order
The status is calculated based on all transactions assigned to the order.
It uses the field chargedAmount
and does not consider pending amounts (which differs from the charge status of the checkout).
The amount used for the status calculation is reduced by order.totalGrantedRefund
.
- NONE: No funds have been charged.
- PARTIAL: The charged funds do not fully cover the amount of
order.total - order.totalGrantedRefund
. - FULL: The charged funds fully cover the amount of
order.total - order.totalGrantedRefund
. - OVERCHARGED: The charged funds exceed the amount of
order.total - order.totalGrantedRefund
.
Available transitions
- Status is updated when Order's
totalAmount
is changed. - Status is updated when Order's
TransactionItem
's amounts are updated. - Status is updated when
Order.grantedRefunds
are updated.
Transactions recalculation of amounts
The recalculation will differ based on the value of the TransactionEventTypeEnum
provided as the field type
used in the transactionEventReport
, transactionInitialize
and transactionProcess
mutations, or optionally in the webhook response:
Examples
The tables below show examples of transactions and their amounts when a given event is attached to the transaction. Depending on the event type, the amounts may change. The last columns show the current amounts assigned to the transaction after processing the events defined in a given row and in the rows above it.
Event | Type | pspReference | Time | Amount | transaction.authorizedAmount | transaction.authorizePendingAmount |
---|---|---|---|---|---|---|
1 | AUTHORIZATION_REQUEST | AB12 | 2022-03-28T12:50:33+00:00 | 10 | 0 | 10 |
2 | AUTHORIZATION_SUCCESS | AB12 | 2022-03-28T12:51:33+00:00 | 10 | 10 | 0 |
3 | AUTHORIZATION_FAILURE | YZ13 | 2022-03-28T12:52:33+00:00 | 10 | 10 | 0 |
After receiving an AUTHORIZATION_REQUEST
event, the amount defined in the event is attached to transaction.authorizePendingAmount
.
Then, an AUTHORIZATION_SUCCESS
event is attached to the transaction. Since the AUTHORIZATION_SUCCESS
event has the same pspReference
as
the AUTHORIZATION_REQUEST
event, the transaction.authorizePendingAmount
is reduced by the event amount, and added to the transaction.authorizedAmount
.
An AUTHORIZATION_FAILURE
event doesn’t change anything, as there isn’t an AUTHORIZATION_REQUEST
event related to it.
Event | Type | pspReference | Time | Amount | transaction.authorizedAmount | transaction.authorizePendingAmount |
---|---|---|---|---|---|---|
1 | AUTHORIZATION_REQUEST | AB12 | 2022-03-28T12:50:33+00:00 | 10 | 0 | 10 |
2 | AUTHORIZATION_SUCCESS | AB12 | 2022-03-28T12:51:33+00:00 | 10 | 10 | 0 |
3 | AUTHORIZATION_ADJUSTMENT | YZ13 | 2022-03-28T12:52:33+00:00 | 100 | 100 | 0 |
Upon receiving an AUTHORIZATION_REQUEST
event, the corresponding amount is attached to transaction.authorizePendingAmount
. An AUTHORIZATION_SUCCESS
event
is then attached to the transaction, with the same pspReference
as the AUTHORIZATION_REQUEST
event. The transaction.authorizePendingAmount
is reduced
by the event amount, and the result is added to the transaction.authorizedAmount
.
Note that an AUTHORIZATION_ADJUSTMENT
event will overwrite the previous transaction.authorizedAmount
and cause the
previous AUTHORIZATION_SUCCESS
event to be ignored.
Event | Type | pspReference | Time | Amount | transaction.authorizedAmount | transaction.authorizePendingAmount |
---|---|---|---|---|---|---|
1 | AUTHORIZATION_SUCCESS | AB12 | 2022-03-28T12:51:33+00:00 | 10 | 10 | 0 |
The transaction receives an AUTHORIZATION_SUCCESS
event. Since there is no AUTHORIZATION_REQUEST
with the same pspReference, the value of transaction.authorizePendingAmount
will not be changed. The amount from the event is assigned to transaction.authorizedAmount
.
Event | Type | pspReference | Time | Amount | transaction.chargedAmount | transaction.chargePendingAmount | transaction.authorizedAmount |
---|---|---|---|---|---|---|---|
1 | AUTHORIZATION_SUCCESS | AB12 | 2022-03-28T12:50:33+00:00 | 10 | 0 | 0 | 10 |
2 | CHARGE_REQUEST | YZ13 | 2022-03-28T12:51:33+00:00 | 3 | 0 | 3 | 7 |
3 | CHARGE_SUCCESS | YZ13 | 2022-03-28T12:52:33+00:00 | 3 | 3 | 0 | 7 |
When the transaction receives an AUTHORIZATION_SUCCESS
event, if there is no AUTHORIZATION_REQUEST
with the same pspReference, the value of transaction.authorizePendingAmount
will not change. The amount from the event is then assigned to transaction.authorizedAmount
. Additionally, a CHARGE_REQUEST
event is added to the transaction, and the amount
from the event is added to transaction.chargePendingAmount
. The amount also reduces transaction.authorizedAmount
. Finally, when a CHARGE_SUCCESS
event occurs, the transaction.chargePendingAmount
is reduced by the event’s amount and added to transaction.chargedAmount
.
Event | Type | pspReference | Time | Amount | transaction.chargedAmount | transaction.chargePendingAmount | transaction.authorizedAmount |
---|---|---|---|---|---|---|---|
1 | AUTHORIZATION_SUCCESS | AB12 | 2022-03-28T12:50:33+00:00 | 10 | 0 | 0 | 10 |
2 | CHARGE_REQUEST | YZ13 | 2022-03-28T12:51:33+00:00 | 3 | 0 | 3 | 7 |
3 | CHARGE_SUCCESS | YZ13 | 2022-03-28T12:51:33+00:00 | 3 | 3 | 0 | 7 |
4 | CHARGE_FAILURE | YZ13 | 2022-03-28T12:55:33+00:00 | 3 | 0 | 0 | 10 |
When an AUTHORIZATION_SUCCESS
event is attached to the transaction, the transaction.authorizedAmount
is updated with the amount from the event.
If there is no AUTHORIZATION_REQUEST
with the same pspReference
, the transaction.authorizePendingAmount
remains unchanged.
Additionally, a CHARGE_REQUEST
event is added to the transaction, and its amount is added to transaction.chargePendingAmount
.
The transaction.authorizedAmount
is reduced by the amount from the CHARGE_REQUEST
event.
Finally, when a CHARGE_SUCCESS
event occurs, the transaction.chargedAmount
is updated with the event's amount, and the
transaction.chargePendingAmount
is reduced by the same amount. A CHARGE_FAILURE
event with the same pspReference
as CHARGE_SUCCESS
is
also attached to the transaction, time
indicating that it is newer than the CHARGE_SUCCESS
. The previous CHARGE_SUCCESS
event is ignored during the recalculation process.
Event | Type | pspReference | Time | Amount | transaction.chargedAmount | transaction.chargePendingAmount | transaction.authorizedAmount |
---|---|---|---|---|---|---|---|
1 | AUTHORIZATION_SUCCESS | AB12 | 2022-03-28T12:50:33+00:00 | 10 | 0 | 0 | 10 |
2 | CHARGE_REQUEST | YZ13 | 2022-03-28T12:51:33+00:00 | 3 | 0 | 3 | 7 |
3 | CHARGE_SUCCESS | YZ13 | 2022-03-28T12:51:33+00:00 | 3 | 3 | 0 | 7 |
4 | CHARGE_FAILURE | YZ13 | 2022-03-28T12:50:45+00:00 | 3 | 3 | 0 | 7 |
When an AUTHORIZATION_SUCCESS
event is attached to a transaction, the transaction.authorizedAmount
is updated with the event's amount. If there is no AUTHORIZATION_REQUEST
with the
same pspReference
, the transaction.authorizePendingAmount
remains unchanged. In addition, a CHARGE_REQUEST
event is added to the transaction, and its amount is added to
transaction.chargePendingAmount
. The transaction.authorizedAmount
is reduced by the amount from the CHARGE_REQUEST
event. Finally, when a CHARGE_SUCCESS
event occurs, the
transaction.chargedAmount
is updated with the event's amount, and the transaction.chargePendingAmount
is reduced by the same amount. A CHARGE_FAILURE
event with
the same pspReference
as CHARGE_SUCCESS
is also attached to the transaction. The time
field indicates that it is older than the CHARGE_SUCCESS
event. This means
that the CHARGE_FAILURE
event will be ignored, and the CHARGE_SUCCESS
event will be included in the calculations.
Event | Type | pspReference | Time | Amount | transaction.chargedAmount | transaction.chargePendingAmount | transaction.authorizedAmount |
---|---|---|---|---|---|---|---|
1 | CHARGE_SUCCESS | AB12 | 2022-03-28T12:50:33+00:00 | 10 | 10 | 0 | 0 |
Event | Type | pspReference | Time | Amount | transaction.chargedAmount | transaction.chargePendingAmount | transaction.authorizedAmount |
---|---|---|---|---|---|---|---|
1 | AUTHORIZATION_SUCCESS | AB12 | 2022-03-28T12:50:33+00:00 | 10 | 0 | 0 | 10 |
2 | CHARGE_SUCCESS | YZ13 | 2022-03-28T12:51:33+00:00 | 3 | 3 | 0 | 7 |
The AUTHORIZATION_SUCCESS
event is attached to the transaction, and its amount is added to transaction.authorizedAmount
. Similarly, the CHARGE_SUCCESS
event is attached to the transaction,
and its amount is added to transaction.chargedAmount
. Finally, the amount of the AUTHORIZATION_SUCCESS
event is subtracted from the transaction.authorizedAmount
.
Transaction event types
Authorization events
AUTHORIZATION_SUCCESS
Saleor assigns provided amount
to transaction.authorizedAmount
. If an AUTHORIZATION_SUCCESS
event is related to an AUTHORIZATION_REQUEST
event by pspReference
, then the transactionItem.authorizePendingAmount
will be reduced by the amount reported in the AUTHORIZATION_SUCCESS
event.
You can’t have two successful authorizations for a single transaction.
Each successful request after the first one will raise an exception. AUTHORIZATION_ADJUSTMENT
should be used to change the transaction.authorizedAmount
.
In the case of finding AUTHORIZATION_SUCCESS
and AUTHORIZATION_FAILURE
with the same pspReference
,
the recalculation for transaction.authorizedAmount
will not take into account the amount from
AUTHORIZATION_SUCCESS
, when AUTHORIZATION_SUCCESS
is the older one.
AUTHORIZATION_FAILURE
If an AUTHORIZATION_FAILURE
event is related to an AUTHORIZATION_REQUEST
event by pspReference
, then the transactionItem.authorizePendingAmount
will be reduced by the amount reported in the AUTHORIZATION_FAILURE
event. If there is no related AUTHORIZATION_REQUEST
, the failure event will only
be used to provide the history of transactionItem
actions.
AUTHORIZATION_ADJUSTMENT
Saleor assigns the provided amount
to the transaction.authorizedAmount
.
Charge events
CHARGE_SUCCESS
Adds the provided amount
to the transaction.chargedAmount
. Each next call will add the amount
to the existing
transaction.chargedAmount
(transaction.chargedAmount += amount
). If a CHARGE_SUCCESS
event is related to a CHARGE_REQUEST
event by pspReference
, then the transactionItem.chargePendingAmount
will be reduced by the amount reported in the CHARGE_SUCCESS
event. If there is no related CHARGE_REQUEST
event, the provided amount
will reduce transaction.authorizedAmount
.
In the case of finding CHARGE_SUCCESS
and CHARGE_FAILURE
with the same pspReference
, the recalculation
for transaction.chargedAmount
will not take into account the amount from CHARGE_SUCCESS
, when
CHARGE_SUCCESS
is the older one.
CHARGE_FAILURE
If an CHARGE_FAILURE
event is related to an CHARGE_REQUEST
event by pspReference
, then the transactionItem.chargePendingAmount
will be reduced by the amount reported in the CHARGE_FAILURE
event. If there is no related CHARGE_REQUEST
, the failure event will only
be used to provide the history of transactionItem
actions.
CHARGE_BACK
The provided amount
will be used to reduce transaction.chargedAmount
(transaction.chargedAmount -= amount
).
Refund events
Refund events should only be triggered if the transaction has been previously charged.
Triggering a refund for uncharged transactions can lead to negative chargedAmount
.
Refund events modify both the refundedAmount
and chargedAmount
values, so if the transaction wasn’t charged beforehand, it may result in data inconsistencies.
REFUND_SUCCESS
Adds provided amount
to transaction.refundedAmount
. Each next call will add the amount
to the existing
transaction.refundedAmount
(transaction.refundedAmount += amount
). If a REFUND_SUCCESS
event is related to a REFUND_REQUEST
event by pspReference
, then the transactionItem.refundPendingAmount
will be reduced by the amount reported in the REFUND_SUCCESS
event. If there is no related REFUND_REQUEST
event, the provided amount
will reduce transaction.chargedAmount
.
In the case of finding REFUND_SUCCESS
and REFUND_FAILURE
with the same pspReference
, the recalculation
for transaction.refundedAmount
will not take into account the amount from REFUND_SUCCESS
, when
REFUND_SUCCESS
is the older one.
REFUND_FAILURE
If an REFUND_FAILURE
event is related to an REFUND_REQUEST
event by pspReference
, then the transactionItem.refundPendingAmount
will be reduced by the amount reported in the REFUND_FAILURE
event. If there is no related REFUND_REQUEST
, the failure event will only
be used to provide the history of transactionItem
actions.
REFUND_REVERSE
The provided amount
will be used to reduce transaction.refundedAmount
(transaction.refundedAmount -= amount
).
The provided amount
will increase transaction.chargedAmount
.
Cancel events
Refund events should only be triggered if the transaction has been previously authorized.
Triggering a refund for uncharged transactions can lead to negative authorizedAmount
.
Refund events modify both the refundedAmount
and authorizedAmount
values, so if the transaction wasn’t authorized beforehand, it may result in data inconsistencies.
CANCEL_SUCCESS
The provided amount
will be added to transaction.canceledAmount
(transaction.canceledAmount += amount
). If a CANCEL_SUCCESS
event is related to a CANCEL_REQUEST
event by pspReference
, then the transactionItem.cancelPendingAmount
will be reduced by the amount reported in the CANCEL_SUCCESS
event. If there is no related CANCEL_REQUEST
event, the provided amount
will reduce transaction.authorizedAmount
.
In the case of finding CANCEL_SUCCESS
and CANCEL_FAILURE
with the same pspReference
, the recalculation
for transaction.canceledAmount
will not take into account the amount from CANCEL_SUCCESS
, when
CANCEL_SUCCESS
is the older one.
CANCEL_FAILURE
If an CANCEL_FAILURE
event is related to an CANCEL_REQUEST
event by pspReference
, then the transactionItem.cancelPendingAmount
will be reduced by the amount reported in the CANCEL_FAILURE
event. If there is no related CANCEL_REQUEST
, the failure event will only
be used to provide the history of transactionItem
actions.
Transaction event flow
Transaction events modify the amount fields, which define the state of the transaction. We do not require any specific order of incoming events, the transaction amounts will be calculated based on the rules described above. But to maintain accuracy and integrity, it is important that events are triggered in a valid order. The chart below illustrates the possible sequence of events that can follow one another. Failure to adhere to these guidelines may result in negative values and data inconsistencies.
- Transaction flow strategy:
Authorization
- Transaction flow strategy:
Charge