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

Blocks API: get billing details from order if not in request #3778

Merged
merged 4 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
*** Changelog ***

= 9.2.0 - xxxx-xx-xx =
* Fix - Fix Stripe customer creation when using the Blocks API for express checkout.
* Add - Add new payment processing flow using confirmation tokens.
* Dev - Adds new logs to identify why express payment methods are not being displayed.
* Fix - Fixes a fatal error when editing the shortcode checkout page with an empty cart on PHP 8.4.
Expand Down
96 changes: 79 additions & 17 deletions includes/class-wc-stripe-customer.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,7 @@ public function set_customer_data( $data ) {
* @return array
*/
protected function generate_customer_request( $args = [] ) {
$billing_email = isset( $_POST['billing_email'] ) ? filter_var( wp_unslash( $_POST['billing_email'] ), FILTER_SANITIZE_EMAIL ) : '';
$user = $this->get_user();
$address_fields = [
'line1' => 'billing_address_1',
'line2' => 'billing_address_2',
'postal_code' => 'billing_postcode',
'city' => 'billing_city',
'state' => 'billing_state',
'country' => 'billing_country',
];

$user = $this->get_user();
if ( $user ) {
$billing_first_name = get_user_meta( $user->ID, 'billing_first_name', true );
$billing_last_name = get_user_meta( $user->ID, 'billing_last_name', true );
Expand Down Expand Up @@ -162,8 +152,9 @@ protected function generate_customer_request( $args = [] ) {
$defaults['name'] = $billing_full_name;
}
} else {
$billing_first_name = isset( $_POST['billing_first_name'] ) ? filter_var( wp_unslash( $_POST['billing_first_name'] ), FILTER_SANITIZE_SPECIAL_CHARS ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
$billing_last_name = isset( $_POST['billing_last_name'] ) ? filter_var( wp_unslash( $_POST['billing_last_name'] ), FILTER_SANITIZE_SPECIAL_CHARS ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
$billing_email = $this->get_billing_data_field( 'billing_email', $args );
$billing_first_name = $this->get_billing_data_field( 'billing_first_name', $args );
$billing_last_name = $this->get_billing_data_field( 'billing_last_name', $args );

// translators: %1$s First name, %2$s Second name.
$description = sprintf( __( 'Name: %1$s %2$s, Guest', 'woocommerce-gateway-stripe' ), $billing_first_name, $billing_last_name );
Expand All @@ -184,17 +175,86 @@ protected function generate_customer_request( $args = [] ) {
$defaults['preferred_locales'] = $this->get_customer_preferred_locale( $user );

// Add customer address default values.
$address_fields = [
'line1' => 'billing_address_1',
'line2' => 'billing_address_2',
'postal_code' => 'billing_postcode',
'city' => 'billing_city',
'state' => 'billing_state',
'country' => 'billing_country',
];
foreach ( $address_fields as $key => $field ) {
if ( $user ) {
$defaults['address'][ $key ] = get_user_meta( $user->ID, $field, true );
} else {
$defaults['address'][ $key ] = isset( $_POST[ $field ] ) ? filter_var( wp_unslash( $_POST[ $field ] ), FILTER_SANITIZE_SPECIAL_CHARS ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
$defaults['address'][ $key ] = $this->get_billing_data_field( $field, $args );
}
}

return wp_parse_args( $args, $defaults );
}

/**
* Get value of billing data field, either from POST or order object.
*
* @param string $field Field name.
* @param array $args Additional arguments (optional).
*
* @return string
*/
private function get_billing_data_field( $field, $args = [] ) {
$valid_fields = [
'billing_email',
'billing_first_name',
'billing_last_name',
'billing_address_1',
'billing_address_2',
'billing_postcode',
'billing_city',
'billing_state',
'billing_country',
];

// Restrict field parameter to list of known billing fields.
if ( ! in_array( $field, $valid_fields, true ) ) {
return '';
}

// Prioritize POST data, if available.
if ( isset( $_POST[ $field ] ) ) {
if ( 'billing_email' === $field ) {
return filter_var( wp_unslash( $_POST[ $field ] ), FILTER_SANITIZE_EMAIL ); // phpcs:ignore WordPress.Security.NonceVerification
}

return filter_var( wp_unslash( $_POST[ $field ] ), FILTER_SANITIZE_SPECIAL_CHARS ); // phpcs:ignore WordPress.Security.NonceVerification
} elseif ( isset( $args['order'] ) && $args['order'] instanceof WC_Order ) {
switch ( $field ) {
case 'billing_email':
return $args['order']->get_billing_email();
case 'billing_first_name':
return $args['order']->get_billing_first_name();
case 'billing_last_name':
return $args['order']->get_billing_last_name();
case 'billing_address_1':
return $args['order']->get_billing_address_1();
case 'billing_address_2':
return $args['order']->get_billing_address_2();
case 'billing_postcode':
return $args['order']->get_billing_postcode();
case 'billing_city':
return $args['order']->get_billing_city();
case 'billing_state':
return $args['order']->get_billing_state();
case 'billing_country':
return $args['order']->get_billing_country();
default:
return '';
}
}

return '';
}

/**
* If customer does not exist, create a new customer. Else retrieve the Stripe customer through the API to check it's existence.
* Recreate the customer if it does not exist in this Stripe account.
Expand Down Expand Up @@ -328,7 +388,7 @@ public function update_customer( $args = [], $is_retry = false ) {
*/
public function update_or_create_customer( $args = [], $is_retry = false ) {
if ( empty( $this->get_id() ) ) {
return $this->recreate_customer();
return $this->recreate_customer( $args );
} else {
return $this->update_customer( $args, true );
}
Expand Down Expand Up @@ -676,11 +736,13 @@ public function delete_id_from_meta() {
/**
* Recreates the customer for this user.
*
* @param array $args Additional arguments for the request (optional).
*
* @return string ID of the new Customer object.
*/
private function recreate_customer() {
private function recreate_customer( $args = [] ) {
$this->delete_id_from_meta();
return $this->create_customer();
return $this->create_customer( $args );
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2440,7 +2440,10 @@ private function get_customer_id_for_order( WC_Order $order ): string {
$user = $this->get_user_from_order( $order );
$customer = new WC_Stripe_Customer( $user->ID );

return $customer->update_or_create_customer();
// Pass the order object so we can retrieve billing details
// in payment flows where it is not present in the request.
$args = [ 'order' => $order ];
return $customer->update_or_create_customer( $args );
}

/**
Expand Down
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
== Changelog ==

= 9.2.0 - xxxx-xx-xx =
* Fix - Fix Stripe customer creation when using the Blocks API for express checkout.
* Add - Add new payment processing flow using confirmation tokens.
* Dev - Adds new logs to identify why express payment methods are not being displayed.
* Fix - Fixes a fatal error when editing the shortcode checkout page with an empty cart on PHP 8.4.
Expand Down
Loading