Automattic / woocommerce-payments

Accept payments via credit card. Manage transactions within WordPress.
https://wordpress.org/plugins/woocommerce-payments/
Other
173 stars 69 forks source link

Rounding problems with Level 3 data when using Product AddOns #9114

Open peterfabian opened 2 months ago

peterfabian commented 2 months ago

Describe the bug

When testing https://github.com/Automattic/woocommerce-payments/pull/9070, I noticed that I can't check out because of the following error:

Invalid level3: pricing must be consistent. Sum(unit_cost * quantity + tax_amount - discount_amount) + shipping_amount != total charged. In this case, 24411 != 24410. (invalid_request_error)
2024-07-17T13:12:38+00:00 Info Level3 data error: 
Error: Invalid level3: pricing must be consistent. Sum(unit_cost * quantity + tax_amount - discount_amount) + shipping_amount != total charged. In this case, 24411 != 24410.

This is happening also with vanilla WooPayments without #9070 applied according to our testing.

To Reproduce

Not sure if this is the minimal example, but I think this should display the same behavior:

  1. Install WooPayments & Product AddOns
  2. Create a Simple Product, price = $21.
  3. Go to Product Data > Add-Ons.
  4. Create a 'Short text' add-on.
  5. Enable Adjust price and set it to Flat fee, e.g. $10.
  6. Add the product to the cart with the addon, use quantity = 3.
  7. The total in the cart should be 21 * 3 + 10 = 73.
  8. However, 73/3 = 24.33333333, so unit cost will be 2433 and 2433 * 3 = 7299 != 7300.
  9. Get the Level 3 data error and can't check out.
  10. Also, the error message is cryptic:

Error: The provided PaymentMethod was previously used with a PaymentIntent without Customer attachment, shared with a connected account without Customer attachment, or was detached from a Customer. It may not be used again. To use a PaymentMethod multiple times, you must attach it to a Customer first.

Actual behavior

Unable to check out

Screenshots

This is the same problem with a more elaborate add-on setup:

Screenshot 2024-07-18 at 08 41 23

Expected behavior

I was expecting being able to check out.

Desktop (please complete the following information):

Smartphone (please complete the following information):

Additional context

Error log below:

