onboarding init

This commit is contained in:
David Remer 2020-06-15 11:48:37 +03:00
parent 772c1f52d7
commit 98d201968e
35 changed files with 7521 additions and 268 deletions

View file

@ -18,16 +18,13 @@
}, },
{ {
"type": "path", "type": "path",
"url": "modules.local/ppcp-button" "url": "modules.local/ppcp-onboarding"
},
{
"type": "path",
"url": "modules.local/ppcp-wc-gateway"
} }
], ],
"require": { "require": {
"dhii/module-interface": "0.2.x-dev", "dhii/module-interface": "0.2.x-dev",
"psr/container": "^1.0", "psr/container": "^1.0",
"inpsyde/ppcp-onboarding": "dev-master",
"inpsyde/ppcp-button": "dev-master", "inpsyde/ppcp-button": "dev-master",
"inpsyde/ppcp-wc-gateway": "dev-master", "inpsyde/ppcp-wc-gateway": "dev-master",
"oomphinc/composer-installers-extender": "^1.1", "oomphinc/composer-installers-extender": "^1.1",
@ -42,7 +39,9 @@
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Inpsyde\\PayPalCommerce\\": "src/" "Inpsyde\\PayPalCommerce\\": "src/",
"Inpsyde\\PayPalCommerce\\Button\\": "modules.local/ppcp-button/src/",
"Inpsyde\\PayPalCommerce\\WcGateway\\": "modules.local/ppcp-wc-gateway/src/"
} }
}, },
"autoload-dev": { "autoload-dev": {

View file

@ -13,12 +13,20 @@ use Inpsyde\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
use Inpsyde\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint; use Inpsyde\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
use Inpsyde\PayPalCommerce\Button\Endpoint\RequestData; use Inpsyde\PayPalCommerce\Button\Endpoint\RequestData;
use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException; use Inpsyde\PayPalCommerce\Button\Exception\RuntimeException;
use Inpsyde\PayPalCommerce\Onboarding\State;
return [ return [
'button.smart-button' => static function (ContainerInterface $container): SmartButtonInterface { 'button.smart-button' => static function (ContainerInterface $container): SmartButtonInterface {
$state = $container->get('onboarding.state');
/**
* @var State $state
*/
if ($state->currentState() < State::STATE_PROGRESSIVE) {
return new DisabledSmartButton();
}
$settings = $container->get('wcgateway.settings'); $settings = $container->get('wcgateway.settings');
if (! wc_string_to_bool($settings->get('enabled'))) { if (!$settings->has('enabled') || ! wc_string_to_bool($settings->get('enabled'))) {
return new DisabledSmartButton(); return new DisabledSmartButton();
} }
$payeeRepository = $container->get('api.repository.payee'); $payeeRepository = $container->get('api.repository.payee');

View file

@ -68,35 +68,54 @@ class SmartButton implements SmartButtonInterface
esc_html__('Pay with Card', 'woocommerce-paypal-commerce-gateway') esc_html__('Pay with Card', 'woocommerce-paypal-commerce-gateway')
); );
}; };
if (is_cart() && wc_string_to_bool($this->settings->get('button_cart_enabled'))) { if (
is_cart()
&& $this->settings->has('button_cart_enabled')
&& wc_string_to_bool($this->settings->get('button_cart_enabled'))
) {
add_action( add_action(
'woocommerce_proceed_to_checkout', 'woocommerce_proceed_to_checkout',
$buttonRenderer, $buttonRenderer,
20 20
); );
} }
if (is_cart() && wc_string_to_bool($this->settings->get('dcc_cart_enabled'))) { if (
is_cart()
&& $this->settings->has('dcc_cart_enabled')
&& wc_string_to_bool($this->settings->get('dcc_cart_enabled'))
) {
add_action( add_action(
'woocommerce_proceed_to_checkout', 'woocommerce_proceed_to_checkout',
$dccRenderer, $dccRenderer,
20 20
); );
} }
if (is_product() && wc_string_to_bool($this->settings->get('button_single_product_enabled'))) { if (
is_product()
&& $this->settings->has('button_single_product_enabled')
&& wc_string_to_bool($this->settings->get('button_single_product_enabled'))
) {
add_action( add_action(
'woocommerce_single_product_summary', 'woocommerce_single_product_summary',
$buttonRenderer, $buttonRenderer,
31 31
); );
} }
if (is_product() && wc_string_to_bool($this->settings->get('dcc_single_product_enabled'))) { if (
is_product()
&& $this->settings->has('dcc_single_product_enabled')
&& wc_string_to_bool($this->settings->get('dcc_single_product_enabled'))
) {
add_action( add_action(
'woocommerce_single_product_summary', 'woocommerce_single_product_summary',
$dccRenderer, $dccRenderer,
31 31
); );
} }
if (wc_string_to_bool($this->settings->get('button_mini_cart_enabled'))) { if (
$this->settings->has('button_mini_cart_enabled')
&& wc_string_to_bool($this->settings->get('button_mini_cart_enabled'))
) {
add_action( add_action(
'woocommerce_widget_shopping_cart_after_buttons', 'woocommerce_widget_shopping_cart_after_buttons',
static function () { static function () {
@ -105,7 +124,10 @@ class SmartButton implements SmartButtonInterface
30 30
); );
} }
if (wc_string_to_bool($this->settings->get('dcc_mini_cart_enabled'))) { if (
$this->settings->has('dcc_mini_cart_enabled')
&& wc_string_to_bool($this->settings->get('dcc_mini_cart_enabled'))
) {
add_action( add_action(
'woocommerce_widget_shopping_cart_after_buttons', 'woocommerce_widget_shopping_cart_after_buttons',
static function () use ($dccRenderer) { static function () use ($dccRenderer) {
@ -119,7 +141,11 @@ class SmartButton implements SmartButtonInterface
$buttonRenderer, $buttonRenderer,
10 10
); );
if (wc_string_to_bool($this->settings->get('dcc_checkout_enabled'))) { if (
$this->settings->has('dcc_checkout_enabled')
&& wc_string_to_bool($this->settings->get('dcc_checkout_enabled'))
) {
add_action( add_action(
'woocommerce_review_order_after_submit', 'woocommerce_review_order_after_submit',
$dccRenderer, $dccRenderer,
@ -132,7 +158,7 @@ class SmartButton implements SmartButtonInterface
public function enqueue(): bool public function enqueue(): bool
{ {
wp_enqueue_script( wp_enqueue_script(
'paypal-smart-button', 'ppcp-smart-button',
$this->moduleUrl . '/assets/js/button.js', $this->moduleUrl . '/assets/js/button.js',
['jquery'], ['jquery'],
1, 1,
@ -140,7 +166,7 @@ class SmartButton implements SmartButtonInterface
); );
wp_localize_script( wp_localize_script(
'paypal-smart-button', 'ppcp-smart-button',
'PayPalCommerceGateway', 'PayPalCommerceGateway',
$this->localizeScript() $this->localizeScript()
); );
@ -149,6 +175,7 @@ class SmartButton implements SmartButtonInterface
private function localizeScript(): array private function localizeScript(): array
{ {
the_post_thumbnail();
$localize = [ $localize = [
'script_attributes' => $this->attributes(), 'script_attributes' => $this->attributes(),
'redirect' => wc_get_checkout_url(), 'redirect' => wc_get_checkout_url(),
@ -175,8 +202,8 @@ class SmartButton implements SmartButtonInterface
'url' => $this->url(), 'url' => $this->url(),
'style' => [ 'style' => [
'layout' => 'vertical', 'layout' => 'vertical',
'color' => $this->settings->get('button_color'), 'color' => ($this->settings->has('button_color')) ? $this->settings->get('button_color') : null,
'shape' => $this->settings->get('button_shape'), 'shape' => ($this->settings->has('button_shape')) ? $this->settings->get('button_shape') : null,
'label' => 'paypal', 'label' => 'paypal',
], ],
], ],
@ -217,7 +244,7 @@ class SmartButton implements SmartButtonInterface
//ToDo: Probably only needed, when DCC //ToDo: Probably only needed, when DCC
'vault' => $this->dccIsEnabled() ? 'false' : 'false', 'vault' => $this->dccIsEnabled() ? 'false' : 'false',
'commit' => is_checkout() ? 'true' : 'false', 'commit' => is_checkout() ? 'true' : 'false',
'intent' => $this->settings->get('intent'), 'intent' => ($this->settings->has('intent')) ? $this->settings->get('intent') : 'commit',
]; ];
if (defined('WP_DEBUG') && \WP_DEBUG && WC()->customer) { if (defined('WP_DEBUG') && \WP_DEBUG && WC()->customer) {
$params['buyer-country'] = WC()->customer->get_billing_country(); $params['buyer-country'] = WC()->customer->get_billing_country();
@ -226,7 +253,7 @@ class SmartButton implements SmartButtonInterface
if ($payee->merchantId()) { if ($payee->merchantId()) {
$params['merchant-id'] = $payee->merchantId(); $params['merchant-id'] = $payee->merchantId();
} }
$disableFunding = $this->settings->get('disable_funding'); $disableFunding = $this->settings->has('disable_funding') ? $this->settings->get('disable_funding') : [];
if (is_array($disableFunding) && count($disableFunding)) { if (is_array($disableFunding) && count($disableFunding)) {
$params['disable-funding'] = implode(',', $disableFunding); $params['disable-funding'] = implode(',', $disableFunding);
} }
@ -273,10 +300,17 @@ class SmartButton implements SmartButtonInterface
private function dccIsEnabled() : bool private function dccIsEnabled() : bool
{ {
return $keys = [
wc_string_to_bool($this->settings->get('dcc_cart_enabled')) 'dcc_cart_enabled',
|| wc_string_to_bool($this->settings->get('dcc_mini_cart_enabled')) 'dcc_mini_cart_enabled',
|| wc_string_to_bool($this->settings->get('dcc_checkout_enabled')) 'dcc_checkout_enabled',
|| wc_string_to_bool($this->settings->get('dcc_single_product_enabled')); 'dcc_single_product_enabled',
];
foreach ($keys as $key) {
if ($this->settings->has($key) && wc_string_to_bool($this->settings->get($key))) {
return true;
}
}
return false;
} }
} }

View file

@ -0,0 +1,5 @@
{
"plugins": [
"babel-plugin-transform-object-rest-spread"
]
}

View file

@ -0,0 +1 @@
/node_modules/

View file

@ -0,0 +1,2 @@
!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t){alert("hello")}]);
//# sourceMappingURL=button.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./resources/js/onboarding.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","alert"],"mappings":"aACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QAKfF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,GAIjBlC,EAAoBA,EAAoBmC,EAAI,G,gBClFrDC,MAAM","file":"js/button.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","alert('hello');"],"sourceRoot":""}

View file

@ -0,0 +1,50 @@
const onboardingCallback = (authCode, sharedId) => {
console.log(authCode);
console.log(sharedId);
fetch(PayPalCommerceGatewayOnboarding.endpoint, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
authCode: authCode,
sharedId: sharedId,
nonce: PayPalCommerceGatewayOnboarding.nonce
})
});
}
/*
const bootstrap = () => {
if (!typeof (PayPalCommerceGatewayOnboarding)) {
console.error('PayPal onboarding could not be configured.');
return;
}
const link = document.createElement('a');
link.innerText = PayPalCommerceGatewayOnboarding.link.text;
Object.entries(PayPalCommerceGatewayOnboarding.link.attributes).forEach(
(keyValue) => {
link.setAttribute(keyValue[0], keyValue[1]);
}
);
link.setAttribute('data-paypal-onboard-complete', 'onboardingCallback');
const table = document.querySelector('.form-table');
const wrapper = table.parentNode;
//wrapper.insertBefore(link, table);
const script = document.createElement('script');
Object.entries(PayPalCommerceGatewayOnboarding.script.attributes).forEach(
(keyValue) => {
script.setAttribute(keyValue[0], keyValue[1]);
}
);
wrapper.insertBefore(script, table);
};
bootstrap();
*/

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,27 @@
{
"name": "inpsyde/ppcp-onboarding",
"type": "inpsyde-module",
"require": {
"dhii/module-interface": "0.2.x-dev"
},
"autoload": {
"psr-4": {
"Inpsyde\\PayPalCommerce\\Onboarding\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Inpsyde\\PayPalCommerce\\Onboarding\\": "tests/PHPUnit"
}
},
"scripts": {
"unit": "./vendor/bin/phpunit --coverage-html build/coverage-report"
},
"require-dev": {
"phpunit/phpunit": "^9.1",
"brain/monkey": "^2.4",
"inpsyde/php-coding-standards": "^1"
},
"minimum-stability": "dev",
"prefer-stable": true
}

View file

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Onboarding;
return [
];

View file

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Onboarding;
use Dhii\Modular\Module\ModuleInterface;
return static function (): ModuleInterface {
return new OnboardingModule();
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,23 @@
{
"name": "ppc-button",
"version": "1.0.0",
"license": "GPL-3.0-or-later",
"main": "resources/js/button.js",
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"babel-loader": "^8.1.0",
"cross-env": "^5.0.1",
"file-loader": "^4.2.0",
"node-sass": "^4.13.0",
"sass-loader": "^8.0.0",
"webpack": "^4.42.1",
"webpack-cli": "^3.1.2",
"babel-plugin-transform-object-rest-spread": "^6.26.0"
},
"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"
}
}

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
bootstrap="vendor/autoload.php"
backupGlobals="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./src</directory>
</whitelist>
</filter>
<testsuites>
<testsuite name="unit">
<directory suffix="Test.php">./tests/PHPUnit</directory>
</testsuite>
</testsuites>
</phpunit>

View file

@ -0,0 +1,53 @@
const bootstrap = () => {
if (!typeof (PayPalCommerceGatewayOnboarding)) {
console.error('PayPal onboarding could not be configured.');
return;
}
const link = document.createElement('a');
link.innerText = PayPalCommerceGatewayOnboarding.link.text;
Object.entries(PayPalCommerceGatewayOnboarding.link.attributes).forEach(
(keyValue) => {
link.setAttribute(keyValue[0], keyValue[1]);
}
);
const onboardingCallback = (authCode, sharedId) => {
console.log(authCode);
console.log(sharedId);
fetch(PayPalCommerceGatewayOnboarding.endpoint, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
authCode: authCode,
sharedId: sharedId,
nonce: PayPalCommerceGatewayOnboarding.nonce
})
}).then(function(res) {
if (!response.ok) {
alert("Something went wrong!");
}
});
}
link.setAttribute('data-paypal-onboard-complete', onboardingCallback);
const table = document.querySelector('.form-table');
const wrapper = table.parentNode;
wrapper.insertBefore(link, table);
const script = document.createElement('script');
Object.entries(PayPalCommerceGatewayOnboarding.script.attributes).forEach(
(keyValue) => {
script.setAttribute(keyValue[0], keyValue[1]);
}
);
document.body.append(script);
};
bootstrap();

View file

@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Onboarding;
use Dhii\Data\Container\ContainerInterface;
use Inpsyde\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
use Inpsyde\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
use Inpsyde\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
use Inpsyde\PayPalCommerce\WcGateway\Admin\OrderDetail;
use Inpsyde\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn;
use Inpsyde\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail;
use Inpsyde\PayPalCommerce\WcGateway\Checkout\DisableGateways;
use Inpsyde\PayPalCommerce\WcGateway\Gateway\WcGateway;
use Inpsyde\PayPalCommerce\WcGateway\Gateway\WcGatewayBase;
use Inpsyde\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
use Inpsyde\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice;
use Inpsyde\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use Inpsyde\PayPalCommerce\WcGateway\Processor\OrderProcessor;
use Inpsyde\PayPalCommerce\WcGateway\Settings\Settings;
use Inpsyde\PayPalCommerce\WcGateway\Settings\SettingsFields;
return [
'onboarding.state' => function(ContainerInterface $container) : State {
$environment = $container->get('onboarding.environment');
$settings = $container->get('wcgateway.settings');
return new State($environment, $settings);
},
'onboarding.environment' => function(ContainerInterface $container) : Environment {
return new Environment();
},
'onboarding.assets' => function(ContainerInterface $container) : OnboardingAssets {
$state = $container->get('onboarding.state');
$loginSellerEndpoint = $container->get('onboarding.endpoint.login-seller');
return new OnboardingAssets(
$container->get('onboarding.url'),
$state,
$loginSellerEndpoint
);
},
'onboarding.url' => static function (ContainerInterface $container): string {
return plugins_url(
'/modules/ppcp-onboarding/',
dirname(__FILE__, 3) . '/woocommerce-paypal-commerce-gateway.php'
);
},
'onboarding.endpoint.login-seller' => static function (ContainerInterface $container) : LoginSellerEndpoint {
$requestData = $container->get('button.request-data');
$loginSellerEndpoint = $container->get('api.endpoint.login-seller');
$partnerReferralsData = $container->get('api.repository.partner-referrals-data');
$gateway = $container->get('wcgateway.gateway.base');
return new LoginSellerEndpoint(
$requestData,
$loginSellerEndpoint,
$partnerReferralsData,
$gateway
);
},
'onboarding.render' => static function (ContainerInterface $container) : OnboardingRenderer {
$partnerReferrals = $container->get('api.endpoint.partner-referrals');
return new OnboardingRenderer(
$partnerReferrals,
);
},
];

View file

@ -0,0 +1,73 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Onboarding\Assets;
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\PartnerReferrals;
use Inpsyde\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
use Inpsyde\PayPalCommerce\Onboarding\State;
class OnboardingAssets
{
private $moduleUrl;
private $state;
private $loginSellerEndpoint;
public function __construct(
string $moduleUrl,
State $state,
LoginSellerEndpoint $loginSellerEndpoint
) {
$this->moduleUrl = $moduleUrl;
$this->state = $state;
$this->loginSellerEndpoint = $loginSellerEndpoint;
}
public function register() : bool
{
if (!$this->shouldRender()) {
return false;
}
$url = $this->moduleUrl . '/assets/js/onboarding.js';
wp_register_script(
'ppcp-onboarding',
$url,
['jquery'],
1,
true
);
wp_localize_script(
'ppcp-onboarding',
'PayPalCommerceGatewayOnboarding',
[
'endpoint' => home_url(\WC_AJAX::get_endpoint(LoginSellerEndpoint::ENDPOINT)),
'nonce' => wp_create_nonce($this->loginSellerEndpoint::nonce()),
]
);
return true;
}
public function enqueue() : bool {
if (! $this->shouldRender()) {
return false;
}
wp_enqueue_script('ppcp-onboarding');
return true;
}
private function shouldRender() : bool {
global $current_section;
if ($current_section !== 'ppcp-gateway') {
return false;
}
$shouldRender = $this->state->currentState() === State::STATE_PROGRESSIVE;
return $shouldRender;
}
}

View file

@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Onboarding\Endpoint;
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\LoginSeller;
use Inpsyde\PayPalCommerce\ApiClient\Repository\PartnerReferralsData;
use Inpsyde\PayPalCommerce\Button\Endpoint\EndpointInterface;
use Inpsyde\PayPalCommerce\Button\Endpoint\RequestData;
use Inpsyde\PayPalCommerce\WcGateway\Gateway\WcGatewayInterface;
class LoginSellerEndpoint implements EndpointInterface
{
public const ENDPOINT = 'ppc-login-seller';
private $requestData;
private $loginSellerEndpoint;
private $partnerReferralsData;
private $gateway;
public function __construct(
RequestData $requestData,
LoginSeller $loginSellerEndpoint,
PartnerReferralsData $partnerReferralsData,
\WC_Payment_Gateway $gateway
) {
$this->requestData = $requestData;
$this->loginSellerEndpoint = $loginSellerEndpoint;
$this->partnerReferralsData = $partnerReferralsData;
$this->gateway = $gateway;
}
public static function nonce(): string
{
return self::ENDPOINT;
}
public function handleRequest(): bool
{
try {
$data = $this->requestData->readRequest($this->nonce());
$credentials = $this->loginSellerEndpoint->credentialsFor(
$data['sharedId'],
$data['authCode'],
$this->partnerReferralsData->nonce()
);
$this->gateway->update_option('client_secret', $credentials->client_secret);
$this->gateway->update_option('client_id', $credentials->client_id);
wp_send_json_success();
return true;
} catch (\RuntimeException $error) {
wp_send_json_error($error->getMessage());
return false;
}
}
}

View file

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Onboarding;
class Environment
{
public const PRODUCTION = 'production';
public const SANDBOX = 'sandbox';
public const VALID_ENVIRONMENTS = [
self::PRODUCTION,
self::SANDBOX,
];
public const OPTION_KEY = 'ppcp-env';
public function currentEnvironment() : string
{
return (string) get_option(self::OPTION_KEY, self::PRODUCTION);
}
public function currentEnvironmentIs(string $environment) : bool {
return $this->currentEnvironment() === $environment;
}
public function changeEnvironmentTo(string $environment) : bool
{
if (! in_array($environment, self::VALID_ENVIRONMENTS, true)) {
return false;
}
update_option(self::OPTION_KEY, $environment);
return true;
}
}

View file

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Onboarding;
use Dhii\Container\ServiceProvider;
use Dhii\Modular\Module\ModuleInterface;
use Inpsyde\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
use Inpsyde\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
use Interop\Container\ServiceProviderInterface;
use Psr\Container\ContainerInterface;
class OnboardingModule implements ModuleInterface
{
public function setup(): ServiceProviderInterface
{
return new ServiceProvider(
require __DIR__ . '/../services.php',
require __DIR__ . '/../extensions.php'
);
}
public function run(ContainerInterface $container)
{
$assetLoader = $container->get('onboarding.assets');
/**
* @var OnboardingAssets $assetLoader
*/
add_action(
'admin_enqueue_scripts',
[
$assetLoader,
'register',
]
);
add_action(
'woocommerce_settings_checkout',
[
$assetLoader,
'enqueue',
]
);
add_action(
'wc_ajax_' . LoginSellerEndpoint::ENDPOINT,
static function () use ($container) {
$endpoint = $container->get('onboarding.endpoint.login-seller');
/**
* @var ChangeCartEndpoint $endpoint
*/
$endpoint->handleRequest();
}
);
}
}

View file

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Onboarding\Render;
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\PartnerReferrals;
class OnboardingRenderer
{
private $partnerReferrals;
public function __construct(PartnerReferrals $partnerReferrals)
{
$this->partnerReferrals = $partnerReferrals;
}
public function render() {
$url = add_query_arg(
[
'displayMode'=>'minibrowser',
],
$this->partnerReferrals->getSignupLink()
);
?>
<script>
function onboardedCallback(authCode, sharedId) {
onboardingCallback(authCode, sharedId);
}
</script>
<a target="_blank" data-paypal-onboard-complete="onboardedCallback" href="<?php echo $url; ?>" data-paypal-button="true">Sign up for PayPal</a>
<script id="paypal-js" src="https://www.sandbox.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js"></script>
<?php
}
}

View file

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\Onboarding;
use Psr\Container\ContainerInterface;
class State
{
const STATE_START = 0;
const STATE_PROGRESSIVE = 4;
const STATE_ONBOARDED = 8;
private $environment;
private $settings;
public function __construct(
Environment $environment,
ContainerInterface $settings
) {
$this->environment = $environment;
$this->settings = $settings;
}
public function currentState() : int {
$value = self::STATE_START;
/**
* Having provided the merchant email means, we are at least
* in the progressive phase of our onboarding.
**/
if ($this->settings->has('merchant_email') && is_email($this->settings->get('merchant_email'))) {
$value = self::STATE_PROGRESSIVE;
}
/**
* Once we can fetch credentials we are completely onboarded.
*/
if ($this->settings->has('client_id')) {
$value = self::STATE_ONBOARDED;
}
return $value;
}
}

View file

@ -0,0 +1,35 @@
const path = require('path');
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
devtool: 'sourcemap',
mode: isProduction ? 'production' : 'development',
target: 'web',
entry: {
onboarding: path.resolve('./resources/js/onboarding.js'),
},
output: {
path: path.resolve(__dirname, 'assets/'),
filename: 'js/[name].js',
},
module: {
rules: [{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{
loader: 'file-loader',
options: {
name: 'css/[name].css',
}
},
{loader:'sass-loader'}
]
}]
}
};

View file

@ -5,5 +5,5 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\WcGateway; namespace Inpsyde\PayPalCommerce\WcGateway;
return [ return [
]; ];

View file

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\WcGateway; namespace Inpsyde\PayPalCommerce\WcGateway;
use Dhii\Data\Container\ContainerInterface; use Dhii\Data\Container\ContainerInterface;
use Inpsyde\PayPalCommerce\WcGateway\Admin\OrderDetail; use Inpsyde\PayPalCommerce\Onboarding\State;
use Inpsyde\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn; use Inpsyde\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn;
use Inpsyde\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail; use Inpsyde\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail;
use Inpsyde\PayPalCommerce\WcGateway\Checkout\DisableGateways; use Inpsyde\PayPalCommerce\WcGateway\Checkout\DisableGateways;
@ -15,8 +15,11 @@ use Inpsyde\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
use Inpsyde\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice; use Inpsyde\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice;
use Inpsyde\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; use Inpsyde\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use Inpsyde\PayPalCommerce\WcGateway\Processor\OrderProcessor; use Inpsyde\PayPalCommerce\WcGateway\Processor\OrderProcessor;
use Inpsyde\PayPalCommerce\WcGateway\Settings\FullyOnboardedSettings;
use Inpsyde\PayPalCommerce\WcGateway\Settings\ProgressiveSettings;
use Inpsyde\PayPalCommerce\WcGateway\Settings\Settings; use Inpsyde\PayPalCommerce\WcGateway\Settings\Settings;
use Inpsyde\PayPalCommerce\WcGateway\Settings\SettingsFields; use Inpsyde\PayPalCommerce\WcGateway\Settings\SettingsFields;
use Inpsyde\PayPalCommerce\WcGateway\Settings\StartSettings;
return [ return [
'wcgateway.gateway.base' => static function (ContainerInterface $container): WcGatewayBase { 'wcgateway.gateway.base' => static function (ContainerInterface $container): WcGatewayBase {
@ -27,11 +30,13 @@ return [
$settingsFields = $container->get('wcgateway.settings.fields'); $settingsFields = $container->get('wcgateway.settings.fields');
$authorizedPayments = $container->get('wcgateway.processor.authorized-payments'); $authorizedPayments = $container->get('wcgateway.processor.authorized-payments');
$notice = $container->get('wcgateway.notice.authorize-order-action'); $notice = $container->get('wcgateway.notice.authorize-order-action');
$onboardingRender = $container->get('onboarding.render');
return new WcGateway( return new WcGateway(
$settingsFields, $settingsFields,
$orderProcessor, $orderProcessor,
$authorizedPayments, $authorizedPayments,
$notice $notice,
$onboardingRender
); );
}, },
'wcgateway.disabler' => static function (ContainerInterface $container): DisableGateways { 'wcgateway.disabler' => static function (ContainerInterface $container): DisableGateways {
@ -40,19 +45,29 @@ return [
}, },
'wcgateway.settings' => static function (ContainerInterface $container): Settings { 'wcgateway.settings' => static function (ContainerInterface $container): Settings {
$gateway = $container->get('wcgateway.gateway.base'); $gateway = $container->get('wcgateway.gateway.base');
$settingsField = $container->get('wcgateway.settings.fields'); return new Settings($gateway);
return new Settings($gateway, $settingsField);
}, },
'wcgateway.notice.connect' => static function (ContainerInterface $container): ConnectAdminNotice { 'wcgateway.notice.connect' => static function (ContainerInterface $container): ConnectAdminNotice {
$state = $container->get('onboarding.state');
$settings = $container->get('wcgateway.settings'); $settings = $container->get('wcgateway.settings');
return new ConnectAdminNotice($settings); return new ConnectAdminNotice($state, $settings);
}, },
'wcgateway.notice.authorize-order-action' => 'wcgateway.notice.authorize-order-action' =>
static function (ContainerInterface $container): AuthorizeOrderActionNotice { static function (ContainerInterface $container): AuthorizeOrderActionNotice {
return new AuthorizeOrderActionNotice(); return new AuthorizeOrderActionNotice();
}, },
'wcgateway.settings.fields' => static function (ContainerInterface $container): SettingsFields { 'wcgateway.settings.fields' => static function (ContainerInterface $container): SettingsFields {
return new SettingsFields(); $state = $container->get('onboarding.state');
/**
* @var State $state
*/
if ($state->currentState() === State::STATE_START) {
return new StartSettings();
}
if ($state->currentState() === State::STATE_PROGRESSIVE) {
return new ProgressiveSettings();
}
return new FullyOnboardedSettings();
}, },
'wcgateway.order-processor' => static function (ContainerInterface $container): OrderProcessor { 'wcgateway.order-processor' => static function (ContainerInterface $container): OrderProcessor {

View file

@ -21,7 +21,7 @@ class OrderTablePaymentStatusColumn
public function register(array $columns): array public function register(array $columns): array
{ {
if ($this->settings->get('intent') !== self::INTENT) { if (! $this->settings->has('intent') || $this->settings->get('intent') !== self::INTENT) {
return $columns; return $columns;
} }
@ -41,7 +41,7 @@ class OrderTablePaymentStatusColumn
public function render(string $column, int $wcOrderId) public function render(string $column, int $wcOrderId)
{ {
if ($this->settings->get('intent') !== self::INTENT) { if (! $this->settings->has('intent') || $this->settings->get('intent') !== self::INTENT) {
return; return;
} }

View file

@ -10,6 +10,7 @@ use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus; use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus;
use Inpsyde\PayPalCommerce\ApiClient\Factory\OrderFactory; use Inpsyde\PayPalCommerce\ApiClient\Factory\OrderFactory;
use Inpsyde\PayPalCommerce\ApiClient\Repository\CartRepository; use Inpsyde\PayPalCommerce\ApiClient\Repository\CartRepository;
use Inpsyde\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
use Inpsyde\PayPalCommerce\Session\SessionHandler; use Inpsyde\PayPalCommerce\Session\SessionHandler;
use Inpsyde\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice; use Inpsyde\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
use Inpsyde\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; use Inpsyde\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
@ -30,18 +31,21 @@ class WcGateway extends WcGatewayBase
private $authorizedPayments; private $authorizedPayments;
private $notice; private $notice;
private $orderProcessor; private $orderProcessor;
private $onboardingRenderer;
public function __construct( public function __construct(
SettingsFields $settingsFields, SettingsFields $settingsFields,
OrderProcessor $orderProcessor, OrderProcessor $orderProcessor,
AuthorizedPaymentsProcessor $authorizedPayments, AuthorizedPaymentsProcessor $authorizedPayments,
AuthorizeOrderActionNotice $notice AuthorizeOrderActionNotice $notice,
OnboardingRenderer $onboardingRenderer
) { ) {
$this->orderProcessor = $orderProcessor; $this->orderProcessor = $orderProcessor;
$this->authorizedPayments = $authorizedPayments; $this->authorizedPayments = $authorizedPayments;
$this->notice = $notice; $this->notice = $notice;
$this->settingsFields = $settingsFields; $this->settingsFields = $settingsFields;
$this->onboardingRenderer = $onboardingRenderer;
$this->method_title = __('PayPal Payments', 'woocommerce-paypal-gateway'); $this->method_title = __('PayPal Payments', 'woocommerce-paypal-gateway');
$this->method_description = __( $this->method_description = __(
@ -132,4 +136,8 @@ class WcGateway extends WcGatewayBase
$displayMessage = (isset($messageMapping[$status])) ? $messageMapping[$status] : AuthorizeOrderActionNotice::FAILED; $displayMessage = (isset($messageMapping[$status])) ? $messageMapping[$status] : AuthorizeOrderActionNotice::FAILED;
$this->notice->displayMessage($displayMessage); $this->notice->displayMessage($displayMessage);
} }
public function generate_ppcp_onboarding_html($a, $b) {
$this->onboardingRenderer->render();
}
} }

View file

@ -5,14 +5,18 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\WcGateway\Notice; namespace Inpsyde\PayPalCommerce\WcGateway\Notice;
use Inpsyde\PayPalCommerce\AdminNotices\Entity\Message; use Inpsyde\PayPalCommerce\AdminNotices\Entity\Message;
use Inpsyde\PayPalCommerce\Onboarding\State;
use Inpsyde\PayPalCommerce\WcGateway\Settings\Settings; use Inpsyde\PayPalCommerce\WcGateway\Settings\Settings;
use Psr\Container\ContainerInterface;
class ConnectAdminNotice class ConnectAdminNotice
{ {
private $state;
private $settings; private $settings;
public function __construct(Settings $settings) public function __construct(State $state, ContainerInterface $settings)
{ {
$this->state = $state;
$this->settings = $settings; $this->settings = $settings;
} }
@ -28,7 +32,7 @@ class ConnectAdminNotice
'%1$s is almost ready. To get started, <a href="%2$s">connect your account</a>.', '%1$s is almost ready. To get started, <a href="%2$s">connect your account</a>.',
'woocommerce-paypal-commerce-gateway' 'woocommerce-paypal-commerce-gateway'
), ),
$this->settings->get('title'), $this->settings->has('title') ? $this->settings->get('title') : '',
// TODO: find a better way to get the url // TODO: find a better way to get the url
admin_url('admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway') admin_url('admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway')
); );
@ -38,6 +42,6 @@ class ConnectAdminNotice
protected function shouldDisplay(): bool protected function shouldDisplay(): bool
{ {
// TODO: decide on what condition to display // TODO: decide on what condition to display
return !wc_string_to_bool($this->settings->get('enabled')); return $this->state->currentState() < State::STATE_PROGRESSIVE;
} }
} }

View file

@ -0,0 +1,234 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\WcGateway\Settings;
class FullyOnboardedSettings implements SettingsFields
{
public function fields(): array
{
return array_merge(
$this->gateway(),
$this->account(),
$this->buttons(),
$this->creditCards(),
);
}
private function gateway(): array
{
return [
'enabled' => [
'title' => __('Enable/Disable', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Enable PayPal Payments', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'title' => [
'title' => __('Title', 'woocommerce-paypal-gateway'),
'type' => 'text',
'description' => __(
'This controls the title which the user sees during checkout.',
'woocommerce-paypal-gateway'
),
'default' => __('PayPal', 'woocommerce-paypal-gateway'),
'desc_tip' => true,
],
'description' => [
'title' => __('Description', 'woocommerce-paypal-gateway'),
'type' => 'text',
'desc_tip' => true,
'description' => __(
'This controls the description which the user sees during checkout.',
'woocommerce-paypal-gateway'
),
'default' => __(
'Pay via PayPal; you can pay with your credit card if you don\'t have a PayPal account.',
'woocommerce-paypal-gateway'
),
],
'intent' => [
'title' => __('Intent', 'woocommerce-paypal-gateway'),
'type' => 'select',
'class' => 'wc-enhanced-select',
'default' => 'capture',
'desc_tip' => true,
'description' => __(
'The intent to either capture payment immediately or authorize a payment for an order after order creation.',
'woocommerce-paypal-gateway'
),
'options' => [
'capture' => __('Capture', 'woocommerce-paypal-gateway'),
'authorize' => __('Authorize', 'woocommerce-paypal-gateway'),
],
],
];
}
private function account(): array
{
return [
'account_settings' => [
'title' => __('Account Settings', 'woocommerce-paypal-gateway'),
'type' => 'title',
'description' => '',
],
'sandbox_on' => [
'title' => __('Enable Sandbox', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __(
'For testing your integration, you can enable the sandbox.',
'woocommerce-paypal-gateway'
),
'default' => 'yes',
],
];
}
private function buttons(): array
{
return [
'button_settings' => [
'title' => __('SmartButton Settings', 'woocommerce-paypal-gateway'),
'type' => 'title',
'description' => __(
'Customize the appearance of PayPal Payments on your site.',
'woocommerce-paypal-gateway'
),
],
'button_single_product_enabled' => [
'title' => __('Buttons on Single Product', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Enable on Single Product', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'button_mini_cart_enabled' => [
'title' => __('Buttons on Mini Cart', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Enable on Mini Cart', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'button_cart_enabled' => [
'title' => __('Buttons on Cart', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Enable on Cart', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'button_color' => [
'title' => __('Color', 'woocommerce-paypal-gateway'),
'type' => 'select',
'class' => 'wc-enhanced-select',
'default' => 'gold',
'desc_tip' => true,
'description' => __(
'Controls the background color of the primary button. Use "Gold" to leverage PayPal\'s recognition and preference, or change it to match your site design or aesthetic.',
'woocommerce-paypal-gateway'
),
'options' => [
'gold' => __('Gold (Recommended)', 'woocommerce-paypal-gateway'),
'blue' => __('Blue', 'woocommerce-paypal-gateway'),
'silver' => __('Silver', 'woocommerce-paypal-gateway'),
'black' => __('Black', 'woocommerce-paypal-gateway'),
],
],
'button_shape' => [
'title' => __('Shape', 'woocommerce-paypal-gateway'),
'type' => 'select',
'class' => 'wc-enhanced-select',
'default' => 'rect',
'desc_tip' => true,
'description' => __(
'The pill-shaped button\'s unique and powerful shape signifies PayPal in people\'s minds. Use the rectangular button as an alternative when pill-shaped buttons might pose design challenges.',
'woocommerce-paypal-gateway'
),
'options' => [
'pill' => __('Pill', 'woocommerce-paypal-gateway'),
'rect' => __('Rectangle', 'woocommerce-paypal-gateway'),
],
],
'disable_funding' => [
'title' => __('Disable funding sources', 'woocommerce-paypal-gateway'),
'type' => 'multiselect',
'class' => 'wc-enhanced-select',
'default' => [],
'desc_tip' => true,
'description' => __(
'By default all possible funding sources will be shown. You can disable some sources, if you wish.',
'woocommerce-paypal-gateway'
),
'options' => [
'card' => _x('Credit or debit cards', 'Name of payment method', 'woocommerce-paypal-gateway'),
'credit' => _x('PayPal Credit', 'Name of payment method', 'woocommerce-paypal-gateway'),
'venmo' => _x('Venmo', 'Name of payment method', 'woocommerce-paypal-gateway'),
'sepa' => _x('SEPA-Lastschrift', 'Name of payment method', 'woocommerce-paypal-gateway'),
'bancontact' => _x('Bancontact', 'Name of payment method', 'woocommerce-paypal-gateway'),
'eps' => _x('eps', 'Name of payment method', 'woocommerce-paypal-gateway'),
'giropay' => _x('giropay', 'Name of payment method', 'woocommerce-paypal-gateway'),
'ideal' => _x('iDEAL', 'Name of payment method', 'woocommerce-paypal-gateway'),
'mybank' => _x('MyBank', 'Name of payment method', 'woocommerce-paypal-gateway'),
'p24' => _x('Przelewy24', 'Name of payment method', 'woocommerce-paypal-gateway'),
'sofort' => _x('Sofort', 'Name of payment method', 'woocommerce-paypal-gateway'),
],
],
];
}
private function creditCards() : array {
return [
'credit_card_settings' => [
'title' => __('Credit Card Settings', 'woocommerce-paypal-gateway'),
'type' => 'title',
'description' => __(
'Customize the appearance of Credit Card Payments on your site.',
'woocommerce-paypal-gateway'
),
],
'dcc_cart_enabled' => [
'title' => __('Enable credit card on cart', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Allow your customers to pay with credit card directly in your cart.', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'dcc_mini_cart_enabled' => [
'title' => __('Enable credit card on mini cart', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Allow your customers to pay with credit card directly in your mini cart.', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'dcc_checkout_enabled' => [
'title' => __('Enable credit card on checkout', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Allow your customers to pay with credit card in the checkout.', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'dcc_single_product_enabled' => [
'title' => __('Enable credit card on products', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Allow your customers to pay with credit card instantly on the product page.', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'disable_cards' => [
'title' => __('Disable specific credid cards', 'woocommerce-paypal-gateway'),
'type' => 'multiselect',
'class' => 'wc-enhanced-select',
'default' => [],
'desc_tip' => true,
'description' => __(
'By default all possible credit cards will be shown. You can disable some cards, if you wish.',
'woocommerce-paypal-gateway'
),
'options' => [
'visa' => _x('Visa', 'Name of credit card', 'woocommerce-paypal-gateway'),
'mastercard' => _x('Mastercard', 'Name of credit card', 'woocommerce-paypal-gateway'),
'amex' => _x('American Express', 'Name of credit card', 'woocommerce-paypal-gateway'),
'discover' => _x('Discover', 'Name of credit card', 'woocommerce-paypal-gateway'),
'jcb' => _x('JCB', 'Name of credit card', 'woocommerce-paypal-gateway'),
'elo' => _x('Elo', 'Name of credit card', 'woocommerce-paypal-gateway'),
'hiper' => _x('Hiper', 'Name of credit card', 'woocommerce-paypal-gateway'),
],
],
];
}
}

View file

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\WcGateway\Settings;
class ProgressiveSettings extends StartSettings implements SettingsFields
{
public function fields(): array
{
$fields = parent::fields();
$fields[] = [
'type' => 'ppcp_onboarding',
];
return $fields;
}
}

View file

@ -11,12 +11,10 @@ use Psr\Container\ContainerInterface;
class Settings implements ContainerInterface class Settings implements ContainerInterface
{ {
private $gateway; private $gateway;
private $formFields;
public function __construct(WcGatewayInterface $gateway, SettingsFields $formFields) public function __construct(WcGatewayInterface $gateway)
{ {
$this->gateway = $gateway; $this->gateway = $gateway;
$this->formFields = $formFields;
} }
// phpcs:disable Inpsyde.CodeQuality.ReturnTypeDeclaration.NoReturnType // phpcs:disable Inpsyde.CodeQuality.ReturnTypeDeclaration.NoReturnType
@ -31,6 +29,6 @@ class Settings implements ContainerInterface
public function has($id) public function has($id)
{ {
return array_key_exists($id, $this->formFields->fields()); return !!$this->gateway->get_option($id);
} }
} }

View file

@ -6,231 +6,7 @@ namespace Inpsyde\PayPalCommerce\WcGateway\Settings;
//phpcs:disable Inpsyde.CodeQuality.FunctionLength.TooLong //phpcs:disable Inpsyde.CodeQuality.FunctionLength.TooLong
class SettingsFields interface SettingsFields
{ {
public function fields(): array public function fields(): array;
{
return array_merge(
$this->gateway(),
$this->account(),
$this->buttons(),
$this->creditCards(),
);
}
private function gateway(): array
{
return [
'enabled' => [
'title' => __('Enable/Disable', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Enable PayPal Payments', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'title' => [
'title' => __('Title', 'woocommerce-paypal-gateway'),
'type' => 'text',
'description' => __(
'This controls the title which the user sees during checkout.',
'woocommerce-paypal-gateway'
),
'default' => __('PayPal', 'woocommerce-paypal-gateway'),
'desc_tip' => true,
],
'description' => [
'title' => __('Description', 'woocommerce-paypal-gateway'),
'type' => 'text',
'desc_tip' => true,
'description' => __(
'This controls the description which the user sees during checkout.',
'woocommerce-paypal-gateway'
),
'default' => __(
'Pay via PayPal; you can pay with your credit card if you don\'t have a PayPal account.',
'woocommerce-paypal-gateway'
),
],
'intent' => [
'title' => __('Intent', 'woocommerce-paypal-gateway'),
'type' => 'select',
'class' => 'wc-enhanced-select',
'default' => 'capture',
'desc_tip' => true,
'description' => __(
'The intent to either capture payment immediately or authorize a payment for an order after order creation.',
'woocommerce-paypal-gateway'
),
'options' => [
'capture' => __('Capture', 'woocommerce-paypal-gateway'),
'authorize' => __('Authorize', 'woocommerce-paypal-gateway'),
],
],
];
}
private function account(): array
{
return [
'account_settings' => [
'title' => __('Account Settings', 'woocommerce-paypal-gateway'),
'type' => 'title',
'description' => '',
],
'sandbox_on' => [
'title' => __('Enable Sandbox', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __(
'For testing your integration, you can enable the sandbox.',
'woocommerce-paypal-gateway'
),
'default' => 'yes',
],
];
}
private function buttons(): array
{
return [
'button_settings' => [
'title' => __('SmartButton Settings', 'woocommerce-paypal-gateway'),
'type' => 'title',
'description' => __(
'Customize the appearance of PayPal Payments on your site.',
'woocommerce-paypal-gateway'
),
],
'button_single_product_enabled' => [
'title' => __('Buttons on Single Product', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Enable on Single Product', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'button_mini_cart_enabled' => [
'title' => __('Buttons on Mini Cart', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Enable on Mini Cart', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'button_cart_enabled' => [
'title' => __('Buttons on Cart', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Enable on Cart', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'button_color' => [
'title' => __('Color', 'woocommerce-paypal-gateway'),
'type' => 'select',
'class' => 'wc-enhanced-select',
'default' => 'gold',
'desc_tip' => true,
'description' => __(
'Controls the background color of the primary button. Use "Gold" to leverage PayPal\'s recognition and preference, or change it to match your site design or aesthetic.',
'woocommerce-paypal-gateway'
),
'options' => [
'gold' => __('Gold (Recommended)', 'woocommerce-paypal-gateway'),
'blue' => __('Blue', 'woocommerce-paypal-gateway'),
'silver' => __('Silver', 'woocommerce-paypal-gateway'),
'black' => __('Black', 'woocommerce-paypal-gateway'),
],
],
'button_shape' => [
'title' => __('Shape', 'woocommerce-paypal-gateway'),
'type' => 'select',
'class' => 'wc-enhanced-select',
'default' => 'rect',
'desc_tip' => true,
'description' => __(
'The pill-shaped button\'s unique and powerful shape signifies PayPal in people\'s minds. Use the rectangular button as an alternative when pill-shaped buttons might pose design challenges.',
'woocommerce-paypal-gateway'
),
'options' => [
'pill' => __('Pill', 'woocommerce-paypal-gateway'),
'rect' => __('Rectangle', 'woocommerce-paypal-gateway'),
],
],
'disable_funding' => [
'title' => __('Disable funding sources', 'woocommerce-paypal-gateway'),
'type' => 'multiselect',
'class' => 'wc-enhanced-select',
'default' => [],
'desc_tip' => true,
'description' => __(
'By default all possible funding sources will be shown. You can disable some sources, if you wish.',
'woocommerce-paypal-gateway'
),
'options' => [
'card' => _x('Credit or debit cards', 'Name of payment method', 'woocommerce-paypal-gateway'),
'credit' => _x('PayPal Credit', 'Name of payment method', 'woocommerce-paypal-gateway'),
'venmo' => _x('Venmo', 'Name of payment method', 'woocommerce-paypal-gateway'),
'sepa' => _x('SEPA-Lastschrift', 'Name of payment method', 'woocommerce-paypal-gateway'),
'bancontact' => _x('Bancontact', 'Name of payment method', 'woocommerce-paypal-gateway'),
'eps' => _x('eps', 'Name of payment method', 'woocommerce-paypal-gateway'),
'giropay' => _x('giropay', 'Name of payment method', 'woocommerce-paypal-gateway'),
'ideal' => _x('iDEAL', 'Name of payment method', 'woocommerce-paypal-gateway'),
'mybank' => _x('MyBank', 'Name of payment method', 'woocommerce-paypal-gateway'),
'p24' => _x('Przelewy24', 'Name of payment method', 'woocommerce-paypal-gateway'),
'sofort' => _x('Sofort', 'Name of payment method', 'woocommerce-paypal-gateway'),
],
],
];
}
private function creditCards() : array {
return [
'credit_card_settings' => [
'title' => __('Credit Card Settings', 'woocommerce-paypal-gateway'),
'type' => 'title',
'description' => __(
'Customize the appearance of Credit Card Payments on your site.',
'woocommerce-paypal-gateway'
),
],
'dcc_cart_enabled' => [
'title' => __('Enable credit card on cart', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Allow your customers to pay with credit card directly in your cart.', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'dcc_mini_cart_enabled' => [
'title' => __('Enable credit card on mini cart', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Allow your customers to pay with credit card directly in your mini cart.', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'dcc_checkout_enabled' => [
'title' => __('Enable credit card on checkout', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Allow your customers to pay with credit card in the checkout.', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'dcc_single_product_enabled' => [
'title' => __('Enable credit card on products', 'woocommerce-paypal-gateway'),
'type' => 'checkbox',
'label' => __('Allow your customers to pay with credit card instantly on the product page.', 'woocommerce-paypal-gateway'),
'default' => 'yes',
],
'disable_cards' => [
'title' => __('Disable specific credid cards', 'woocommerce-paypal-gateway'),
'type' => 'multiselect',
'class' => 'wc-enhanced-select',
'default' => [],
'desc_tip' => true,
'description' => __(
'By default all possible credit cards will be shown. You can disable some cards, if you wish.',
'woocommerce-paypal-gateway'
),
'options' => [
'visa' => _x('Visa', 'Name of credit card', 'woocommerce-paypal-gateway'),
'mastercard' => _x('Mastercard', 'Name of credit card', 'woocommerce-paypal-gateway'),
'amex' => _x('American Express', 'Name of credit card', 'woocommerce-paypal-gateway'),
'discover' => _x('Discover', 'Name of credit card', 'woocommerce-paypal-gateway'),
'jcb' => _x('JCB', 'Name of credit card', 'woocommerce-paypal-gateway'),
'elo' => _x('Elo', 'Name of credit card', 'woocommerce-paypal-gateway'),
'hiper' => _x('Hiper', 'Name of credit card', 'woocommerce-paypal-gateway'),
],
],
];
}
} }

View file

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\WcGateway\Settings;
class StartSettings implements SettingsFields
{
public function fields(): array
{
return [
'merchant_email' => [
'title' => __('Email', 'woocommerce-paypal-gateway'),
'type' => 'email',
'description' => __(
'Please enter the email address with which you want to receive payments.',
'woocommerce-paypal-gateway'
),
'default' => '',
'desc_tip' => true,
],];
}
}

View file

@ -14,6 +14,7 @@ declare( strict_types = 1 );
* Network: TODO: Specify value 'true' or remove line * Network: TODO: Specify value 'true' or remove line
*/ */
namespace Inpsyde\PayPalCommerce; namespace Inpsyde\PayPalCommerce;
use Dhii\Container\CachingContainer; use Dhii\Container\CachingContainer;
@ -38,6 +39,9 @@ use Inpsyde\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
foreach (glob(plugin_dir_path(__FILE__).'modules/*/module.php') as $moduleFile) { foreach (glob(plugin_dir_path(__FILE__).'modules/*/module.php') as $moduleFile) {
$modules[] = (@require $moduleFile)(); $modules[] = (@require $moduleFile)();
} }
foreach (glob(plugin_dir_path(__FILE__).'modules.local/*/module.php') as $moduleFile) {
$modules[] = (@require $moduleFile)();
}
$providers = []; $providers = [];
foreach ($modules as $module) { foreach ($modules as $module) {
/* @var $module ModuleInterface */ /* @var $module ModuleInterface */