Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ECE Payment buttons on Pay for Order page #3440

Merged
merged 78 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 77 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
7d1d4b7
add ece feature flag
Mayisha Sep 2, 2024
a5cc1f0
update '@stripe/react-stripe-js' to latest
Mayisha Sep 3, 2024
26c0196
render ece button on block checkout
Mayisha Sep 3, 2024
fe572d5
display ece button if feature flag is enabled
Mayisha Sep 4, 2024
48e7e11
Merge branch 'develop' into task/3402-ece-ff
Mayisha Sep 9, 2024
122db02
check ece feature flag status from blocks data
Mayisha Sep 9, 2024
6a8e7ae
add min height to express checkout container
Mayisha Sep 9, 2024
34dc409
create 'WC_Stripe_Express_Checkout_Element' class
Mayisha Sep 10, 2024
ac13e24
fix callback function name
Mayisha Sep 10, 2024
0da1b05
register script for shortcode checkout
Mayisha Sep 10, 2024
9291021
move ajax functions to separate class
Mayisha Sep 10, 2024
8c6f05d
move helper functions to a separate class
Mayisha Sep 10, 2024
e3f68d3
include and initialize express checkout classes
Mayisha Sep 10, 2024
9502a5a
Merge branch 'develop' into task/ece-backend
Mayisha Sep 10, 2024
55e661c
make functions public in the helper class
Mayisha Sep 11, 2024
08c3205
fix lint issue
Mayisha Sep 11, 2024
7539f73
Merge branch 'develop' into task/ece-backend
Mayisha Sep 11, 2024
1f42347
use correct global variable
Mayisha Sep 11, 2024
632b63c
fix php lint issues
Mayisha Sep 11, 2024
1be4921
Integrating ECE to shortcode checkout
wjrosa Sep 13, 2024
f2b64f3
Adding extra contraints to show ECE
wjrosa Sep 13, 2024
1e901c9
Merge branch 'develop' into add/ece-for-shortcode-checkout
wjrosa Sep 17, 2024
b318c26
Importing additional implementations from WCPay
wjrosa Sep 17, 2024
8956e8e
Use our own Stripe tracking
mattallan Sep 17, 2024
0af7c3e
Fix typos in normalizeOrderData
mattallan Sep 17, 2024
acc8e92
Add missing client/api methods to handle ECE requests
mattallan Sep 18, 2024
afbb84e
Update ESLint config to not require await directly within async funct…
mattallan Sep 18, 2024
0cd28d5
Fix JS linting issues
mattallan Sep 18, 2024
d94bde5
Use startExpressCheckoutElement() to init the payment button
james-allan Sep 18, 2024
56225b3
Add getExpressCheckoutAjaxURL util function
mattallan Sep 18, 2024
9a40a5d
Update ECE API functions to use express checkout data
mattallan Sep 18, 2024
942af31
Move api const to top and add init function for page specific initial…
james-allan Sep 18, 2024
3efecab
Fix comment
james-allan Sep 18, 2024
08b7718
Localize scripts for pay for order screen and init payment element
james-allan Sep 18, 2024
3a24788
Adding changelog entry
wjrosa Sep 18, 2024
c07f00d
Putting display none back
wjrosa Sep 18, 2024
8244cf3
Multiple changes to the display logic based on WCPay
wjrosa Sep 18, 2024
99cceb4
Multiple changes to the display logic based on WCPay
wjrosa Sep 18, 2024
b894df0
Fix multiple issues + changing the main element ID
wjrosa Sep 18, 2024
ef6f49d
Removing unsupported coalesce operator
wjrosa Sep 18, 2024
1114804
Including missing methods
wjrosa Sep 18, 2024
d0055ea
Fix lint issues
wjrosa Sep 18, 2024
eeee466
Fix lint issues
wjrosa Sep 18, 2024
bc581aa
Updating ESLint version and requirement
wjrosa Sep 18, 2024
e839cd0
ECE instantiation options update
wjrosa Sep 18, 2024
2c01b39
Process Express payment button payments via Pay for Order page
james-allan Sep 19, 2024
bd7dacd
Fix get/update shipping option AJAX requests
mattallan Sep 19, 2024
1168099
Rename WooPayment related funtion and fix camelcase issue
james-allan Sep 19, 2024
a933b6e
Fetch proper requestShipping meta from product data
mattallan Sep 19, 2024
e49eb3a
Set 'wc-stripe-is-deferred-intent' in data submitted with the checkou…
mattallan Sep 19, 2024
710df89
Set the wc-stripe-is-deferred-intent flag via the request, not the ha…
james-allan Sep 19, 2024
03ecb97
Use camel case variable to avoid linting ignores
james-allan Sep 19, 2024
b204302
Remove eslint diable for camelcase
james-allan Sep 19, 2024
e36f28b
Merge branch 'develop' into add/ece-for-shortcode-checkout
wjrosa Sep 19, 2024
1e08089
Fixing additional JS error + reverting removal of ESLint rule
wjrosa Sep 20, 2024
dbee822
Resolving ESLint issues
wjrosa Sep 20, 2024
a3409f9
Increasing ECMAScript version in .jshintrc
wjrosa Sep 20, 2024
15ed41f
Reverting unnecessary changes to stripe-utils
wjrosa Sep 20, 2024
fe64a45
Reverting more unnecessary changes
wjrosa Sep 20, 2024
63ba605
Reverting hardcoded flag
wjrosa Sep 20, 2024
74df4cf
Fix Jest functions undefined in .jshintrc
wjrosa Sep 20, 2024
c0f2336
Adding specific unit tests
wjrosa Sep 20, 2024
bc7a79b
Adding specific unit tests
wjrosa Sep 20, 2024
94b9c63
Reverting unnecessary changes
wjrosa Sep 20, 2024
1554796
Putting some coalesce operators back
wjrosa Sep 20, 2024
a5b19e4
Replace i18n text domain
james-allan Sep 23, 2024
7a53b7c
Fix typo
james-allan Sep 23, 2024
584252f
Merge branch 'add/ece-for-shortcode-checkout' into add/ece-for-pay-fo…
james-allan Sep 23, 2024
299d422
Merge branch 'develop' into add/ece-for-pay-for-order-page
james-allan Sep 26, 2024
5c99912
Set deferred-intent flag
james-allan Sep 26, 2024
d9e80a8
Remove merge conflict flags
james-allan Sep 26, 2024
53a8d2d
Remove unused files
james-allan Sep 26, 2024
371649e
Add changelog entries
james-allan Sep 26, 2024
8f91625
Merge branch 'develop' into add/ece-for-pay-for-order-page
james-allan Sep 26, 2024
fd8281e
Reintroduce changelog removed by error
james-allan Sep 26, 2024
1236826
Fix button width issues
james-allan Sep 26, 2024
d30566a
Use tabs and add empty line
james-allan Sep 26, 2024
d9b9149
Merge branch 'develop' into add/ece-for-pay-for-order-page
mattallan Sep 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

= 8.8.0 - xxxx-xx-xx =
* Add - Implemented the "Update all subscriptions payment methods" checkbox on My Account → Payment methods for UPE payment methods.
* Add - Add support for the new Stripe Checkout Element on the shortcode checkout page.
* Add - Add support for the new Stripe Checkout Element on the shortcode checkout page.
* Add - Add support for the new Stripe Checkout Element on the pay for order page.
* Dev - Introduces a new class with payment methods constants.
* Dev - Introduces a new class with currency codes constants.
* Dev - Improves the readability of the redirect URL generation code (UPE).
Expand Down
18 changes: 17 additions & 1 deletion client/entrypoints/express-checkout/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/*global wcStripeExpressCheckoutPayForOrderParams */
import { __ } from '@wordpress/i18n';
import { debounce } from 'lodash';
import jQuery from 'jquery';
Expand All @@ -21,6 +22,7 @@ import {
} from 'wcstripe/express-checkout/event-handler';
import { getStripeServerData } from 'wcstripe/stripe-utils';
import { getAddToCartVariationParams } from 'wcstripe/utils';
import './styles.scss';

jQuery( function ( $ ) {
// Don't load if blocks checkout is being loaded.
Expand Down Expand Up @@ -267,7 +269,21 @@ jQuery( function ( $ ) {
*/
init: () => {
if ( getExpressCheckoutData( 'is_pay_for_order' ) ) {
// Pay for order page specific initialization.
const {
total: { amount: total },
displayItems,
order,
} = wcStripeExpressCheckoutPayForOrderParams;

wcStripeECE.startExpressCheckoutElement( {
mode: 'payment',
total,
currency: getExpressCheckoutData( 'checkout' )
.currency_code,
appearance: getExpressCheckoutButtonAppearance(),
displayItems,
order,
} );
} else if ( getExpressCheckoutData( 'is_product_page' ) ) {
// Product page specific initialization.
} else {
Expand Down
3 changes: 3 additions & 0 deletions client/entrypoints/express-checkout/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#wc-stripe-express-checkout-element iframe {
max-width: unset;
Copy link
Contributor Author

@james-allan james-allan Sep 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes an issue on all shortcode powered pages and follows the same approach WooPayments took in Automattic/woocommerce-payments#9094 and discussed with Stripe internallly here: p1720833500937719-slack-C9976E5MJ

PAY FOR ORDER

Screenshot 2024-09-26 at 4 44 10 pm
Gap on the right hand side of the payment elements.

CHECKOUT

Screenshot 2024-09-26 at 5 20 45 pm

CART

Screenshot 2024-09-26 at 5 11 45 pm

}
1 change: 1 addition & 0 deletions client/express-checkout/utils/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export const normalizeOrderData = ( event, paymentMethodId ) => {
export const normalizePayForOrderData = ( event, paymentMethodId ) => {
return {
payment_method: 'stripe',
'wc-stripe-is-deferred-intent': true, // Set the deferred intent flag, so the deferred intent flow is used.
'wc-stripe-payment-method': paymentMethodId,
express_payment_type: event?.expressPaymentType,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public function init() {
add_action( 'wc_ajax_wc_stripe_get_selected_product_data', [ $this, 'ajax_get_selected_product_data' ] );
add_action( 'wc_ajax_wc_stripe_clear_cart', [ $this, 'ajax_clear_cart' ] );
add_action( 'wc_ajax_wc_stripe_log_errors', [ $this, 'ajax_log_errors' ] );
add_action( 'wc_ajax_wc_stripe_pay_for_order', [ $this, 'ajax_pay_for_order' ] );
}

/**
Expand Down Expand Up @@ -71,7 +72,7 @@ public function ajax_get_cart_details() {
/**
* Adds the current product to the cart. Used on product detail page.
*
* @return array $data Results of adding the product to the cart.
* @return array $data Results of adding the product to the cart.
*/
public function ajax_add_to_cart() {
check_ajax_referer( 'wc-stripe-add-to-cart', 'security' );
Expand Down Expand Up @@ -307,4 +308,65 @@ public function ajax_log_errors() {

exit;
}

/**
* Processes the Pay for Order AJAX request from the Express Checkout.
*/
public function ajax_pay_for_order() {
check_ajax_referer( 'wc-stripe-pay-for-order' );

if (
! isset( $_POST['payment_method'] ) || 'stripe' !== $_POST['payment_method']
|| ! isset( $_POST['order'] ) || ! intval( $_POST['order'] )
|| ! isset( $_POST['wc-stripe-payment-method'] ) || empty( $_POST['wc-stripe-payment-method'] )
) {
// Incomplete request.
$response = [
'result' => 'error',
'messages' => __( 'Invalid request', 'woocommerce-gateway-stripe' ),
];
wp_send_json( $response, 400 );
return;
}

try {
// Set up an environment, similar to core checkout.
wc_maybe_define_constant( 'WOOCOMMERCE_CHECKOUT', true );
wc_set_time_limit( 0 );

// Load the order.
$order_id = intval( $_POST['order'] );
$order = wc_get_order( $order_id );

if ( ! is_a( $order, WC_Order::class ) ) {
throw new Exception( __( 'Invalid order!', 'woocommerce-gateway-stripe' ) );
}

if ( ! $order->needs_payment() ) {
throw new Exception( __( 'This order does not require payment!', 'woocommerce-gateway-stripe' ) );
}

// Process the payment.
$result = WC_Stripe::get_instance()->get_main_stripe_gateway()->process_payment( $order_id );

$this->express_checkout_helper->add_order_payment_method_title( $order );

// process_payment() should only return `success` or throw an exception.
if ( ! is_array( $result ) || ! isset( $result['result'] ) || 'success' !== $result['result'] || ! isset( $result['redirect'] ) ) {
throw new Exception( __( 'Unable to determine payment success.', 'woocommerce-gateway-stripe' ) );
}

// Include the order ID in the result.
$result['order_id'] = $order_id;

$result = apply_filters( 'woocommerce_payment_successful_result', $result, $order_id );
} catch ( Exception $e ) {
$result = [
'result' => 'error',
'messages' => $e->getMessage(),
];
}

wp_send_json( $result );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,14 @@ public function init() {
add_action( 'woocommerce_after_add_to_cart_form', [ $this, 'display_express_checkout_button_html' ], 1 );
add_action( 'woocommerce_proceed_to_checkout', [ $this, 'display_express_checkout_button_html' ], 25 );
add_action( 'woocommerce_checkout_before_customer_details', [ $this, 'display_express_checkout_button_html' ], 1 );
add_action( 'woocommerce_pay_order_before_payment', [ $this, 'display_express_checkout_button_html' ], 1 );

add_filter( 'woocommerce_gateway_title', [ $this, 'filter_gateway_title' ], 10, 2 );
add_action( 'woocommerce_checkout_order_processed', [ $this, 'add_order_meta' ], 10, 2 );
add_filter( 'woocommerce_login_redirect', [ $this, 'get_login_redirect_url' ], 10, 3 );
add_filter( 'woocommerce_registration_redirect', [ $this, 'get_login_redirect_url' ], 10, 3 );

add_action( 'before_woocommerce_pay_form', [ $this, 'localize_pay_for_order_page_scripts' ] );
}

/**
Expand Down Expand Up @@ -184,6 +187,7 @@ public function javascript_params() {
'get_selected_product_data' => wp_create_nonce( 'wc-stripe-get-selected-product-data' ),
'log_errors' => wp_create_nonce( 'wc-stripe-log-errors' ),
'clear_cart' => wp_create_nonce( 'wc-stripe-clear-cart' ),
'pay_for_order' => wp_create_nonce( 'wc-stripe-pay-for-order' ),
],
'i18n' => [
'no_prepaid_card' => __( 'Sorry, we\'re not accepting prepaid cards at this time.', 'woocommerce-gateway-stripe' ),
Expand All @@ -208,6 +212,64 @@ public function javascript_params() {
];
}

/**
* Localizes additional parameters necessary for the Pay for Order page.
*
* @param WC_Order $order The order that needs payment.
*/
public function localize_pay_for_order_page_scripts( $order ) {
$currency = get_woocommerce_currency();
$data = [];
$items = [];

foreach ( $order->get_items() as $item ) {
if ( method_exists( $item, 'get_total' ) ) {
$items[] = [
'label' => $item->get_name(),
'amount' => WC_Stripe_Helper::get_stripe_amount( $item->get_total(), $currency ),
];
}
}

if ( $order->get_total_tax() ) {
$items[] = [
'label' => __( 'Tax', 'woocommerce-gateway-stripe' ),
'amount' => WC_Stripe_Helper::get_stripe_amount( $order->get_total_tax(), $currency ),
];
}

if ( $order->get_shipping_total() ) {
$shipping_label = sprintf(
// Translators: %s is the name of the shipping method.
__( 'Shipping (%s)', 'woocommerce-gateway-stripe' ),
$order->get_shipping_method()
);

$items[] = [
'label' => $shipping_label,
'amount' => WC_Stripe_Helper::get_stripe_amount( $order->get_shipping_total(), $currency ),
];
}

foreach ( $order->get_fees() as $fee ) {
$items[] = [
'label' => $fee->get_name(),
'amount' => WC_Stripe_Helper::get_stripe_amount( $fee->get_amount(), $currency ),
];
}

$data['order'] = $order->get_id();
$data['displayItems'] = $items;
$data['needs_shipping'] = false; // This should be already entered/prepared.
$data['total'] = [
'label' => $this->express_checkout_helper->get_total_label(),
'amount' => WC_Stripe_Helper::get_stripe_amount( $order->get_total(), $currency ),
'pending' => true,
];

wp_localize_script( 'wc_stripe_express_checkout', 'wcStripeExpressCheckoutPayForOrderParams', $data );
}

/**
* Load scripts and styles.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1218,4 +1218,34 @@ public function maybe_restore_recurring_chosen_shipping_methods( $previous_chose

WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
}

/**
* Adds the express checkout payment method title to the order.
*
* @param WC_Order $order The order.
*/
public function add_order_payment_method_title( $order ) {
if ( empty( $_POST['express_payment_type'] ) || ! isset( $_POST['payment_method'] ) || 'stripe' !== $_POST['payment_method'] ) { // phpcs:ignore WordPress.Security.NonceVerification
return;
}

$express_payment_type = wc_clean( wp_unslash( $_POST['express_payment_type'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
$express_payment_titles = [
'apple_pay' => 'Apple Pay',
'google_pay' => 'Google Pay',
];
$payment_method_title = $express_payment_titles[ $express_payment_type ] ?? false;

if ( ! $payment_method_title ) {
return;
}

$suffix = apply_filters( 'wc_stripe_payment_request_payment_method_title_suffix', 'Stripe' );
if ( ! empty( $suffix ) ) {
$suffix = " ($suffix)";
}

$order->set_payment_method_title( $payment_method_title . $suffix );
$order->save();
}
}
3 changes: 2 additions & 1 deletion readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ If you get stuck, you can ask for help in the Plugin Forum.

= 8.8.0 - xxxx-xx-xx =
* Add - Implemented the "Update all subscriptions payment methods" checkbox on My Account → Payment methods for UPE payment methods.
* Add - Add support for the new Stripe Checkout Element on the shortcode checkout page.
* Add - Add support for the new Stripe Checkout Element on the shortcode checkout page.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is just a blank space at the end of the line which is being removed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird that GH isn't showing the whitespace being removed!

* Add - Add support for the new Stripe Checkout Element on the pay for order page.
* Dev - Introduces a new class with payment methods constants.
* Dev - Introduces a new class with currency codes constants.
* Dev - Improves the readability of the redirect URL generation code (UPE).
Expand Down
Loading