Ensure that you are not calling any graphQl endpoint to either resolve/reject. Due to a bug we were rejecting the transaction before calling cancel_url. We fixed that and after that on redirecting to cancel_url User was taken back to checkout page with no errors shown to user. Once User clicks on our payment mode again, the same response is used by Shopify Server that they received in initial transaction/initiate call. So Idempotency is also maintained.