woocommerce / woocommerce-blocks

(Deprecated) This plugin has been merged into woocommerce/woocommerce
https://wordpress.org/plugins/woo-gutenberg-products-block/
GNU General Public License v3.0
403 stars 219 forks source link

Coupon amount become 0 after checkout using WooCommerce Store API #8446

Closed ismailkoksal closed 1 year ago

ismailkoksal commented 1 year ago

Describe the bug

Using WooCommerce Store API, with coupon applied with usage limit per user set to 1. If I checkout with user connected (I'm using JWT Authentication for WP-API plugin to login and use returned token for next requests), coupon amount become 0.

To reproduce

Steps to reproduce the behavior:

See https://github.com/woocommerce/woocommerce-blocks/issues/8446#issuecomment-1433433753 for simpler reproduction steps

  1. Create any coupon and set Usage limit per user to 1
  2. Using WooCommerce Store API, add a product to your cart
  3. Using WooCommerce Store API, apply this coupon to your cart
  4. Using WooCommerce Store API, checkout

Expected behavior

Coupon amount to not being 0.

Screenshots

On Get Checkout (/wp-json/wc/store/v1/checkout), its create me a draft order with coupon applied

Capture d’écran 2023-02-15 à 18 05 30

On Post Checkout, order status change to Pending with coupon amount = 0

Capture d’écran 2023-02-15 à 18 06 07

Environment

WordPress (please complete the following information):

Desktop (please complete the following information):

Additional context

All steps I've done its with a new customer created with 0 orders.

After some research in the code, I found the error coming from $discounts->apply_coupon( $coupon ) Here the stack trace:

Error: 
object(WP_Error)[3720]
  public 'errors' => 
    array (size=1)
      'invalid_coupon' => 
        array (size=1)
          0 => string 'Coupon usage limit has been reached.' (length=36)
  public 'error_data' => 
    array (size=1)
      'invalid_coupon' => 
        array (size=1)
          'status' => int 400
  protected 'additional_data' => 
    array (size=0)
      empty

Stack trace:
(class-wc-totals.php:777) $discounts->apply_coupon( $coupon )
(class-wc-totals.php:654) $this->calculate_discounts()
(class-wc-totals.php:143) $this->calculate_item_totals()
(class-wc-totals.php:134) $this->calculate()
(class-wc-cart.php:1406) new WC_Cart_Totals( $this )
(OrderController.php:52) wc()->cart->calculate_totals()
(AbstractCartRoute.php:221) $this->order_controller->update_order_from_cart( $draft_order )
(AbstractCartRoute.php:115) $this->cart_updated( $request )
(AbstractCartRoute.php:89) get_response
opr commented 1 year ago

Hi there @ismailkoksal I tried this and could not replicate. Can you consistently replicate this over multiple attempts?

I also noticed that requests were succeeding regardless of whether I used the JWT, can you confirm if that's the case for you as well?

Could you also try with WC Blocks 9.6.0 which was released earlier today?

ismailkoksal commented 1 year ago

Yes I can consistently replicate this over multiple attempts.

Here an example in video https://user-images.githubusercontent.com/20714736/219174960-9a666182-6562-4f76-aadb-b52985798e36.mp4

ismailkoksal commented 1 year ago

@opr I'm using internal woocoomerce-blocks package from woocommerce plugin. How can I install WC Blocks 9.6.0 ?

opr commented 1 year ago

Hi @ismailkoksal thank you for the information, I will continue to investigate today.

How can I install WC Blocks 9.6.0

You can install our feature plugin from https://wordpress.org/plugins/woo-gutenberg-products-block/

Let me know if this changes things for you!

ismailkoksal commented 1 year ago

Hi @ismailkoksal thank you for the information, I will continue to investigate today.

@opr Hi, ok ty

You can install our feature plugin from https://wordpress.org/plugins/woo-gutenberg-products-block/

Let me know if this changes things for you!

Same problem with WC Blocks 9.6.0

opr commented 1 year ago

@ismailkoksal I have tried multiple times with the following steps:

  1. Create a new user in WP Dashboard
  2. Create a new Coupon in the WC Marketing area. Set it to "Fixed cart discount" and set it to 1 use per customer
  3. Using Postman, create a JWT for the new user.
  4. Apply this JWT to all future requests
  5. Via postman: Add an item to the cart
  6. Via postman: Apply the coupon to the cart
  7. Via postman: Get the cart to verify the coupon is there
  8. Via postman, GET the checkout to create the draft order
  9. Go to the WC Orders dashboard, verify the draft order is there and has the coupon applied
  10. Via postman: POST to the checkout endpoint, placing the order
  11. Go to WC Orders dashboard, verify the order was placed and the token is applied.

Can you confirm these are the steps you're doing too?

On step 8, can you double check the customer_id matches the ID of the new customer you created in step 1?

Thanks!

ismailkoksal commented 1 year ago

@opr Yes these are the steps I'm doing and order customer_id matches the ID of the new customer I created. Note that I'm using paypal as payment method.

Here the content of my functions.php

<?php

add_filter('woocommerce_should_load_paypal_standard', '__return_true');
opr commented 1 year ago

Thank you, I have been able to replicate this, I will add it to our queue to work on!

To summarise, the testing steps are:

  1. Create a new user in WP Dashboard
  2. Create a new Coupon in the WC Marketing area. Set it to "Fixed cart discount" and set it to 1 use per customer
  3. Using Postman, create a JWT for the new user.
  4. Apply this JWT to all future requests
  5. Via postman: Add an item to the cart
  6. Via postman: Apply the coupon to the cart
  7. Via postman: Get the cart to verify the coupon is there
  8. Via postman, GET the checkout to create the draft order
  9. Go to the WC Orders dashboard, verify the draft order is there and has the coupon applied
  10. Via postman: POST to the checkout endpoint, placing the order
  11. Go to WC Orders dashboard, verify the order was placed and the token is applied.

You will need to use the paypal payment method, and send the following payment data with your request:

"payment_data": [
    {
        "key": "wc-paypal-new-payment-method",
        "value": false
    }
]

This code https://github.com/woocommerce/woocommerce/blob/4dcff8ccf1b989888170a247be69c6e91deed27b/plugins/woocommerce/includes/class-wc-discounts.php#L654 is called twice when placing the order, the first time it succeeds, the second time it fails.

opr commented 1 year ago

Hi @ismailkoksal, this is a problem with PayPal not with Blocks, I will leave this issue open while we investigate some more to see if we can apply a fix on our end. I edited your main comment to show these reproduction steps instead.

@wavvves since you will be working on this next week please note that this only happens with PayPal and there are some easier reproductions steps here:

  1. Install and configure https://wordpress.org/plugins/enable-standard-paypal-for-woocommerce/ - you will need a PayPal sandbox account
  2. Create a coupon that is limited to 1 use per customer.
  3. Add an item to your cart and apply the coupon.
  4. Check out using PayPal.
  5. Check the order in the back end and see the coupon is not applied.
ismailkoksal commented 1 year ago

@opr Actually, I have the same problem with another payment method "SogeCommerce" https://sogecommerce.societegenerale.eu/doc/en-EN/plugins/#woocommerce so I don't think its specific to Paypal

ismailkoksal commented 1 year ago

If I comment this line the problem disappears https://github.com/woocommerce/woocommerce-blocks/blob/trunk/src/StoreApi/Routes/V1/AbstractCartRoute.php#L121

opr commented 1 year ago

Thanks for the clarification @ismailkoksal - I am not familiar with SogeCommerce, can you let me know if this takes users away from the WooCommerce store (i.e. off-site) to complete the payment?

If not specific to PayPal, then it is specific to the way payment methods that go off-site to complete payment work.

Either way, we will investigate it some more and update this issue when we find more information.

ismailkoksal commented 1 year ago

@opr

can you let me know if this takes users away from the WooCommerce store (i.e. off-site) to complete the payment?

Yes

opr commented 1 year ago

@ismailkoksal great! well this gives us more to go on. Thanks again and keep an eye on this issue for updates.

mikailturkoglu commented 1 year ago

Hi @opr @wavvves, thanks for the amazing job you guys are doing.

I face the exact same thing at my end on a website, using Paypal. Any chance you could share us any visibility about the fix for this issue ?

Thank you guys and good luck !

wavvves commented 1 year ago

Hi @mikailturkoglu , thanks for reaching out. We are planning to take the time to fix it in the current cycle, so it is expectable to see a PR being attached to this during the next week

mikailturkoglu commented 1 year ago

Hi @wavvves, any news for this issue ?

Thanks for your help.

wavvves commented 1 year ago

Hi @mikailturkoglu, this is being investigated right now, so far it seems the problem is not attached to either the payment gateway or the JWT usage, and it is a bug relating to single usage coupons and Store API. Having to create new coupons and orders is slowing debug down a bit, sorry for that.

opr commented 1 year ago

Having to create new coupons and orders is slowing debug down a bit, sorry for that.

I can give you a tip on this! Create 10 coupons, and then create a new user. Cycle through each coupon per user account, so you only need to switch users once every 10 requests. It sped up debugging a lot for me!