mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
Merge branch 'trunk' into PCP-2768-zero-sum-subscriptions-cause-cannot-be-zero-or-negative-when-using-vault-v-3
This commit is contained in:
commit
a83d022228
22 changed files with 283 additions and 63 deletions
|
@ -1,5 +1,19 @@
|
|||
*** Changelog ***
|
||||
|
||||
= 2.6.1 - xxxx-xx-xx =
|
||||
* Fix - Payment tokens fixes and adjustments #2106
|
||||
* Fix - Pay upon Invoice: Add input validation to Experience Context fields #2092
|
||||
* Fix - Disable markup in get_plugin_data() returns to fix an issue with wptexturize() #2094
|
||||
* Enhancement - Pay later messaging configurator improvements #2107
|
||||
* Enhancement - Replace the middleware URL from connect.woocommerce.com to api.woocommerce.com/integrations #2130
|
||||
* Enhancement - Remove all Sofort references as it has been deprecated #2124
|
||||
* Enhancement - Improve funding source names #2118
|
||||
* Enhancement - More fraud prevention capabilities by storing additional data in the order #2125
|
||||
* Enhancement - Update ACDC currency eligibility for AMEX #2129
|
||||
* Enhancement - Sync shipping options with Venmo when skipping final confirmation on Checkout #2108
|
||||
* Enhancement - Card Fields: Add a filter for the CVC field and update the placeholder to match the label #2089
|
||||
* Enhancement - Product Title: Sanitize before sending to PayPal #2090
|
||||
|
||||
= 2.6.0 - 2024-03-20 =
|
||||
* Fix - invoice_id not included in API call when creating payment with saved card #2086
|
||||
* Fix - Typo in SCA indicators for ACDC Vault transactions #2083
|
||||
|
|
|
@ -1000,11 +1000,21 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
if ( $this->settings->has( '3d_secure_contingency' ) ) {
|
||||
$value = $this->settings->get( '3d_secure_contingency' );
|
||||
if ( $value ) {
|
||||
return $value;
|
||||
return $this->return_3ds_contingency( $value );
|
||||
}
|
||||
}
|
||||
|
||||
return 'SCA_WHEN_REQUIRED';
|
||||
return $this->return_3ds_contingency( 'SCA_WHEN_REQUIRED' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes and returns the 3D Secure contingency.
|
||||
*
|
||||
* @param string $contingency The ThreeD secure contingency.
|
||||
* @return string
|
||||
*/
|
||||
private function return_3ds_contingency( string $contingency ): string {
|
||||
return apply_filters( 'woocommerce_paypal_payments_three_d_secure_contingency', $contingency );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -329,6 +329,21 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
if ( 'pay-now' === $data['context'] && is_a( $wc_order, \WC_Order::class ) ) {
|
||||
$wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $order->id() );
|
||||
$wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() );
|
||||
|
||||
$payment_source = $order->payment_source();
|
||||
$payment_source_name = $payment_source ? $payment_source->name() : null;
|
||||
$payer = $order->payer();
|
||||
if (
|
||||
$payer
|
||||
&& $payment_source_name
|
||||
&& in_array( $payment_source_name, PayPalGateway::PAYMENT_SOURCES_WITH_PAYER_EMAIL, true )
|
||||
) {
|
||||
$payer_email = $payer->email_address();
|
||||
if ( $payer_email ) {
|
||||
$wc_order->update_meta_data( PayPalGateway::ORDER_PAYER_EMAIL_META_KEY, $payer_email );
|
||||
}
|
||||
}
|
||||
|
||||
$wc_order->save_meta_data();
|
||||
|
||||
do_action( 'woocommerce_paypal_payments_woocommerce_order_created', $wc_order, $order );
|
||||
|
|
|
@ -159,6 +159,22 @@ class EarlyOrderHandler {
|
|||
$wc_order = wc_get_order( $order_id );
|
||||
$wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $order->id() );
|
||||
$wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() );
|
||||
|
||||
$payment_source = $order->payment_source();
|
||||
$payment_source_name = $payment_source ? $payment_source->name() : null;
|
||||
$payer = $order->payer();
|
||||
if (
|
||||
$payer
|
||||
&& $payment_source_name
|
||||
&& in_array( $payment_source_name, PayPalGateway::PAYMENT_SOURCES_WITH_PAYER_EMAIL, true )
|
||||
&& $wc_order instanceof \WC_Order
|
||||
) {
|
||||
$payer_email = $payer->email_address();
|
||||
if ( $payer_email ) {
|
||||
$wc_order->update_meta_data( PayPalGateway::ORDER_PAYER_EMAIL_META_KEY, $payer_email );
|
||||
}
|
||||
}
|
||||
|
||||
$wc_order->save_meta_data();
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,21 +57,24 @@ class ThreeDSecure {
|
|||
*
|
||||
* @link https://developer.paypal.com/docs/business/checkout/add-capabilities/3d-secure/#authenticationresult
|
||||
*
|
||||
* @param Order $order The order for which the decission is needed.
|
||||
* @param Order $order The order for which the decision is needed.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function proceed_with_order( Order $order ): int {
|
||||
|
||||
do_action( 'woocommerce_paypal_payments_three_d_secure_before_check', $order );
|
||||
|
||||
$payment_source = $order->payment_source();
|
||||
if ( ! $payment_source ) {
|
||||
return self::NO_DECISION;
|
||||
return $this->return_decision( self::NO_DECISION, $order );
|
||||
}
|
||||
|
||||
if ( ! ( $payment_source->properties()->brand ?? '' ) ) {
|
||||
return self::NO_DECISION;
|
||||
return $this->return_decision( self::NO_DECISION, $order );
|
||||
}
|
||||
if ( ! ( $payment_source->properties()->authentication_result ?? '' ) ) {
|
||||
return self::NO_DECISION;
|
||||
return $this->return_decision( self::NO_DECISION, $order );
|
||||
}
|
||||
|
||||
$authentication_result = $payment_source->properties()->authentication_result ?? null;
|
||||
|
@ -81,18 +84,31 @@ class ThreeDSecure {
|
|||
$this->logger->info( '3DS Authentication Result: ' . wc_print_r( $result->to_array(), true ) );
|
||||
|
||||
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_POSSIBLE ) {
|
||||
return self::PROCCEED;
|
||||
return $this->return_decision( self::PROCCEED, $order );
|
||||
}
|
||||
|
||||
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_UNKNOWN ) {
|
||||
return self::RETRY;
|
||||
return $this->return_decision( self::RETRY, $order );
|
||||
}
|
||||
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_NO ) {
|
||||
return $this->no_liability_shift( $result );
|
||||
return $this->return_decision( $this->no_liability_shift( $result ), $order );
|
||||
}
|
||||
}
|
||||
|
||||
return self::NO_DECISION;
|
||||
return $this->return_decision( self::NO_DECISION, $order );
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes and returns a ThreeD secure decision.
|
||||
*
|
||||
* @param int $decision The ThreeD secure decision.
|
||||
* @param Order $order The PayPal Order object.
|
||||
* @return int
|
||||
*/
|
||||
public function return_decision( int $decision, Order $order ) {
|
||||
$decision = apply_filters( 'woocommerce_paypal_payments_three_d_secure_decision', $decision, $order );
|
||||
do_action( 'woocommerce_paypal_payments_three_d_secure_after_check', $order, $decision );
|
||||
return $decision;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -115,17 +115,19 @@ class CardFieldsModule implements ModuleInterface {
|
|||
$settings = $c->get( 'wcgateway.settings' );
|
||||
assert( $settings instanceof Settings );
|
||||
|
||||
$three_d_secure_contingency =
|
||||
$settings->has( '3d_secure_contingency' )
|
||||
? apply_filters( 'woocommerce_paypal_payments_three_d_secure_contingency', $settings->get( '3d_secure_contingency' ) )
|
||||
: '';
|
||||
|
||||
if (
|
||||
$settings->has( '3d_secure_contingency' )
|
||||
&& (
|
||||
$settings->get( '3d_secure_contingency' ) === 'SCA_ALWAYS'
|
||||
|| $settings->get( '3d_secure_contingency' ) === 'SCA_WHEN_REQUIRED'
|
||||
)
|
||||
$three_d_secure_contingency === 'SCA_ALWAYS'
|
||||
|| $three_d_secure_contingency === 'SCA_WHEN_REQUIRED'
|
||||
) {
|
||||
$data['payment_source']['card'] = array(
|
||||
'attributes' => array(
|
||||
'verification' => array(
|
||||
'method' => $settings->get( '3d_secure_contingency' ),
|
||||
'method' => $three_d_secure_contingency,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -194,12 +194,11 @@ export default function Edit( { attributes, clientId, setAttributes } ) {
|
|||
help={ __( 'Used for the analytics dashboard in the merchant account.', 'woocommerce-paypal-payments' ) }
|
||||
options={ [
|
||||
{ label: __( 'Detect automatically', 'woocommerce-paypal-payments' ), value: 'auto' },
|
||||
{ label: __( 'Product Page', 'woocommerce-paypal-payments' ), value: 'product' },
|
||||
{ label: __( 'Cart', 'woocommerce-paypal-payments' ), value: 'cart' },
|
||||
{ label: __( 'Payment', 'woocommerce-paypal-payments' ), value: 'payment' },
|
||||
{ label: __( 'Product', 'woocommerce-paypal-payments' ), value: 'product' },
|
||||
{ label: __( 'Product list', 'woocommerce-paypal-payments' ), value: 'product-list' },
|
||||
{ label: __( 'Checkout', 'woocommerce-paypal-payments' ), value: 'checkout' },
|
||||
{ label: __( 'Home', 'woocommerce-paypal-payments' ), value: 'home' },
|
||||
{ label: __( 'Category', 'woocommerce-paypal-payments' ), value: 'category' },
|
||||
{ label: __( 'Shop', 'woocommerce-paypal-payments' ), value: 'shop' },
|
||||
] }
|
||||
value={ placement }
|
||||
onChange={ ( value ) => setAttributes( { placement: value } ) }
|
||||
|
|
|
@ -40,7 +40,7 @@ class PayLaterBlockModule implements ModuleInterface {
|
|||
* @return bool true if the block is enabled, otherwise false.
|
||||
*/
|
||||
public static function is_block_enabled( SettingsStatus $settings_status ): bool {
|
||||
return self::is_module_loading_required() && $settings_status->is_pay_later_messaging_enabled_for_location( 'woocommerceBlock' );
|
||||
return self::is_module_loading_required() && $settings_status->is_pay_later_messaging_enabled_for_location( 'custom_placement' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,21 +29,17 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
|||
setTimeout(() => {
|
||||
saveChangesButton.click(); // Trigger click event on saveChangesButton
|
||||
isSaving = false; // Reset flag when saving is complete
|
||||
}, 500); // Adjust the delay as needed
|
||||
}, 1000); // Adjust the delay as needed
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
merchantConfigurators.Messaging({
|
||||
config: PcpPayLaterConfigurator.config,
|
||||
merchantClientId: PcpPayLaterConfigurator.merchantClientId,
|
||||
partnerClientId: PcpPayLaterConfigurator.partnerClientId,
|
||||
partnerName: 'WooCommerce',
|
||||
bnCode: 'Woo_PPCP',
|
||||
placements: ['cart', 'checkout', 'product', 'shop', 'home'],
|
||||
custom_placement:[{
|
||||
message_reference: 'woocommerceBlock',
|
||||
}],
|
||||
placements: ['cart', 'checkout', 'product', 'shop', 'home', 'custom_placement'],
|
||||
styleOverrides: {
|
||||
button: publishButtonClassName,
|
||||
header: PcpPayLaterConfigurator.headerClassName,
|
||||
|
|
|
@ -99,10 +99,13 @@ class SaveConfig {
|
|||
$this->settings->set( 'pay_later_messaging_enabled', true );
|
||||
|
||||
$enabled_locations = array();
|
||||
|
||||
foreach ( $config as $placement => $data ) {
|
||||
$this->save_config_for_location( $data, $placement );
|
||||
|
||||
if ( $placement === 'custom_placement' ) {
|
||||
$data = $data[0] ?? array();
|
||||
}
|
||||
|
||||
if ( $data['status'] === 'enabled' ) {
|
||||
$enabled_locations[] = $placement;
|
||||
}
|
||||
|
@ -129,6 +132,7 @@ class SaveConfig {
|
|||
$this->set_value_if_present( $config, 'logo-type', "pay_later_{$location}_message_logo" );
|
||||
$this->set_value_if_present( $config, 'logo-color', "pay_later_{$location}_message_color" );
|
||||
$this->set_value_if_present( $config, 'text-size', "pay_later_{$location}_message_text_size" );
|
||||
$this->set_value_if_present( $config, 'text-color', "pay_later_{$location}_message_color" );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ class ConfigFactory {
|
|||
'product' => $this->for_location( $settings, 'product' ),
|
||||
'shop' => $this->for_location( $settings, 'shop' ),
|
||||
'home' => $this->for_location( $settings, 'home' ),
|
||||
'woocommerceBlock' => $this->for_location( $settings, 'woocommerceBlock' ),
|
||||
'custom_placement' => array( $this->for_location( $settings, 'woocommerceBlock' ) ),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -40,29 +40,87 @@ class ConfigFactory {
|
|||
private function for_location( Settings $settings, string $location ): array {
|
||||
$selected_locations = $settings->has( 'pay_later_messaging_locations' ) ? $settings->get( 'pay_later_messaging_locations' ) : array();
|
||||
|
||||
if ( in_array( $location, array( 'shop', 'home' ), true ) ) {
|
||||
$config = array(
|
||||
'layout' => $this->get_or_default( $settings, "pay_later_{$location}_message_layout", 'flex' ),
|
||||
'color' => $this->get_or_default( $settings, "pay_later_{$location}_message_flex_color", 'black' ),
|
||||
'ratio' => $this->get_or_default( $settings, "pay_later_{$location}_message_flex_ratio", '8x1' ),
|
||||
);
|
||||
} elseif ( $location !== 'woocommerceBlock' ) {
|
||||
$config = array(
|
||||
'layout' => $this->get_or_default( $settings, "pay_later_{$location}_message_layout", 'text' ),
|
||||
'logo-position' => $this->get_or_default( $settings, "pay_later_{$location}_message_position", 'left' ),
|
||||
'logo-type' => $this->get_or_default( $settings, "pay_later_{$location}_message_logo", 'inline' ),
|
||||
'text-color' => $this->get_or_default( $settings, "pay_later_{$location}_message_color", 'black' ),
|
||||
'text-size' => $this->get_or_default( $settings, "pay_later_{$location}_message_text_size", '12' ),
|
||||
|
||||
);
|
||||
switch ( $location ) {
|
||||
case 'shop':
|
||||
case 'home':
|
||||
$config = $this->for_shop_or_home( $settings, $location, $selected_locations );
|
||||
break;
|
||||
case 'woocommerceBlock':
|
||||
$config = $this->for_woocommerce_block( $selected_locations );
|
||||
break;
|
||||
default:
|
||||
$config = $this->for_default_location( $settings, $location, $selected_locations );
|
||||
break;
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
array(
|
||||
'status' => in_array( $location, $selected_locations, true ) ? 'enabled' : 'disabled',
|
||||
'placement' => $location,
|
||||
),
|
||||
$config ?? array()
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configurator config for shop, home locations.
|
||||
*
|
||||
* @param Settings $settings The settings.
|
||||
* @param string $location The location.
|
||||
* @param string[] $selected_locations The list of selected locations.
|
||||
* @return array{
|
||||
* layout: string,
|
||||
* color: string,
|
||||
* ratio: string,
|
||||
* status: "disabled"|"enabled",
|
||||
* placement: string
|
||||
* } The configurator config map.
|
||||
*/
|
||||
private function for_shop_or_home( Settings $settings, string $location, array $selected_locations ): array {
|
||||
return array(
|
||||
'layout' => $this->get_or_default( $settings, "pay_later_{$location}_message_layout", 'flex' ),
|
||||
'color' => $this->get_or_default( $settings, "pay_later_{$location}_message_flex_color", 'black' ),
|
||||
'ratio' => $this->get_or_default( $settings, "pay_later_{$location}_message_flex_ratio", '8x1' ),
|
||||
'status' => in_array( $location, $selected_locations, true ) ? 'enabled' : 'disabled',
|
||||
'placement' => $location,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configurator config for woocommerceBlock location.
|
||||
*
|
||||
* @param array $selected_locations The list of selected locations.
|
||||
* @return array{
|
||||
* status: "disabled"|"enabled",
|
||||
* message_reference: string
|
||||
* } The configurator config map.
|
||||
*/
|
||||
private function for_woocommerce_block( array $selected_locations ): array {
|
||||
return array(
|
||||
'status' => in_array( 'custom_placement', $selected_locations, true ) ? 'enabled' : 'disabled',
|
||||
'message_reference' => 'woocommerceBlock',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configurator config for default locations.
|
||||
*
|
||||
* @param Settings $settings The settings.
|
||||
* @param string $location The location.
|
||||
* @param string[] $selected_locations The list of selected locations.
|
||||
* @return array{
|
||||
* layout: string,
|
||||
* logo-position: string,
|
||||
* logo-type: string,
|
||||
* text-color: string,
|
||||
* text-size: string,
|
||||
* status: "disabled"|"enabled",
|
||||
* placement: string
|
||||
* } The configurator config map.
|
||||
*/
|
||||
private function for_default_location( Settings $settings, string $location, array $selected_locations ): array {
|
||||
return array(
|
||||
'layout' => $this->get_or_default( $settings, "pay_later_{$location}_message_layout", 'text' ),
|
||||
'logo-position' => $this->get_or_default( $settings, "pay_later_{$location}_message_position", 'left' ),
|
||||
'logo-type' => $this->get_or_default( $settings, "pay_later_{$location}_message_logo", 'inline' ),
|
||||
'text-color' => $this->get_or_default( $settings, "pay_later_{$location}_message_color", 'black' ),
|
||||
'text-size' => $this->get_or_default( $settings, "pay_later_{$location}_message_text_size", '12' ),
|
||||
'status' => in_array( $location, $selected_locations, true ) ? 'enabled' : 'disabled',
|
||||
'placement' => $location,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -73,9 +131,9 @@ class ConfigFactory {
|
|||
* @param string $key The key.
|
||||
* @param mixed $default The default value.
|
||||
* @param array|null $allowed_values The list of allowed values, or null if all values are allowed.
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
private function get_or_default( Settings $settings, string $key, $default, ?array $allowed_values = null ) {
|
||||
private function get_or_default( Settings $settings, string $key, $default, ?array $allowed_values = null ): string {
|
||||
if ( $settings->has( $key ) ) {
|
||||
$value = $settings->get( $key );
|
||||
if ( ! $allowed_values || in_array( $value, $allowed_values, true ) ) {
|
||||
|
|
|
@ -281,7 +281,11 @@ class SavePaymentMethodsModule implements ModuleInterface {
|
|||
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
assert( $settings instanceof Settings );
|
||||
$verification_method = $settings->has( '3d_secure_contingency' ) ? $settings->get( '3d_secure_contingency' ) : '';
|
||||
|
||||
$verification_method =
|
||||
$settings->has( '3d_secure_contingency' )
|
||||
? apply_filters( 'woocommerce_paypal_payments_three_d_secure_contingency', $settings->get( '3d_secure_contingency' ) )
|
||||
: '';
|
||||
|
||||
$change_payment_method = wc_clean( wp_unslash( $_GET['change_payment_method'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
|
|
|
@ -48,12 +48,18 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
const ORDER_ID_META_KEY = '_ppcp_paypal_order_id';
|
||||
const ORDER_PAYMENT_MODE_META_KEY = '_ppcp_paypal_payment_mode';
|
||||
const ORDER_PAYMENT_SOURCE_META_KEY = '_ppcp_paypal_payment_source';
|
||||
const ORDER_PAYER_EMAIL_META_KEY = '_ppcp_paypal_payer_email';
|
||||
const FEES_META_KEY = '_ppcp_paypal_fees';
|
||||
const REFUND_FEES_META_KEY = '_ppcp_paypal_refund_fees';
|
||||
const REFUNDS_META_KEY = '_ppcp_refunds';
|
||||
const THREE_D_AUTH_RESULT_META_KEY = '_ppcp_paypal_3DS_auth_result';
|
||||
const FRAUD_RESULT_META_KEY = '_ppcp_paypal_fraud_result';
|
||||
|
||||
/**
|
||||
* List of payment sources wich we are expected to store the payer email in the WC Order metadata.
|
||||
*/
|
||||
const PAYMENT_SOURCES_WITH_PAYER_EMAIL = array( 'paypal', 'paylater', 'venmo' );
|
||||
|
||||
/**
|
||||
* The Settings Renderer.
|
||||
*
|
||||
|
|
|
@ -76,7 +76,7 @@ trait CreditCardOrderInfoHandlingTrait {
|
|||
/**
|
||||
* Fired when the 3DS information is added to WC order.
|
||||
*/
|
||||
do_action( 'woocommerce_paypal_payments_thee_d_secure_added', $wc_order, $order );
|
||||
do_action( 'woocommerce_paypal_payments_three_d_secure_added', $wc_order, $order );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,8 +96,9 @@ trait CreditCardOrderInfoHandlingTrait {
|
|||
return;
|
||||
}
|
||||
|
||||
$fraud_responses = $fraud->to_array();
|
||||
$card_brand = $payment_source->properties()->brand ?? __( 'N/A', 'woocommerce-paypal-payments' );
|
||||
$fraud_responses = $fraud->to_array();
|
||||
$card_brand = $payment_source->properties()->brand ?? __( 'N/A', 'woocommerce-paypal-payments' );
|
||||
$card_last_digits = $payment_source->properties()->last_digits ?? __( 'N/A', 'woocommerce-paypal-payments' );
|
||||
|
||||
$avs_response_order_note_title = __( 'Address Verification Result', 'woocommerce-paypal-payments' );
|
||||
/* translators: %1$s is AVS order note title, %2$s is AVS order note result markup */
|
||||
|
@ -109,6 +110,7 @@ trait CreditCardOrderInfoHandlingTrait {
|
|||
<li>%3$s</li>
|
||||
</ul>
|
||||
<li>%4$s</li>
|
||||
<li>%5$s</li>
|
||||
</ul>';
|
||||
$avs_response_order_note_result = sprintf(
|
||||
$avs_response_order_note_result_format,
|
||||
|
@ -119,7 +121,9 @@ trait CreditCardOrderInfoHandlingTrait {
|
|||
/* translators: %s is fraud AVS postal match */
|
||||
sprintf( __( 'Postal Match: %s', 'woocommerce-paypal-payments' ), esc_html( $fraud_responses['postal_match'] ) ),
|
||||
/* translators: %s is card brand */
|
||||
sprintf( __( 'Card Brand: %s', 'woocommerce-paypal-payments' ), esc_html( $card_brand ) )
|
||||
sprintf( __( 'Card Brand: %s', 'woocommerce-paypal-payments' ), esc_html( $card_brand ) ),
|
||||
/* translators: %s card last digits */
|
||||
sprintf( __( 'Card Last Digits: %s', 'woocommerce-paypal-payments' ), esc_html( $card_last_digits ) )
|
||||
);
|
||||
$avs_response_order_note = sprintf(
|
||||
$avs_response_order_note_format,
|
||||
|
|
|
@ -45,6 +45,18 @@ trait OrderMetaTrait {
|
|||
$wc_order->update_meta_data( PayPalGateway::ORDER_PAYMENT_SOURCE_META_KEY, $payment_source );
|
||||
}
|
||||
|
||||
$payer = $order->payer();
|
||||
if (
|
||||
$payer
|
||||
&& $payment_source
|
||||
&& in_array( $payment_source, PayPalGateway::PAYMENT_SOURCES_WITH_PAYER_EMAIL, true )
|
||||
) {
|
||||
$payer_email = $payer->email_address();
|
||||
if ( $payer_email ) {
|
||||
$wc_order->update_meta_data( PayPalGateway::ORDER_PAYER_EMAIL_META_KEY, $payer_email );
|
||||
}
|
||||
}
|
||||
|
||||
$wc_order->save();
|
||||
|
||||
do_action( 'woocommerce_paypal_payments_woocommerce_order_created', $wc_order, $order );
|
||||
|
|
|
@ -448,6 +448,49 @@ class WCGatewayModule implements ModuleInterface {
|
|||
delete_transient( 'ppcp_reference_transaction_enabled' );
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
add_filter(
|
||||
'woocommerce_admin_billing_fields',
|
||||
function ( $fields ) {
|
||||
global $theorder;
|
||||
|
||||
if ( ! is_array( $fields ) ) {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
if ( ! $theorder instanceof WC_Order ) {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
$email = $theorder->get_meta( PayPalGateway::ORDER_PAYER_EMAIL_META_KEY ) ?: '';
|
||||
|
||||
if ( ! $email ) {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
// Is payment source is paypal exclude all non paypal funding sources.
|
||||
$payment_source = $theorder->get_meta( PayPalGateway::ORDER_PAYMENT_SOURCE_META_KEY ) ?: '';
|
||||
$is_paypal_funding_source = ( strpos( $theorder->get_payment_method_title(), '(via PayPal)' ) === false );
|
||||
|
||||
if ( $payment_source === 'paypal' && ! $is_paypal_funding_source ) {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
$fields['paypal_email'] = array(
|
||||
'label' => __( 'PayPal email address', 'woocommerce-paypal-payments' ),
|
||||
'value' => $email,
|
||||
'wrapper_class' => 'form-field-wide',
|
||||
'custom_attributes' => array( 'disabled' => 'disabled' ),
|
||||
);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "woocommerce-paypal-payments",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.1",
|
||||
"description": "WooCommerce PayPal Payments",
|
||||
"repository": "https://github.com/woocommerce/woocommerce-paypal-payments",
|
||||
"license": "GPL-2.0",
|
||||
|
|
18
readme.txt
18
readme.txt
|
@ -2,9 +2,9 @@
|
|||
Contributors: woocommerce, automattic, inpsyde
|
||||
Tags: woocommerce, paypal, payments, ecommerce, checkout, cart, pay later, apple pay, subscriptions, debit card, credit card, google pay
|
||||
Requires at least: 5.3
|
||||
Tested up to: 6.4
|
||||
Tested up to: 6.5
|
||||
Requires PHP: 7.2
|
||||
Stable tag: 2.6.0
|
||||
Stable tag: 2.6.1
|
||||
License: GPLv2
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
|
@ -179,6 +179,20 @@ If you encounter issues with the PayPal buttons not appearing after an update, p
|
|||
|
||||
== Changelog ==
|
||||
|
||||
= 2.6.1 - xxxx-xx-xx =
|
||||
* Fix - Payment tokens fixes and adjustments #2106
|
||||
* Fix - Pay upon Invoice: Add input validation to Experience Context fields #2092
|
||||
* Fix - Disable markup in get_plugin_data() returns to fix an issue with wptexturize() #2094
|
||||
* Enhancement - Pay later messaging configurator improvements #2107
|
||||
* Enhancement - Replace the middleware URL from connect.woocommerce.com to api.woocommerce.com/integrations #2130
|
||||
* Enhancement - Remove all Sofort references as it has been deprecated #2124
|
||||
* Enhancement - Improve funding source names #2118
|
||||
* Enhancement - More fraud prevention capabilities by storing additional data in the order #2125
|
||||
* Enhancement - Update ACDC currency eligibility for AMEX #2129
|
||||
* Enhancement - Sync shipping options with Venmo when skipping final confirmation on Checkout #2108
|
||||
* Enhancement - Card Fields: Add a filter for the CVC field and update the placeholder to match the label #2089
|
||||
* Enhancement - Product Title: Sanitize before sending to PayPal #2090
|
||||
|
||||
= 2.6.0 - 2024-03-20 =
|
||||
* Fix - invoice_id not included in API call when creating payment with saved card #2086
|
||||
* Fix - Typo in SCA indicators for ACDC Vault transactions #2083
|
||||
|
|
|
@ -92,6 +92,8 @@ class VaultedCreditCardHandlerTest extends TestCase
|
|||
$customer = Mockery::mock(WC_Customer::class);
|
||||
|
||||
$payer = Mockery::mock(Payer::class);
|
||||
$payer->shouldReceive('email_address');
|
||||
|
||||
$this->payerFactory->shouldReceive('from_wc_order')
|
||||
->andReturn($payer);
|
||||
$this->shippingPreferenceFactory->shouldReceive('from_state')
|
||||
|
@ -100,6 +102,7 @@ class VaultedCreditCardHandlerTest extends TestCase
|
|||
$order = Mockery::mock(Order::class);
|
||||
$order->shouldReceive('id')->andReturn('1');
|
||||
$order->shouldReceive('intent')->andReturn('CAPTURE');
|
||||
$order->shouldReceive('payer')->andReturn($payer);
|
||||
|
||||
$paymentSource = Mockery::mock(PaymentSource::class);
|
||||
$paymentSource->shouldReceive('name')->andReturn('card');
|
||||
|
|
|
@ -89,6 +89,7 @@ private $testee;
|
|||
$order->shouldReceive('id')->andReturn('1');
|
||||
$order->shouldReceive('intent');
|
||||
$order->shouldReceive('payment_source');
|
||||
$order->shouldReceive('payer');
|
||||
|
||||
$this->orderEndpoint
|
||||
->shouldReceive('create')
|
||||
|
|
|
@ -93,6 +93,7 @@ class OrderProcessorTest extends TestCase
|
|||
$currentOrder
|
||||
->shouldReceive('payment_source')
|
||||
->andReturn(null);
|
||||
$currentOrder->shouldReceive('payer');
|
||||
|
||||
$wcOrder
|
||||
->shouldReceive('get_meta')
|
||||
|
@ -230,6 +231,7 @@ class OrderProcessorTest extends TestCase
|
|||
$currentOrder
|
||||
->shouldReceive('payment_source')
|
||||
->andReturn(null);
|
||||
$currentOrder->shouldReceive('payer');
|
||||
|
||||
$wcOrder
|
||||
->shouldReceive('get_meta')
|
||||
|
@ -357,6 +359,7 @@ class OrderProcessorTest extends TestCase
|
|||
$currentOrder
|
||||
->shouldReceive('purchase_units')
|
||||
->andReturn([$purchaseUnit]);
|
||||
$currentOrder->shouldReceive('payer');
|
||||
|
||||
$wcOrder
|
||||
->shouldReceive('get_meta')
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
* Plugin Name: WooCommerce PayPal Payments
|
||||
* Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/
|
||||
* Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage.
|
||||
* Version: 2.6.0
|
||||
* Version: 2.6.1
|
||||
* Author: WooCommerce
|
||||
* Author URI: https://woocommerce.com/
|
||||
* License: GPL-2.0
|
||||
* Requires PHP: 7.2
|
||||
* WC requires at least: 3.9
|
||||
* WC tested up to: 8.6
|
||||
* WC tested up to: 8.7
|
||||
* Text Domain: woocommerce-paypal-payments
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce
|
||||
|
@ -25,7 +25,7 @@ define( 'PAYPAL_API_URL', 'https://api-m.paypal.com' );
|
|||
define( 'PAYPAL_URL', 'https://www.paypal.com' );
|
||||
define( 'PAYPAL_SANDBOX_API_URL', 'https://api-m.sandbox.paypal.com' );
|
||||
define( 'PAYPAL_SANDBOX_URL', 'https://www.sandbox.paypal.com' );
|
||||
define( 'PAYPAL_INTEGRATION_DATE', '2024-03-12' );
|
||||
define( 'PAYPAL_INTEGRATION_DATE', '2024-04-03' );
|
||||
|
||||
! defined( 'CONNECT_WOO_CLIENT_ID' ) && define( 'CONNECT_WOO_CLIENT_ID', 'AcCAsWta_JTL__OfpjspNyH7c1GGHH332fLwonA5CwX4Y10mhybRZmHLA0GdRbwKwjQIhpDQy0pluX_P' );
|
||||
! defined( 'CONNECT_WOO_SANDBOX_CLIENT_ID' ) && define( 'CONNECT_WOO_SANDBOX_CLIENT_ID', 'AYmOHbt1VHg-OZ_oihPdzKEVbU3qg0qXonBcAztuzniQRaKE0w1Hr762cSFwd4n8wxOl-TCWohEa0XM_' );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue