Hello,
We operate an offsite payments app and need to understand Shopify’s expected behaviour
when a capture session is rejected. We have merchants who are unable to refund orders,
and we have reproduced the behaviour ourselves on a test store.
This is a question about expected platform behaviour rather than a request to
investigate a specific merchant’s order, so we have described the flow generically.
We can supply store, order and session identifiers privately if you need them to
answer.
BACKGROUND — OUR APP’S BEHAVIOUR
Our payments app settles funds immediately at the payment session stage. It does not
support a separate authorisation-and-capture flow. However, our extension
configuration currently declares both a capture_session_url and a void_session_url,
so merchants who have “Manually capture payment for orders” enabled do receive the
authorisation flow.
When such a merchant’s customer checks out, the sequence is:
- We receive a payment session with kind “authorization”.
- We settle the funds immediately — there is no separate capture step on our side.
- We call paymentSessionResolve. This succeeds with no userErrors.
- Some minutes later, when the merchant captures, we receive a capture session.
- Because the funds are already settled and we have no capture step to perform, we
call captureSessionReject with reason code PROCESSING_ERROR. This also succeeds
with no userErrors.
We now understand this is the wrong shape for our app, and we intend to remove the
capture and void session URLs so that we only ever receive kind “sale”. That change is
separate from the questions below.
WHAT WE OBSERVED
After the above sequence, when the merchant refunds the order in the Shopify admin:
- We receive NO refund session request at our refund_session_url.
- We receive NO void session request at our void_session_url either.
- The order displays in the admin as Refunded, with the full amount shown as paid
and then refunded, and a net payment of zero. - A “Capture payment” button is still shown on the order.
Our refund_session_url is correctly configured and works normally: we have processed
several hundred refund sessions in the same period for orders that arrived as kind
“sale”. The absence is specific to orders that arrived as kind “authorization” and
whose capture session we rejected. Across all such orders on our platform, we have
never once received a refund session.
WE HAVE REPRODUCED THIS
On our own test store we repeated the flow — authorisation-kind payment session,
paymentSessionResolve, then captureSessionReject. The order was subsequently manually
captured and shows as Paid in the admin. Even in that state, no refund session request
was sent to our app when a refund was initiated.
This is the part we cannot explain, and it is the core of our question.
OUR QUESTIONS
-
After a capture session is rejected with captureSessionReject, what state does the
payment end up in on Shopify’s side? Is the authorisation voided, left open, or
marked as failed? -
Why is no refund session sent to the app when the order subsequently displays as
Paid? Specifically: is the refund session gated on the order’s financial status, or
on a successfully captured amount recorded against the payment session? If it is
the latter, does a rejected capture permanently leave the capturable and refundable
amount at zero, with no way to recover? -
When a merchant refunds such an order in the admin and no refund session is sent to
the app, what is Shopify recording? The admin shows a refund that never
corresponded to any request to us — the funds are still with us and were never
returned to the customer. -
Should we have received a void session instead of a refund session in this
scenario? We received neither. -
Is there any supported way to recover an order already in this state so that a
refund session can be issued — for example, by the merchant re-attempting the
capture, which we would then resolve rather than reject? -
To confirm our intended fix: if we remove capture_session_url and void_session_url
from our extension configuration and deploy a new app version, will Shopify send
kind “sale” for all future payment sessions on all installed stores, including
stores that have manual capture enabled? And will that release apply automatically
to existing installs without any merchant action?