``` 2024-07-17T13:12:36+00:00 Info ENVIRONMENT: array ( 'WP_User' => 'demo', 'HTTP_REFERER' => 'https://fortunately-wise.jurassic.ninja/checkout/', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', 'REQUEST_URI' => '/wp-json/wc/store/v1/checkout?_locale=user', 'DOING_AJAX' => false, 'DOING_CRON' => false, 'WP_CLI' => false, ) 2024-07-17T13:12:36+00:00 Info REQUEST POST https://public-api.wordpress.com/wpcom/v2/sites/%s/wcpay/customers/cus_QRQT3cMHddrF94 2024-07-17T13:12:36+00:00 Info HEADERS: array ( 'Content-Type' => 'application/json; charset=utf-8', 'User-Agent' => 'WooCommerce Payments/7.8.1', 'Idempotency-Key' => 'b315ce5a-209a-4952-8553-00a9fba80b22', ) 2024-07-17T13:12:36+00:00 Info BODY: array ( 'test_mode' => true, 'name' => '(redacted)', 'description' => 'Name: Jason Kytros, Username: demo', 'email' => '(redacted)', 'phone' => '(redacted)', 'address' => array ( 'line1' => '(redacted)', 'line2' => '(redacted)', 'postal_code' => '(redacted)', 'city' => '(redacted)', 'state' => '(redacted)', 'country' => '(redacted)', ), 'shipping' => array ( 'name' => '(redacted)', 'address' => array ( 'line1' => '(redacted)', 'line2' => '(redacted)', 'postal_code' => '(redacted)', 'city' => '(redacted)', 'state' => '(redacted)', 'country' => '(redacted)', ), ), ) 2024-07-17T13:12:36+00:00 Info RESPONSE: array ( 'id' => 'cus_QRQT3cMHddrF94', 'object' => 'customer', 'address' => array ( 'city' => '(redacted)', 'country' => '(redacted)', 'line1' => '(redacted)', 'line2' => '(redacted)', 'postal_code' => '(redacted)', 'state' => '(redacted)', ), 'balance' => 0, 'created' => 1720506840, 'currency' => NULL, 'default_currency' => NULL, 'default_source' => NULL, 'delinquent' => false, 'description' => 'Name: Jason Kytros, Username: demo', 'discount' => NULL, 'email' => '(redacted)', 'invoice_prefix' => '2AC9F430', 'invoice_settings' => array ( 'custom_fields' => NULL, 'default_payment_method' => NULL, 'footer' => NULL, 'rendering_options' => NULL, ), 'livemode' => false, 'metadata' => 'stdClass()', 'name' => '(redacted)', 'next_invoice_sequence' => 1, 'phone' => '(redacted)', 'preferred_locales' => array ( ), 'shipping' => array ( 'address' => array ( 'city' => '(redacted)', 'country' => '(redacted)', 'line1' => '(redacted)', 'line2' => '(redacted)', 'postal_code' => '(redacted)', 'state' => '(redacted)', ), 'name' => '(redacted)', 'phone' => '(redacted)', ), 'tax_exempt' => 'none', 'test_clock' => NULL, ) 2024-07-17T13:12:36+00:00 Info ENVIRONMENT: array ( 'WP_User' => 'demo', 'HTTP_REFERER' => 'https://fortunately-wise.jurassic.ninja/checkout/', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', 'REQUEST_URI' => '/wp-json/wc/store/v1/checkout?_locale=user', 'DOING_AJAX' => false, 'DOING_CRON' => false, 'WP_CLI' => false, ) 2024-07-17T13:12:36+00:00 Info REQUEST POST https://public-api.wordpress.com/wpcom/v2/sites/%s/wcpay/intentions 2024-07-17T13:12:36+00:00 Info HEADERS: array ( 'Content-Type' => 'application/json; charset=utf-8', 'User-Agent' => 'WooCommerce Payments/7.8.1', 'Idempotency-Key' => 'aa1f4907-3486-482f-a4eb-f287325c6677', ) 2024-07-17T13:12:36+00:00 Info BODY: array ( 'test_mode' => true, 'confirm' => 'true', 'capture_method' => 'automatic', 'is_platform_payment_method' => 'true', 'woopay_has_subscription' => false, 'save_payment_method_to_platform' => false, 'amount' => 24410, 'currency' => 'gbp', 'payment_method' => 'pm_1PdXeoFuiXB5oUVxqGWz1S4j', 'customer' => 'cus_QRQT3cMHddrF94', 'metadata' => array ( 'customer_name' => '(redacted)', 'customer_email' => '(redacted)', 'site_url' => 'https://fortunately-wise.jurassic.ninja', 'order_id' => 34, 'order_number' => '34', 'order_key' => 'wc_order_IE8cK3v6Dip3q', 'payment_type' => 'WCPay\\Constants\\Payment_Type()', 'checkout_type' => 'store-api', 'client_version' => '7.8.1', 'subscription_payment' => 'no', 'fraud_prevention_data_shopper_ip_hash' => '00a22165d1acc0868df0afa51b3dc2e3fab7b03a71d96804d3da4ff95b75dfd21d038c02a20e5d36f67baa4925f6a0b3aa1230a09c508590b4af9ea2404961e2', 'fraud_prevention_data_shopper_ua_hash' => '8b0231e90cc69a1e4e8d184cb5bc9d70', 'fraud_prevention_data_ip_country' => 'SE', 'fraud_prevention_data_cart_contents' => 3, 'fraud_prevention_data_available' => true, ), 'description' => 'Online Payment for Order #34 for fortunately-wise.jurassic.ninja blog_id 234929657', 'level3' => array ( 'merchant_reference' => '34', 'customer_reference' => '34', 'shipping_amount' => 0, 'line_items' => array ( 0 => 'stdClass()', ), 'shipping_address_zip' => '94110', ), 'payment_method_types' => array ( 0 => 'card', ), 'cvc_confirmation' => NULL, ) 2024-07-17T13:12:38+00:00 Info Invalid level3: pricing must be consistent. Sum(unit_cost * quantity + tax_amount - discount_amount) + shipping_amount != total charged. In this case, 24411 != 24410. (invalid_request_error) 2024-07-17T13:12:38+00:00 Info Level3 data error: Error: Invalid level3: pricing must be consistent. Sum(unit_cost * quantity + tax_amount - discount_amount) + shipping_amount != total charged. In this case, 24411 != 24410. Level 3 data sent: Array ( [merchant_reference] => 34 [customer_reference] => 34 [shipping_amount] => 0 [line_items] => Array ( [0] => stdClass Object ( [product_code] => 25 [product_description] => Simple test pf 2024-07-19 [unit_cost] => 8137 [quantity] => 3 [tax_amount] => 0 [discount_amount] => 0 ) ) [shipping_address_zip] => 94110 ) 2024-07-17T13:12:38+00:00 Info ENVIRONMENT: array ( 'WP_User' => 'demo', 'HTTP_REFERER' => 'https://fortunately-wise.jurassic.ninja/checkout/', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', 'REQUEST_URI' => '/wp-json/wc/store/v1/checkout?_locale=user', 'DOING_AJAX' => false, 'DOING_CRON' => false, 'WP_CLI' => false, ) 2024-07-17T13:12:38+00:00 Info REQUEST POST https://public-api.wordpress.com/wpcom/v2/sites/%s/wcpay/intentions 2024-07-17T13:12:38+00:00 Info HEADERS: array ( 'Content-Type' => 'application/json; charset=utf-8', 'User-Agent' => 'WooCommerce Payments/7.8.1', 'Idempotency-Key' => 'd9aa61d6-ca7b-4a3f-b54a-0e95132b3f29', ) 2024-07-17T13:12:38+00:00 Info BODY: array ( 'test_mode' => true, 'confirm' => 'true', 'capture_method' => 'automatic', 'is_platform_payment_method' => 'true', 'woopay_has_subscription' => false, 'save_payment_method_to_platform' => false, 'amount' => 24410, 'currency' => 'gbp', 'payment_method' => 'pm_1PdXeoFuiXB5oUVxqGWz1S4j', 'customer' => 'cus_QRQT3cMHddrF94', 'metadata' => array ( 'customer_name' => '(redacted)', 'customer_email' => '(redacted)', 'site_url' => 'https://fortunately-wise.jurassic.ninja', 'order_id' => 34, 'order_number' => '34', 'order_key' => 'wc_order_IE8cK3v6Dip3q', 'payment_type' => 'WCPay\\Constants\\Payment_Type()', 'checkout_type' => 'store-api', 'client_version' => '7.8.1', 'subscription_payment' => 'no', 'fraud_prevention_data_shopper_ip_hash' => '00a22165d1acc0868df0afa51b3dc2e3fab7b03a71d96804d3da4ff95b75dfd21d038c02a20e5d36f67baa4925f6a0b3aa1230a09c508590b4af9ea2404961e2', 'fraud_prevention_data_shopper_ua_hash' => '8b0231e90cc69a1e4e8d184cb5bc9d70', 'fraud_prevention_data_ip_country' => 'SE', 'fraud_prevention_data_cart_contents' => 3, 'fraud_prevention_data_available' => true, ), 'description' => 'Online Payment for Order #34 for fortunately-wise.jurassic.ninja blog_id 234929657', 'payment_method_types' => array ( 0 => 'card', ), 'cvc_confirmation' => NULL, ) 2024-07-17T13:12:38+00:00 Info The provided PaymentMethod was previously used with a PaymentIntent without Customer attachment, shared with a connected account without Customer attachment, or was detached from a Customer. It may not be used again. To use a PaymentMethod multiple times, you must attach it to a Customer first. (invalid_request_error) 2024-07-17T13:12:47+00:00 Info ENVIRONMENT: array ( 'WP_User' => 'demo', 'HTTP_REFERER' => '--', 'HTTP_USER_AGENT' => 'WordPress/6.6; https://fortunately-wise.jurassic.ninja', 'REQUEST_URI' => '/wp-admin/admin-ajax.php?action=as_async_request_queue_runner&nonce=a3d5af65f0', 'DOING_AJAX' => true, 'DOING_CRON' => false, 'WP_CLI' => false, ) 2024-07-17T13:12:47+00:00 Info REQUEST POST https://public-api.wordpress.com/wpcom/v2/sites/%s/wcpay/tracking/order 2024-07-17T13:12:47+00:00 Info HEADERS: array ( 'Content-Type' => 'application/json; charset=utf-8', 'User-Agent' => 'WooCommerce Payments/7.8.1', 'Idempotency-Key' => 'af03462f-7786-4fa0-83f4-c00cd337869a', ) 2024-07-17T13:12:47+00:00 Info BODY: array ( 'test_mode' => true, 'order_data' => array ( 'id' => 34, 'parent_id' => 0, 'status' => 'failed', 'currency' => 'GBP', 'version' => '9.0.2', 'prices_include_tax' => false, 'date_created' => 'WC_DateTime()', 'date_modified' => 'WC_DateTime()', 'discount_total' => '0', 'discount_tax' => '0', 'shipping_total' => '0', 'shipping_tax' => '0', 'cart_tax' => '0', 'total' => '244.10', 'total_tax' => '0', 'customer_id' => 1, 'order_key' => 'wc_order_IE8cK3v6Dip3q', 'billing' => array ( 'first_name' => '(redacted)', 'last_name' => '(redacted)', 'company' => '(redacted)', 'address_1' => '(redacted)', 'address_2' => '(redacted)', 'city' => '(redacted)', 'state' => '(redacted)', 'postcode' => '(redacted)', 'country' => '(redacted)', 'email' => '(redacted)', 'phone' => '(redacted)', ), 'shipping' => array ( 'first_name' => '(redacted)', 'last_name' => '(redacted)', 'company' => '(redacted)', 'address_1' => '(redacted)', 'address_2' => '(redacted)', 'city' => '(redacted)', 'state' => '(redacted)', 'postcode' => '(redacted)', 'country' => '(redacted)', 'phone' => '(redacted)', ), 'payment_method' => 'woocommerce_payments', 'payment_method_title' => 'Credit card / debit card', 'transaction_id' => '', 'customer_ip_address' => '185.138.30.251', 'customer_user_agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', 'created_via' => 'store-api', 'customer_note' => '', 'date_completed' => NULL, 'date_paid' => NULL, 'cart_hash' => '4724eb05c6769fba4bfe89f91ecee097', 'order_stock_reduced' => false, 'download_permissions_granted' => false, 'new_order_email_sent' => false, 'recorded_sales' => false, 'recorded_coupon_usage_counts' => false, 'number' => '34', 'meta_data' => array ( 0 => 'WC_Meta_Data()', 1 => 'WC_Meta_Data()', 2 => 'WC_Meta_Data()', 3 => 'WC_Meta_Data()', 4 => 'WC_Meta_Data()', 5 => 'WC_Meta_Data()', 6 => 'WC_Meta_Data()', 7 => 'WC_Meta_Data()', 8 => 'WC_Meta_Data()', 9 => 'WC_Meta_Data()', 10 => 'WC_Meta_Data()', 11 => 'WC_Meta_Data()', 12 => 'WC_Meta_Data()', 13 => 'WC_Meta_Data()', 14 => 'WC_Meta_Data()', 15 => 'WC_Meta_Data()', 16 => 'WC_Meta_Data()', 17 => 'WC_Meta_Data()', 18 => 'WC_Meta_Data()', 19 => 'WC_Meta_Data()', ), 'line_items' => array ( 621 => 'WC_Order_Item_Product()', ), 'tax_lines' => array ( ), 'shipping_lines' => array ( 622 => 'WC_Order_Item_Shipping()', ), 'fee_lines' => array ( ), 'coupon_lines' => array ( ), '_payment_method_id' => 'pm_1PdXeoFuiXB5oUVxqGWz1S4j', '_stripe_customer_id' => 'cus_QRQT3cMHddrF94', '_wcpay_mode' => 'test', ), 'update' => false, ) 2024-07-17T13:12:47+00:00 Info RESPONSE: array ( 'result' => 'error', ) ```
jimjasson commented 2 months ago

Worth surfacing that:

I wasn't able to check out with product qty > 1 due to the rounding problem with Level 3 data, but I will create a separate issue for that, since it seems that this problem also happens with the latest stable WooPayments.

Even though this issue was discovered via testing https://github.com/Automattic/woocommerce-payments/pull/9070, we could replicate this issue with the previous stable WooPayments version as well.

peterfabian commented 2 months ago

Good point, thanks @jimjasson , updated the description.