mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 10:55:00 +08:00
Merge branch 'trunk'
# Conflicts: # modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue.js
This commit is contained in:
commit
010f5fbdf1
101 changed files with 10063 additions and 2015 deletions
|
@ -1,7 +1,11 @@
|
||||||
{
|
{
|
||||||
"extends": [ "plugin:@wordpress/eslint-plugin/recommended" ],
|
"extends": [ "plugin:@wordpress/eslint-plugin/recommended" ],
|
||||||
|
"env": {
|
||||||
|
"browser": true
|
||||||
|
},
|
||||||
"globals": {
|
"globals": {
|
||||||
"wc": true
|
"wc": true,
|
||||||
|
"jQuery": "readonly"
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-console": ["error", { "allow": ["warn", "error"] }]
|
"no-console": ["error", { "allow": ["warn", "error"] }]
|
||||||
|
|
20
.psalm/wc-bookings.php
Normal file
20
.psalm/wc-bookings.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and create a new booking manually.
|
||||||
|
*
|
||||||
|
* @version 1.10.7
|
||||||
|
* @see WC_Booking::new_booking() for available $new_booking_data args
|
||||||
|
* @param int $product_id you are booking
|
||||||
|
* @param array $new_booking_data
|
||||||
|
* @param string $status
|
||||||
|
* @param bool $exact If false, the function will look for the next available block after your start date if the date is unavailable.
|
||||||
|
* @return mixed WC_Booking object on success or false on fail
|
||||||
|
*/
|
||||||
|
function create_wc_booking( $product_id, $new_booking_data = array(), $status = 'confirmed', $exact = false ) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the product is a booking product, false if not
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function is_wc_booking_product( $product ) {}
|
|
@ -88,5 +88,12 @@ return function ( string $root_dir ): iterable {
|
||||||
$modules[] = ( require "$modules_dir/ppcp-axo/module.php" )();
|
$modules[] = ( require "$modules_dir/ppcp-axo/module.php" )();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( apply_filters(
|
||||||
|
'woocommerce.feature-flags.woocommerce_paypal_payments.local_apms_enabled',
|
||||||
|
getenv( 'PCP_LOCAL_APMS_ENABLED' ) === '1'
|
||||||
|
) ) {
|
||||||
|
$modules[] = ( require "$modules_dir/ppcp-local-alternative-payment-methods/module.php" )();
|
||||||
|
}
|
||||||
|
|
||||||
return $modules;
|
return $modules;
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\ClientCredentials;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\ClientCredentials;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\SdkClientToken;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\SdkClientToken;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult;
|
||||||
|
@ -240,6 +241,13 @@ return array(
|
||||||
$bn_code
|
$bn_code
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
'api.endpoint.orders' => static function ( ContainerInterface $container ): Orders {
|
||||||
|
return new Orders(
|
||||||
|
$container->get( 'api.host' ),
|
||||||
|
$container->get( 'api.bearer' ),
|
||||||
|
$container->get( 'woocommerce.logger.woocommerce' )
|
||||||
|
);
|
||||||
|
},
|
||||||
'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint {
|
'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint {
|
||||||
return new BillingAgreementsEndpoint(
|
return new BillingAgreementsEndpoint(
|
||||||
$container->get( 'api.host' ),
|
$container->get( 'api.host' ),
|
||||||
|
@ -1444,7 +1452,6 @@ return array(
|
||||||
'CN' => array(
|
'CN' => array(
|
||||||
'mastercard' => array(),
|
'mastercard' => array(),
|
||||||
'visa' => array(),
|
'visa' => array(),
|
||||||
'amex' => array(),
|
|
||||||
),
|
),
|
||||||
'CY' => array(
|
'CY' => array(
|
||||||
'mastercard' => array(),
|
'mastercard' => array(),
|
||||||
|
|
108
modules/ppcp-api-client/src/Endpoint/Orders.php
Normal file
108
modules/ppcp-api-client/src/Endpoint/Orders.php
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orders API endpoints.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
|
||||||
|
* @link https://developer.paypal.com/docs/api/orders/v2/ Orders API documentation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||||
|
use WP_Error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Orders
|
||||||
|
*/
|
||||||
|
class Orders {
|
||||||
|
|
||||||
|
use RequestTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The host.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bearer.
|
||||||
|
*
|
||||||
|
* @var Bearer
|
||||||
|
*/
|
||||||
|
private $bearer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Orders constructor.
|
||||||
|
*
|
||||||
|
* @param string $host The host.
|
||||||
|
* @param Bearer $bearer The bearer.
|
||||||
|
* @param LoggerInterface $logger The logger.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $host,
|
||||||
|
Bearer $bearer,
|
||||||
|
LoggerInterface $logger
|
||||||
|
) {
|
||||||
|
$this->host = $host;
|
||||||
|
$this->bearer = $bearer;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PayPal order.
|
||||||
|
*
|
||||||
|
* @param array $request_body The request body.
|
||||||
|
* @param array $headers The request headers.
|
||||||
|
* @return array
|
||||||
|
* @throws RuntimeException If something went wrong with the request.
|
||||||
|
* @throws PayPalApiException If something went wrong with the PayPal API request.
|
||||||
|
*/
|
||||||
|
public function create( array $request_body, array $headers = array() ): array {
|
||||||
|
$bearer = $this->bearer->bearer();
|
||||||
|
$url = trailingslashit( $this->host ) . 'v2/checkout/orders';
|
||||||
|
|
||||||
|
$default_headers = array(
|
||||||
|
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
|
||||||
|
);
|
||||||
|
$headers = array_merge(
|
||||||
|
$default_headers,
|
||||||
|
$headers
|
||||||
|
);
|
||||||
|
|
||||||
|
$args = array(
|
||||||
|
'method' => 'POST',
|
||||||
|
'headers' => $headers,
|
||||||
|
'body' => wp_json_encode( $request_body ),
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = $this->request( $url, $args );
|
||||||
|
if ( $response instanceof WP_Error ) {
|
||||||
|
throw new RuntimeException( $response->get_error_message() );
|
||||||
|
}
|
||||||
|
|
||||||
|
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||||
|
if ( $status_code !== 200 ) {
|
||||||
|
throw new PayPalApiException(
|
||||||
|
json_decode( $response['body'] ),
|
||||||
|
$status_code
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -269,7 +269,7 @@ return array(
|
||||||
'classes' => array( 'ppcp-field-indent' ),
|
'classes' => array( 'ppcp-field-indent' ),
|
||||||
'class' => array(),
|
'class' => array(),
|
||||||
'input_class' => array( 'wc-enhanced-select' ),
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
'default' => 'pay',
|
'default' => 'plain',
|
||||||
'options' => PropertiesDictionary::button_types(),
|
'options' => PropertiesDictionary::button_types(),
|
||||||
'screens' => array( State::STATE_ONBOARDED ),
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
'gateway' => 'dcc',
|
'gateway' => 'dcc',
|
||||||
|
|
|
@ -52,3 +52,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ppc-button-ppcp-applepay {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/* global ApplePaySession */
|
||||||
|
/* global PayPalCommerceGateway */
|
||||||
|
|
||||||
import ContextHandlerFactory from './Context/ContextHandlerFactory';
|
import ContextHandlerFactory from './Context/ContextHandlerFactory';
|
||||||
import { createAppleErrors } from './Helper/applePayError';
|
import { createAppleErrors } from './Helper/applePayError';
|
||||||
import { setVisible } from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
import { setVisible } from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
||||||
|
@ -7,18 +10,95 @@ import ErrorHandler from '../../../ppcp-button/resources/js/modules/ErrorHandler
|
||||||
import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder';
|
import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder';
|
||||||
import { apmButtonsInit } from '../../../ppcp-button/resources/js/modules/Helper/ApmButtons';
|
import { apmButtonsInit } from '../../../ppcp-button/resources/js/modules/Helper/ApmButtons';
|
||||||
|
|
||||||
class ApplepayButton {
|
/**
|
||||||
constructor( context, externalHandler, buttonConfig, ppcpConfig ) {
|
* Plugin-specific styling.
|
||||||
apmButtonsInit( ppcpConfig );
|
*
|
||||||
|
* Note that most properties of this object do not apply to the Apple Pay button.
|
||||||
|
*
|
||||||
|
* @typedef {Object} PPCPStyle
|
||||||
|
* @property {string} shape - Outline shape.
|
||||||
|
* @property {?number} height - Button height in pixel.
|
||||||
|
*/
|
||||||
|
|
||||||
this.isInitialized = false;
|
/**
|
||||||
|
* Style options that are defined by the Apple Pay SDK and are required to render the button.
|
||||||
|
*
|
||||||
|
* @typedef {Object} ApplePayStyle
|
||||||
|
* @property {string} type - Defines the button label.
|
||||||
|
* @property {string} color - Button color
|
||||||
|
* @property {string} lang - The locale; an empty string will apply the user-agent's language.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of valid context values that the button can have.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
const CONTEXT = {
|
||||||
|
Product: 'product',
|
||||||
|
Cart: 'cart',
|
||||||
|
Checkout: 'checkout',
|
||||||
|
PayNow: 'pay-now',
|
||||||
|
MiniCart: 'mini-cart',
|
||||||
|
BlockCart: 'cart-block',
|
||||||
|
BlockCheckout: 'checkout-block',
|
||||||
|
Preview: 'preview',
|
||||||
|
|
||||||
|
// Block editor contexts.
|
||||||
|
Blocks: [ 'cart-block', 'checkout-block' ],
|
||||||
|
|
||||||
|
// Custom gateway contexts.
|
||||||
|
Gateways: [ 'checkout', 'pay-now' ],
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A payment button for Apple Pay.
|
||||||
|
*
|
||||||
|
* On a single page, multiple Apple Pay buttons can be displayed, which also means multiple
|
||||||
|
* ApplePayButton instances exist. A typical case is on the product page, where one Apple Pay button
|
||||||
|
* is located inside the minicart-popup, and another pay-now button is in the product context.
|
||||||
|
*/
|
||||||
|
class ApplePayButton {
|
||||||
|
/**
|
||||||
|
* Whether the payment button is initialized.
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
#isInitialized = false;
|
||||||
|
|
||||||
|
#wrapperId = '';
|
||||||
|
#ppcpButtonWrapperId = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context describes the button's location on the website and what details it submits.
|
||||||
|
*
|
||||||
|
* @type {''|'product'|'cart'|'checkout'|'pay-now'|'mini-cart'|'cart-block'|'checkout-block'|'preview'}
|
||||||
|
*/
|
||||||
|
context = '';
|
||||||
|
|
||||||
|
externalHandler = null;
|
||||||
|
buttonConfig = null;
|
||||||
|
ppcpConfig = null;
|
||||||
|
paymentsClient = null;
|
||||||
|
formData = null;
|
||||||
|
contextHandler = null;
|
||||||
|
updatedContactInfo = [];
|
||||||
|
selectedShippingMethod = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores initialization data sent to the button.
|
||||||
|
*/
|
||||||
|
initialPaymentRequest = null;
|
||||||
|
|
||||||
|
constructor( context, externalHandler, buttonConfig, ppcpConfig ) {
|
||||||
|
this._initDebug( !! buttonConfig?.is_debug );
|
||||||
|
|
||||||
|
apmButtonsInit( ppcpConfig );
|
||||||
|
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.externalHandler = externalHandler;
|
this.externalHandler = externalHandler;
|
||||||
this.buttonConfig = buttonConfig;
|
this.buttonConfig = buttonConfig;
|
||||||
this.ppcpConfig = ppcpConfig;
|
this.ppcpConfig = ppcpConfig;
|
||||||
this.paymentsClient = null;
|
|
||||||
this.formData = null;
|
|
||||||
|
|
||||||
this.contextHandler = ContextHandlerFactory.create(
|
this.contextHandler = ContextHandlerFactory.create(
|
||||||
this.context,
|
this.context,
|
||||||
|
@ -26,36 +106,226 @@ class ApplepayButton {
|
||||||
this.ppcpConfig
|
this.ppcpConfig
|
||||||
);
|
);
|
||||||
|
|
||||||
this.updatedContactInfo = [];
|
|
||||||
this.selectedShippingMethod = [];
|
|
||||||
this.nonce =
|
|
||||||
document.getElementById( 'woocommerce-process-checkout-nonce' )
|
|
||||||
?.value || buttonConfig.nonce;
|
|
||||||
|
|
||||||
// Stores initialization data sent to the button.
|
|
||||||
this.initialPaymentRequest = null;
|
|
||||||
|
|
||||||
// Default eligibility status.
|
|
||||||
this.isEligible = true;
|
|
||||||
|
|
||||||
this.log = function () {
|
|
||||||
if ( this.buttonConfig.is_debug ) {
|
|
||||||
//console.log('[ApplePayButton]', ...arguments);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.refreshContextData();
|
this.refreshContextData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOOP log function to avoid errors when debugging is disabled.
|
||||||
|
*/
|
||||||
|
log() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables debugging tools, when the button's is_debug flag is set.
|
||||||
|
*
|
||||||
|
* @param {boolean} enableDebugging If debugging features should be enabled for this instance.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_initDebug( enableDebugging ) {
|
||||||
|
if ( ! enableDebugging || this.#isInitialized ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Debug helpers
|
|
||||||
jQuery( document ).on( 'ppcp-applepay-debug', () => {
|
|
||||||
console.log( 'ApplePayButton', this.context, this );
|
|
||||||
} );
|
|
||||||
document.ppcpApplepayButtons = document.ppcpApplepayButtons || {};
|
document.ppcpApplepayButtons = document.ppcpApplepayButtons || {};
|
||||||
document.ppcpApplepayButtons[ this.context ] = this;
|
document.ppcpApplepayButtons[ this.context ] = this;
|
||||||
|
|
||||||
|
this.log = ( ...args ) => {
|
||||||
|
console.log( `[ApplePayButton | ${ this.context }]`, ...args );
|
||||||
|
};
|
||||||
|
|
||||||
|
jQuery( document ).on( 'ppcp-applepay-debug', () => {
|
||||||
|
this.log( this );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The nonce for ajax requests.
|
||||||
|
*
|
||||||
|
* @return {string} The nonce value
|
||||||
|
*/
|
||||||
|
get nonce() {
|
||||||
|
const input = document.getElementById(
|
||||||
|
'woocommerce-process-checkout-nonce'
|
||||||
|
);
|
||||||
|
|
||||||
|
return input?.value || this.buttonConfig.nonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the current page qualifies to use the Apple Pay button.
|
||||||
|
*
|
||||||
|
* In admin, the button is always eligible, to display an accurate preview.
|
||||||
|
* On front-end, PayPal's response decides if customers can use Apple Pay.
|
||||||
|
*
|
||||||
|
* @return {boolean} True, if the button can be displayed.
|
||||||
|
*/
|
||||||
|
get isEligible() {
|
||||||
|
if ( ! this.#isInitialized ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( CONTEXT.Preview === this.context ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the ApplePaySession is available and accepts payments
|
||||||
|
* This check is required when using Apple Pay SDK v1; canMakePayments() returns false
|
||||||
|
* if the current device is not liked to iCloud or the Apple Wallet is not available
|
||||||
|
* for a different reason.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
if ( ! window.ApplePaySession?.canMakePayments() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch ( error ) {
|
||||||
|
console.warn( error );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !! this.applePayConfig.isEligible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the current payment button should be rendered as a stand-alone gateway.
|
||||||
|
* The return value `false` usually means, that the payment button is bundled with all available
|
||||||
|
* payment buttons.
|
||||||
|
*
|
||||||
|
* The decision depends on the button context (placement) and the plugin settings.
|
||||||
|
*
|
||||||
|
* @return {boolean} True, if the current button represents a stand-alone gateway.
|
||||||
|
*/
|
||||||
|
get isSeparateGateway() {
|
||||||
|
return (
|
||||||
|
this.buttonConfig.is_wc_gateway_enabled &&
|
||||||
|
CONTEXT.Gateways.includes( this.context )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the wrapper ID for the current button context.
|
||||||
|
* The ID varies for the MiniCart context.
|
||||||
|
*
|
||||||
|
* @return {string} The wrapper-element's ID (without the `#` prefix).
|
||||||
|
*/
|
||||||
|
get wrapperId() {
|
||||||
|
if ( ! this.#wrapperId ) {
|
||||||
|
let id;
|
||||||
|
|
||||||
|
if ( CONTEXT.MiniCart === this.context ) {
|
||||||
|
id = this.buttonConfig.button.mini_cart_wrapper;
|
||||||
|
} else if ( this.isSeparateGateway ) {
|
||||||
|
id = 'ppc-button-ppcp-applepay';
|
||||||
|
} else {
|
||||||
|
id = this.buttonConfig.button.wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#wrapperId = id.replace( /^#/, '' );
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.#wrapperId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the wrapper ID for the ppcpButton
|
||||||
|
*
|
||||||
|
* @return {string} The wrapper-element's ID (without the `#` prefix).
|
||||||
|
*/
|
||||||
|
get ppcpButtonWrapperId() {
|
||||||
|
if ( ! this.#ppcpButtonWrapperId ) {
|
||||||
|
let id;
|
||||||
|
|
||||||
|
if ( CONTEXT.MiniCart === this.context ) {
|
||||||
|
id = this.ppcpConfig.button.mini_cart_wrapper;
|
||||||
|
} else if ( CONTEXT.Blocks.includes( this.context ) ) {
|
||||||
|
id = '#express-payment-method-ppcp-gateway-paypal';
|
||||||
|
} else {
|
||||||
|
id = this.ppcpConfig.button.wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#ppcpButtonWrapperId = id.replace( /^#/, '' );
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.#ppcpButtonWrapperId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the context-relevant PPCP style object.
|
||||||
|
* The style for the MiniCart context can be different.
|
||||||
|
*
|
||||||
|
* The PPCP style are custom style options, that are provided by this plugin.
|
||||||
|
*
|
||||||
|
* @return {PPCPStyle} The style object.
|
||||||
|
*/
|
||||||
|
get ppcpStyle() {
|
||||||
|
if ( CONTEXT.MiniCart === this.context ) {
|
||||||
|
return this.ppcpConfig.button.mini_cart_style;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.ppcpConfig.button.style;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns default style options that are propagated to and rendered by the Apple Pay button.
|
||||||
|
*
|
||||||
|
* These styles are the official style options provided by the Apple Pay SDK.
|
||||||
|
*
|
||||||
|
* @return {ApplePayStyle} The style object.
|
||||||
|
*/
|
||||||
|
get buttonStyle() {
|
||||||
|
return {
|
||||||
|
type: this.buttonConfig.button.type,
|
||||||
|
lang: this.buttonConfig.button.lang,
|
||||||
|
color: this.buttonConfig.button.color,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the HTML element that wraps the current button
|
||||||
|
*
|
||||||
|
* @return {HTMLElement|null} The wrapper element, or null.
|
||||||
|
*/
|
||||||
|
get wrapperElement() {
|
||||||
|
return document.getElementById( this.wrapperId );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of HTMLElements that belong to the payment button.
|
||||||
|
*
|
||||||
|
* @return {HTMLElement[]} List of payment button wrapper elements.
|
||||||
|
*/
|
||||||
|
get allElements() {
|
||||||
|
const selectors = [];
|
||||||
|
|
||||||
|
// Payment button (Pay now, smart button block)
|
||||||
|
selectors.push( `#${ this.wrapperId }` );
|
||||||
|
|
||||||
|
// Block Checkout: Express checkout button.
|
||||||
|
if ( CONTEXT.Blocks.includes( this.context ) ) {
|
||||||
|
selectors.push( '#express-payment-method-ppcp-applepay' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classic Checkout: Apple Pay gateway.
|
||||||
|
if ( CONTEXT.Gateways.includes( this.context ) ) {
|
||||||
|
selectors.push( '.wc_payment_method.payment_method_ppcp-applepay' );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log( 'Wrapper Elements:', selectors );
|
||||||
|
return /** @type {HTMLElement[]} */ selectors.flatMap( ( selector ) =>
|
||||||
|
Array.from( document.querySelectorAll( selector ) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the main button-wrapper is present in the current DOM.
|
||||||
|
*
|
||||||
|
* @return {boolean} True, if the button context (wrapper element) is found.
|
||||||
|
*/
|
||||||
|
get isPresent() {
|
||||||
|
return this.wrapperElement instanceof HTMLElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
init( config ) {
|
init( config ) {
|
||||||
if ( this.isInitialized ) {
|
if ( this.#isInitialized ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,41 +333,35 @@ class ApplepayButton {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log( 'Init', this.context );
|
this.log( 'Init' );
|
||||||
this.initEventHandlers();
|
this.initEventHandlers();
|
||||||
this.isInitialized = true;
|
|
||||||
|
this.#isInitialized = true;
|
||||||
this.applePayConfig = config;
|
this.applePayConfig = config;
|
||||||
this.isEligible =
|
|
||||||
( this.applePayConfig.isEligible && window.ApplePaySession ) ||
|
|
||||||
this.buttonConfig.is_admin;
|
|
||||||
|
|
||||||
if ( this.isEligible ) {
|
if ( ! this.isEligible ) {
|
||||||
this.fetchTransactionInfo().then( () => {
|
this.hide();
|
||||||
this.addButton();
|
|
||||||
const id_minicart =
|
|
||||||
'#apple-' + this.buttonConfig.button.mini_cart_wrapper;
|
|
||||||
const id = '#apple-' + this.buttonConfig.button.wrapper;
|
|
||||||
|
|
||||||
if ( this.context === 'mini-cart' ) {
|
|
||||||
document
|
|
||||||
.querySelector( id_minicart )
|
|
||||||
?.addEventListener( 'click', ( evt ) => {
|
|
||||||
evt.preventDefault();
|
|
||||||
this.onButtonClick();
|
|
||||||
} );
|
|
||||||
} else {
|
} else {
|
||||||
document
|
// Bail if the button wrapper is not present; handles mini-cart logic on checkout page.
|
||||||
.querySelector( id )
|
if ( ! this.isPresent ) {
|
||||||
?.addEventListener( 'click', ( evt ) => {
|
this.log( 'Abort init (no wrapper found)' );
|
||||||
evt.preventDefault();
|
return;
|
||||||
this.onButtonClick();
|
|
||||||
} );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.show();
|
||||||
|
|
||||||
|
this.fetchTransactionInfo().then( () => {
|
||||||
|
const button = this.addButton();
|
||||||
|
|
||||||
|
if ( ! button ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.addEventListener( 'click', ( evt ) => {
|
||||||
|
evt.preventDefault();
|
||||||
|
this.onButtonClick();
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
} else {
|
|
||||||
jQuery( '#' + this.buttonConfig.button.wrapper ).hide();
|
|
||||||
jQuery( '#' + this.buttonConfig.button.mini_cart_wrapper ).hide();
|
|
||||||
jQuery( '#express-payment-method-ppcp-applepay' ).hide();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,49 +370,51 @@ class ApplepayButton {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isInitialized = false;
|
this.#isInitialized = false;
|
||||||
this.init( this.applePayConfig );
|
this.init( this.applePayConfig );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides all wrappers that belong to this ApplePayButton instance.
|
||||||
|
*/
|
||||||
|
hide() {
|
||||||
|
this.log( 'Hide button' );
|
||||||
|
this.allElements.forEach( ( element ) => {
|
||||||
|
element.style.display = 'none';
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures all wrapper elements of this ApplePayButton instance are visible.
|
||||||
|
*/
|
||||||
|
show() {
|
||||||
|
this.log( 'Show button' );
|
||||||
|
if ( ! this.isPresent ) {
|
||||||
|
this.log( '!! Cannot show button, wrapper is not present' );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classic Checkout/PayNow: Make the Apple Pay gateway visible after page load.
|
||||||
|
document
|
||||||
|
.querySelectorAll( 'style#ppcp-hide-apple-pay' )
|
||||||
|
.forEach( ( el ) => el.remove() );
|
||||||
|
|
||||||
|
this.allElements.forEach( ( element ) => {
|
||||||
|
element.style.display = '';
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
async fetchTransactionInfo() {
|
async fetchTransactionInfo() {
|
||||||
this.transactionInfo = await this.contextHandler.transactionInfo();
|
this.transactionInfo = await this.contextHandler.transactionInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns configurations relative to this button context.
|
|
||||||
*/
|
|
||||||
contextConfig() {
|
|
||||||
const config = {
|
|
||||||
wrapper: this.buttonConfig.button.wrapper,
|
|
||||||
ppcpStyle: this.ppcpConfig.button.style,
|
|
||||||
buttonStyle: this.buttonConfig.button.style,
|
|
||||||
ppcpButtonWrapper: this.ppcpConfig.button.wrapper,
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( this.context === 'mini-cart' ) {
|
|
||||||
config.wrapper = this.buttonConfig.button.mini_cart_wrapper;
|
|
||||||
config.ppcpStyle = this.ppcpConfig.button.mini_cart_style;
|
|
||||||
config.buttonStyle = this.buttonConfig.button.mini_cart_style;
|
|
||||||
config.ppcpButtonWrapper = this.ppcpConfig.button.mini_cart_wrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
[ 'cart-block', 'checkout-block' ].indexOf( this.context ) !== -1
|
|
||||||
) {
|
|
||||||
config.ppcpButtonWrapper =
|
|
||||||
'#express-payment-method-ppcp-gateway-paypal';
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
initEventHandlers() {
|
initEventHandlers() {
|
||||||
const { wrapper, ppcpButtonWrapper } = this.contextConfig();
|
const ppcpButtonWrapper = `#${ this.ppcpButtonWrapperId }`;
|
||||||
const wrapper_id = '#' + wrapper;
|
const wrapperId = `#${ this.wrapperId }`;
|
||||||
|
|
||||||
if ( wrapper_id === ppcpButtonWrapper ) {
|
if ( wrapperId === ppcpButtonWrapper ) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`[ApplePayButton] "wrapper" and "ppcpButtonWrapper" values must differ to avoid infinite loop. Current value: "${ wrapper_id }"`
|
`[ApplePayButton] "wrapper" and "ppcpButtonWrapper" values must differ to avoid infinite loop. Current value: "${ wrapperId }"`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,9 +424,9 @@ class ApplepayButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
const $ppcpButtonWrapper = jQuery( ppcpButtonWrapper );
|
const $ppcpButtonWrapper = jQuery( ppcpButtonWrapper );
|
||||||
setVisible( wrapper_id, $ppcpButtonWrapper.is( ':visible' ) );
|
setVisible( wrapperId, $ppcpButtonWrapper.is( ':visible' ) );
|
||||||
setEnabled(
|
setEnabled(
|
||||||
wrapper_id,
|
wrapperId,
|
||||||
! $ppcpButtonWrapper.hasClass( 'ppcp-disabled' )
|
! $ppcpButtonWrapper.hasClass( 'ppcp-disabled' )
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -179,7 +445,8 @@ class ApplepayButton {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts an Apple Pay session.
|
* Starts an Apple Pay session.
|
||||||
* @param paymentRequest
|
*
|
||||||
|
* @param {Object} paymentRequest The payment request object.
|
||||||
*/
|
*/
|
||||||
applePaySession( paymentRequest ) {
|
applePaySession( paymentRequest ) {
|
||||||
this.log( 'applePaySession', paymentRequest );
|
this.log( 'applePaySession', paymentRequest );
|
||||||
|
@ -192,6 +459,7 @@ class ApplepayButton {
|
||||||
session.onshippingcontactselected =
|
session.onshippingcontactselected =
|
||||||
this.onShippingContactSelected( session );
|
this.onShippingContactSelected( session );
|
||||||
}
|
}
|
||||||
|
|
||||||
session.onvalidatemerchant = this.onValidateMerchant( session );
|
session.onvalidatemerchant = this.onValidateMerchant( session );
|
||||||
session.onpaymentauthorized = this.onPaymentAuthorized( session );
|
session.onpaymentauthorized = this.onPaymentAuthorized( session );
|
||||||
return session;
|
return session;
|
||||||
|
@ -199,32 +467,38 @@ class ApplepayButton {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an Apple Pay purchase button.
|
* Adds an Apple Pay purchase button.
|
||||||
|
*
|
||||||
|
* @return {HTMLElement|null} The newly created `<apple-pay-button>` element. Null on failure.
|
||||||
*/
|
*/
|
||||||
addButton() {
|
addButton() {
|
||||||
this.log( 'addButton', this.context );
|
this.log( 'addButton' );
|
||||||
|
|
||||||
const { wrapper, ppcpStyle } = this.contextConfig();
|
const wrapper = this.wrapperElement;
|
||||||
|
const style = this.buttonStyle;
|
||||||
|
const id = 'apple-' + this.wrapperId;
|
||||||
|
|
||||||
const appleContainer = document.getElementById( wrapper );
|
if ( ! wrapper ) {
|
||||||
const type = this.buttonConfig.button.type;
|
return null;
|
||||||
const language = this.buttonConfig.button.lang;
|
|
||||||
const color = this.buttonConfig.button.color;
|
|
||||||
const id = 'apple-' + wrapper;
|
|
||||||
|
|
||||||
if ( appleContainer ) {
|
|
||||||
appleContainer.innerHTML = `<apple-pay-button id="${ id }" buttonstyle="${ color }" type="${ type }" locale="${ language }">`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const $wrapper = jQuery( '#' + wrapper );
|
const ppcpStyle = this.ppcpStyle;
|
||||||
$wrapper.addClass( 'ppcp-button-' + ppcpStyle.shape );
|
|
||||||
|
wrapper.innerHTML = `<apple-pay-button id='${ id }' buttonstyle='${ style.color }' type='${ style.type }' locale='${ style.lang }' />`;
|
||||||
|
wrapper.classList.add(
|
||||||
|
`ppcp-button-${ ppcpStyle.shape }`,
|
||||||
|
'ppcp-button-apm',
|
||||||
|
'ppcp-button-applepay'
|
||||||
|
);
|
||||||
|
|
||||||
if ( ppcpStyle.height ) {
|
if ( ppcpStyle.height ) {
|
||||||
$wrapper.css(
|
wrapper.style.setProperty(
|
||||||
'--apple-pay-button-height',
|
'--apple-pay-button-height',
|
||||||
`${ ppcpStyle.height }px`
|
`${ ppcpStyle.height }px`
|
||||||
);
|
);
|
||||||
$wrapper.css( 'height', `${ ppcpStyle.height }px` );
|
wrapper.style.height = `${ ppcpStyle.height }px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return wrapper.querySelector( 'apple-pay-button' );
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------
|
//------------------------
|
||||||
|
@ -235,19 +509,21 @@ class ApplepayButton {
|
||||||
* Show Apple Pay payment sheet when Apple Pay payment button is clicked
|
* Show Apple Pay payment sheet when Apple Pay payment button is clicked
|
||||||
*/
|
*/
|
||||||
async onButtonClick() {
|
async onButtonClick() {
|
||||||
this.log( 'onButtonClick', this.context );
|
this.log( 'onButtonClick' );
|
||||||
|
|
||||||
const paymentRequest = this.paymentRequest();
|
const paymentRequest = this.paymentRequest();
|
||||||
|
|
||||||
window.ppcpFundingSource = 'apple_pay'; // Do this on another place like on create order endpoint handler.
|
// Do this on another place like on create order endpoint handler.
|
||||||
|
window.ppcpFundingSource = 'apple_pay';
|
||||||
|
|
||||||
// Trigger woocommerce validation if we are in the checkout page.
|
// Trigger woocommerce validation if we are in the checkout page.
|
||||||
if ( this.context === 'checkout' ) {
|
if ( CONTEXT.Checkout === this.context ) {
|
||||||
const checkoutFormSelector = 'form.woocommerce-checkout';
|
const checkoutFormSelector = 'form.woocommerce-checkout';
|
||||||
const errorHandler = new ErrorHandler(
|
const errorHandler = new ErrorHandler(
|
||||||
PayPalCommerceGateway.labels.error.generic,
|
PayPalCommerceGateway.labels.error.generic,
|
||||||
document.querySelector( '.woocommerce-notices-wrapper' )
|
document.querySelector( '.woocommerce-notices-wrapper' )
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const formData = new FormData(
|
const formData = new FormData(
|
||||||
document.querySelector( checkoutFormSelector )
|
document.querySelector( checkoutFormSelector )
|
||||||
|
@ -269,6 +545,7 @@ class ApplepayButton {
|
||||||
PayPalCommerceGateway.ajax.validate_checkout.nonce
|
PayPalCommerceGateway.ajax.validate_checkout.nonce
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if ( formValidator ) {
|
if ( formValidator ) {
|
||||||
try {
|
try {
|
||||||
const errors = await formValidator.validate(
|
const errors = await formValidator.validate(
|
||||||
|
@ -296,13 +573,13 @@ class ApplepayButton {
|
||||||
/**
|
/**
|
||||||
* If the button should show the shipping fields.
|
* If the button should show the shipping fields.
|
||||||
*
|
*
|
||||||
* @return {false|*}
|
* @return {boolean} True, if shipping fields should be captured by ApplePay.
|
||||||
*/
|
*/
|
||||||
shouldRequireShippingInButton() {
|
shouldRequireShippingInButton() {
|
||||||
return (
|
return (
|
||||||
this.contextHandler.shippingAllowed() &&
|
this.contextHandler.shippingAllowed() &&
|
||||||
this.buttonConfig.product.needShipping &&
|
this.buttonConfig.product.needShipping &&
|
||||||
( this.context !== 'checkout' ||
|
( CONTEXT.Checkout !== this.context ||
|
||||||
this.shouldUpdateButtonWithFormData() )
|
this.shouldUpdateButtonWithFormData() )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -310,10 +587,10 @@ class ApplepayButton {
|
||||||
/**
|
/**
|
||||||
* If the button should be updated with the form addresses.
|
* If the button should be updated with the form addresses.
|
||||||
*
|
*
|
||||||
* @return {boolean}
|
* @return {boolean} True, when Apple Pay data should be submitted to WooCommerce.
|
||||||
*/
|
*/
|
||||||
shouldUpdateButtonWithFormData() {
|
shouldUpdateButtonWithFormData() {
|
||||||
if ( this.context !== 'checkout' ) {
|
if ( CONTEXT.Checkout !== this.context ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -323,29 +600,28 @@ class ApplepayButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates how payment completion should be handled if with the context handler default actions.
|
* Indicates how payment completion should be handled if with the context handler default
|
||||||
* Or with ApplePay module specific completion.
|
* actions. Or with Apple Pay module specific completion.
|
||||||
*
|
*
|
||||||
* @return {boolean}
|
* @return {boolean} True, when the Apple Pay data should be submitted to WooCommerce.
|
||||||
*/
|
*/
|
||||||
shouldCompletePaymentWithContextHandler() {
|
shouldCompletePaymentWithContextHandler() {
|
||||||
// Data already handled, ex: PayNow
|
// Data already handled, ex: PayNow
|
||||||
if ( ! this.contextHandler.shippingAllowed() ) {
|
if ( ! this.contextHandler.shippingAllowed() ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use WC form data mode in Checkout.
|
// Use WC form data mode in Checkout.
|
||||||
if (
|
return (
|
||||||
this.context === 'checkout' &&
|
CONTEXT.Checkout === this.context &&
|
||||||
! this.shouldUpdateButtonWithFormData()
|
! this.shouldUpdateButtonWithFormData()
|
||||||
) {
|
);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates Apple Pay paymentRequest with form data.
|
* Updates Apple Pay paymentRequest with form data.
|
||||||
* @param paymentRequest
|
*
|
||||||
|
* @param {Object} paymentRequest Object to extend with form data.
|
||||||
*/
|
*/
|
||||||
updateRequestDataWithForm( paymentRequest ) {
|
updateRequestDataWithForm( paymentRequest ) {
|
||||||
if ( ! this.shouldUpdateButtonWithFormData() ) {
|
if ( ! this.shouldUpdateButtonWithFormData() ) {
|
||||||
|
@ -358,8 +634,9 @@ class ApplepayButton {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add custom data.
|
// Add custom data.
|
||||||
// "applicationData" is originating a "PayPalApplePayError: An internal server error has occurred" on paypal.Applepay().confirmOrder().
|
// "applicationData" is originating a "PayPalApplePayError: An internal server error has
|
||||||
// paymentRequest.applicationData = this.fillApplicationData(this.formData);
|
// occurred" on paypal.Applepay().confirmOrder(). paymentRequest.applicationData =
|
||||||
|
// this.fillApplicationData(this.formData);
|
||||||
|
|
||||||
if ( ! this.shouldRequireShippingInButton() ) {
|
if ( ! this.shouldRequireShippingInButton() ) {
|
||||||
return;
|
return;
|
||||||
|
@ -425,7 +702,8 @@ class ApplepayButton {
|
||||||
'email',
|
'email',
|
||||||
'phone',
|
'phone',
|
||||||
],
|
],
|
||||||
requiredBillingContactFields: [ 'postalAddress' ], // ApplePay does not implement billing email and phone fields.
|
requiredBillingContactFields: [ 'postalAddress' ], // ApplePay does not implement billing
|
||||||
|
// email and phone fields.
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( ! this.shouldRequireShippingInButton() ) {
|
if ( ! this.shouldRequireShippingInButton() ) {
|
||||||
|
@ -453,14 +731,11 @@ class ApplepayButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshContextData() {
|
refreshContextData() {
|
||||||
switch ( this.context ) {
|
if ( CONTEXT.Product === this.context ) {
|
||||||
case 'product':
|
|
||||||
// Refresh product data that makes the price change.
|
// Refresh product data that makes the price change.
|
||||||
this.productQuantity =
|
this.productQuantity = document.querySelector( 'input.qty' )?.value;
|
||||||
document.querySelector( 'input.qty' )?.value;
|
|
||||||
this.products = this.contextHandler.products();
|
this.products = this.contextHandler.products();
|
||||||
this.log( 'Products updated', this.products );
|
this.log( 'Products updated', this.products );
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,8 +743,36 @@ class ApplepayButton {
|
||||||
// Payment process
|
// Payment process
|
||||||
//------------------------
|
//------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make ajax call to change the verification-status of the current domain.
|
||||||
|
*
|
||||||
|
* @param {boolean} isValid
|
||||||
|
*/
|
||||||
|
adminValidation( isValid ) {
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const ignored = fetch( this.buttonConfig.ajax_url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
body: new URLSearchParams( {
|
||||||
|
action: 'ppcp_validate',
|
||||||
|
'woocommerce-process-checkout-nonce': this.nonce,
|
||||||
|
validation: isValid,
|
||||||
|
} ).toString(),
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an event handler that Apple Pay calls when displaying the payment sheet.
|
||||||
|
*
|
||||||
|
* @see https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/1778021-onvalidatemerchant
|
||||||
|
*
|
||||||
|
* @param {Object} session The ApplePaySession object.
|
||||||
|
*
|
||||||
|
* @return {(function(*): void)|*} Callback that runs after the merchant validation
|
||||||
|
*/
|
||||||
onValidateMerchant( session ) {
|
onValidateMerchant( session ) {
|
||||||
this.log( 'onvalidatemerchant', this.buttonConfig.ajax_url );
|
|
||||||
return ( applePayValidateMerchantEvent ) => {
|
return ( applePayValidateMerchantEvent ) => {
|
||||||
this.log( 'onvalidatemerchant call' );
|
this.log( 'onvalidatemerchant call' );
|
||||||
|
|
||||||
|
@ -479,34 +782,15 @@ class ApplepayButton {
|
||||||
validationUrl: applePayValidateMerchantEvent.validationURL,
|
validationUrl: applePayValidateMerchantEvent.validationURL,
|
||||||
} )
|
} )
|
||||||
.then( ( validateResult ) => {
|
.then( ( validateResult ) => {
|
||||||
this.log( 'onvalidatemerchant ok' );
|
|
||||||
session.completeMerchantValidation(
|
session.completeMerchantValidation(
|
||||||
validateResult.merchantSession
|
validateResult.merchantSession
|
||||||
);
|
);
|
||||||
//call backend to update validation to true
|
|
||||||
jQuery.ajax( {
|
this.adminValidation( true );
|
||||||
url: this.buttonConfig.ajax_url,
|
|
||||||
type: 'POST',
|
|
||||||
data: {
|
|
||||||
action: 'ppcp_validate',
|
|
||||||
validation: true,
|
|
||||||
'woocommerce-process-checkout-nonce': this.nonce,
|
|
||||||
},
|
|
||||||
} );
|
|
||||||
} )
|
} )
|
||||||
.catch( ( validateError ) => {
|
.catch( ( validateError ) => {
|
||||||
this.log( 'onvalidatemerchant error', validateError );
|
|
||||||
console.error( validateError );
|
console.error( validateError );
|
||||||
//call backend to update validation to false
|
this.adminValidation( false );
|
||||||
jQuery.ajax( {
|
|
||||||
url: this.buttonConfig.ajax_url,
|
|
||||||
type: 'POST',
|
|
||||||
data: {
|
|
||||||
action: 'ppcp_validate',
|
|
||||||
validation: false,
|
|
||||||
'woocommerce-process-checkout-nonce': this.nonce,
|
|
||||||
},
|
|
||||||
} );
|
|
||||||
this.log( 'onvalidatemerchant session abort' );
|
this.log( 'onvalidatemerchant session abort' );
|
||||||
session.abort();
|
session.abort();
|
||||||
} );
|
} );
|
||||||
|
@ -515,14 +799,14 @@ class ApplepayButton {
|
||||||
|
|
||||||
onShippingMethodSelected( session ) {
|
onShippingMethodSelected( session ) {
|
||||||
this.log( 'onshippingmethodselected', this.buttonConfig.ajax_url );
|
this.log( 'onshippingmethodselected', this.buttonConfig.ajax_url );
|
||||||
const ajax_url = this.buttonConfig.ajax_url;
|
const ajaxUrl = this.buttonConfig.ajax_url;
|
||||||
return ( event ) => {
|
return ( event ) => {
|
||||||
this.log( 'onshippingmethodselected call' );
|
this.log( 'onshippingmethodselected call' );
|
||||||
|
|
||||||
const data = this.getShippingMethodData( event );
|
const data = this.getShippingMethodData( event );
|
||||||
|
|
||||||
jQuery.ajax( {
|
jQuery.ajax( {
|
||||||
url: ajax_url,
|
url: ajaxUrl,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data,
|
data,
|
||||||
success: (
|
success: (
|
||||||
|
@ -537,7 +821,8 @@ class ApplepayButton {
|
||||||
}
|
}
|
||||||
this.selectedShippingMethod = event.shippingMethod;
|
this.selectedShippingMethod = event.shippingMethod;
|
||||||
|
|
||||||
// Sort the response shipping methods, so that the selected shipping method is the first one.
|
// Sort the response shipping methods, so that the selected shipping method is
|
||||||
|
// the first one.
|
||||||
response.newShippingMethods =
|
response.newShippingMethods =
|
||||||
response.newShippingMethods.sort( ( a, b ) => {
|
response.newShippingMethods.sort( ( a, b ) => {
|
||||||
if (
|
if (
|
||||||
|
@ -565,7 +850,7 @@ class ApplepayButton {
|
||||||
onShippingContactSelected( session ) {
|
onShippingContactSelected( session ) {
|
||||||
this.log( 'onshippingcontactselected', this.buttonConfig.ajax_url );
|
this.log( 'onshippingcontactselected', this.buttonConfig.ajax_url );
|
||||||
|
|
||||||
const ajax_url = this.buttonConfig.ajax_url;
|
const ajaxUrl = this.buttonConfig.ajax_url;
|
||||||
|
|
||||||
return ( event ) => {
|
return ( event ) => {
|
||||||
this.log( 'onshippingcontactselected call' );
|
this.log( 'onshippingcontactselected call' );
|
||||||
|
@ -573,7 +858,7 @@ class ApplepayButton {
|
||||||
const data = this.getShippingContactData( event );
|
const data = this.getShippingContactData( event );
|
||||||
|
|
||||||
jQuery.ajax( {
|
jQuery.ajax( {
|
||||||
url: ajax_url,
|
url: ajaxUrl,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data,
|
data,
|
||||||
success: (
|
success: (
|
||||||
|
@ -603,15 +888,15 @@ class ApplepayButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
getShippingContactData( event ) {
|
getShippingContactData( event ) {
|
||||||
const product_id = this.buttonConfig.product.id;
|
const productId = this.buttonConfig.product.id;
|
||||||
|
|
||||||
this.refreshContextData();
|
this.refreshContextData();
|
||||||
|
|
||||||
switch ( this.context ) {
|
switch ( this.context ) {
|
||||||
case 'product':
|
case CONTEXT.Product:
|
||||||
return {
|
return {
|
||||||
action: 'ppcp_update_shipping_contact',
|
action: 'ppcp_update_shipping_contact',
|
||||||
product_id,
|
product_id: productId,
|
||||||
products: JSON.stringify( this.products ),
|
products: JSON.stringify( this.products ),
|
||||||
caller_page: 'productDetail',
|
caller_page: 'productDetail',
|
||||||
product_quantity: this.productQuantity,
|
product_quantity: this.productQuantity,
|
||||||
|
@ -619,11 +904,12 @@ class ApplepayButton {
|
||||||
need_shipping: this.shouldRequireShippingInButton(),
|
need_shipping: this.shouldRequireShippingInButton(),
|
||||||
'woocommerce-process-checkout-nonce': this.nonce,
|
'woocommerce-process-checkout-nonce': this.nonce,
|
||||||
};
|
};
|
||||||
case 'cart':
|
|
||||||
case 'checkout':
|
case CONTEXT.Cart:
|
||||||
case 'cart-block':
|
case CONTEXT.Checkout:
|
||||||
case 'checkout-block':
|
case CONTEXT.BlockCart:
|
||||||
case 'mini-cart':
|
case CONTEXT.BlockCheckout:
|
||||||
|
case CONTEXT.MiniCart:
|
||||||
return {
|
return {
|
||||||
action: 'ppcp_update_shipping_contact',
|
action: 'ppcp_update_shipping_contact',
|
||||||
simplified_contact: event.shippingContact,
|
simplified_contact: event.shippingContact,
|
||||||
|
@ -635,12 +921,12 @@ class ApplepayButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
getShippingMethodData( event ) {
|
getShippingMethodData( event ) {
|
||||||
const product_id = this.buttonConfig.product.id;
|
const productId = this.buttonConfig.product.id;
|
||||||
|
|
||||||
this.refreshContextData();
|
this.refreshContextData();
|
||||||
|
|
||||||
switch ( this.context ) {
|
switch ( this.context ) {
|
||||||
case 'product':
|
case CONTEXT.Product:
|
||||||
return {
|
return {
|
||||||
action: 'ppcp_update_shipping_method',
|
action: 'ppcp_update_shipping_method',
|
||||||
shipping_method: event.shippingMethod,
|
shipping_method: event.shippingMethod,
|
||||||
|
@ -650,17 +936,18 @@ class ApplepayButton {
|
||||||
? this.updatedContactInfo
|
? this.updatedContactInfo
|
||||||
: this.initialPaymentRequest?.shippingContact ??
|
: this.initialPaymentRequest?.shippingContact ??
|
||||||
this.initialPaymentRequest?.billingContact,
|
this.initialPaymentRequest?.billingContact,
|
||||||
product_id,
|
product_id: productId,
|
||||||
products: JSON.stringify( this.products ),
|
products: JSON.stringify( this.products ),
|
||||||
caller_page: 'productDetail',
|
caller_page: 'productDetail',
|
||||||
product_quantity: this.productQuantity,
|
product_quantity: this.productQuantity,
|
||||||
'woocommerce-process-checkout-nonce': this.nonce,
|
'woocommerce-process-checkout-nonce': this.nonce,
|
||||||
};
|
};
|
||||||
case 'cart':
|
|
||||||
case 'checkout':
|
case CONTEXT.Cart:
|
||||||
case 'cart-block':
|
case CONTEXT.Checkout:
|
||||||
case 'checkout-block':
|
case CONTEXT.BlockCart:
|
||||||
case 'mini-cart':
|
case CONTEXT.BlockCheckout:
|
||||||
|
case CONTEXT.MiniCart:
|
||||||
return {
|
return {
|
||||||
action: 'ppcp_update_shipping_method',
|
action: 'ppcp_update_shipping_method',
|
||||||
shipping_method: event.shippingMethod,
|
shipping_method: event.shippingMethod,
|
||||||
|
@ -681,9 +968,6 @@ class ApplepayButton {
|
||||||
return async ( event ) => {
|
return async ( event ) => {
|
||||||
this.log( 'onpaymentauthorized call' );
|
this.log( 'onpaymentauthorized call' );
|
||||||
|
|
||||||
function form() {
|
|
||||||
return document.querySelector( 'form.cart' );
|
|
||||||
}
|
|
||||||
const processInWooAndCapture = async ( data ) => {
|
const processInWooAndCapture = async ( data ) => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
try {
|
try {
|
||||||
|
@ -698,7 +982,7 @@ class ApplepayButton {
|
||||||
( this.initialPaymentRequest.shippingMethods ||
|
( this.initialPaymentRequest.shippingMethods ||
|
||||||
[] )[ 0 ];
|
[] )[ 0 ];
|
||||||
|
|
||||||
const request_data = {
|
const requestData = {
|
||||||
action: 'ppcp_create_order',
|
action: 'ppcp_create_order',
|
||||||
caller_page: this.context,
|
caller_page: this.context,
|
||||||
product_id: this.buttonConfig.product.id ?? null,
|
product_id: this.buttonConfig.product.id ?? null,
|
||||||
|
@ -723,7 +1007,7 @@ class ApplepayButton {
|
||||||
jQuery.ajax( {
|
jQuery.ajax( {
|
||||||
url: this.buttonConfig.ajax_url,
|
url: this.buttonConfig.ajax_url,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: request_data,
|
data: requestData,
|
||||||
complete: ( jqXHR, textStatus ) => {
|
complete: ( jqXHR, textStatus ) => {
|
||||||
this.log( 'onpaymentauthorized complete' );
|
this.log( 'onpaymentauthorized complete' );
|
||||||
},
|
},
|
||||||
|
@ -785,7 +1069,8 @@ class ApplepayButton {
|
||||||
if (
|
if (
|
||||||
this.shouldCompletePaymentWithContextHandler()
|
this.shouldCompletePaymentWithContextHandler()
|
||||||
) {
|
) {
|
||||||
// No shipping, expect immediate capture, ex: PayNow, Checkout with form data.
|
// No shipping, expect immediate capture, ex: PayNow, Checkout with
|
||||||
|
// form data.
|
||||||
|
|
||||||
let approveFailed = false;
|
let approveFailed = false;
|
||||||
await this.contextHandler.approveOrder(
|
await this.contextHandler.approveOrder(
|
||||||
|
@ -960,4 +1245,4 @@ class ApplepayButton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ApplepayButton;
|
export default ApplePayButton;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import buttonModuleWatcher from '../../../ppcp-button/resources/js/modules/ButtonModuleWatcher';
|
/* global paypal */
|
||||||
import ApplepayButton from './ApplepayButton';
|
|
||||||
|
|
||||||
class ApplepayManager {
|
import buttonModuleWatcher from '../../../ppcp-button/resources/js/modules/ButtonModuleWatcher';
|
||||||
|
import ApplePayButton from './ApplepayButton';
|
||||||
|
|
||||||
|
class ApplePayManager {
|
||||||
constructor( buttonConfig, ppcpConfig ) {
|
constructor( buttonConfig, ppcpConfig ) {
|
||||||
this.buttonConfig = buttonConfig;
|
this.buttonConfig = buttonConfig;
|
||||||
this.ppcpConfig = ppcpConfig;
|
this.ppcpConfig = ppcpConfig;
|
||||||
|
@ -9,7 +11,7 @@ class ApplepayManager {
|
||||||
this.buttons = [];
|
this.buttons = [];
|
||||||
|
|
||||||
buttonModuleWatcher.watchContextBootstrap( ( bootstrap ) => {
|
buttonModuleWatcher.watchContextBootstrap( ( bootstrap ) => {
|
||||||
const button = new ApplepayButton(
|
const button = new ApplePayButton(
|
||||||
bootstrap.context,
|
bootstrap.context,
|
||||||
bootstrap.handler,
|
bootstrap.handler,
|
||||||
buttonConfig,
|
buttonConfig,
|
||||||
|
@ -41,7 +43,6 @@ class ApplepayManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets Apple Pay configuration of the PayPal merchant.
|
* Gets Apple Pay configuration of the PayPal merchant.
|
||||||
* @return {Promise<null>}
|
|
||||||
*/
|
*/
|
||||||
async config() {
|
async config() {
|
||||||
this.ApplePayConfig = await paypal.Applepay().config();
|
this.ApplePayConfig = await paypal.Applepay().config();
|
||||||
|
@ -49,4 +50,4 @@ class ApplepayManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ApplepayManager;
|
export default ApplePayManager;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import ApplepayButton from './ApplepayButton';
|
/* global paypal */
|
||||||
|
|
||||||
class ApplepayManagerBlockEditor {
|
import ApplePayButton from './ApplepayButton';
|
||||||
|
|
||||||
|
class ApplePayManagerBlockEditor {
|
||||||
constructor( buttonConfig, ppcpConfig ) {
|
constructor( buttonConfig, ppcpConfig ) {
|
||||||
this.buttonConfig = buttonConfig;
|
this.buttonConfig = buttonConfig;
|
||||||
this.ppcpConfig = ppcpConfig;
|
this.ppcpConfig = ppcpConfig;
|
||||||
|
@ -17,7 +19,7 @@ class ApplepayManagerBlockEditor {
|
||||||
try {
|
try {
|
||||||
this.applePayConfig = await paypal.Applepay().config();
|
this.applePayConfig = await paypal.Applepay().config();
|
||||||
|
|
||||||
const button = new ApplepayButton(
|
const button = new ApplePayButton(
|
||||||
this.ppcpConfig.context,
|
this.ppcpConfig.context,
|
||||||
null,
|
null,
|
||||||
this.buttonConfig,
|
this.buttonConfig,
|
||||||
|
@ -31,4 +33,4 @@ class ApplepayManagerBlockEditor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ApplepayManagerBlockEditor;
|
export default ApplePayManagerBlockEditor;
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import BaseHandler from './BaseHandler';
|
import BaseHandler from './BaseHandler';
|
||||||
|
|
||||||
class PreviewHandler extends BaseHandler {
|
class PreviewHandler extends BaseHandler {
|
||||||
constructor( buttonConfig, ppcpConfig, externalHandler ) {
|
|
||||||
super( buttonConfig, ppcpConfig, externalHandler );
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionInfo() {
|
transactionInfo() {
|
||||||
// We need to return something as ApplePay button initialization expects valid data.
|
// We need to return something as ApplePay button initialization expects valid data.
|
||||||
return {
|
return {
|
||||||
|
@ -19,7 +15,7 @@ class PreviewHandler extends BaseHandler {
|
||||||
throw new Error( 'Create order fail. This is just a preview.' );
|
throw new Error( 'Create order fail. This is just a preview.' );
|
||||||
}
|
}
|
||||||
|
|
||||||
approveOrder( data, actions ) {
|
approveOrder() {
|
||||||
throw new Error( 'Approve order fail. This is just a preview.' );
|
throw new Error( 'Approve order fail. This is just a preview.' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export const buttonID = 'applepay-container';
|
export const buttonID = 'ppc-button-applepay-container';
|
||||||
export const endpoints = {
|
export const endpoints = {
|
||||||
validation: '_apple_pay_validation',
|
validation: '_apple_pay_validation',
|
||||||
createOrderCart: '_apple_pay_create_order_cart',
|
createOrderCart: '_apple_pay_create_order_cart',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import ApplepayButton from './ApplepayButton';
|
import ApplePayButton from './ApplepayButton';
|
||||||
import PreviewButton from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButton';
|
import PreviewButton from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButton';
|
||||||
import PreviewButtonManager from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager';
|
import PreviewButtonManager from '../../../ppcp-button/resources/js/modules/Renderer/PreviewButtonManager';
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ class ApplePayPreviewButton extends PreviewButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
createButton( buttonConfig ) {
|
createButton( buttonConfig ) {
|
||||||
const button = new ApplepayButton(
|
const button = new ApplePayButton(
|
||||||
'preview',
|
'preview',
|
||||||
null,
|
null,
|
||||||
buttonConfig,
|
buttonConfig,
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Help
|
||||||
import { cartHasSubscriptionProducts } from '../../../ppcp-blocks/resources/js/Helper/Subscription';
|
import { cartHasSubscriptionProducts } from '../../../ppcp-blocks/resources/js/Helper/Subscription';
|
||||||
import { loadCustomScript } from '@paypal/paypal-js';
|
import { loadCustomScript } from '@paypal/paypal-js';
|
||||||
import CheckoutHandler from './Context/CheckoutHandler';
|
import CheckoutHandler from './Context/CheckoutHandler';
|
||||||
import ApplepayManager from './ApplepayManager';
|
import ApplePayManager from './ApplepayManager';
|
||||||
import ApplepayManagerBlockEditor from './ApplepayManagerBlockEditor';
|
import ApplePayManagerBlockEditor from './ApplepayManagerBlockEditor';
|
||||||
|
|
||||||
const ppcpData = wc.wcSettings.getSetting( 'ppcp-gateway_data' );
|
const ppcpData = wc.wcSettings.getSetting( 'ppcp-gateway_data' );
|
||||||
const ppcpConfig = ppcpData.scriptData;
|
const ppcpConfig = ppcpData.scriptData;
|
||||||
|
@ -24,8 +24,8 @@ const ApplePayComponent = ( props ) => {
|
||||||
|
|
||||||
const bootstrap = function () {
|
const bootstrap = function () {
|
||||||
const ManagerClass = props.isEditing
|
const ManagerClass = props.isEditing
|
||||||
? ApplepayManagerBlockEditor
|
? ApplePayManagerBlockEditor
|
||||||
: ApplepayManager;
|
: ApplePayManager;
|
||||||
const manager = new ManagerClass( buttonConfig, ppcpConfig );
|
const manager = new ManagerClass( buttonConfig, ppcpConfig );
|
||||||
manager.init();
|
manager.init();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { loadCustomScript } from '@paypal/paypal-js';
|
import { loadCustomScript } from '@paypal/paypal-js';
|
||||||
import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading';
|
import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading';
|
||||||
import ApplepayManager from './ApplepayManager';
|
import ApplePayManager from './ApplepayManager';
|
||||||
import { setupButtonEvents } from '../../../ppcp-button/resources/js/modules/Helper/ButtonRefreshHelper';
|
import { setupButtonEvents } from '../../../ppcp-button/resources/js/modules/Helper/ButtonRefreshHelper';
|
||||||
|
|
||||||
( function ( { buttonConfig, ppcpConfig, jQuery } ) {
|
( function ( { buttonConfig, ppcpConfig, jQuery } ) {
|
||||||
let manager;
|
let manager;
|
||||||
|
|
||||||
const bootstrap = function () {
|
const bootstrap = function () {
|
||||||
manager = new ApplepayManager( buttonConfig, ppcpConfig );
|
manager = new ApplePayManager( buttonConfig, ppcpConfig );
|
||||||
manager.init();
|
manager.init();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -299,5 +299,15 @@ return array(
|
||||||
esc_html( $button_text )
|
esc_html( $button_text )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
'applepay.wc-gateway' => static function ( ContainerInterface $container ): ApplePayGateway {
|
||||||
|
return new ApplePayGateway(
|
||||||
|
$container->get( 'wcgateway.order-processor' ),
|
||||||
|
$container->get( 'api.factory.paypal-checkout-url' ),
|
||||||
|
$container->get( 'wcgateway.processor.refunds' ),
|
||||||
|
$container->get( 'wcgateway.transaction-url-provider' ),
|
||||||
|
$container->get( 'session.handler' ),
|
||||||
|
$container->get( 'applepay.url' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
231
modules/ppcp-applepay/src/ApplePayGateway.php
Normal file
231
modules/ppcp-applepay/src/ApplePayGateway.php
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The Apple Pay Payment Gateway
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\Applepay
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare( strict_types = 1 );
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\Applepay;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use WC_Order;
|
||||||
|
use WC_Payment_Gateway;
|
||||||
|
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\ProcessPaymentTrait;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Exception\PayPalOrderMissingException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\Messages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ApplePayGateway
|
||||||
|
*/
|
||||||
|
class ApplePayGateway extends WC_Payment_Gateway {
|
||||||
|
use ProcessPaymentTrait;
|
||||||
|
|
||||||
|
const ID = 'ppcp-applepay';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The processor for orders.
|
||||||
|
*
|
||||||
|
* @var OrderProcessor
|
||||||
|
*/
|
||||||
|
protected $order_processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function return the PayPal checkout URL for the given order ID.
|
||||||
|
*
|
||||||
|
* @var callable(string):string
|
||||||
|
*/
|
||||||
|
private $paypal_checkout_url_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refund Processor.
|
||||||
|
*
|
||||||
|
* @var RefundProcessor
|
||||||
|
*/
|
||||||
|
private $refund_processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service able to provide transaction url for an order.
|
||||||
|
*
|
||||||
|
* @var TransactionUrlProvider
|
||||||
|
*/
|
||||||
|
protected $transaction_url_provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Session Handler.
|
||||||
|
*
|
||||||
|
* @var SessionHandler
|
||||||
|
*/
|
||||||
|
protected $session_handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL to the module.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $module_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ApplePayGateway constructor.
|
||||||
|
*
|
||||||
|
* @param OrderProcessor $order_processor The Order Processor.
|
||||||
|
* @param callable(string):string $paypal_checkout_url_factory The function return the PayPal
|
||||||
|
* checkout URL for the given order
|
||||||
|
* ID.
|
||||||
|
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||||
|
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction
|
||||||
|
* view URL based on order.
|
||||||
|
* @param SessionHandler $session_handler The Session Handler.
|
||||||
|
* @param string $module_url The URL to the module.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
OrderProcessor $order_processor,
|
||||||
|
callable $paypal_checkout_url_factory,
|
||||||
|
RefundProcessor $refund_processor,
|
||||||
|
TransactionUrlProvider $transaction_url_provider,
|
||||||
|
SessionHandler $session_handler,
|
||||||
|
string $module_url
|
||||||
|
) {
|
||||||
|
$this->id = self::ID;
|
||||||
|
|
||||||
|
$this->method_title = __( 'Apple Pay (via PayPal) ', 'woocommerce-paypal-payments' );
|
||||||
|
$this->method_description = __( 'Display Apple Pay as a standalone payment option instead of bundling it with PayPal.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$this->title = $this->get_option( 'title', __( 'Apple Pay', 'woocommerce-paypal-payments' ) );
|
||||||
|
$this->description = $this->get_option( 'description', '' );
|
||||||
|
|
||||||
|
$this->module_url = $module_url;
|
||||||
|
$this->icon = esc_url( $this->module_url ) . 'assets/images/applepay.png';
|
||||||
|
|
||||||
|
$this->init_form_fields();
|
||||||
|
$this->init_settings();
|
||||||
|
$this->order_processor = $order_processor;
|
||||||
|
$this->paypal_checkout_url_factory = $paypal_checkout_url_factory;
|
||||||
|
$this->refund_processor = $refund_processor;
|
||||||
|
$this->transaction_url_provider = $transaction_url_provider;
|
||||||
|
$this->session_handler = $session_handler;
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'woocommerce_update_options_payment_gateways_' . $this->id,
|
||||||
|
array( $this, 'process_admin_options' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the form fields.
|
||||||
|
*/
|
||||||
|
public function init_form_fields() {
|
||||||
|
$this->form_fields = array(
|
||||||
|
'enabled' => array(
|
||||||
|
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => __( 'Enable Apple Pay', 'woocommerce-paypal-payments' ),
|
||||||
|
'default' => 'no',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'Enable/Disable Apple Pay payment gateway.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'title' => array(
|
||||||
|
'title' => __( 'Title', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->title,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'title' => __( 'Description', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->description,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process payment for a WooCommerce order.
|
||||||
|
*
|
||||||
|
* @param int $order_id The WooCommerce order id.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function process_payment( $order_id ) : array {
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||||
|
return $this->handle_payment_failure(
|
||||||
|
null,
|
||||||
|
new GatewayGenericException( new Exception( 'WC order was not found.' ) )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_action( 'woocommerce_paypal_payments_before_process_order', $wc_order );
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
$this->order_processor->process( $wc_order );
|
||||||
|
|
||||||
|
do_action( 'woocommerce_paypal_payments_before_handle_payment_success', $wc_order );
|
||||||
|
|
||||||
|
return $this->handle_payment_success( $wc_order );
|
||||||
|
} catch ( PayPalOrderMissingException $exc ) {
|
||||||
|
$order = $this->order_processor->create_order( $wc_order );
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'success',
|
||||||
|
'redirect' => ( $this->paypal_checkout_url_factory )( $order->id() ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch ( PayPalApiException $error ) {
|
||||||
|
return $this->handle_payment_failure(
|
||||||
|
$wc_order,
|
||||||
|
new Exception(
|
||||||
|
Messages::generic_payment_error_message() . ' ' . $error->getMessage(),
|
||||||
|
$error->getCode(),
|
||||||
|
$error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch ( Exception $error ) {
|
||||||
|
return $this->handle_payment_failure( $wc_order, $error );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process refund.
|
||||||
|
*
|
||||||
|
* If the gateway declares 'refunds' support, this will allow it to refund.
|
||||||
|
* a passed in amount.
|
||||||
|
*
|
||||||
|
* @param int $order_id Order ID.
|
||||||
|
* @param float $amount Refund amount.
|
||||||
|
* @param string $reason Refund reason.
|
||||||
|
*
|
||||||
|
* @return boolean True or false based on success, or a WP_Error object.
|
||||||
|
*/
|
||||||
|
public function process_refund( $order_id, $amount = null, $reason = '' ) : bool {
|
||||||
|
$order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $order, WC_Order::class ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return transaction url for this gateway and given order.
|
||||||
|
*
|
||||||
|
* @param WC_Order $order WC order to get transaction url by.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_transaction_url( $order ) : string {
|
||||||
|
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||||
|
|
||||||
|
return parent::get_transaction_url( $order );
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\Applepay;
|
namespace WooCommerce\PayPalCommerce\Applepay;
|
||||||
|
|
||||||
|
use WC_Payment_Gateway;
|
||||||
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
|
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
|
||||||
use WooCommerce\PayPalCommerce\Applepay\Assets\ApplePayButton;
|
use WooCommerce\PayPalCommerce\Applepay\Assets\ApplePayButton;
|
||||||
use WooCommerce\PayPalCommerce\Applepay\Assets\AppleProductStatus;
|
use WooCommerce\PayPalCommerce\Applepay\Assets\AppleProductStatus;
|
||||||
|
@ -117,6 +118,48 @@ class ApplepayModule implements ModuleInterface {
|
||||||
100,
|
100,
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_payment_gateways',
|
||||||
|
/**
|
||||||
|
* Param types removed to avoid third-party issues.
|
||||||
|
*
|
||||||
|
* @psalm-suppress MissingClosureParamType
|
||||||
|
*/
|
||||||
|
static function ( $methods ) use ( $c ): array {
|
||||||
|
if ( ! is_array( $methods ) ) {
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = $c->get( 'wcgateway.settings' );
|
||||||
|
assert( $settings instanceof Settings );
|
||||||
|
|
||||||
|
if ( $settings->has( 'applepay_button_enabled' ) && $settings->get( 'applepay_button_enabled' ) ) {
|
||||||
|
$applepay_gateway = $c->get( 'applepay.wc-gateway' );
|
||||||
|
assert( $applepay_gateway instanceof WC_Payment_Gateway );
|
||||||
|
|
||||||
|
$methods[] = $applepay_gateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'woocommerce_review_order_after_submit',
|
||||||
|
function () {
|
||||||
|
// Wrapper ID: #ppc-button-ppcp-applepay.
|
||||||
|
echo '<div id="ppc-button-' . esc_attr( ApplePayGateway::ID ) . '"></div>';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'woocommerce_pay_order_after_submit',
|
||||||
|
function () {
|
||||||
|
// Wrapper ID: #ppc-button-ppcp-applepay.
|
||||||
|
echo '<div id="ppc-button-' . esc_attr( ApplePayGateway::ID ) . '"></div>';
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -306,7 +349,7 @@ class ApplepayModule implements ModuleInterface {
|
||||||
* @param bool $is_sandbox The environment for this merchant.
|
* @param bool $is_sandbox The environment for this merchant.
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function validation_string( bool $is_sandbox ) {
|
public function validation_string( bool $is_sandbox ) : string {
|
||||||
$sandbox_string = $this->sandbox_validation_string();
|
$sandbox_string = $this->sandbox_validation_string();
|
||||||
$live_string = $this->live_validation_string();
|
$live_string = $this->live_validation_string();
|
||||||
return $is_sandbox ? $sandbox_string : $live_string;
|
return $is_sandbox ? $sandbox_string : $live_string;
|
||||||
|
|
|
@ -20,12 +20,13 @@ use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
use WooCommerce\PayPalCommerce\Webhooks\Handler\RequestHandlerTrait;
|
use WooCommerce\PayPalCommerce\Webhooks\Handler\RequestHandlerTrait;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ApplePayButton
|
* Class ApplePayButton
|
||||||
*/
|
*/
|
||||||
class ApplePayButton implements ButtonInterface {
|
class ApplePayButton implements ButtonInterface {
|
||||||
use RequestHandlerTrait;
|
use RequestHandlerTrait, ContextTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings.
|
* The settings.
|
||||||
|
@ -340,7 +341,7 @@ class ApplePayButton implements ButtonInterface {
|
||||||
}
|
}
|
||||||
$response = $this->response_templates->apple_formatted_response( $payment_details );
|
$response = $this->response_templates->apple_formatted_response( $payment_details );
|
||||||
$this->response_templates->response_success( $response );
|
$this->response_templates->response_success( $response );
|
||||||
} catch ( \Exception $e ) {
|
} catch ( Exception $e ) {
|
||||||
$this->response_templates->response_with_data_errors(
|
$this->response_templates->response_with_data_errors(
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
@ -382,7 +383,7 @@ class ApplePayButton implements ButtonInterface {
|
||||||
}
|
}
|
||||||
$response = $this->response_templates->apple_formatted_response( $payment_details );
|
$response = $this->response_templates->apple_formatted_response( $payment_details );
|
||||||
$this->response_templates->response_success( $response );
|
$this->response_templates->response_success( $response );
|
||||||
} catch ( \Exception $e ) {
|
} catch ( Exception $e ) {
|
||||||
$this->response_templates->response_with_data_errors(
|
$this->response_templates->response_with_data_errors(
|
||||||
array(
|
array(
|
||||||
array(
|
array(
|
||||||
|
@ -399,7 +400,7 @@ class ApplePayButton implements ButtonInterface {
|
||||||
* On error returns an array of errors to be handled by the script
|
* On error returns an array of errors to be handled by the script
|
||||||
* On success returns the new order data
|
* On success returns the new order data
|
||||||
*
|
*
|
||||||
* @throws \Exception When validation fails.
|
* @throws Exception When validation fails.
|
||||||
*/
|
*/
|
||||||
public function create_wc_order(): void {
|
public function create_wc_order(): void {
|
||||||
$applepay_request_data_object = $this->applepay_data_object_http();
|
$applepay_request_data_object = $this->applepay_data_object_http();
|
||||||
|
@ -420,15 +421,18 @@ class ApplePayButton implements ButtonInterface {
|
||||||
$applepay_request_data_object->order_data( $context );
|
$applepay_request_data_object->order_data( $context );
|
||||||
|
|
||||||
$this->update_posted_data( $applepay_request_data_object );
|
$this->update_posted_data( $applepay_request_data_object );
|
||||||
|
|
||||||
if ( $context === 'product' ) {
|
if ( $context === 'product' ) {
|
||||||
$cart_item_key = $this->prepare_cart( $applepay_request_data_object );
|
$cart_item_key = $this->prepare_cart( $applepay_request_data_object );
|
||||||
$cart = WC()->cart;
|
$cart = WC()->cart;
|
||||||
$address = $applepay_request_data_object->shipping_address();
|
$address = $applepay_request_data_object->shipping_address();
|
||||||
|
|
||||||
$this->calculate_totals_single_product(
|
$this->calculate_totals_single_product(
|
||||||
$cart,
|
$cart,
|
||||||
$address,
|
$address,
|
||||||
$applepay_request_data_object->shipping_method()
|
$applepay_request_data_object->shipping_method()
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( ! $cart_item_key ) {
|
if ( ! $cart_item_key ) {
|
||||||
$this->response_templates->response_with_data_errors(
|
$this->response_templates->response_with_data_errors(
|
||||||
array(
|
array(
|
||||||
|
@ -438,20 +442,17 @@ class ApplePayButton implements ButtonInterface {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'woocommerce_payment_successful_result',
|
'woocommerce_payment_successful_result',
|
||||||
function ( array $result ) use ( $cart, $cart_item_key ) : array {
|
function ( array $result ) use ( $cart, $cart_item_key ) : array {
|
||||||
if ( ! is_string( $cart_item_key ) ) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
$this->clear_current_cart( $cart, $cart_item_key );
|
$this->clear_current_cart( $cart, $cart_item_key );
|
||||||
$this->reload_cart( $cart );
|
$this->reload_cart( $cart );
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WC()->checkout()->process_checkout();
|
WC()->checkout()->process_checkout();
|
||||||
}
|
}
|
||||||
|
@ -460,17 +461,20 @@ class ApplePayButton implements ButtonInterface {
|
||||||
/**
|
/**
|
||||||
* Checks if the nonce in the data object is valid
|
* Checks if the nonce in the data object is valid
|
||||||
*
|
*
|
||||||
* @return bool|int
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function is_nonce_valid(): bool {
|
protected function is_nonce_valid(): bool {
|
||||||
$nonce = filter_input( INPUT_POST, 'woocommerce-process-checkout-nonce', FILTER_SANITIZE_SPECIAL_CHARS );
|
$nonce = filter_input( INPUT_POST, 'woocommerce-process-checkout-nonce', FILTER_SANITIZE_SPECIAL_CHARS );
|
||||||
if ( ! $nonce ) {
|
if ( ! $nonce ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return wp_verify_nonce(
|
|
||||||
|
// Return value 1 indicates "valid nonce, generated in past 12 hours".
|
||||||
|
// Return value 2 also indicated valid nonce, but older than 12 hours.
|
||||||
|
return 1 === wp_verify_nonce(
|
||||||
$nonce,
|
$nonce,
|
||||||
'woocommerce-process_checkout'
|
'woocommerce-process_checkout'
|
||||||
) === 1;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -511,7 +515,7 @@ class ApplePayButton implements ButtonInterface {
|
||||||
$address,
|
$address,
|
||||||
$applepay_request_data_object->shipping_method()
|
$applepay_request_data_object->shipping_method()
|
||||||
);
|
);
|
||||||
if ( is_string( $cart_item_key ) ) {
|
if ( $cart_item_key ) {
|
||||||
$this->clear_current_cart( $cart, $cart_item_key );
|
$this->clear_current_cart( $cart, $cart_item_key );
|
||||||
$this->reload_cart( $cart );
|
$this->reload_cart( $cart );
|
||||||
}
|
}
|
||||||
|
@ -819,9 +823,9 @@ class ApplePayButton implements ButtonInterface {
|
||||||
/**
|
/**
|
||||||
* Removes the old cart, saves it, and creates a new one
|
* Removes the old cart, saves it, and creates a new one
|
||||||
*
|
*
|
||||||
|
* @throws Exception If it cannot be added to cart.
|
||||||
* @param ApplePayDataObjectHttp $applepay_request_data_object The request data object.
|
* @param ApplePayDataObjectHttp $applepay_request_data_object The request data object.
|
||||||
* @return bool | string The cart item key after adding to the new cart.
|
* @return string The cart item key after adding to the new cart.
|
||||||
* @throws \Exception If it cannot be added to cart.
|
|
||||||
*/
|
*/
|
||||||
public function prepare_cart( ApplePayDataObjectHttp $applepay_request_data_object ): string {
|
public function prepare_cart( ApplePayDataObjectHttp $applepay_request_data_object ): string {
|
||||||
$this->save_old_cart();
|
$this->save_old_cart();
|
||||||
|
@ -838,7 +842,7 @@ class ApplePayButton implements ButtonInterface {
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->cart_products->add_products( array( $product ) );
|
$this->cart_products->add_products( array( $product ) );
|
||||||
return $this->cart_products->cart_item_keys()[0];
|
return $this->cart_products->cart_item_keys()[0] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -949,6 +953,7 @@ class ApplePayButton implements ButtonInterface {
|
||||||
$render_placeholder,
|
$render_placeholder,
|
||||||
function () {
|
function () {
|
||||||
$this->applepay_button();
|
$this->applepay_button();
|
||||||
|
$this->hide_gateway_until_eligible();
|
||||||
},
|
},
|
||||||
21
|
21
|
||||||
);
|
);
|
||||||
|
@ -961,6 +966,7 @@ class ApplePayButton implements ButtonInterface {
|
||||||
$render_placeholder,
|
$render_placeholder,
|
||||||
function () {
|
function () {
|
||||||
$this->applepay_button();
|
$this->applepay_button();
|
||||||
|
$this->hide_gateway_until_eligible();
|
||||||
},
|
},
|
||||||
21
|
21
|
||||||
);
|
);
|
||||||
|
@ -973,7 +979,7 @@ class ApplePayButton implements ButtonInterface {
|
||||||
add_action(
|
add_action(
|
||||||
$render_placeholder,
|
$render_placeholder,
|
||||||
function () {
|
function () {
|
||||||
echo '<span id="applepay-container-minicart" class="ppcp-button-apm ppcp-button-applepay ppcp-button-minicart"></span>';
|
echo '<span id="ppc-button-applepay-container-minicart" class="ppcp-button-apm ppcp-button-applepay ppcp-button-minicart"></span>';
|
||||||
},
|
},
|
||||||
21
|
21
|
||||||
);
|
);
|
||||||
|
@ -981,24 +987,29 @@ class ApplePayButton implements ButtonInterface {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ApplePay button markup
|
* ApplePay button markup
|
||||||
*/
|
*/
|
||||||
protected function applepay_button(): void {
|
protected function applepay_button(): void {
|
||||||
?>
|
?>
|
||||||
<div id="applepay-container" class="ppcp-button-apm ppcp-button-applepay">
|
<div id="ppc-button-applepay-container" class="ppcp-button-apm ppcp-button-applepay">
|
||||||
<?php wp_nonce_field( 'woocommerce-process_checkout', 'woocommerce-process-checkout-nonce' ); ?>
|
<?php wp_nonce_field( 'woocommerce-process_checkout', 'woocommerce-process-checkout-nonce' ); ?>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the module should load the script.
|
* Outputs an inline CSS style that hides the Apple Pay gateway (on Classic Checkout).
|
||||||
|
* The style is removed by `ApplepayButton.js` once the eligibility of the payment method
|
||||||
|
* is confirmed.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function should_load_script(): bool {
|
protected function hide_gateway_until_eligible(): void {
|
||||||
return true;
|
?>
|
||||||
|
<style id="ppcp-hide-apple-pay">.wc_payment_method.payment_method_ppcp-applepay{display:none}</style>
|
||||||
|
<?php
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,6 +11,8 @@ namespace WooCommerce\PayPalCommerce\Applepay\Assets;
|
||||||
|
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
use WooCommerce\PayPalCommerce\Applepay\ApplePayGateway;
|
||||||
|
use WC_Product;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class DataToAppleButtonScripts
|
* Class DataToAppleButtonScripts
|
||||||
|
@ -45,57 +47,92 @@ class DataToAppleButtonScripts {
|
||||||
* Sets the appropriate data to send to ApplePay script
|
* Sets the appropriate data to send to ApplePay script
|
||||||
* Data differs between product page and cart page
|
* Data differs between product page and cart page
|
||||||
*
|
*
|
||||||
* @param bool $is_block Whether the button is in a block or not.
|
|
||||||
* @return array
|
* @return array
|
||||||
* @throws NotFoundException When the setting is not found.
|
|
||||||
*/
|
*/
|
||||||
public function apple_pay_script_data( bool $is_block = false ): array {
|
public function apple_pay_script_data() : array {
|
||||||
$base_location = wc_get_base_location();
|
|
||||||
$shop_country_code = $base_location['country'];
|
|
||||||
$currency_code = get_woocommerce_currency();
|
|
||||||
$total_label = get_bloginfo( 'name' );
|
|
||||||
if ( is_product() ) {
|
if ( is_product() ) {
|
||||||
return $this->data_for_product_page(
|
return $this->data_for_product_page();
|
||||||
$shop_country_code,
|
|
||||||
$currency_code,
|
|
||||||
$total_label
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->data_for_cart_page(
|
return $this->data_for_cart_page();
|
||||||
$shop_country_code,
|
|
||||||
$currency_code,
|
|
||||||
$total_label
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the appropriate admin data to send to ApplePay script
|
* Returns the appropriate admin data to send to ApplePay script
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* @throws NotFoundException When the setting is not found.
|
|
||||||
*/
|
*/
|
||||||
public function apple_pay_script_data_for_admin() : array {
|
public function apple_pay_script_data_for_admin() : array {
|
||||||
|
return $this->data_for_admin_page();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full config array for the Apple Pay integration with default values.
|
||||||
|
*
|
||||||
|
* @param array $product - Optional. Product details for the payment button.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function get_apple_pay_data( array $product = array() ) : array {
|
||||||
|
// true: Use Apple Pay as distinct gateway.
|
||||||
|
// false: integrate it with the smart buttons.
|
||||||
|
$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
|
||||||
|
$is_wc_gateway_enabled = isset( $available_gateways[ ApplePayGateway::ID ] );
|
||||||
|
|
||||||
|
// use_wc: Use WC checkout data
|
||||||
|
// use_applepay: Use data provided by Apple Pay.
|
||||||
|
$checkout_data_mode = $this->settings->has( 'applepay_checkout_data_mode' )
|
||||||
|
? $this->settings->get( 'applepay_checkout_data_mode' )
|
||||||
|
: PropertiesDictionary::BILLING_DATA_MODE_DEFAULT;
|
||||||
|
|
||||||
|
// Store country, currency and name.
|
||||||
$base_location = wc_get_base_location();
|
$base_location = wc_get_base_location();
|
||||||
$shop_country_code = $base_location['country'];
|
$shop_country_code = $base_location['country'];
|
||||||
$currency_code = get_woocommerce_currency();
|
$currency_code = get_woocommerce_currency();
|
||||||
$total_label = get_bloginfo( 'name' );
|
$total_label = get_bloginfo( 'name' );
|
||||||
|
|
||||||
return $this->data_for_admin_page(
|
// Button layout (label, color, language).
|
||||||
$shop_country_code,
|
$type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : '';
|
||||||
$currency_code,
|
$color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : '';
|
||||||
$total_label
|
$lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : '';
|
||||||
|
$lang = apply_filters( 'woocommerce_paypal_payments_applepay_button_language', $lang );
|
||||||
|
$is_enabled = $this->settings->has( 'applepay_button_enabled' ) && $this->settings->get( 'applepay_button_enabled' );
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'sdk_url' => $this->sdk_url,
|
||||||
|
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
|
||||||
|
'is_admin' => false,
|
||||||
|
'is_enabled' => $is_enabled,
|
||||||
|
'is_wc_gateway_enabled' => $is_wc_gateway_enabled,
|
||||||
|
'preferences' => array(
|
||||||
|
'checkout_data_mode' => $checkout_data_mode,
|
||||||
|
),
|
||||||
|
'button' => array(
|
||||||
|
'wrapper' => 'ppc-button-applepay-container',
|
||||||
|
'mini_cart_wrapper' => 'ppc-button-applepay-container-minicart',
|
||||||
|
'type' => $type,
|
||||||
|
'color' => $color,
|
||||||
|
'lang' => $lang,
|
||||||
|
),
|
||||||
|
'product' => $product,
|
||||||
|
'shop' => array(
|
||||||
|
'countryCode' => $shop_country_code,
|
||||||
|
'currencyCode' => $currency_code,
|
||||||
|
'totalLabel' => $total_label,
|
||||||
|
),
|
||||||
|
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||||
|
'nonce' => wp_create_nonce( 'woocommerce-process_checkout' ),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the product needs shipping
|
* Check if the product needs shipping
|
||||||
*
|
*
|
||||||
* @param \WC_Product $product The product.
|
* @param WC_Product $product Product to check.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function check_if_need_shipping( $product ) {
|
protected function check_if_need_shipping( WC_Product $product ) : bool {
|
||||||
if (
|
if (
|
||||||
! wc_shipping_enabled()
|
! wc_shipping_enabled()
|
||||||
|| 0 === wc_get_shipping_method_count(
|
|| 0 === wc_get_shipping_method_count(
|
||||||
|
@ -104,30 +141,20 @@ class DataToAppleButtonScripts {
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$needs_shipping = false;
|
|
||||||
|
|
||||||
if ( $product->needs_shipping() ) {
|
if ( $product->needs_shipping() ) {
|
||||||
$needs_shipping = true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $needs_shipping;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares the data for the product page.
|
* Prepares the data for the product page.
|
||||||
*
|
*
|
||||||
* @param string $shop_country_code The shop country code.
|
|
||||||
* @param string $currency_code The currency code.
|
|
||||||
* @param string $total_label The label for the total amount.
|
|
||||||
*
|
|
||||||
* @return array
|
* @return array
|
||||||
* @throws NotFoundException When the setting is not found.
|
|
||||||
*/
|
*/
|
||||||
protected function data_for_product_page(
|
protected function data_for_product_page() : array {
|
||||||
$shop_country_code,
|
|
||||||
$currency_code,
|
|
||||||
$total_label
|
|
||||||
) {
|
|
||||||
$product = wc_get_product( get_the_id() );
|
$product = wc_get_product( get_the_id() );
|
||||||
if ( ! $product ) {
|
if ( ! $product ) {
|
||||||
return array();
|
return array();
|
||||||
|
@ -136,146 +163,59 @@ class DataToAppleButtonScripts {
|
||||||
if ( $product->get_type() === 'variable' || $product->get_type() === 'variable-subscription' ) {
|
if ( $product->get_type() === 'variable' || $product->get_type() === 'variable-subscription' ) {
|
||||||
$is_variation = true;
|
$is_variation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$product_need_shipping = $this->check_if_need_shipping( $product );
|
$product_need_shipping = $this->check_if_need_shipping( $product );
|
||||||
$product_id = get_the_id();
|
$product_id = get_the_id();
|
||||||
$product_price = $product->get_price();
|
$product_price = $product->get_price();
|
||||||
$product_stock = $product->get_stock_status();
|
$product_stock = $product->get_stock_status();
|
||||||
$type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : '';
|
|
||||||
$color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : '';
|
|
||||||
$lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : '';
|
|
||||||
$checkout_data_mode = $this->settings->has( 'applepay_checkout_data_mode' ) ? $this->settings->get( 'applepay_checkout_data_mode' ) : PropertiesDictionary::BILLING_DATA_MODE_DEFAULT;
|
|
||||||
|
|
||||||
return array(
|
return $this->get_apple_pay_data(
|
||||||
'sdk_url' => $this->sdk_url,
|
array(
|
||||||
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
|
||||||
'is_admin' => false,
|
|
||||||
'preferences' => array(
|
|
||||||
'checkout_data_mode' => $checkout_data_mode,
|
|
||||||
),
|
|
||||||
'button' => array(
|
|
||||||
'wrapper' => 'applepay-container',
|
|
||||||
'mini_cart_wrapper' => 'applepay-container-minicart',
|
|
||||||
'type' => $type,
|
|
||||||
'color' => $color,
|
|
||||||
'lang' => $lang,
|
|
||||||
),
|
|
||||||
'product' => array(
|
|
||||||
'needShipping' => $product_need_shipping,
|
'needShipping' => $product_need_shipping,
|
||||||
'id' => $product_id,
|
'id' => $product_id,
|
||||||
'price' => $product_price,
|
'price' => $product_price,
|
||||||
'isVariation' => $is_variation,
|
'isVariation' => $is_variation,
|
||||||
'stock' => $product_stock,
|
'stock' => $product_stock,
|
||||||
),
|
)
|
||||||
'shop' => array(
|
|
||||||
'countryCode' => $shop_country_code,
|
|
||||||
'currencyCode' => $currency_code,
|
|
||||||
'totalLabel' => $total_label,
|
|
||||||
),
|
|
||||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
|
||||||
'nonce' => wp_create_nonce( 'woocommerce-process_checkout' ),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares the data for the cart page.
|
* Prepares the data for the cart page.
|
||||||
*
|
*
|
||||||
* @param string $shop_country_code The shop country code.
|
|
||||||
* @param string $currency_code The currency code.
|
|
||||||
* @param string $total_label The label for the total amount.
|
|
||||||
*
|
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function data_for_cart_page(
|
protected function data_for_cart_page() : array {
|
||||||
$shop_country_code,
|
|
||||||
$currency_code,
|
|
||||||
$total_label
|
|
||||||
) {
|
|
||||||
$cart = WC()->cart;
|
$cart = WC()->cart;
|
||||||
if ( ! $cart ) {
|
if ( ! $cart ) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : '';
|
return $this->get_apple_pay_data(
|
||||||
$color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : '';
|
array(
|
||||||
$lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : '';
|
|
||||||
$lang = apply_filters( 'woocommerce_paypal_payments_applepay_button_language', $lang );
|
|
||||||
$checkout_data_mode = $this->settings->has( 'applepay_checkout_data_mode' ) ? $this->settings->get( 'applepay_checkout_data_mode' ) : PropertiesDictionary::BILLING_DATA_MODE_DEFAULT;
|
|
||||||
|
|
||||||
return array(
|
|
||||||
'sdk_url' => $this->sdk_url,
|
|
||||||
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
|
||||||
'is_admin' => false,
|
|
||||||
'preferences' => array(
|
|
||||||
'checkout_data_mode' => $checkout_data_mode,
|
|
||||||
),
|
|
||||||
'button' => array(
|
|
||||||
'wrapper' => 'applepay-container',
|
|
||||||
'mini_cart_wrapper' => 'applepay-container-minicart',
|
|
||||||
'type' => $type,
|
|
||||||
'color' => $color,
|
|
||||||
'lang' => $lang,
|
|
||||||
),
|
|
||||||
'product' => array(
|
|
||||||
'needShipping' => $cart->needs_shipping(),
|
'needShipping' => $cart->needs_shipping(),
|
||||||
'subtotal' => $cart->get_subtotal(),
|
'subtotal' => $cart->get_subtotal(),
|
||||||
),
|
)
|
||||||
'shop' => array(
|
|
||||||
'countryCode' => $shop_country_code,
|
|
||||||
'currencyCode' => $currency_code,
|
|
||||||
'totalLabel' => $total_label,
|
|
||||||
),
|
|
||||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
|
||||||
'nonce' => wp_create_nonce( 'woocommerce-process_checkout' ),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares the data for the cart page.
|
* Prepares the data for the cart page.
|
||||||
* Consider refactoring this method along with data_for_cart_page() and data_for_product_page() methods.
|
* Consider refactoring this method along with data_for_cart_page() and data_for_product_page()
|
||||||
*
|
* methods.
|
||||||
* @param string $shop_country_code The shop country code.
|
|
||||||
* @param string $currency_code The currency code.
|
|
||||||
* @param string $total_label The label for the total amount.
|
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function data_for_admin_page(
|
protected function data_for_admin_page() : array {
|
||||||
$shop_country_code,
|
$data = $this->get_apple_pay_data(
|
||||||
$currency_code,
|
array(
|
||||||
$total_label
|
|
||||||
) {
|
|
||||||
$type = $this->settings->has( 'applepay_button_type' ) ? $this->settings->get( 'applepay_button_type' ) : '';
|
|
||||||
$color = $this->settings->has( 'applepay_button_color' ) ? $this->settings->get( 'applepay_button_color' ) : '';
|
|
||||||
$lang = $this->settings->has( 'applepay_button_language' ) ? $this->settings->get( 'applepay_button_language' ) : '';
|
|
||||||
$lang = apply_filters( 'woocommerce_paypal_payments_applepay_button_language', $lang );
|
|
||||||
$checkout_data_mode = $this->settings->has( 'applepay_checkout_data_mode' ) ? $this->settings->get( 'applepay_checkout_data_mode' ) : PropertiesDictionary::BILLING_DATA_MODE_DEFAULT;
|
|
||||||
$is_enabled = $this->settings->has( 'applepay_button_enabled' ) && $this->settings->get( 'applepay_button_enabled' );
|
|
||||||
|
|
||||||
return array(
|
|
||||||
'sdk_url' => $this->sdk_url,
|
|
||||||
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG,
|
|
||||||
'is_admin' => true,
|
|
||||||
'is_enabled' => $is_enabled,
|
|
||||||
'preferences' => array(
|
|
||||||
'checkout_data_mode' => $checkout_data_mode,
|
|
||||||
),
|
|
||||||
'button' => array(
|
|
||||||
'wrapper' => 'applepay-container',
|
|
||||||
'mini_cart_wrapper' => 'applepay-container-minicart',
|
|
||||||
'type' => $type,
|
|
||||||
'color' => $color,
|
|
||||||
'lang' => $lang,
|
|
||||||
),
|
|
||||||
'product' => array(
|
|
||||||
'needShipping' => false,
|
'needShipping' => false,
|
||||||
'subtotal' => 0,
|
'subtotal' => 0,
|
||||||
),
|
)
|
||||||
'shop' => array(
|
|
||||||
'countryCode' => $shop_country_code,
|
|
||||||
'currencyCode' => $currency_code,
|
|
||||||
'totalLabel' => $total_label,
|
|
||||||
),
|
|
||||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$data['is_admin'] = true;
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ return array(
|
||||||
'title' => __( 'Require final confirmation on checkout', 'woocommerce-paypal-payments' ),
|
'title' => __( 'Require final confirmation on checkout', 'woocommerce-paypal-payments' ),
|
||||||
'type' => 'checkbox',
|
'type' => 'checkbox',
|
||||||
'label' => $label,
|
'label' => $label,
|
||||||
'default' => false,
|
'default' => true,
|
||||||
'screens' => array( State::STATE_START, State::STATE_ONBOARDED ),
|
'screens' => array( State::STATE_START, State::STATE_ONBOARDED ),
|
||||||
'requirements' => array(),
|
'requirements' => array(),
|
||||||
'gateway' => 'paypal',
|
'gateway' => 'paypal',
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"Edge >= 14"
|
"Edge >= 14"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@paypal/react-paypal-js": "^8.3.0",
|
"@paypal/react-paypal-js": "^8.5.0",
|
||||||
"core-js": "^3.25.0",
|
"core-js": "^3.25.0",
|
||||||
"react": "^17.0.0",
|
"react": "^17.0.0",
|
||||||
"react-dom": "^17.0.0"
|
"react-dom": "^17.0.0"
|
||||||
|
|
|
@ -7,7 +7,12 @@ import {
|
||||||
} from '@paypal/react-paypal-js';
|
} from '@paypal/react-paypal-js';
|
||||||
|
|
||||||
import { CheckoutHandler } from './checkout-handler';
|
import { CheckoutHandler } from './checkout-handler';
|
||||||
import { createOrder, onApprove } from '../card-fields-config';
|
import {
|
||||||
|
createOrder,
|
||||||
|
onApprove,
|
||||||
|
createVaultSetupToken,
|
||||||
|
onApproveSavePayment,
|
||||||
|
} from '../card-fields-config';
|
||||||
import { cartHasSubscriptionProducts } from '../Helper/Subscription';
|
import { cartHasSubscriptionProducts } from '../Helper/Subscription';
|
||||||
|
|
||||||
export function CardFields( {
|
export function CardFields( {
|
||||||
|
@ -70,8 +75,21 @@ export function CardFields( {
|
||||||
} }
|
} }
|
||||||
>
|
>
|
||||||
<PayPalCardFieldsProvider
|
<PayPalCardFieldsProvider
|
||||||
createOrder={ createOrder }
|
createVaultSetupToken={
|
||||||
onApprove={ onApprove }
|
config.scriptData.is_free_trial_cart
|
||||||
|
? createVaultSetupToken
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
createOrder={
|
||||||
|
config.scriptData.is_free_trial_cart
|
||||||
|
? undefined
|
||||||
|
: createOrder
|
||||||
|
}
|
||||||
|
onApprove={
|
||||||
|
config.scriptData.is_free_trial_cart
|
||||||
|
? onApproveSavePayment
|
||||||
|
: onApprove
|
||||||
|
}
|
||||||
onError={ ( err ) => {
|
onError={ ( err ) => {
|
||||||
console.error( err );
|
console.error( err );
|
||||||
} }
|
} }
|
||||||
|
|
|
@ -44,3 +44,61 @@ export async function onApprove( data ) {
|
||||||
console.error( err );
|
console.error( err );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function createVaultSetupToken() {
|
||||||
|
const config = wc.wcSettings.getSetting( 'ppcp-credit-card-gateway_data' );
|
||||||
|
|
||||||
|
return fetch( config.scriptData.ajax.create_setup_token.endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify( {
|
||||||
|
nonce: config.scriptData.ajax.create_setup_token.nonce,
|
||||||
|
payment_method: 'ppcp-credit-card-gateway',
|
||||||
|
} ),
|
||||||
|
} )
|
||||||
|
.then( ( response ) => response.json() )
|
||||||
|
.then( ( result ) => {
|
||||||
|
console.log( result );
|
||||||
|
return result.data.id;
|
||||||
|
} )
|
||||||
|
.catch( ( err ) => {
|
||||||
|
console.error( err );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function onApproveSavePayment( { vaultSetupToken } ) {
|
||||||
|
const config = wc.wcSettings.getSetting( 'ppcp-credit-card-gateway_data' );
|
||||||
|
|
||||||
|
let endpoint =
|
||||||
|
config.scriptData.ajax.create_payment_token_for_guest.endpoint;
|
||||||
|
let bodyContent = {
|
||||||
|
nonce: config.scriptData.ajax.create_payment_token_for_guest.nonce,
|
||||||
|
vault_setup_token: vaultSetupToken,
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( config.scriptData.user.is_logged_in ) {
|
||||||
|
endpoint = config.scriptData.ajax.create_payment_token.endpoint;
|
||||||
|
|
||||||
|
bodyContent = {
|
||||||
|
nonce: config.scriptData.ajax.create_payment_token.nonce,
|
||||||
|
vault_setup_token: vaultSetupToken,
|
||||||
|
is_free_trial_cart: config.scriptData.is_free_trial_cart,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch( endpoint, {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify( bodyContent ),
|
||||||
|
} );
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
if ( result.success !== true ) {
|
||||||
|
console.error( result );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ const PayPalComponent = ( {
|
||||||
throw new Error( config.scriptData.labels.error.generic );
|
throw new Error( config.scriptData.labels.error.generic );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! shouldHandleShippingInPayPal() ) {
|
if ( ! shouldskipFinalConfirmation() ) {
|
||||||
location.href = getCheckoutRedirectUrl();
|
location.href = getCheckoutRedirectUrl();
|
||||||
} else {
|
} else {
|
||||||
setGotoContinuationOnError( true );
|
setGotoContinuationOnError( true );
|
||||||
|
@ -318,7 +318,7 @@ const PayPalComponent = ( {
|
||||||
throw new Error( config.scriptData.labels.error.generic );
|
throw new Error( config.scriptData.labels.error.generic );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! shouldHandleShippingInPayPal() ) {
|
if ( ! shouldskipFinalConfirmation() ) {
|
||||||
location.href = getCheckoutRedirectUrl();
|
location.href = getCheckoutRedirectUrl();
|
||||||
} else {
|
} else {
|
||||||
setGotoContinuationOnError( true );
|
setGotoContinuationOnError( true );
|
||||||
|
@ -364,6 +364,10 @@ const PayPalComponent = ( {
|
||||||
};
|
};
|
||||||
|
|
||||||
const shouldHandleShippingInPayPal = () => {
|
const shouldHandleShippingInPayPal = () => {
|
||||||
|
return shouldskipFinalConfirmation() && config.needShipping
|
||||||
|
};
|
||||||
|
|
||||||
|
const shouldskipFinalConfirmation = () => {
|
||||||
if ( config.finalReviewEnabled ) {
|
if ( config.finalReviewEnabled ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -544,7 +548,7 @@ const PayPalComponent = ( {
|
||||||
if ( config.scriptData.continuation ) {
|
if ( config.scriptData.continuation ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ( shouldHandleShippingInPayPal() ) {
|
if ( shouldskipFinalConfirmation() ) {
|
||||||
location.href = getCheckoutRedirectUrl();
|
location.href = getCheckoutRedirectUrl();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -13,6 +13,7 @@ use WooCommerce\PayPalCommerce\Blocks\Endpoint\GetPayPalOrderFromSession;
|
||||||
use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint;
|
use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface;
|
use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface;
|
||||||
|
use WC_Cart;
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'blocks.url' => static function ( ContainerInterface $container ): string {
|
'blocks.url' => static function ( ContainerInterface $container ): string {
|
||||||
|
@ -27,6 +28,13 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'blocks.method' => static function ( ContainerInterface $container ): PayPalPaymentMethod {
|
'blocks.method' => static function ( ContainerInterface $container ): PayPalPaymentMethod {
|
||||||
|
/**
|
||||||
|
* Cart instance; might be null, esp. in customizer or in Block Editor.
|
||||||
|
*
|
||||||
|
* @var null|WC_Cart $cart
|
||||||
|
*/
|
||||||
|
$cart = WC()->cart;
|
||||||
|
|
||||||
return new PayPalPaymentMethod(
|
return new PayPalPaymentMethod(
|
||||||
$container->get( 'blocks.url' ),
|
$container->get( 'blocks.url' ),
|
||||||
$container->get( 'ppcp.asset-version' ),
|
$container->get( 'ppcp.asset-version' ),
|
||||||
|
@ -43,7 +51,8 @@ return array(
|
||||||
$container->get( 'wcgateway.use-place-order-button' ),
|
$container->get( 'wcgateway.use-place-order-button' ),
|
||||||
$container->get( 'wcgateway.place-order-button-text' ),
|
$container->get( 'wcgateway.place-order-button-text' ),
|
||||||
$container->get( 'wcgateway.place-order-button-description' ),
|
$container->get( 'wcgateway.place-order-button-description' ),
|
||||||
$container->get( 'wcgateway.all-funding-sources' )
|
$container->get( 'wcgateway.all-funding-sources' ),
|
||||||
|
$cart && $cart->needs_shipping()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'blocks.advanced-card-method' => static function( ContainerInterface $container ): AdvancedCardPaymentMethod {
|
'blocks.advanced-card-method' => static function( ContainerInterface $container ): AdvancedCardPaymentMethod {
|
||||||
|
|
|
@ -97,15 +97,6 @@ class UpdateShippingEndpoint implements EndpointInterface {
|
||||||
$pu = $this->purchase_unit_factory->from_wc_cart( null, true );
|
$pu = $this->purchase_unit_factory->from_wc_cart( null, true );
|
||||||
$pu_data = $pu->to_array();
|
$pu_data = $pu->to_array();
|
||||||
|
|
||||||
if ( ! isset( $pu_data['shipping']['options'] ) ) {
|
|
||||||
wp_send_json_error(
|
|
||||||
array(
|
|
||||||
'message' => 'No shipping methods.',
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: maybe should patch only if methods changed.
|
// TODO: maybe should patch only if methods changed.
|
||||||
// But it seems a bit difficult to detect,
|
// But it seems a bit difficult to detect,
|
||||||
// e.g. ->order($id) may not have Shipping because we drop it when address or name are missing.
|
// e.g. ->order($id) may not have Shipping because we drop it when address or name are missing.
|
||||||
|
|
|
@ -122,6 +122,13 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
||||||
*/
|
*/
|
||||||
private $all_funding_sources;
|
private $all_funding_sources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether shipping details must be collected during checkout; i.e. paying for physical goods?
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $need_shipping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assets constructor.
|
* Assets constructor.
|
||||||
*
|
*
|
||||||
|
@ -139,6 +146,7 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
||||||
* @param string $place_order_button_text The text for the standard "Place order" button.
|
* @param string $place_order_button_text The text for the standard "Place order" button.
|
||||||
* @param string $place_order_button_description The text for additional "Place order" description.
|
* @param string $place_order_button_description The text for additional "Place order" description.
|
||||||
* @param array $all_funding_sources All existing funding sources for PayPal buttons.
|
* @param array $all_funding_sources All existing funding sources for PayPal buttons.
|
||||||
|
* @param bool $need_shipping Whether shipping details are required for the purchase.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $module_url,
|
string $module_url,
|
||||||
|
@ -154,7 +162,8 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
||||||
bool $use_place_order,
|
bool $use_place_order,
|
||||||
string $place_order_button_text,
|
string $place_order_button_text,
|
||||||
string $place_order_button_description,
|
string $place_order_button_description,
|
||||||
array $all_funding_sources
|
array $all_funding_sources,
|
||||||
|
bool $need_shipping
|
||||||
) {
|
) {
|
||||||
$this->name = PayPalGateway::ID;
|
$this->name = PayPalGateway::ID;
|
||||||
$this->module_url = $module_url;
|
$this->module_url = $module_url;
|
||||||
|
@ -171,6 +180,7 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
||||||
$this->place_order_button_text = $place_order_button_text;
|
$this->place_order_button_text = $place_order_button_text;
|
||||||
$this->place_order_button_description = $place_order_button_description;
|
$this->place_order_button_description = $place_order_button_description;
|
||||||
$this->all_funding_sources = $all_funding_sources;
|
$this->all_funding_sources = $all_funding_sources;
|
||||||
|
$this->need_shipping = $need_shipping;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,6 +264,7 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'scriptData' => $script_data,
|
'scriptData' => $script_data,
|
||||||
|
'needShipping' => $this->need_shipping,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1005,19 +1005,19 @@
|
||||||
"@jridgewell/resolve-uri" "3.1.0"
|
"@jridgewell/resolve-uri" "3.1.0"
|
||||||
"@jridgewell/sourcemap-codec" "1.4.14"
|
"@jridgewell/sourcemap-codec" "1.4.14"
|
||||||
|
|
||||||
"@paypal/paypal-js@^8.0.5":
|
"@paypal/paypal-js@^8.1.0":
|
||||||
version "8.0.5"
|
version "8.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@paypal/paypal-js/-/paypal-js-8.0.5.tgz#77bc461b4d1e5a2c6f081269e3ef0b2e3331a68c"
|
resolved "https://registry.yarnpkg.com/@paypal/paypal-js/-/paypal-js-8.1.0.tgz#4e7d10e0a0b4164985029cfdac748e5694d117e9"
|
||||||
integrity sha512-yQNV7rOILeaVCNU4aVDRPqEnbIlzfxgQfFsxzsBuZW1ouqRD/4kYBWJDzczCiscSr2xOeA/Pkm7e3a9fRfnuMQ==
|
integrity sha512-f64bom5xYwmxyeKPJUFS/XpM0tXojQEgjRIADPqe1R9WmK+PFqL4SEkT85cGU0ZXLVx4EGbjwREHhqEOR+OstA==
|
||||||
dependencies:
|
dependencies:
|
||||||
promise-polyfill "^8.3.0"
|
promise-polyfill "^8.3.0"
|
||||||
|
|
||||||
"@paypal/react-paypal-js@^8.3.0":
|
"@paypal/react-paypal-js@^8.5.0":
|
||||||
version "8.3.0"
|
version "8.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@paypal/react-paypal-js/-/react-paypal-js-8.3.0.tgz#a103080b752766b8ff59b8620887abf802e1a01b"
|
resolved "https://registry.yarnpkg.com/@paypal/react-paypal-js/-/react-paypal-js-8.5.0.tgz#cf17483202c8fa7a33dae86798d50a102705f182"
|
||||||
integrity sha512-SX17d2h1CMNFGI+wtjb329AEDaBR8Ziy2LCV076eDcY1Q0MFKRkfQ/v0HOAvZtk3sJoydRmYez2pq47BRblwqQ==
|
integrity sha512-YIAyLw4OiUoHHoUgXvibrBDdluzqnqVMGsJXyBcoOzlWHQIe5zhh8dgYezNNRXjXwy6t22YmPljjw7lr+eD9cw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@paypal/paypal-js" "^8.0.5"
|
"@paypal/paypal-js" "^8.1.0"
|
||||||
"@paypal/sdk-constants" "^1.0.122"
|
"@paypal/sdk-constants" "^1.0.122"
|
||||||
|
|
||||||
"@paypal/sdk-constants@^1.0.122":
|
"@paypal/sdk-constants@^1.0.122":
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Renderer from './modules/Renderer/Renderer';
|
||||||
import ErrorHandler from './modules/ErrorHandler';
|
import ErrorHandler from './modules/ErrorHandler';
|
||||||
import HostedFieldsRenderer from './modules/Renderer/HostedFieldsRenderer';
|
import HostedFieldsRenderer from './modules/Renderer/HostedFieldsRenderer';
|
||||||
import CardFieldsRenderer from './modules/Renderer/CardFieldsRenderer';
|
import CardFieldsRenderer from './modules/Renderer/CardFieldsRenderer';
|
||||||
|
import CardFieldsFreeTrialRenderer from './modules/Renderer/CardFieldsFreeTrialRenderer';
|
||||||
import MessageRenderer from './modules/Renderer/MessageRenderer';
|
import MessageRenderer from './modules/Renderer/MessageRenderer';
|
||||||
import Spinner from './modules/Helper/Spinner';
|
import Spinner from './modules/Helper/Spinner';
|
||||||
import {
|
import {
|
||||||
|
@ -215,6 +216,16 @@ const bootstrap = () => {
|
||||||
spinner
|
spinner
|
||||||
);
|
);
|
||||||
if ( typeof paypal.CardFields !== 'undefined' ) {
|
if ( typeof paypal.CardFields !== 'undefined' ) {
|
||||||
|
if (
|
||||||
|
PayPalCommerceGateway.is_free_trial_cart &&
|
||||||
|
PayPalCommerceGateway.user?.has_wc_card_payment_tokens !== true
|
||||||
|
) {
|
||||||
|
creditCardRenderer = new CardFieldsFreeTrialRenderer(
|
||||||
|
PayPalCommerceGateway,
|
||||||
|
errorHandler,
|
||||||
|
spinner
|
||||||
|
);
|
||||||
|
} else {
|
||||||
creditCardRenderer = new CardFieldsRenderer(
|
creditCardRenderer = new CardFieldsRenderer(
|
||||||
PayPalCommerceGateway,
|
PayPalCommerceGateway,
|
||||||
errorHandler,
|
errorHandler,
|
||||||
|
@ -222,6 +233,7 @@ const bootstrap = () => {
|
||||||
onCardFieldsBeforeSubmit
|
onCardFieldsBeforeSubmit
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const renderer = new Renderer(
|
const renderer = new Renderer(
|
||||||
creditCardRenderer,
|
creditCardRenderer,
|
||||||
|
|
|
@ -173,61 +173,6 @@ class CheckoutActionHandler {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
addPaymentMethodConfiguration() {
|
|
||||||
return {
|
|
||||||
createVaultSetupToken: async () => {
|
|
||||||
const response = await fetch(
|
|
||||||
this.config.ajax.create_setup_token.endpoint,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify( {
|
|
||||||
nonce: this.config.ajax.create_setup_token.nonce,
|
|
||||||
} ),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
if ( result.data.id ) {
|
|
||||||
return result.data.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error( result );
|
|
||||||
},
|
|
||||||
onApprove: async ( { vaultSetupToken } ) => {
|
|
||||||
const response = await fetch(
|
|
||||||
this.config.ajax.create_payment_token_for_guest.endpoint,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify( {
|
|
||||||
nonce: this.config.ajax
|
|
||||||
.create_payment_token_for_guest.nonce,
|
|
||||||
vault_setup_token: vaultSetupToken,
|
|
||||||
} ),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
if ( result.success === true ) {
|
|
||||||
document.querySelector( '#place_order' ).click();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error( result );
|
|
||||||
},
|
|
||||||
onError: ( error ) => {
|
|
||||||
console.error( error );
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CheckoutActionHandler;
|
export default CheckoutActionHandler;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* global PayPalCommerceGateway */
|
||||||
|
|
||||||
import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler';
|
import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler';
|
||||||
import { setVisible, setVisibleByClass } from '../Helper/Hiding';
|
import { setVisible, setVisibleByClass } from '../Helper/Hiding';
|
||||||
import {
|
import {
|
||||||
|
@ -7,6 +9,7 @@ import {
|
||||||
PaymentMethods,
|
PaymentMethods,
|
||||||
} from '../Helper/CheckoutMethodState';
|
} from '../Helper/CheckoutMethodState';
|
||||||
import BootstrapHelper from '../Helper/BootstrapHelper';
|
import BootstrapHelper from '../Helper/BootstrapHelper';
|
||||||
|
import { addPaymentMethodConfiguration } from '../../../../../ppcp-save-payment-methods/resources/js/Configuration';
|
||||||
import {
|
import {
|
||||||
ButtonEvents,
|
ButtonEvents,
|
||||||
dispatchButtonEvent,
|
dispatchButtonEvent,
|
||||||
|
@ -165,7 +168,7 @@ class CheckoutBootstap {
|
||||||
PayPalCommerceGateway.vault_v3_enabled
|
PayPalCommerceGateway.vault_v3_enabled
|
||||||
) {
|
) {
|
||||||
this.renderer.render(
|
this.renderer.render(
|
||||||
actionHandler.addPaymentMethodConfiguration(),
|
addPaymentMethodConfiguration( PayPalCommerceGateway ),
|
||||||
{},
|
{},
|
||||||
actionHandler.configuration()
|
actionHandler.configuration()
|
||||||
);
|
);
|
||||||
|
@ -196,12 +199,15 @@ class CheckoutBootstap {
|
||||||
);
|
);
|
||||||
const isGooglePayMethod =
|
const isGooglePayMethod =
|
||||||
currentPaymentMethod === PaymentMethods.GOOGLEPAY;
|
currentPaymentMethod === PaymentMethods.GOOGLEPAY;
|
||||||
|
const isApplePayMethod =
|
||||||
|
currentPaymentMethod === PaymentMethods.APPLEPAY;
|
||||||
const isSavedCard = isCard && isSavedCardSelected();
|
const isSavedCard = isCard && isSavedCardSelected();
|
||||||
const isNotOurGateway =
|
const isNotOurGateway =
|
||||||
! isPaypal &&
|
! isPaypal &&
|
||||||
! isCard &&
|
! isCard &&
|
||||||
! isSeparateButtonGateway &&
|
! isSeparateButtonGateway &&
|
||||||
! isGooglePayMethod;
|
! isGooglePayMethod &&
|
||||||
|
! isApplePayMethod;
|
||||||
const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;
|
const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;
|
||||||
const hasVaultedPaypal =
|
const hasVaultedPaypal =
|
||||||
PayPalCommerceGateway.vaulted_paypal_email !== '';
|
PayPalCommerceGateway.vaulted_paypal_email !== '';
|
||||||
|
@ -256,6 +262,8 @@ class CheckoutBootstap {
|
||||||
paymentMethod: currentPaymentMethod,
|
paymentMethod: currentPaymentMethod,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
setVisible( '#ppc-button-ppcp-applepay', isApplePayMethod );
|
||||||
|
|
||||||
document.body.dispatchEvent( new Event( 'ppcp_checkout_rendered' ) );
|
document.body.dispatchEvent( new Event( 'ppcp_checkout_rendered' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ export const PaymentMethods = {
|
||||||
OXXO: 'ppcp-oxxo-gateway',
|
OXXO: 'ppcp-oxxo-gateway',
|
||||||
CARD_BUTTON: 'ppcp-card-button-gateway',
|
CARD_BUTTON: 'ppcp-card-button-gateway',
|
||||||
GOOGLEPAY: 'ppcp-googlepay',
|
GOOGLEPAY: 'ppcp-googlepay',
|
||||||
|
APPLEPAY: 'ppcp-applepay',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { show } from '../Helper/Hiding';
|
||||||
|
import { renderFields } from '../../../../../ppcp-card-fields/resources/js/Render';
|
||||||
|
import {
|
||||||
|
addPaymentMethodConfiguration,
|
||||||
|
cardFieldsConfiguration,
|
||||||
|
} from '../../../../../ppcp-save-payment-methods/resources/js/Configuration';
|
||||||
|
|
||||||
|
class CardFieldsFreeTrialRenderer {
|
||||||
|
constructor( defaultConfig, errorHandler, spinner ) {
|
||||||
|
this.defaultConfig = defaultConfig;
|
||||||
|
this.errorHandler = errorHandler;
|
||||||
|
this.spinner = spinner;
|
||||||
|
}
|
||||||
|
|
||||||
|
render( wrapper, contextConfig ) {
|
||||||
|
if (
|
||||||
|
( this.defaultConfig.context !== 'checkout' &&
|
||||||
|
this.defaultConfig.context !== 'pay-now' ) ||
|
||||||
|
wrapper === null ||
|
||||||
|
document.querySelector( wrapper ) === null
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonSelector = wrapper + ' button';
|
||||||
|
|
||||||
|
const gateWayBox = document.querySelector(
|
||||||
|
'.payment_box.payment_method_ppcp-credit-card-gateway'
|
||||||
|
);
|
||||||
|
if ( ! gateWayBox ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldDisplayStyle = gateWayBox.style.display;
|
||||||
|
gateWayBox.style.display = 'block';
|
||||||
|
|
||||||
|
const hideDccGateway = document.querySelector( '#ppcp-hide-dcc' );
|
||||||
|
if ( hideDccGateway ) {
|
||||||
|
hideDccGateway.parentNode.removeChild( hideDccGateway );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.errorHandler.clear();
|
||||||
|
|
||||||
|
let cardFields = paypal.CardFields(
|
||||||
|
addPaymentMethodConfiguration( this.defaultConfig )
|
||||||
|
);
|
||||||
|
if ( this.defaultConfig.user.is_logged ) {
|
||||||
|
cardFields = paypal.CardFields(
|
||||||
|
cardFieldsConfiguration( this.defaultConfig, this.errorHandler )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cardFields.isEligible() ) {
|
||||||
|
renderFields( cardFields );
|
||||||
|
}
|
||||||
|
|
||||||
|
gateWayBox.style.display = oldDisplayStyle;
|
||||||
|
|
||||||
|
show( buttonSelector );
|
||||||
|
|
||||||
|
if ( this.defaultConfig.cart_contains_subscription ) {
|
||||||
|
const saveToAccount = document.querySelector(
|
||||||
|
'#wc-ppcp-credit-card-gateway-new-payment-method'
|
||||||
|
);
|
||||||
|
if ( saveToAccount ) {
|
||||||
|
saveToAccount.checked = true;
|
||||||
|
saveToAccount.disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector( buttonSelector )
|
||||||
|
?.addEventListener( 'click', ( event ) => {
|
||||||
|
event.preventDefault();
|
||||||
|
this.spinner.block();
|
||||||
|
this.errorHandler.clear();
|
||||||
|
|
||||||
|
cardFields.submit().catch( ( error ) => {
|
||||||
|
console.error( error );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
disableFields() {}
|
||||||
|
enableFields() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CardFieldsFreeTrialRenderer;
|
|
@ -1,5 +1,5 @@
|
||||||
import { show } from '../Helper/Hiding';
|
import { show } from '../Helper/Hiding';
|
||||||
import { cardFieldStyles } from '../Helper/CardFieldsHelper';
|
import { renderFields } from '../../../../../ppcp-card-fields/resources/js/Render';
|
||||||
|
|
||||||
class CardFieldsRenderer {
|
class CardFieldsRenderer {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -45,7 +45,7 @@ class CardFieldsRenderer {
|
||||||
hideDccGateway.parentNode.removeChild( hideDccGateway );
|
hideDccGateway.parentNode.removeChild( hideDccGateway );
|
||||||
}
|
}
|
||||||
|
|
||||||
const cardField = paypal.CardFields( {
|
const cardFields = paypal.CardFields( {
|
||||||
createOrder: contextConfig.createOrder,
|
createOrder: contextConfig.createOrder,
|
||||||
onApprove( data ) {
|
onApprove( data ) {
|
||||||
return contextConfig.onApprove( data );
|
return contextConfig.onApprove( data );
|
||||||
|
@ -56,79 +56,8 @@ class CardFieldsRenderer {
|
||||||
},
|
},
|
||||||
} );
|
} );
|
||||||
|
|
||||||
if ( cardField.isEligible() ) {
|
if ( cardFields.isEligible() ) {
|
||||||
const nameField = document.getElementById(
|
renderFields( cardFields );
|
||||||
'ppcp-credit-card-gateway-card-name'
|
|
||||||
);
|
|
||||||
if ( nameField ) {
|
|
||||||
const styles = cardFieldStyles( nameField );
|
|
||||||
const fieldOptions = {
|
|
||||||
style: { input: styles },
|
|
||||||
};
|
|
||||||
if ( nameField.getAttribute( 'placeholder' ) ) {
|
|
||||||
fieldOptions.placeholder =
|
|
||||||
nameField.getAttribute( 'placeholder' );
|
|
||||||
}
|
|
||||||
cardField
|
|
||||||
.NameField( fieldOptions )
|
|
||||||
.render( nameField.parentNode );
|
|
||||||
nameField.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
const numberField = document.getElementById(
|
|
||||||
'ppcp-credit-card-gateway-card-number'
|
|
||||||
);
|
|
||||||
if ( numberField ) {
|
|
||||||
const styles = cardFieldStyles( numberField );
|
|
||||||
const fieldOptions = {
|
|
||||||
style: { input: styles },
|
|
||||||
};
|
|
||||||
if ( numberField.getAttribute( 'placeholder' ) ) {
|
|
||||||
fieldOptions.placeholder =
|
|
||||||
numberField.getAttribute( 'placeholder' );
|
|
||||||
}
|
|
||||||
cardField
|
|
||||||
.NumberField( fieldOptions )
|
|
||||||
.render( numberField.parentNode );
|
|
||||||
numberField.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
const expiryField = document.getElementById(
|
|
||||||
'ppcp-credit-card-gateway-card-expiry'
|
|
||||||
);
|
|
||||||
if ( expiryField ) {
|
|
||||||
const styles = cardFieldStyles( expiryField );
|
|
||||||
const fieldOptions = {
|
|
||||||
style: { input: styles },
|
|
||||||
};
|
|
||||||
if ( expiryField.getAttribute( 'placeholder' ) ) {
|
|
||||||
fieldOptions.placeholder =
|
|
||||||
expiryField.getAttribute( 'placeholder' );
|
|
||||||
}
|
|
||||||
cardField
|
|
||||||
.ExpiryField( fieldOptions )
|
|
||||||
.render( expiryField.parentNode );
|
|
||||||
expiryField.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
const cvvField = document.getElementById(
|
|
||||||
'ppcp-credit-card-gateway-card-cvc'
|
|
||||||
);
|
|
||||||
if ( cvvField ) {
|
|
||||||
const styles = cardFieldStyles( cvvField );
|
|
||||||
const fieldOptions = {
|
|
||||||
style: { input: styles },
|
|
||||||
};
|
|
||||||
if ( cvvField.getAttribute( 'placeholder' ) ) {
|
|
||||||
fieldOptions.placeholder =
|
|
||||||
cvvField.getAttribute( 'placeholder' );
|
|
||||||
}
|
|
||||||
cardField
|
|
||||||
.CVVField( fieldOptions )
|
|
||||||
.render( cvvField.parentNode );
|
|
||||||
cvvField.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
document.dispatchEvent( new CustomEvent( 'hosted_fields_loaded' ) );
|
document.dispatchEvent( new CustomEvent( 'hosted_fields_loaded' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +98,7 @@ class CardFieldsRenderer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cardField.submit().catch( ( error ) => {
|
cardFields.submit().catch( ( error ) => {
|
||||||
this.spinner.unblock();
|
this.spinner.unblock();
|
||||||
console.error( error );
|
console.error( error );
|
||||||
this.errorHandler.message(
|
this.errorHandler.message(
|
||||||
|
|
|
@ -139,7 +139,7 @@ class Renderer {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check the condition and add the handler if needed
|
// Check the condition and add the handler if needed
|
||||||
if ( this.defaultSettings.should_handle_shipping_in_paypal ) {
|
if ( this.shouldEnableShippingCallback() ) {
|
||||||
options.onShippingOptionsChange = ( data, actions ) => {
|
options.onShippingOptionsChange = ( data, actions ) => {
|
||||||
let shippingOptionsChange =
|
let shippingOptionsChange =
|
||||||
! this.isVenmoButtonClickedWhenVaultingIsEnabled(
|
! this.isVenmoButtonClickedWhenVaultingIsEnabled(
|
||||||
|
@ -227,6 +227,12 @@ class Renderer {
|
||||||
return venmoButtonClicked && this.defaultSettings.vaultingEnabled;
|
return venmoButtonClicked && this.defaultSettings.vaultingEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
shouldEnableShippingCallback = () => {
|
||||||
|
console.log(this.defaultSettings.context, this.defaultSettings)
|
||||||
|
let needShipping = this.defaultSettings.needShipping || this.defaultSettings.context === 'product'
|
||||||
|
return this.defaultSettings.should_handle_shipping_in_paypal && needShipping
|
||||||
|
};
|
||||||
|
|
||||||
isAlreadyRendered( wrapper, fundingSource ) {
|
isAlreadyRendered( wrapper, fundingSource ) {
|
||||||
return this.renderedSources.has( wrapper + ( fundingSource ?? '' ) );
|
return this.renderedSources.has( wrapper + ( fundingSource ?? '' ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\Button\Assets;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use WC_Order;
|
use WC_Order;
|
||||||
|
use WC_Payment_Tokens;
|
||||||
use WC_Product;
|
use WC_Product;
|
||||||
use WC_Product_Variation;
|
use WC_Product_Variation;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
||||||
|
@ -50,6 +51,8 @@ use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
use WC_Shipping_Method;
|
||||||
|
use WC_Cart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SmartButton
|
* Class SmartButton
|
||||||
|
@ -1084,6 +1087,22 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
||||||
return apply_filters( 'woocommerce_paypal_payments_three_d_secure_contingency', $contingency );
|
return apply_filters( 'woocommerce_paypal_payments_three_d_secure_contingency', $contingency );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the current cart contains a product that requires physical shipping.
|
||||||
|
*
|
||||||
|
* @return bool True, if any cart item requires shipping.
|
||||||
|
*/
|
||||||
|
private function need_shipping() : bool {
|
||||||
|
/**
|
||||||
|
* Cart instance; might be null, esp. in customizer or in Block Editor.
|
||||||
|
*
|
||||||
|
* @var null|WC_Cart $cart
|
||||||
|
*/
|
||||||
|
$cart = WC()->cart;
|
||||||
|
|
||||||
|
return $cart && $cart->needs_shipping();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration for the smart buttons.
|
* The configuration for the smart buttons.
|
||||||
*
|
*
|
||||||
|
@ -1293,8 +1312,10 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
||||||
'funding_sources_without_redirect' => $this->funding_sources_without_redirect,
|
'funding_sources_without_redirect' => $this->funding_sources_without_redirect,
|
||||||
'user' => array(
|
'user' => array(
|
||||||
'is_logged' => is_user_logged_in(),
|
'is_logged' => is_user_logged_in(),
|
||||||
|
'has_wc_card_payment_tokens' => $this->user_has_wc_card_payment_tokens( get_current_user_id() ),
|
||||||
),
|
),
|
||||||
'should_handle_shipping_in_paypal' => $this->should_handle_shipping_in_paypal && ! $this->is_checkout(),
|
'should_handle_shipping_in_paypal' => $this->should_handle_shipping_in_paypal && ! $this->is_checkout(),
|
||||||
|
'needShipping' => $this->need_shipping(),
|
||||||
'vaultingEnabled' => $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' ),
|
'vaultingEnabled' => $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' ),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2132,4 +2153,19 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
||||||
return $location;
|
return $location;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the given user has WC card payment tokens.
|
||||||
|
*
|
||||||
|
* @param int $user_id The user ID.
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function user_has_wc_card_payment_tokens( int $user_id ): bool {
|
||||||
|
$tokens = WC_Payment_Tokens::get_customer_tokens( $user_id, CreditCardGateway::ID );
|
||||||
|
if ( $tokens ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,10 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\Button\Helper;
|
namespace WooCommerce\PayPalCommerce\Button\Helper;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use WC_Cart;
|
use WC_Cart;
|
||||||
|
use WC_Data_Exception;
|
||||||
use WC_Order;
|
use WC_Order;
|
||||||
use WC_Order_Item_Product;
|
use WC_Order_Item_Product;
|
||||||
use WC_Order_Item_Shipping;
|
use WC_Order_Item_Shipping;
|
||||||
|
@ -85,17 +87,24 @@ class WooCommerceOrderCreator {
|
||||||
throw new RuntimeException( 'Problem creating WC order.' );
|
throw new RuntimeException( 'Problem creating WC order.' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
$payer = $order->payer();
|
$payer = $order->payer();
|
||||||
$shipping = $order->purchase_units()[0]->shipping();
|
$shipping = $order->purchase_units()[0]->shipping();
|
||||||
|
|
||||||
$this->configure_payment_source( $wc_order );
|
$this->configure_payment_source( $wc_order );
|
||||||
$this->configure_customer( $wc_order );
|
$this->configure_customer( $wc_order );
|
||||||
$this->configure_line_items( $wc_order, $wc_cart, $payer, $shipping );
|
$this->configure_line_items( $wc_order, $wc_cart, $payer, $shipping );
|
||||||
$this->configure_shipping( $wc_order, $payer, $shipping );
|
$this->configure_shipping( $wc_order, $payer, $shipping, $wc_cart );
|
||||||
$this->configure_coupons( $wc_order, $wc_cart->get_applied_coupons() );
|
$this->configure_coupons( $wc_order, $wc_cart->get_applied_coupons() );
|
||||||
|
|
||||||
$wc_order->calculate_totals();
|
$wc_order->calculate_totals();
|
||||||
$wc_order->save();
|
$wc_order->save();
|
||||||
|
} catch ( Exception $exception ) {
|
||||||
|
$wc_order->delete( true );
|
||||||
|
throw new RuntimeException( 'Failed to create WooCommerce order: ' . $exception->getMessage() );
|
||||||
|
}
|
||||||
|
|
||||||
|
do_action( 'woocommerce_paypal_payments_shipping_callback_woocommerce_order_created', $wc_order, $wc_cart );
|
||||||
|
|
||||||
return $wc_order;
|
return $wc_order;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +162,7 @@ class WooCommerceOrderCreator {
|
||||||
$item->set_total( $subscription_total );
|
$item->set_total( $subscription_total );
|
||||||
|
|
||||||
$subscription->add_product( $product );
|
$subscription->add_product( $product );
|
||||||
$this->configure_shipping( $subscription, $payer, $shipping );
|
$this->configure_shipping( $subscription, $payer, $shipping, $wc_cart );
|
||||||
$this->configure_payment_source( $subscription );
|
$this->configure_payment_source( $subscription );
|
||||||
$this->configure_coupons( $subscription, $wc_cart->get_applied_coupons() );
|
$this->configure_coupons( $subscription, $wc_cart->get_applied_coupons() );
|
||||||
|
|
||||||
|
@ -178,9 +187,11 @@ class WooCommerceOrderCreator {
|
||||||
* @param WC_Order $wc_order The WC order.
|
* @param WC_Order $wc_order The WC order.
|
||||||
* @param Payer|null $payer The payer.
|
* @param Payer|null $payer The payer.
|
||||||
* @param Shipping|null $shipping The shipping.
|
* @param Shipping|null $shipping The shipping.
|
||||||
|
* @param WC_Cart $wc_cart The Cart.
|
||||||
* @return void
|
* @return void
|
||||||
|
* @throws WC_Data_Exception|RuntimeException When failing to configure shipping.
|
||||||
*/
|
*/
|
||||||
protected function configure_shipping( WC_Order $wc_order, ?Payer $payer, ?Shipping $shipping ): void {
|
protected function configure_shipping( WC_Order $wc_order, ?Payer $payer, ?Shipping $shipping, WC_Cart $wc_cart ): void {
|
||||||
$shipping_address = null;
|
$shipping_address = null;
|
||||||
$billing_address = null;
|
$billing_address = null;
|
||||||
$shipping_options = null;
|
$shipping_options = null;
|
||||||
|
@ -218,6 +229,10 @@ class WooCommerceOrderCreator {
|
||||||
$shipping_options = $shipping->options()[0] ?? '';
|
$shipping_options = $shipping->options()[0] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $wc_cart->needs_shipping() && empty( $shipping_options ) ) {
|
||||||
|
throw new RuntimeException( 'No shipping method has been selected.' );
|
||||||
|
}
|
||||||
|
|
||||||
if ( $shipping_address ) {
|
if ( $shipping_address ) {
|
||||||
$wc_order->set_shipping_address( $shipping_address );
|
$wc_order->set_shipping_address( $shipping_address );
|
||||||
}
|
}
|
||||||
|
|
31
modules/ppcp-card-fields/package.json
Normal file
31
modules/ppcp-card-fields/package.json
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "ppcp-card-fields",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"browserslist": [
|
||||||
|
"> 0.5%",
|
||||||
|
"Safari >= 8",
|
||||||
|
"Chrome >= 41",
|
||||||
|
"Firefox >= 43",
|
||||||
|
"Edge >= 14"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": "^3.25.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.19",
|
||||||
|
"@babel/preset-env": "^7.19",
|
||||||
|
"babel-loader": "^8.2",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"file-loader": "^6.2.0",
|
||||||
|
"sass": "^1.42.1",
|
||||||
|
"sass-loader": "^12.1.0",
|
||||||
|
"webpack": "^5.76",
|
||||||
|
"webpack-cli": "^4.10"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",
|
||||||
|
"watch": "cross-env BABEL_ENV=default NODE_ENV=production webpack --watch",
|
||||||
|
"dev": "cross-env BABEL_ENV=default webpack --watch"
|
||||||
|
}
|
||||||
|
}
|
47
modules/ppcp-card-fields/resources/js/Render.js
Normal file
47
modules/ppcp-card-fields/resources/js/Render.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { cardFieldStyles } from './CardFieldsHelper';
|
||||||
|
|
||||||
|
export function renderFields( cardFields ) {
|
||||||
|
const nameField = document.getElementById(
|
||||||
|
'ppcp-credit-card-gateway-card-name'
|
||||||
|
);
|
||||||
|
if ( nameField && nameField.hidden !== true ) {
|
||||||
|
const styles = cardFieldStyles( nameField );
|
||||||
|
cardFields
|
||||||
|
.NameField( { style: { input: styles } } )
|
||||||
|
.render( nameField.parentNode );
|
||||||
|
nameField.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const numberField = document.getElementById(
|
||||||
|
'ppcp-credit-card-gateway-card-number'
|
||||||
|
);
|
||||||
|
if ( numberField && numberField.hidden !== true ) {
|
||||||
|
const styles = cardFieldStyles( numberField );
|
||||||
|
cardFields
|
||||||
|
.NumberField( { style: { input: styles } } )
|
||||||
|
.render( numberField.parentNode );
|
||||||
|
numberField.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const expiryField = document.getElementById(
|
||||||
|
'ppcp-credit-card-gateway-card-expiry'
|
||||||
|
);
|
||||||
|
if ( expiryField && expiryField.hidden !== true ) {
|
||||||
|
const styles = cardFieldStyles( expiryField );
|
||||||
|
cardFields
|
||||||
|
.ExpiryField( { style: { input: styles } } )
|
||||||
|
.render( expiryField.parentNode );
|
||||||
|
expiryField.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cvvField = document.getElementById(
|
||||||
|
'ppcp-credit-card-gateway-card-cvc'
|
||||||
|
);
|
||||||
|
if ( cvvField && cvvField.hidden !== true ) {
|
||||||
|
const styles = cardFieldStyles( cvvField );
|
||||||
|
cardFields
|
||||||
|
.CVVField( { style: { input: styles } } )
|
||||||
|
.render( cvvField.parentNode );
|
||||||
|
cvvField.hidden = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,795 +17,51 @@ return array(
|
||||||
$save_payment_methods_applies = $container->get( 'card-fields.helpers.save-payment-methods-applies' );
|
$save_payment_methods_applies = $container->get( 'card-fields.helpers.save-payment-methods-applies' );
|
||||||
assert( $save_payment_methods_applies instanceof CardFieldsApplies );
|
assert( $save_payment_methods_applies instanceof CardFieldsApplies );
|
||||||
|
|
||||||
return $save_payment_methods_applies->for_country_currency();
|
return $save_payment_methods_applies->for_country();
|
||||||
},
|
},
|
||||||
'card-fields.helpers.save-payment-methods-applies' => static function ( ContainerInterface $container ) : CardFieldsApplies {
|
'card-fields.helpers.save-payment-methods-applies' => static function ( ContainerInterface $container ) : CardFieldsApplies {
|
||||||
return new CardFieldsApplies(
|
return new CardFieldsApplies(
|
||||||
$container->get( 'card-fields.supported-country-currency-matrix' ),
|
$container->get( 'card-fields.supported-country-matrix' ),
|
||||||
$container->get( 'api.shop.currency' ),
|
|
||||||
$container->get( 'api.shop.country' )
|
$container->get( 'api.shop.country' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'card-fields.supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array {
|
'card-fields.supported-country-matrix' => static function ( ContainerInterface $container ) : array {
|
||||||
return apply_filters(
|
return apply_filters(
|
||||||
'woocommerce_paypal_payments_card_fields_supported_country_currency_matrix',
|
'woocommerce_paypal_payments_card_fields_supported_country_matrix',
|
||||||
array(
|
array(
|
||||||
'AU' => array(
|
'AU',
|
||||||
'AUD',
|
'AT',
|
||||||
'BRL',
|
'BE',
|
||||||
'CAD',
|
'BG',
|
||||||
'CHF',
|
'CA',
|
||||||
'CZK',
|
'CN',
|
||||||
'DKK',
|
'CY',
|
||||||
'EUR',
|
'CZ',
|
||||||
'GBP',
|
'DK',
|
||||||
'HKD',
|
'EE',
|
||||||
'HUF',
|
'FI',
|
||||||
'ILS',
|
'FR',
|
||||||
'JPY',
|
'DE',
|
||||||
'MXN',
|
'GR',
|
||||||
'NOK',
|
'HU',
|
||||||
'NZD',
|
'IE',
|
||||||
'PHP',
|
'IT',
|
||||||
'PLN',
|
'LV',
|
||||||
'SEK',
|
'LI',
|
||||||
'SGD',
|
'LT',
|
||||||
'THB',
|
'LU',
|
||||||
'TWD',
|
'MT',
|
||||||
'USD',
|
'NL',
|
||||||
),
|
'PL',
|
||||||
'AT' => array(
|
'PT',
|
||||||
'AUD',
|
'RO',
|
||||||
'BRL',
|
'SK',
|
||||||
'CAD',
|
'SI',
|
||||||
'CHF',
|
'ES',
|
||||||
'CZK',
|
'SE',
|
||||||
'DKK',
|
'GB',
|
||||||
'EUR',
|
'US',
|
||||||
'GBP',
|
'NO',
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'BE' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'BG' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'CA' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'CN' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'CY' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'CZ' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'DK' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'EE' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'FI' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'FR' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'DE' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'GR' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'HU' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'IE' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'IT' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'LV' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'LI' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'LT' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'LU' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'MT' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'NL' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'PL' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'PT' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'RO' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'SK' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'SI' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'ES' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'SE' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'GB' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'US' => array(
|
|
||||||
'AUD',
|
|
||||||
'CAD',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'JPY',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
'NO' => array(
|
|
||||||
'AUD',
|
|
||||||
'BRL',
|
|
||||||
'CAD',
|
|
||||||
'CHF',
|
|
||||||
'CZK',
|
|
||||||
'DKK',
|
|
||||||
'EUR',
|
|
||||||
'GBP',
|
|
||||||
'HKD',
|
|
||||||
'HUF',
|
|
||||||
'ILS',
|
|
||||||
'JPY',
|
|
||||||
'MXN',
|
|
||||||
'NOK',
|
|
||||||
'NZD',
|
|
||||||
'PHP',
|
|
||||||
'PLN',
|
|
||||||
'SEK',
|
|
||||||
'SGD',
|
|
||||||
'THB',
|
|
||||||
'TWD',
|
|
||||||
'USD',
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Service for checking whether Card Fields can be used in the current country and the current currency.
|
* Service for checking whether Card Fields can be used in the current country.
|
||||||
*
|
*
|
||||||
* @package WooCommerce\PayPalCommerce\CardFields\Helper
|
* @package WooCommerce\PayPalCommerce\CardFields\Helper
|
||||||
*/
|
*/
|
||||||
|
@ -15,18 +15,11 @@ namespace WooCommerce\PayPalCommerce\CardFields\Helper;
|
||||||
class CardFieldsApplies {
|
class CardFieldsApplies {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The matrix which countries and currency combinations can be used.
|
* The matrix which countries can be used.
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $allowed_country_currency_matrix;
|
private $allowed_country_matrix;
|
||||||
|
|
||||||
/**
|
|
||||||
* 3-letter currency code of the shop.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private $currency;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2-letter country code of the shop.
|
* 2-letter country code of the shop.
|
||||||
|
@ -38,29 +31,23 @@ class CardFieldsApplies {
|
||||||
/**
|
/**
|
||||||
* CardFieldsApplies constructor.
|
* CardFieldsApplies constructor.
|
||||||
*
|
*
|
||||||
* @param array $allowed_country_currency_matrix The matrix which countries and currency combinations can be used.
|
* @param array $allowed_country_matrix The matrix which countries can be used.
|
||||||
* @param string $currency 3-letter currency code of the shop.
|
|
||||||
* @param string $country 2-letter country code of the shop.
|
* @param string $country 2-letter country code of the shop.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
array $allowed_country_currency_matrix,
|
array $allowed_country_matrix,
|
||||||
string $currency,
|
|
||||||
string $country
|
string $country
|
||||||
) {
|
) {
|
||||||
$this->allowed_country_currency_matrix = $allowed_country_currency_matrix;
|
$this->allowed_country_matrix = $allowed_country_matrix;
|
||||||
$this->currency = $currency;
|
|
||||||
$this->country = $country;
|
$this->country = $country;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether Card Fields can be used in the current country and the current currency.
|
* Returns whether Card Fields can be used in the current country.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function for_country_currency(): bool {
|
public function for_country(): bool {
|
||||||
if ( ! in_array( $this->country, array_keys( $this->allowed_country_currency_matrix ), true ) ) {
|
return in_array( $this->country, $this->allowed_country_matrix, true );
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return in_array( $this->currency, $this->allowed_country_currency_matrix[ $this->country ], true );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
38
modules/ppcp-card-fields/webpack.config.js
Normal file
38
modules/ppcp-card-fields/webpack.config.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
const path = require( 'path' );
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
||||||
|
mode: isProduction ? 'production' : 'development',
|
||||||
|
target: 'web',
|
||||||
|
entry: {
|
||||||
|
render: path.resolve( './resources/js/Render.js' ),
|
||||||
|
helper: path.resolve( './resources/js/CardFieldsHelper.js' ),
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.resolve( __dirname, 'assets/' ),
|
||||||
|
filename: 'js/[name].js',
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'babel-loader',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.scss$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'file-loader',
|
||||||
|
options: {
|
||||||
|
name: 'css/[name].css',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ loader: 'sass-loader' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
2194
modules/ppcp-card-fields/yarn.lock
Normal file
2194
modules/ppcp-card-fields/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
|
@ -15,6 +15,8 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
||||||
);
|
);
|
||||||
const wcShipmentTaxBuyLabelButtonSelector =
|
const wcShipmentTaxBuyLabelButtonSelector =
|
||||||
'.components-modal__screen-overlay .label-purchase-modal__sidebar .purchase-section button.components-button';
|
'.components-modal__screen-overlay .label-purchase-modal__sidebar .purchase-section button.components-button';
|
||||||
|
const dhlGenerateLabelButton =
|
||||||
|
document.getElementById( 'dhl-label-button' );
|
||||||
|
|
||||||
const toggleLoaderVisibility = function () {
|
const toggleLoaderVisibility = function () {
|
||||||
const loader = document.querySelector( '.ppcp-tracking-loader' );
|
const loader = document.querySelector( '.ppcp-tracking-loader' );
|
||||||
|
@ -44,6 +46,20 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const waitForButtonRemoval = function ( button ) {
|
||||||
|
if ( document.body.contains( button ) ) {
|
||||||
|
setTimeout( () => waitForButtonRemoval( button ), 100 );
|
||||||
|
} else {
|
||||||
|
jQuery( orderTrackingContainerSelector ).load(
|
||||||
|
loadLocation,
|
||||||
|
'',
|
||||||
|
function () {
|
||||||
|
toggleLoaderVisibility();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
gzdSyncEnabled &&
|
gzdSyncEnabled &&
|
||||||
typeof gzdSaveButton !== 'undefined' &&
|
typeof gzdSaveButton !== 'undefined' &&
|
||||||
|
@ -66,10 +82,30 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof dhlGenerateLabelButton !== 'undefined' &&
|
||||||
|
dhlGenerateLabelButton != null
|
||||||
|
) {
|
||||||
|
dhlGenerateLabelButton.addEventListener( 'click', function ( event ) {
|
||||||
|
toggleLoaderVisibility();
|
||||||
|
waitForButtonRemoval( dhlGenerateLabelButton );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
jQuery( document ).on(
|
||||||
|
'mouseover mouseout',
|
||||||
|
'#dhl_delete_label',
|
||||||
|
function ( event ) {
|
||||||
|
jQuery( '#ppcp-shipment-status' )
|
||||||
|
.val( 'CANCELLED' )
|
||||||
|
.trigger( 'change' );
|
||||||
|
document.querySelector( '.update_shipment' ).click();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
wcShippingTaxSyncEnabled &&
|
wcShippingTaxSyncEnabled &&
|
||||||
typeof wcShippingTaxSyncEnabled !== 'undefined' &&
|
typeof wcShippingTaxSyncEnabled !== 'undefined'
|
||||||
wcShippingTaxSyncEnabled != null
|
|
||||||
) {
|
) {
|
||||||
document.addEventListener( 'click', function ( event ) {
|
document.addEventListener( 'click', function ( event ) {
|
||||||
const wcShipmentTaxBuyLabelButton = event.target.closest(
|
const wcShipmentTaxBuyLabelButton = event.target.closest(
|
||||||
|
|
|
@ -77,6 +77,9 @@ return array(
|
||||||
'compat.ywot.is_supported_plugin_version_active' => function (): bool {
|
'compat.ywot.is_supported_plugin_version_active' => function (): bool {
|
||||||
return function_exists( 'yith_ywot_init' );
|
return function_exists( 'yith_ywot_init' );
|
||||||
},
|
},
|
||||||
|
'compat.dhl.is_supported_plugin_version_active' => function (): bool {
|
||||||
|
return function_exists( 'PR_DHL' );
|
||||||
|
},
|
||||||
'compat.shipstation.is_supported_plugin_version_active' => function (): bool {
|
'compat.shipstation.is_supported_plugin_version_active' => function (): bool {
|
||||||
return function_exists( 'woocommerce_shipstation_init' );
|
return function_exists( 'woocommerce_shipstation_init' );
|
||||||
},
|
},
|
||||||
|
@ -86,6 +89,9 @@ return array(
|
||||||
'compat.nyp.is_supported_plugin_version_active' => function (): bool {
|
'compat.nyp.is_supported_plugin_version_active' => function (): bool {
|
||||||
return function_exists( 'wc_nyp_init' );
|
return function_exists( 'wc_nyp_init' );
|
||||||
},
|
},
|
||||||
|
'compat.wc_bookings.is_supported_plugin_version_active' => function (): bool {
|
||||||
|
return class_exists( 'WC_Bookings' );
|
||||||
|
},
|
||||||
|
|
||||||
'compat.module.url' => static function ( ContainerInterface $container ): string {
|
'compat.module.url' => static function ( ContainerInterface $container ): string {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,6 +9,11 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\Compat;
|
namespace WooCommerce\PayPalCommerce\Compat;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use WC_Cart;
|
||||||
|
use WC_Order;
|
||||||
|
use WC_Order_Item_Product;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||||
|
@ -61,6 +66,13 @@ class CompatModule implements ModuleInterface {
|
||||||
if ( $is_nyp_active ) {
|
if ( $is_nyp_active ) {
|
||||||
$this->initialize_nyp_compat_layer();
|
$this->initialize_nyp_compat_layer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||||
|
|
||||||
|
$is_wc_bookings_active = $c->get( 'compat.wc_bookings.is_supported_plugin_version_active' );
|
||||||
|
if ( $is_wc_bookings_active ) {
|
||||||
|
$this->initialize_wc_bookings_compat_layer( $logger );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -412,4 +424,62 @@ class CompatModule implements ModuleInterface {
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the compatibility layer for WooCommerce Bookings plugin.
|
||||||
|
*
|
||||||
|
* @param LoggerInterface $logger The logger.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function initialize_wc_bookings_compat_layer( LoggerInterface $logger ): void {
|
||||||
|
add_action(
|
||||||
|
'woocommerce_paypal_payments_shipping_callback_woocommerce_order_created',
|
||||||
|
static function ( WC_Order $wc_order, WC_Cart $wc_cart ) use ( $logger ): void {
|
||||||
|
try {
|
||||||
|
$cart_contents = $wc_cart->get_cart();
|
||||||
|
foreach ( $cart_contents as $cart_item ) {
|
||||||
|
if ( empty( $cart_item['booking'] ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( $wc_order->get_items() as $wc_order_item ) {
|
||||||
|
if ( ! is_a( $wc_order_item, WC_Order_Item_Product::class ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$product_id = $wc_order_item->get_variation_id() ?: $wc_order_item->get_product_id();
|
||||||
|
$product = wc_get_product( $product_id );
|
||||||
|
|
||||||
|
if ( ! is_wc_booking_product( $product ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$booking_data = array(
|
||||||
|
'cost' => $cart_item['booking']['_cost'] ?? 0,
|
||||||
|
'start_date' => $cart_item['booking']['_start_date'] ?? 0,
|
||||||
|
'end_date' => $cart_item['booking']['_end_date'] ?? 0,
|
||||||
|
'all_day' => $cart_item['booking']['_all_day'] ?? 0,
|
||||||
|
'local_timezone' => $cart_item['booking']['_local_timezone'] ?? 0,
|
||||||
|
'order_item_id' => $wc_order_item->get_id(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( isset( $cart_item['booking']['_resource_id'] ) ) {
|
||||||
|
$booking_data['resource_id'] = $cart_item['booking']['_resource_id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isset( $cart_item['booking']['_persons'] ) ) {
|
||||||
|
$booking_data['persons'] = $cart_item['booking']['_persons'];
|
||||||
|
}
|
||||||
|
|
||||||
|
create_wc_booking( $cart_item['product_id'], $booking_data, 'unpaid' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch ( Exception $exception ) {
|
||||||
|
$logger->warning( 'Failed to create booking for WooCommerce Bookings plugin: ' . $exception->getMessage() );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
10,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,7 @@ return array(
|
||||||
'classes' => array( 'ppcp-field-indent' ),
|
'classes' => array( 'ppcp-field-indent' ),
|
||||||
'class' => array(),
|
'class' => array(),
|
||||||
'input_class' => array( 'wc-enhanced-select' ),
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
'default' => 'pay',
|
'default' => 'plain',
|
||||||
'options' => PropertiesDictionary::button_types(),
|
'options' => PropertiesDictionary::button_types(),
|
||||||
'screens' => array( State::STATE_ONBOARDED ),
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
'gateway' => 'dcc',
|
'gateway' => 'dcc',
|
||||||
|
|
|
@ -92,6 +92,11 @@ class GooglePayGateway extends WC_Payment_Gateway {
|
||||||
) {
|
) {
|
||||||
$this->id = self::ID;
|
$this->id = self::ID;
|
||||||
|
|
||||||
|
$this->supports = array(
|
||||||
|
'refunds',
|
||||||
|
'products',
|
||||||
|
);
|
||||||
|
|
||||||
$this->method_title = __( 'Google Pay (via PayPal) ', 'woocommerce-paypal-payments' );
|
$this->method_title = __( 'Google Pay (via PayPal) ', 'woocommerce-paypal-payments' );
|
||||||
$this->method_description = __( 'The separate payment gateway with the Google Pay button. If disabled, the button is included in the PayPal gateway.', 'woocommerce-paypal-payments' );
|
$this->method_description = __( 'The separate payment gateway with the Google Pay button. If disabled, the button is included in the PayPal gateway.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
|
14
modules/ppcp-local-alternative-payment-methods/.babelrc
Normal file
14
modules/ppcp-local-alternative-payment-methods/.babelrc
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
"@babel/preset-env",
|
||||||
|
{
|
||||||
|
"useBuiltIns": "usage",
|
||||||
|
"corejs": "3.25.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@babel/preset-react"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
3
modules/ppcp-local-alternative-payment-methods/.gitignore
vendored
Normal file
3
modules/ppcp-local-alternative-payment-methods/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
node_modules
|
||||||
|
assets/js
|
||||||
|
assets/css
|
17
modules/ppcp-local-alternative-payment-methods/composer.json
Normal file
17
modules/ppcp-local-alternative-payment-methods/composer.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "woocommerce/ppcp-local-alternative-payment-methods",
|
||||||
|
"type": "dhii-mod",
|
||||||
|
"description": "Country based Alternative Payment Methods module",
|
||||||
|
"license": "GPL-2.0",
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2 | ^8.0",
|
||||||
|
"dhii/module-interface": "^0.3.0-alpha1"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"WooCommerce\\PayPalCommerce\\LocalAlternativePaymentMethods\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"prefer-stable": true
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The local alternative payment methods module extensions.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
return array();
|
16
modules/ppcp-local-alternative-payment-methods/module.php
Normal file
16
modules/ppcp-local-alternative-payment-methods/module.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The local alternative payment methods module.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||||
|
|
||||||
|
return static function (): ModuleInterface {
|
||||||
|
return new LocalAlternativePaymentMethodsModule();
|
||||||
|
};
|
33
modules/ppcp-local-alternative-payment-methods/package.json
Normal file
33
modules/ppcp-local-alternative-payment-methods/package.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "ppcp-local-alternative-payment-methods",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"browserslist": [
|
||||||
|
"> 0.5%",
|
||||||
|
"Safari >= 8",
|
||||||
|
"Chrome >= 41",
|
||||||
|
"Firefox >= 43",
|
||||||
|
"Edge >= 14"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": "^3.25.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.19",
|
||||||
|
"@babel/preset-env": "^7.19",
|
||||||
|
"@babel/preset-react": "^7.18.6",
|
||||||
|
"@woocommerce/dependency-extraction-webpack-plugin": "2.2.0",
|
||||||
|
"babel-loader": "^8.2",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"file-loader": "^6.2.0",
|
||||||
|
"sass": "^1.42.1",
|
||||||
|
"sass-loader": "^12.1.0",
|
||||||
|
"webpack": "^5.76",
|
||||||
|
"webpack-cli": "^4.10"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",
|
||||||
|
"watch": "cross-env BABEL_ENV=default NODE_ENV=production webpack --watch",
|
||||||
|
"dev": "cross-env BABEL_ENV=default webpack --watch"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
export function APM( { config, components } ) {
|
||||||
|
const { PaymentMethodIcons } = components;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PaymentMethodIcons icons={ [ config.icon ] } align="right" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||||
|
import { APM } from './apm-block';
|
||||||
|
|
||||||
|
const config = wc.wcSettings.getSetting( 'ppcp-bancontact_data' );
|
||||||
|
|
||||||
|
registerPaymentMethod( {
|
||||||
|
name: config.id,
|
||||||
|
label: <div dangerouslySetInnerHTML={ { __html: config.title } } />,
|
||||||
|
content: <APM config={ config } />,
|
||||||
|
edit: <div></div>,
|
||||||
|
ariaLabel: config.title,
|
||||||
|
canMakePayment: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
supports: {
|
||||||
|
features: config.supports,
|
||||||
|
},
|
||||||
|
} );
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||||
|
import { APM } from './apm-block';
|
||||||
|
|
||||||
|
const config = wc.wcSettings.getSetting( 'ppcp-blik_data' );
|
||||||
|
|
||||||
|
registerPaymentMethod( {
|
||||||
|
name: config.id,
|
||||||
|
label: <div dangerouslySetInnerHTML={ { __html: config.title } } />,
|
||||||
|
content: <APM config={ config } />,
|
||||||
|
edit: <div></div>,
|
||||||
|
ariaLabel: config.title,
|
||||||
|
canMakePayment: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
supports: {
|
||||||
|
features: config.supports,
|
||||||
|
},
|
||||||
|
} );
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||||
|
import { APM } from './apm-block';
|
||||||
|
|
||||||
|
const config = wc.wcSettings.getSetting( 'ppcp-eps_data' );
|
||||||
|
|
||||||
|
registerPaymentMethod( {
|
||||||
|
name: config.id,
|
||||||
|
label: <div dangerouslySetInnerHTML={ { __html: config.title } } />,
|
||||||
|
content: <APM config={ config } />,
|
||||||
|
edit: <div></div>,
|
||||||
|
ariaLabel: config.title,
|
||||||
|
canMakePayment: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
supports: {
|
||||||
|
features: config.supports,
|
||||||
|
},
|
||||||
|
} );
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||||
|
import { APM } from './apm-block';
|
||||||
|
|
||||||
|
const config = wc.wcSettings.getSetting( 'ppcp-ideal_data' );
|
||||||
|
|
||||||
|
registerPaymentMethod( {
|
||||||
|
name: config.id,
|
||||||
|
label: <div dangerouslySetInnerHTML={ { __html: config.title } } />,
|
||||||
|
content: <APM config={ config } />,
|
||||||
|
edit: <div></div>,
|
||||||
|
ariaLabel: config.title,
|
||||||
|
canMakePayment: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
supports: {
|
||||||
|
features: config.supports,
|
||||||
|
},
|
||||||
|
} );
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||||
|
import { APM } from './apm-block';
|
||||||
|
|
||||||
|
const config = wc.wcSettings.getSetting( 'ppcp-mybank_data' );
|
||||||
|
|
||||||
|
registerPaymentMethod( {
|
||||||
|
name: config.id,
|
||||||
|
label: <div dangerouslySetInnerHTML={ { __html: config.title } } />,
|
||||||
|
content: <APM config={ config } />,
|
||||||
|
edit: <div></div>,
|
||||||
|
ariaLabel: config.title,
|
||||||
|
canMakePayment: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
supports: {
|
||||||
|
features: config.supports,
|
||||||
|
},
|
||||||
|
} );
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||||
|
import { APM } from './apm-block';
|
||||||
|
|
||||||
|
const config = wc.wcSettings.getSetting( 'ppcp-p24_data' );
|
||||||
|
|
||||||
|
registerPaymentMethod( {
|
||||||
|
name: config.id,
|
||||||
|
label: <div dangerouslySetInnerHTML={ { __html: config.title } } />,
|
||||||
|
content: <APM config={ config } />,
|
||||||
|
edit: <div></div>,
|
||||||
|
ariaLabel: config.title,
|
||||||
|
canMakePayment: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
supports: {
|
||||||
|
features: config.supports,
|
||||||
|
},
|
||||||
|
} );
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||||
|
import { APM } from './apm-block';
|
||||||
|
|
||||||
|
const config = wc.wcSettings.getSetting( 'ppcp-trustly_data' );
|
||||||
|
|
||||||
|
registerPaymentMethod( {
|
||||||
|
name: config.id,
|
||||||
|
label: <div dangerouslySetInnerHTML={ { __html: config.title } } />,
|
||||||
|
content: <APM config={ config } />,
|
||||||
|
edit: <div></div>,
|
||||||
|
ariaLabel: config.title,
|
||||||
|
canMakePayment: () => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
supports: {
|
||||||
|
features: config.supports,
|
||||||
|
},
|
||||||
|
} );
|
170
modules/ppcp-local-alternative-payment-methods/services.php
Normal file
170
modules/ppcp-local-alternative-payment-methods/services.php
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The local alternative payment methods module services.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'ppcp-local-apms.url' => static function ( ContainerInterface $container ): string {
|
||||||
|
/**
|
||||||
|
* The path cannot be false.
|
||||||
|
*
|
||||||
|
* @psalm-suppress PossiblyFalseArgument
|
||||||
|
*/
|
||||||
|
return plugins_url(
|
||||||
|
'/modules/ppcp-local-alternative-payment-methods/',
|
||||||
|
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.payment-methods' => static function( ContainerInterface $container ): array {
|
||||||
|
return array(
|
||||||
|
'bancontact' => array(
|
||||||
|
'id' => BancontactGateway::ID,
|
||||||
|
'countries' => array( 'BE' ),
|
||||||
|
'currencies' => array( 'EUR' ),
|
||||||
|
),
|
||||||
|
'blik' => array(
|
||||||
|
'id' => BlikGateway::ID,
|
||||||
|
'countries' => array( 'PL' ),
|
||||||
|
'currencies' => array( 'PLN' ),
|
||||||
|
),
|
||||||
|
'eps' => array(
|
||||||
|
'id' => EPSGateway::ID,
|
||||||
|
'countries' => array( 'AT' ),
|
||||||
|
'currencies' => array( 'EUR' ),
|
||||||
|
),
|
||||||
|
'ideal' => array(
|
||||||
|
'id' => IDealGateway::ID,
|
||||||
|
'countries' => array( 'NL' ),
|
||||||
|
'currencies' => array( 'EUR' ),
|
||||||
|
),
|
||||||
|
'mybank' => array(
|
||||||
|
'id' => MyBankGateway::ID,
|
||||||
|
'countries' => array( 'IT' ),
|
||||||
|
'currencies' => array( 'EUR' ),
|
||||||
|
),
|
||||||
|
'p24' => array(
|
||||||
|
'id' => P24Gateway::ID,
|
||||||
|
'countries' => array( 'PL' ),
|
||||||
|
'currencies' => array( 'EUR', 'PLN' ),
|
||||||
|
),
|
||||||
|
'trustly' => array(
|
||||||
|
'id' => TrustlyGateway::ID,
|
||||||
|
'countries' => array( 'AT', 'DE', 'DK', 'EE', 'ES', 'FI', 'GB', 'LT', 'LV', 'NL', 'NO', 'SE' ),
|
||||||
|
'currencies' => array( 'EUR', 'DKK', 'SEK', 'GBP', 'NOK' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.bancontact.wc-gateway' => static function ( ContainerInterface $container ): BancontactGateway {
|
||||||
|
return new BancontactGateway(
|
||||||
|
$container->get( 'api.endpoint.orders' ),
|
||||||
|
$container->get( 'api.factory.purchase-unit' ),
|
||||||
|
$container->get( 'wcgateway.processor.refunds' ),
|
||||||
|
$container->get( 'wcgateway.transaction-url-provider' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.blik.wc-gateway' => static function ( ContainerInterface $container ): BlikGateway {
|
||||||
|
return new BlikGateway(
|
||||||
|
$container->get( 'api.endpoint.orders' ),
|
||||||
|
$container->get( 'api.factory.purchase-unit' ),
|
||||||
|
$container->get( 'wcgateway.processor.refunds' ),
|
||||||
|
$container->get( 'wcgateway.transaction-url-provider' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.eps.wc-gateway' => static function ( ContainerInterface $container ): EPSGateway {
|
||||||
|
return new EPSGateway(
|
||||||
|
$container->get( 'api.endpoint.orders' ),
|
||||||
|
$container->get( 'api.factory.purchase-unit' ),
|
||||||
|
$container->get( 'wcgateway.processor.refunds' ),
|
||||||
|
$container->get( 'wcgateway.transaction-url-provider' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.ideal.wc-gateway' => static function ( ContainerInterface $container ): IDealGateway {
|
||||||
|
return new IDealGateway(
|
||||||
|
$container->get( 'api.endpoint.orders' ),
|
||||||
|
$container->get( 'api.factory.purchase-unit' ),
|
||||||
|
$container->get( 'wcgateway.processor.refunds' ),
|
||||||
|
$container->get( 'wcgateway.transaction-url-provider' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.mybank.wc-gateway' => static function ( ContainerInterface $container ): MyBankGateway {
|
||||||
|
return new MyBankGateway(
|
||||||
|
$container->get( 'api.endpoint.orders' ),
|
||||||
|
$container->get( 'api.factory.purchase-unit' ),
|
||||||
|
$container->get( 'wcgateway.processor.refunds' ),
|
||||||
|
$container->get( 'wcgateway.transaction-url-provider' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.p24.wc-gateway' => static function ( ContainerInterface $container ): P24Gateway {
|
||||||
|
return new P24Gateway(
|
||||||
|
$container->get( 'api.endpoint.orders' ),
|
||||||
|
$container->get( 'api.factory.purchase-unit' ),
|
||||||
|
$container->get( 'wcgateway.processor.refunds' ),
|
||||||
|
$container->get( 'wcgateway.transaction-url-provider' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.trustly.wc-gateway' => static function ( ContainerInterface $container ): TrustlyGateway {
|
||||||
|
return new TrustlyGateway(
|
||||||
|
$container->get( 'api.endpoint.orders' ),
|
||||||
|
$container->get( 'api.factory.purchase-unit' ),
|
||||||
|
$container->get( 'wcgateway.processor.refunds' ),
|
||||||
|
$container->get( 'wcgateway.transaction-url-provider' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.bancontact.payment-method' => static function( ContainerInterface $container ): BancontactPaymentMethod {
|
||||||
|
return new BancontactPaymentMethod(
|
||||||
|
$container->get( 'ppcp-local-apms.url' ),
|
||||||
|
$container->get( 'ppcp.asset-version' ),
|
||||||
|
$container->get( 'ppcp-local-apms.bancontact.wc-gateway' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.blik.payment-method' => static function( ContainerInterface $container ): BlikPaymentMethod {
|
||||||
|
return new BlikPaymentMethod(
|
||||||
|
$container->get( 'ppcp-local-apms.url' ),
|
||||||
|
$container->get( 'ppcp.asset-version' ),
|
||||||
|
$container->get( 'ppcp-local-apms.blik.wc-gateway' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.eps.payment-method' => static function( ContainerInterface $container ): EPSPaymentMethod {
|
||||||
|
return new EPSPaymentMethod(
|
||||||
|
$container->get( 'ppcp-local-apms.url' ),
|
||||||
|
$container->get( 'ppcp.asset-version' ),
|
||||||
|
$container->get( 'ppcp-local-apms.eps.wc-gateway' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.ideal.payment-method' => static function( ContainerInterface $container ): IDealPaymentMethod {
|
||||||
|
return new IDealPaymentMethod(
|
||||||
|
$container->get( 'ppcp-local-apms.url' ),
|
||||||
|
$container->get( 'ppcp.asset-version' ),
|
||||||
|
$container->get( 'ppcp-local-apms.ideal.wc-gateway' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.mybank.payment-method' => static function( ContainerInterface $container ): MyBankPaymentMethod {
|
||||||
|
return new MyBankPaymentMethod(
|
||||||
|
$container->get( 'ppcp-local-apms.url' ),
|
||||||
|
$container->get( 'ppcp.asset-version' ),
|
||||||
|
$container->get( 'ppcp-local-apms.mybank.wc-gateway' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.p24.payment-method' => static function( ContainerInterface $container ): P24PaymentMethod {
|
||||||
|
return new P24PaymentMethod(
|
||||||
|
$container->get( 'ppcp-local-apms.url' ),
|
||||||
|
$container->get( 'ppcp.asset-version' ),
|
||||||
|
$container->get( 'ppcp-local-apms.p24.wc-gateway' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
'ppcp-local-apms.trustly.payment-method' => static function( ContainerInterface $container ): TrustlyPaymentMethod {
|
||||||
|
return new TrustlyPaymentMethod(
|
||||||
|
$container->get( 'ppcp-local-apms.url' ),
|
||||||
|
$container->get( 'ppcp.asset-version' ),
|
||||||
|
$container->get( 'ppcp-local-apms.trustly.wc-gateway' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
|
@ -0,0 +1,226 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The Bancontact payment gateway.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use WC_Payment_Gateway;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BancontactGateway
|
||||||
|
*/
|
||||||
|
class BancontactGateway extends WC_Payment_Gateway {
|
||||||
|
|
||||||
|
const ID = 'ppcp-bancontact';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PayPal Orders endpoint.
|
||||||
|
*
|
||||||
|
* @var Orders
|
||||||
|
*/
|
||||||
|
private $orders_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purchase unit factory.
|
||||||
|
*
|
||||||
|
* @var PurchaseUnitFactory
|
||||||
|
*/
|
||||||
|
private $purchase_unit_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refund Processor.
|
||||||
|
*
|
||||||
|
* @var RefundProcessor
|
||||||
|
*/
|
||||||
|
private $refund_processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service able to provide transaction url for an order.
|
||||||
|
*
|
||||||
|
* @var TransactionUrlProvider
|
||||||
|
*/
|
||||||
|
protected $transaction_url_provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BancontactGateway constructor.
|
||||||
|
*
|
||||||
|
* @param Orders $orders_endpoint PayPal Orders endpoint.
|
||||||
|
* @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory.
|
||||||
|
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||||
|
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Orders $orders_endpoint,
|
||||||
|
PurchaseUnitFactory $purchase_unit_factory,
|
||||||
|
RefundProcessor $refund_processor,
|
||||||
|
TransactionUrlProvider $transaction_url_provider
|
||||||
|
) {
|
||||||
|
$this->id = self::ID;
|
||||||
|
|
||||||
|
$this->supports = array(
|
||||||
|
'refunds',
|
||||||
|
'products',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->method_title = __( 'Bancontact', 'woocommerce-paypal-payments' );
|
||||||
|
$this->method_description = __( 'A popular and trusted electronic payment method in Belgium, used by Belgian customers with Bancontact cards issued by local banks. Transactions are processed in EUR.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$this->title = $this->get_option( 'title', __( 'Bancontact', 'woocommerce-paypal-payments' ) );
|
||||||
|
$this->description = $this->get_option( 'description', '' );
|
||||||
|
|
||||||
|
$this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_bancontact_color.svg' );
|
||||||
|
|
||||||
|
$this->init_form_fields();
|
||||||
|
$this->init_settings();
|
||||||
|
|
||||||
|
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||||
|
|
||||||
|
$this->orders_endpoint = $orders_endpoint;
|
||||||
|
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||||
|
$this->refund_processor = $refund_processor;
|
||||||
|
$this->transaction_url_provider = $transaction_url_provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the form fields.
|
||||||
|
*/
|
||||||
|
public function init_form_fields() {
|
||||||
|
$this->form_fields = array(
|
||||||
|
'enabled' => array(
|
||||||
|
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => __( 'Bancontact', 'woocommerce-paypal-payments' ),
|
||||||
|
'default' => 'no',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'Enable/Disable Bancontact payment gateway.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'title' => array(
|
||||||
|
'title' => __( 'Title', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->title,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'title' => __( 'Description', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->description,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the order.
|
||||||
|
*
|
||||||
|
* @param int $order_id The WC order ID.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function process_payment( $order_id ) {
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
$wc_order->update_status( 'on-hold', __( 'Awaiting Bancontact to confirm the payment.', 'woocommerce-paypal-payments' ) );
|
||||||
|
|
||||||
|
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||||
|
$amount = $purchase_unit->amount()->to_array();
|
||||||
|
|
||||||
|
$request_body = array(
|
||||||
|
'intent' => 'CAPTURE',
|
||||||
|
'payment_source' => array(
|
||||||
|
'bancontact' => array(
|
||||||
|
'country_code' => $wc_order->get_billing_country(),
|
||||||
|
'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
|
||||||
|
'purchase_units' => array(
|
||||||
|
array(
|
||||||
|
'reference_id' => $purchase_unit->reference_id(),
|
||||||
|
'amount' => array(
|
||||||
|
'currency_code' => $amount['currency_code'],
|
||||||
|
'value' => $amount['value'],
|
||||||
|
),
|
||||||
|
'custom_id' => $purchase_unit->custom_id(),
|
||||||
|
'invoice_id' => $purchase_unit->invoice_id(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'application_context' => array(
|
||||||
|
'locale' => 'en-BE',
|
||||||
|
'return_url' => $this->get_return_url( $wc_order ),
|
||||||
|
'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $this->orders_endpoint->create( $request_body );
|
||||||
|
} catch ( RuntimeException $exception ) {
|
||||||
|
$wc_order->update_status(
|
||||||
|
'failed',
|
||||||
|
$exception->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'failure',
|
||||||
|
'redirect' => wc_get_checkout_url(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = json_decode( $response['body'] );
|
||||||
|
|
||||||
|
$payer_action = '';
|
||||||
|
foreach ( $body->links as $link ) {
|
||||||
|
if ( $link->rel === 'payer-action' ) {
|
||||||
|
$payer_action = $link->href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WC()->cart->empty_cart();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'success',
|
||||||
|
'redirect' => esc_url( $payer_action ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process refund.
|
||||||
|
*
|
||||||
|
* If the gateway declares 'refunds' support, this will allow it to refund.
|
||||||
|
* a passed in amount.
|
||||||
|
*
|
||||||
|
* @param int $order_id Order ID.
|
||||||
|
* @param float $amount Refund amount.
|
||||||
|
* @param string $reason Refund reason.
|
||||||
|
* @return boolean True or false based on success, or a WP_Error object.
|
||||||
|
*/
|
||||||
|
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
||||||
|
$order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $order, \WC_Order::class ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return transaction url for this gateway and given order.
|
||||||
|
*
|
||||||
|
* @param \WC_Order $order WC order to get transaction url by.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_transaction_url( $order ): string {
|
||||||
|
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||||
|
|
||||||
|
return parent::get_transaction_url( $order );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Bancontact payment method.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BancontactPaymentMethod
|
||||||
|
*/
|
||||||
|
class BancontactPaymentMethod extends AbstractPaymentMethodType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of this module.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $module_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The assets version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bancontact WC gateway.
|
||||||
|
*
|
||||||
|
* @var BancontactGateway
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BancontactPaymentMethod constructor.
|
||||||
|
*
|
||||||
|
* @param string $module_url The URL of this module.
|
||||||
|
* @param string $version The assets version.
|
||||||
|
* @param BancontactGateway $gateway Bancontact WC gateway.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $module_url,
|
||||||
|
string $version,
|
||||||
|
BancontactGateway $gateway
|
||||||
|
) {
|
||||||
|
$this->module_url = $module_url;
|
||||||
|
$this->version = $version;
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
|
||||||
|
$this->name = BancontactGateway::ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function initialize() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function is_active() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_script_handles() {
|
||||||
|
wp_register_script(
|
||||||
|
'ppcp-bancontact-payment-method',
|
||||||
|
trailingslashit( $this->module_url ) . 'assets/js/bancontact-payment-method.js',
|
||||||
|
array(),
|
||||||
|
$this->version,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return array( 'ppcp-bancontact-payment-method' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_data() {
|
||||||
|
return array(
|
||||||
|
'id' => $this->name,
|
||||||
|
'title' => $this->gateway->title,
|
||||||
|
'description' => $this->gateway->description,
|
||||||
|
'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_bancontact_color.svg' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The Blik payment gateway.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use WC_Payment_Gateway;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BlikGateway
|
||||||
|
*/
|
||||||
|
class BlikGateway extends WC_Payment_Gateway {
|
||||||
|
|
||||||
|
const ID = 'ppcp-blik';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PayPal Orders endpoint.
|
||||||
|
*
|
||||||
|
* @var Orders
|
||||||
|
*/
|
||||||
|
private $orders_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purchase unit factory.
|
||||||
|
*
|
||||||
|
* @var PurchaseUnitFactory
|
||||||
|
*/
|
||||||
|
private $purchase_unit_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refund Processor.
|
||||||
|
*
|
||||||
|
* @var RefundProcessor
|
||||||
|
*/
|
||||||
|
private $refund_processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service able to provide transaction url for an order.
|
||||||
|
*
|
||||||
|
* @var TransactionUrlProvider
|
||||||
|
*/
|
||||||
|
protected $transaction_url_provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BlikGateway constructor.
|
||||||
|
*
|
||||||
|
* @param Orders $orders_endpoint PayPal Orders endpoint.
|
||||||
|
* @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory.
|
||||||
|
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||||
|
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Orders $orders_endpoint,
|
||||||
|
PurchaseUnitFactory $purchase_unit_factory,
|
||||||
|
RefundProcessor $refund_processor,
|
||||||
|
TransactionUrlProvider $transaction_url_provider
|
||||||
|
) {
|
||||||
|
$this->id = self::ID;
|
||||||
|
|
||||||
|
$this->supports = array(
|
||||||
|
'refunds',
|
||||||
|
'products',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->method_title = __( 'Blik', 'woocommerce-paypal-payments' );
|
||||||
|
$this->method_description = __( 'A widely used mobile payment method in Poland, allowing Polish customers to pay directly via their banking apps. Transactions are processed in PLN.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$this->title = $this->get_option( 'title', __( 'Blik', 'woocommerce-paypal-payments' ) );
|
||||||
|
$this->description = $this->get_option( 'description', '' );
|
||||||
|
|
||||||
|
$this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_blik_color.svg' );
|
||||||
|
|
||||||
|
$this->init_form_fields();
|
||||||
|
$this->init_settings();
|
||||||
|
|
||||||
|
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||||
|
|
||||||
|
$this->orders_endpoint = $orders_endpoint;
|
||||||
|
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||||
|
$this->refund_processor = $refund_processor;
|
||||||
|
$this->transaction_url_provider = $transaction_url_provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the form fields.
|
||||||
|
*/
|
||||||
|
public function init_form_fields() {
|
||||||
|
$this->form_fields = array(
|
||||||
|
'enabled' => array(
|
||||||
|
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => __( 'Blik', 'woocommerce-paypal-payments' ),
|
||||||
|
'default' => 'no',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'Enable/Disable Blik payment gateway.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'title' => array(
|
||||||
|
'title' => __( 'Title', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->title,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'title' => __( 'Description', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->description,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the order.
|
||||||
|
*
|
||||||
|
* @param int $order_id The WC order ID.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function process_payment( $order_id ) {
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
$wc_order->update_status( 'on-hold', __( 'Awaiting Blik to confirm the payment.', 'woocommerce-paypal-payments' ) );
|
||||||
|
|
||||||
|
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||||
|
$amount = $purchase_unit->amount()->to_array();
|
||||||
|
|
||||||
|
$request_body = array(
|
||||||
|
'intent' => 'CAPTURE',
|
||||||
|
'payment_source' => array(
|
||||||
|
'blik' => array(
|
||||||
|
'country_code' => $wc_order->get_billing_country(),
|
||||||
|
'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(),
|
||||||
|
'email' => $wc_order->get_billing_email(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
|
||||||
|
'purchase_units' => array(
|
||||||
|
array(
|
||||||
|
'reference_id' => $purchase_unit->reference_id(),
|
||||||
|
'amount' => array(
|
||||||
|
'currency_code' => $amount['currency_code'],
|
||||||
|
'value' => $amount['value'],
|
||||||
|
),
|
||||||
|
'custom_id' => $purchase_unit->custom_id(),
|
||||||
|
'invoice_id' => $purchase_unit->invoice_id(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'application_context' => array(
|
||||||
|
'locale' => 'en-PL',
|
||||||
|
'return_url' => $this->get_return_url( $wc_order ),
|
||||||
|
'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $this->orders_endpoint->create( $request_body );
|
||||||
|
} catch ( RuntimeException $exception ) {
|
||||||
|
$wc_order->update_status(
|
||||||
|
'failed',
|
||||||
|
$exception->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'failure',
|
||||||
|
'redirect' => wc_get_checkout_url(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = json_decode( $response['body'] );
|
||||||
|
|
||||||
|
$payer_action = '';
|
||||||
|
foreach ( $body->links as $link ) {
|
||||||
|
if ( $link->rel === 'payer-action' ) {
|
||||||
|
$payer_action = $link->href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WC()->cart->empty_cart();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'success',
|
||||||
|
'redirect' => esc_url( $payer_action ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process refund.
|
||||||
|
*
|
||||||
|
* If the gateway declares 'refunds' support, this will allow it to refund.
|
||||||
|
* a passed in amount.
|
||||||
|
*
|
||||||
|
* @param int $order_id Order ID.
|
||||||
|
* @param float $amount Refund amount.
|
||||||
|
* @param string $reason Refund reason.
|
||||||
|
* @return boolean True or false based on success, or a WP_Error object.
|
||||||
|
*/
|
||||||
|
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
||||||
|
$order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $order, \WC_Order::class ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return transaction url for this gateway and given order.
|
||||||
|
*
|
||||||
|
* @param \WC_Order $order WC order to get transaction url by.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_transaction_url( $order ): string {
|
||||||
|
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||||
|
|
||||||
|
return parent::get_transaction_url( $order );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Blik payment method.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BlikPaymentMethod
|
||||||
|
*/
|
||||||
|
class BlikPaymentMethod extends AbstractPaymentMethodType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of this module.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $module_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The assets version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blik WC gateway.
|
||||||
|
*
|
||||||
|
* @var BlikGateway
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BlikPaymentMethod constructor.
|
||||||
|
*
|
||||||
|
* @param string $module_url The URL of this module.
|
||||||
|
* @param string $version The assets version.
|
||||||
|
* @param BlikGateway $gateway Blik WC gateway.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $module_url,
|
||||||
|
string $version,
|
||||||
|
BlikGateway $gateway
|
||||||
|
) {
|
||||||
|
$this->module_url = $module_url;
|
||||||
|
$this->version = $version;
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
|
||||||
|
$this->name = BlikGateway::ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function initialize() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function is_active() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_script_handles() {
|
||||||
|
wp_register_script(
|
||||||
|
'ppcp-blick-payment-method',
|
||||||
|
trailingslashit( $this->module_url ) . 'assets/js/blik-payment-method.js',
|
||||||
|
array(),
|
||||||
|
$this->version,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return array( 'ppcp-blick-payment-method' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_data() {
|
||||||
|
return array(
|
||||||
|
'id' => $this->name,
|
||||||
|
'title' => $this->gateway->title,
|
||||||
|
'description' => $this->gateway->description,
|
||||||
|
'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_blik_color.svg' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,226 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The EPS payment gateway.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use WC_Payment_Gateway;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class EPSGateway
|
||||||
|
*/
|
||||||
|
class EPSGateway extends WC_Payment_Gateway {
|
||||||
|
|
||||||
|
const ID = 'ppcp-eps';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PayPal Orders endpoint.
|
||||||
|
*
|
||||||
|
* @var Orders
|
||||||
|
*/
|
||||||
|
private $orders_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purchase unit factory.
|
||||||
|
*
|
||||||
|
* @var PurchaseUnitFactory
|
||||||
|
*/
|
||||||
|
private $purchase_unit_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refund Processor.
|
||||||
|
*
|
||||||
|
* @var RefundProcessor
|
||||||
|
*/
|
||||||
|
private $refund_processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service able to provide transaction url for an order.
|
||||||
|
*
|
||||||
|
* @var TransactionUrlProvider
|
||||||
|
*/
|
||||||
|
protected $transaction_url_provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EPSGateway constructor.
|
||||||
|
*
|
||||||
|
* @param Orders $orders_endpoint PayPal Orders endpoint.
|
||||||
|
* @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory.
|
||||||
|
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||||
|
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Orders $orders_endpoint,
|
||||||
|
PurchaseUnitFactory $purchase_unit_factory,
|
||||||
|
RefundProcessor $refund_processor,
|
||||||
|
TransactionUrlProvider $transaction_url_provider
|
||||||
|
) {
|
||||||
|
$this->id = self::ID;
|
||||||
|
|
||||||
|
$this->supports = array(
|
||||||
|
'refunds',
|
||||||
|
'products',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->method_title = __( 'EPS', 'woocommerce-paypal-payments' );
|
||||||
|
$this->method_description = __( 'An online payment method in Austria, enabling Austrian buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$this->title = $this->get_option( 'title', __( 'EPS', 'woocommerce-paypal-payments' ) );
|
||||||
|
$this->description = $this->get_option( 'description', '' );
|
||||||
|
|
||||||
|
$this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_eps_color.svg' );
|
||||||
|
|
||||||
|
$this->init_form_fields();
|
||||||
|
$this->init_settings();
|
||||||
|
|
||||||
|
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||||
|
|
||||||
|
$this->orders_endpoint = $orders_endpoint;
|
||||||
|
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||||
|
$this->refund_processor = $refund_processor;
|
||||||
|
$this->transaction_url_provider = $transaction_url_provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the form fields.
|
||||||
|
*/
|
||||||
|
public function init_form_fields() {
|
||||||
|
$this->form_fields = array(
|
||||||
|
'enabled' => array(
|
||||||
|
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => __( 'EPS', 'woocommerce-paypal-payments' ),
|
||||||
|
'default' => 'no',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'Enable/Disable EPS payment gateway.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'title' => array(
|
||||||
|
'title' => __( 'Title', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->title,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'title' => __( 'Description', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->description,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the order.
|
||||||
|
*
|
||||||
|
* @param int $order_id The WC order ID.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function process_payment( $order_id ) {
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
$wc_order->update_status( 'on-hold', __( 'Awaiting EPS to confirm the payment.', 'woocommerce-paypal-payments' ) );
|
||||||
|
|
||||||
|
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||||
|
$amount = $purchase_unit->amount()->to_array();
|
||||||
|
|
||||||
|
$request_body = array(
|
||||||
|
'intent' => 'CAPTURE',
|
||||||
|
'payment_source' => array(
|
||||||
|
'eps' => array(
|
||||||
|
'country_code' => $wc_order->get_billing_country(),
|
||||||
|
'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
|
||||||
|
'purchase_units' => array(
|
||||||
|
array(
|
||||||
|
'reference_id' => $purchase_unit->reference_id(),
|
||||||
|
'amount' => array(
|
||||||
|
'currency_code' => $amount['currency_code'],
|
||||||
|
'value' => $amount['value'],
|
||||||
|
),
|
||||||
|
'custom_id' => $purchase_unit->custom_id(),
|
||||||
|
'invoice_id' => $purchase_unit->invoice_id(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'application_context' => array(
|
||||||
|
'locale' => 'en-AT',
|
||||||
|
'return_url' => $this->get_return_url( $wc_order ),
|
||||||
|
'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $this->orders_endpoint->create( $request_body );
|
||||||
|
} catch ( RuntimeException $exception ) {
|
||||||
|
$wc_order->update_status(
|
||||||
|
'failed',
|
||||||
|
$exception->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'failure',
|
||||||
|
'redirect' => wc_get_checkout_url(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = json_decode( $response['body'] );
|
||||||
|
|
||||||
|
$payer_action = '';
|
||||||
|
foreach ( $body->links as $link ) {
|
||||||
|
if ( $link->rel === 'payer-action' ) {
|
||||||
|
$payer_action = $link->href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WC()->cart->empty_cart();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'success',
|
||||||
|
'redirect' => esc_url( $payer_action ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process refund.
|
||||||
|
*
|
||||||
|
* If the gateway declares 'refunds' support, this will allow it to refund.
|
||||||
|
* a passed in amount.
|
||||||
|
*
|
||||||
|
* @param int $order_id Order ID.
|
||||||
|
* @param float $amount Refund amount.
|
||||||
|
* @param string $reason Refund reason.
|
||||||
|
* @return boolean True or false based on success, or a WP_Error object.
|
||||||
|
*/
|
||||||
|
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
||||||
|
$order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $order, \WC_Order::class ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return transaction url for this gateway and given order.
|
||||||
|
*
|
||||||
|
* @param \WC_Order $order WC order to get transaction url by.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_transaction_url( $order ): string {
|
||||||
|
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||||
|
|
||||||
|
return parent::get_transaction_url( $order );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* EPS payment method.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class EPSPaymentMethod
|
||||||
|
*/
|
||||||
|
class EPSPaymentMethod extends AbstractPaymentMethodType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of this module.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $module_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The assets version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EPS WC gateway.
|
||||||
|
*
|
||||||
|
* @var EPSGateway
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EPSPaymentMethod constructor.
|
||||||
|
*
|
||||||
|
* @param string $module_url The URL of this module.
|
||||||
|
* @param string $version The assets version.
|
||||||
|
* @param EPSGateway $gateway EPS WC gateway.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $module_url,
|
||||||
|
string $version,
|
||||||
|
EPSGateway $gateway
|
||||||
|
) {
|
||||||
|
$this->module_url = $module_url;
|
||||||
|
$this->version = $version;
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
|
||||||
|
$this->name = EPSGateway::ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function initialize() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function is_active() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_script_handles() {
|
||||||
|
wp_register_script(
|
||||||
|
'ppcp-eps-payment-method',
|
||||||
|
trailingslashit( $this->module_url ) . 'assets/js/eps-payment-method.js',
|
||||||
|
array(),
|
||||||
|
$this->version,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return array( 'ppcp-eps-payment-method' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_data() {
|
||||||
|
return array(
|
||||||
|
'id' => $this->name,
|
||||||
|
'title' => $this->gateway->title,
|
||||||
|
'description' => $this->gateway->description,
|
||||||
|
'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_eps_color.svg' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,228 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The iDeal payment gateway.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use WC_Payment_Gateway;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IDealGateway
|
||||||
|
*/
|
||||||
|
class IDealGateway extends WC_Payment_Gateway {
|
||||||
|
|
||||||
|
const ID = 'ppcp-ideal';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PayPal Orders endpoint.
|
||||||
|
*
|
||||||
|
* @var Orders
|
||||||
|
*/
|
||||||
|
private $orders_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purchase unit factory.
|
||||||
|
*
|
||||||
|
* @var PurchaseUnitFactory
|
||||||
|
*/
|
||||||
|
private $purchase_unit_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refund Processor.
|
||||||
|
*
|
||||||
|
* @var RefundProcessor
|
||||||
|
*/
|
||||||
|
private $refund_processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service able to provide transaction url for an order.
|
||||||
|
*
|
||||||
|
* @var TransactionUrlProvider
|
||||||
|
*/
|
||||||
|
protected $transaction_url_provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IDealGateway constructor.
|
||||||
|
*
|
||||||
|
* @param Orders $orders_endpoint PayPal Orders endpoint.
|
||||||
|
* @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory.
|
||||||
|
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||||
|
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Orders $orders_endpoint,
|
||||||
|
PurchaseUnitFactory $purchase_unit_factory,
|
||||||
|
RefundProcessor $refund_processor,
|
||||||
|
TransactionUrlProvider $transaction_url_provider
|
||||||
|
) {
|
||||||
|
$this->id = self::ID;
|
||||||
|
|
||||||
|
$this->supports = array(
|
||||||
|
'refunds',
|
||||||
|
'products',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->method_title = __( 'iDeal', 'woocommerce-paypal-payments' );
|
||||||
|
$this->method_description = __( 'The most common payment method in the Netherlands, allowing Dutch buyers to pay directly through their preferred bank. Transactions are processed in EUR.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$this->title = $this->get_option( 'title', __( 'iDeal', 'woocommerce-paypal-payments' ) );
|
||||||
|
$this->description = $this->get_option( 'description', '' );
|
||||||
|
|
||||||
|
$this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_ideal_color.svg' );
|
||||||
|
|
||||||
|
$this->init_form_fields();
|
||||||
|
$this->init_settings();
|
||||||
|
|
||||||
|
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||||
|
|
||||||
|
$this->orders_endpoint = $orders_endpoint;
|
||||||
|
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||||
|
$this->refund_processor = $refund_processor;
|
||||||
|
$this->transaction_url_provider = $transaction_url_provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the form fields.
|
||||||
|
*/
|
||||||
|
public function init_form_fields() {
|
||||||
|
$this->form_fields = array(
|
||||||
|
'enabled' => array(
|
||||||
|
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => __( 'iDeal', 'woocommerce-paypal-payments' ),
|
||||||
|
'default' => 'no',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'Enable/Disable iDeal payment gateway.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'title' => array(
|
||||||
|
'title' => __( 'Title', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->title,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'title' => __( 'Description', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->description,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the order.
|
||||||
|
*
|
||||||
|
* @param int $order_id The WC order ID.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function process_payment( $order_id ) {
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
$wc_order->update_status( 'on-hold', __( 'Awaiting iDeal to confirm the payment.', 'woocommerce-paypal-payments' ) );
|
||||||
|
|
||||||
|
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||||
|
$amount = $purchase_unit->amount()->to_array();
|
||||||
|
|
||||||
|
$payment_source = array(
|
||||||
|
'country_code' => $wc_order->get_billing_country(),
|
||||||
|
'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(),
|
||||||
|
);
|
||||||
|
// TODO get "bic" from gateway settings.
|
||||||
|
|
||||||
|
$request_body = array(
|
||||||
|
'intent' => 'CAPTURE',
|
||||||
|
'payment_source' => array(
|
||||||
|
'ideal' => $payment_source,
|
||||||
|
),
|
||||||
|
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
|
||||||
|
'purchase_units' => array(
|
||||||
|
array(
|
||||||
|
'reference_id' => $purchase_unit->reference_id(),
|
||||||
|
'amount' => array(
|
||||||
|
'currency_code' => $amount['currency_code'],
|
||||||
|
'value' => $amount['value'],
|
||||||
|
),
|
||||||
|
'custom_id' => $purchase_unit->custom_id(),
|
||||||
|
'invoice_id' => $purchase_unit->invoice_id(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'application_context' => array(
|
||||||
|
'return_url' => $this->get_return_url( $wc_order ),
|
||||||
|
'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $this->orders_endpoint->create( $request_body );
|
||||||
|
} catch ( RuntimeException $exception ) {
|
||||||
|
$wc_order->update_status(
|
||||||
|
'failed',
|
||||||
|
$exception->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'failure',
|
||||||
|
'redirect' => wc_get_checkout_url(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = json_decode( $response['body'] );
|
||||||
|
|
||||||
|
$payer_action = '';
|
||||||
|
foreach ( $body->links as $link ) {
|
||||||
|
if ( $link->rel === 'payer-action' ) {
|
||||||
|
$payer_action = $link->href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WC()->cart->empty_cart();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'success',
|
||||||
|
'redirect' => esc_url( $payer_action ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process refund.
|
||||||
|
*
|
||||||
|
* If the gateway declares 'refunds' support, this will allow it to refund.
|
||||||
|
* a passed in amount.
|
||||||
|
*
|
||||||
|
* @param int $order_id Order ID.
|
||||||
|
* @param float $amount Refund amount.
|
||||||
|
* @param string $reason Refund reason.
|
||||||
|
* @return boolean True or false based on success, or a WP_Error object.
|
||||||
|
*/
|
||||||
|
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
||||||
|
$order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $order, \WC_Order::class ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return transaction url for this gateway and given order.
|
||||||
|
*
|
||||||
|
* @param \WC_Order $order WC order to get transaction url by.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_transaction_url( $order ): string {
|
||||||
|
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||||
|
|
||||||
|
return parent::get_transaction_url( $order );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* IDeal payment method.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IDealPaymentMethod
|
||||||
|
*/
|
||||||
|
class IDealPaymentMethod extends AbstractPaymentMethodType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of this module.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $module_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The assets version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IDeal WC gateway.
|
||||||
|
*
|
||||||
|
* @var IDealGateway
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IDealPaymentMethod constructor.
|
||||||
|
*
|
||||||
|
* @param string $module_url The URL of this module.
|
||||||
|
* @param string $version The assets version.
|
||||||
|
* @param IDealGateway $gateway IDeal WC gateway.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $module_url,
|
||||||
|
string $version,
|
||||||
|
IDealGateway $gateway
|
||||||
|
) {
|
||||||
|
$this->module_url = $module_url;
|
||||||
|
$this->version = $version;
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
|
||||||
|
$this->name = IDealGateway::ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function initialize() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function is_active() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_script_handles() {
|
||||||
|
wp_register_script(
|
||||||
|
'ppcp-ideal-payment-method',
|
||||||
|
trailingslashit( $this->module_url ) . 'assets/js/ideal-payment-method.js',
|
||||||
|
array(),
|
||||||
|
$this->version,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return array( 'ppcp-ideal-payment-method' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_data() {
|
||||||
|
return array(
|
||||||
|
'id' => $this->name,
|
||||||
|
'title' => $this->gateway->title,
|
||||||
|
'description' => $this->gateway->description,
|
||||||
|
'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_ideal_color.svg' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The local alternative payment methods module.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
|
||||||
|
use WC_Order;
|
||||||
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||||
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class LocalAlternativePaymentMethodsModule
|
||||||
|
*/
|
||||||
|
class LocalAlternativePaymentMethodsModule implements ModuleInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setup(): ServiceProviderInterface {
|
||||||
|
return new ServiceProvider(
|
||||||
|
require __DIR__ . '/../services.php',
|
||||||
|
require __DIR__ . '/../extensions.php'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function run( ContainerInterface $c ): void {
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_payment_gateways',
|
||||||
|
/**
|
||||||
|
* Param types removed to avoid third-party issues.
|
||||||
|
*
|
||||||
|
* @psalm-suppress MissingClosureParamType
|
||||||
|
*/
|
||||||
|
function ( $methods ) use ( $c ) {
|
||||||
|
if ( ! is_array( $methods ) ) {
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
||||||
|
foreach ( $payment_methods as $key => $value ) {
|
||||||
|
$methods[] = $c->get( 'ppcp-local-apms.' . $key . '.wc-gateway' );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_available_payment_gateways',
|
||||||
|
/**
|
||||||
|
* Param types removed to avoid third-party issues.
|
||||||
|
*
|
||||||
|
* @psalm-suppress MissingClosureParamType
|
||||||
|
*/
|
||||||
|
function ( $methods ) use ( $c ) {
|
||||||
|
if ( ! is_array( $methods ) ) {
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! is_admin() ) {
|
||||||
|
if ( ! isset( WC()->customer ) ) {
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer_country = WC()->customer->get_billing_country() ?: WC()->customer->get_shipping_country();
|
||||||
|
$site_currency = get_woocommerce_currency();
|
||||||
|
|
||||||
|
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
||||||
|
foreach ( $payment_methods as $payment_method ) {
|
||||||
|
if (
|
||||||
|
! in_array( $customer_country, $payment_method['countries'], true )
|
||||||
|
|| ! in_array( $site_currency, $payment_method['currencies'], true )
|
||||||
|
) {
|
||||||
|
unset( $methods[ $payment_method['id'] ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $methods;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'woocommerce_blocks_payment_method_type_registration',
|
||||||
|
function( PaymentMethodRegistry $payment_method_registry ) use ( $c ): void {
|
||||||
|
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
||||||
|
foreach ( $payment_methods as $key => $value ) {
|
||||||
|
$payment_method_registry->register( $c->get( 'ppcp-local-apms.' . $key . '.payment-method' ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_paypal_payments_localized_script_data',
|
||||||
|
function ( array $data ) use ( $c ) {
|
||||||
|
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
||||||
|
|
||||||
|
$default_disable_funding = $data['url_params']['disable-funding'] ?? '';
|
||||||
|
$disable_funding = array_merge( array_keys( $payment_methods ), array_filter( explode( ',', $default_disable_funding ) ) );
|
||||||
|
$data['url_params']['disable-funding'] = implode( ',', array_unique( $disable_funding ) );
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'woocommerce_before_thankyou',
|
||||||
|
/**
|
||||||
|
* Activate is_checkout() on woocommerce/classic-shortcode checkout blocks.
|
||||||
|
*
|
||||||
|
* @psalm-suppress MissingClosureParamType
|
||||||
|
*/
|
||||||
|
function( $order_id ) use ( $c ) {
|
||||||
|
$order = wc_get_order( $order_id );
|
||||||
|
if ( ! $order instanceof WC_Order ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||||
|
$cancelled = wc_clean( wp_unslash( $_GET['cancelled'] ?? '' ) );
|
||||||
|
$order_key = wc_clean( wp_unslash( $_GET['key'] ?? '' ) );
|
||||||
|
// phpcs:enable
|
||||||
|
|
||||||
|
$payment_methods = $c->get( 'ppcp-local-apms.payment-methods' );
|
||||||
|
if (
|
||||||
|
! $this->is_local_apm( $order->get_payment_method(), $payment_methods )
|
||||||
|
|| ! $cancelled
|
||||||
|
|| $order->get_order_key() !== $order_key
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||||
|
$error_code = wc_clean( wp_unslash( $_GET['errorcode'] ?? '' ) );
|
||||||
|
if ( $error_code === 'processing_error' || $error_code === 'payment_error' ) {
|
||||||
|
$order->update_status( 'failed', __( "The payment can't be processed because of an error.", 'woocommerce-paypal-payments' ) );
|
||||||
|
|
||||||
|
add_filter( 'woocommerce_order_has_status', '__return_true' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if given payment method is a local APM.
|
||||||
|
*
|
||||||
|
* @param string $selected_payment_method Selected payment method.
|
||||||
|
* @param array $payment_methods Available local APMs.
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function is_local_apm( string $selected_payment_method, array $payment_methods ): bool {
|
||||||
|
foreach ( $payment_methods as $payment_method ) {
|
||||||
|
if ( $payment_method['id'] === $selected_payment_method ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,226 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The MyBank payment gateway.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use WC_Payment_Gateway;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MyBankGateway
|
||||||
|
*/
|
||||||
|
class MyBankGateway extends WC_Payment_Gateway {
|
||||||
|
|
||||||
|
const ID = 'ppcp-mybank';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PayPal Orders endpoint.
|
||||||
|
*
|
||||||
|
* @var Orders
|
||||||
|
*/
|
||||||
|
private $orders_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purchase unit factory.
|
||||||
|
*
|
||||||
|
* @var PurchaseUnitFactory
|
||||||
|
*/
|
||||||
|
private $purchase_unit_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refund Processor.
|
||||||
|
*
|
||||||
|
* @var RefundProcessor
|
||||||
|
*/
|
||||||
|
private $refund_processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service able to provide transaction url for an order.
|
||||||
|
*
|
||||||
|
* @var TransactionUrlProvider
|
||||||
|
*/
|
||||||
|
protected $transaction_url_provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MyBankGateway constructor.
|
||||||
|
*
|
||||||
|
* @param Orders $orders_endpoint PayPal Orders endpoint.
|
||||||
|
* @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory.
|
||||||
|
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||||
|
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Orders $orders_endpoint,
|
||||||
|
PurchaseUnitFactory $purchase_unit_factory,
|
||||||
|
RefundProcessor $refund_processor,
|
||||||
|
TransactionUrlProvider $transaction_url_provider
|
||||||
|
) {
|
||||||
|
$this->id = self::ID;
|
||||||
|
|
||||||
|
$this->supports = array(
|
||||||
|
'refunds',
|
||||||
|
'products',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->method_title = __( 'MyBank', 'woocommerce-paypal-payments' );
|
||||||
|
$this->method_description = __( 'A European online banking payment solution primarily used in Italy, enabling customers to make secure bank transfers during checkout. Transactions are processed in EUR.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$this->title = $this->get_option( 'title', __( 'MyBank', 'woocommerce-paypal-payments' ) );
|
||||||
|
$this->description = $this->get_option( 'description', '' );
|
||||||
|
|
||||||
|
$this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_mybank_color.svg' );
|
||||||
|
|
||||||
|
$this->init_form_fields();
|
||||||
|
$this->init_settings();
|
||||||
|
|
||||||
|
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||||
|
|
||||||
|
$this->orders_endpoint = $orders_endpoint;
|
||||||
|
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||||
|
$this->refund_processor = $refund_processor;
|
||||||
|
$this->transaction_url_provider = $transaction_url_provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the form fields.
|
||||||
|
*/
|
||||||
|
public function init_form_fields() {
|
||||||
|
$this->form_fields = array(
|
||||||
|
'enabled' => array(
|
||||||
|
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => __( 'MyBank', 'woocommerce-paypal-payments' ),
|
||||||
|
'default' => 'no',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'Enable/Disable MyBank payment gateway.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'title' => array(
|
||||||
|
'title' => __( 'Title', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->title,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'title' => __( 'Description', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->description,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the order.
|
||||||
|
*
|
||||||
|
* @param int $order_id The WC order ID.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function process_payment( $order_id ) {
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
$wc_order->update_status( 'on-hold', __( 'Awaiting MyBank to confirm the payment.', 'woocommerce-paypal-payments' ) );
|
||||||
|
|
||||||
|
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||||
|
$amount = $purchase_unit->amount()->to_array();
|
||||||
|
|
||||||
|
$request_body = array(
|
||||||
|
'intent' => 'CAPTURE',
|
||||||
|
'payment_source' => array(
|
||||||
|
'mybank' => array(
|
||||||
|
'country_code' => $wc_order->get_billing_country(),
|
||||||
|
'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
|
||||||
|
'purchase_units' => array(
|
||||||
|
array(
|
||||||
|
'reference_id' => $purchase_unit->reference_id(),
|
||||||
|
'amount' => array(
|
||||||
|
'currency_code' => $amount['currency_code'],
|
||||||
|
'value' => $amount['value'],
|
||||||
|
),
|
||||||
|
'custom_id' => $purchase_unit->custom_id(),
|
||||||
|
'invoice_id' => $purchase_unit->invoice_id(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'application_context' => array(
|
||||||
|
'locale' => 'en-IT',
|
||||||
|
'return_url' => $this->get_return_url( $wc_order ),
|
||||||
|
'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $this->orders_endpoint->create( $request_body );
|
||||||
|
} catch ( RuntimeException $exception ) {
|
||||||
|
$wc_order->update_status(
|
||||||
|
'failed',
|
||||||
|
$exception->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'failure',
|
||||||
|
'redirect' => wc_get_checkout_url(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = json_decode( $response['body'] );
|
||||||
|
|
||||||
|
$payer_action = '';
|
||||||
|
foreach ( $body->links as $link ) {
|
||||||
|
if ( $link->rel === 'payer-action' ) {
|
||||||
|
$payer_action = $link->href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WC()->cart->empty_cart();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'success',
|
||||||
|
'redirect' => esc_url( $payer_action ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process refund.
|
||||||
|
*
|
||||||
|
* If the gateway declares 'refunds' support, this will allow it to refund.
|
||||||
|
* a passed in amount.
|
||||||
|
*
|
||||||
|
* @param int $order_id Order ID.
|
||||||
|
* @param float $amount Refund amount.
|
||||||
|
* @param string $reason Refund reason.
|
||||||
|
* @return boolean True or false based on success, or a WP_Error object.
|
||||||
|
*/
|
||||||
|
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
||||||
|
$order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $order, \WC_Order::class ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return transaction url for this gateway and given order.
|
||||||
|
*
|
||||||
|
* @param \WC_Order $order WC order to get transaction url by.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_transaction_url( $order ): string {
|
||||||
|
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||||
|
|
||||||
|
return parent::get_transaction_url( $order );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* MyBank payment method.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class MyBankPaymentMethod
|
||||||
|
*/
|
||||||
|
class MyBankPaymentMethod extends AbstractPaymentMethodType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of this module.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $module_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The assets version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MyBank WC gateway.
|
||||||
|
*
|
||||||
|
* @var MyBankGateway
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MyBankPaymentMethod constructor.
|
||||||
|
*
|
||||||
|
* @param string $module_url The URL of this module.
|
||||||
|
* @param string $version The assets version.
|
||||||
|
* @param MyBankGateway $gateway MyBank WC gateway.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $module_url,
|
||||||
|
string $version,
|
||||||
|
MyBankGateway $gateway
|
||||||
|
) {
|
||||||
|
$this->module_url = $module_url;
|
||||||
|
$this->version = $version;
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
|
||||||
|
$this->name = MyBankGateway::ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function initialize() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function is_active() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_script_handles() {
|
||||||
|
wp_register_script(
|
||||||
|
'ppcp-mybank-payment-method',
|
||||||
|
trailingslashit( $this->module_url ) . 'assets/js/mybank-payment-method.js',
|
||||||
|
array(),
|
||||||
|
$this->version,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return array( 'ppcp-mybank-payment-method' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_data() {
|
||||||
|
return array(
|
||||||
|
'id' => $this->name,
|
||||||
|
'title' => $this->gateway->title,
|
||||||
|
'description' => $this->gateway->description,
|
||||||
|
'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_mybank_color.svg' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The P24 payment gateway.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use WC_Payment_Gateway;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class P24Gateway
|
||||||
|
*/
|
||||||
|
class P24Gateway extends WC_Payment_Gateway {
|
||||||
|
|
||||||
|
const ID = 'ppcp-p24';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PayPal Orders endpoint.
|
||||||
|
*
|
||||||
|
* @var Orders
|
||||||
|
*/
|
||||||
|
private $orders_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purchase unit factory.
|
||||||
|
*
|
||||||
|
* @var PurchaseUnitFactory
|
||||||
|
*/
|
||||||
|
private $purchase_unit_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refund Processor.
|
||||||
|
*
|
||||||
|
* @var RefundProcessor
|
||||||
|
*/
|
||||||
|
private $refund_processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service able to provide transaction url for an order.
|
||||||
|
*
|
||||||
|
* @var TransactionUrlProvider
|
||||||
|
*/
|
||||||
|
protected $transaction_url_provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P24Gateway constructor.
|
||||||
|
*
|
||||||
|
* @param Orders $orders_endpoint PayPal Orders endpoint.
|
||||||
|
* @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory.
|
||||||
|
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||||
|
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Orders $orders_endpoint,
|
||||||
|
PurchaseUnitFactory $purchase_unit_factory,
|
||||||
|
RefundProcessor $refund_processor,
|
||||||
|
TransactionUrlProvider $transaction_url_provider
|
||||||
|
) {
|
||||||
|
$this->id = self::ID;
|
||||||
|
|
||||||
|
$this->supports = array(
|
||||||
|
'refunds',
|
||||||
|
'products',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->method_title = __( 'Przelewy24', 'woocommerce-paypal-payments' );
|
||||||
|
$this->method_description = __( 'A popular online payment gateway in Poland, offering various payment options for Polish customers. Transactions can be processed in PLN or EUR.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$this->title = $this->get_option( 'title', __( 'Przelewy24', 'woocommerce-paypal-payments' ) );
|
||||||
|
$this->description = $this->get_option( 'description', '' );
|
||||||
|
|
||||||
|
$this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_przelewy24_color.svg' );
|
||||||
|
|
||||||
|
$this->init_form_fields();
|
||||||
|
$this->init_settings();
|
||||||
|
|
||||||
|
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||||
|
|
||||||
|
$this->orders_endpoint = $orders_endpoint;
|
||||||
|
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||||
|
$this->refund_processor = $refund_processor;
|
||||||
|
$this->transaction_url_provider = $transaction_url_provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the form fields.
|
||||||
|
*/
|
||||||
|
public function init_form_fields() {
|
||||||
|
$this->form_fields = array(
|
||||||
|
'enabled' => array(
|
||||||
|
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => __( 'Przelewy24', 'woocommerce-paypal-payments' ),
|
||||||
|
'default' => 'no',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'Enable/Disable Przelewy24 payment gateway.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'title' => array(
|
||||||
|
'title' => __( 'Title', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->title,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'title' => __( 'Description', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->description,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the order.
|
||||||
|
*
|
||||||
|
* @param int $order_id The WC order ID.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function process_payment( $order_id ) {
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
$wc_order->update_status( 'on-hold', __( 'Awaiting Przelewy24 to confirm the payment.', 'woocommerce-paypal-payments' ) );
|
||||||
|
|
||||||
|
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||||
|
$amount = $purchase_unit->amount()->to_array();
|
||||||
|
|
||||||
|
$request_body = array(
|
||||||
|
'intent' => 'CAPTURE',
|
||||||
|
'payment_source' => array(
|
||||||
|
'p24' => array(
|
||||||
|
'country_code' => $wc_order->get_billing_country(),
|
||||||
|
'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(),
|
||||||
|
'email' => $wc_order->get_billing_email(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
|
||||||
|
'purchase_units' => array(
|
||||||
|
array(
|
||||||
|
'reference_id' => $purchase_unit->reference_id(),
|
||||||
|
'amount' => array(
|
||||||
|
'currency_code' => $amount['currency_code'],
|
||||||
|
'value' => $amount['value'],
|
||||||
|
),
|
||||||
|
'custom_id' => $purchase_unit->custom_id(),
|
||||||
|
'invoice_id' => $purchase_unit->invoice_id(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'application_context' => array(
|
||||||
|
'locale' => 'en-PL',
|
||||||
|
'return_url' => $this->get_return_url( $wc_order ),
|
||||||
|
'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $this->orders_endpoint->create( $request_body );
|
||||||
|
} catch ( RuntimeException $exception ) {
|
||||||
|
$wc_order->update_status(
|
||||||
|
'failed',
|
||||||
|
$exception->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'failure',
|
||||||
|
'redirect' => wc_get_checkout_url(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = json_decode( $response['body'] );
|
||||||
|
|
||||||
|
$payer_action = '';
|
||||||
|
foreach ( $body->links as $link ) {
|
||||||
|
if ( $link->rel === 'payer-action' ) {
|
||||||
|
$payer_action = $link->href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WC()->cart->empty_cart();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'success',
|
||||||
|
'redirect' => esc_url( $payer_action ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process refund.
|
||||||
|
*
|
||||||
|
* If the gateway declares 'refunds' support, this will allow it to refund.
|
||||||
|
* a passed in amount.
|
||||||
|
*
|
||||||
|
* @param int $order_id Order ID.
|
||||||
|
* @param float $amount Refund amount.
|
||||||
|
* @param string $reason Refund reason.
|
||||||
|
* @return boolean True or false based on success, or a WP_Error object.
|
||||||
|
*/
|
||||||
|
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
||||||
|
$order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $order, \WC_Order::class ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return transaction url for this gateway and given order.
|
||||||
|
*
|
||||||
|
* @param \WC_Order $order WC order to get transaction url by.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_transaction_url( $order ): string {
|
||||||
|
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||||
|
|
||||||
|
return parent::get_transaction_url( $order );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Przelewy24 payment method.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class P24PaymentMethod
|
||||||
|
*/
|
||||||
|
class P24PaymentMethod extends AbstractPaymentMethodType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of this module.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $module_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The assets version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P24Gateway WC gateway.
|
||||||
|
*
|
||||||
|
* @var P24Gateway
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* P24PaymentMethod constructor.
|
||||||
|
*
|
||||||
|
* @param string $module_url The URL of this module.
|
||||||
|
* @param string $version The assets version.
|
||||||
|
* @param P24Gateway $gateway Przelewy24 WC gateway.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $module_url,
|
||||||
|
string $version,
|
||||||
|
P24Gateway $gateway
|
||||||
|
) {
|
||||||
|
$this->module_url = $module_url;
|
||||||
|
$this->version = $version;
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
|
||||||
|
$this->name = P24Gateway::ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function initialize() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function is_active() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_script_handles() {
|
||||||
|
wp_register_script(
|
||||||
|
'ppcp-p24-payment-method',
|
||||||
|
trailingslashit( $this->module_url ) . 'assets/js/p24-payment-method.js',
|
||||||
|
array(),
|
||||||
|
$this->version,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return array( 'ppcp-p24-payment-method' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_data() {
|
||||||
|
return array(
|
||||||
|
'id' => $this->name,
|
||||||
|
'title' => $this->gateway->title,
|
||||||
|
'description' => $this->gateway->description,
|
||||||
|
'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_przelewy24_color.svg' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,249 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The Trustly payment gateway.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use WC_Payment_Gateway;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TrustlyGateway
|
||||||
|
*/
|
||||||
|
class TrustlyGateway extends WC_Payment_Gateway {
|
||||||
|
|
||||||
|
const ID = 'ppcp-trustly';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PayPal Orders endpoint.
|
||||||
|
*
|
||||||
|
* @var Orders
|
||||||
|
*/
|
||||||
|
private $orders_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purchase unit factory.
|
||||||
|
*
|
||||||
|
* @var PurchaseUnitFactory
|
||||||
|
*/
|
||||||
|
private $purchase_unit_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refund Processor.
|
||||||
|
*
|
||||||
|
* @var RefundProcessor
|
||||||
|
*/
|
||||||
|
private $refund_processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service able to provide transaction url for an order.
|
||||||
|
*
|
||||||
|
* @var TransactionUrlProvider
|
||||||
|
*/
|
||||||
|
protected $transaction_url_provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TrustlyGateway constructor.
|
||||||
|
*
|
||||||
|
* @param Orders $orders_endpoint PayPal Orders endpoint.
|
||||||
|
* @param PurchaseUnitFactory $purchase_unit_factory Purchase unit factory.
|
||||||
|
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||||
|
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Orders $orders_endpoint,
|
||||||
|
PurchaseUnitFactory $purchase_unit_factory,
|
||||||
|
RefundProcessor $refund_processor,
|
||||||
|
TransactionUrlProvider $transaction_url_provider
|
||||||
|
) {
|
||||||
|
$this->id = self::ID;
|
||||||
|
|
||||||
|
$this->supports = array(
|
||||||
|
'refunds',
|
||||||
|
'products',
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->method_title = __( 'Trustly', 'woocommerce-paypal-payments' );
|
||||||
|
$this->method_description = __( 'A European payment method that allows buyers to make payments directly from their bank accounts, suitable for customers across multiple European countries. Supported currencies include EUR, DKK, SEK, GBP, and NOK.', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$this->title = $this->get_option( 'title', __( 'Trustly', 'woocommerce-paypal-payments' ) );
|
||||||
|
$this->description = $this->get_option( 'description', '' );
|
||||||
|
|
||||||
|
$this->icon = esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_trustly_color.svg' );
|
||||||
|
|
||||||
|
$this->init_form_fields();
|
||||||
|
$this->init_settings();
|
||||||
|
|
||||||
|
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||||
|
|
||||||
|
$this->orders_endpoint = $orders_endpoint;
|
||||||
|
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||||
|
$this->refund_processor = $refund_processor;
|
||||||
|
$this->transaction_url_provider = $transaction_url_provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the form fields.
|
||||||
|
*/
|
||||||
|
public function init_form_fields() {
|
||||||
|
$this->form_fields = array(
|
||||||
|
'enabled' => array(
|
||||||
|
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => __( 'Trustly', 'woocommerce-paypal-payments' ),
|
||||||
|
'default' => 'no',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'Enable/Disable Trustly payment gateway.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'title' => array(
|
||||||
|
'title' => __( 'Title', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->title,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'description' => array(
|
||||||
|
'title' => __( 'Description', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'text',
|
||||||
|
'default' => $this->description,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'This controls the description which the user sees during checkout.', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the order.
|
||||||
|
*
|
||||||
|
* @param int $order_id The WC order ID.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function process_payment( $order_id ) {
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
$wc_order->update_status( 'on-hold', __( 'Awaiting Trustly to confirm the payment.', 'woocommerce-paypal-payments' ) );
|
||||||
|
|
||||||
|
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||||
|
$amount = $purchase_unit->amount()->to_array();
|
||||||
|
|
||||||
|
$request_body = array(
|
||||||
|
'intent' => 'CAPTURE',
|
||||||
|
'payment_source' => array(
|
||||||
|
'trustly' => array(
|
||||||
|
'country_code' => $wc_order->get_billing_country(),
|
||||||
|
'name' => $wc_order->get_billing_first_name() . ' ' . $wc_order->get_billing_last_name(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
|
||||||
|
'purchase_units' => array(
|
||||||
|
array(
|
||||||
|
'reference_id' => $purchase_unit->reference_id(),
|
||||||
|
'amount' => array(
|
||||||
|
'currency_code' => $amount['currency_code'],
|
||||||
|
'value' => $amount['value'],
|
||||||
|
),
|
||||||
|
'custom_id' => $purchase_unit->custom_id(),
|
||||||
|
'invoice_id' => $purchase_unit->invoice_id(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'application_context' => array(
|
||||||
|
'locale' => $this->valid_bcp47_code(),
|
||||||
|
'return_url' => $this->get_return_url( $wc_order ),
|
||||||
|
'cancel_url' => add_query_arg( 'cancelled', 'true', $this->get_return_url( $wc_order ) ),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $this->orders_endpoint->create( $request_body );
|
||||||
|
} catch ( RuntimeException $exception ) {
|
||||||
|
$wc_order->update_status(
|
||||||
|
'failed',
|
||||||
|
$exception->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'failure',
|
||||||
|
'redirect' => wc_get_checkout_url(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = json_decode( $response['body'] );
|
||||||
|
|
||||||
|
$payer_action = '';
|
||||||
|
foreach ( $body->links as $link ) {
|
||||||
|
if ( $link->rel === 'payer-action' ) {
|
||||||
|
$payer_action = $link->href;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WC()->cart->empty_cart();
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'result' => 'success',
|
||||||
|
'redirect' => esc_url( $payer_action ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process refund.
|
||||||
|
*
|
||||||
|
* If the gateway declares 'refunds' support, this will allow it to refund.
|
||||||
|
* a passed in amount.
|
||||||
|
*
|
||||||
|
* @param int $order_id Order ID.
|
||||||
|
* @param float $amount Refund amount.
|
||||||
|
* @param string $reason Refund reason.
|
||||||
|
* @return boolean True or false based on success, or a WP_Error object.
|
||||||
|
*/
|
||||||
|
public function process_refund( $order_id, $amount = null, $reason = '' ) {
|
||||||
|
$order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $order, \WC_Order::class ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return transaction url for this gateway and given order.
|
||||||
|
*
|
||||||
|
* @param \WC_Order $order WC order to get transaction url by.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_transaction_url( $order ): string {
|
||||||
|
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||||
|
|
||||||
|
return parent::get_transaction_url( $order );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a PayPal-supported BCP-47 code, for example de-DE-formal becomes de-DE.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function valid_bcp47_code() {
|
||||||
|
$locale = str_replace( '_', '-', get_user_locale() );
|
||||||
|
|
||||||
|
if ( preg_match( '/^[a-z]{2}(?:-[A-Z][a-z]{3})?(?:-(?:[A-Z]{2}))?$/', $locale ) ) {
|
||||||
|
return $locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parts = explode( '-', $locale );
|
||||||
|
if ( count( $parts ) === 3 ) {
|
||||||
|
$ret = substr( $locale, 0, strrpos( $locale, '-' ) );
|
||||||
|
if ( false !== $ret ) {
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'en';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Trustly payment method.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods;
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TrustlyPaymentMethod
|
||||||
|
*/
|
||||||
|
class TrustlyPaymentMethod extends AbstractPaymentMethodType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of this module.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $module_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The assets version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TrustlyGateway WC gateway.
|
||||||
|
*
|
||||||
|
* @var TrustlyGateway
|
||||||
|
*/
|
||||||
|
private $gateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TrustlyPaymentMethod constructor.
|
||||||
|
*
|
||||||
|
* @param string $module_url The URL of this module.
|
||||||
|
* @param string $version The assets version.
|
||||||
|
* @param TrustlyGateway $gateway Trustly WC gateway.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $module_url,
|
||||||
|
string $version,
|
||||||
|
TrustlyGateway $gateway
|
||||||
|
) {
|
||||||
|
$this->module_url = $module_url;
|
||||||
|
$this->version = $version;
|
||||||
|
$this->gateway = $gateway;
|
||||||
|
|
||||||
|
$this->name = TrustlyGateway::ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function initialize() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function is_active() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_script_handles() {
|
||||||
|
wp_register_script(
|
||||||
|
'ppcp-trustly-payment-method',
|
||||||
|
trailingslashit( $this->module_url ) . 'assets/js/trustly-payment-method.js',
|
||||||
|
array(),
|
||||||
|
$this->version,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return array( 'ppcp-trustly-payment-method' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_payment_method_data() {
|
||||||
|
return array(
|
||||||
|
'id' => $this->name,
|
||||||
|
'title' => $this->gateway->title,
|
||||||
|
'description' => $this->gateway->description,
|
||||||
|
'icon' => esc_url( 'https://www.paypalobjects.com/images/checkout/alternative_payments/paypal_trustly_color.svg' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
const path = require( 'path' );
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
|
const DependencyExtractionWebpackPlugin = require( '@woocommerce/dependency-extraction-webpack-plugin' );
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
||||||
|
mode: isProduction ? 'production' : 'development',
|
||||||
|
target: 'web',
|
||||||
|
plugins: [ new DependencyExtractionWebpackPlugin() ],
|
||||||
|
entry: {
|
||||||
|
'bancontact-payment-method': path.resolve(
|
||||||
|
'./resources/js/bancontact-payment-method.js'
|
||||||
|
),
|
||||||
|
'blik-payment-method': path.resolve(
|
||||||
|
'./resources/js/blik-payment-method.js'
|
||||||
|
),
|
||||||
|
'eps-payment-method': path.resolve(
|
||||||
|
'./resources/js/eps-payment-method.js'
|
||||||
|
),
|
||||||
|
'ideal-payment-method': path.resolve(
|
||||||
|
'./resources/js/ideal-payment-method.js'
|
||||||
|
),
|
||||||
|
'mybank-payment-method': path.resolve(
|
||||||
|
'./resources/js/mybank-payment-method.js'
|
||||||
|
),
|
||||||
|
'p24-payment-method': path.resolve(
|
||||||
|
'./resources/js/p24-payment-method.js'
|
||||||
|
),
|
||||||
|
'trustly-payment-method': path.resolve(
|
||||||
|
'./resources/js/trustly-payment-method.js'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.resolve( __dirname, 'assets/' ),
|
||||||
|
filename: 'js/[name].js',
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'babel-loader',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.scss$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: 'file-loader',
|
||||||
|
options: {
|
||||||
|
name: 'css/[name].css',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ loader: 'sass-loader' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
2247
modules/ppcp-local-alternative-payment-methods/yarn.lock
Normal file
2247
modules/ppcp-local-alternative-payment-methods/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\OrderTracking;
|
namespace WooCommerce\PayPalCommerce\OrderTracking;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\OrderTracking\Integration\DhlShipmentIntegration;
|
||||||
use WooCommerce\PayPalCommerce\OrderTracking\Integration\GermanizedShipmentIntegration;
|
use WooCommerce\PayPalCommerce\OrderTracking\Integration\GermanizedShipmentIntegration;
|
||||||
use WooCommerce\PayPalCommerce\OrderTracking\Integration\ShipmentTrackingIntegration;
|
use WooCommerce\PayPalCommerce\OrderTracking\Integration\ShipmentTrackingIntegration;
|
||||||
use WooCommerce\PayPalCommerce\OrderTracking\Integration\ShipStationIntegration;
|
use WooCommerce\PayPalCommerce\OrderTracking\Integration\ShipStationIntegration;
|
||||||
|
@ -118,6 +119,7 @@ return array(
|
||||||
$is_gzd_active = $container->get( 'compat.gzd.is_supported_plugin_version_active' );
|
$is_gzd_active = $container->get( 'compat.gzd.is_supported_plugin_version_active' );
|
||||||
$is_wc_shipment_active = $container->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' );
|
$is_wc_shipment_active = $container->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' );
|
||||||
$is_yith_ywot_active = $container->get( 'compat.ywot.is_supported_plugin_version_active' );
|
$is_yith_ywot_active = $container->get( 'compat.ywot.is_supported_plugin_version_active' );
|
||||||
|
$is_dhl_de_active = $container->get( 'compat.dhl.is_supported_plugin_version_active' );
|
||||||
$is_ship_station_active = $container->get( 'compat.shipstation.is_supported_plugin_version_active' );
|
$is_ship_station_active = $container->get( 'compat.shipstation.is_supported_plugin_version_active' );
|
||||||
$is_wc_shipping_tax_active = $container->get( 'compat.wc_shipping_tax.is_supported_plugin_version_active' );
|
$is_wc_shipping_tax_active = $container->get( 'compat.wc_shipping_tax.is_supported_plugin_version_active' );
|
||||||
|
|
||||||
|
@ -135,6 +137,10 @@ return array(
|
||||||
$integrations[] = new YithShipmentIntegration( $shipment_factory, $logger, $endpoint );
|
$integrations[] = new YithShipmentIntegration( $shipment_factory, $logger, $endpoint );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $is_dhl_de_active ) {
|
||||||
|
$integrations[] = new DhlShipmentIntegration( $shipment_factory, $logger, $endpoint );
|
||||||
|
}
|
||||||
|
|
||||||
if ( $is_ship_station_active ) {
|
if ( $is_ship_station_active ) {
|
||||||
$integrations[] = new ShipStationIntegration( $shipment_factory, $logger, $endpoint );
|
$integrations[] = new ShipStationIntegration( $shipment_factory, $logger, $endpoint );
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The Shipment integration for DHL Shipping Germany for WooCommerce plugin.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\OrderTracking\Integration
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\OrderTracking\Integration;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use WC_Order;
|
||||||
|
use Exception;
|
||||||
|
use WooCommerce\PayPalCommerce\Compat\Integration;
|
||||||
|
use WooCommerce\PayPalCommerce\OrderTracking\Endpoint\OrderTrackingEndpoint;
|
||||||
|
use WooCommerce\PayPalCommerce\OrderTracking\Shipment\ShipmentFactoryInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||||
|
use function WooCommerce\PayPalCommerce\Api\ppcp_get_paypal_order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class DhlShipmentIntegration
|
||||||
|
*/
|
||||||
|
class DhlShipmentIntegration implements Integration {
|
||||||
|
|
||||||
|
use TransactionIdHandlingTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shipment factory.
|
||||||
|
*
|
||||||
|
* @var ShipmentFactoryInterface
|
||||||
|
*/
|
||||||
|
protected $shipment_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
|
protected $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The order tracking endpoint.
|
||||||
|
*
|
||||||
|
* @var OrderTrackingEndpoint
|
||||||
|
*/
|
||||||
|
protected $endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DhlShipmentIntegration constructor.
|
||||||
|
*
|
||||||
|
* @param ShipmentFactoryInterface $shipment_factory The shipment factory.
|
||||||
|
* @param LoggerInterface $logger The logger.
|
||||||
|
* @param OrderTrackingEndpoint $endpoint The order tracking endpoint.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
ShipmentFactoryInterface $shipment_factory,
|
||||||
|
LoggerInterface $logger,
|
||||||
|
OrderTrackingEndpoint $endpoint
|
||||||
|
) {
|
||||||
|
$this->shipment_factory = $shipment_factory;
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->endpoint = $endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function integrate(): void {
|
||||||
|
add_action(
|
||||||
|
'pr_save_dhl_label_tracking',
|
||||||
|
function( int $order_id, array $tracking_details ) {
|
||||||
|
try {
|
||||||
|
$wc_order = wc_get_order( $order_id );
|
||||||
|
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$paypal_order = ppcp_get_paypal_order( $wc_order );
|
||||||
|
$capture_id = $this->get_paypal_order_transaction_id( $paypal_order );
|
||||||
|
$tracking_number = $tracking_details['tracking_number'];
|
||||||
|
$carrier = $tracking_details['carrier'];
|
||||||
|
|
||||||
|
if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $capture_id ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ppcp_shipment = $this->shipment_factory->create_shipment(
|
||||||
|
$order_id,
|
||||||
|
$capture_id,
|
||||||
|
$tracking_number,
|
||||||
|
'SHIPPED',
|
||||||
|
'DE_DHL',
|
||||||
|
$carrier,
|
||||||
|
array()
|
||||||
|
);
|
||||||
|
|
||||||
|
$tracking_information = $this->endpoint->get_tracking_information( $order_id, $tracking_number );
|
||||||
|
|
||||||
|
$tracking_information
|
||||||
|
? $this->endpoint->update_tracking_information( $ppcp_shipment, $order_id )
|
||||||
|
: $this->endpoint->add_tracking_information( $ppcp_shipment, $order_id );
|
||||||
|
|
||||||
|
} catch ( Exception $exception ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
600,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
230
modules/ppcp-save-payment-methods/resources/js/Configuration.js
Normal file
230
modules/ppcp-save-payment-methods/resources/js/Configuration.js
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
import {
|
||||||
|
getCurrentPaymentMethod,
|
||||||
|
PaymentMethods,
|
||||||
|
} from '../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState';
|
||||||
|
|
||||||
|
export function buttonConfiguration( ppcp_add_payment_method, errorHandler ) {
|
||||||
|
return {
|
||||||
|
createVaultSetupToken: async () => {
|
||||||
|
const response = await fetch(
|
||||||
|
ppcp_add_payment_method.ajax.create_setup_token.endpoint,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify( {
|
||||||
|
nonce: ppcp_add_payment_method.ajax.create_setup_token
|
||||||
|
.nonce,
|
||||||
|
} ),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
if ( result.data.id ) {
|
||||||
|
return result.data.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorHandler.message( ppcp_add_payment_method.error_message );
|
||||||
|
},
|
||||||
|
onApprove: async ( { vaultSetupToken } ) => {
|
||||||
|
const response = await fetch(
|
||||||
|
ppcp_add_payment_method.ajax.create_payment_token.endpoint,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify( {
|
||||||
|
nonce: ppcp_add_payment_method.ajax.create_payment_token
|
||||||
|
.nonce,
|
||||||
|
vault_setup_token: vaultSetupToken,
|
||||||
|
} ),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
if ( result.success === true ) {
|
||||||
|
window.location.href =
|
||||||
|
ppcp_add_payment_method.payment_methods_page;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorHandler.message( ppcp_add_payment_method.error_message );
|
||||||
|
},
|
||||||
|
onError: ( error ) => {
|
||||||
|
console.error( error );
|
||||||
|
errorHandler.message( ppcp_add_payment_method.error_message );
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cardFieldsConfiguration(
|
||||||
|
ppcp_add_payment_method,
|
||||||
|
errorHandler
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
createVaultSetupToken: async () => {
|
||||||
|
const response = await fetch(
|
||||||
|
ppcp_add_payment_method.ajax.create_setup_token.endpoint,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify( {
|
||||||
|
nonce: ppcp_add_payment_method.ajax.create_setup_token
|
||||||
|
.nonce,
|
||||||
|
payment_method: PaymentMethods.CARDS,
|
||||||
|
verification_method:
|
||||||
|
ppcp_add_payment_method.verification_method,
|
||||||
|
} ),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
if ( result.data.id ) {
|
||||||
|
return result.data.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorHandler.message( ppcp_add_payment_method.error_message );
|
||||||
|
},
|
||||||
|
onApprove: async ( { vaultSetupToken } ) => {
|
||||||
|
const isFreeTrialCart =
|
||||||
|
ppcp_add_payment_method?.is_free_trial_cart ?? false;
|
||||||
|
const response = await fetch(
|
||||||
|
ppcp_add_payment_method.ajax.create_payment_token.endpoint,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify( {
|
||||||
|
nonce: ppcp_add_payment_method.ajax.create_payment_token
|
||||||
|
.nonce,
|
||||||
|
vault_setup_token: vaultSetupToken,
|
||||||
|
payment_method: PaymentMethods.CARDS,
|
||||||
|
is_free_trial_cart: isFreeTrialCart,
|
||||||
|
} ),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
if ( result.success === true ) {
|
||||||
|
const context = ppcp_add_payment_method?.context ?? '';
|
||||||
|
if ( context === 'checkout' ) {
|
||||||
|
document.querySelector( '#place_order' ).click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
ppcp_add_payment_method.is_subscription_change_payment_page
|
||||||
|
) {
|
||||||
|
const subscriptionId =
|
||||||
|
ppcp_add_payment_method.subscription_id_to_change_payment;
|
||||||
|
if ( subscriptionId && result.data ) {
|
||||||
|
const req = await fetch(
|
||||||
|
ppcp_add_payment_method.ajax
|
||||||
|
.subscription_change_payment_method.endpoint,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify( {
|
||||||
|
nonce: ppcp_add_payment_method.ajax
|
||||||
|
.subscription_change_payment_method
|
||||||
|
.nonce,
|
||||||
|
subscription_id: subscriptionId,
|
||||||
|
payment_method: getCurrentPaymentMethod(),
|
||||||
|
wc_payment_token_id: result.data,
|
||||||
|
} ),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const res = await req.json();
|
||||||
|
if ( res.success === true ) {
|
||||||
|
window.location.href = `${ ppcp_add_payment_method.view_subscriptions_page }/${ subscriptionId }`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.href =
|
||||||
|
ppcp_add_payment_method.payment_methods_page;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.errorHandler.message( ppcp_add_payment_method.error_message );
|
||||||
|
},
|
||||||
|
onError: ( error ) => {
|
||||||
|
console.error( error );
|
||||||
|
errorHandler.message( ppcp_add_payment_method.error_message );
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addPaymentMethodConfiguration( ppcp_add_payment_method ) {
|
||||||
|
return {
|
||||||
|
createVaultSetupToken: async () => {
|
||||||
|
const response = await fetch(
|
||||||
|
ppcp_add_payment_method.ajax.create_setup_token.endpoint,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify( {
|
||||||
|
nonce: ppcp_add_payment_method.ajax.create_setup_token
|
||||||
|
.nonce,
|
||||||
|
payment_method: getCurrentPaymentMethod(),
|
||||||
|
} ),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
if ( result.data.id ) {
|
||||||
|
return result.data.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error( result );
|
||||||
|
},
|
||||||
|
onApprove: async ( { vaultSetupToken } ) => {
|
||||||
|
const response = await fetch(
|
||||||
|
ppcp_add_payment_method.ajax.create_payment_token_for_guest
|
||||||
|
.endpoint,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify( {
|
||||||
|
nonce: ppcp_add_payment_method.ajax
|
||||||
|
.create_payment_token_for_guest.nonce,
|
||||||
|
vault_setup_token: vaultSetupToken,
|
||||||
|
} ),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
if ( result.success === true ) {
|
||||||
|
document.querySelector( '#place_order' ).click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error( result );
|
||||||
|
},
|
||||||
|
onError: ( error ) => {
|
||||||
|
console.error( error );
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
|
@ -4,19 +4,20 @@ import {
|
||||||
PaymentMethods,
|
PaymentMethods,
|
||||||
} from '../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState';
|
} from '../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState';
|
||||||
import { loadScript } from '@paypal/paypal-js';
|
import { loadScript } from '@paypal/paypal-js';
|
||||||
|
import ErrorHandler from '../../../ppcp-button/resources/js/modules/ErrorHandler';
|
||||||
|
import { buttonConfiguration, cardFieldsConfiguration } from './Configuration';
|
||||||
|
import { renderFields } from '../../../ppcp-card-fields/resources/js/Render';
|
||||||
import {
|
import {
|
||||||
setVisible,
|
setVisible,
|
||||||
setVisibleByClass,
|
setVisibleByClass,
|
||||||
} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
||||||
import ErrorHandler from '../../../ppcp-button/resources/js/modules/ErrorHandler';
|
|
||||||
import { cardFieldStyles } from '../../../ppcp-button/resources/js/modules/Helper/CardFieldsHelper';
|
|
||||||
|
|
||||||
const errorHandler = new ErrorHandler(
|
( function ( { ppcp_add_payment_method, jQuery } ) {
|
||||||
ppcp_add_payment_method.labels.error.generic,
|
document.addEventListener( 'DOMContentLoaded', () => {
|
||||||
document.querySelector( '.woocommerce-notices-wrapper' )
|
jQuery( document.body ).on(
|
||||||
);
|
'click init_add_payment_method',
|
||||||
|
'.payment_methods input.input-radio',
|
||||||
const init = () => {
|
function () {
|
||||||
setVisibleByClass(
|
setVisibleByClass(
|
||||||
ORDER_BUTTON_SELECTOR,
|
ORDER_BUTTON_SELECTOR,
|
||||||
getCurrentPaymentMethod() !== PaymentMethods.PAYPAL,
|
getCurrentPaymentMethod() !== PaymentMethods.PAYPAL,
|
||||||
|
@ -26,17 +27,10 @@ const init = () => {
|
||||||
`#ppc-button-${ PaymentMethods.PAYPAL }-save-payment-method`,
|
`#ppc-button-${ PaymentMethods.PAYPAL }-save-payment-method`,
|
||||||
getCurrentPaymentMethod() === PaymentMethods.PAYPAL
|
getCurrentPaymentMethod() === PaymentMethods.PAYPAL
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener( 'DOMContentLoaded', () => {
|
|
||||||
jQuery( document.body ).on(
|
|
||||||
'click init_add_payment_method',
|
|
||||||
'.payment_methods input.input-radio',
|
|
||||||
function () {
|
|
||||||
init();
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO move to wc subscriptions module
|
||||||
if ( ppcp_add_payment_method.is_subscription_change_payment_page ) {
|
if ( ppcp_add_payment_method.is_subscription_change_payment_page ) {
|
||||||
const saveToAccount = document.querySelector(
|
const saveToAccount = document.querySelector(
|
||||||
'#wc-ppcp-credit-card-gateway-new-payment-method'
|
'#wc-ppcp-credit-card-gateway-new-payment-method'
|
||||||
|
@ -54,231 +48,38 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
||||||
dataUserIdToken: ppcp_add_payment_method.id_token,
|
dataUserIdToken: ppcp_add_payment_method.id_token,
|
||||||
components: 'buttons,card-fields',
|
components: 'buttons,card-fields',
|
||||||
} ).then( ( paypal ) => {
|
} ).then( ( paypal ) => {
|
||||||
|
const errorHandler = new ErrorHandler(
|
||||||
|
ppcp_add_payment_method.labels.error.generic,
|
||||||
|
document.querySelector( '.woocommerce-notices-wrapper' )
|
||||||
|
);
|
||||||
errorHandler.clear();
|
errorHandler.clear();
|
||||||
|
|
||||||
const paypalButtonContainer = document.querySelector(
|
const paypalButtonContainer = document.querySelector(
|
||||||
`#ppc-button-${ PaymentMethods.PAYPAL }-save-payment-method`
|
`#ppc-button-${ PaymentMethods.PAYPAL }-save-payment-method`
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( paypalButtonContainer ) {
|
if ( paypalButtonContainer ) {
|
||||||
paypal
|
paypal
|
||||||
.Buttons( {
|
.Buttons(
|
||||||
createVaultSetupToken: async () => {
|
buttonConfiguration(
|
||||||
const response = await fetch(
|
ppcp_add_payment_method,
|
||||||
ppcp_add_payment_method.ajax.create_setup_token
|
errorHandler
|
||||||
.endpoint,
|
)
|
||||||
{
|
)
|
||||||
method: 'POST',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify( {
|
|
||||||
nonce: ppcp_add_payment_method.ajax
|
|
||||||
.create_setup_token.nonce,
|
|
||||||
} ),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
if ( result.data.id ) {
|
|
||||||
return result.data.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorHandler.message(
|
|
||||||
ppcp_add_payment_method.error_message
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onApprove: async ( { vaultSetupToken } ) => {
|
|
||||||
const response = await fetch(
|
|
||||||
ppcp_add_payment_method.ajax
|
|
||||||
.create_payment_token.endpoint,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify( {
|
|
||||||
nonce: ppcp_add_payment_method.ajax
|
|
||||||
.create_payment_token.nonce,
|
|
||||||
vault_setup_token: vaultSetupToken,
|
|
||||||
} ),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
if ( result.success === true ) {
|
|
||||||
window.location.href =
|
|
||||||
ppcp_add_payment_method.payment_methods_page;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorHandler.message(
|
|
||||||
ppcp_add_payment_method.error_message
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onError: ( error ) => {
|
|
||||||
console.error( error );
|
|
||||||
errorHandler.message(
|
|
||||||
ppcp_add_payment_method.error_message
|
|
||||||
);
|
|
||||||
},
|
|
||||||
} )
|
|
||||||
.render(
|
.render(
|
||||||
`#ppc-button-${ PaymentMethods.PAYPAL }-save-payment-method`
|
`#ppc-button-${ PaymentMethods.PAYPAL }-save-payment-method`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cardField = paypal.CardFields( {
|
const cardFields = paypal.CardFields(
|
||||||
createVaultSetupToken: async () => {
|
cardFieldsConfiguration(
|
||||||
const response = await fetch(
|
ppcp_add_payment_method,
|
||||||
ppcp_add_payment_method.ajax.create_setup_token
|
errorHandler
|
||||||
.endpoint,
|
)
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify( {
|
|
||||||
nonce: ppcp_add_payment_method.ajax
|
|
||||||
.create_setup_token.nonce,
|
|
||||||
payment_method: PaymentMethods.CARDS,
|
|
||||||
verification_method:
|
|
||||||
ppcp_add_payment_method.verification_method,
|
|
||||||
} ),
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = await response.json();
|
if ( cardFields.isEligible() ) {
|
||||||
if ( result.data.id ) {
|
renderFields( cardFields );
|
||||||
return result.data.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorHandler.message(
|
|
||||||
ppcp_add_payment_method.error_message
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onApprove: async ( { vaultSetupToken } ) => {
|
|
||||||
const response = await fetch(
|
|
||||||
ppcp_add_payment_method.ajax.create_payment_token
|
|
||||||
.endpoint,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify( {
|
|
||||||
nonce: ppcp_add_payment_method.ajax
|
|
||||||
.create_payment_token.nonce,
|
|
||||||
vault_setup_token: vaultSetupToken,
|
|
||||||
payment_method: PaymentMethods.CARDS,
|
|
||||||
} ),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
if ( result.success === true ) {
|
|
||||||
if (
|
|
||||||
ppcp_add_payment_method.is_subscription_change_payment_page
|
|
||||||
) {
|
|
||||||
const subscriptionId =
|
|
||||||
ppcp_add_payment_method.subscription_id_to_change_payment;
|
|
||||||
if ( subscriptionId && result.data ) {
|
|
||||||
const req = await fetch(
|
|
||||||
ppcp_add_payment_method.ajax
|
|
||||||
.subscription_change_payment_method
|
|
||||||
.endpoint,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify( {
|
|
||||||
nonce: ppcp_add_payment_method.ajax
|
|
||||||
.subscription_change_payment_method
|
|
||||||
.nonce,
|
|
||||||
subscription_id: subscriptionId,
|
|
||||||
payment_method:
|
|
||||||
getCurrentPaymentMethod(),
|
|
||||||
wc_payment_token_id: result.data,
|
|
||||||
} ),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const res = await req.json();
|
|
||||||
if ( res.success === true ) {
|
|
||||||
window.location.href = `${ ppcp_add_payment_method.view_subscriptions_page }/${ subscriptionId }`;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.location.href =
|
|
||||||
ppcp_add_payment_method.payment_methods_page;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorHandler.message(
|
|
||||||
ppcp_add_payment_method.error_message
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onError: ( error ) => {
|
|
||||||
console.error( error );
|
|
||||||
errorHandler.message(
|
|
||||||
ppcp_add_payment_method.error_message
|
|
||||||
);
|
|
||||||
},
|
|
||||||
} );
|
|
||||||
|
|
||||||
if ( cardField.isEligible() ) {
|
|
||||||
const nameField = document.getElementById(
|
|
||||||
'ppcp-credit-card-gateway-card-name'
|
|
||||||
);
|
|
||||||
if ( nameField ) {
|
|
||||||
const styles = cardFieldStyles( nameField );
|
|
||||||
cardField
|
|
||||||
.NameField( { style: { input: styles } } )
|
|
||||||
.render( nameField.parentNode );
|
|
||||||
nameField.hidden = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const numberField = document.getElementById(
|
|
||||||
'ppcp-credit-card-gateway-card-number'
|
|
||||||
);
|
|
||||||
if ( numberField ) {
|
|
||||||
const styles = cardFieldStyles( numberField );
|
|
||||||
cardField
|
|
||||||
.NumberField( { style: { input: styles } } )
|
|
||||||
.render( numberField.parentNode );
|
|
||||||
numberField.hidden = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const expiryField = document.getElementById(
|
|
||||||
'ppcp-credit-card-gateway-card-expiry'
|
|
||||||
);
|
|
||||||
if ( expiryField ) {
|
|
||||||
const styles = cardFieldStyles( expiryField );
|
|
||||||
cardField
|
|
||||||
.ExpiryField( { style: { input: styles } } )
|
|
||||||
.render( expiryField.parentNode );
|
|
||||||
expiryField.hidden = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cvvField = document.getElementById(
|
|
||||||
'ppcp-credit-card-gateway-card-cvc'
|
|
||||||
);
|
|
||||||
if ( cvvField ) {
|
|
||||||
const styles = cardFieldStyles( cvvField );
|
|
||||||
cardField
|
|
||||||
.CVVField( { style: { input: styles } } )
|
|
||||||
.render( cvvField.parentNode );
|
|
||||||
cvvField.hidden = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document
|
document
|
||||||
|
@ -297,10 +98,14 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
cardField.submit().catch( ( error ) => {
|
cardFields.submit().catch( ( error ) => {
|
||||||
console.error( error );
|
console.error( error );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
}, 1000 );
|
}, 1000 );
|
||||||
} );
|
} );
|
||||||
|
} )( {
|
||||||
|
ppcp_add_payment_method: window.ppcp_add_payment_method,
|
||||||
|
jQuery: window.jQuery,
|
||||||
|
} );
|
||||||
|
|
|
@ -115,6 +115,11 @@ class CreatePaymentToken implements EndpointInterface {
|
||||||
|
|
||||||
if ( isset( $result->payment_source->card ) ) {
|
if ( isset( $result->payment_source->card ) ) {
|
||||||
$wc_token_id = $this->wc_payment_tokens->create_payment_token_card( $current_user_id, $result );
|
$wc_token_id = $this->wc_payment_tokens->create_payment_token_card( $current_user_id, $result );
|
||||||
|
|
||||||
|
$is_free_trial_cart = $data['is_free_trial_cart'] ?? '';
|
||||||
|
if ( $is_free_trial_cart === '1' ) {
|
||||||
|
WC()->session->set( 'ppcp_card_payment_token_for_free_trial', $wc_token_id );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\SectionsRenderer;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer;
|
||||||
|
use WooCommerce\PayPalCommerce\Applepay\ApplePayGateway;
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'wcgateway.paypal-gateway' => static function ( ContainerInterface $container ): PayPalGateway {
|
'wcgateway.paypal-gateway' => static function ( ContainerInterface $container ): PayPalGateway {
|
||||||
|
@ -198,6 +199,7 @@ return array(
|
||||||
Settings::PAY_LATER_TAB_ID,
|
Settings::PAY_LATER_TAB_ID,
|
||||||
AxoGateway::ID,
|
AxoGateway::ID,
|
||||||
GooglePayGateway::ID,
|
GooglePayGateway::ID,
|
||||||
|
ApplePayGateway::ID,
|
||||||
),
|
),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -220,6 +222,7 @@ return array(
|
||||||
Settings::PAY_LATER_TAB_ID,
|
Settings::PAY_LATER_TAB_ID,
|
||||||
Settings::CONNECTION_TAB_ID,
|
Settings::CONNECTION_TAB_ID,
|
||||||
GooglePayGateway::ID,
|
GooglePayGateway::ID,
|
||||||
|
ApplePayGateway::ID,
|
||||||
),
|
),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
@ -1411,10 +1414,10 @@ return array(
|
||||||
return $label;
|
return $label;
|
||||||
},
|
},
|
||||||
'wcgateway.enable-dcc-url-sandbox' => static function ( ContainerInterface $container ): string {
|
'wcgateway.enable-dcc-url-sandbox' => static function ( ContainerInterface $container ): string {
|
||||||
return 'https://www.sandbox.paypal.com/bizsignup/entry/product/ppcp';
|
return 'https://www.sandbox.paypal.com/bizsignup/entry?product=ppcp';
|
||||||
},
|
},
|
||||||
'wcgateway.enable-dcc-url-live' => static function ( ContainerInterface $container ): string {
|
'wcgateway.enable-dcc-url-live' => static function ( ContainerInterface $container ): string {
|
||||||
return 'https://www.paypal.com/bizsignup/entry/product/ppcp';
|
return 'https://www.paypal.com/bizsignup/entry?product=ppcp';
|
||||||
},
|
},
|
||||||
'wcgateway.enable-pui-url-sandbox' => static function ( ContainerInterface $container ): string {
|
'wcgateway.enable-pui-url-sandbox' => static function ( ContainerInterface $container ): string {
|
||||||
return 'https://www.sandbox.paypal.com/bizsignup/entry?country.x=DE&product=payment_methods&capabilities=PAY_UPON_INVOICE';
|
return 'https://www.sandbox.paypal.com/bizsignup/entry?country.x=DE&product=payment_methods&capabilities=PAY_UPON_INVOICE';
|
||||||
|
|
|
@ -426,12 +426,42 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
||||||
public function process_payment( $order_id ) {
|
public function process_payment( $order_id ) {
|
||||||
$wc_order = wc_get_order( $order_id );
|
$wc_order = wc_get_order( $order_id );
|
||||||
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
if ( ! is_a( $wc_order, WC_Order::class ) ) {
|
||||||
|
WC()->session->set( 'ppcp_card_payment_token_for_free_trial', null );
|
||||||
|
|
||||||
return $this->handle_payment_failure(
|
return $this->handle_payment_failure(
|
||||||
null,
|
null,
|
||||||
new GatewayGenericException( new Exception( 'WC order was not found.' ) )
|
new GatewayGenericException( new Exception( 'WC order was not found.' ) )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$guest_card_payment_for_free_trial = WC()->session->get( 'ppcp_guest_payment_for_free_trial' ) ?? null;
|
||||||
|
WC()->session->get( 'ppcp_guest_payment_for_free_trial', null );
|
||||||
|
if ( $guest_card_payment_for_free_trial ) {
|
||||||
|
$customer_id = $guest_card_payment_for_free_trial->customer->id ?? '';
|
||||||
|
if ( $customer_id ) {
|
||||||
|
update_user_meta( $wc_order->get_customer_id(), '_ppcp_target_customer_id', $customer_id );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isset( $guest_card_payment_for_free_trial->payment_source->card ) ) {
|
||||||
|
$this->wc_payment_tokens->create_payment_token_card( $wc_order->get_customer_id(), $guest_card_payment_for_free_trial );
|
||||||
|
|
||||||
|
$wc_order->payment_complete();
|
||||||
|
return $this->handle_payment_success( $wc_order );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$card_payment_token_for_free_trial = WC()->session->get( 'ppcp_card_payment_token_for_free_trial' ) ?? null;
|
||||||
|
WC()->session->set( 'ppcp_card_payment_token_for_free_trial', null );
|
||||||
|
if ( $card_payment_token_for_free_trial ) {
|
||||||
|
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id() );
|
||||||
|
foreach ( $tokens as $token ) {
|
||||||
|
if ( $token->get_id() === (int) $card_payment_token_for_free_trial ) {
|
||||||
|
$wc_order->payment_complete();
|
||||||
|
return $this->handle_payment_success( $wc_order );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||||
$card_payment_token_id = wc_clean( wp_unslash( $_POST['wc-ppcp-credit-card-gateway-payment-token'] ?? '' ) );
|
$card_payment_token_id = wc_clean( wp_unslash( $_POST['wc-ppcp-credit-card-gateway-payment-token'] ?? '' ) );
|
||||||
|
|
||||||
|
|
|
@ -118,18 +118,15 @@ class Settings implements ContainerInterface {
|
||||||
* Stores the settings to the database.
|
* Stores the settings to the database.
|
||||||
*/
|
*/
|
||||||
public function persist() {
|
public function persist() {
|
||||||
|
|
||||||
return update_option( self::KEY, $this->settings );
|
return update_option( self::KEY, $this->settings );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the settings.
|
* Loads the settings.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function load(): bool {
|
private function load(): bool {
|
||||||
|
|
||||||
if ( $this->settings ) {
|
if ( $this->settings ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message;
|
use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\Orders;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"install:modules:ppcp-paylater-configurator": "cd modules/ppcp-paylater-configurator && yarn install",
|
"install:modules:ppcp-paylater-configurator": "cd modules/ppcp-paylater-configurator && yarn install",
|
||||||
"install:modules:ppcp-button": "cd modules/ppcp-button && yarn install",
|
"install:modules:ppcp-button": "cd modules/ppcp-button && yarn install",
|
||||||
"install:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn install",
|
"install:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn install",
|
||||||
|
"install:modules:ppcp-local-alternative-payment-methods": "cd modules/ppcp-local-alternative-payment-methods && yarn install",
|
||||||
"install:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn install",
|
"install:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn install",
|
||||||
"install:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn install",
|
"install:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn install",
|
||||||
"install:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn install",
|
"install:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn install",
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
"install:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn install",
|
"install:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn install",
|
||||||
"install:modules:ppcp-axo": "cd modules/ppcp-axo && yarn install",
|
"install:modules:ppcp-axo": "cd modules/ppcp-axo && yarn install",
|
||||||
"install:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn install",
|
"install:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn install",
|
||||||
|
"install:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn install",
|
||||||
"install:modules:ppcp-compat": "cd modules/ppcp-compat && yarn install",
|
"install:modules:ppcp-compat": "cd modules/ppcp-compat && yarn install",
|
||||||
"install:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn install",
|
"install:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn install",
|
||||||
"build:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run build",
|
"build:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run build",
|
||||||
|
@ -30,6 +32,7 @@
|
||||||
"build:modules:ppcp-paylater-configurator": "cd modules/ppcp-paylater-configurator && yarn run build",
|
"build:modules:ppcp-paylater-configurator": "cd modules/ppcp-paylater-configurator && yarn run build",
|
||||||
"build:modules:ppcp-button": "cd modules/ppcp-button && yarn run build",
|
"build:modules:ppcp-button": "cd modules/ppcp-button && yarn run build",
|
||||||
"build:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run build",
|
"build:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run build",
|
||||||
|
"build:modules:ppcp-local-alternative-payment-methods": "cd modules/ppcp-local-alternative-payment-methods && yarn run build",
|
||||||
"build:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run build",
|
"build:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run build",
|
||||||
"build:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run build",
|
"build:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run build",
|
||||||
"build:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run build",
|
"build:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run build",
|
||||||
|
@ -37,6 +40,7 @@
|
||||||
"build:modules:ppcp-axo": "cd modules/ppcp-axo && yarn run build",
|
"build:modules:ppcp-axo": "cd modules/ppcp-axo && yarn run build",
|
||||||
"build:modules:ppcp-paypal-subscriptions": "cd modules/ppcp-paypal-subscriptions && yarn run build",
|
"build:modules:ppcp-paypal-subscriptions": "cd modules/ppcp-paypal-subscriptions && yarn run build",
|
||||||
"build:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run build",
|
"build:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run build",
|
||||||
|
"build:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn run build",
|
||||||
"build:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run build",
|
"build:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run build",
|
||||||
"build:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run build",
|
"build:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run build",
|
||||||
"build:modules": "run-p build:modules:*",
|
"build:modules": "run-p build:modules:*",
|
||||||
|
@ -47,6 +51,7 @@
|
||||||
"watch:modules:ppcp-paylater-configurator": "cd modules/ppcp-paylater-configurator && yarn run watch",
|
"watch:modules:ppcp-paylater-configurator": "cd modules/ppcp-paylater-configurator && yarn run watch",
|
||||||
"watch:modules:ppcp-button": "cd modules/ppcp-button && yarn run watch",
|
"watch:modules:ppcp-button": "cd modules/ppcp-button && yarn run watch",
|
||||||
"watch:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run watch",
|
"watch:modules:ppcp-googlepay": "cd modules/ppcp-googlepay && yarn run watch",
|
||||||
|
"watch:modules:ppcp-local-alternative-payment-methods": "cd modules/ppcp-local-alternative-payment-methods && yarn run watch",
|
||||||
"watch:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run watch",
|
"watch:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run watch",
|
||||||
"watch:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run watch",
|
"watch:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run watch",
|
||||||
"watch:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run watch",
|
"watch:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run watch",
|
||||||
|
@ -54,6 +59,7 @@
|
||||||
"watch:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn run watch",
|
"watch:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn run watch",
|
||||||
"watch:modules:ppcp-axo": "cd modules/ppcp-axo && yarn run watch",
|
"watch:modules:ppcp-axo": "cd modules/ppcp-axo && yarn run watch",
|
||||||
"watch:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run watch",
|
"watch:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run watch",
|
||||||
|
"watch:modules:ppcp-card-fields": "cd modules/ppcp-card-fields && yarn run watch",
|
||||||
"watch:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run watch",
|
"watch:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run watch",
|
||||||
"watch:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run watch",
|
"watch:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run watch",
|
||||||
"watch:modules": "run-p watch:modules:*",
|
"watch:modules": "run-p watch:modules:*",
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
<file name=".psalm/wcblocks.php"/>
|
<file name=".psalm/wcblocks.php"/>
|
||||||
<file name=".psalm/wcs.php"/>
|
<file name=".psalm/wcs.php"/>
|
||||||
<file name=".psalm/gzd.php"/>
|
<file name=".psalm/gzd.php"/>
|
||||||
|
<file name=".psalm/wc-bookings.php"/>
|
||||||
<file name=".psalm/wpcli.php"/>
|
<file name=".psalm/wpcli.php"/>
|
||||||
<file name="vendor/php-stubs/wordpress-stubs/wordpress-stubs.php"/>
|
<file name="vendor/php-stubs/wordpress-stubs/wordpress-stubs.php"/>
|
||||||
<file name="vendor/php-stubs/woocommerce-stubs/woocommerce-stubs.php"/>
|
<file name="vendor/php-stubs/woocommerce-stubs/woocommerce-stubs.php"/>
|
||||||
|
|
|
@ -7,10 +7,10 @@ require('dotenv').config({ path: '.env' });
|
||||||
* @see https://playwright.dev/docs/test-configuration
|
* @see https://playwright.dev/docs/test-configuration
|
||||||
*/
|
*/
|
||||||
module.exports = defineConfig( {
|
module.exports = defineConfig( {
|
||||||
timeout: 60000,
|
timeout: 30000,
|
||||||
testDir: './tests',
|
testDir: './tests',
|
||||||
/* Run tests in files in parallel */
|
/* Run tests in files in parallel */
|
||||||
fullyParallel: true,
|
fullyParallel: false,
|
||||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
forbidOnly: !! process.env.CI,
|
forbidOnly: !! process.env.CI,
|
||||||
/* Retry on CI only */
|
/* Retry on CI only */
|
||||||
|
|
76
tests/Playwright/tests/apms-place-order.spec.js
Normal file
76
tests/Playwright/tests/apms-place-order.spec.js
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const {
|
||||||
|
fillCheckoutForm,
|
||||||
|
expectOrderReceivedPage,
|
||||||
|
acceptTerms,
|
||||||
|
} = require( './utils/checkout' );
|
||||||
|
const {
|
||||||
|
openPaypalPopup,
|
||||||
|
completePaypalPayment,
|
||||||
|
} = require( './utils/paypal-popup' );
|
||||||
|
|
||||||
|
const { PRODUCT_ID, CHECKOUT_URL, CART_URL, APM_ID } = process.env;
|
||||||
|
|
||||||
|
async function expectContinuation( page ) {
|
||||||
|
await expect(
|
||||||
|
page.locator( '#payment_method_ppcp-gateway' )
|
||||||
|
).toBeChecked();
|
||||||
|
|
||||||
|
await expect( page.locator( '.component-frame' ) ).toHaveCount( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
async function completeContinuation( page ) {
|
||||||
|
await expectContinuation( page );
|
||||||
|
|
||||||
|
await Promise.all( [
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page.locator( '#place_order' ).click(),
|
||||||
|
] );
|
||||||
|
}
|
||||||
|
|
||||||
|
test( 'PayPal APM button place order', async ( { page } ) => {
|
||||||
|
await page.goto( CART_URL + '?add-to-cart=' + PRODUCT_ID );
|
||||||
|
|
||||||
|
await page.goto( CHECKOUT_URL );
|
||||||
|
|
||||||
|
await fillCheckoutForm( page );
|
||||||
|
|
||||||
|
const popup = await openPaypalPopup( page, { fundingSource: APM_ID } );
|
||||||
|
|
||||||
|
await popup.getByText( 'Continue', { exact: true } ).click();
|
||||||
|
await completePaypalPayment( popup, {
|
||||||
|
selector: '[name="Successful"]',
|
||||||
|
} );
|
||||||
|
|
||||||
|
await expectOrderReceivedPage( page );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'PayPal APM button place order when redirect fails', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( CART_URL + '?add-to-cart=' + PRODUCT_ID );
|
||||||
|
|
||||||
|
await page.goto( CHECKOUT_URL );
|
||||||
|
|
||||||
|
await fillCheckoutForm( page );
|
||||||
|
|
||||||
|
await page.evaluate( 'PayPalCommerceGateway.ajax.approve_order = null' );
|
||||||
|
|
||||||
|
const popup = await openPaypalPopup( page, { fundingSource: APM_ID } );
|
||||||
|
|
||||||
|
await popup.getByText( 'Continue', { exact: true } ).click();
|
||||||
|
await completePaypalPayment( popup, {
|
||||||
|
selector: '[name="Successful"]',
|
||||||
|
} );
|
||||||
|
|
||||||
|
await expect( page.locator( '.woocommerce-error' ) ).toBeVisible();
|
||||||
|
|
||||||
|
await page.reload();
|
||||||
|
await expectContinuation( page );
|
||||||
|
|
||||||
|
await acceptTerms( page );
|
||||||
|
|
||||||
|
await completeContinuation( page );
|
||||||
|
|
||||||
|
await expectOrderReceivedPage( page );
|
||||||
|
} );
|
109
tests/Playwright/tests/blocks-place-order.spec.js
Normal file
109
tests/Playwright/tests/blocks-place-order.spec.js
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
const { expect, test } = require( '@playwright/test' );
|
||||||
|
const { serverExec } = require( './utils/server' );
|
||||||
|
const {
|
||||||
|
openPaypalPopup,
|
||||||
|
loginIntoPaypal,
|
||||||
|
completePaypalPayment,
|
||||||
|
waitForPaypalShippingList,
|
||||||
|
} = require( './utils/paypal-popup' );
|
||||||
|
const { expectOrderReceivedPage } = require( './utils/checkout' );
|
||||||
|
|
||||||
|
const {
|
||||||
|
PRODUCT_ID,
|
||||||
|
BLOCK_CHECKOUT_URL,
|
||||||
|
BLOCK_CHECKOUT_PAGE_ID,
|
||||||
|
BLOCK_CART_URL,
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
async function completeBlockContinuation( page ) {
|
||||||
|
await expect(
|
||||||
|
page.locator( '#radio-control-wc-payment-method-options-ppcp-gateway' )
|
||||||
|
).toBeChecked();
|
||||||
|
|
||||||
|
await expect( page.locator( '.component-frame' ) ).toHaveCount( 0 );
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page
|
||||||
|
.locator( '.wc-block-components-checkout-place-order-button' )
|
||||||
|
.click()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
test.beforeAll( async ( { browser } ) => {
|
||||||
|
await serverExec(
|
||||||
|
'wp option update woocommerce_checkout_page_id ' +
|
||||||
|
BLOCK_CHECKOUT_PAGE_ID
|
||||||
|
);
|
||||||
|
await serverExec(
|
||||||
|
'wp pcp settings update blocks_final_review_enabled true'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'PayPal express block checkout', async ( { page } ) => {
|
||||||
|
await page.goto( '?add-to-cart=' + PRODUCT_ID );
|
||||||
|
|
||||||
|
await page.goto( BLOCK_CHECKOUT_URL );
|
||||||
|
|
||||||
|
const popup = await openPaypalPopup( page );
|
||||||
|
|
||||||
|
await loginIntoPaypal( popup );
|
||||||
|
|
||||||
|
await completePaypalPayment( popup );
|
||||||
|
|
||||||
|
await completeBlockContinuation( page );
|
||||||
|
|
||||||
|
await expectOrderReceivedPage( page );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'PayPal express block cart', async ( { page } ) => {
|
||||||
|
await page.goto( BLOCK_CART_URL + '?add-to-cart=' + PRODUCT_ID );
|
||||||
|
|
||||||
|
const popup = await openPaypalPopup( page );
|
||||||
|
|
||||||
|
await loginIntoPaypal( popup );
|
||||||
|
|
||||||
|
await completePaypalPayment( popup );
|
||||||
|
|
||||||
|
await completeBlockContinuation( page );
|
||||||
|
|
||||||
|
await expectOrderReceivedPage( page );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test.describe( 'Without review', () => {
|
||||||
|
test.beforeAll( async ( { browser } ) => {
|
||||||
|
await serverExec(
|
||||||
|
'wp pcp settings update blocks_final_review_enabled false'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'PayPal express block checkout', async ( { page } ) => {
|
||||||
|
await page.goto( '?add-to-cart=' + PRODUCT_ID );
|
||||||
|
|
||||||
|
await page.goto( BLOCK_CHECKOUT_URL );
|
||||||
|
|
||||||
|
const popup = await openPaypalPopup( page );
|
||||||
|
|
||||||
|
await loginIntoPaypal( popup );
|
||||||
|
|
||||||
|
await waitForPaypalShippingList( popup );
|
||||||
|
|
||||||
|
await completePaypalPayment( popup );
|
||||||
|
|
||||||
|
await expectOrderReceivedPage( page );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'PayPal express block cart', async ( { page } ) => {
|
||||||
|
await page.goto( BLOCK_CART_URL + '?add-to-cart=' + PRODUCT_ID );
|
||||||
|
|
||||||
|
const popup = await openPaypalPopup( page );
|
||||||
|
|
||||||
|
await loginIntoPaypal( popup );
|
||||||
|
|
||||||
|
await waitForPaypalShippingList( popup );
|
||||||
|
|
||||||
|
await completePaypalPayment( popup );
|
||||||
|
|
||||||
|
await expectOrderReceivedPage( page );
|
||||||
|
} );
|
||||||
|
} );
|
97
tests/Playwright/tests/classic-place-order.spec.js
Normal file
97
tests/Playwright/tests/classic-place-order.spec.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const { serverExec } = require( './utils/server' );
|
||||||
|
const {
|
||||||
|
fillCheckoutForm,
|
||||||
|
expectOrderReceivedPage,
|
||||||
|
} = require( './utils/checkout' );
|
||||||
|
const {
|
||||||
|
openPaypalPopup,
|
||||||
|
loginIntoPaypal,
|
||||||
|
completePaypalPayment,
|
||||||
|
} = require( './utils/paypal-popup' );
|
||||||
|
|
||||||
|
const {
|
||||||
|
CREDIT_CARD_NUMBER,
|
||||||
|
CREDIT_CARD_CVV,
|
||||||
|
PRODUCT_URL,
|
||||||
|
CHECKOUT_URL,
|
||||||
|
CHECKOUT_PAGE_ID,
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
async function expectContinuation( page ) {
|
||||||
|
await expect(
|
||||||
|
page.locator( '#payment_method_ppcp-gateway' )
|
||||||
|
).toBeChecked();
|
||||||
|
|
||||||
|
await expect( page.locator( '.component-frame' ) ).toHaveCount( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
async function completeContinuation( page ) {
|
||||||
|
await expectContinuation( page );
|
||||||
|
|
||||||
|
await Promise.all( [
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page.locator( '#place_order' ).click(),
|
||||||
|
] );
|
||||||
|
}
|
||||||
|
|
||||||
|
test.beforeAll( async ( { browser } ) => {
|
||||||
|
await serverExec(
|
||||||
|
'wp option update woocommerce_checkout_page_id ' + CHECKOUT_PAGE_ID
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'PayPal button place order from Product page', async ( { page } ) => {
|
||||||
|
await serverExec(
|
||||||
|
'wp pcp settings update blocks_final_review_enabled true'
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.goto( PRODUCT_URL );
|
||||||
|
|
||||||
|
const popup = await openPaypalPopup( page );
|
||||||
|
|
||||||
|
await loginIntoPaypal( popup );
|
||||||
|
|
||||||
|
await completePaypalPayment( popup );
|
||||||
|
|
||||||
|
await fillCheckoutForm( page );
|
||||||
|
|
||||||
|
await completeContinuation( page );
|
||||||
|
|
||||||
|
await expectOrderReceivedPage( page );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'Advanced Credit and Debit Card place order from Checkout page', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await page.goto( PRODUCT_URL );
|
||||||
|
await page.locator( '.single_add_to_cart_button' ).click();
|
||||||
|
|
||||||
|
await page.goto( CHECKOUT_URL );
|
||||||
|
await fillCheckoutForm( page );
|
||||||
|
|
||||||
|
await page.click( 'text=Credit Cards' );
|
||||||
|
|
||||||
|
const expirationDate = await page
|
||||||
|
.frameLocator( 'iframe[title="paypal_card_expiry_field"]' )
|
||||||
|
.locator( 'input.card-field-expiry' );
|
||||||
|
await expirationDate.click();
|
||||||
|
await page.keyboard.type( '01/42' );
|
||||||
|
|
||||||
|
const creditCardNumber = await page
|
||||||
|
.frameLocator( '[title="paypal_card_number_field"]' )
|
||||||
|
.locator( '.card-field-number' );
|
||||||
|
await creditCardNumber.fill( CREDIT_CARD_NUMBER );
|
||||||
|
|
||||||
|
const cvv = await page
|
||||||
|
.frameLocator( '[title="paypal_card_cvv_field"]' )
|
||||||
|
.locator( '.card-field-cvv' );
|
||||||
|
await cvv.fill( CREDIT_CARD_CVV );
|
||||||
|
|
||||||
|
await Promise.all( [
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page.locator( '.ppcp-dcc-order-button' ).click(),
|
||||||
|
] );
|
||||||
|
|
||||||
|
await expectOrderReceivedPage( page );
|
||||||
|
} );
|
97
tests/Playwright/tests/free-trial-subscriptions.spec.js
Normal file
97
tests/Playwright/tests/free-trial-subscriptions.spec.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
const { test, expect } = require( '@playwright/test' );
|
||||||
|
const { loginAsCustomer } = require( './utils/user' );
|
||||||
|
const { openPaypalPopup, loginIntoPaypal } = require( './utils/paypal-popup' );
|
||||||
|
const { serverExec } = require( './utils/server' );
|
||||||
|
const { expectOrderReceivedPage } = require( './utils/checkout' );
|
||||||
|
|
||||||
|
const { CREDIT_CARD_NUMBER, CREDIT_CARD_CVV } = process.env;
|
||||||
|
|
||||||
|
test( 'PayPal logged-in user free trial subscription without payment token with shipping callback enabled', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await serverExec(
|
||||||
|
'wp pcp settings update blocks_final_review_enabled false'
|
||||||
|
);
|
||||||
|
|
||||||
|
await loginAsCustomer( page );
|
||||||
|
await page.goto( '/product/free-trial' );
|
||||||
|
await page.click( 'text=Sign up now' );
|
||||||
|
await page.goto( '/classic-checkout' );
|
||||||
|
|
||||||
|
const popup = await openPaypalPopup( page );
|
||||||
|
await loginIntoPaypal( popup );
|
||||||
|
popup.locator( '#consentButton' ).click();
|
||||||
|
|
||||||
|
await page.waitForURL( '**/order-received/**' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'ACDC logged-in user free trial subscription without payment token', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await loginAsCustomer( page );
|
||||||
|
await page.goto( '/product/free-trial' );
|
||||||
|
await page.click( 'text=Sign up now' );
|
||||||
|
await page.goto( '/classic-checkout' );
|
||||||
|
|
||||||
|
await page.click( 'text=Credit Cards' );
|
||||||
|
|
||||||
|
const creditCardNumber = await page
|
||||||
|
.frameLocator( '[title="paypal_card_number_field"]' )
|
||||||
|
.locator( '.card-field-number' );
|
||||||
|
await creditCardNumber.fill( CREDIT_CARD_NUMBER );
|
||||||
|
|
||||||
|
const expirationDate = await page
|
||||||
|
.frameLocator( 'iframe[title="paypal_card_expiry_field"]' )
|
||||||
|
.locator( 'input.card-field-expiry' );
|
||||||
|
await expirationDate.click();
|
||||||
|
await page.keyboard.type( '01/42' );
|
||||||
|
|
||||||
|
const cvv = await page
|
||||||
|
.frameLocator( '[title="paypal_card_cvv_field"]' )
|
||||||
|
.locator( '.card-field-cvv' );
|
||||||
|
await cvv.fill( CREDIT_CARD_CVV );
|
||||||
|
|
||||||
|
await Promise.all( [
|
||||||
|
page.waitForNavigation(),
|
||||||
|
page.locator( '.ppcp-dcc-order-button' ).click(),
|
||||||
|
] );
|
||||||
|
|
||||||
|
await expectOrderReceivedPage( page );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'ACDC purchase free trial in Block checkout page as logged-in without saved card payments', async ( {
|
||||||
|
page,
|
||||||
|
} ) => {
|
||||||
|
await loginAsCustomer( page );
|
||||||
|
await page.goto( '/product/free-trial' );
|
||||||
|
await page.click( 'text=Sign up now' );
|
||||||
|
await page.goto( '/checkout' );
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator(
|
||||||
|
'#radio-control-wc-payment-method-options-ppcp-credit-card-gateway'
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const expirationDate = await page
|
||||||
|
.frameLocator( 'iframe[title="paypal_card_expiry_field"]' )
|
||||||
|
.locator( 'input.card-field-expiry' );
|
||||||
|
await expirationDate.click();
|
||||||
|
await page.keyboard.type( '01/42' );
|
||||||
|
|
||||||
|
const creditCardNumber = await page
|
||||||
|
.frameLocator( '[title="paypal_card_number_field"]' )
|
||||||
|
.locator( '.card-field-number' );
|
||||||
|
await creditCardNumber.fill( CREDIT_CARD_NUMBER );
|
||||||
|
|
||||||
|
const cvv = await page
|
||||||
|
.frameLocator( '[title="paypal_card_cvv_field"]' )
|
||||||
|
.locator( '.card-field-cvv' );
|
||||||
|
await cvv.fill( CREDIT_CARD_CVV );
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator( '.wc-block-components-checkout-place-order-button' )
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await page.waitForURL( '**/order-received/**' );
|
||||||
|
} );
|
|
@ -1,207 +0,0 @@
|
||||||
const {test, expect} = require('@playwright/test');
|
|
||||||
const {serverExec} = require("./utils/server");
|
|
||||||
const {fillCheckoutForm, expectOrderReceivedPage, acceptTerms} = require("./utils/checkout");
|
|
||||||
const {openPaypalPopup, loginIntoPaypal, waitForPaypalShippingList, completePaypalPayment} = require("./utils/paypal-popup");
|
|
||||||
|
|
||||||
const {
|
|
||||||
CREDIT_CARD_NUMBER,
|
|
||||||
CREDIT_CARD_EXPIRATION,
|
|
||||||
CREDIT_CARD_CVV,
|
|
||||||
PRODUCT_URL,
|
|
||||||
PRODUCT_ID,
|
|
||||||
CHECKOUT_URL,
|
|
||||||
CHECKOUT_PAGE_ID,
|
|
||||||
CART_URL,
|
|
||||||
BLOCK_CHECKOUT_URL,
|
|
||||||
BLOCK_CHECKOUT_PAGE_ID,
|
|
||||||
BLOCK_CART_URL,
|
|
||||||
APM_ID,
|
|
||||||
} = process.env;
|
|
||||||
|
|
||||||
async function completeBlockContinuation(page) {
|
|
||||||
await expect(page.locator('#radio-control-wc-payment-method-options-ppcp-gateway')).toBeChecked();
|
|
||||||
|
|
||||||
await expect(page.locator('.component-frame')).toHaveCount(0);
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
page.waitForNavigation(),
|
|
||||||
page.locator('.wc-block-components-checkout-place-order-button').click(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function expectContinuation(page) {
|
|
||||||
await expect(page.locator('#payment_method_ppcp-gateway')).toBeChecked();
|
|
||||||
|
|
||||||
await expect(page.locator('.component-frame')).toHaveCount(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function completeContinuation(page) {
|
|
||||||
await expectContinuation(page);
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
page.waitForNavigation(),
|
|
||||||
page.locator('#place_order').click(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
test.describe('Classic checkout', () => {
|
|
||||||
test.beforeAll(async ({ browser }) => {
|
|
||||||
await serverExec('wp option update woocommerce_checkout_page_id ' + CHECKOUT_PAGE_ID);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('PayPal button place order from Product page', async ({page}) => {
|
|
||||||
await page.goto(PRODUCT_URL);
|
|
||||||
|
|
||||||
const popup = await openPaypalPopup(page);
|
|
||||||
|
|
||||||
await loginIntoPaypal(popup);
|
|
||||||
|
|
||||||
await completePaypalPayment(popup);
|
|
||||||
|
|
||||||
await fillCheckoutForm(page);
|
|
||||||
|
|
||||||
await completeContinuation(page);
|
|
||||||
|
|
||||||
await expectOrderReceivedPage(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Advanced Credit and Debit Card place order from Checkout page', async ({page}) => {
|
|
||||||
await page.goto(PRODUCT_URL);
|
|
||||||
await page.locator('.single_add_to_cart_button').click();
|
|
||||||
|
|
||||||
await page.goto(CHECKOUT_URL);
|
|
||||||
await fillCheckoutForm(page);
|
|
||||||
|
|
||||||
await page.click("text=Credit Cards");
|
|
||||||
|
|
||||||
const creditCardNumber = page.frameLocator('#braintree-hosted-field-number').locator('#credit-card-number');
|
|
||||||
await creditCardNumber.fill(CREDIT_CARD_NUMBER);
|
|
||||||
|
|
||||||
const expirationDate = page.frameLocator('#braintree-hosted-field-expirationDate').locator('#expiration');
|
|
||||||
await expirationDate.fill(CREDIT_CARD_EXPIRATION);
|
|
||||||
|
|
||||||
const cvv = page.frameLocator('#braintree-hosted-field-cvv').locator('#cvv');
|
|
||||||
await cvv.fill(CREDIT_CARD_CVV);
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
page.waitForNavigation(),
|
|
||||||
page.locator('.ppcp-dcc-order-button').click(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
await expectOrderReceivedPage(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('PayPal APM button place order', async ({page}) => {
|
|
||||||
await page.goto(CART_URL + '?add-to-cart=' + PRODUCT_ID);
|
|
||||||
|
|
||||||
await page.goto(CHECKOUT_URL);
|
|
||||||
|
|
||||||
await fillCheckoutForm(page);
|
|
||||||
|
|
||||||
const popup = await openPaypalPopup(page, {fundingSource: APM_ID});
|
|
||||||
|
|
||||||
await popup.getByText('Continue', { exact: true }).click();
|
|
||||||
await completePaypalPayment(popup, {selector: '[name="Successful"]'});
|
|
||||||
|
|
||||||
await expectOrderReceivedPage(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('PayPal APM button place order when redirect fails', async ({page}) => {
|
|
||||||
await page.goto(CART_URL + '?add-to-cart=' + PRODUCT_ID);
|
|
||||||
|
|
||||||
await page.goto(CHECKOUT_URL);
|
|
||||||
|
|
||||||
await fillCheckoutForm(page);
|
|
||||||
|
|
||||||
await page.evaluate('PayPalCommerceGateway.ajax.approve_order = null');
|
|
||||||
|
|
||||||
const popup = await openPaypalPopup(page, {fundingSource: APM_ID});
|
|
||||||
|
|
||||||
await popup.getByText('Continue', { exact: true }).click();
|
|
||||||
await completePaypalPayment(popup, {selector: '[name="Successful"]'});
|
|
||||||
|
|
||||||
await expect(page.locator('.woocommerce-error')).toBeVisible();
|
|
||||||
|
|
||||||
await page.reload();
|
|
||||||
await expectContinuation(page);
|
|
||||||
|
|
||||||
await acceptTerms(page);
|
|
||||||
|
|
||||||
await completeContinuation(page);
|
|
||||||
|
|
||||||
await expectOrderReceivedPage(page);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('Block checkout', () => {
|
|
||||||
test.beforeAll(async ({browser}) => {
|
|
||||||
await serverExec('wp option update woocommerce_checkout_page_id ' + BLOCK_CHECKOUT_PAGE_ID);
|
|
||||||
await serverExec('wp pcp settings update blocks_final_review_enabled true');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('PayPal express block checkout', async ({page}) => {
|
|
||||||
await page.goto('?add-to-cart=' + PRODUCT_ID);
|
|
||||||
|
|
||||||
await page.goto(BLOCK_CHECKOUT_URL)
|
|
||||||
|
|
||||||
const popup = await openPaypalPopup(page);
|
|
||||||
|
|
||||||
await loginIntoPaypal(popup);
|
|
||||||
|
|
||||||
await completePaypalPayment(popup);
|
|
||||||
|
|
||||||
await completeBlockContinuation(page);
|
|
||||||
|
|
||||||
await expectOrderReceivedPage(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('PayPal express block cart', async ({page}) => {
|
|
||||||
await page.goto(BLOCK_CART_URL + '?add-to-cart=' + PRODUCT_ID)
|
|
||||||
|
|
||||||
const popup = await openPaypalPopup(page);
|
|
||||||
|
|
||||||
await loginIntoPaypal(popup);
|
|
||||||
|
|
||||||
await completePaypalPayment(popup);
|
|
||||||
|
|
||||||
await completeBlockContinuation(page);
|
|
||||||
|
|
||||||
await expectOrderReceivedPage(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('Without review', () => {
|
|
||||||
test.beforeAll(async ({browser}) => {
|
|
||||||
await serverExec('wp pcp settings update blocks_final_review_enabled false');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('PayPal express block checkout', async ({page}) => {
|
|
||||||
await page.goto('?add-to-cart=' + PRODUCT_ID);
|
|
||||||
|
|
||||||
await page.goto(BLOCK_CHECKOUT_URL)
|
|
||||||
|
|
||||||
const popup = await openPaypalPopup(page);
|
|
||||||
|
|
||||||
await loginIntoPaypal(popup);
|
|
||||||
|
|
||||||
await waitForPaypalShippingList(popup);
|
|
||||||
|
|
||||||
await completePaypalPayment(popup);
|
|
||||||
|
|
||||||
await expectOrderReceivedPage(page);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('PayPal express block cart', async ({page}) => {
|
|
||||||
await page.goto(BLOCK_CART_URL + '?add-to-cart=' + PRODUCT_ID)
|
|
||||||
|
|
||||||
const popup = await openPaypalPopup(page);
|
|
||||||
|
|
||||||
await loginIntoPaypal(popup);
|
|
||||||
|
|
||||||
await waitForPaypalShippingList(popup);
|
|
||||||
|
|
||||||
await completePaypalPayment(popup);
|
|
||||||
|
|
||||||
await expectOrderReceivedPage(page);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,14 +1,21 @@
|
||||||
const { test, expect } = require( '@playwright/test' );
|
const { test, expect } = require( '@playwright/test' );
|
||||||
const {loginAsCustomer} = require("./utils/user");
|
const { loginAsCustomer } = require( './utils/user' );
|
||||||
const {openPaypalPopup, loginIntoPaypal, completePaypalPayment} = require("./utils/paypal-popup");
|
|
||||||
const {fillCheckoutForm, expectOrderReceivedPage} = require("./utils/checkout");
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
PRODUCT_URL,
|
openPaypalPopup,
|
||||||
} = process.env;
|
loginIntoPaypal,
|
||||||
|
completePaypalPayment,
|
||||||
|
} = require( './utils/paypal-popup' );
|
||||||
|
const {
|
||||||
|
fillCheckoutForm,
|
||||||
|
expectOrderReceivedPage,
|
||||||
|
} = require( './utils/checkout' );
|
||||||
|
|
||||||
|
const { PRODUCT_URL } = process.env;
|
||||||
|
|
||||||
async function expectContinuation( page ) {
|
async function expectContinuation( page ) {
|
||||||
await expect(page.locator('#payment_method_ppcp-gateway')).toBeChecked();
|
await expect(
|
||||||
|
page.locator( '#payment_method_ppcp-gateway' )
|
||||||
|
).toBeChecked();
|
||||||
|
|
||||||
await expect( page.locator( '.component-frame' ) ).toHaveCount( 0 );
|
await expect( page.locator( '.component-frame' ) ).toHaveCount( 0 );
|
||||||
}
|
}
|
||||||
|
@ -22,8 +29,9 @@ async function completeContinuation(page) {
|
||||||
] );
|
] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// preconditions: shipping callback disabled and no saved payments
|
||||||
test( 'Save during purchase', async ( { page } ) => {
|
test( 'Save during purchase', async ( { page } ) => {
|
||||||
await loginAsCustomer(page)
|
await loginAsCustomer( page );
|
||||||
|
|
||||||
await page.goto( PRODUCT_URL );
|
await page.goto( PRODUCT_URL );
|
||||||
const popup = await openPaypalPopup( page );
|
const popup = await openPaypalPopup( page );
|
||||||
|
@ -52,38 +60,25 @@ test('ACDC add payment method', async ({page}) => {
|
||||||
await loginAsCustomer( page );
|
await loginAsCustomer( page );
|
||||||
await page.goto( '/my-account/add-payment-method' );
|
await page.goto( '/my-account/add-payment-method' );
|
||||||
|
|
||||||
await page.click("text=Debit & Credit Cards");
|
await page.click( 'text=Debit & Credit Cards' );
|
||||||
|
|
||||||
const creditCardNumber = await page.frameLocator('[title="paypal_card_number_field"]').locator('.card-field-number');
|
const creditCardNumber = await page
|
||||||
|
.frameLocator( '[title="paypal_card_number_field"]' )
|
||||||
|
.locator( '.card-field-number' );
|
||||||
await creditCardNumber.fill( '4005519200000004' );
|
await creditCardNumber.fill( '4005519200000004' );
|
||||||
|
|
||||||
const expirationDate = await page.frameLocator('[title="paypal_card_expiry_field"]').locator('.card-field-expiry');
|
const expirationDate = await page
|
||||||
await expirationDate.fill('01/25');
|
.frameLocator( 'iframe[title="paypal_card_expiry_field"]' )
|
||||||
|
.locator( 'input.card-field-expiry' );
|
||||||
|
await expirationDate.click();
|
||||||
|
await page.keyboard.type( '12/25' );
|
||||||
|
|
||||||
const cvv = await page.frameLocator('[title="paypal_card_cvv_field"]').locator('.card-field-cvv');
|
const cvv = await page
|
||||||
|
.frameLocator( '[title="paypal_card_cvv_field"]' )
|
||||||
|
.locator( '.card-field-cvv' );
|
||||||
await cvv.fill( '123' );
|
await cvv.fill( '123' );
|
||||||
|
|
||||||
|
await page.getByRole( 'button', { name: 'Add payment method' } ).click();
|
||||||
|
|
||||||
await page.waitForURL( '/my-account/payment-methods' );
|
await page.waitForURL( '/my-account/payment-methods' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test('PayPal logged-in user free trial subscription without payment token', async ({page}) => {
|
|
||||||
await loginAsCustomer(page);
|
|
||||||
|
|
||||||
await page.goto('/shop');
|
|
||||||
await page.click("text=Sign up now");
|
|
||||||
await page.goto('/classic-checkout');
|
|
||||||
|
|
||||||
const popup = await openPaypalPopup(page);
|
|
||||||
await loginIntoPaypal(popup);
|
|
||||||
popup.locator('#consentButton').click();
|
|
||||||
|
|
||||||
await page.click("text=Proceed to PayPal");
|
|
||||||
|
|
||||||
const title = await page.locator('.entry-title');
|
|
||||||
await expect(title).toHaveText('Order received');
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue