mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2026-07-29 02:07:27 +08:00
146 lines
7.6 KiB
PHP
146 lines
7.6 KiB
PHP
<?php
|
|
|
|
/**
|
|
* The Card Fields module.
|
|
*
|
|
* @package WooCommerce\PayPalCommerce\CardFields
|
|
*/
|
|
declare (strict_types=1);
|
|
namespace WooCommerce\PayPalCommerce\CardFields;
|
|
|
|
use DomainException;
|
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Log\LoggerInterface;
|
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\ExperienceContextBuilder;
|
|
use WooCommerce\PayPalCommerce\CardFields\Service\CardCaptureValidator;
|
|
use WooCommerce\PayPalCommerce\Settings\Data\SettingsProvider;
|
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule;
|
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
|
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
|
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\CardPaymentsConfiguration;
|
|
/**
|
|
* Class CardFieldsModule
|
|
*/
|
|
class CardFieldsModule implements ServiceModule, ExecutableModule
|
|
{
|
|
use ModuleClassNameIdTrait;
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function services(): array
|
|
{
|
|
return require __DIR__ . '/../services.php';
|
|
}
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function run(ContainerInterface $c): bool
|
|
{
|
|
add_action('init', function () use ($c): void {
|
|
$eligibility_check = $c->get('card-fields.eligibility.check');
|
|
if (!$eligibility_check()) {
|
|
return;
|
|
}
|
|
$this->register_hooks($c);
|
|
});
|
|
return \true;
|
|
}
|
|
/**
|
|
* Registers all hooks that require card-fields eligibility.
|
|
*
|
|
* @param ContainerInterface $c The DI container.
|
|
*/
|
|
private function register_hooks(ContainerInterface $c): void
|
|
{
|
|
add_filter('woocommerce_paypal_payments_sdk_components_hook', static function (array $components) use ($c) {
|
|
$dcc_config = $c->get('wcgateway.configuration.card-configuration');
|
|
assert($dcc_config instanceof CardPaymentsConfiguration);
|
|
if (!$dcc_config->is_acdc_enabled()) {
|
|
return $components;
|
|
}
|
|
// Enable the new "card-fields" component.
|
|
$components[] = 'card-fields';
|
|
// Ensure the older "hosted-fields" component is not loaded.
|
|
return array_filter($components, static fn(string $component) => $component !== 'hosted-fields');
|
|
});
|
|
add_filter(
|
|
'woocommerce_credit_card_form_fields',
|
|
/**
|
|
* Return/Param types removed to avoid third-party issues.
|
|
*
|
|
* @psalm-suppress MissingClosureReturnType
|
|
* @psalm-suppress MissingClosureParamType
|
|
*/
|
|
function ($default_fields, $id) use ($c) {
|
|
if (!$c->get('wcgateway.configuration.card-configuration')->is_enabled()) {
|
|
return $default_fields;
|
|
}
|
|
$card_payments_configuration = $c->get('wcgateway.configuration.card-configuration');
|
|
assert($card_payments_configuration instanceof CardPaymentsConfiguration);
|
|
$should_show_card_holder_name = apply_filters('woocommerce_paypal_payments_enable_cardholder_name_field', $card_payments_configuration->show_name_on_card() === 'yes');
|
|
if (CreditCardGateway::ID === $id && $should_show_card_holder_name) {
|
|
$default_fields['card-name-field'] = '<p class="form-row form-row-wide">
|
|
<label for="ppcp-credit-card-gateway-card-name">' . esc_attr__('Cardholder Name', 'woocommerce-paypal-payments') . '</label>
|
|
<input id="ppcp-credit-card-gateway-card-name" class="input-text wc-credit-card-form-card-expiry" type="text" placeholder="' . esc_attr__('Cardholder Name (optional)', 'woocommerce-paypal-payments') . '" name="ppcp-credit-card-gateway-card-name">
|
|
</p>';
|
|
// Moves new item to first position.
|
|
$new_field = $default_fields['card-name-field'];
|
|
unset($default_fields['card-name-field']);
|
|
array_unshift($default_fields, $new_field);
|
|
}
|
|
if (apply_filters('woocommerce_paypal_payments_card_fields_translate_card_number', \true)) {
|
|
if (isset($default_fields['card-number-field'])) {
|
|
// Replaces the default card number placeholder with a translatable one.
|
|
$default_fields['card-number-field'] = str_replace('•••• •••• •••• ••••', esc_attr__('Card number', 'woocommerce-paypal-payments'), $default_fields['card-number-field']);
|
|
}
|
|
}
|
|
return $default_fields;
|
|
},
|
|
10,
|
|
2
|
|
);
|
|
add_filter('ppcp_create_order_request_body_data', function (array $data, string $payment_method) use ($c): array {
|
|
if (!$c->get('wcgateway.configuration.card-configuration')->is_enabled()) {
|
|
return $data;
|
|
}
|
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
|
if ($payment_method !== CreditCardGateway::ID) {
|
|
return $data;
|
|
}
|
|
$settings = $c->get('settings.settings-provider');
|
|
assert($settings instanceof SettingsProvider);
|
|
$experience_context_builder = $c->get('wcgateway.builder.experience-context');
|
|
assert($experience_context_builder instanceof ExperienceContextBuilder);
|
|
$payment_source_data = array('experience_context' => $experience_context_builder->with_endpoint_return_urls()->build()->to_array());
|
|
$three_d_secure_contingency = $settings->three_d_secure_enum() ? apply_filters('woocommerce_paypal_payments_three_d_secure_contingency', $settings->three_d_secure_enum()) : '';
|
|
if ($three_d_secure_contingency === 'SCA_ALWAYS' || $three_d_secure_contingency === 'SCA_WHEN_REQUIRED') {
|
|
$payment_source_data['attributes'] = array('verification' => array('method' => $three_d_secure_contingency));
|
|
}
|
|
$data['payment_source'] = array('card' => $payment_source_data);
|
|
return $data;
|
|
}, 10, 2);
|
|
// Validates if an order with card payment source can be captured.
|
|
add_action('woocommerce_paypal_payments_before_capture_order', function (Order $order) use ($c) {
|
|
$validator = $c->get('card-fields.service.card-capture-validator');
|
|
assert($validator instanceof CardCaptureValidator);
|
|
if (!$validator->is_valid($order)) {
|
|
$logger = $c->get('woocommerce.logger.woocommerce');
|
|
assert($logger instanceof LoggerInterface);
|
|
$logger->warning("Could not capture order {$order->id()}");
|
|
// Only set session flag if WC session exists (not in API/agentic context).
|
|
/**
|
|
* Fires to add a delete order flag in WC session.
|
|
*/
|
|
if (apply_filters('woocommerce_paypal_payments_force_delete_wc_order_on_failed_capture', \true) && function_exists('WC') && WC()->session instanceof \WC_Session) {
|
|
/**
|
|
* Add delete order flag in WC session to force delete on process payment failure handler.
|
|
*/
|
|
WC()->session->set('ppcp_delete_wc_order_on_payment_failure', \true);
|
|
}
|
|
throw new DomainException(esc_html__('Could not capture the PayPal order.', 'woocommerce-paypal-payments'));
|
|
}
|
|
});
|
|
}
|
|
}
|