mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-08-30 05:00:51 +08:00
Fix merge conflicts with trunk
This commit is contained in:
commit
34b624905d
31 changed files with 1008 additions and 165 deletions
|
@ -1,6 +1,6 @@
|
|||
# WooCommerce PayPal Payments
|
||||
|
||||
PayPal's latest complete payments processing solution. Accept PayPal, PayPal Credit, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage.
|
||||
PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage.
|
||||
|
||||
## Requirements
|
||||
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
*** Changelog ***
|
||||
|
||||
= 1.2.1 - 2021-03-08 =
|
||||
* Fix - Address compatibility issue with Jetpack.
|
||||
|
||||
= 1.2.0 - 2021-03-08 =
|
||||
* Add - Rework onboarding code and add REST controller for integration with the OBW. #121
|
||||
* Fix - Remove spinner on click, on cancel and on error. #124
|
||||
|
||||
= 1.1.0 - 2021-02-01 =
|
||||
* Add - Buy Now Pay Later for UK. #104
|
||||
* Add - DE now has 12 month installments. #106
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"license": "GPL-2.0",
|
||||
"require": {
|
||||
"dhii/module-interface": "0.1",
|
||||
"psr/container": "^1.0",
|
||||
"psr/container": "1.0.0",
|
||||
"container-interop/service-provider": "^0.4.0",
|
||||
"dhii/containers": "v0.1.0-alpha1",
|
||||
"dhii/wp-containers": "v0.1.0-alpha1",
|
||||
|
|
|
@ -74,12 +74,13 @@ class PartnerReferralsData {
|
|||
return array(
|
||||
'partner_config_override' => array(
|
||||
'partner_logo_url' => 'https://connect.woocommerce.com/images/woocommerce_logo.png',
|
||||
'return_url' => admin_url(
|
||||
'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway'
|
||||
'return_url' => apply_filters(
|
||||
'woocommerce_paypal_payments_partner_config_override_return_url',
|
||||
admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' )
|
||||
),
|
||||
'return_url_description' => __(
|
||||
'Return to your shop.',
|
||||
'woocommerce-paypal-payments'
|
||||
'return_url_description' => apply_filters(
|
||||
'woocommerce_paypal_payments_partner_config_override_return_url_description',
|
||||
__( 'Return to your shop.', 'woocommerce-paypal-payments' )
|
||||
),
|
||||
'show_add_credit_card' => true,
|
||||
),
|
||||
|
|
|
@ -19,9 +19,6 @@ class CheckoutActionHandler {
|
|||
const errorHandler = this.errorHandler;
|
||||
|
||||
const formSelector = this.config.context === 'checkout' ? 'form.checkout' : 'form#order_review';
|
||||
spinner.setTarget(formSelector);
|
||||
spinner.block();
|
||||
|
||||
const formValues = jQuery(formSelector).serialize();
|
||||
|
||||
return fetch(this.config.ajax.create_order.endpoint, {
|
||||
|
@ -39,7 +36,18 @@ class CheckoutActionHandler {
|
|||
}).then(function (data) {
|
||||
if (!data.success) {
|
||||
spinner.unblock();
|
||||
errorHandler.message(data.data.message, true);
|
||||
//handle both messages sent from Woocommerce (data.messages) and this plugin (data.data.message)
|
||||
if (typeof(data.messages) !== 'undefined' )
|
||||
{
|
||||
const domParser = new DOMParser();
|
||||
errorHandler.appendPreparedErrorMessageElement(
|
||||
domParser.parseFromString(data.messages, 'text/html')
|
||||
.querySelector('ul')
|
||||
);
|
||||
} else {
|
||||
errorHandler.message(data.data.message, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
const input = document.createElement('input');
|
||||
|
@ -53,8 +61,12 @@ class CheckoutActionHandler {
|
|||
return {
|
||||
createOrder,
|
||||
onApprove:onApprove(this, this.errorHandler, this.spinner),
|
||||
onError: (error) => {
|
||||
onCancel: () => {
|
||||
spinner.unblock();
|
||||
},
|
||||
onError: () => {
|
||||
this.errorHandler.genericError();
|
||||
spinner.unblock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ class ErrorHandler {
|
|||
{
|
||||
this.genericErrorText = genericErrorText;
|
||||
this.wrapper = document.querySelector('.woocommerce-notices-wrapper');
|
||||
this.messagesList = document.querySelector('ul.woocommerce-error');
|
||||
}
|
||||
|
||||
genericError() {
|
||||
|
@ -14,18 +15,55 @@ class ErrorHandler {
|
|||
this.message(this.genericErrorText)
|
||||
}
|
||||
|
||||
appendPreparedErrorMessageElement(errorMessageElement)
|
||||
{
|
||||
if(this.messagesList === null) {
|
||||
this.prepareMessagesList();
|
||||
}
|
||||
|
||||
this.messagesList.replaceWith(errorMessageElement);
|
||||
}
|
||||
|
||||
message(text, persist = false)
|
||||
{
|
||||
this.wrapper.classList.add('woocommerce-error');
|
||||
if(! typeof String || text.length === 0){
|
||||
throw new Error('A new message text must be a non-empty string.');
|
||||
}
|
||||
|
||||
if(this.messagesList === null){
|
||||
this.prepareMessagesList();
|
||||
}
|
||||
|
||||
if (persist) {
|
||||
this.wrapper.classList.add('ppcp-persist');
|
||||
} else {
|
||||
this.wrapper.classList.remove('ppcp-persist');
|
||||
}
|
||||
this.wrapper.innerHTML = this.sanitize(text);
|
||||
|
||||
let messageNode = this.prepareMessagesListItem(text);
|
||||
this.messagesList.appendChild(messageNode);
|
||||
|
||||
jQuery.scroll_to_notices(jQuery('.woocommerce-notices-wrapper'))
|
||||
}
|
||||
|
||||
prepareMessagesList()
|
||||
{
|
||||
if(this.messagesList === null){
|
||||
this.messagesList = document.createElement('ul');
|
||||
this.messagesList.setAttribute('class', 'woocommerce-error');
|
||||
this.messagesList.setAttribute('role', 'alert');
|
||||
this.wrapper.appendChild(this.messagesList);
|
||||
}
|
||||
}
|
||||
|
||||
prepareMessagesListItem(message)
|
||||
{
|
||||
const li = document.createElement('li');
|
||||
li.innerHTML = message;
|
||||
|
||||
return li;
|
||||
}
|
||||
|
||||
sanitize(text)
|
||||
{
|
||||
const textarea = document.createElement('textarea');
|
||||
|
|
|
@ -113,6 +113,9 @@ class CreditCardRenderer {
|
|||
payload.orderID = payload.orderId;
|
||||
this.spinner.unblock();
|
||||
return contextConfig.onApprove(payload);
|
||||
}).catch(() => {
|
||||
this.errorHandler.genericError();
|
||||
this.spinner.unblock();
|
||||
});
|
||||
} else {
|
||||
this.spinner.unblock();
|
||||
|
|
|
@ -60,7 +60,6 @@ return array(
|
|||
return new DisabledSmartButton();
|
||||
}
|
||||
$payee_repository = $container->get( 'api.repository.payee' );
|
||||
$identity_token = $container->get( 'api.endpoint.identity-token' );
|
||||
$payer_factory = $container->get( 'api.factory.payer' );
|
||||
$request_data = $container->get( 'button.request-data' );
|
||||
|
||||
|
@ -75,7 +74,6 @@ return array(
|
|||
$container->get( 'session.handler' ),
|
||||
$settings,
|
||||
$payee_repository,
|
||||
$identity_token,
|
||||
$payer_factory,
|
||||
$client_id,
|
||||
$request_data,
|
||||
|
|
|
@ -60,13 +60,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
*/
|
||||
private $payee_repository;
|
||||
|
||||
/**
|
||||
* The Identity Token.
|
||||
*
|
||||
* @var IdentityToken
|
||||
*/
|
||||
private $identity_token;
|
||||
|
||||
/**
|
||||
* The Payer Factory.
|
||||
*
|
||||
|
@ -145,7 +138,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
SessionHandler $session_handler,
|
||||
Settings $settings,
|
||||
PayeeRepository $payee_repository,
|
||||
IdentityToken $identity_token,
|
||||
PayerFactory $payer_factory,
|
||||
string $client_id,
|
||||
RequestData $request_data,
|
||||
|
@ -160,7 +152,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
$this->session_handler = $session_handler;
|
||||
$this->settings = $settings;
|
||||
$this->payee_repository = $payee_repository;
|
||||
$this->identity_token = $identity_token;
|
||||
$this->payer_factory = $payer_factory;
|
||||
$this->client_id = $client_id;
|
||||
$this->request_data = $request_data;
|
||||
|
@ -373,7 +364,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
);
|
||||
}
|
||||
|
||||
add_action( 'woocommerce_review_order_after_submit', array( $this, 'button_renderer' ), 10 );
|
||||
add_action( 'woocommerce_review_order_after_payment', array( $this, 'button_renderer' ), 10 );
|
||||
add_action( 'woocommerce_pay_order_after_submit', array( $this, 'button_renderer' ), 10 );
|
||||
|
||||
return true;
|
||||
|
@ -613,7 +604,6 @@ class SmartButton implements SmartButtonInterface {
|
|||
return is_user_logged_in();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether we need to initialize the script to enable tokenization for subscriptions or not.
|
||||
*
|
||||
|
@ -775,22 +765,15 @@ class SmartButton implements SmartButtonInterface {
|
|||
if ( $payee->merchant_id() ) {
|
||||
$params['merchant-id'] = $payee->merchant_id();
|
||||
}
|
||||
$disable_funding = $this->settings->has( 'disable_funding' ) ?
|
||||
$disable_funding = $this->settings->has( 'disable_funding' ) ?
|
||||
$this->settings->get( 'disable_funding' ) : array();
|
||||
$disable_funding[] = 'venmo';
|
||||
if ( ! is_checkout() ) {
|
||||
$disable_funding[] = 'card';
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable card for UK.
|
||||
*/
|
||||
$region = wc_get_base_location();
|
||||
$country = $region['country'];
|
||||
if ( 'GB' === $country ) {
|
||||
$disable_funding[] = 'credit';
|
||||
if ( count( $disable_funding ) > 0 ) {
|
||||
$params['disable-funding'] = implode( ',', array_unique( $disable_funding ) );
|
||||
}
|
||||
$params['disable-funding'] = implode( ',', array_unique( $disable_funding ) );
|
||||
|
||||
$smart_button_url = add_query_arg( $params, 'https://www.paypal.com/sdk/js' );
|
||||
return $smart_button_url;
|
||||
|
|
|
@ -163,7 +163,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
|
||||
$this->set_bn_code( $data );
|
||||
$needs_shipping = WC()->cart && WC()->cart->needs_shipping();
|
||||
$shipping_address_is_fix = $needs_shipping && 'checkout' === $data['context'] ? true : false;
|
||||
$shipping_address_is_fix = $needs_shipping && 'checkout' === $data['context'];
|
||||
$order = $this->api_endpoint->create(
|
||||
$purchase_units,
|
||||
$this->payer( $data, $wc_order ),
|
||||
|
@ -173,7 +173,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
$shipping_address_is_fix
|
||||
);
|
||||
if ( 'checkout' === $data['context'] ) {
|
||||
$this->validate_checkout_form( $data['form'], $order );
|
||||
$this->process_checkout_form( $data['form'], $order );
|
||||
}
|
||||
if ( 'pay-now' === $data['context'] && get_option( 'woocommerce_terms_page_id', '' ) !== '' ) {
|
||||
$this->validate_paynow_form( $data['form'] );
|
||||
|
@ -263,7 +263,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
*
|
||||
* @throws \Exception On Error.
|
||||
*/
|
||||
private function validate_checkout_form( string $form_values, Order $order ) {
|
||||
private function process_checkout_form( string $form_values, Order $order ) {
|
||||
$this->order = $order;
|
||||
$form_values = explode( '&', $form_values );
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ class MessagesApply {
|
|||
'US',
|
||||
'DE',
|
||||
'GB',
|
||||
'FR',
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,22 +1,104 @@
|
|||
function onboardingCallback(authCode, sharedId) {
|
||||
const sandboxSwitchElement = document.querySelector('#ppcp-sandbox_on');
|
||||
fetch(
|
||||
PayPalCommerceGatewayOnboarding.endpoint,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(
|
||||
{
|
||||
authCode: authCode,
|
||||
sharedId: sharedId,
|
||||
nonce: PayPalCommerceGatewayOnboarding.nonce,
|
||||
env: sandboxSwitchElement && sandboxSwitchElement.checked ? 'sandbox' : 'production'
|
||||
}
|
||||
)
|
||||
// Onboarding.
|
||||
const ppcp_onboarding = {
|
||||
BUTTON_SELECTOR: '[data-paypal-onboard-button]',
|
||||
PAYPAL_JS_ID: 'ppcp-onboarding-paypal-js',
|
||||
_timeout: false,
|
||||
|
||||
init: function() {
|
||||
document.addEventListener('DOMContentLoaded', this.reload);
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
const buttons = document.querySelectorAll(ppcp_onboarding.BUTTON_SELECTOR);
|
||||
|
||||
if (0 === buttons.length) {
|
||||
return;
|
||||
}
|
||||
);
|
||||
|
||||
// Add event listeners to buttons.
|
||||
buttons.forEach(
|
||||
(element) => {
|
||||
if (element.hasAttribute('data-ppcp-button-initialized')) {
|
||||
return;
|
||||
}
|
||||
|
||||
element.addEventListener(
|
||||
'click',
|
||||
(e) => {
|
||||
if (!element.hasAttribute('data-ppcp-button-initialized') || 'undefined' === typeof window.PAYPAL) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// Clear any previous PayPal scripts.
|
||||
[ppcp_onboarding.PAYPAL_JS_ID, 'signup-js', 'biz-js'].forEach(
|
||||
(scriptID) => {
|
||||
const scriptTag = document.getElementById(scriptID);
|
||||
|
||||
if (scriptTag) {
|
||||
scriptTag.parentNode.removeChild(scriptTag);
|
||||
}
|
||||
|
||||
if ('undefined' !== typeof window.PAYPAL) {
|
||||
delete window.PAYPAL;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Load PayPal scripts.
|
||||
const paypalScriptTag = document.createElement('script');
|
||||
paypalScriptTag.id = ppcp_onboarding.PAYPAL_JS_ID;
|
||||
paypalScriptTag.src = PayPalCommerceGatewayOnboarding.paypal_js_url;
|
||||
document.body.append(paypalScriptTag);
|
||||
|
||||
if (ppcp_onboarding._timeout) {
|
||||
clearTimeout(ppcp_onboarding._timeout);
|
||||
}
|
||||
|
||||
ppcp_onboarding._timeout = setTimeout(
|
||||
() => {
|
||||
buttons.forEach((element) => { element.setAttribute('data-ppcp-button-initialized', 'true'); });
|
||||
|
||||
if ('undefined' !== window.PAYPAL.apps.Signup) {
|
||||
window.PAYPAL.apps.Signup.render();
|
||||
}
|
||||
},
|
||||
1000
|
||||
);
|
||||
},
|
||||
|
||||
loginSeller: function(env, authCode, sharedId) {
|
||||
fetch(
|
||||
PayPalCommerceGatewayOnboarding.endpoint,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(
|
||||
{
|
||||
authCode: authCode,
|
||||
sharedId: sharedId,
|
||||
nonce: PayPalCommerceGatewayOnboarding.nonce,
|
||||
env: env
|
||||
}
|
||||
)
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
||||
function ppcp_onboarding_sandboxCallback(...args) {
|
||||
return ppcp_onboarding.loginSeller('sandbox', ...args);
|
||||
}
|
||||
|
||||
function ppcp_onboarding_productionCallback(...args) {
|
||||
return ppcp_onboarding.loginSeller('production', ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,21 +256,23 @@ const disconnect = (event) => {
|
|||
);
|
||||
|
||||
// Prevent a possibly dirty form arising from this particular checkbox.
|
||||
sandboxSwitchElement.addEventListener(
|
||||
'click',
|
||||
(event) => {
|
||||
const value = event.target.checked;
|
||||
if (sandboxSwitchElement) {
|
||||
sandboxSwitchElement.addEventListener(
|
||||
'click',
|
||||
(event) => {
|
||||
const value = event.target.checked;
|
||||
|
||||
toggleSandboxProduction( ! value );
|
||||
toggleSandboxProduction( ! value );
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setTimeout( () => {
|
||||
event.target.checked = value;
|
||||
}, 1
|
||||
);
|
||||
}
|
||||
);
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setTimeout( () => {
|
||||
event.target.checked = value;
|
||||
}, 1
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// document.querySelectorAll('#mainform input[type="checkbox"]').forEach(
|
||||
// (checkbox) => {
|
||||
|
@ -207,6 +291,8 @@ const disconnect = (event) => {
|
|||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Onboarding buttons.
|
||||
ppcp_onboarding.init();
|
||||
})();
|
||||
|
|
|
@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
|||
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Onboarding_REST_Controller;
|
||||
|
||||
return array(
|
||||
'api.sandbox-host' => static function ( $container ): string {
|
||||
|
@ -207,4 +208,7 @@ return array(
|
|||
$partner_referrals_sandbox
|
||||
);
|
||||
},
|
||||
'onboarding.rest' => static function( $container ) : Onboarding_REST_Controller {
|
||||
return new Onboarding_REST_Controller( $container );
|
||||
},
|
||||
);
|
||||
|
|
|
@ -51,7 +51,7 @@ class OnboardingAssets {
|
|||
LoginSellerEndpoint $login_seller_endpoint
|
||||
) {
|
||||
|
||||
$this->module_url = $module_url;
|
||||
$this->module_url = untrailingslashit( $module_url );
|
||||
$this->state = $state;
|
||||
$this->login_seller_endpoint = $login_seller_endpoint;
|
||||
}
|
||||
|
@ -78,9 +78,6 @@ class OnboardingAssets {
|
|||
1,
|
||||
true
|
||||
);
|
||||
if ( ! $this->should_render_onboarding_script() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$url = $this->module_url . '/assets/js/onboarding.js';
|
||||
wp_register_script(
|
||||
|
@ -93,15 +90,25 @@ class OnboardingAssets {
|
|||
wp_localize_script(
|
||||
'ppcp-onboarding',
|
||||
'PayPalCommerceGatewayOnboarding',
|
||||
array(
|
||||
'endpoint' => home_url( \WC_AJAX::get_endpoint( LoginSellerEndpoint::ENDPOINT ) ),
|
||||
'nonce' => wp_create_nonce( $this->login_seller_endpoint::nonce() ),
|
||||
)
|
||||
$this->get_script_data()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the onboarding script.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
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',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the necessary scripts.
|
||||
*
|
||||
|
|
|
@ -52,6 +52,23 @@ class OnboardingRenderer {
|
|||
$this->sandbox_partner_referrals = $sandbox_partner_referrals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action URL for the onboarding button/link.
|
||||
*
|
||||
* @param boolean $is_production Whether the production or sandbox button should be rendered.
|
||||
* @return string URL.
|
||||
*/
|
||||
public function get_signup_link( bool $is_production ) {
|
||||
$args = array(
|
||||
'displayMode' => 'minibrowser',
|
||||
);
|
||||
|
||||
$url = $is_production ? $this->production_partner_referrals->signup_link() : $this->sandbox_partner_referrals->signup_link();
|
||||
$url = add_query_arg( $args, $url );
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the "Connect to PayPal" button.
|
||||
*
|
||||
|
@ -59,27 +76,12 @@ class OnboardingRenderer {
|
|||
*/
|
||||
public function render( bool $is_production ) {
|
||||
try {
|
||||
$args = array(
|
||||
'displayMode' => 'minibrowser',
|
||||
$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' ),
|
||||
$is_production ? 'production' : 'sandbox'
|
||||
);
|
||||
|
||||
$url = $is_production ? $this->production_partner_referrals->signup_link() : $this->sandbox_partner_referrals->signup_link();
|
||||
$url = add_query_arg( $args, $url );
|
||||
$id = $is_production ? 'connect-to-production' : 'connect-to-sandbox';
|
||||
$label = $is_production ? __( 'Connect to PayPal', 'woocommerce-paypal-payments' ) : __( 'Connect to PayPal Sandbox', 'woocommerce-paypal-payments' );
|
||||
$this->render_button(
|
||||
$url,
|
||||
$id,
|
||||
$label
|
||||
);
|
||||
|
||||
$script_url = 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js'; ?>
|
||||
<script>document.querySelectorAll('[data-paypal-onboard-complete=onboardingCallback]').forEach( (element) => { element.addEventListener('click', (e) => {if ('undefined' === typeof PAYPAL ) e.preventDefault(); }) });</script>
|
||||
<script
|
||||
id="paypal-js"
|
||||
src="<?php echo esc_url( $script_url ); ?>"
|
||||
></script>
|
||||
<?php
|
||||
} catch ( RuntimeException $exception ) {
|
||||
esc_html_e(
|
||||
'We could not properly connect to PayPal. Please reload the page to continue',
|
||||
|
@ -94,14 +96,16 @@ 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 $env The environment ('production' or 'sandbox').
|
||||
*/
|
||||
private function render_button( string $url, string $id, string $label ) {
|
||||
private function render_button( string $url, string $id, string $label, string $env ) {
|
||||
?>
|
||||
<a
|
||||
target="_blank"
|
||||
class="button-primary"
|
||||
id="<?php echo esc_attr( $id ); ?>"
|
||||
data-paypal-onboard-complete="onboardingCallback"
|
||||
data-paypal-onboard-complete="ppcp_onboarding_<?php echo esc_attr( $env ); ?>Callback"
|
||||
data-paypal-onboard-button="true"
|
||||
href="<?php echo esc_url( $url ); ?>"
|
||||
data-paypal-button="true"
|
||||
>
|
||||
|
|
321
modules/ppcp-onboarding/src/class-onboarding-rest-controller.php
Normal file
321
modules/ppcp-onboarding/src/class-onboarding-rest-controller.php
Normal file
|
@ -0,0 +1,321 @@
|
|||
<?php
|
||||
/**
|
||||
* Onboarding REST controller.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Onboarding
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Onboarding;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
* Exposes and handles REST routes related to onboarding.
|
||||
*/
|
||||
class Onboarding_REST_Controller {
|
||||
|
||||
/**
|
||||
* REST namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_namespace = 'wc-paypal/v1';
|
||||
|
||||
/**
|
||||
* REST base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'onboarding';
|
||||
|
||||
/**
|
||||
* Module container with access to plugin services.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container = null;
|
||||
|
||||
/**
|
||||
* Used to temporarily store URL arguments to add to the return URL associated to a signup link.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $return_url_args = array();
|
||||
|
||||
|
||||
/**
|
||||
* OnboardingRESTController constructor.
|
||||
*
|
||||
* @param ContainerInterface $container Module container with access to plugin services.
|
||||
*/
|
||||
public function __construct( ContainerInterface $container ) {
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers REST routes under 'wc-paypal/v1/onboarding'.
|
||||
* Specifically:
|
||||
* - `/onboarding/get-params`, which returns information useful to display an onboarding button.
|
||||
* - `/onboarding/get-status`, which returns information about the current environment and its onboarding state.
|
||||
* - `/onboarding/set-credentials`, which allows setting merchant/API credentials.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->rest_namespace,
|
||||
'/' . $this->rest_base . '/get-params',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array( $this, 'get_params' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->rest_namespace,
|
||||
'/' . $this->rest_base . '/get-status',
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( $this, 'get_status' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->rest_namespace,
|
||||
'/' . $this->rest_base . '/set-credentials',
|
||||
array(
|
||||
'methods' => 'POST',
|
||||
'callback' => array( $this, 'set_credentials' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the requester's permissions.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
* @return bool
|
||||
*/
|
||||
public function check_permission( $request ) {
|
||||
return current_user_can( 'install_plugins' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the `/onboarding/get-params` endpoint.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
* @return array
|
||||
*/
|
||||
public function get_params( $request ) {
|
||||
$params = $request->get_json_params();
|
||||
|
||||
$environment = ( isset( $params['environment'] ) && in_array( $params['environment'], array( 'production', 'sandbox' ), true ) ) ? $params['environment'] : 'sandbox';
|
||||
|
||||
return array(
|
||||
'scriptURL' => trailingslashit( $this->container->get( 'onboarding.url' ) ) . 'assets/js/onboarding.js',
|
||||
'scriptData' => $this->container->get( 'onboarding.assets' )->get_script_data(),
|
||||
'environment' => $environment,
|
||||
'onboardCompleteCallback' => 'ppcp_onboarding_' . $environment . 'Callback',
|
||||
'signupLink' => $this->generate_signup_link( $environment, ( ! empty( $params['returnUrlArgs'] ) ? $params['returnUrlArgs'] : array() ) ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the `/onboarding/get-status` endpoint.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
* @return array
|
||||
*/
|
||||
public function get_status( $request ) {
|
||||
$environment = $this->container->get( 'onboarding.environment' );
|
||||
$state = $this->container->get( 'onboarding.state' );
|
||||
|
||||
return array(
|
||||
'environment' => $environment->current_environment(),
|
||||
'onboarded' => ( $state->current_state() >= State::STATE_ONBOARDED ),
|
||||
'state' => $this->get_onboarding_state_name( $state->current_state() ),
|
||||
'sandbox' => array(
|
||||
'state' => $this->get_onboarding_state_name( $state->sandbox_state() ),
|
||||
'onboarded' => ( $state->sandbox_state() >= State::STATE_ONBOARDED ),
|
||||
),
|
||||
'production' => array(
|
||||
'state' => $this->get_onboarding_state_name( $state->production_state() ),
|
||||
'onboarded' => ( $state->production_state() >= State::STATE_ONBOARDED ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the `/onboarding/set-credentials` endpoint.
|
||||
*
|
||||
* @param WP_REST_Request $request The request.
|
||||
* @return WP_Error|array
|
||||
*/
|
||||
public function set_credentials( $request ) {
|
||||
static $credential_keys = array(
|
||||
'merchant_id',
|
||||
'merchant_email',
|
||||
'client_id',
|
||||
'client_secret',
|
||||
);
|
||||
|
||||
// Sanitize params.
|
||||
$params = array_filter( array_map( 'trim', $request->get_json_params() ) );
|
||||
|
||||
// Validate 'environment'.
|
||||
if ( empty( $params['environment'] ) || ! in_array( $params['environment'], array( 'sandbox', 'production' ), true ) ) {
|
||||
return new \WP_Error(
|
||||
'woocommerce_paypal_payments_invalid_environment',
|
||||
sprintf(
|
||||
/* translators: placeholder is an arbitrary string. */
|
||||
__( 'Environment "%s" is invalid. Use "sandbox" or "production".', 'woocommerce-paypal-payments' ),
|
||||
isset( $params['environment'] ) ? $params['environment'] : ''
|
||||
),
|
||||
array( 'status' => 400 )
|
||||
);
|
||||
}
|
||||
|
||||
// Validate the other fields.
|
||||
$missing_keys = array_values( array_diff( $credential_keys, array_keys( $params ) ) );
|
||||
if ( $missing_keys ) {
|
||||
return new \WP_Error(
|
||||
'woocommerce_paypal_payments_credentials_incomplete',
|
||||
sprintf(
|
||||
/* translators: placeholder is a comma-separated list of fields. */
|
||||
__( 'Credentials are incomplete. Missing fields: %s.', 'woocommerce-paypal-payments' ),
|
||||
implode( ', ', $missing_keys )
|
||||
),
|
||||
array(
|
||||
'missing_fields' => $missing_keys,
|
||||
'status' => 400,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$settings = $this->container->get( 'wcgateway.settings' );
|
||||
$skip_persist = true;
|
||||
|
||||
// Enable gateway.
|
||||
if ( ! $settings->has( 'enabled' ) || ! $settings->get( 'enabled' ) ) {
|
||||
$settings->set( 'enabled', true );
|
||||
$skip_persist = false;
|
||||
}
|
||||
|
||||
foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) {
|
||||
if ( PayPalGateway::ID === $gateway->id ) {
|
||||
$gateway->update_option( 'enabled', 'yes' );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update settings.
|
||||
$sandbox_on = ( 'sandbox' === $params['environment'] );
|
||||
if ( ! $settings->has( 'sandbox_on' ) || ( (bool) $settings->get( 'sandbox_on' ) !== $sandbox_on ) ) {
|
||||
$settings->set( 'sandbox_on', $sandbox_on );
|
||||
$skip_persist = false;
|
||||
}
|
||||
|
||||
foreach ( $credential_keys as $key ) {
|
||||
$value = $params[ $key ];
|
||||
$env_key = $key . '_' . $params['environment'];
|
||||
|
||||
if ( ! $settings->has( $key ) || ! $settings->has( $env_key ) || $settings->get( $key ) !== $value || $settings->get( $env_key ) !== $value ) {
|
||||
$settings->set( $key, $value );
|
||||
$settings->set( $env_key, $value );
|
||||
$skip_persist = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $skip_persist ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$settings->set( 'products_dcc_enabled', null );
|
||||
|
||||
if ( ! $settings->persist() ) {
|
||||
return new \WP_Error(
|
||||
'woocommerce_paypal_payments_credentials_not_saved',
|
||||
__( 'An error occurred while saving the credentials.', 'woocommerce-paypal-payments' ),
|
||||
array(
|
||||
'status' => 500,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$webhook_registrar = $this->container->get( 'webhook.registrar' );
|
||||
$webhook_registrar->unregister();
|
||||
$webhook_registrar->register();
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends URL parameters stored in this class to a given URL.
|
||||
*
|
||||
* @hooked woocommerce_paypal_payments_partner_config_override_return_url - 10
|
||||
* @param string $url URL.
|
||||
* @return string The URL with the stored URL parameters added to it.
|
||||
*/
|
||||
public function add_args_to_return_url( $url ) {
|
||||
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.
|
||||
*
|
||||
* @param string $environment The environment to use. Either 'sandbox' or 'production'. Defaults to 'sandbox'.
|
||||
* @param array $url_args An array of URL arguments to add to the return URL via {@link add_query_arg()}.
|
||||
* @return string
|
||||
*/
|
||||
private function generate_signup_link( $environment = 'sandbox', $url_args = array() ) {
|
||||
$this->return_url_args = ( ! empty( $url_args ) && is_array( $url_args ) ) ? $url_args : array();
|
||||
|
||||
if ( $this->return_url_args ) {
|
||||
add_filter( 'woocommerce_paypal_payments_partner_config_override_return_url', array( $this, 'add_args_to_return_url' ) );
|
||||
}
|
||||
|
||||
$link = $this->container->get( 'onboarding.render' )->get_signup_link( 'production' === $environment );
|
||||
|
||||
if ( $this->return_url_args ) {
|
||||
remove_filter( 'woocommerce_paypal_payments_partner_config_override_return_url', array( $this, 'add_args_to_return_url' ) );
|
||||
$this->return_url_args = array();
|
||||
}
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
}
|
|
@ -41,7 +41,6 @@ class OnboardingModule implements ModuleInterface {
|
|||
* @param ContainerInterface|null $container The container.
|
||||
*/
|
||||
public function run( ContainerInterface $container = null ) {
|
||||
|
||||
$asset_loader = $container->get( 'onboarding.assets' );
|
||||
/**
|
||||
* The OnboardingAssets.
|
||||
|
@ -100,6 +99,10 @@ class OnboardingModule implements ModuleInterface {
|
|||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
|
||||
// Initialize REST routes at the appropriate time.
|
||||
$rest_controller = $container->get( 'onboarding.rest' );
|
||||
add_action( 'rest_api_init', array( $rest_controller, 'register_routes' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,6 +13,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail;
|
||||
|
@ -22,6 +23,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Checkout\DisableGateways;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||
use Woocommerce\PayPalCommerce\WcGateway\Helper\DccProductStatus;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice;
|
||||
|
@ -32,7 +34,6 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\SectionsRenderer;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer;
|
||||
use WpOop\TransientCache\CachePoolFactory;
|
||||
|
||||
return array(
|
||||
'wcgateway.paypal-gateway' => static function ( $container ): PayPalGateway {
|
||||
|
@ -44,6 +45,7 @@ return array(
|
|||
$session_handler = $container->get( 'session.handler' );
|
||||
$refund_processor = $container->get( 'wcgateway.processor.refunds' );
|
||||
$state = $container->get( 'onboarding.state' );
|
||||
$transaction_url_provider = $container->get( 'wcgateway.transaction-url-provider' );
|
||||
|
||||
return new PayPalGateway(
|
||||
$settings_renderer,
|
||||
|
@ -53,7 +55,8 @@ return array(
|
|||
$settings,
|
||||
$session_handler,
|
||||
$refund_processor,
|
||||
$state
|
||||
$state,
|
||||
$transaction_url_provider
|
||||
);
|
||||
},
|
||||
'wcgateway.credit-card-gateway' => static function ( $container ): CreditCardGateway {
|
||||
|
@ -66,6 +69,7 @@ return array(
|
|||
$session_handler = $container->get( 'session.handler' );
|
||||
$refund_processor = $container->get( 'wcgateway.processor.refunds' );
|
||||
$state = $container->get( 'onboarding.state' );
|
||||
$transaction_url_provider = $container->get( 'wcgateway.transaction-url-provider' );
|
||||
$payment_token_repository = $container->get( 'subscription.repository.payment-token' );
|
||||
$purchase_unit_factory = $container->get( 'api.factory.purchase-unit' );
|
||||
$payer_factory = $container->get( 'api.factory.payer' );
|
||||
|
@ -80,6 +84,7 @@ return array(
|
|||
$session_handler,
|
||||
$refund_processor,
|
||||
$state,
|
||||
$transaction_url_provider,
|
||||
$payment_token_repository,
|
||||
$purchase_unit_factory,
|
||||
$payer_factory,
|
||||
|
@ -139,7 +144,10 @@ return array(
|
|||
$order_factory = $container->get( 'api.factory.order' );
|
||||
$threed_secure = $container->get( 'button.helper.three-d-secure' );
|
||||
$authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$environment = $container->get( 'onboarding.environment' );
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
|
||||
return new OrderProcessor(
|
||||
$session_handler,
|
||||
$cart_repository,
|
||||
|
@ -148,7 +156,9 @@ return array(
|
|||
$order_factory,
|
||||
$threed_secure,
|
||||
$authorized_payments_processor,
|
||||
$settings
|
||||
$settings,
|
||||
$logger,
|
||||
$environment->current_environment_is( Environment::SANDBOX )
|
||||
);
|
||||
},
|
||||
'wcgateway.processor.refunds' => static function ( $container ): RefundProcessor {
|
||||
|
@ -648,6 +658,7 @@ return array(
|
|||
'mybank' => _x( 'MyBank', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
||||
'p24' => _x( 'Przelewy24', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
||||
'sofort' => _x( 'Sofort', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
||||
'venmo' => _x( 'Venmo', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
||||
),
|
||||
'screens' => array(
|
||||
State::STATE_PROGRESSIVE,
|
||||
|
@ -1847,6 +1858,28 @@ return array(
|
|||
$fields['message_cart_heading']['description'] = __( 'Display pay later messaging on your site for offers like Pay in 3, which lets customers pay with 3 interest-free monthly payments. We’ll show messages on your site to promote this feature for you. You may not promote pay later offers with any other content, marketing, or materials.', 'woocommerce-paypal-payments' );
|
||||
}
|
||||
|
||||
if ( 'FR' === $country ) {
|
||||
// todo: replace this with the text in English and use this text for French translation when it will be created.
|
||||
$french_pay_later_description = 'Affichez le Paiement en 4X PayPal sur votre site.' .
|
||||
'Le Paiement en 4X PayPal permet aux consommateurs français de payer en 4 versements égaux.' .
|
||||
'Vous pouvez promouvoir le Paiement en 4X PayPal uniquement si vous êtes un commerçant basé en France, ' .
|
||||
'avec un site internet en français et uneintégration PayPal standard. ' .
|
||||
'Les marchands ayantl’outil Vaulting(coffre-fort numérique) ou une intégration de paiements récurrents/abonnement, ' .
|
||||
'ainsi que ceux présentant certaines activités (vente de biens numériques / de biens non physiques) ' .
|
||||
'ne sont pas éligibles pour promouvoir le Paiement en 4X PayPal.' .
|
||||
'Nous afficherons des messages sur votre site pour promouvoir le Paiement en 4X PayPal. ' .
|
||||
'Vous ne pouvez pas promouvoir le Paiement en 4X PayPal avec un autre contenu, quel qu’il soit.';
|
||||
|
||||
$fields['message_heading']['heading'] = __( 'Pay Later Messaging on Checkout', 'woocommerce-paypal-payments' );
|
||||
$fields['message_heading']['description'] = $french_pay_later_description;
|
||||
|
||||
$fields['message_product_heading']['heading'] = __( 'Pay Later Messaging on Single Product Page', 'woocommerce-paypal-payments' );
|
||||
$fields['message_product_heading']['description'] = $french_pay_later_description;
|
||||
|
||||
$fields['message_cart_heading']['heading'] = __( 'Pay Later Messaging on Cart', 'woocommerce-paypal-payments' );
|
||||
$fields['message_cart_heading']['description'] = $french_pay_later_description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Pay Later link for DE
|
||||
*/
|
||||
|
@ -1908,6 +1941,22 @@ return array(
|
|||
$prefix
|
||||
);
|
||||
},
|
||||
|
||||
'wcgateway.transaction-url-sandbox' => static function ( $container ): string {
|
||||
return 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s';
|
||||
},
|
||||
|
||||
'wcgateway.transaction-url-live' => static function ( $container ): string {
|
||||
return 'https://www.paypal.com/cgi-bin/webscr?cmd=_view-a-trans&id=%s';
|
||||
},
|
||||
|
||||
'wcgateway.transaction-url-provider' => static function ( $container ): TransactionUrlProvider {
|
||||
$sandbox_url_base = $container->get( 'wcgateway.transaction-url-sandbox' );
|
||||
$live_url_base = $container->get( 'wcgateway.transaction-url-live' );
|
||||
|
||||
return new TransactionUrlProvider( $sandbox_url_base, $live_url_base );
|
||||
},
|
||||
|
||||
'wcgateway.helper.dcc-product-status' => static function ( $container ) : DccProductStatus {
|
||||
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
|
|
|
@ -31,6 +31,13 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
|
||||
const ID = 'ppcp-credit-card-gateway';
|
||||
|
||||
/**
|
||||
* Service to get transaction url for an order.
|
||||
*
|
||||
* @var TransactionUrlProvider
|
||||
*/
|
||||
protected $transaction_url_provider;
|
||||
|
||||
/**
|
||||
* The URL to the module.
|
||||
*
|
||||
|
@ -89,6 +96,7 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
|
||||
* @param PayerFactory $payer_factory The payer factory.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param TransactionUrlProvider $transaction_url_provider Service able to provide view transaction url base.
|
||||
*/
|
||||
public function __construct(
|
||||
SettingsRenderer $settings_renderer,
|
||||
|
@ -99,7 +107,8 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
string $module_url,
|
||||
SessionHandler $session_handler,
|
||||
RefundProcessor $refund_processor,
|
||||
State $state,
|
||||
State $state,
|
||||
TransactionUrlProvider $transaction_url_provider,
|
||||
PaymentTokenRepository $payment_token_repository,
|
||||
PurchaseUnitFactory $purchase_unit_factory,
|
||||
PayerFactory $payer_factory,
|
||||
|
@ -168,6 +177,7 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||
$this->payer_factory = $payer_factory;
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->transaction_url_provider = $transaction_url_provider;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -292,4 +302,17 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
}
|
||||
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the class property then call parent function.
|
||||
*
|
||||
* @param \WC_Order $order WC Order to get transaction url for.
|
||||
*
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function get_transaction_url( $order ): string {
|
||||
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||
|
||||
return parent::get_transaction_url( $order );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
||||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
|
||||
|
@ -27,10 +26,11 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
|
||||
use ProcessPaymentTrait;
|
||||
|
||||
const ID = 'ppcp-gateway';
|
||||
const CAPTURED_META_KEY = '_ppcp_paypal_captured';
|
||||
const INTENT_META_KEY = '_ppcp_paypal_intent';
|
||||
const ORDER_ID_META_KEY = '_ppcp_paypal_order_id';
|
||||
const ID = 'ppcp-gateway';
|
||||
const CAPTURED_META_KEY = '_ppcp_paypal_captured';
|
||||
const INTENT_META_KEY = '_ppcp_paypal_intent';
|
||||
const ORDER_ID_META_KEY = '_ppcp_paypal_order_id';
|
||||
const ORDER_PAYMENT_MODE_META_KEY = '_ppcp_paypal_payment_mode';
|
||||
|
||||
/**
|
||||
* The Settings Renderer.
|
||||
|
@ -74,6 +74,13 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
*/
|
||||
protected $session_handler;
|
||||
|
||||
/**
|
||||
* Service able to provide transaction url for an order.
|
||||
*
|
||||
* @var TransactionUrlProvider
|
||||
*/
|
||||
protected $transaction_url_provider;
|
||||
|
||||
/**
|
||||
* The Refund Processor.
|
||||
*
|
||||
|
@ -92,6 +99,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
* @param SessionHandler $session_handler The Session Handler.
|
||||
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||
* @param State $state The state.
|
||||
* @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order.
|
||||
*/
|
||||
public function __construct(
|
||||
SettingsRenderer $settings_renderer,
|
||||
|
@ -101,17 +109,19 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
ContainerInterface $config,
|
||||
SessionHandler $session_handler,
|
||||
RefundProcessor $refund_processor,
|
||||
State $state
|
||||
State $state,
|
||||
TransactionUrlProvider $transaction_url_provider
|
||||
) {
|
||||
|
||||
$this->id = self::ID;
|
||||
$this->order_processor = $order_processor;
|
||||
$this->authorized_payments = $authorized_payments_processor;
|
||||
$this->notice = $notice;
|
||||
$this->settings_renderer = $settings_renderer;
|
||||
$this->config = $config;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->refund_processor = $refund_processor;
|
||||
$this->id = self::ID;
|
||||
$this->order_processor = $order_processor;
|
||||
$this->authorized_payments = $authorized_payments_processor;
|
||||
$this->notice = $notice;
|
||||
$this->settings_renderer = $settings_renderer;
|
||||
$this->config = $config;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->refund_processor = $refund_processor;
|
||||
$this->transaction_url_provider = $transaction_url_provider;
|
||||
|
||||
if ( $state->current_state() === State::STATE_ONBOARDED ) {
|
||||
$this->supports = array( 'refunds' );
|
||||
|
@ -339,4 +349,17 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
}
|
||||
return $this->refund_processor->process( $order, (float) $amount, (string) $reason );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return transaction url for this gateway and given order.
|
||||
*
|
||||
* @param \WC_Order $order WC order to get transaction url by.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_transaction_url( $order ): string {
|
||||
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||
|
||||
return parent::get_transaction_url( $order );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
/**
|
||||
* Service able to provide transaction url base (URL with the placeholder instead of an actual transaction id)
|
||||
* based on the given WC Order.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcGateway\Gateway
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
||||
|
||||
/**
|
||||
* Class TransactionUrlProvider
|
||||
*/
|
||||
class TransactionUrlProvider {
|
||||
|
||||
/**
|
||||
* Transaction URL base used for sandbox payments.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $transaction_url_base_sandbox;
|
||||
|
||||
/**
|
||||
* Transaction URL base used for live payments.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $transaction_url_base_live;
|
||||
|
||||
/**
|
||||
* TransactionUrlProvider constructor.
|
||||
*
|
||||
* @param string $transaction_url_base_sandbox URL for sandbox orders.
|
||||
* @param string $transaction_url_base_live URL for live orders.
|
||||
*/
|
||||
public function __construct(
|
||||
string $transaction_url_base_sandbox,
|
||||
string $transaction_url_base_live
|
||||
) {
|
||||
|
||||
$this->transaction_url_base_sandbox = $transaction_url_base_sandbox;
|
||||
$this->transaction_url_base_live = $transaction_url_base_live;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return transaction url base
|
||||
*
|
||||
* @param \WC_Order $order WC order to get payment type from.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_transaction_url_base( \WC_Order $order ): string {
|
||||
$order_payment_mode = $order->get_meta( PayPalGateway::ORDER_PAYMENT_MODE_META_KEY, true );
|
||||
|
||||
return 'sandbox' === $order_payment_mode ? $this->transaction_url_base_sandbox : $this->transaction_url_base_live;
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* The WcGateway interface.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcGateway\Gateway
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
||||
|
||||
/**
|
||||
* Interface WcGatewayInterface
|
||||
*/
|
||||
interface WcGatewayInterface {
|
||||
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Processor;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
|
@ -25,6 +26,13 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
|||
*/
|
||||
class OrderProcessor {
|
||||
|
||||
/**
|
||||
* Whether current payment mode is sandbox.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $sandbox_mode;
|
||||
|
||||
/**
|
||||
* The Session Handler.
|
||||
*
|
||||
|
@ -88,6 +96,13 @@ class OrderProcessor {
|
|||
*/
|
||||
private $last_error = '';
|
||||
|
||||
/**
|
||||
* A logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* OrderProcessor constructor.
|
||||
*
|
||||
|
@ -99,6 +114,8 @@ class OrderProcessor {
|
|||
* @param ThreeDSecure $three_d_secure The ThreeDSecure Helper.
|
||||
* @param AuthorizedPaymentsProcessor $authorized_payments_processor The Authorized Payments Processor.
|
||||
* @param Settings $settings The Settings.
|
||||
* @param LoggerInterface $logger A logger service.
|
||||
* @param bool $sandbox_mode Whether sandbox mode enabled.
|
||||
*/
|
||||
public function __construct(
|
||||
SessionHandler $session_handler,
|
||||
|
@ -108,7 +125,9 @@ class OrderProcessor {
|
|||
OrderFactory $order_factory,
|
||||
ThreeDSecure $three_d_secure,
|
||||
AuthorizedPaymentsProcessor $authorized_payments_processor,
|
||||
Settings $settings
|
||||
Settings $settings,
|
||||
LoggerInterface $logger,
|
||||
bool $sandbox_mode
|
||||
) {
|
||||
|
||||
$this->session_handler = $session_handler;
|
||||
|
@ -119,6 +138,8 @@ class OrderProcessor {
|
|||
$this->threed_secure = $three_d_secure;
|
||||
$this->authorized_payments_processor = $authorized_payments_processor;
|
||||
$this->settings = $settings;
|
||||
$this->sandbox_mode = $sandbox_mode;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,9 +157,13 @@ class OrderProcessor {
|
|||
}
|
||||
$wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $order->id() );
|
||||
$wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() );
|
||||
$wc_order->update_meta_data(
|
||||
PayPalGateway::ORDER_PAYMENT_MODE_META_KEY,
|
||||
$this->sandbox_mode ? 'sandbox' : 'live'
|
||||
);
|
||||
|
||||
$error_message = null;
|
||||
if ( ! $order || ! $this->order_is_approved( $order ) ) {
|
||||
if ( ! $this->order_is_approved( $order ) ) {
|
||||
$error_message = __(
|
||||
'The payment has not been approved yet.',
|
||||
'woocommerce-paypal-payments'
|
||||
|
@ -163,6 +188,12 @@ class OrderProcessor {
|
|||
$wc_order->update_meta_data( PayPalGateway::CAPTURED_META_KEY, 'false' );
|
||||
}
|
||||
|
||||
$transaction_id = $this->get_paypal_order_transaction_id( $order );
|
||||
|
||||
if ( '' !== $transaction_id ) {
|
||||
$this->set_order_transaction_id( $transaction_id, $wc_order );
|
||||
}
|
||||
|
||||
$wc_order->update_status(
|
||||
'on-hold',
|
||||
__( 'Awaiting payment.', 'woocommerce-paypal-payments' )
|
||||
|
@ -187,6 +218,55 @@ class OrderProcessor {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set transaction id to WC order meta data.
|
||||
*
|
||||
* @param string $transaction_id Transaction id to set.
|
||||
* @param \WC_Order $wc_order Order to set transaction ID to.
|
||||
*/
|
||||
public function set_order_transaction_id( string $transaction_id, \WC_Order $wc_order ) {
|
||||
try {
|
||||
$wc_order->set_transaction_id( $transaction_id );
|
||||
} catch ( \WC_Data_Exception $exception ) {
|
||||
$this->logger->log(
|
||||
'warning',
|
||||
sprintf(
|
||||
'Failed to set transaction ID. Exception caught when tried: %1$s',
|
||||
$exception->getMessage()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve transaction id from PayPal order.
|
||||
*
|
||||
* @param Order $order Order to get transaction id from.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_paypal_order_transaction_id( Order $order ): string {
|
||||
$purchase_units = $order->purchase_units();
|
||||
|
||||
if ( ! isset( $purchase_units[0] ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$payments = $purchase_units[0]->payments();
|
||||
|
||||
if ( null === $payments ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$captures = $payments->captures();
|
||||
|
||||
if ( isset( $captures[0] ) ) {
|
||||
return $captures[0]->id();
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if an order should be captured immediately.
|
||||
*
|
||||
|
|
|
@ -69,7 +69,7 @@ class Settings implements ContainerInterface {
|
|||
*/
|
||||
public function persist() {
|
||||
|
||||
update_option( self::KEY, $this->settings );
|
||||
return update_option( self::KEY, $this->settings );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -117,10 +117,14 @@ class SettingsListener {
|
|||
$this->settings->set( 'merchant_email_production', $merchant_email );
|
||||
}
|
||||
$this->settings->persist();
|
||||
$redirect_url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' );
|
||||
|
||||
do_action( 'woocommerce_paypal_payments_onboarding_before_redirect' );
|
||||
|
||||
$redirect_url = apply_filters( 'woocommerce_paypal_payments_onboarding_redirect_url', admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' ) );
|
||||
if ( ! $this->settings->has( 'client_id' ) || ! $this->settings->get( 'client_id' ) ) {
|
||||
$redirect_url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-onboarding-error=1' );
|
||||
$redirect_url = add_query_arg( 'ppcp-onboarding-error', '1', $redirect_url );
|
||||
}
|
||||
|
||||
wp_safe_redirect( $redirect_url, 302 );
|
||||
exit;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "woocommerce-paypal-payments",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.1",
|
||||
"description": "WooCommerce PayPal Payments",
|
||||
"repository": "https://github.com/woocommerce/woocommerce-paypal-payments",
|
||||
"license": "GPL-2.0",
|
||||
|
|
11
readme.txt
11
readme.txt
|
@ -4,11 +4,11 @@ Tags: woocommerce, paypal, payments, ecommerce, e-commerce, store, sales, sell,
|
|||
Requires at least: 5.3
|
||||
Tested up to: 5.6
|
||||
Requires PHP: 7.0
|
||||
Stable tag: 1.1.0
|
||||
Stable tag: 1.2.1
|
||||
License: GPLv2
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
PayPal's latest payments processing solution. Accept PayPal, PayPal Credit, credit/debit cards, alternative digital wallets and bank accounts.
|
||||
PayPal's latest payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets and bank accounts.
|
||||
|
||||
== Description ==
|
||||
|
||||
|
@ -58,6 +58,13 @@ Follow the steps below to connect the plugin to your PayPal account:
|
|||
|
||||
== Changelog ==
|
||||
|
||||
= 1.2.1 =
|
||||
* Fix - Address compatibility issue with Jetpack.
|
||||
|
||||
= 1.2.0 =
|
||||
* Add - Rework onboarding code and add REST controller for integration with the OBW. #121
|
||||
* Fix - Remove spinner on click, on cancel and on error. #124
|
||||
|
||||
= 1.1.0 =
|
||||
* Add - Buy Now Pay Later for UK. #104
|
||||
* Add - DE now has 12 month installments. #106
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
||||
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
|
||||
class TransactionUrlProviderTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider getTransactionUrlDataProvider
|
||||
*/
|
||||
public function testGetTransactionUrlBase(
|
||||
string $sandboxUrl,
|
||||
string $liveUrl,
|
||||
string $orderPaymentMode,
|
||||
$expectedResult
|
||||
) {
|
||||
$testee = new TransactionUrlProvider($sandboxUrl, $liveUrl);
|
||||
|
||||
$wcOrder = \Mockery::mock(\WC_Order::class);
|
||||
|
||||
$wcOrder->expects('get_meta')
|
||||
->with(PayPalGateway::ORDER_PAYMENT_MODE_META_KEY, true)
|
||||
->andReturn($orderPaymentMode);
|
||||
|
||||
$this->assertSame($expectedResult, $testee->get_transaction_url_base($wcOrder));
|
||||
}
|
||||
|
||||
function getTransactionUrlDataProvider(): array
|
||||
{
|
||||
$sandboxUrl = 'sandbox.example.com';
|
||||
$liveUrl = 'example.com';
|
||||
|
||||
return [
|
||||
[
|
||||
$sandboxUrl, $liveUrl, 'sandbox', $sandboxUrl
|
||||
],
|
||||
[
|
||||
$sandboxUrl, $liveUrl, 'live', $liveUrl
|
||||
],
|
||||
[
|
||||
$sandboxUrl, $liveUrl, '', $liveUrl
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
||||
|
||||
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
|
@ -45,6 +44,7 @@ class WcGatewayTest extends TestCase
|
|||
$settings
|
||||
->shouldReceive('has')->andReturnFalse();
|
||||
$refundProcessor = Mockery::mock(RefundProcessor::class);
|
||||
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
|
||||
$state = Mockery::mock(State::class);
|
||||
$state
|
||||
->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
|
||||
|
@ -56,7 +56,8 @@ class WcGatewayTest extends TestCase
|
|||
$settings,
|
||||
$sessionHandler,
|
||||
$refundProcessor,
|
||||
$state
|
||||
$state,
|
||||
$transactionUrlProvider
|
||||
);
|
||||
|
||||
expect('wc_get_order')
|
||||
|
@ -86,6 +87,7 @@ class WcGatewayTest extends TestCase
|
|||
$sessionHandler = Mockery::mock(SessionHandler::class);
|
||||
$refundProcessor = Mockery::mock(RefundProcessor::class);
|
||||
$state = Mockery::mock(State::class);
|
||||
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
|
||||
$state
|
||||
->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
|
||||
$testee = new PayPalGateway(
|
||||
|
@ -96,7 +98,8 @@ class WcGatewayTest extends TestCase
|
|||
$settings,
|
||||
$sessionHandler,
|
||||
$refundProcessor,
|
||||
$state
|
||||
$state,
|
||||
$transactionUrlProvider
|
||||
);
|
||||
|
||||
expect('wc_get_order')
|
||||
|
@ -132,6 +135,7 @@ class WcGatewayTest extends TestCase
|
|||
$sessionHandler = Mockery::mock(SessionHandler::class);
|
||||
$refundProcessor = Mockery::mock(RefundProcessor::class);
|
||||
$state = Mockery::mock(State::class);
|
||||
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
|
||||
$state
|
||||
->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
|
||||
$testee = new PayPalGateway(
|
||||
|
@ -142,7 +146,8 @@ class WcGatewayTest extends TestCase
|
|||
$settings,
|
||||
$sessionHandler,
|
||||
$refundProcessor,
|
||||
$state
|
||||
$state,
|
||||
$transactionUrlProvider
|
||||
);
|
||||
|
||||
expect('wc_get_order')
|
||||
|
@ -193,6 +198,7 @@ class WcGatewayTest extends TestCase
|
|||
$sessionHandler = Mockery::mock(SessionHandler::class);
|
||||
$refundProcessor = Mockery::mock(RefundProcessor::class);
|
||||
$state = Mockery::mock(State::class);
|
||||
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
|
||||
$state
|
||||
->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
|
||||
$testee = new PayPalGateway(
|
||||
|
@ -203,7 +209,8 @@ class WcGatewayTest extends TestCase
|
|||
$settings,
|
||||
$sessionHandler,
|
||||
$refundProcessor,
|
||||
$state
|
||||
$state,
|
||||
$transactionUrlProvider
|
||||
);
|
||||
|
||||
$this->assertTrue($testee->capture_authorized_payment($wcOrder));
|
||||
|
@ -246,6 +253,7 @@ class WcGatewayTest extends TestCase
|
|||
$sessionHandler = Mockery::mock(SessionHandler::class);
|
||||
$refundProcessor = Mockery::mock(RefundProcessor::class);
|
||||
$state = Mockery::mock(State::class);
|
||||
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
|
||||
$state
|
||||
->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
|
||||
$testee = new PayPalGateway(
|
||||
|
@ -256,7 +264,8 @@ class WcGatewayTest extends TestCase
|
|||
$settings,
|
||||
$sessionHandler,
|
||||
$refundProcessor,
|
||||
$state
|
||||
$state,
|
||||
$transactionUrlProvider
|
||||
);
|
||||
|
||||
$this->assertTrue($testee->capture_authorized_payment($wcOrder));
|
||||
|
@ -292,6 +301,7 @@ class WcGatewayTest extends TestCase
|
|||
$sessionHandler = Mockery::mock(SessionHandler::class);
|
||||
$refundProcessor = Mockery::mock(RefundProcessor::class);
|
||||
$state = Mockery::mock(State::class);
|
||||
$transactionUrlProvider = Mockery::mock(TransactionUrlProvider::class);
|
||||
$state
|
||||
->shouldReceive('current_state')->andReturn(State::STATE_ONBOARDED);
|
||||
$testee = new PayPalGateway(
|
||||
|
@ -302,7 +312,8 @@ class WcGatewayTest extends TestCase
|
|||
$settings,
|
||||
$sessionHandler,
|
||||
$refundProcessor,
|
||||
$state
|
||||
$state,
|
||||
$transactionUrlProvider
|
||||
);
|
||||
|
||||
$this->assertFalse($testee->capture_authorized_payment($wcOrder));
|
||||
|
@ -325,4 +336,4 @@ class WcGatewayTest extends TestCase
|
|||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,14 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\WcGateway\Processor;
|
||||
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
||||
use Woocommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure;
|
||||
|
@ -15,14 +19,32 @@ use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
|||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\WooCommerce\Logging\WooCommerceLoggingModule;
|
||||
use Mockery;
|
||||
|
||||
class OrderProcessorTest extends TestCase
|
||||
{
|
||||
|
||||
public function testAuthorize() {
|
||||
$transactionId = 'ABC123';
|
||||
|
||||
$capture = Mockery::mock(Capture::class);
|
||||
$capture->expects('id')
|
||||
->andReturn($transactionId);
|
||||
|
||||
$payments = Mockery::mock(Payments::class);
|
||||
$payments->expects('captures')
|
||||
->andReturn([$capture]);
|
||||
|
||||
$purchaseUnit = Mockery::mock(PurchaseUnit::class);
|
||||
$purchaseUnit->expects('payments')
|
||||
->andReturn($payments);
|
||||
|
||||
$wcOrder = Mockery::mock(\WC_Order::class);
|
||||
$wcOrder->expects('update_meta_data')
|
||||
->with(PayPalGateway::ORDER_PAYMENT_MODE_META_KEY, 'live');
|
||||
$wcOrder->expects('set_transaction_id')
|
||||
->with($transactionId);
|
||||
|
||||
$orderStatus = Mockery::mock(OrderStatus::class);
|
||||
$orderStatus
|
||||
->expects('is')
|
||||
|
@ -32,8 +54,10 @@ class OrderProcessorTest extends TestCase
|
|||
->expects('is')
|
||||
->with(OrderStatus::COMPLETED)
|
||||
->andReturn(true);
|
||||
|
||||
$orderId = 'abc';
|
||||
$orderIntent = 'AUTHORIZE';
|
||||
|
||||
$currentOrder = Mockery::mock(Order::class);
|
||||
$currentOrder
|
||||
->expects('id')
|
||||
|
@ -44,13 +68,18 @@ class OrderProcessorTest extends TestCase
|
|||
$currentOrder
|
||||
->shouldReceive('status')
|
||||
->andReturn($orderStatus);
|
||||
$currentOrder->expects('purchase_units')
|
||||
->andReturn([$purchaseUnit]);
|
||||
|
||||
$sessionHandler = Mockery::mock(SessionHandler::class);
|
||||
$sessionHandler
|
||||
->expects('order')
|
||||
->andReturn($currentOrder);
|
||||
$sessionHandler
|
||||
->expects('destroy_session_data');
|
||||
|
||||
$cartRepository = Mockery::mock(CartRepository::class);
|
||||
|
||||
$orderEndpoint = Mockery::mock(OrderEndpoint::class);
|
||||
$orderEndpoint
|
||||
->expects('patch_order_with')
|
||||
|
@ -60,19 +89,26 @@ class OrderProcessorTest extends TestCase
|
|||
->expects('authorize')
|
||||
->with($currentOrder)
|
||||
->andReturn($currentOrder);
|
||||
|
||||
$paymentsEndpoint = Mockery::mock(PaymentsEndpoint::class);
|
||||
|
||||
$orderFactory = Mockery::mock(OrderFactory::class);
|
||||
$orderFactory
|
||||
->expects('from_wc_order')
|
||||
->with($wcOrder, $currentOrder)
|
||||
->andReturn($currentOrder);
|
||||
|
||||
$threeDSecure = Mockery::mock(ThreeDSecure::class);
|
||||
|
||||
$authorizedPaymentProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class);
|
||||
|
||||
$settings = Mockery::mock(Settings::class);
|
||||
$settings
|
||||
->shouldReceive('has')
|
||||
->andReturnFalse();
|
||||
|
||||
$logger = Mockery::mock(LoggerInterface::class);
|
||||
|
||||
$testee = new OrderProcessor(
|
||||
$sessionHandler,
|
||||
$cartRepository,
|
||||
|
@ -81,7 +117,9 @@ class OrderProcessorTest extends TestCase
|
|||
$orderFactory,
|
||||
$threeDSecure,
|
||||
$authorizedPaymentProcessor,
|
||||
$settings
|
||||
$settings,
|
||||
$logger,
|
||||
false
|
||||
);
|
||||
|
||||
$cart = Mockery::mock(\WC_Cart::class);
|
||||
|
@ -115,6 +153,20 @@ class OrderProcessorTest extends TestCase
|
|||
}
|
||||
|
||||
public function testCapture() {
|
||||
$transactionId = 'ABC123';
|
||||
|
||||
$capture = Mockery::mock(Capture::class);
|
||||
$capture->expects('id')
|
||||
->andReturn($transactionId);
|
||||
|
||||
$payments = Mockery::mock(Payments::class);
|
||||
$payments->expects('captures')
|
||||
->andReturn([$capture]);
|
||||
|
||||
$purchaseUnit = Mockery::mock(PurchaseUnit::class);
|
||||
$purchaseUnit->expects('payments')
|
||||
->andReturn($payments);
|
||||
|
||||
$wcOrder = Mockery::mock(\WC_Order::class);
|
||||
$orderStatus = Mockery::mock(OrderStatus::class);
|
||||
$orderStatus
|
||||
|
@ -137,6 +189,9 @@ class OrderProcessorTest extends TestCase
|
|||
$currentOrder
|
||||
->shouldReceive('status')
|
||||
->andReturn($orderStatus);
|
||||
$currentOrder
|
||||
->expects('purchase_units')
|
||||
->andReturn([$purchaseUnit]);
|
||||
$sessionHandler = Mockery::mock(SessionHandler::class);
|
||||
$sessionHandler
|
||||
->expects('order')
|
||||
|
@ -166,7 +221,10 @@ class OrderProcessorTest extends TestCase
|
|||
->shouldReceive('has')
|
||||
->andReturnFalse();
|
||||
|
||||
$testee = new OrderProcessor(
|
||||
$logger = Mockery::mock(LoggerInterface::class);
|
||||
|
||||
|
||||
$testee = new OrderProcessor(
|
||||
$sessionHandler,
|
||||
$cartRepository,
|
||||
$orderEndpoint,
|
||||
|
@ -174,7 +232,9 @@ class OrderProcessorTest extends TestCase
|
|||
$orderFactory,
|
||||
$threeDSecure,
|
||||
$authorizedPaymentProcessor,
|
||||
$settings
|
||||
$settings,
|
||||
$logger,
|
||||
false
|
||||
);
|
||||
|
||||
$cart = Mockery::mock(\WC_Cart::class);
|
||||
|
@ -198,6 +258,10 @@ class OrderProcessorTest extends TestCase
|
|||
$wcOrder
|
||||
->expects('update_status')
|
||||
->with('on-hold', 'Awaiting payment.');
|
||||
$wcOrder->expects('update_meta_data')
|
||||
->with(PayPalGateway::ORDER_PAYMENT_MODE_META_KEY, 'live');
|
||||
$wcOrder->expects('set_transaction_id')
|
||||
->with($transactionId);
|
||||
$wcOrder
|
||||
->expects('update_status')
|
||||
->with('processing', 'Payment received.');
|
||||
|
@ -205,7 +269,26 @@ class OrderProcessorTest extends TestCase
|
|||
}
|
||||
|
||||
public function testError() {
|
||||
$transactionId = 'ABC123';
|
||||
|
||||
$capture = Mockery::mock(Capture::class);
|
||||
$capture->shouldReceive('id')
|
||||
->andReturn($transactionId);
|
||||
|
||||
$payments = Mockery::mock(Payments::class);
|
||||
$payments->shouldReceive('captures')
|
||||
->andReturn([$capture]);
|
||||
|
||||
$purchaseUnit = Mockery::mock(PurchaseUnit::class);
|
||||
$purchaseUnit->shouldReceive('payments')
|
||||
->andReturn($payments);
|
||||
|
||||
$wcOrder = Mockery::mock(\WC_Order::class);
|
||||
$wcOrder->expects('update_meta_data')
|
||||
->with(PayPalGateway::ORDER_PAYMENT_MODE_META_KEY, 'live');
|
||||
$wcOrder->shouldReceive('set_transaction_id')
|
||||
->with($transactionId);
|
||||
|
||||
$orderStatus = Mockery::mock(OrderStatus::class);
|
||||
$orderStatus
|
||||
->expects('is')
|
||||
|
@ -226,6 +309,9 @@ class OrderProcessorTest extends TestCase
|
|||
$currentOrder
|
||||
->shouldReceive('payment_source')
|
||||
->andReturnNull();
|
||||
$currentOrder
|
||||
->shouldReceive('purchase_units')
|
||||
->andReturn([$purchaseUnit]);
|
||||
$sessionHandler = Mockery::mock(SessionHandler::class);
|
||||
$sessionHandler
|
||||
->expects('order')
|
||||
|
@ -238,7 +324,9 @@ class OrderProcessorTest extends TestCase
|
|||
$authorizedPaymentProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class);
|
||||
$settings = Mockery::mock(Settings::class);
|
||||
|
||||
$testee = new OrderProcessor(
|
||||
$logger = Mockery::mock(LoggerInterface::class);
|
||||
|
||||
$testee = new OrderProcessor(
|
||||
$sessionHandler,
|
||||
$cartRepository,
|
||||
$orderEndpoint,
|
||||
|
@ -246,7 +334,9 @@ class OrderProcessorTest extends TestCase
|
|||
$orderFactory,
|
||||
$threeDSecure,
|
||||
$authorizedPaymentProcessor,
|
||||
$settings
|
||||
$settings,
|
||||
$logger,
|
||||
false
|
||||
);
|
||||
|
||||
$cart = Mockery::mock(\WC_Cart::class);
|
||||
|
@ -270,4 +360,4 @@ class OrderProcessorTest extends TestCase
|
|||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
/**
|
||||
* Plugin Name: WooCommerce PayPal Payments
|
||||
* Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/
|
||||
* Description: PayPal's latest complete payments processing solution. Accept PayPal, PayPal Credit, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage.
|
||||
* Version: 1.1.0
|
||||
* Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage.
|
||||
* Version: 1.2.1
|
||||
* Author: WooCommerce
|
||||
* Author URI: https://woocommerce.com/
|
||||
* License: GPL-2.0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue