mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 10:55:00 +08:00
🚧 New Gateway for Apple Pay
This commit is contained in:
parent
10439ff02b
commit
eb216425fb
12 changed files with 516 additions and 268 deletions
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* The Apple Pay Payment Gateway
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Applepay
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Applepay;
|
||||
|
||||
use WC_Payment_Gateway;
|
||||
|
||||
/**
|
||||
* Class ApplePayGateway
|
||||
*/
|
||||
class ApplePayGateway extends WC_Payment_Gateway {
|
||||
const ID = 'ppcp-applepay';
|
||||
|
||||
}
|
|
@ -52,3 +52,8 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initially hide the APM button until it's explicitly activated.
|
||||
#ppc-button-ppcp-applepay {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/* global ApplePaySession */
|
||||
/* global PayPalCommerceGateway */
|
||||
|
||||
import ContextHandlerFactory from './Context/ContextHandlerFactory';
|
||||
import { createAppleErrors } from './Helper/applePayError';
|
||||
import { setVisible } from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
||||
|
@ -7,12 +10,31 @@ import ErrorHandler from '../../../ppcp-button/resources/js/modules/ErrorHandler
|
|||
import widgetBuilder from '../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder';
|
||||
import { apmButtonsInit } from '../../../ppcp-button/resources/js/modules/Helper/ApmButtons';
|
||||
|
||||
class ApplepayButton {
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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 = '';
|
||||
|
||||
constructor( context, externalHandler, buttonConfig, ppcpConfig ) {
|
||||
apmButtonsInit( ppcpConfig );
|
||||
|
||||
this.isInitialized = false;
|
||||
|
||||
this.context = context;
|
||||
this.externalHandler = externalHandler;
|
||||
this.buttonConfig = buttonConfig;
|
||||
|
@ -65,40 +87,43 @@ class ApplepayButton {
|
|||
|
||||
this.log( 'Init', this.context );
|
||||
this.initEventHandlers();
|
||||
|
||||
this.isInitialized = true;
|
||||
this.applePayConfig = config;
|
||||
this.isEligible =
|
||||
( this.applePayConfig.isEligible && window.ApplePaySession ) ||
|
||||
this.buttonConfig.is_admin;
|
||||
|
||||
if ( this.isEligible ) {
|
||||
const idMinicart = this.buttonConfig.button.mini_cart_wrapper;
|
||||
const idButton = this.buttonConfig.button.wrapper;
|
||||
|
||||
if ( ! this.isEligible ) {
|
||||
jQuery( '#' + idButton ).hide();
|
||||
jQuery( '#' + idMinicart ).hide();
|
||||
jQuery( '#express-payment-method-ppcp-applepay' ).hide();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Add click-handler to the button.
|
||||
const setupButtonEvents = ( id ) => {
|
||||
document
|
||||
.getElementById( id )
|
||||
?.addEventListener( 'click', ( evt ) => {
|
||||
evt.preventDefault();
|
||||
this.onButtonClick();
|
||||
} );
|
||||
};
|
||||
|
||||
this.fetchTransactionInfo().then( () => {
|
||||
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();
|
||||
} );
|
||||
setupButtonEvents( idMinicart );
|
||||
} else {
|
||||
document
|
||||
.querySelector( id )
|
||||
?.addEventListener( 'click', ( evt ) => {
|
||||
evt.preventDefault();
|
||||
this.onButtonClick();
|
||||
} );
|
||||
setupButtonEvents( idButton );
|
||||
}
|
||||
} );
|
||||
} else {
|
||||
jQuery( '#' + this.buttonConfig.button.wrapper ).hide();
|
||||
jQuery( '#' + this.buttonConfig.button.mini_cart_wrapper ).hide();
|
||||
jQuery( '#express-payment-method-ppcp-applepay' ).hide();
|
||||
}
|
||||
}
|
||||
|
||||
reinit() {
|
||||
|
@ -144,11 +169,11 @@ class ApplepayButton {
|
|||
|
||||
initEventHandlers() {
|
||||
const { wrapper, ppcpButtonWrapper } = this.contextConfig();
|
||||
const wrapper_id = '#' + wrapper;
|
||||
const wrapperId = '#' + wrapper;
|
||||
|
||||
if ( wrapper_id === ppcpButtonWrapper ) {
|
||||
if ( wrapperId === ppcpButtonWrapper ) {
|
||||
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 +183,9 @@ class ApplepayButton {
|
|||
}
|
||||
|
||||
const $ppcpButtonWrapper = jQuery( ppcpButtonWrapper );
|
||||
setVisible( wrapper_id, $ppcpButtonWrapper.is( ':visible' ) );
|
||||
setVisible( wrapperId, $ppcpButtonWrapper.is( ':visible' ) );
|
||||
setEnabled(
|
||||
wrapper_id,
|
||||
wrapperId,
|
||||
! $ppcpButtonWrapper.hasClass( 'ppcp-disabled' )
|
||||
);
|
||||
};
|
||||
|
@ -192,6 +217,7 @@ class ApplepayButton {
|
|||
session.onshippingcontactselected =
|
||||
this.onShippingContactSelected( session );
|
||||
}
|
||||
|
||||
session.onvalidatemerchant = this.onValidateMerchant( session );
|
||||
session.onpaymentauthorized = this.onPaymentAuthorized( session );
|
||||
return session;
|
||||
|
@ -211,19 +237,19 @@ class ApplepayButton {
|
|||
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 }">`;
|
||||
if ( ! appleContainer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $wrapper = jQuery( '#' + wrapper );
|
||||
$wrapper.addClass( 'ppcp-button-' + ppcpStyle.shape );
|
||||
appleContainer.innerHTML = `<apple-pay-button id='${ id }' buttonstyle='${ color }' type='${ type }' locale='${ language }'>`;
|
||||
appleContainer.classList.add( 'ppcp-button-' + ppcpStyle.shape );
|
||||
|
||||
if ( ppcpStyle.height ) {
|
||||
$wrapper.css(
|
||||
appleContainer.style.setProperty(
|
||||
'--apple-pay-button-height',
|
||||
`${ ppcpStyle.height }px`
|
||||
);
|
||||
$wrapper.css( 'height', `${ ppcpStyle.height }px` );
|
||||
appleContainer.style.height = `${ ppcpStyle.height }px`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,7 +265,8 @@ class ApplepayButton {
|
|||
|
||||
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.
|
||||
if ( this.context === 'checkout' ) {
|
||||
|
@ -323,8 +350,8 @@ class ApplepayButton {
|
|||
}
|
||||
|
||||
/**
|
||||
* Indicates how payment completion should be handled if with the context handler default actions.
|
||||
* Or with ApplePay module specific completion.
|
||||
* Indicates how payment completion should be handled if with the context handler default
|
||||
* actions. Or with Apple Pay module specific completion.
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
|
@ -333,18 +360,17 @@ class ApplepayButton {
|
|||
if ( ! this.contextHandler.shippingAllowed() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use WC form data mode in Checkout.
|
||||
if (
|
||||
return (
|
||||
this.context === 'checkout' &&
|
||||
! this.shouldUpdateButtonWithFormData()
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates Apple Pay paymentRequest with form data.
|
||||
*
|
||||
* @param paymentRequest
|
||||
*/
|
||||
updateRequestDataWithForm( paymentRequest ) {
|
||||
|
@ -358,8 +384,9 @@ class ApplepayButton {
|
|||
);
|
||||
|
||||
// Add custom data.
|
||||
// "applicationData" is originating a "PayPalApplePayError: An internal server error has occurred" on paypal.Applepay().confirmOrder().
|
||||
// paymentRequest.applicationData = this.fillApplicationData(this.formData);
|
||||
// "applicationData" is originating a "PayPalApplePayError: An internal server error has
|
||||
// occurred" on paypal.Applepay().confirmOrder(). paymentRequest.applicationData =
|
||||
// this.fillApplicationData(this.formData);
|
||||
|
||||
if ( ! this.shouldRequireShippingInButton() ) {
|
||||
return;
|
||||
|
@ -425,7 +452,8 @@ class ApplepayButton {
|
|||
'email',
|
||||
'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() ) {
|
||||
|
@ -453,14 +481,11 @@ class ApplepayButton {
|
|||
}
|
||||
|
||||
refreshContextData() {
|
||||
switch ( this.context ) {
|
||||
case 'product':
|
||||
if ( 'product' === this.context ) {
|
||||
// Refresh product data that makes the price change.
|
||||
this.productQuantity =
|
||||
document.querySelector( 'input.qty' )?.value;
|
||||
this.productQuantity = document.querySelector( 'input.qty' )?.value;
|
||||
this.products = this.contextHandler.products();
|
||||
this.log( 'Products updated', this.products );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,8 +493,35 @@ class ApplepayButton {
|
|||
// 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 session
|
||||
* @return {(function(*): void)|*}
|
||||
*/
|
||||
onValidateMerchant( session ) {
|
||||
this.log( 'onvalidatemerchant', this.buttonConfig.ajax_url );
|
||||
return ( applePayValidateMerchantEvent ) => {
|
||||
this.log( 'onvalidatemerchant call' );
|
||||
|
||||
|
@ -479,34 +531,15 @@ class ApplepayButton {
|
|||
validationUrl: applePayValidateMerchantEvent.validationURL,
|
||||
} )
|
||||
.then( ( validateResult ) => {
|
||||
this.log( 'onvalidatemerchant ok' );
|
||||
session.completeMerchantValidation(
|
||||
validateResult.merchantSession
|
||||
);
|
||||
//call backend to update validation to true
|
||||
jQuery.ajax( {
|
||||
url: this.buttonConfig.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'ppcp_validate',
|
||||
validation: true,
|
||||
'woocommerce-process-checkout-nonce': this.nonce,
|
||||
},
|
||||
} );
|
||||
|
||||
this.adminValidation( true );
|
||||
} )
|
||||
.catch( ( validateError ) => {
|
||||
this.log( 'onvalidatemerchant error', validateError );
|
||||
console.error( validateError );
|
||||
//call backend to update validation to false
|
||||
jQuery.ajax( {
|
||||
url: this.buttonConfig.ajax_url,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'ppcp_validate',
|
||||
validation: false,
|
||||
'woocommerce-process-checkout-nonce': this.nonce,
|
||||
},
|
||||
} );
|
||||
this.adminValidation( false );
|
||||
this.log( 'onvalidatemerchant session abort' );
|
||||
session.abort();
|
||||
} );
|
||||
|
@ -537,7 +570,8 @@ class ApplepayButton {
|
|||
}
|
||||
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.sort( ( a, b ) => {
|
||||
if (
|
||||
|
@ -680,6 +714,7 @@ class ApplepayButton {
|
|||
function form() {
|
||||
return document.querySelector( 'form.cart' );
|
||||
}
|
||||
|
||||
const processInWooAndCapture = async ( data ) => {
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
try {
|
||||
|
@ -781,7 +816,8 @@ class ApplepayButton {
|
|||
if (
|
||||
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;
|
||||
await this.contextHandler.approveOrder(
|
||||
|
@ -950,4 +986,4 @@ class ApplepayButton {
|
|||
}
|
||||
}
|
||||
|
||||
export default ApplepayButton;
|
||||
export default ApplePayButton;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export const buttonID = 'applepay-container';
|
||||
export const buttonID = 'ppc-button-applepay-container';
|
||||
export const endpoints = {
|
||||
validation: '_apple_pay_validation',
|
||||
createOrderCart: '_apple_pay_create_order_cart',
|
||||
|
|
|
@ -976,5 +976,15 @@ return array(
|
|||
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' )
|
||||
);
|
||||
},
|
||||
|
||||
);
|
||||
|
|
234
modules/ppcp-applepay/src/ApplePayGateway.php
Normal file
234
modules/ppcp-applepay/src/ApplePayGateway.php
Normal file
|
@ -0,0 +1,234 @@
|
|||
<?php
|
||||
/**
|
||||
* The Apple Pay Payment Gateway
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Applepay
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Applepay;
|
||||
|
||||
use WC_Payment_Gateway;
|
||||
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\Session\SessionHandler;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException;
|
||||
use Exception;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\PayPalOrderMissingException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
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 = __( 'The separate payment gateway with the Apple Pay button. If disabled, the button is included in the PayPal gateway.', '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;
|
||||
|
||||
use WC_Payment_Gateway;
|
||||
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
|
||||
use WooCommerce\PayPalCommerce\Applepay\Assets\ApplePayButton;
|
||||
use WooCommerce\PayPalCommerce\Applepay\Assets\AppleProductStatus;
|
||||
|
@ -117,6 +118,48 @@ class ApplepayModule implements ModuleInterface {
|
|||
100,
|
||||
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.
|
||||
* @return string
|
||||
*/
|
||||
public function validation_string( bool $is_sandbox ) {
|
||||
public function validation_string( bool $is_sandbox ) : string {
|
||||
$sandbox_string = $this->sandbox_validation_string();
|
||||
$live_string = $this->live_validation_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\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\Webhooks\Handler\RequestHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait;
|
||||
|
||||
/**
|
||||
* Class ApplePayButton
|
||||
*/
|
||||
class ApplePayButton implements ButtonInterface {
|
||||
use RequestHandlerTrait;
|
||||
use RequestHandlerTrait, ContextTrait;
|
||||
|
||||
/**
|
||||
* The settings.
|
||||
|
@ -973,7 +974,7 @@ class ApplePayButton implements ButtonInterface {
|
|||
add_action(
|
||||
$render_placeholder,
|
||||
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
|
||||
);
|
||||
|
@ -986,7 +987,7 @@ class ApplePayButton implements ButtonInterface {
|
|||
*/
|
||||
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' ); ?>
|
||||
</div>
|
||||
<?php
|
||||
|
|
|
@ -11,6 +11,8 @@ namespace WooCommerce\PayPalCommerce\Applepay\Assets;
|
|||
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\Applepay\ApplePayGateway;
|
||||
use WC_Product;
|
||||
|
||||
/**
|
||||
* Class DataToAppleButtonScripts
|
||||
|
@ -45,57 +47,90 @@ class DataToAppleButtonScripts {
|
|||
* Sets the appropriate data to send to ApplePay script
|
||||
* Data differs between product page and cart page
|
||||
*
|
||||
* @param bool $is_block Whether the button is in a block or not.
|
||||
* @return array
|
||||
* @throws NotFoundException When the setting is not found.
|
||||
*/
|
||||
public function apple_pay_script_data( bool $is_block = false ): array {
|
||||
$base_location = wc_get_base_location();
|
||||
$shop_country_code = $base_location['country'];
|
||||
$currency_code = get_woocommerce_currency();
|
||||
$total_label = get_bloginfo( 'name' );
|
||||
public function apple_pay_script_data() : array {
|
||||
if ( is_product() ) {
|
||||
return $this->data_for_product_page(
|
||||
$shop_country_code,
|
||||
$currency_code,
|
||||
$total_label
|
||||
);
|
||||
return $this->data_for_product_page();
|
||||
}
|
||||
|
||||
return $this->data_for_cart_page(
|
||||
$shop_country_code,
|
||||
$currency_code,
|
||||
$total_label
|
||||
);
|
||||
return $this->data_for_cart_page();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate admin data to send to ApplePay script
|
||||
*
|
||||
* @return array
|
||||
* @throws NotFoundException When the setting is not found.
|
||||
*/
|
||||
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 {
|
||||
// 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();
|
||||
$shop_country_code = $base_location['country'];
|
||||
$currency_code = get_woocommerce_currency();
|
||||
$total_label = get_bloginfo( 'name' );
|
||||
|
||||
return $this->data_for_admin_page(
|
||||
$shop_country_code,
|
||||
$currency_code,
|
||||
$total_label
|
||||
// Button layout (label, color, language).
|
||||
$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 );
|
||||
$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
|
||||
*
|
||||
* @param \WC_Product $product The product.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function check_if_need_shipping( $product ) {
|
||||
protected function check_if_need_shipping( WC_Product $product ) : bool {
|
||||
if (
|
||||
! wc_shipping_enabled()
|
||||
|| 0 === wc_get_shipping_method_count(
|
||||
|
@ -104,30 +139,20 @@ class DataToAppleButtonScripts {
|
|||
) {
|
||||
return false;
|
||||
}
|
||||
$needs_shipping = false;
|
||||
|
||||
if ( $product->needs_shipping() ) {
|
||||
$needs_shipping = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return $needs_shipping;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @throws NotFoundException When the setting is not found.
|
||||
*/
|
||||
protected function data_for_product_page(
|
||||
$shop_country_code,
|
||||
$currency_code,
|
||||
$total_label
|
||||
) {
|
||||
protected function data_for_product_page() : array {
|
||||
$product = wc_get_product( get_the_id() );
|
||||
if ( ! $product ) {
|
||||
return array();
|
||||
|
@ -136,146 +161,53 @@ class DataToAppleButtonScripts {
|
|||
if ( $product->get_type() === 'variable' || $product->get_type() === 'variable-subscription' ) {
|
||||
$is_variation = true;
|
||||
}
|
||||
|
||||
$product_need_shipping = $this->check_if_need_shipping( $product );
|
||||
$product_id = get_the_id();
|
||||
$product_price = $product->get_price();
|
||||
$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(
|
||||
'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(
|
||||
return $this->get_apple_pay_data( array(
|
||||
'needShipping' => $product_need_shipping,
|
||||
'id' => $product_id,
|
||||
'price' => $product_price,
|
||||
'isVariation' => $is_variation,
|
||||
'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.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
protected function data_for_cart_page(
|
||||
$shop_country_code,
|
||||
$currency_code,
|
||||
$total_label
|
||||
) {
|
||||
protected function data_for_cart_page() : array {
|
||||
$cart = WC()->cart;
|
||||
if ( ! $cart ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$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;
|
||||
|
||||
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(
|
||||
return $this->get_apple_pay_data( array(
|
||||
'needShipping' => $cart->needs_shipping(),
|
||||
'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.
|
||||
* 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.
|
||||
* Consider refactoring this method along with data_for_cart_page() and data_for_product_page()
|
||||
* methods.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function data_for_admin_page(
|
||||
$shop_country_code,
|
||||
$currency_code,
|
||||
$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(
|
||||
protected function data_for_admin_page() : array {
|
||||
$data = $this->get_apple_pay_data( array(
|
||||
'needShipping' => false,
|
||||
'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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* global PayPalCommerceGateway */
|
||||
|
||||
import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler';
|
||||
import { setVisible, setVisibleByClass } from '../Helper/Hiding';
|
||||
import {
|
||||
|
@ -181,9 +183,14 @@ class CheckoutBootstap {
|
|||
const isSeparateButtonGateway = [ PaymentMethods.CARD_BUTTON ].includes(
|
||||
currentPaymentMethod
|
||||
);
|
||||
const isApplePayMethod =
|
||||
currentPaymentMethod === PaymentMethods.APPLEPAY;
|
||||
const isSavedCard = isCard && isSavedCardSelected();
|
||||
const isNotOurGateway =
|
||||
! isPaypal && ! isCard && ! isSeparateButtonGateway;
|
||||
! isPaypal &&
|
||||
! isCard &&
|
||||
! isSeparateButtonGateway &&
|
||||
! isApplePayMethod;
|
||||
const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;
|
||||
const hasVaultedPaypal =
|
||||
PayPalCommerceGateway.vaulted_paypal_email !== '';
|
||||
|
@ -227,6 +234,8 @@ class CheckoutBootstap {
|
|||
}
|
||||
}
|
||||
|
||||
setVisible( '#ppc-button-ppcp-applepay', isApplePayMethod );
|
||||
|
||||
jQuery( document.body ).trigger( 'ppcp_checkout_rendered' );
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ export const PaymentMethods = {
|
|||
CARDS: 'ppcp-credit-card-gateway',
|
||||
OXXO: 'ppcp-oxxo-gateway',
|
||||
CARD_BUTTON: 'ppcp-card-button-gateway',
|
||||
APPLEPAY: 'ppcp-applepay',
|
||||
};
|
||||
|
||||
export const ORDER_BUTTON_SELECTOR = '#place_order';
|
||||
|
|
|
@ -117,19 +117,16 @@ class Settings implements ContainerInterface {
|
|||
/**
|
||||
* Stores the settings to the database.
|
||||
*/
|
||||
public function persist() {
|
||||
|
||||
public function persist() : bool {
|
||||
return update_option( self::KEY, $this->settings );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads the settings.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function load(): bool {
|
||||
|
||||
if ( $this->settings ) {
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue