mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 18:16:38 +08:00
Merge branch 'PCP-1744-google-pay-integration' into wip/apple-google-combined
# Conflicts: # modules.php
This commit is contained in:
commit
2e7f9b46b0
36 changed files with 4240 additions and 7 deletions
|
@ -35,5 +35,13 @@ return function ( string $root_dir ): iterable {
|
|||
$modules[] = ( require "$modules_dir/ppcp-applepay/module.php" )();
|
||||
}
|
||||
|
||||
if ( apply_filters(
|
||||
//phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
'woocommerce.feature-flags.woocommerce_paypal_payments.googlepay_enabled',
|
||||
getenv( 'PCP_GOOGLEPAY_ENABLED' ) === '1'
|
||||
) ) {
|
||||
$modules[] = ( require "$modules_dir/ppcp-googlepay/module.php" )();
|
||||
}
|
||||
|
||||
return $modules;
|
||||
};
|
||||
|
|
|
@ -109,12 +109,14 @@ const PayPalComponent = ({
|
|||
setPaypalOrder(order);
|
||||
|
||||
if (config.finalReviewEnabled) {
|
||||
if (order) {
|
||||
const addresses = paypalOrderToWcAddresses(order);
|
||||
|
||||
await wp.data.dispatch('wc/store/cart').updateCustomerData({
|
||||
billing_address: addresses.billingAddress,
|
||||
shipping_address: addresses.shippingAddress,
|
||||
});
|
||||
}
|
||||
const checkoutUrl = new URL(config.scriptData.redirect);
|
||||
// sometimes some browsers may load some kind of cached version of the page,
|
||||
// so adding a parameter to avoid that
|
||||
|
|
14
modules/ppcp-googlepay/.babelrc
Normal file
14
modules/ppcp-googlepay/.babelrc
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": "usage",
|
||||
"corejs": "3.25.0"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@babel/preset-react"
|
||||
]
|
||||
]
|
||||
}
|
3
modules/ppcp-googlepay/.gitignore
vendored
Normal file
3
modules/ppcp-googlepay/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
node_modules
|
||||
assets/js
|
||||
assets/css
|
17
modules/ppcp-googlepay/composer.json
Normal file
17
modules/ppcp-googlepay/composer.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "woocommerce/ppcp-googlepay",
|
||||
"type": "dhii-mod",
|
||||
"description": "Googlepay module for PPCP",
|
||||
"license": "GPL-2.0",
|
||||
"require": {
|
||||
"php": "^7.2 | ^8.0",
|
||||
"dhii/module-interface": "^0.3.0-alpha1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WooCommerce\\PayPalCommerce\\Googlepay\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
94
modules/ppcp-googlepay/extensions.php
Normal file
94
modules/ppcp-googlepay/extensions.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
/**
|
||||
* The Googlepay module extensions.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Googlepay
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Googlepay;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Googlepay\Helper\PropertiesDictionary;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
|
||||
return array(
|
||||
|
||||
'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array {
|
||||
$insert_after = function( array $array, string $key, array $new ): array {
|
||||
$keys = array_keys( $array );
|
||||
$index = array_search( $key, $keys, true );
|
||||
$pos = false === $index ? count( $array ) : $index + 1;
|
||||
|
||||
return array_merge( array_slice( $array, 0, $pos ), $new, array_slice( $array, $pos ) );
|
||||
};
|
||||
|
||||
return $insert_after(
|
||||
$fields,
|
||||
'allow_card_button_gateway',
|
||||
array(
|
||||
'googlepay_button_enabled' => array(
|
||||
'title' => __( 'Google Pay Button', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable Google Pay button', 'woocommerce-paypal-payments' ),
|
||||
'default' => 'yes',
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'requirements' => array(),
|
||||
'custom_attributes' => array(
|
||||
'data-ppcp-handlers' => wp_json_encode(
|
||||
array(
|
||||
array(
|
||||
'handler' => 'SubElementsHandler',
|
||||
'options' => array(
|
||||
'values' => array( '1' ),
|
||||
'elements' => array(
|
||||
'#field-googlepay_button_color',
|
||||
'#field-googlepay_button_type',
|
||||
'#field-googlepay_button_shipping_enabled',
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
'googlepay_button_color' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Button Color', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'label' => '',
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'class' => array(),
|
||||
'default' => 'black',
|
||||
'options' => PropertiesDictionary::button_colors(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'googlepay_button_type' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Button Type', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'class' => array(),
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'default' => 'pay',
|
||||
'options' => PropertiesDictionary::button_types(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'googlepay_button_shipping_enabled' => array(
|
||||
'title' => str_repeat( ' ', 6 ) . __( 'Shipping Callback', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable Google Pay shipping callback', 'woocommerce-paypal-payments' ),
|
||||
'default' => 'no',
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'requirements' => array(),
|
||||
),
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
);
|
16
modules/ppcp-googlepay/module.php
Normal file
16
modules/ppcp-googlepay/module.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* The Googlepay module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Googlepay
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Googlepay;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
|
||||
return static function (): ModuleInterface {
|
||||
return new GooglepayModule();
|
||||
};
|
34
modules/ppcp-googlepay/package.json
Normal file
34
modules/ppcp-googlepay/package.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "ppcp-googlepay",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"browserslist": [
|
||||
"> 0.5%",
|
||||
"Safari >= 8",
|
||||
"Chrome >= 41",
|
||||
"Firefox >= 43",
|
||||
"Edge >= 14"
|
||||
],
|
||||
"dependencies": {
|
||||
"@paypal/paypal-js": "^6.0.0",
|
||||
"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"
|
||||
}
|
||||
}
|
46
modules/ppcp-googlepay/resources/css/styles.scss
Normal file
46
modules/ppcp-googlepay/resources/css/styles.scss
Normal file
|
@ -0,0 +1,46 @@
|
|||
.ppcp-button-googlepay {
|
||||
margin: 7px 0;
|
||||
overflow: hidden;
|
||||
min-height: 40px;
|
||||
height: 45px;
|
||||
|
||||
&.ppcp-button-pill {
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
&.ppcp-button-minicart {
|
||||
display: block;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-checkout {
|
||||
.ppcp-button-googlepay {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ppcp-has-googlepay-block {
|
||||
|
||||
.wp-block-woocommerce-checkout {
|
||||
.ppcp-button-googlepay {
|
||||
margin: 0;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.wp-block-woocommerce-cart {
|
||||
.ppcp-button-googlepay {
|
||||
margin: 0;
|
||||
height: 40px;
|
||||
}
|
||||
/* Workaround for blocks grid */
|
||||
.wc-block-components-express-payment__event-buttons {
|
||||
display: block;
|
||||
li[id*="express-payment-method-ppcp-"] {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
67
modules/ppcp-googlepay/resources/js/Context/BaseHandler.js
Normal file
67
modules/ppcp-googlepay/resources/js/Context/BaseHandler.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
import ErrorHandler from "../../../../ppcp-button/resources/js/modules/ErrorHandler";
|
||||
import CartActionHandler
|
||||
from "../../../../ppcp-button/resources/js/modules/ActionHandler/CartActionHandler";
|
||||
|
||||
class BaseHandler {
|
||||
|
||||
constructor(buttonConfig, ppcpConfig, externalHandler) {
|
||||
this.buttonConfig = buttonConfig;
|
||||
this.ppcpConfig = ppcpConfig;
|
||||
this.externalHandler = externalHandler;
|
||||
}
|
||||
|
||||
transactionInfo() {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
fetch(
|
||||
this.ppcpConfig.ajax.cart_script_params.endpoint,
|
||||
{
|
||||
method: 'GET',
|
||||
credentials: 'same-origin',
|
||||
}
|
||||
)
|
||||
.then(result => result.json())
|
||||
.then(result => {
|
||||
if (! result.success) {
|
||||
return;
|
||||
}
|
||||
|
||||
// handle script reload
|
||||
const data = result.data;
|
||||
|
||||
resolve({
|
||||
countryCode: data.country_code,
|
||||
currencyCode: data.currency_code,
|
||||
totalPriceStatus: 'FINAL',
|
||||
totalPrice: data.total_str
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
createOrder() {
|
||||
return this.actionHandler().configuration().createOrder(null, null);
|
||||
}
|
||||
|
||||
approveOrder(data, actions) {
|
||||
return this.actionHandler().configuration().onApprove(data, actions);
|
||||
}
|
||||
|
||||
actionHandler() {
|
||||
return new CartActionHandler(
|
||||
this.ppcpConfig,
|
||||
this.errorHandler(),
|
||||
);
|
||||
}
|
||||
|
||||
errorHandler() {
|
||||
return new ErrorHandler(
|
||||
this.ppcpConfig.labels.error.generic,
|
||||
document.querySelector('.woocommerce-notices-wrapper')
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BaseHandler;
|
|
@ -0,0 +1,15 @@
|
|||
import BaseHandler from "./BaseHandler";
|
||||
|
||||
class CartBlockHandler extends BaseHandler {
|
||||
|
||||
createOrder() {
|
||||
return this.externalHandler.createOrder();
|
||||
}
|
||||
|
||||
approveOrder(data, actions) {
|
||||
return this.externalHandler.onApprove(data, actions);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CartBlockHandler;
|
|
@ -0,0 +1,7 @@
|
|||
import BaseHandler from "./BaseHandler";
|
||||
|
||||
class CartHandler extends BaseHandler {
|
||||
|
||||
}
|
||||
|
||||
export default CartHandler;
|
|
@ -0,0 +1,15 @@
|
|||
import BaseHandler from "./BaseHandler";
|
||||
|
||||
class CheckoutBlockHandler extends BaseHandler{
|
||||
|
||||
createOrder() {
|
||||
return this.externalHandler.createOrder();
|
||||
}
|
||||
|
||||
approveOrder(data, actions) {
|
||||
return this.externalHandler.onApprove(data, actions);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CheckoutBlockHandler;
|
|
@ -0,0 +1,60 @@
|
|||
import Spinner from "../../../../ppcp-button/resources/js/modules/Helper/Spinner";
|
||||
import BaseHandler from "./BaseHandler";
|
||||
import CheckoutActionHandler
|
||||
from "../../../../ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler";
|
||||
import FormValidator from "../../../../ppcp-button/resources/js/modules/Helper/FormValidator";
|
||||
|
||||
class CheckoutHandler extends BaseHandler {
|
||||
|
||||
transactionInfo() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
||||
try {
|
||||
const spinner = new Spinner();
|
||||
const errorHandler = this.errorHandler();
|
||||
|
||||
const formSelector = this.ppcpConfig.context === 'checkout' ? 'form.checkout' : 'form#order_review';
|
||||
const formValidator = this.ppcpConfig.early_checkout_validation_enabled ?
|
||||
new FormValidator(
|
||||
this.ppcpConfig.ajax.validate_checkout.endpoint,
|
||||
this.ppcpConfig.ajax.validate_checkout.nonce,
|
||||
) : null;
|
||||
|
||||
if (!formValidator) {
|
||||
resolve(super.transactionInfo());
|
||||
return;
|
||||
}
|
||||
|
||||
formValidator.validate(document.querySelector(formSelector)).then((errors) => {
|
||||
if (errors.length > 0) {
|
||||
spinner.unblock();
|
||||
errorHandler.clear();
|
||||
errorHandler.messages(errors);
|
||||
|
||||
// fire WC event for other plugins
|
||||
jQuery( document.body ).trigger( 'checkout_error' , [ errorHandler.currentHtml() ] );
|
||||
|
||||
reject();
|
||||
} else {
|
||||
resolve(super.transactionInfo());
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
reject();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
actionHandler() {
|
||||
return new CheckoutActionHandler(
|
||||
this.ppcpConfig,
|
||||
this.errorHandler(),
|
||||
new Spinner()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CheckoutHandler;
|
|
@ -0,0 +1,29 @@
|
|||
import SingleProductHandler from "./SingleProductHandler";
|
||||
import CartHandler from "./CartHandler";
|
||||
import CheckoutHandler from "./CheckoutHandler";
|
||||
import CartBlockHandler from "./CartBlockHandler";
|
||||
import CheckoutBlockHandler from "./CheckoutBlockHandler";
|
||||
import MiniCartHandler from "./MiniCartHandler";
|
||||
|
||||
class ContextHandlerFactory {
|
||||
|
||||
static create(context, buttonConfig, ppcpConfig, externalActionHandler) {
|
||||
switch (context) {
|
||||
case 'product':
|
||||
return new SingleProductHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||
case 'cart':
|
||||
return new CartHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||
case 'checkout':
|
||||
case 'pay-now': // same as checkout
|
||||
return new CheckoutHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||
case 'mini-cart':
|
||||
return new MiniCartHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||
case 'cart-block':
|
||||
return new CartBlockHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||
case 'checkout-block':
|
||||
return new CheckoutBlockHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ContextHandlerFactory;
|
|
@ -0,0 +1,7 @@
|
|||
import BaseHandler from "./BaseHandler";
|
||||
|
||||
class MiniCartHandler extends BaseHandler {
|
||||
|
||||
}
|
||||
|
||||
export default MiniCartHandler;
|
|
@ -0,0 +1,65 @@
|
|||
import SingleProductActionHandler
|
||||
from "../../../../ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler";
|
||||
import SimulateCart from "../../../../ppcp-button/resources/js/modules/Helper/SimulateCart";
|
||||
import ErrorHandler from "../../../../ppcp-button/resources/js/modules/ErrorHandler";
|
||||
import UpdateCart from "../../../../ppcp-button/resources/js/modules/Helper/UpdateCart";
|
||||
import BaseHandler from "./BaseHandler";
|
||||
|
||||
class SingleProductHandler extends BaseHandler {
|
||||
|
||||
transactionInfo() {
|
||||
const errorHandler = new ErrorHandler(
|
||||
this.ppcpConfig.labels.error.generic,
|
||||
document.querySelector('.woocommerce-notices-wrapper')
|
||||
);
|
||||
|
||||
function form() {
|
||||
return document.querySelector('form.cart');
|
||||
}
|
||||
|
||||
const actionHandler = new SingleProductActionHandler(
|
||||
null,
|
||||
null,
|
||||
form(),
|
||||
errorHandler,
|
||||
);
|
||||
|
||||
const hasSubscriptions = PayPalCommerceGateway.data_client_id.has_subscriptions
|
||||
&& PayPalCommerceGateway.data_client_id.paypal_subscriptions_enabled;
|
||||
|
||||
const products = hasSubscriptions
|
||||
? actionHandler.getSubscriptionProducts()
|
||||
: actionHandler.getProducts();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
(new SimulateCart(
|
||||
this.ppcpConfig.ajax.simulate_cart.endpoint,
|
||||
this.ppcpConfig.ajax.simulate_cart.nonce,
|
||||
)).simulate((data) => {
|
||||
|
||||
resolve({
|
||||
countryCode: data.country_code,
|
||||
currencyCode: data.currency_code,
|
||||
totalPriceStatus: 'FINAL',
|
||||
totalPrice: data.total_str
|
||||
});
|
||||
|
||||
}, products);
|
||||
});
|
||||
}
|
||||
|
||||
actionHandler() {
|
||||
return new SingleProductActionHandler(
|
||||
this.ppcpConfig,
|
||||
new UpdateCart(
|
||||
this.ppcpConfig.ajax.change_cart.endpoint,
|
||||
this.ppcpConfig.ajax.change_cart.nonce,
|
||||
),
|
||||
document.querySelector('form.cart'),
|
||||
this.errorHandler(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SingleProductHandler;
|
268
modules/ppcp-googlepay/resources/js/GooglepayButton.js
Normal file
268
modules/ppcp-googlepay/resources/js/GooglepayButton.js
Normal file
|
@ -0,0 +1,268 @@
|
|||
import ContextHandlerFactory from "./Context/ContextHandlerFactory";
|
||||
import {setVisible} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
||||
import {setEnabled} from '../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler';
|
||||
|
||||
class GooglepayButton {
|
||||
|
||||
constructor(context, externalHandler, buttonConfig, ppcpConfig) {
|
||||
this.isInitialized = false;
|
||||
|
||||
this.context = context;
|
||||
this.externalHandler = externalHandler;
|
||||
this.buttonConfig = buttonConfig;
|
||||
this.ppcpConfig = ppcpConfig;
|
||||
|
||||
this.paymentsClient = null;
|
||||
|
||||
this.contextHandler = ContextHandlerFactory.create(
|
||||
this.context,
|
||||
this.buttonConfig,
|
||||
this.ppcpConfig,
|
||||
this.externalHandler
|
||||
);
|
||||
|
||||
console.log('[GooglePayButton] new Button', this);
|
||||
}
|
||||
|
||||
init(config) {
|
||||
if (this.isInitialized) {
|
||||
return;
|
||||
}
|
||||
this.isInitialized = true;
|
||||
|
||||
if (!this.validateConfig()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.googlePayConfig = config;
|
||||
this.allowedPaymentMethods = config.allowedPaymentMethods;
|
||||
this.baseCardPaymentMethod = this.allowedPaymentMethods[0];
|
||||
|
||||
this.initClient();
|
||||
this.initEventHandlers();
|
||||
|
||||
this.paymentsClient.isReadyToPay(
|
||||
this.buildReadyToPayRequest(this.allowedPaymentMethods, config)
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.result) {
|
||||
this.addButton(this.baseCardPaymentMethod);
|
||||
}
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
validateConfig() {
|
||||
if ( ['PRODUCTION', 'TEST'].indexOf(this.buttonConfig.environment) === -1) {
|
||||
console.error('[GooglePayButton] Invalid environment.', this.buttonConfig.environment);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !this.contextHandler ) {
|
||||
console.error('[GooglePayButton] Invalid context handler.', this.contextHandler);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns configurations relative to this button context.
|
||||
*/
|
||||
contextConfig() {
|
||||
let 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;
|
||||
|
||||
// Handle incompatible types.
|
||||
if (config.buttonStyle.type === 'buy') {
|
||||
config.buttonStyle.type = 'pay';
|
||||
}
|
||||
}
|
||||
|
||||
if (['cart-block', 'checkout-block'].indexOf(this.context) !== -1) {
|
||||
config.ppcpButtonWrapper = '#express-payment-method-ppcp-gateway';
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
initClient() {
|
||||
this.paymentsClient = new google.payments.api.PaymentsClient({
|
||||
environment: this.buttonConfig.environment,
|
||||
// add merchant info maybe
|
||||
paymentDataCallbacks: {
|
||||
//onPaymentDataChanged: onPaymentDataChanged,
|
||||
onPaymentAuthorized: this.onPaymentAuthorized.bind(this),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initEventHandlers() {
|
||||
const { wrapper, ppcpButtonWrapper } = this.contextConfig();
|
||||
|
||||
const syncButtonVisibility = () => {
|
||||
const $ppcpButtonWrapper = jQuery(ppcpButtonWrapper);
|
||||
setVisible(wrapper, $ppcpButtonWrapper.is(':visible'));
|
||||
setEnabled(wrapper, !$ppcpButtonWrapper.hasClass('ppcp-disabled'));
|
||||
}
|
||||
|
||||
jQuery(document).on('ppcp-shown ppcp-hidden ppcp-enabled ppcp-disabled', (ev, data) => {
|
||||
if (jQuery(data.selector).is(ppcpButtonWrapper)) {
|
||||
syncButtonVisibility();
|
||||
}
|
||||
});
|
||||
|
||||
syncButtonVisibility();
|
||||
}
|
||||
|
||||
buildReadyToPayRequest(allowedPaymentMethods, baseRequest) {
|
||||
return Object.assign({}, baseRequest, {
|
||||
allowedPaymentMethods: allowedPaymentMethods,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Google Pay purchase button
|
||||
*/
|
||||
addButton(baseCardPaymentMethod) {
|
||||
console.log('[GooglePayButton] addButton', this.context);
|
||||
|
||||
const { wrapper, ppcpStyle, buttonStyle } = this.contextConfig();
|
||||
|
||||
jQuery(wrapper).addClass('ppcp-button-' + ppcpStyle.shape);
|
||||
|
||||
const button =
|
||||
this.paymentsClient.createButton({
|
||||
onClick: this.onButtonClick.bind(this),
|
||||
allowedPaymentMethods: [baseCardPaymentMethod],
|
||||
buttonColor: buttonStyle.color || 'black',
|
||||
buttonType: buttonStyle.type || 'pay',
|
||||
buttonSizeMode: 'fill',
|
||||
});
|
||||
jQuery(wrapper).append(button);
|
||||
}
|
||||
|
||||
//------------------------
|
||||
// Button click
|
||||
//------------------------
|
||||
|
||||
/**
|
||||
* Show Google Pay payment sheet when Google Pay payment button is clicked
|
||||
*/
|
||||
async onButtonClick() {
|
||||
console.log('[GooglePayButton] onButtonClick', this.context);
|
||||
|
||||
const paymentDataRequest = await this.paymentDataRequest();
|
||||
console.log('[GooglePayButton] onButtonClick: paymentDataRequest', paymentDataRequest, this.context);
|
||||
|
||||
window.ppcpFundingSource = 'googlepay'; // Do this on another place like on create order endpoint handler.
|
||||
|
||||
this.paymentsClient.loadPaymentData(paymentDataRequest);
|
||||
}
|
||||
|
||||
async paymentDataRequest() {
|
||||
let baseRequest = {
|
||||
apiVersion: 2,
|
||||
apiVersionMinor: 0
|
||||
}
|
||||
|
||||
const googlePayConfig = this.googlePayConfig;
|
||||
const paymentDataRequest = Object.assign({}, baseRequest);
|
||||
paymentDataRequest.allowedPaymentMethods = googlePayConfig.allowedPaymentMethods;
|
||||
paymentDataRequest.transactionInfo = await this.contextHandler.transactionInfo();
|
||||
paymentDataRequest.merchantInfo = googlePayConfig.merchantInfo;
|
||||
paymentDataRequest.callbackIntents = ['PAYMENT_AUTHORIZATION'];
|
||||
return paymentDataRequest;
|
||||
}
|
||||
|
||||
|
||||
//------------------------
|
||||
// Payment process
|
||||
//------------------------
|
||||
|
||||
onPaymentAuthorized(paymentData) {
|
||||
console.log('[GooglePayButton] onPaymentAuthorized', this.context);
|
||||
return this.processPayment(paymentData);
|
||||
}
|
||||
|
||||
async processPayment(paymentData) {
|
||||
console.log('[GooglePayButton] processPayment', this.context);
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
let id = await this.contextHandler.createOrder();
|
||||
|
||||
console.log('[GooglePayButton] processPayment: createOrder', id, this.context);
|
||||
|
||||
const confirmOrderResponse = await paypal.Googlepay().confirmOrder({
|
||||
orderId: id,
|
||||
paymentMethodData: paymentData.paymentMethodData
|
||||
});
|
||||
|
||||
console.log('[GooglePayButton] processPayment: confirmOrder', confirmOrderResponse, this.context);
|
||||
|
||||
/** Capture the Order on the Server */
|
||||
if (confirmOrderResponse.status === "APPROVED") {
|
||||
|
||||
let approveFailed = false;
|
||||
await this.contextHandler.approveOrder({
|
||||
orderID: id
|
||||
}, { // actions mock object.
|
||||
restart: () => new Promise((resolve, reject) => {
|
||||
approveFailed = true;
|
||||
resolve();
|
||||
}),
|
||||
order: {
|
||||
get: () => new Promise((resolve, reject) => {
|
||||
resolve(null);
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
if (!approveFailed) {
|
||||
resolve(this.processPaymentResponse('SUCCESS'));
|
||||
} else {
|
||||
resolve(this.processPaymentResponse('ERROR', 'PAYMENT_AUTHORIZATION', 'FAILED TO APPROVE'));
|
||||
}
|
||||
|
||||
} else {
|
||||
resolve(this.processPaymentResponse('ERROR', 'PAYMENT_AUTHORIZATION', 'TRANSACTION FAILED'));
|
||||
}
|
||||
} catch(err) {
|
||||
resolve(this.processPaymentResponse('ERROR', 'PAYMENT_AUTHORIZATION', err.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
processPaymentResponse(state, intent = null, message = null) {
|
||||
let response = {
|
||||
transactionState: state,
|
||||
}
|
||||
|
||||
if (intent || message) {
|
||||
response.error = {
|
||||
intent: intent,
|
||||
message: message,
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[GooglePayButton] processPaymentResponse', response, this.context);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default GooglepayButton;
|
43
modules/ppcp-googlepay/resources/js/GooglepayManager.js
Normal file
43
modules/ppcp-googlepay/resources/js/GooglepayManager.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
import buttonModuleWatcher from "../../../ppcp-button/resources/js/modules/ButtonModuleWatcher";
|
||||
import GooglepayButton from "./GooglepayButton";
|
||||
|
||||
class GooglepayManager {
|
||||
|
||||
constructor(buttonConfig, ppcpConfig) {
|
||||
|
||||
this.buttonConfig = buttonConfig;
|
||||
this.ppcpConfig = ppcpConfig;
|
||||
this.googlePayConfig = null;
|
||||
|
||||
this.buttons = [];
|
||||
|
||||
buttonModuleWatcher.watchContextBootstrap((bootstrap) => {
|
||||
const button = new GooglepayButton(
|
||||
bootstrap.context,
|
||||
bootstrap.handler,
|
||||
buttonConfig,
|
||||
ppcpConfig,
|
||||
);
|
||||
|
||||
this.buttons.push(button);
|
||||
|
||||
if (this.googlePayConfig) {
|
||||
button.init(this.googlePayConfig);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init() {
|
||||
(async () => {
|
||||
// Gets GooglePay configuration of the PayPal merchant.
|
||||
this.googlePayConfig = await paypal.Googlepay().config();
|
||||
|
||||
for (const button of this.buttons) {
|
||||
button.init(this.googlePayConfig);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default GooglepayManager;
|
71
modules/ppcp-googlepay/resources/js/boot-block.js
Normal file
71
modules/ppcp-googlepay/resources/js/boot-block.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
import {useEffect, useState} from '@wordpress/element';
|
||||
import {registerExpressPaymentMethod, registerPaymentMethod} from '@woocommerce/blocks-registry';
|
||||
import {loadPaypalScript} from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading'
|
||||
import GooglepayManager from "./GooglepayManager";
|
||||
import {loadCustomScript} from "@paypal/paypal-js";
|
||||
|
||||
const ppcpData = wc.wcSettings.getSetting('ppcp-gateway_data');
|
||||
const ppcpConfig = ppcpData.scriptData;
|
||||
|
||||
const buttonData = wc.wcSettings.getSetting('ppcp-googlepay_data');
|
||||
const buttonConfig = buttonData.scriptData;
|
||||
|
||||
if (typeof window.PayPalCommerceGateway === 'undefined') {
|
||||
window.PayPalCommerceGateway = ppcpConfig;
|
||||
}
|
||||
|
||||
const GooglePayComponent = () => {
|
||||
const [bootstrapped, setBootstrapped] = useState(false);
|
||||
const [paypalLoaded, setPaypalLoaded] = useState(false);
|
||||
const [googlePayLoaded, setGooglePayLoaded] = useState(false);
|
||||
|
||||
const bootstrap = function () {
|
||||
const manager = new GooglepayManager(buttonConfig, ppcpConfig);
|
||||
manager.init();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const bodyClass = 'ppcp-has-googlepay-block';
|
||||
if (!document.body.classList.contains(bodyClass)) {
|
||||
document.body.classList.add(bodyClass);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Load GooglePay SDK
|
||||
loadCustomScript({ url: buttonConfig.sdk_url }).then(() => {
|
||||
setGooglePayLoaded(true);
|
||||
});
|
||||
|
||||
// Load PayPal
|
||||
loadPaypalScript(ppcpConfig, () => {
|
||||
setPaypalLoaded(true);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!bootstrapped && paypalLoaded && googlePayLoaded) {
|
||||
setBootstrapped(true);
|
||||
bootstrap();
|
||||
}
|
||||
}, [paypalLoaded, googlePayLoaded]);
|
||||
|
||||
return (
|
||||
<div id={buttonConfig.button.wrapper.replace('#', '')} className="ppcp-button-googlepay"></div>
|
||||
);
|
||||
}
|
||||
|
||||
const features = ['products'];
|
||||
let registerMethod = registerExpressPaymentMethod;
|
||||
|
||||
registerMethod({
|
||||
name: buttonData.id,
|
||||
label: <div dangerouslySetInnerHTML={{__html: buttonData.title}}/>,
|
||||
content: <GooglePayComponent isEditing={false}/>,
|
||||
edit: <GooglePayComponent isEditing={true}/>,
|
||||
ariaLabel: buttonData.title,
|
||||
canMakePayment: () => buttonData.enabled,
|
||||
supports: {
|
||||
features: features,
|
||||
},
|
||||
});
|
61
modules/ppcp-googlepay/resources/js/boot.js
Normal file
61
modules/ppcp-googlepay/resources/js/boot.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
import {loadCustomScript} from "@paypal/paypal-js";
|
||||
import {loadPaypalScript} from "../../../ppcp-button/resources/js/modules/Helper/ScriptLoading";
|
||||
import GooglepayManager from "./GooglepayManager";
|
||||
|
||||
(function ({
|
||||
buttonConfig,
|
||||
ppcpConfig,
|
||||
jQuery
|
||||
}) {
|
||||
|
||||
const bootstrap = function () {
|
||||
const manager = new GooglepayManager(buttonConfig, ppcpConfig);
|
||||
manager.init();
|
||||
};
|
||||
|
||||
document.addEventListener(
|
||||
'DOMContentLoaded',
|
||||
() => {
|
||||
if (
|
||||
(typeof (buttonConfig) === 'undefined') ||
|
||||
(typeof (ppcpConfig) === 'undefined')
|
||||
) {
|
||||
console.error('PayPal button could not be configured.');
|
||||
return;
|
||||
}
|
||||
|
||||
// If button wrapper is not present then there is no need to load the scripts.
|
||||
if (!jQuery(buttonConfig.button.wrapper).length) {
|
||||
return;
|
||||
}
|
||||
|
||||
let bootstrapped = false;
|
||||
let paypalLoaded = false;
|
||||
let googlePayLoaded = false;
|
||||
|
||||
const tryToBoot = () => {
|
||||
if (!bootstrapped && paypalLoaded && googlePayLoaded) {
|
||||
bootstrapped = true;
|
||||
bootstrap();
|
||||
}
|
||||
}
|
||||
|
||||
// Load GooglePay SDK
|
||||
loadCustomScript({ url: buttonConfig.sdk_url }).then(() => {
|
||||
googlePayLoaded = true;
|
||||
tryToBoot();
|
||||
});
|
||||
|
||||
// Load PayPal
|
||||
loadPaypalScript(ppcpConfig, () => {
|
||||
paypalLoaded = true;
|
||||
tryToBoot();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
})({
|
||||
buttonConfig: window.wc_ppcp_googlepay,
|
||||
ppcpConfig: window.PayPalCommerceGateway,
|
||||
jQuery: window.jQuery
|
||||
});
|
120
modules/ppcp-googlepay/services.php
Normal file
120
modules/ppcp-googlepay/services.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
/**
|
||||
* The Googlepay module services.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Googlepay
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Googlepay;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodTypeInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
||||
use WooCommerce\PayPalCommerce\Googlepay\Assets\BlocksPaymentMethod;
|
||||
use WooCommerce\PayPalCommerce\Googlepay\Assets\Button;
|
||||
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmApplies;
|
||||
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
|
||||
// If GooglePay can be configured.
|
||||
'googlepay.eligible' => static function ( ContainerInterface $container ): bool {
|
||||
$apm_applies = $container->get( 'googlepay.helpers.apm-applies' );
|
||||
assert( $apm_applies instanceof ApmApplies );
|
||||
|
||||
return $apm_applies->for_country_currency();
|
||||
},
|
||||
|
||||
'googlepay.helpers.apm-applies' => static function ( ContainerInterface $container ) : ApmApplies {
|
||||
return new ApmApplies(
|
||||
$container->get( 'googlepay.supported-country-currency-matrix' ),
|
||||
$container->get( 'api.shop.currency' ),
|
||||
$container->get( 'api.shop.country' )
|
||||
);
|
||||
},
|
||||
|
||||
// If GooglePay is configured.
|
||||
'googlepay.available' => static function ( ContainerInterface $container ): bool {
|
||||
if ( apply_filters( 'woocommerce_paypal_payments_googlepay_validate_product_status', false ) ) {
|
||||
$status = $container->get( 'googlepay.helpers.apm-product-status' );
|
||||
assert( $status instanceof ApmProductStatus );
|
||||
/**
|
||||
* If merchant isn't onboarded via /v1/customer/partner-referrals this returns false as the API call fails.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_paypal_payments_googlepay_product_status', $status->is_active() );
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
'googlepay.helpers.apm-product-status' => static function( ContainerInterface $container ): ApmProductStatus {
|
||||
return new ApmProductStatus(
|
||||
$container->get( 'wcgateway.settings' ),
|
||||
$container->get( 'api.endpoint.partners' ),
|
||||
$container->get( 'onboarding.state' )
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* The matrix which countries and currency combinations can be used for GooglePay.
|
||||
*/
|
||||
'googlepay.supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array {
|
||||
/**
|
||||
* Returns which countries and currency combinations can be used for GooglePay.
|
||||
*/
|
||||
return apply_filters(
|
||||
'woocommerce_paypal_payments_googlepay_supported_country_currency_matrix',
|
||||
array(
|
||||
'US' => array(
|
||||
'AUD',
|
||||
'CAD',
|
||||
'EUR',
|
||||
'GBP',
|
||||
'JPY',
|
||||
'USD',
|
||||
),
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'googlepay.button' => static function ( ContainerInterface $container ): ButtonInterface {
|
||||
return new Button(
|
||||
$container->get( 'googlepay.url' ),
|
||||
$container->get( 'googlepay.sdk_url' ),
|
||||
$container->get( 'ppcp.asset-version' ),
|
||||
$container->get( 'session.handler' ),
|
||||
$container->get( 'wcgateway.settings' ),
|
||||
$container->get( 'onboarding.environment' ),
|
||||
$container->get( 'wcgateway.settings.status' ),
|
||||
$container->get( 'api.shop.currency' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
||||
'googlepay.blocks-payment-method' => static function ( ContainerInterface $container ): PaymentMethodTypeInterface {
|
||||
return new BlocksPaymentMethod(
|
||||
'ppcp-googlepay',
|
||||
$container->get( 'googlepay.url' ),
|
||||
$container->get( 'ppcp.asset-version' ),
|
||||
$container->get( 'googlepay.button' ),
|
||||
$container->get( 'blocks.method' )
|
||||
);
|
||||
},
|
||||
|
||||
'googlepay.url' => static function ( ContainerInterface $container ): string {
|
||||
$path = realpath( __FILE__ );
|
||||
if ( false === $path ) {
|
||||
return '';
|
||||
}
|
||||
return plugins_url(
|
||||
'/modules/ppcp-googlepay/',
|
||||
dirname( $path, 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
|
||||
'googlepay.sdk_url' => static function ( ContainerInterface $container ): string {
|
||||
return 'https://pay.google.com/gp/p/js/pay.js';
|
||||
},
|
||||
|
||||
);
|
114
modules/ppcp-googlepay/src/Assets/BlocksPaymentMethod.php
Normal file
114
modules/ppcp-googlepay/src/Assets/BlocksPaymentMethod.php
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
/**
|
||||
* The googlepay blocks module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Googlepay
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Googlepay\Assets;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
|
||||
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodTypeInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
||||
|
||||
/**
|
||||
* Class BlocksPaymentMethod
|
||||
*/
|
||||
class BlocksPaymentMethod extends AbstractPaymentMethodType {
|
||||
/**
|
||||
* The URL of this module.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $module_url;
|
||||
|
||||
/**
|
||||
* The assets version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* The button.
|
||||
*
|
||||
* @var ButtonInterface
|
||||
*/
|
||||
private $button;
|
||||
|
||||
/**
|
||||
* The paypal payment method.
|
||||
*
|
||||
* @var PaymentMethodTypeInterface
|
||||
*/
|
||||
private $paypal_payment_method;
|
||||
|
||||
/**
|
||||
* Assets constructor.
|
||||
*
|
||||
* @param string $name The name of this module.
|
||||
* @param string $module_url The url of this module.
|
||||
* @param string $version The assets version.
|
||||
* @param ButtonInterface $button The button.
|
||||
* @param PaymentMethodTypeInterface $paypal_payment_method The paypal payment method.
|
||||
*/
|
||||
public function __construct(
|
||||
string $name,
|
||||
string $module_url,
|
||||
string $version,
|
||||
ButtonInterface $button,
|
||||
PaymentMethodTypeInterface $paypal_payment_method
|
||||
) {
|
||||
$this->name = $name;
|
||||
$this->module_url = $module_url;
|
||||
$this->version = $version;
|
||||
$this->button = $button;
|
||||
$this->paypal_payment_method = $paypal_payment_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function initialize() { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function is_active() {
|
||||
return $this->paypal_payment_method->is_active();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_payment_method_script_handles() {
|
||||
$handle = $this->name . '-block';
|
||||
|
||||
wp_register_script(
|
||||
$handle,
|
||||
trailingslashit( $this->module_url ) . 'assets/js/boot-block.js',
|
||||
array(),
|
||||
$this->version,
|
||||
true
|
||||
);
|
||||
|
||||
return array( $handle );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function get_payment_method_data() {
|
||||
$paypal_data = $this->paypal_payment_method->get_payment_method_data();
|
||||
|
||||
return array(
|
||||
'id' => $this->name,
|
||||
'title' => $paypal_data['title'], // See if we should use another.
|
||||
'description' => $paypal_data['description'], // See if we should use another.
|
||||
'enabled' => $paypal_data['enabled'], // This button is enabled when PayPal buttons are.
|
||||
'scriptData' => $this->button->script_data(),
|
||||
);
|
||||
}
|
||||
}
|
406
modules/ppcp-googlepay/src/Assets/Button.php
Normal file
406
modules/ppcp-googlepay/src/Assets/Button.php
Normal file
|
@ -0,0 +1,406 @@
|
|||
<?php
|
||||
/**
|
||||
* Registers and configures the necessary Javascript for the button, credit messaging and DCC fields.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Googlepay\Assets
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Googlepay\Assets;
|
||||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
* Class Button
|
||||
*/
|
||||
class Button implements ButtonInterface {
|
||||
|
||||
/**
|
||||
* The URL to the module.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $module_url;
|
||||
|
||||
/**
|
||||
* The URL to the SDK.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $sdk_url;
|
||||
|
||||
/**
|
||||
* The assets version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* The settings.
|
||||
*
|
||||
* @var Settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* The environment object.
|
||||
*
|
||||
* @var Environment
|
||||
*/
|
||||
private $environment;
|
||||
|
||||
/**
|
||||
* The Settings status helper.
|
||||
*
|
||||
* @var SettingsStatus
|
||||
*/
|
||||
private $settings_status;
|
||||
|
||||
/**
|
||||
* 3-letter currency code of the shop.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $currency;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Session handler.
|
||||
*
|
||||
* @var SessionHandler
|
||||
*/
|
||||
private $session_handler;
|
||||
|
||||
/**
|
||||
* SmartButton constructor.
|
||||
*
|
||||
* @param string $module_url The URL to the module.
|
||||
* @param string $sdk_url The URL to the SDK.
|
||||
* @param string $version The assets version.
|
||||
* @param SessionHandler $session_handler The Session handler.
|
||||
* @param Settings $settings The Settings.
|
||||
* @param Environment $environment The environment object.
|
||||
* @param SettingsStatus $settings_status The Settings status helper.
|
||||
* @param string $currency 3-letter currency code of the shop.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
string $module_url,
|
||||
string $sdk_url,
|
||||
string $version,
|
||||
SessionHandler $session_handler,
|
||||
Settings $settings,
|
||||
Environment $environment,
|
||||
SettingsStatus $settings_status,
|
||||
string $currency,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
$this->module_url = $module_url;
|
||||
$this->sdk_url = $sdk_url;
|
||||
$this->version = $version;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->settings = $settings;
|
||||
$this->environment = $environment;
|
||||
$this->settings_status = $settings_status;
|
||||
$this->currency = $currency;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the button.
|
||||
*/
|
||||
public function initialize(): void {
|
||||
add_filter( 'ppcp_onboarding_options', array( $this, 'add_onboarding_options' ), 10, 1 );
|
||||
add_filter( 'ppcp_partner_referrals_data', array( $this, 'add_partner_referrals_data' ), 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the GooglePay onboarding option.
|
||||
*
|
||||
* @param string $options The options.
|
||||
* @return string
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
public function add_onboarding_options( $options ): string {
|
||||
$checked = '';
|
||||
try {
|
||||
$onboard_with_google = $this->settings->get( 'ppcp-onboarding-google' );
|
||||
if ( $onboard_with_google === '1' ) {
|
||||
$checked = 'checked';
|
||||
}
|
||||
} catch ( NotFoundException $exception ) {
|
||||
$checked = '';
|
||||
}
|
||||
|
||||
return $options
|
||||
. '<li><label><input type="checkbox" id="ppcp-onboarding-google" ' . $checked . '> '
|
||||
. __( 'Onboard with GooglePay', 'woocommerce-paypal-payments' )
|
||||
. '</label></li>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to partner referrals data.
|
||||
*
|
||||
* @param array $data The referrals data.
|
||||
* @return array
|
||||
*/
|
||||
public function add_partner_referrals_data( array $data ): array {
|
||||
try {
|
||||
$onboard_with_google = $this->settings->get( 'ppcp-onboarding-google' );
|
||||
if ( ! wc_string_to_bool( $onboard_with_google ) ) {
|
||||
return $data;
|
||||
}
|
||||
} catch ( NotFoundException $exception ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ( ! in_array( 'PAYMENT_METHODS', $data['products'], true ) ) {
|
||||
if ( in_array( 'PPCP', $data['products'], true ) ) {
|
||||
$data['products'][] = 'PAYMENT_METHODS';
|
||||
} elseif ( in_array( 'EXPRESS_CHECKOUT', $data['products'], true ) ) { // A bit sketchy, maybe replace on the EXPRESS_CHECKOUT index.
|
||||
$data['products'][0] = 'PAYMENT_METHODS';
|
||||
}
|
||||
}
|
||||
|
||||
$data['capabilities'][] = 'GOOGLE_PAY';
|
||||
|
||||
$nonce = $data['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['seller_nonce'];
|
||||
|
||||
$data['operations'][] = array(
|
||||
'operation' => 'API_INTEGRATION',
|
||||
'api_integration_preference' => array(
|
||||
'rest_api_integration' => array(
|
||||
'integration_method' => 'PAYPAL',
|
||||
'integration_type' => 'THIRD_PARTY',
|
||||
'third_party_details' => array(
|
||||
'features' => array(
|
||||
'PAYMENT',
|
||||
'REFUND',
|
||||
),
|
||||
'seller_nonce' => $nonce,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if Google Pay button is enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_enabled(): bool {
|
||||
try {
|
||||
return $this->settings->has( 'googlepay_button_enabled' ) && $this->settings->get( 'googlepay_button_enabled' );
|
||||
} catch ( Exception $e ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the necessary action hooks to render the HTML depending on the settings.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-suppress RedundantCondition
|
||||
*/
|
||||
public function render(): bool {
|
||||
if ( ! $this->is_enabled() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$button_enabled_product = $this->settings_status->is_smart_button_enabled_for_location( 'product' );
|
||||
$button_enabled_cart = $this->settings_status->is_smart_button_enabled_for_location( 'cart' );
|
||||
$button_enabled_checkout = true;
|
||||
$button_enabled_payorder = true;
|
||||
$button_enabled_minicart = $this->settings_status->is_smart_button_enabled_for_location( 'mini-cart' );
|
||||
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
add_filter(
|
||||
'woocommerce_paypal_payments_sdk_components_hook',
|
||||
function( $components ) {
|
||||
$components[] = 'googlepay';
|
||||
return $components;
|
||||
}
|
||||
);
|
||||
|
||||
if ( $button_enabled_product ) {
|
||||
$default_hook_name = 'woocommerce_paypal_payments_single_product_button_render';
|
||||
$render_placeholder = apply_filters( 'woocommerce_paypal_payments_googlepay_single_product_button_render_hook', $default_hook_name );
|
||||
$render_placeholder = is_string( $render_placeholder ) ? $render_placeholder : $default_hook_name;
|
||||
add_action(
|
||||
$render_placeholder,
|
||||
function () {
|
||||
$this->googlepay_button();
|
||||
},
|
||||
32
|
||||
);
|
||||
}
|
||||
|
||||
if ( $button_enabled_cart ) {
|
||||
$default_hook_name = 'woocommerce_paypal_payments_cart_button_render';
|
||||
$render_placeholder = apply_filters( 'woocommerce_paypal_payments_googlepay_cart_button_render_hook', $default_hook_name );
|
||||
$render_placeholder = is_string( $render_placeholder ) ? $render_placeholder : $default_hook_name;
|
||||
add_action(
|
||||
$render_placeholder,
|
||||
function () {
|
||||
$this->googlepay_button();
|
||||
},
|
||||
21
|
||||
);
|
||||
}
|
||||
|
||||
if ( $button_enabled_checkout ) {
|
||||
$default_hook_name = 'woocommerce_paypal_payments_checkout_button_render';
|
||||
$render_placeholder = apply_filters( 'woocommerce_paypal_payments_googlepay_checkout_button_render_hook', $default_hook_name );
|
||||
$render_placeholder = is_string( $render_placeholder ) ? $render_placeholder : $default_hook_name;
|
||||
add_action(
|
||||
$render_placeholder,
|
||||
function () {
|
||||
$this->googlepay_button();
|
||||
},
|
||||
21
|
||||
);
|
||||
}
|
||||
|
||||
if ( $button_enabled_payorder ) {
|
||||
$default_hook_name = 'woocommerce_paypal_payments_payorder_button_render';
|
||||
$render_placeholder = apply_filters( 'woocommerce_paypal_payments_googlepay_payorder_button_render_hook', $default_hook_name );
|
||||
$render_placeholder = is_string( $render_placeholder ) ? $render_placeholder : $default_hook_name;
|
||||
add_action(
|
||||
$render_placeholder,
|
||||
function () {
|
||||
$this->googlepay_button();
|
||||
},
|
||||
21
|
||||
);
|
||||
}
|
||||
|
||||
if ( $button_enabled_minicart ) {
|
||||
$default_hook_name = 'woocommerce_paypal_payments_minicart_button_render';
|
||||
$render_placeholder = apply_filters( 'woocommerce_paypal_payments_googlepay_minicart_button_render_hook', $default_hook_name );
|
||||
$render_placeholder = is_string( $render_placeholder ) ? $render_placeholder : $default_hook_name;
|
||||
add_action(
|
||||
$render_placeholder,
|
||||
function () {
|
||||
echo '<span id="ppc-button-googlepay-container-minicart" class="ppcp-button-googlepay ppcp-button-minicart"></span>';
|
||||
},
|
||||
21
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* GooglePay button markup
|
||||
*/
|
||||
private function googlepay_button(): void {
|
||||
?>
|
||||
<div id="ppc-button-googlepay-container" class="ppcp-button-googlepay">
|
||||
<?php wp_nonce_field( 'woocommerce-process_checkout', 'woocommerce-process-checkout-nonce' ); ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues scripts/styles.
|
||||
*/
|
||||
public function enqueue(): void {
|
||||
if ( ! $this->is_enabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_register_script(
|
||||
'wc-ppcp-googlepay',
|
||||
untrailingslashit( $this->module_url ) . '/assets/js/boot.js',
|
||||
array(),
|
||||
$this->version,
|
||||
true
|
||||
);
|
||||
wp_enqueue_script( 'wc-ppcp-googlepay' );
|
||||
|
||||
wp_register_style(
|
||||
'wc-ppcp-googlepay',
|
||||
untrailingslashit( $this->module_url ) . '/assets/css/styles.css',
|
||||
array(),
|
||||
$this->version
|
||||
);
|
||||
wp_enqueue_style( 'wc-ppcp-googlepay' );
|
||||
|
||||
wp_localize_script(
|
||||
'wc-ppcp-googlepay',
|
||||
'wc_ppcp_googlepay',
|
||||
$this->script_data()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The configuration for the smart buttons.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function script_data(): array {
|
||||
return array(
|
||||
'environment' => $this->environment->current_environment_is( Environment::SANDBOX ) ? 'TEST' : 'PRODUCTION',
|
||||
'sdk_url' => $this->sdk_url,
|
||||
'button' => array(
|
||||
'wrapper' => '#ppc-button-googlepay-container',
|
||||
'style' => $this->button_styles_for_context( 'cart' ), // For now use cart. Pass the context if necessary.
|
||||
'mini_cart_wrapper' => '#ppc-button-googlepay-container-minicart',
|
||||
'mini_cart_style' => $this->button_styles_for_context( 'mini-cart' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the style for a given indicator in a given context.
|
||||
*
|
||||
* @param string $context The context.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function button_styles_for_context( string $context ): array {
|
||||
// Use the cart/checkout styles for blocks.
|
||||
$context = str_replace( '-block', '', $context );
|
||||
|
||||
$values = array(
|
||||
'color' => 'black',
|
||||
'type' => 'pay',
|
||||
);
|
||||
|
||||
foreach ( $values as $style => $value ) {
|
||||
if ( $this->settings->has( 'googlepay_button_' . $context . '_' . $style ) ) {
|
||||
$values[ $style ] = $this->settings->get( 'googlepay_button_' . $context . '_' . $style );
|
||||
} elseif ( $this->settings->has( 'googlepay_button_' . $style ) ) {
|
||||
$values[ $style ] = $this->settings->get( 'googlepay_button_' . $style );
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
}
|
102
modules/ppcp-googlepay/src/GooglepayModule.php
Normal file
102
modules/ppcp-googlepay/src/GooglepayModule.php
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* The Googlepay module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Googlepay
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Googlepay;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
||||
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus;
|
||||
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;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
* Class GooglepayModule
|
||||
*/
|
||||
class GooglepayModule 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 {
|
||||
|
||||
if ( ! $c->get( 'googlepay.eligible' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$button = $c->get( 'googlepay.button' );
|
||||
assert( $button instanceof ButtonInterface );
|
||||
$button->initialize();
|
||||
|
||||
if ( ! $c->get( 'googlepay.available' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action(
|
||||
'wp',
|
||||
static function () use ( $c, $button ) {
|
||||
if ( is_admin() ) {
|
||||
return;
|
||||
}
|
||||
$button->render();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
static function () use ( $c, $button ) {
|
||||
$button->enqueue();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_blocks_payment_method_type_registration',
|
||||
function( PaymentMethodRegistry $payment_method_registry ) use ( $c, $button ): void {
|
||||
if ( $button->is_enabled() ) {
|
||||
$payment_method_registry->register( $c->get( 'googlepay.blocks-payment-method' ) );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Clear product status handling.
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_clear_apm_product_status',
|
||||
function( Settings $settings = null ) use ( $c ): void {
|
||||
$apm_status = $c->get( 'googlepay.helpers.apm-product-status' );
|
||||
assert( $apm_status instanceof ApmProductStatus );
|
||||
|
||||
if ( ! $settings instanceof Settings ) {
|
||||
$settings = null;
|
||||
}
|
||||
|
||||
$apm_status->clear( $settings );
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key for the module.
|
||||
*
|
||||
* @return string|void
|
||||
*/
|
||||
public function getKey() {
|
||||
}
|
||||
}
|
67
modules/ppcp-googlepay/src/Helper/ApmApplies.php
Normal file
67
modules/ppcp-googlepay/src/Helper/ApmApplies.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
/**
|
||||
* Properties of the GooglePay module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Googlepay\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Googlepay\Helper;
|
||||
|
||||
/**
|
||||
* Class ApmApplies
|
||||
*/
|
||||
class ApmApplies {
|
||||
|
||||
/**
|
||||
* The matrix which countries and currency combinations can be used for DCC.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $allowed_country_currency_matrix;
|
||||
|
||||
/**
|
||||
* 3-letter currency code of the shop.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $currency;
|
||||
|
||||
/**
|
||||
* 2-letter country code of the shop.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $country;
|
||||
|
||||
/**
|
||||
* DccApplies constructor.
|
||||
*
|
||||
* @param array $allowed_country_currency_matrix The matrix which countries and currency combinations can be used for DCC.
|
||||
* @param string $currency 3-letter currency code of the shop.
|
||||
* @param string $country 2-letter country code of the shop.
|
||||
*/
|
||||
public function __construct(
|
||||
array $allowed_country_currency_matrix,
|
||||
string $currency,
|
||||
string $country
|
||||
) {
|
||||
$this->allowed_country_currency_matrix = $allowed_country_currency_matrix;
|
||||
$this->currency = $currency;
|
||||
$this->country = $country;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether GooglePay can be used in the current country and the current currency used.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function for_country_currency(): bool {
|
||||
if ( ! in_array( $this->country, array_keys( $this->allowed_country_currency_matrix ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
return in_array( $this->currency, $this->allowed_country_currency_matrix[ $this->country ], true );
|
||||
}
|
||||
|
||||
}
|
139
modules/ppcp-googlepay/src/Helper/ApmProductStatus.php
Normal file
139
modules/ppcp-googlepay/src/Helper/ApmProductStatus.php
Normal file
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
/**
|
||||
* Status of the GooglePay merchant connection.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Googlepay\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Googlepay\Helper;
|
||||
|
||||
use Throwable;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
* Class ApmProductStatus
|
||||
*/
|
||||
class ApmProductStatus {
|
||||
const CAPABILITY_NAME = 'GOOGLE_PAY';
|
||||
const SETTINGS_KEY = 'products_googlepay_enabled';
|
||||
|
||||
const SETTINGS_VALUE_ENABLED = 'yes';
|
||||
const SETTINGS_VALUE_DISABLED = 'no';
|
||||
const SETTINGS_VALUE_UNDEFINED = '';
|
||||
|
||||
/**
|
||||
* The current status stored in memory.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
private $current_status = null;
|
||||
|
||||
/**
|
||||
* The settings.
|
||||
*
|
||||
* @var Settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* The partners endpoint.
|
||||
*
|
||||
* @var PartnersEndpoint
|
||||
*/
|
||||
private $partners_endpoint;
|
||||
|
||||
/**
|
||||
* The onboarding status
|
||||
*
|
||||
* @var State
|
||||
*/
|
||||
private $onboarding_state;
|
||||
|
||||
/**
|
||||
* ApmProductStatus constructor.
|
||||
*
|
||||
* @param Settings $settings The Settings.
|
||||
* @param PartnersEndpoint $partners_endpoint The Partner Endpoint.
|
||||
* @param State $onboarding_state The onboarding state.
|
||||
*/
|
||||
public function __construct(
|
||||
Settings $settings,
|
||||
PartnersEndpoint $partners_endpoint,
|
||||
State $onboarding_state
|
||||
) {
|
||||
$this->settings = $settings;
|
||||
$this->partners_endpoint = $partners_endpoint;
|
||||
$this->onboarding_state = $onboarding_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the active/subscribed products support Googlepay.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_active() : bool {
|
||||
if ( $this->onboarding_state->current_state() < State::STATE_ONBOARDED ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( null !== $this->current_status ) {
|
||||
return $this->current_status;
|
||||
}
|
||||
|
||||
if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) {
|
||||
$this->current_status = wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) );
|
||||
return $this->current_status;
|
||||
}
|
||||
|
||||
try {
|
||||
$seller_status = $this->partners_endpoint->seller_status();
|
||||
} catch ( Throwable $error ) {
|
||||
// It may be a transitory error, don't persist the status.
|
||||
$this->current_status = false;
|
||||
return $this->current_status;
|
||||
}
|
||||
|
||||
foreach ( $seller_status->products() as $product ) {
|
||||
if ( $product->name() !== 'PAYMENT_METHODS' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( in_array( self::CAPABILITY_NAME, $product->capabilities(), true ) ) {
|
||||
$this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED );
|
||||
$this->settings->persist();
|
||||
|
||||
$this->current_status = true;
|
||||
return $this->current_status;
|
||||
}
|
||||
}
|
||||
|
||||
$this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED );
|
||||
$this->settings->persist();
|
||||
|
||||
$this->current_status = false;
|
||||
return $this->current_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the persisted result to force a recheck.
|
||||
*
|
||||
* @param Settings|null $settings The settings object.
|
||||
* We accept a Settings object to don't override other sequential settings that are being updated elsewhere.
|
||||
* @return void
|
||||
*/
|
||||
public function clear( Settings $settings = null ): void {
|
||||
if ( null === $settings ) {
|
||||
$settings = $this->settings;
|
||||
}
|
||||
|
||||
$this->current_status = null;
|
||||
|
||||
$settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_UNDEFINED );
|
||||
$settings->persist();
|
||||
}
|
||||
|
||||
}
|
46
modules/ppcp-googlepay/src/Helper/PropertiesDictionary.php
Normal file
46
modules/ppcp-googlepay/src/Helper/PropertiesDictionary.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
/**
|
||||
* Properties of the GooglePay module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Googlepay\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Googlepay\Helper;
|
||||
|
||||
/**
|
||||
* Class Button
|
||||
*/
|
||||
class PropertiesDictionary {
|
||||
|
||||
/**
|
||||
* Returns the possible list of button colors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function button_colors(): array {
|
||||
return array(
|
||||
'white' => __( 'White', 'woocommerce-paypal-payments' ),
|
||||
'black' => __( 'Black', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the possible list of button types.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function button_types(): array {
|
||||
return array(
|
||||
'book' => __( 'Book', 'woocommerce-paypal-payments' ),
|
||||
'buy' => __( 'Buy', 'woocommerce-paypal-payments' ),
|
||||
'checkout' => __( 'Checkout', 'woocommerce-paypal-payments' ),
|
||||
'donate' => __( 'Donate', 'woocommerce-paypal-payments' ),
|
||||
'order' => __( 'Order', 'woocommerce-paypal-payments' ),
|
||||
'pay' => __( 'Pay', 'woocommerce-paypal-payments' ),
|
||||
'plain' => __( 'Plain', 'woocommerce-paypal-payments' ),
|
||||
'subscribe' => __( 'Book', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
}
|
||||
}
|
40
modules/ppcp-googlepay/webpack.config.js
Normal file
40
modules/ppcp-googlepay/webpack.config.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
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: {
|
||||
'boot': path.resolve('./resources/js/boot.js'),
|
||||
'boot-block': path.resolve('./resources/js/boot-block.js'),
|
||||
"styles": path.resolve('./resources/css/styles.scss')
|
||||
},
|
||||
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'}
|
||||
]
|
||||
}]
|
||||
}
|
||||
};
|
2241
modules/ppcp-googlepay/yarn.lock
Normal file
2241
modules/ppcp-googlepay/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
|
@ -134,6 +134,7 @@ class LoginSellerEndpoint implements EndpointInterface {
|
|||
$this->settings->set( 'products_dcc_enabled', null );
|
||||
$this->settings->set( 'products_pui_enabled', null );
|
||||
$this->settings->persist();
|
||||
do_action( 'woocommerce_paypal_payments_clear_apm_product_status', $this->settings );
|
||||
|
||||
$endpoint = $is_sandbox ? $this->login_seller_sandbox : $this->login_seller_production;
|
||||
$credentials = $endpoint->credentials_for(
|
||||
|
|
|
@ -238,6 +238,7 @@ class OnboardingRESTController {
|
|||
|
||||
$settings->set( 'products_dcc_enabled', null );
|
||||
$settings->set( 'products_pui_enabled', null );
|
||||
do_action( 'woocommerce_paypal_payments_clear_apm_product_status', $settings );
|
||||
|
||||
if ( ! $settings->persist() ) {
|
||||
return new \WP_Error(
|
||||
|
|
|
@ -703,7 +703,6 @@ return array(
|
|||
'requirements' => array(),
|
||||
'gateway' => 'paypal',
|
||||
),
|
||||
|
||||
'disable_cards' => array(
|
||||
'title' => __( 'Disable specific credit cards', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-multiselect',
|
||||
|
@ -950,6 +949,13 @@ return array(
|
|||
'paylater' => _x( 'Pay Later', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
},
|
||||
|
||||
'wcgateway.extra-funding-sources' => static function( ContainerInterface $container ): array {
|
||||
return array(
|
||||
'googlepay' => _x( 'Google Pay', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* The sources that do not cause issues about redirecting (on mobile, ...) and sometimes not returning back.
|
||||
*/
|
||||
|
@ -1051,7 +1057,10 @@ return array(
|
|||
'wcgateway.funding-source.renderer' => function ( ContainerInterface $container ) : FundingSourceRenderer {
|
||||
return new FundingSourceRenderer(
|
||||
$container->get( 'wcgateway.settings' ),
|
||||
$container->get( 'wcgateway.all-funding-sources' )
|
||||
array_merge(
|
||||
$container->get( 'wcgateway.all-funding-sources' ),
|
||||
$container->get( 'wcgateway.extra-funding-sources' )
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
|
|
|
@ -391,6 +391,7 @@ class SettingsListener {
|
|||
if ( self::CREDENTIALS_UNCHANGED !== $credentials_change_status ) {
|
||||
$this->settings->set( 'products_dcc_enabled', null );
|
||||
$this->settings->set( 'products_pui_enabled', null );
|
||||
do_action( 'woocommerce_paypal_payments_clear_apm_product_status', $this->settings );
|
||||
}
|
||||
|
||||
if ( in_array(
|
||||
|
|
|
@ -288,6 +288,7 @@ class WCGatewayModule implements ModuleInterface {
|
|||
$settings->set( 'products_dcc_enabled', false );
|
||||
$settings->set( 'products_pui_enabled', false );
|
||||
$settings->persist();
|
||||
do_action( 'woocommerce_paypal_payments_clear_apm_product_status', $settings );
|
||||
|
||||
// Update caches.
|
||||
$dcc_status = $c->get( 'wcgateway.helper.dcc-product-status' );
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"install:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn install",
|
||||
"install:modules:ppcp-blocks": "cd modules/ppcp-blocks && 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-wc-gateway": "cd modules/ppcp-wc-gateway && yarn install",
|
||||
"install:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn install",
|
||||
"install:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn install",
|
||||
|
@ -20,6 +21,7 @@
|
|||
"build:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run build",
|
||||
"build:modules:ppcp-blocks": "cd modules/ppcp-blocks && 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-wc-gateway": "cd modules/ppcp-wc-gateway && 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",
|
||||
|
@ -31,6 +33,7 @@
|
|||
"watch:modules:ppcp-applepay": "cd modules/ppcp-applepay && yarn run watch",
|
||||
"watch:modules:ppcp-blocks": "cd modules/ppcp-blocks && 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-wc-gateway": "cd modules/ppcp-wc-gateway && 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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue