vendure-ecommerce / vendure

The commerce platform with customization in its DNA.
https://www.vendure.io
Other
5.71k stars 1.01k forks source link

[StripePlugin] Order stuck in ArrangingPayment because shipping charges are not included in payment #3025

Open adamknipfer opened 2 months ago

adamknipfer commented 2 months ago

Describe the bug When using the StripePlugin following the official guide, the Payment that is created does not include the shipping charges so the Order is stuck in ArrangingPayment. When selecting a Shipping Method without a cost (i.e. $0.00), this issue does not occur.

To Reproduce Steps to reproduce the behavior:

  1. Setup the Stripe Plugin following the official docs linked above for use in React (via Next.js 14)
  2. Create a basic Checkout form to collect Customer information, Shipping Info, Shipping Method, Billing Info, and Payment
  3. Ensure that Stripe Elements is configured correctly and that the Payment Intent is created via the exposed query (createStripePaymentIntent) on the server and pass this to the form
  4. Setup the Stripe cli to proxy Webhook calls to Vendure's backend
  5. Setup the Stripe payment method for the Channel that is being used and save the appropriate API key/Webhook secrets.
  6. As a guest user, using cookie based authentication, add items to your Active Order using the addItemToOrder mutation via your Next.js storefront
  7. Setup at least one Shipping Method that costs more than $0.00 via the admin UI.
  8. Start a simple checkout flow by calling the following mutations in this sequence: setCustomerForOrder, setOrderShippingAddress, setOrderShippingMethod, setOrderBillingAddress (I currently have just one basic form collecting all the required fields)
  9. Ensure that the Shipping Method setup is assigned to the Active Order.
  10. After those calls have successfully resolved, call the Stripe confirmPayment
  11. See that the page redirects to the return_url specified in the confirmPayment method in previous step
  12. See that the Stripe CLI correctly receives the webhook call and forwards it to Vendure
  13. See the Vendure server output contains no error messages and that the webhooks were received success.
  14. See that the Order has a payment that has been settled but doesn't include the shipping costs.
  15. See that the Order is still in ArrangingPayment.

Expected behavior After confirmPayment is called, the customer is charged for the full amount of the order including shipping charges and the Order is moved into the PaymentSettled state so that orderByCode query can be called for displaying a confirmation page.

Environment (please complete the following information):

Additional context Here's an example. See that the Order still requires additional payment for the amount of the shipping cost, but a payment was made actually settled: vendure-bug

Please let me know if there is additional detail that can be provided!

adamknipfer commented 2 months ago

Adding additional information...

I ran the following query against the admin-api and the correct Shipping amount was returned.

Request:

query GetOrder($id: ID!) {
  order(id: $id) {
    ... on Order {
      id
      code
      shipping
    }
  }
}

Response:

{
  "data": {
    "order": {
      "id": "18",
      "code": "AS4NWNQH96CU6NM5",
      "shipping": 500
    }
  }
}
adamknipfer commented 2 months ago

After digging in deeper, I found the root cause of the issue (if it can still be called that...)

If you create the PaymentIntent prior to selecting the Shipping Method, the payment amount will not be updated to account for the update in total cost. My solution was to move the Payment Method logic to later in the checkout flow so the shipping is set prior to the PaymentIntent's creation.

I believe this logic makes sense but there's no documentation stating this behavior so it takes a fair bit of debugging to figure it out. I am going to leave this open in case this helps someone in the future but the bug label can be removed.