mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
init hosted fields functionality
This commit is contained in:
parent
1225ad83c8
commit
23dd407fc8
21 changed files with 212 additions and 45 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,11 +1,13 @@
|
|||
import MiniCartBootstap from './modules/MiniCartBootstap';
|
||||
import SingleProductBootstap from './modules/SingleProductBootstap';
|
||||
import CartBootstrap from './modules/CartBootstap';
|
||||
import CheckoutBootstap from './modules/CheckoutBootstap';
|
||||
import Renderer from './modules/Renderer';
|
||||
import MiniCartBootstap from './modules/ContextBootstrap/MiniCartBootstap';
|
||||
import SingleProductBootstap from './modules/ContextBootstrap/SingleProductBootstap';
|
||||
import CartBootstrap from './modules/ContextBootstrap/CartBootstap';
|
||||
import CheckoutBootstap from './modules/ContextBootstrap/CheckoutBootstap';
|
||||
import Renderer from './modules/Renderer/Renderer';
|
||||
import CreditCardRenderer from "./modules/Renderer/CreditCardRenderer";
|
||||
|
||||
const bootstrap = () => {
|
||||
const renderer = new Renderer(PayPalCommerceGateway);
|
||||
const creditCardRenderer = new CreditCardRenderer(PayPalCommerceGateway);
|
||||
const renderer = new Renderer(creditCardRenderer, PayPalCommerceGateway);
|
||||
const context = PayPalCommerceGateway.context;
|
||||
|
||||
if (context === 'mini-cart' || context === 'product') {
|
||||
|
@ -55,6 +57,11 @@ document.addEventListener(
|
|||
const script = document.createElement('script');
|
||||
|
||||
script.setAttribute('src', PayPalCommerceGateway.button.url);
|
||||
Object.entries(PayPalCommerceGateway.script_attributes).forEach(
|
||||
(keyValue) => {
|
||||
script.setAttribute(keyValue[0], keyValue[1]);
|
||||
}
|
||||
);
|
||||
script.addEventListener('load', (event) => {
|
||||
bootstrap();
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import onApprove from './onApproveForContinue.js';
|
||||
import {payerData} from "./Payer";
|
||||
import onApprove from '../OnApproveHandler/onApproveForContinue.js';
|
||||
import {payerData} from "../Helper/PayerData";
|
||||
|
||||
class CartActionHandler {
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import onApprove from './onApproveForPayNow.js';
|
||||
import {payerData} from "./Payer";
|
||||
import onApprove from '../OnApproveHandler/onApproveForPayNow.js';
|
||||
import {payerData} from "../Helper/PayerData";
|
||||
|
||||
class CheckoutActionHandler {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import ButtonsToggleListener from './ButtonsToggleListener';
|
||||
import Product from './Product';
|
||||
import onApprove from './onApproveForContinue';
|
||||
import {payerData} from "./Payer";
|
||||
import ButtonsToggleListener from '../Helper/ButtonsToggleListener';
|
||||
import Product from '../Entity/Product';
|
||||
import onApprove from '../OnApproveHandler/onApproveForContinue';
|
||||
import {payerData} from "../Helper/PayerData";
|
||||
|
||||
class SingleProductActionHandler {
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import CartActionHandler from './CartActionHandler';
|
||||
import ErrorHandler from './ErrorHandler';
|
||||
import CartActionHandler from '../ActionHandler/CartActionHandler';
|
||||
import ErrorHandler from '../ErrorHandler';
|
||||
|
||||
class CartBootstrap {
|
||||
constructor(gateway, renderer) {
|
||||
|
@ -31,6 +31,7 @@ class CartBootstrap {
|
|||
|
||||
this.renderer.render(
|
||||
this.gateway.button.wrapper,
|
||||
this.gateway.hosted_fields.wrapper,
|
||||
actionHandler.configuration(),
|
||||
);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import ErrorHandler from './ErrorHandler';
|
||||
import CheckoutActionHandler from './CheckoutActionHandler';
|
||||
import ErrorHandler from '../ErrorHandler';
|
||||
import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler';
|
||||
|
||||
class CheckoutBootstap {
|
||||
constructor(gateway, renderer) {
|
||||
|
@ -22,6 +22,7 @@ class CheckoutBootstap {
|
|||
on('updated_checkout payment_method_selected', () => {
|
||||
this.switchBetweenPayPalandOrderButton();
|
||||
});
|
||||
this.switchBetweenPayPalandOrderButton();
|
||||
}
|
||||
|
||||
shouldRender() {
|
||||
|
@ -40,6 +41,7 @@ class CheckoutBootstap {
|
|||
|
||||
this.renderer.render(
|
||||
this.gateway.button.wrapper,
|
||||
this.gateway.hosted_fields.wrapper,
|
||||
actionHandler.configuration(),
|
||||
);
|
||||
}
|
||||
|
@ -50,10 +52,12 @@ class CheckoutBootstap {
|
|||
|
||||
if (currentPaymentMethod !== 'ppcp-gateway') {
|
||||
this.renderer.hideButtons(this.gateway.button.wrapper);
|
||||
this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);
|
||||
jQuery('#place_order').show();
|
||||
}
|
||||
else {
|
||||
this.renderer.showButtons(this.gateway.button.wrapper);
|
||||
this.renderer.showButtons(this.gateway.hosted_fields.wrapper);
|
||||
jQuery('#place_order').hide();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import ErrorHandler from './ErrorHandler';
|
||||
import CartActionHandler from './CartActionHandler';
|
||||
import ErrorHandler from '../ErrorHandler';
|
||||
import CartActionHandler from '../ActionHandler/CartActionHandler';
|
||||
|
||||
class MiniCartBootstap {
|
||||
constructor(gateway, renderer) {
|
||||
|
@ -32,6 +32,7 @@ class MiniCartBootstap {
|
|||
|
||||
this.renderer.render(
|
||||
this.gateway.button.mini_cart_wrapper,
|
||||
null,
|
||||
actionHandler.configuration()
|
||||
);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import ErrorHandler from './ErrorHandler';
|
||||
import UpdateCart from './UpdateCart';
|
||||
import SingleProductActionHandler from './SingleProductActionHandler';
|
||||
import ErrorHandler from '../ErrorHandler';
|
||||
import UpdateCart from "../Helper/UpdateCart";
|
||||
import SingleProductActionHandler from "../ActionHandler/SingleProductActionHandler";
|
||||
|
||||
class SingleProductBootstap {
|
||||
constructor(gateway, renderer) {
|
||||
|
@ -43,6 +43,7 @@ class SingleProductBootstap {
|
|||
|
||||
this.renderer.render(
|
||||
this.gateway.button.wrapper,
|
||||
this.gateway.hosted_fields.wrapper,
|
||||
actionHandler.configuration(),
|
||||
);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import Product from "./Product";
|
||||
import Product from "../Entity/Product";
|
||||
class UpdateCart {
|
||||
|
||||
constructor(endpoint, nonce)
|
|
@ -0,0 +1,49 @@
|
|||
class CreditCardRenderer {
|
||||
|
||||
constructor(defaultConfig) {
|
||||
this.defaultConfig = defaultConfig;
|
||||
}
|
||||
|
||||
render(wrapper, contextConfig) {
|
||||
|
||||
if (
|
||||
wrapper === null
|
||||
|| typeof paypal.HostedFields === 'undefined'
|
||||
|| ! paypal.HostedFields.isEligible()
|
||||
|| document.querySelector(wrapper) === null
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
//ToDo: Styles
|
||||
paypal.HostedFields.render({
|
||||
createOrder: contextConfig.createOrder,
|
||||
fields: {
|
||||
number: {
|
||||
selector: '#ppcp-credit-card',
|
||||
placeholder: this.defaultConfig.hosted_fields.labels.credit_card_number,
|
||||
},
|
||||
cvv: {
|
||||
selector: '#ppcp-cvv',
|
||||
placeholder: this.defaultConfig.hosted_fields.labels.cvv,
|
||||
},
|
||||
expirationDate: {
|
||||
selector: '#ppcp-expiration-date',
|
||||
placeholder: this.defaultConfig.hosted_fields.labels.mm_yyyy,
|
||||
}
|
||||
}
|
||||
}).then(hostedFields => {
|
||||
document.querySelector(wrapper).addEventListener(
|
||||
'submit',
|
||||
event => {
|
||||
event.preventDefault();
|
||||
hostedFields.submit().then(payload => {
|
||||
payload.orderID = payload.orderId;
|
||||
return contextConfig.onApprove(payload);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
export default CreditCardRenderer;
|
|
@ -1,9 +1,10 @@
|
|||
class Renderer {
|
||||
constructor(defaultConfig) {
|
||||
constructor(creditCardRenderer, defaultConfig) {
|
||||
this.defaultConfig = defaultConfig;
|
||||
this.creditCardRenderer = creditCardRenderer;
|
||||
}
|
||||
|
||||
render(wrapper, contextConfig) {
|
||||
render(wrapper, hostedFieldsWrapper, contextConfig) {
|
||||
if (this.isAlreadyRendered(wrapper)) {
|
||||
return;
|
||||
}
|
||||
|
@ -13,6 +14,8 @@ class Renderer {
|
|||
style,
|
||||
...contextConfig,
|
||||
}).render(wrapper);
|
||||
|
||||
this.creditCardRenderer.render(hostedFieldsWrapper, contextConfig);
|
||||
}
|
||||
|
||||
isAlreadyRendered(wrapper) {
|
|
@ -16,17 +16,21 @@ use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
|
|||
|
||||
return [
|
||||
'button.smart-button' => static function (ContainerInterface $container): SmartButtonInterface {
|
||||
|
||||
$settings = $container->get('wcgateway.settings');
|
||||
if (! wc_string_to_bool($settings->get('enabled'))) {
|
||||
return new DisabledSmartButton();
|
||||
}
|
||||
$payeeRepository = $container->get('api.repository.payee');
|
||||
if (wc_string_to_bool($settings->get('enabled'))) {
|
||||
$identityToken = $container->get('api.endpoint.identity-token');
|
||||
return new SmartButton(
|
||||
$container->get('button.url'),
|
||||
$container->get('session.handler'),
|
||||
$settings,
|
||||
$payeeRepository
|
||||
$payeeRepository,
|
||||
$identityToken
|
||||
);
|
||||
}
|
||||
return new DisabledSmartButton();
|
||||
|
||||
},
|
||||
'button.url' => static function (ContainerInterface $container): string {
|
||||
return plugins_url(
|
||||
|
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Inpsyde\PayPalCommerce\Button\Assets;
|
||||
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\IdentityToken;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Repository\PayeeRepository;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint;
|
||||
use Inpsyde\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
||||
|
@ -17,24 +19,39 @@ class SmartButton implements SmartButtonInterface
|
|||
private $sessionHandler;
|
||||
private $settings;
|
||||
private $payeeRepository;
|
||||
private $identityToken;
|
||||
|
||||
public function __construct(
|
||||
string $moduleUrl,
|
||||
SessionHandler $sessionHandler,
|
||||
Settings $settings,
|
||||
PayeeRepository $payeeRepository
|
||||
PayeeRepository $payeeRepository,
|
||||
IdentityToken $identityToken
|
||||
) {
|
||||
|
||||
$this->moduleUrl = $moduleUrl;
|
||||
$this->sessionHandler = $sessionHandler;
|
||||
$this->settings = $settings;
|
||||
$this->payeeRepository = $payeeRepository;
|
||||
$this->identityToken = $identityToken;
|
||||
}
|
||||
|
||||
public function renderWrapper(): bool
|
||||
{
|
||||
$renderer = static function () {
|
||||
|
||||
$hostedFieldsEnabled = $this->dccIsEnabled();
|
||||
$renderer = static function () use ($hostedFieldsEnabled) {
|
||||
echo '<div id="ppc-button"></div>';
|
||||
if (! $hostedFieldsEnabled) {
|
||||
return;
|
||||
}
|
||||
printf(
|
||||
'<form id="ppc-hosted-fields"><label for="ppcp-credit-card">%s</label><div id="ppcp-credit-card"></div><label for="ppcp-expiration-date">%s</label><div id="ppcp-expiration-date"></div><label for="ppcp-cvv">%s</label><div id="ppcp-cvv"></div><button>%s</button></form>',
|
||||
__('Card number', 'woocommerce-paypal-commerce-gateway'),
|
||||
__('Expiration Date', 'woocommerce-paypal-commerce-gateway'),
|
||||
__('CVV', 'woocommerce-paypal-commerce-gateway'),
|
||||
__('Pay with Card', 'woocommerce-paypal-commerce-gateway')
|
||||
);
|
||||
};
|
||||
if (is_cart() && wc_string_to_bool($this->settings->get('button_cart_enabled'))) {
|
||||
add_action(
|
||||
|
@ -88,6 +105,7 @@ class SmartButton implements SmartButtonInterface
|
|||
private function localizeScript(): array
|
||||
{
|
||||
$localize = [
|
||||
'script_attributes' => $this->attributes(),
|
||||
'redirect' => wc_get_checkout_url(),
|
||||
'context' => $this->context(),
|
||||
'ajax' => [
|
||||
|
@ -117,6 +135,14 @@ class SmartButton implements SmartButtonInterface
|
|||
'label' => 'paypal',
|
||||
],
|
||||
],
|
||||
'hosted_fields' => [
|
||||
'wrapper' => '#ppc-hosted-fields',
|
||||
'labels' => [
|
||||
'credit_card_number' => __('Credit Card Number', 'woocommerce-paypal-commerce-gateway'),
|
||||
'cvv' => __('CVV', 'woocommerce-paypal-commerce-gateway'),
|
||||
'mm_yyyy' => __('MM/YYYY', 'woocommerce-paypal-commerce-gateway'),
|
||||
],
|
||||
],
|
||||
];
|
||||
return $localize;
|
||||
}
|
||||
|
@ -155,18 +181,21 @@ class SmartButton implements SmartButtonInterface
|
|||
{
|
||||
$params = [
|
||||
//ToDo: Add the correct client id, toggle when settings is set to sandbox
|
||||
'client-id' => 'AcVzowpNCpTxFzLG7onQI4JD0sVcA0BkZv-D42qRZPv_gZ8cNfX9zGL_8bXmSu7cbJ5B2DH7sot8vDpw',
|
||||
'client-id' => 'AQB97CzMsd58-It1vxbcDAGvMuXNCXRD9le_XUaMlHB_U7XsU9IiItBwGQOtZv9sEeD6xs2vlIrL4NiD',
|
||||
'currency' => get_woocommerce_currency(),
|
||||
'locale' => get_user_locale(),
|
||||
//'debug' => (defined('WP_DEBUG') && WP_DEBUG) ? 'true' : 'false',
|
||||
//ToDo: Update date on releases.
|
||||
'integration-date' => date('Y-m-d'),
|
||||
'components' => 'marks,buttons',
|
||||
'components' => implode(',', $this->components()),
|
||||
//ToDo: Probably only needed, when DCC
|
||||
'vault' => 'false',
|
||||
'vault' => $this->dccIsEnabled() ? 'false' : 'false',
|
||||
'commit' => is_checkout() ? 'true' : 'false',
|
||||
'intent' => $this->settings->get('intent'),
|
||||
];
|
||||
if (defined('WP_DEBUG') && \WP_DEBUG && WC()->customer) {
|
||||
$params['buyer-country'] = WC()->customer->get_billing_country();
|
||||
}
|
||||
$payee = $this->payeeRepository->payee();
|
||||
if ($payee->merchantId()) {
|
||||
$params['merchant-id'] = $payee->merchantId();
|
||||
|
@ -179,6 +208,28 @@ class SmartButton implements SmartButtonInterface
|
|||
return $smartButtonUrl;
|
||||
}
|
||||
|
||||
private function attributes() : array {
|
||||
$attributes = [
|
||||
//'data-partner-attribution-id' => '',
|
||||
];
|
||||
try {
|
||||
$clientToken = $this->identityToken->generate();
|
||||
$attributes['data-client-token'] = $clientToken->token();
|
||||
return $attributes;
|
||||
} catch (RuntimeException $exception) {
|
||||
return $attributes;
|
||||
}
|
||||
}
|
||||
|
||||
private function components() : array
|
||||
{
|
||||
$components = ['buttons'];
|
||||
if ($this->dccIsEnabled()) {
|
||||
$components[] = 'hosted-fields';
|
||||
}
|
||||
return $components;
|
||||
}
|
||||
|
||||
private function context(): string
|
||||
{
|
||||
$context = 'mini-cart';
|
||||
|
@ -193,4 +244,9 @@ class SmartButton implements SmartButtonInterface
|
|||
}
|
||||
return $context;
|
||||
}
|
||||
|
||||
private function dccIsEnabled() : bool
|
||||
{
|
||||
return wc_string_to_bool($this->settings->get('enable_dcc'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,11 @@ class SettingsFields
|
|||
$this->gateway(),
|
||||
$this->account(),
|
||||
$this->buttons(),
|
||||
$this->creditCards(),
|
||||
);
|
||||
}
|
||||
|
||||
protected function gateway(): array
|
||||
private function gateway(): array
|
||||
{
|
||||
return [
|
||||
'enabled' => [
|
||||
|
@ -91,7 +92,7 @@ class SettingsFields
|
|||
{
|
||||
return [
|
||||
'button_settings' => [
|
||||
'title' => __('Button Settings', 'woocommerce-paypal-gateway'),
|
||||
'title' => __('SmartButton Settings', 'woocommerce-paypal-gateway'),
|
||||
'type' => 'title',
|
||||
'description' => __(
|
||||
'Customize the appearance of PayPal Payments on your site.',
|
||||
|
@ -174,4 +175,44 @@ class SettingsFields
|
|||
],
|
||||
];
|
||||
}
|
||||
|
||||
private function creditCards() : array {
|
||||
return [
|
||||
|
||||
'credit_card_settings' => [
|
||||
'title' => __('Credit Card Settings', 'woocommerce-paypal-gateway'),
|
||||
'type' => 'title',
|
||||
'description' => __(
|
||||
'Customize the appearance of Credit Card Payments on your site.',
|
||||
'woocommerce-paypal-gateway'
|
||||
),
|
||||
],
|
||||
'enable_dcc' => [
|
||||
'title' => __('Enable credit card payment', 'woocommerce-paypal-gateway'),
|
||||
'type' => 'checkbox',
|
||||
'label' => __('Enable credit card payments.', 'woocommerce-paypal-gateway'),
|
||||
'default' => 'yes',
|
||||
],
|
||||
'disable_cards' => [
|
||||
'title' => __('Disable specific credid cards', 'woocommerce-paypal-gateway'),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => [],
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'By default all possible credit cards will be shown. You can disable some cards, if you wish.',
|
||||
'woocommerce-paypal-gateway'
|
||||
),
|
||||
'options' => [
|
||||
'visa' => _x('Visa', 'Name of credit card', 'woocommerce-paypal-gateway'),
|
||||
'mastercard' => _x('Mastercard', 'Name of credit card', 'woocommerce-paypal-gateway'),
|
||||
'amex' => _x('American Express', 'Name of credit card', 'woocommerce-paypal-gateway'),
|
||||
'discover' => _x('Discover', 'Name of credit card', 'woocommerce-paypal-gateway'),
|
||||
'jcb' => _x('JCB', 'Name of credit card', 'woocommerce-paypal-gateway'),
|
||||
'elo' => _x('Elo', 'Name of credit card', 'woocommerce-paypal-gateway'),
|
||||
'hiper' => _x('Hiper', 'Name of credit card', 'woocommerce-paypal-gateway'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue