mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-08-31 06:52:50 +08:00
Merge pull request #445 from woocommerce/pcp-370-onboarding
Improve onboarding, allow no card processing
This commit is contained in:
commit
415ffb4268
24 changed files with 864 additions and 699 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -5,7 +5,8 @@ node_modules
|
|||
.phpunit.result.cache
|
||||
yarn-error.log
|
||||
modules/ppcp-button/assets/*
|
||||
modules/ppcp-wc-gateway/assets/*
|
||||
modules/ppcp-wc-gateway/assets/js
|
||||
modules/ppcp-wc-gateway/assets/css
|
||||
*.zip
|
||||
.env
|
||||
auth.json
|
||||
|
|
|
@ -127,7 +127,6 @@ return array(
|
|||
return new PartnerReferrals(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'api.repository.partner-referrals-data' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
@ -209,9 +208,8 @@ return array(
|
|||
},
|
||||
'api.repository.partner-referrals-data' => static function ( ContainerInterface $container ) : PartnerReferralsData {
|
||||
|
||||
$merchant_email = $container->get( 'api.merchant_email' );
|
||||
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
|
||||
return new PartnerReferralsData( $merchant_email, $dcc_applies );
|
||||
return new PartnerReferralsData( $dcc_applies );
|
||||
},
|
||||
'api.repository.cart' => static function ( ContainerInterface $container ): CartRepository {
|
||||
$factory = $container->get( 'api.factory.purchase-unit' );
|
||||
|
|
|
@ -12,7 +12,6 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\PartnerReferralsData;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
|
@ -36,13 +35,6 @@ class PartnerReferrals {
|
|||
*/
|
||||
private $bearer;
|
||||
|
||||
/**
|
||||
* The PartnerReferralsData.
|
||||
*
|
||||
* @var PartnerReferralsData
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
|
@ -53,32 +45,29 @@ class PartnerReferrals {
|
|||
/**
|
||||
* PartnerReferrals constructor.
|
||||
*
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param PartnerReferralsData $data The partner referrals data.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
string $host,
|
||||
Bearer $bearer,
|
||||
PartnerReferralsData $data,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->data = $data;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the signup link.
|
||||
*
|
||||
* @param array $data The partner referrals data.
|
||||
* @return string
|
||||
* @throws RuntimeException If the request fails.
|
||||
*/
|
||||
public function signup_link(): string {
|
||||
$data = $this->data->data();
|
||||
public function signup_link( array $data ): string {
|
||||
$bearer = $this->bearer->bearer();
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
|
|
|
@ -15,14 +15,6 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
|||
* Class PartnerReferralsData
|
||||
*/
|
||||
class PartnerReferralsData {
|
||||
|
||||
/**
|
||||
* The merchant email.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $merchant_email;
|
||||
|
||||
/**
|
||||
* The DCC Applies Helper object.
|
||||
*
|
||||
|
@ -30,19 +22,39 @@ class PartnerReferralsData {
|
|||
*/
|
||||
private $dcc_applies;
|
||||
|
||||
/**
|
||||
* The list of products ('PPCP', 'EXPRESS_CHECKOUT').
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $products;
|
||||
|
||||
/**
|
||||
* PartnerReferralsData constructor.
|
||||
*
|
||||
* @param string $merchant_email The email of the merchant.
|
||||
* @param DccApplies $dcc_applies The DCC Applies helper.
|
||||
*/
|
||||
public function __construct(
|
||||
string $merchant_email,
|
||||
DccApplies $dcc_applies
|
||||
) {
|
||||
$this->dcc_applies = $dcc_applies;
|
||||
$this->products = array(
|
||||
$this->dcc_applies->for_country_currency() ? 'PPCP' : 'EXPRESS_CHECKOUT',
|
||||
);
|
||||
}
|
||||
|
||||
$this->merchant_email = $merchant_email;
|
||||
$this->dcc_applies = $dcc_applies;
|
||||
/**
|
||||
* Returns a new copy of this object with the given value set.
|
||||
*
|
||||
* @param string[] $products The list of products ('PPCP', 'EXPRESS_CHECKOUT').
|
||||
* @return static
|
||||
*/
|
||||
public function with_products( array $products ): self {
|
||||
$obj = clone $this;
|
||||
|
||||
$obj->products = $products;
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,17 +72,6 @@ class PartnerReferralsData {
|
|||
* @return array
|
||||
*/
|
||||
public function data(): array {
|
||||
$data = $this->default_data();
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function default_data(): array {
|
||||
|
||||
return array(
|
||||
'partner_config_override' => array(
|
||||
'partner_logo_url' => 'https://connect.woocommerce.com/images/woocommerce_logo.png',
|
||||
|
@ -84,9 +85,7 @@ class PartnerReferralsData {
|
|||
),
|
||||
'show_add_credit_card' => true,
|
||||
),
|
||||
'products' => array(
|
||||
$this->dcc_applies->for_country_currency() ? 'PPCP' : 'EXPRESS_CHECKOUT',
|
||||
),
|
||||
'products' => $this->products,
|
||||
'legal_consents' => array(
|
||||
array(
|
||||
'type' => 'SHARE_DATA_CONSENT',
|
||||
|
|
|
@ -52,7 +52,7 @@ return array(
|
|||
*
|
||||
* @var State $state
|
||||
*/
|
||||
if ( $state->current_state() <= State::STATE_PROGRESSIVE ) {
|
||||
if ( $state->current_state() !== State::STATE_ONBOARDED ) {
|
||||
return new DisabledSmartButton();
|
||||
}
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
|
|
|
@ -2,41 +2,28 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
#field-merchant_email_production,
|
||||
#field-ppcp_disconnect_sandbox,
|
||||
#field-ppcp_disconnect_production,
|
||||
#field-merchant_id_production,
|
||||
#field-client_id_production,
|
||||
#field-client_secret_production,
|
||||
#field-merchant_email_sandbox,
|
||||
#field-merchant_id_sandbox,
|
||||
#field-client_id_sandbox,
|
||||
#field-client_secret_sandbox{
|
||||
.ppcp-onboarded .ppcp-onboarding-element:not(.ppcp-always-shown-element) {
|
||||
display: none;
|
||||
}
|
||||
#field-merchant_email_production.show,
|
||||
#field-ppcp_disconnect_sandbox.show,
|
||||
#field-ppcp_disconnect_production.show,
|
||||
#field-merchant_id_production.show,
|
||||
#field-client_id_production.show,
|
||||
#field-client_secret_production.show,
|
||||
#field-merchant_email_sandbox.show,
|
||||
#field-merchant_id_sandbox.show,
|
||||
#field-client_id_sandbox.show,
|
||||
#field-client_secret_sandbox.show {
|
||||
|
||||
.ppcp-onboarding .ppcp-settings-field:not(.ppcp-onboarding-element):not(.ppcp-always-shown-element) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ppcp-settings-field.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ppcp-settings-field.show {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
#field-toggle_manual_input span.hide,
|
||||
#field-toggle_manual_input.show span.show{
|
||||
display: none;
|
||||
}
|
||||
#field-toggle_manual_input.show span.hide {
|
||||
display: unset;
|
||||
label.error {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#field-production_toggle_manual_input button,
|
||||
#field-sandbox_toggle_manual_input button {
|
||||
#field-toggle_manual_input button {
|
||||
color: #0073aa;
|
||||
transition-property: border, background, color;
|
||||
transition-duration: .05s;
|
||||
|
@ -49,39 +36,8 @@
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
#field-sandbox_toggle_manual_input.onboarded,
|
||||
#field-production_toggle_manual_input.onboarded {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
#field-ppcp_disconnect_sandbox.onboarded,
|
||||
#field-ppcp_disconnect_production.onboarded,
|
||||
#field-merchant_email_sandbox.onboarded,
|
||||
#field-merchant_id_sandbox.onboarded,
|
||||
#field-client_id_sandbox.onboarded,
|
||||
#field-client_secret_sandbox.onboarded,
|
||||
#field-merchant_email_production.onboarded,
|
||||
#field-merchant_id_production.onboarded,
|
||||
#field-client_id_production.onboarded,
|
||||
#field-client_secret_production.onboarded {
|
||||
display:table-row;
|
||||
}
|
||||
#field-ppcp_disconnect_sandbox.onboarded.hide,
|
||||
#field-ppcp_disconnect_production.onboarded.hide,
|
||||
#field-merchant_email_sandbox.onboarded.hide,
|
||||
#field-merchant_id_sandbox.onboarded.hide,
|
||||
#field-client_id_sandbox.onboarded.hide,
|
||||
#field-client_secret_sandbox.onboarded.hide,
|
||||
#field-merchant_email_production.onboarded.hide,
|
||||
#field-merchant_id_production.onboarded.hide,
|
||||
#field-client_id_production.onboarded.hide,
|
||||
#field-client_secret_production.onboarded.hide {
|
||||
display:none;
|
||||
}
|
||||
|
||||
/* Probably not the best location for this but will do until there's a general purpose settings CSS file. */
|
||||
.ppcp-settings-field-heading td, .ppcp-settings-field-heading th {
|
||||
.ppcp-settings-field-heading td, .ppcp-settings-field-heading th, .ppcp-settings-no-title-col td {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
|
@ -92,3 +48,40 @@
|
|||
.input-text[pattern]:invalid {
|
||||
border: red solid 2px;
|
||||
}
|
||||
|
||||
ul.ppcp-onboarding-options, ul.ppcp-onboarding-options-sublist {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
ul.ppcp-onboarding-options-sublist {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.ppcp-muted-text {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.ppcp-onboarding-header {
|
||||
display: flex;
|
||||
width: 1000px;
|
||||
}
|
||||
|
||||
.ppcp-onboarding-header-left, .ppcp-onboarding-header-right {
|
||||
flex: 50%;
|
||||
}
|
||||
|
||||
.ppcp-onboarding-header h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.ppcp-onboarding-header-cards img, .ppcp-onboarding-header-paypal-logos img {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.ppcp-onboarding-header-cards img {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.ppcp-onboarding-header-paypal-logos img {
|
||||
height: 45px;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
// Onboarding.
|
||||
const ppcp_onboarding = {
|
||||
BUTTON_SELECTOR: '[data-paypal-onboard-button]',
|
||||
PAYPAL_JS_ID: 'ppcp-onboarding-paypal-js',
|
||||
_timeout: false,
|
||||
|
||||
STATE_START: 'start',
|
||||
STATE_ONBOARDED: 'onboarded',
|
||||
|
||||
init: function() {
|
||||
document.addEventListener('DOMContentLoaded', this.reload);
|
||||
},
|
||||
|
@ -15,7 +17,7 @@ const ppcp_onboarding = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Add event listeners to buttons.
|
||||
// Add event listeners to buttons preventing link clicking if PayPal init failed.
|
||||
buttons.forEach(
|
||||
(element) => {
|
||||
if (element.hasAttribute('data-ppcp-button-initialized')) {
|
||||
|
@ -89,8 +91,6 @@ const ppcp_onboarding = {
|
|||
}
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
||||
function ppcp_onboarding_sandboxCallback(...args) {
|
||||
|
@ -101,150 +101,142 @@ function ppcp_onboarding_productionCallback(...args) {
|
|||
return ppcp_onboarding.loginSeller('production', ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Since the PayPal modal will redirect the user a dirty form
|
||||
* provokes an alert if the user wants to leave the page. Since the user
|
||||
* needs to toggle the sandbox switch, we disable this dirty state with the
|
||||
* following workaround for checkboxes.
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
const checkBoxOnClick = (event) => {
|
||||
const value = event.target.checked;
|
||||
if (event.target.getAttribute('id') === 'ppcp-sandbox_on') {
|
||||
toggleSandboxProduction(! value);
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setTimeout( () => {
|
||||
event.target.checked = value;
|
||||
},1
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggles the credential input fields.
|
||||
*
|
||||
* @param forProduction
|
||||
*/
|
||||
const credentialToggle = (forProduction) => {
|
||||
|
||||
const sandboxClassSelectors = [
|
||||
'#field-ppcp_disconnect_sandbox',
|
||||
'#field-merchant_email_sandbox',
|
||||
'#field-merchant_id_sandbox',
|
||||
'#field-client_id_sandbox',
|
||||
'#field-client_secret_sandbox',
|
||||
];
|
||||
const productionClassSelectors = [
|
||||
'#field-ppcp_disconnect_production',
|
||||
'#field-merchant_email_production',
|
||||
'#field-merchant_id_production',
|
||||
'#field-client_id_production',
|
||||
'#field-client_secret_production',
|
||||
];
|
||||
|
||||
const selectors = forProduction ? productionClassSelectors : sandboxClassSelectors;
|
||||
document.querySelectorAll(selectors.join()).forEach(
|
||||
(element) => {element.classList.toggle('show')}
|
||||
)
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggles the visibility of the sandbox/production input fields.
|
||||
*
|
||||
* @param showProduction
|
||||
*/
|
||||
const toggleSandboxProduction = (showProduction) => {
|
||||
const productionDisplaySelectors = [
|
||||
'#field-credentials_production_heading',
|
||||
'#field-production_toggle_manual_input',
|
||||
'#field-ppcp_onboarding_production',
|
||||
];
|
||||
const productionClassSelectors = [
|
||||
|
||||
'#field-ppcp_disconnect_production',
|
||||
'#field-merchant_email_production',
|
||||
'#field-merchant_id_production',
|
||||
'#field-client_id_production',
|
||||
'#field-client_secret_production',
|
||||
];
|
||||
const sandboxDisplaySelectors = [
|
||||
'#field-credentials_sandbox_heading',
|
||||
'#field-sandbox_toggle_manual_input',
|
||||
'#field-ppcp_onboarding_sandbox',
|
||||
];
|
||||
const sandboxClassSelectors = [
|
||||
'#field-ppcp_disconnect_sandbox',
|
||||
'#field-merchant_email_sandbox',
|
||||
'#field-merchant_id_sandbox',
|
||||
'#field-client_id_sandbox',
|
||||
'#field-client_secret_sandbox',
|
||||
];
|
||||
|
||||
if (showProduction) {
|
||||
document.querySelectorAll(productionDisplaySelectors.join()).forEach(
|
||||
(element) => {element.style.display = ''}
|
||||
);
|
||||
document.querySelectorAll(sandboxDisplaySelectors.join()).forEach(
|
||||
(element) => {element.style.display = 'none'}
|
||||
);
|
||||
document.querySelectorAll(productionClassSelectors.join()).forEach(
|
||||
(element) => {element.classList.remove('hide')}
|
||||
);
|
||||
document.querySelectorAll(sandboxClassSelectors.join()).forEach(
|
||||
(element) => {
|
||||
element.classList.remove('show');
|
||||
element.classList.add('hide');
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
document.querySelectorAll(productionDisplaySelectors.join()).forEach(
|
||||
(element) => {element.style.display = 'none'}
|
||||
);
|
||||
document.querySelectorAll(sandboxDisplaySelectors.join()).forEach(
|
||||
(element) => {element.style.display = ''}
|
||||
);
|
||||
|
||||
document.querySelectorAll(sandboxClassSelectors.join()).forEach(
|
||||
(element) => {element.classList.remove('hide')}
|
||||
);
|
||||
document.querySelectorAll(productionClassSelectors.join()).forEach(
|
||||
(element) => {
|
||||
element.classList.remove('show');
|
||||
element.classList.add('hide');
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
const disconnect = (event) => {
|
||||
event.preventDefault();
|
||||
const fields = event.target.classList.contains('production') ? [
|
||||
'#field-merchant_email_production input',
|
||||
'#field-merchant_id_production input',
|
||||
'#field-client_id_production input',
|
||||
'#field-client_secret_production input',
|
||||
] : [
|
||||
'#field-merchant_email_sandbox input',
|
||||
'#field-merchant_id_sandbox input',
|
||||
'#field-client_id_sandbox input',
|
||||
'#field-client_secret_sandbox input',
|
||||
];
|
||||
|
||||
document.querySelectorAll(fields.join()).forEach(
|
||||
(element) => {
|
||||
element.value = '';
|
||||
}
|
||||
);
|
||||
document.querySelector('.woocommerce-save-button').click();
|
||||
};
|
||||
|
||||
(() => {
|
||||
const sandboxSwitchElement = document.querySelector('#ppcp-sandbox_on');
|
||||
if (sandboxSwitchElement) {
|
||||
toggleSandboxProduction(! sandboxSwitchElement.checked);
|
||||
}
|
||||
const productionCredentialElementsSelectors = [
|
||||
'#field-merchant_email_production',
|
||||
'#field-merchant_id_production',
|
||||
'#field-client_id_production',
|
||||
'#field-client_secret_production',
|
||||
];
|
||||
const sandboxCredentialElementsSelectors = [
|
||||
'#field-merchant_email_sandbox',
|
||||
'#field-merchant_id_sandbox',
|
||||
'#field-client_id_sandbox',
|
||||
'#field-client_secret_sandbox',
|
||||
];
|
||||
|
||||
const updateOptionsState = () => {
|
||||
const cardsChk = document.querySelector('#ppcp-onboarding-accept-cards');
|
||||
if (!cardsChk) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.querySelectorAll('#ppcp-onboarding-dcc-options input').forEach(input => {
|
||||
input.disabled = !cardsChk.checked;
|
||||
});
|
||||
|
||||
const basicRb = document.querySelector('#ppcp-onboarding-dcc-basic');
|
||||
|
||||
const isExpress = !cardsChk.checked || basicRb.checked;
|
||||
|
||||
const expressButtonSelectors = [
|
||||
'#field-ppcp_onboarding_production_express',
|
||||
'#field-ppcp_onboarding_sandbox_express',
|
||||
];
|
||||
const ppcpButtonSelectors = [
|
||||
'#field-ppcp_onboarding_production_ppcp',
|
||||
'#field-ppcp_onboarding_sandbox_ppcp',
|
||||
];
|
||||
|
||||
document.querySelectorAll(expressButtonSelectors.join()).forEach(
|
||||
element => element.style.display = isExpress ? '' : 'none'
|
||||
);
|
||||
document.querySelectorAll(ppcpButtonSelectors.join()).forEach(
|
||||
element => element.style.display = !isExpress ? '' : 'none'
|
||||
);
|
||||
};
|
||||
|
||||
const updateManualInputControls = (shown, isSandbox, isAnyEnvOnboarded) => {
|
||||
const productionElementsSelectors = productionCredentialElementsSelectors;
|
||||
const sandboxElementsSelectors = sandboxCredentialElementsSelectors;
|
||||
const otherElementsSelectors = [
|
||||
'.woocommerce-save-button',
|
||||
];
|
||||
if (!isAnyEnvOnboarded) {
|
||||
otherElementsSelectors.push('#field-sandbox_on');
|
||||
}
|
||||
|
||||
document.querySelectorAll(productionElementsSelectors.join()).forEach(
|
||||
element => {
|
||||
element.classList.remove('hide', 'show');
|
||||
element.classList.add((shown && !isSandbox) ? 'show' : 'hide');
|
||||
}
|
||||
);
|
||||
document.querySelectorAll(sandboxElementsSelectors.join()).forEach(
|
||||
element => {
|
||||
element.classList.remove('hide', 'show');
|
||||
element.classList.add((shown && isSandbox) ? 'show' : 'hide');
|
||||
}
|
||||
);
|
||||
document.querySelectorAll(otherElementsSelectors.join()).forEach(
|
||||
element => element.style.display = shown ? '' : 'none'
|
||||
);
|
||||
};
|
||||
|
||||
const updateEnvironmentControls = (isSandbox) => {
|
||||
const productionElementsSelectors = [
|
||||
'#field-ppcp_disconnect_production',
|
||||
'#field-credentials_production_heading',
|
||||
];
|
||||
const sandboxElementsSelectors = [
|
||||
'#field-ppcp_disconnect_sandbox',
|
||||
'#field-credentials_sandbox_heading',
|
||||
];
|
||||
|
||||
document.querySelectorAll(productionElementsSelectors.join()).forEach(
|
||||
element => element.style.display = !isSandbox ? '' : 'none'
|
||||
);
|
||||
document.querySelectorAll(sandboxElementsSelectors.join()).forEach(
|
||||
element => element.style.display = isSandbox ? '' : 'none'
|
||||
);
|
||||
};
|
||||
|
||||
let isDisconnecting = false;
|
||||
|
||||
const disconnect = (event) => {
|
||||
event.preventDefault();
|
||||
const fields = event.target.classList.contains('production') ? productionCredentialElementsSelectors : sandboxCredentialElementsSelectors;
|
||||
|
||||
document.querySelectorAll(fields.map(f => f + ' input').join()).forEach(
|
||||
(element) => {
|
||||
element.value = '';
|
||||
}
|
||||
);
|
||||
|
||||
isDisconnecting = true;
|
||||
|
||||
document.querySelector('.woocommerce-save-button').click();
|
||||
};
|
||||
|
||||
// Prevent the message about unsaved checkbox/radiobutton when reloading the page.
|
||||
// (WC listens for changes on all inputs and sets dirty flag until form submission)
|
||||
const preventDirtyCheckboxPropagation = event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const value = event.target.checked;
|
||||
setTimeout( () => {
|
||||
event.target.checked = value;
|
||||
}, 1
|
||||
);
|
||||
};
|
||||
|
||||
const sandboxSwitchElement = document.querySelector('#ppcp-sandbox_on');
|
||||
|
||||
const validate = () => {
|
||||
const selectors = sandboxSwitchElement.checked ? sandboxCredentialElementsSelectors : productionCredentialElementsSelectors;
|
||||
const values = selectors.map(s => document.querySelector(s + ' input')).map(el => el.value);
|
||||
|
||||
const errors = [];
|
||||
if (values.some(v => !v)) {
|
||||
errors.push(PayPalCommerceGatewayOnboarding.error_messages.no_credentials);
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
const isAnyEnvOnboarded = PayPalCommerceGatewayOnboarding.sandbox_state === ppcp_onboarding.STATE_ONBOARDED ||
|
||||
PayPalCommerceGatewayOnboarding.production_state === ppcp_onboarding.STATE_ONBOARDED;
|
||||
|
||||
document.querySelectorAll('.ppcp-disconnect').forEach(
|
||||
(button) => {
|
||||
|
@ -255,43 +247,89 @@ const disconnect = (event) => {
|
|||
}
|
||||
);
|
||||
|
||||
// Prevent a possibly dirty form arising from this particular checkbox.
|
||||
if (sandboxSwitchElement) {
|
||||
sandboxSwitchElement.addEventListener(
|
||||
'click',
|
||||
(event) => {
|
||||
const value = event.target.checked;
|
||||
document.querySelectorAll('.ppcp-onboarding-options input').forEach(
|
||||
(element) => {
|
||||
element.addEventListener('click', event => {
|
||||
updateOptionsState();
|
||||
|
||||
toggleSandboxProduction( ! value );
|
||||
preventDirtyCheckboxPropagation(event);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setTimeout( () => {
|
||||
event.target.checked = value;
|
||||
}, 1
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
const isSandboxInBackend = PayPalCommerceGatewayOnboarding.current_env === 'sandbox';
|
||||
if (sandboxSwitchElement.checked !== isSandboxInBackend) {
|
||||
sandboxSwitchElement.checked = isSandboxInBackend;
|
||||
}
|
||||
|
||||
// document.querySelectorAll('#mainform input[type="checkbox"]').forEach(
|
||||
// (checkbox) => {
|
||||
// checkbox.addEventListener('click', checkBoxOnClick);
|
||||
// }
|
||||
// );
|
||||
updateOptionsState();
|
||||
|
||||
document.querySelectorAll('#field-sandbox_toggle_manual_input button, #field-production_toggle_manual_input button').forEach(
|
||||
(button) => {
|
||||
button.addEventListener(
|
||||
'click',
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
const isProduction = event.target.classList.contains('production-toggle');
|
||||
credentialToggle(isProduction);
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
const settingsContainer = document.querySelector('#mainform .form-table');
|
||||
|
||||
const markCurrentOnboardingState = (isOnboarded) => {
|
||||
settingsContainer.classList.remove('ppcp-onboarded', 'ppcp-onboarding');
|
||||
settingsContainer.classList.add(isOnboarded ? 'ppcp-onboarded' : 'ppcp-onboarding');
|
||||
}
|
||||
|
||||
markCurrentOnboardingState(PayPalCommerceGatewayOnboarding.current_state === ppcp_onboarding.STATE_ONBOARDED);
|
||||
|
||||
const manualInputToggleButton = document.querySelector('#field-toggle_manual_input button');
|
||||
let isManualInputShown = PayPalCommerceGatewayOnboarding.current_state === ppcp_onboarding.STATE_ONBOARDED;
|
||||
|
||||
manualInputToggleButton.addEventListener(
|
||||
'click',
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
|
||||
isManualInputShown = !isManualInputShown;
|
||||
|
||||
updateManualInputControls(isManualInputShown, sandboxSwitchElement.checked, isAnyEnvOnboarded);
|
||||
}
|
||||
);
|
||||
|
||||
sandboxSwitchElement.addEventListener(
|
||||
'click',
|
||||
(event) => {
|
||||
const isSandbox = sandboxSwitchElement.checked;
|
||||
|
||||
if (isAnyEnvOnboarded) {
|
||||
const onboardingState = isSandbox ? PayPalCommerceGatewayOnboarding.sandbox_state : PayPalCommerceGatewayOnboarding.production_state;
|
||||
const isOnboarded = onboardingState === ppcp_onboarding.STATE_ONBOARDED;
|
||||
|
||||
markCurrentOnboardingState(isOnboarded);
|
||||
isManualInputShown = isOnboarded;
|
||||
}
|
||||
|
||||
updateManualInputControls(isManualInputShown, isSandbox, isAnyEnvOnboarded);
|
||||
|
||||
updateEnvironmentControls(isSandbox);
|
||||
|
||||
preventDirtyCheckboxPropagation(event);
|
||||
}
|
||||
);
|
||||
|
||||
updateManualInputControls(isManualInputShown, sandboxSwitchElement.checked, isAnyEnvOnboarded);
|
||||
|
||||
updateEnvironmentControls(sandboxSwitchElement.checked);
|
||||
|
||||
document.querySelector('#mainform').addEventListener('submit', e => {
|
||||
if (isDisconnecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
const errors = validate();
|
||||
if (errors.length) {
|
||||
e.preventDefault();
|
||||
|
||||
const errorLabel = document.querySelector('#ppcp-form-errors-label');
|
||||
errorLabel.parentElement.parentElement.classList.remove('hide');
|
||||
|
||||
errorLabel.innerHTML = errors.join('<br/>');
|
||||
|
||||
errorLabel.scrollIntoView();
|
||||
window.scrollBy(0, -120); // WP + WC floating header
|
||||
}
|
||||
});
|
||||
|
||||
// Onboarding buttons.
|
||||
ppcp_onboarding.init();
|
||||
|
|
|
@ -23,7 +23,7 @@ document.addEventListener(
|
|||
}
|
||||
|
||||
group.forEach( (elementToShow) => {
|
||||
document.querySelector(elementToShow).style.display = 'table-row';
|
||||
document.querySelector(elementToShow).style.display = '';
|
||||
})
|
||||
|
||||
if('ppcp-message_enabled' === event.target.getAttribute('id')){
|
||||
|
@ -56,7 +56,7 @@ document.addEventListener(
|
|||
return;
|
||||
}
|
||||
if (value === elementToToggle.value && domElement.style.display !== 'none') {
|
||||
domElement.style.display = 'table-row';
|
||||
domElement.style.display = '';
|
||||
return;
|
||||
}
|
||||
domElement.style.display = 'none';
|
||||
|
@ -69,7 +69,7 @@ document.addEventListener(
|
|||
const value = event.target.value;
|
||||
group.forEach( (elementToToggle) => {
|
||||
if (value === elementToToggle.value) {
|
||||
document.querySelector(elementToToggle.selector).style.display = 'table-row';
|
||||
document.querySelector(elementToToggle.selector).style.display = '';
|
||||
return;
|
||||
}
|
||||
document.querySelector(elementToToggle.selector).style.display = 'none';
|
||||
|
|
|
@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnerReferrals;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\OnboardingRESTController;
|
||||
|
||||
|
@ -117,9 +118,8 @@ return array(
|
|||
);
|
||||
},
|
||||
'onboarding.state' => function( ContainerInterface $container ) : State {
|
||||
$environment = $container->get( 'onboarding.environment' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
return new State( $environment, $settings );
|
||||
return new State( $settings );
|
||||
},
|
||||
'onboarding.environment' => function( ContainerInterface $container ) : Environment {
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
|
@ -132,6 +132,7 @@ return array(
|
|||
return new OnboardingAssets(
|
||||
$container->get( 'onboarding.url' ),
|
||||
$state,
|
||||
$container->get( 'onboarding.environment' ),
|
||||
$login_seller_endpoint
|
||||
);
|
||||
},
|
||||
|
@ -188,7 +189,6 @@ return array(
|
|||
return new PartnerReferrals(
|
||||
CONNECT_WOO_SANDBOX_URL,
|
||||
new ConnectBearer(),
|
||||
$container->get( 'api.repository.partner-referrals-data' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
@ -197,7 +197,6 @@ return array(
|
|||
return new PartnerReferrals(
|
||||
CONNECT_WOO_URL,
|
||||
new ConnectBearer(),
|
||||
$container->get( 'api.repository.partner-referrals-data' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
@ -205,13 +204,18 @@ return array(
|
|||
|
||||
$partner_referrals = $container->get( 'api.endpoint.partner-referrals-production' );
|
||||
$partner_referrals_sandbox = $container->get( 'api.endpoint.partner-referrals-sandbox' );
|
||||
$partner_referrals_data = $container->get( 'api.repository.partner-referrals-data' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
return new OnboardingRenderer(
|
||||
$settings,
|
||||
$partner_referrals,
|
||||
$partner_referrals_sandbox
|
||||
$partner_referrals_sandbox,
|
||||
$partner_referrals_data
|
||||
);
|
||||
},
|
||||
'onboarding.render-options' => static function ( ContainerInterface $container ) : OnboardingOptionsRenderer {
|
||||
return new OnboardingOptionsRenderer();
|
||||
},
|
||||
'onboarding.rest' => static function( $container ) : OnboardingRESTController {
|
||||
return new OnboardingRESTController( $container );
|
||||
},
|
||||
|
|
|
@ -10,6 +10,7 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\Onboarding\Assets;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
|
||||
/**
|
||||
|
@ -31,6 +32,13 @@ class OnboardingAssets {
|
|||
*/
|
||||
private $state;
|
||||
|
||||
/**
|
||||
* The Environment.
|
||||
*
|
||||
* @var Environment
|
||||
*/
|
||||
private $environment;
|
||||
|
||||
/**
|
||||
* The LoginSeller Endpoint.
|
||||
*
|
||||
|
@ -43,16 +51,19 @@ class OnboardingAssets {
|
|||
*
|
||||
* @param string $module_url The URL to the module.
|
||||
* @param State $state The State object.
|
||||
* @param Environment $environment The Environment.
|
||||
* @param LoginSellerEndpoint $login_seller_endpoint The LoginSeller endpoint.
|
||||
*/
|
||||
public function __construct(
|
||||
string $module_url,
|
||||
State $state,
|
||||
Environment $environment,
|
||||
LoginSellerEndpoint $login_seller_endpoint
|
||||
) {
|
||||
|
||||
$this->module_url = untrailingslashit( $module_url );
|
||||
$this->state = $state;
|
||||
$this->environment = $environment;
|
||||
$this->login_seller_endpoint = $login_seller_endpoint;
|
||||
}
|
||||
|
||||
|
@ -103,9 +114,16 @@ class OnboardingAssets {
|
|||
*/
|
||||
public function get_script_data() {
|
||||
return array(
|
||||
'endpoint' => home_url( \WC_AJAX::get_endpoint( LoginSellerEndpoint::ENDPOINT ) ),
|
||||
'nonce' => wp_create_nonce( $this->login_seller_endpoint::nonce() ),
|
||||
'paypal_js_url' => 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js',
|
||||
'endpoint' => home_url( \WC_AJAX::get_endpoint( LoginSellerEndpoint::ENDPOINT ) ),
|
||||
'nonce' => wp_create_nonce( $this->login_seller_endpoint::nonce() ),
|
||||
'paypal_js_url' => 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js',
|
||||
'sandbox_state' => State::get_state_name( $this->state->sandbox_state() ),
|
||||
'production_state' => State::get_state_name( $this->state->production_state() ),
|
||||
'current_state' => State::get_state_name( $this->state->current_state() ),
|
||||
'current_env' => $this->environment->current_environment(),
|
||||
'error_messages' => array(
|
||||
'no_credentials' => __( 'Enter the credentials.', 'woocommerce-paypal-payments' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -65,16 +65,15 @@ class OnboardingModule implements ModuleInterface {
|
|||
if ( 'ppcp_onboarding' !== $config['type'] ) {
|
||||
return $field;
|
||||
}
|
||||
$renderer = $c->get( 'onboarding.render' );
|
||||
$is_production = 'production' === $config['env'];
|
||||
|
||||
/**
|
||||
* The OnboardingRenderer.
|
||||
*
|
||||
* @var OnboardingRenderer $renderer
|
||||
*/
|
||||
$renderer = $c->get( 'onboarding.render' );
|
||||
assert( $renderer instanceof OnboardingRenderer );
|
||||
|
||||
$is_production = 'production' === $config['env'];
|
||||
$products = $config['products'];
|
||||
|
||||
ob_start();
|
||||
$renderer->render( $is_production );
|
||||
$renderer->render( $is_production, $products );
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
return $content;
|
||||
|
|
|
@ -10,7 +10,6 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\Onboarding;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
|
@ -138,13 +137,13 @@ class OnboardingRESTController {
|
|||
return array(
|
||||
'environment' => $environment->current_environment(),
|
||||
'onboarded' => ( $state->current_state() >= State::STATE_ONBOARDED ),
|
||||
'state' => $this->get_onboarding_state_name( $state->current_state() ),
|
||||
'state' => State::get_state_name( $state->current_state() ),
|
||||
'sandbox' => array(
|
||||
'state' => $this->get_onboarding_state_name( $state->sandbox_state() ),
|
||||
'state' => State::get_state_name( $state->sandbox_state() ),
|
||||
'onboarded' => ( $state->sandbox_state() >= State::STATE_ONBOARDED ),
|
||||
),
|
||||
'production' => array(
|
||||
'state' => $this->get_onboarding_state_name( $state->production_state() ),
|
||||
'state' => State::get_state_name( $state->production_state() ),
|
||||
'onboarded' => ( $state->production_state() >= State::STATE_ONBOARDED ),
|
||||
),
|
||||
);
|
||||
|
@ -265,34 +264,6 @@ class OnboardingRESTController {
|
|||
return add_query_arg( $this->return_url_args, $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates an onboarding state to a string.
|
||||
*
|
||||
* @param int $state An onboarding state to translate as returned by {@link State} methods.
|
||||
* @return string A string representing the state: "start", "progressive" or "onboarded".
|
||||
* @see State::current_state(), State::sandbox_state(), State::production_state().
|
||||
*/
|
||||
public function get_onboarding_state_name( $state ) {
|
||||
$name = 'unknown';
|
||||
|
||||
switch ( absint( $state ) ) {
|
||||
case State::STATE_START:
|
||||
$name = 'start';
|
||||
break;
|
||||
case State::STATE_PROGRESSIVE:
|
||||
$name = 'progressive';
|
||||
break;
|
||||
case State::STATE_ONBOARDED:
|
||||
$name = 'onboarded';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a signup link for onboarding for a given environment and optionally adding certain URL arguments
|
||||
* to the URL users are redirected after completing the onboarding flow.
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
/**
|
||||
* Renders the onboarding options.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Onboarding\Render
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Onboarding\Render;
|
||||
|
||||
/**
|
||||
* Class OnboardingRenderer
|
||||
*/
|
||||
class OnboardingOptionsRenderer {
|
||||
/**
|
||||
* Renders the onboarding options.
|
||||
*
|
||||
* @param bool $is_shop_supports_dcc Whether the shop can use DCC (country, currency).
|
||||
*/
|
||||
public function render( bool $is_shop_supports_dcc ): string {
|
||||
return '
|
||||
<ul class="ppcp-onboarding-options">
|
||||
<li>
|
||||
<label><input type="checkbox" disabled checked> ' .
|
||||
__( 'Accept PayPal, Venmo, Pay Later and local payment methods', 'woocommerce-paypal-payments' ) . '
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label><input type="checkbox" id="ppcp-onboarding-accept-cards" checked> ' .
|
||||
__( 'Securely accept all major credit & debit cards on the strength of the PayPal network', 'woocommerce-paypal-payments' ) . '
|
||||
</label>
|
||||
</li>
|
||||
<li>' . $this->render_dcc( $is_shop_supports_dcc ) . '</li>
|
||||
</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the onboarding DCC options.
|
||||
*
|
||||
* @param bool $is_shop_supports_dcc Whether the shop can use DCC (country, currency).
|
||||
*/
|
||||
private function render_dcc( bool $is_shop_supports_dcc ): string {
|
||||
$items = array();
|
||||
|
||||
if ( $is_shop_supports_dcc ) {
|
||||
$items[] = '
|
||||
<li>
|
||||
<label><input type="radio" id="ppcp-onboarding-dcc-acdc" name="ppcp_onboarding_dcc" value="acdc" checked> ' .
|
||||
__( 'Advanced credit and debit card processing', 'woocommerce-paypal-payments' ) . '*<br/> ' .
|
||||
__( '(With advanced fraud protection and fully customizable card fields)', 'woocommerce-paypal-payments' ) . '
|
||||
<span class="ppcp-muted-text">*' . __( 'Additional onboarding steps required', 'woocommerce-paypal-payments' ) . '</span>
|
||||
</label>
|
||||
</li>';
|
||||
}
|
||||
|
||||
$items[] = '
|
||||
<li>
|
||||
<label><input type="radio" id="ppcp-onboarding-dcc-basic" name="ppcp_onboarding_dcc" value="basic" ' . ( ! $is_shop_supports_dcc ? 'checked' : '' ) . '> ' .
|
||||
__( 'Basic credit and debit card processing', 'woocommerce-paypal-payments' ) . '
|
||||
</label>
|
||||
</li>';
|
||||
|
||||
return '<ul id="ppcp-onboarding-dcc-options" class="ppcp-onboarding-options-sublist">' .
|
||||
implode( '', $items ) .
|
||||
'</ul>';
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Onboarding\Render;
|
|||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnerReferrals;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\PartnerReferralsData;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
|
@ -39,31 +40,50 @@ class OnboardingRenderer {
|
|||
*/
|
||||
private $sandbox_partner_referrals;
|
||||
|
||||
/**
|
||||
* The default partner referrals data.
|
||||
*
|
||||
* @var PartnerReferralsData
|
||||
*/
|
||||
private $partner_referrals_data;
|
||||
|
||||
/**
|
||||
* OnboardingRenderer constructor.
|
||||
*
|
||||
* @param Settings $settings The settings.
|
||||
* @param PartnerReferrals $production_partner_referrals The PartnerReferrals for production.
|
||||
* @param PartnerReferrals $sandbox_partner_referrals The PartnerReferrals for sandbox.
|
||||
* @param Settings $settings The settings.
|
||||
* @param PartnerReferrals $production_partner_referrals The PartnerReferrals for production.
|
||||
* @param PartnerReferrals $sandbox_partner_referrals The PartnerReferrals for sandbox.
|
||||
* @param PartnerReferralsData $partner_referrals_data The default partner referrals data.
|
||||
*/
|
||||
public function __construct( Settings $settings, PartnerReferrals $production_partner_referrals, PartnerReferrals $sandbox_partner_referrals ) {
|
||||
public function __construct(
|
||||
Settings $settings,
|
||||
PartnerReferrals $production_partner_referrals,
|
||||
PartnerReferrals $sandbox_partner_referrals,
|
||||
PartnerReferralsData $partner_referrals_data
|
||||
) {
|
||||
$this->settings = $settings;
|
||||
$this->production_partner_referrals = $production_partner_referrals;
|
||||
$this->sandbox_partner_referrals = $sandbox_partner_referrals;
|
||||
$this->partner_referrals_data = $partner_referrals_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action URL for the onboarding button/link.
|
||||
*
|
||||
* @param boolean $is_production Whether the production or sandbox button should be rendered.
|
||||
* @param boolean $is_production Whether the production or sandbox button should be rendered.
|
||||
* @param string[] $products The list of products ('PPCP', 'EXPRESS_CHECKOUT').
|
||||
* @return string URL.
|
||||
*/
|
||||
public function get_signup_link( bool $is_production ) {
|
||||
public function get_signup_link( bool $is_production, array $products ) {
|
||||
$args = array(
|
||||
'displayMode' => 'minibrowser',
|
||||
);
|
||||
|
||||
$url = $is_production ? $this->production_partner_referrals->signup_link() : $this->sandbox_partner_referrals->signup_link();
|
||||
$data = $this->partner_referrals_data
|
||||
->with_products( $products )
|
||||
->data();
|
||||
|
||||
$url = $is_production ? $this->production_partner_referrals->signup_link( $data ) : $this->sandbox_partner_referrals->signup_link( $data );
|
||||
$url = add_query_arg( $args, $url );
|
||||
|
||||
return $url;
|
||||
|
@ -72,14 +92,18 @@ class OnboardingRenderer {
|
|||
/**
|
||||
* Renders the "Connect to PayPal" button.
|
||||
*
|
||||
* @param bool $is_production Whether the production or sandbox button should be rendered.
|
||||
* @param bool $is_production Whether the production or sandbox button should be rendered.
|
||||
* @param string[] $products The list of products ('PPCP', 'EXPRESS_CHECKOUT').
|
||||
*/
|
||||
public function render( bool $is_production ) {
|
||||
public function render( bool $is_production, array $products ) {
|
||||
try {
|
||||
$id = 'connect-to' . ( $is_production ? 'production' : 'sandbox' ) . strtolower( implode( '-', $products ) );
|
||||
|
||||
$this->render_button(
|
||||
$this->get_signup_link( $is_production ),
|
||||
$is_production ? 'connect-to-production' : 'connect-to-sandbox',
|
||||
$is_production ? __( 'Connect to PayPal', 'woocommerce-paypal-payments' ) : __( 'Connect to PayPal Sandbox', 'woocommerce-paypal-payments' ),
|
||||
$this->get_signup_link( $is_production, $products ),
|
||||
$id,
|
||||
$is_production ? __( 'Connect with PayPal', 'woocommerce-paypal-payments' ) : __( 'Test payments with PayPal sandbox', 'woocommerce-paypal-payments' ),
|
||||
$is_production ? 'primary' : 'secondary',
|
||||
$is_production ? 'production' : 'sandbox'
|
||||
);
|
||||
} catch ( RuntimeException $exception ) {
|
||||
|
@ -96,13 +120,14 @@ class OnboardingRenderer {
|
|||
* @param string $url The url of the button.
|
||||
* @param string $id The ID of the button.
|
||||
* @param string $label The button text.
|
||||
* @param string $class The CSS class for button ('primary', 'secondary').
|
||||
* @param string $env The environment ('production' or 'sandbox').
|
||||
*/
|
||||
private function render_button( string $url, string $id, string $label, string $env ) {
|
||||
private function render_button( string $url, string $id, string $label, string $class, string $env ) {
|
||||
?>
|
||||
<a
|
||||
target="_blank"
|
||||
class="button-primary"
|
||||
class="button-<?php echo esc_attr( $class ); ?>"
|
||||
id="<?php echo esc_attr( $id ); ?>"
|
||||
data-paypal-onboard-complete="ppcp_onboarding_<?php echo esc_attr( $env ); ?>Callback"
|
||||
data-paypal-onboard-button="true"
|
||||
|
|
|
@ -16,16 +16,8 @@ use Psr\Container\ContainerInterface;
|
|||
*/
|
||||
class State {
|
||||
|
||||
const STATE_START = 0;
|
||||
const STATE_PROGRESSIVE = 4;
|
||||
const STATE_ONBOARDED = 8;
|
||||
|
||||
/**
|
||||
* The Environment.
|
||||
*
|
||||
* @var Environment
|
||||
*/
|
||||
private $environment;
|
||||
const STATE_START = 0;
|
||||
const STATE_ONBOARDED = 8;
|
||||
|
||||
/**
|
||||
* The Settings.
|
||||
|
@ -37,16 +29,29 @@ class State {
|
|||
/**
|
||||
* State constructor.
|
||||
*
|
||||
* @param Environment $environment The Environment.
|
||||
* @param ContainerInterface $settings The Settings.
|
||||
*/
|
||||
public function __construct(
|
||||
Environment $environment,
|
||||
ContainerInterface $settings
|
||||
) {
|
||||
|
||||
$this->environment = $environment;
|
||||
$this->settings = $settings;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state of the specified environment (or the active environment if null).
|
||||
*
|
||||
* @param string|null $environment 'sandbox', 'production'.
|
||||
* @return int
|
||||
*/
|
||||
public function environment_state( ?string $environment = null ): int {
|
||||
switch ( $environment ) {
|
||||
case Environment::PRODUCTION:
|
||||
return $this->production_state();
|
||||
case Environment::SANDBOX:
|
||||
return $this->sandbox_state();
|
||||
}
|
||||
return $this->current_state();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,9 +62,6 @@ class State {
|
|||
public function current_state(): int {
|
||||
|
||||
return $this->state_by_keys(
|
||||
array(
|
||||
'merchant_email',
|
||||
),
|
||||
array(
|
||||
'merchant_email',
|
||||
'merchant_id',
|
||||
|
@ -77,9 +79,6 @@ class State {
|
|||
public function sandbox_state() : int {
|
||||
|
||||
return $this->state_by_keys(
|
||||
array(
|
||||
'merchant_email_sandbox',
|
||||
),
|
||||
array(
|
||||
'merchant_email_sandbox',
|
||||
'merchant_id_sandbox',
|
||||
|
@ -97,9 +96,6 @@ class State {
|
|||
public function production_state() : int {
|
||||
|
||||
return $this->state_by_keys(
|
||||
array(
|
||||
'merchant_email_production',
|
||||
),
|
||||
array(
|
||||
'merchant_email_production',
|
||||
'merchant_id_production',
|
||||
|
@ -110,36 +106,36 @@ class State {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the state based on progressive and onboarded values being looked up in the settings.
|
||||
* Translates an onboarding state to a string.
|
||||
*
|
||||
* @param int $state An onboarding state to translate.
|
||||
* @return string A string representing the state: "start" or "onboarded".
|
||||
*/
|
||||
public static function get_state_name( int $state ) : string {
|
||||
switch ( $state ) {
|
||||
case self::STATE_START:
|
||||
return 'start';
|
||||
case self::STATE_ONBOARDED:
|
||||
return 'onboarded';
|
||||
default:
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state based on onboarding settings values.
|
||||
*
|
||||
* @param array $progressive_keys The keys which need to be present to be at least in progressive state.
|
||||
* @param array $onboarded_keys The keys which need to be present to be in onboarded state.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function state_by_keys( array $progressive_keys, array $onboarded_keys ) : int {
|
||||
$state = self::STATE_START;
|
||||
$is_progressive = true;
|
||||
foreach ( $progressive_keys as $key ) {
|
||||
if ( ! $this->settings->has( $key ) || ! $this->settings->get( $key ) ) {
|
||||
$is_progressive = false;
|
||||
}
|
||||
}
|
||||
if ( $is_progressive ) {
|
||||
$state = self::STATE_PROGRESSIVE;
|
||||
}
|
||||
|
||||
$is_onboarded = true;
|
||||
private function state_by_keys( array $onboarded_keys ) : int {
|
||||
foreach ( $onboarded_keys as $key ) {
|
||||
if ( ! $this->settings->has( $key ) || ! $this->settings->get( $key ) ) {
|
||||
$is_onboarded = false;
|
||||
return self::STATE_START;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $is_onboarded ) {
|
||||
$state = self::STATE_ONBOARDED;
|
||||
}
|
||||
|
||||
return $state;
|
||||
return self::STATE_ONBOARDED;
|
||||
}
|
||||
}
|
||||
|
|
BIN
modules/ppcp-wc-gateway/assets/images/paylater-button.png
Normal file
BIN
modules/ppcp-wc-gateway/assets/images/paylater-button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
modules/ppcp-wc-gateway/assets/images/paypal-button.png
Normal file
BIN
modules/ppcp-wc-gateway/assets/images/paypal-button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
modules/ppcp-wc-gateway/assets/images/paypal.png
Normal file
BIN
modules/ppcp-wc-gateway/assets/images/paypal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
BIN
modules/ppcp-wc-gateway/assets/images/venmo-button.png
Normal file
BIN
modules/ppcp-wc-gateway/assets/images/venmo-button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
File diff suppressed because it is too large
Load diff
|
@ -71,6 +71,6 @@ class ConnectAdminNotice {
|
|||
* @return bool
|
||||
*/
|
||||
protected function should_display(): bool {
|
||||
return $this->state->current_state() < State::STATE_PROGRESSIVE;
|
||||
return $this->state->current_state() !== State::STATE_ONBOARDED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -377,8 +377,18 @@ $data_rows_html
|
|||
?>
|
||||
<input type="hidden" name="ppcp-nonce" value="<?php echo esc_attr( $nonce ); ?>">
|
||||
<?php
|
||||
|
||||
// Create a hidden first row with 2 cells to avoid issues with table-layout: fixed
|
||||
// when the first visible row needs to have one cell.
|
||||
?>
|
||||
<tr style="height: 1px; padding-top: 0; padding-bottom: 0;">
|
||||
<th style="padding-top: 0; padding-bottom: 0;"></th>
|
||||
<td style="padding-top: 0; padding-bottom: 0;"></td>
|
||||
</tr>
|
||||
<?php
|
||||
|
||||
foreach ( $this->fields as $field => $config ) :
|
||||
if ( ! in_array( $this->state->current_state(), $config['screens'], true ) ) {
|
||||
if ( ! in_array( $this->state->environment_state( $config['state_from'] ?? null ), $config['screens'], true ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( ! $this->field_matches_page( $config, $this->page_id ) ) {
|
||||
|
@ -406,14 +416,18 @@ $data_rows_html
|
|||
$key = 'ppcp[' . $field . ']';
|
||||
$id = 'ppcp-' . $field;
|
||||
$config['id'] = $id;
|
||||
$colspan = 'ppcp-heading' !== $config['type'] ? 1 : 2;
|
||||
$colspan = ( 'ppcp-heading' !== $config['type'] && isset( $config['title'] ) ) ? 1 : 2;
|
||||
$classes = isset( $config['classes'] ) ? $config['classes'] : array();
|
||||
$classes[] = 'ppcp-settings-field';
|
||||
$classes[] = sprintf( 'ppcp-settings-field-%s', str_replace( 'ppcp-', '', $config['type'] ) );
|
||||
$description = isset( $config['description'] ) ? $config['description'] : '';
|
||||
if ( 1 !== $colspan ) {
|
||||
$classes[] = 'ppcp-settings-no-title-col';
|
||||
}
|
||||
$description = isset( $config['description'] ) ? $config['description'] : '';
|
||||
unset( $config['description'] );
|
||||
?>
|
||||
<tr valign="top" id="<?php echo esc_attr( 'field-' . $field ); ?>" class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
|
||||
<?php if ( 'ppcp-heading' !== $config['type'] ) : ?>
|
||||
<?php if ( 'ppcp-heading' !== $config['type'] && isset( $config['title'] ) ) : ?>
|
||||
<th scope="row">
|
||||
<label
|
||||
for="<?php echo esc_attr( $id ); ?>"
|
||||
|
@ -462,7 +476,14 @@ $data_rows_html
|
|||
* @param array $config The configuration array.
|
||||
*/
|
||||
private function render_text( array $config ) {
|
||||
echo wp_kses_post( $config['text'] );
|
||||
$raw = $config['raw'] ?? false;
|
||||
if ( $raw ) {
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo $config['text'];
|
||||
} else {
|
||||
echo wp_kses_post( $config['text'] );
|
||||
}
|
||||
|
||||
if ( isset( $config['hidden'] ) ) {
|
||||
$value = $this->settings->has( $config['hidden'] ) ?
|
||||
(string) $this->settings->get( $config['hidden'] )
|
||||
|
|
|
@ -19,7 +19,6 @@ return array(
|
|||
'title' => __( 'Subscribed webhooks', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-table',
|
||||
'screens' => array(
|
||||
State::STATE_PROGRESSIVE,
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array(),
|
||||
|
@ -34,7 +33,6 @@ return array(
|
|||
'type' => 'ppcp-text',
|
||||
'text' => '<button type="button" class="button ppcp-webhooks-resubscribe">' . esc_html__( 'Resubscribe', 'woocommerce-paypal-payments' ) . '</button>',
|
||||
'screens' => array(
|
||||
State::STATE_PROGRESSIVE,
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array(),
|
||||
|
@ -53,7 +51,6 @@ return array(
|
|||
'type' => 'ppcp-text',
|
||||
'text' => '<button type="button" class="button ppcp-webhooks-simulate">' . esc_html__( 'Simulate', 'woocommerce-paypal-payments' ) . '</button>',
|
||||
'screens' => array(
|
||||
State::STATE_PROGRESSIVE,
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array(),
|
||||
|
|
|
@ -270,7 +270,6 @@ class WcGatewayTest extends TestCase
|
|||
{
|
||||
return [
|
||||
[State::STATE_START, true],
|
||||
[State::STATE_PROGRESSIVE, true],
|
||||
[State::STATE_ONBOARDED, false]
|
||||
];
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue