Fix merge conflict

This commit is contained in:
dinamiko 2022-09-14 12:22:46 +02:00
commit e4e968a823
57 changed files with 6080 additions and 1624 deletions

View file

@ -1,5 +1,20 @@
*** Changelog ***
= 1.9.3 - 2022-08-31 =
* Add - Tracking API #792
* Fix - Improve compatibility with Siteground Optimizer plugin #797
* Fix - Transaction ID in order not updated when manually capturing authorized payment from WC #766
* Fix - Failed form validation on Checkout page causing page to be sticky #781
* Fix - Do not include full path in exception #779
* Fix - PUI conflict with Germanized plugin and taxes #808
* Enhancement - Enable ACDC by default only in locations where WooCommerce Payments is not available #799
* Enhancement - Add links to docs & support in plugin #782
* Enhancement - Put gateway sub-options into tabs #772
* Enhancement - Show tabs only after onboarding #789
* Enhancement - Add header on settings page #790
* Enhancement - PUI add option for a phone number field next to the Birth Date field #742
* Enhancement - PUI gateway availability on pay for order page with unsupported currency #744
= 1.9.2 - 2022-08-09 =
* Fix - Do not allow birth date older than 100 years for PUI. #743
* Fix - Store the customer id for vaulted payment method in usermeta to not lose vaulted methods after the invoice prefix change. #698

View file

@ -24,6 +24,7 @@ return function ( string $root_dir ): iterable {
( require "$modules_dir/ppcp-wc-gateway/module.php" )(),
( require "$modules_dir/ppcp-webhooks/module.php" )(),
( require "$modules_dir/ppcp-vaulting/module.php" )(),
( require "$modules_dir/ppcp-order-tracking/module.php" )(),
);
return $modules;

View file

@ -12,8 +12,16 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
use Psr\Log\LoggerInterface;
use RuntimeException;
use stdClass;
use WC_Customer;
use WC_Order;
use WC_Order_Item_Fee;
use WC_Order_Item_Product;
use WC_Product;
use WC_Tax;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Item;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
@ -92,18 +100,19 @@ class PayUponInvoiceOrderEndpoint {
*
* @param PurchaseUnit[] $items The purchase unit items for the order.
* @param PaymentSource $payment_source The payment source.
* @param WC_Order $wc_order The WC order.
* @return Order
* @throws RuntimeException When there is a problem with the payment source.
* @throws PayPalApiException When there is a problem creating the order.
*/
public function create( array $items, PaymentSource $payment_source ): Order {
public function create( array $items, PaymentSource $payment_source, WC_Order $wc_order ): Order {
$data = array(
'intent' => 'CAPTURE',
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
'purchase_units' => array_map(
static function ( PurchaseUnit $item ): array {
return $item->to_array();
return $item->to_array( false );
},
$items
),
@ -112,8 +121,7 @@ class PayUponInvoiceOrderEndpoint {
),
);
$data = $this->ensure_tax( $data );
$data = $this->ensure_tax_rate( $data );
$data = $this->ensure_taxes( $wc_order, $data );
$data = $this->ensure_shipping( $data, $payment_source->to_array() );
$bearer = $this->bearer->bearer();
@ -195,45 +203,6 @@ class PayUponInvoiceOrderEndpoint {
return $json;
}
/**
* Ensures items contains tax.
*
* @param array $data The data.
* @return array
*/
private function ensure_tax( array $data ): array {
$items_count = count( $data['purchase_units'][0]['items'] );
for ( $i = 0; $i < $items_count; $i++ ) {
if ( ! isset( $data['purchase_units'][0]['items'][ $i ]['tax'] ) ) {
$data['purchase_units'][0]['items'][ $i ]['tax'] = array(
'currency_code' => 'EUR',
'value' => '0.00',
);
}
}
return $data;
}
/**
* Ensures items contains tax rate.
*
* @param array $data The data.
* @return array
*/
private function ensure_tax_rate( array $data ): array {
$items_count = count( $data['purchase_units'][0]['items'] );
for ( $i = 0; $i < $items_count; $i++ ) {
if ( ! isset( $data['purchase_units'][0]['items'][ $i ]['tax_rate'] ) ) {
$data['purchase_units'][0]['items'][ $i ]['tax_rate'] = '0.00';
}
}
return $data;
}
/**
* Ensures purchase units contains shipping by using payment source data.
*
@ -255,4 +224,51 @@ class PayUponInvoiceOrderEndpoint {
return $data;
}
/**
* Ensure items contains taxes.
*
* @param WC_Order $wc_order The WC order.
* @param array $data The data.
* @return array
*/
private function ensure_taxes( WC_Order $wc_order, array $data ): array {
$tax_total = $data['purchase_units'][0]['amount']['breakdown']['tax_total']['value'];
$item_total = $data['purchase_units'][0]['amount']['breakdown']['item_total']['value'];
$shipping = $data['purchase_units'][0]['amount']['breakdown']['shipping']['value'];
$order_tax_total = $wc_order->get_total_tax();
$tax_rate = round( ( $order_tax_total / $item_total ) * 100, 1 );
$item_name = $data['purchase_units'][0]['items'][0]['name'];
$item_currency = $data['purchase_units'][0]['items'][0]['unit_amount']['currency_code'];
$item_description = $data['purchase_units'][0]['items'][0]['description'];
$item_sku = $data['purchase_units'][0]['items'][0]['sku'];
unset( $data['purchase_units'][0]['items'] );
$data['purchase_units'][0]['items'][0] = array(
'name' => $item_name,
'unit_amount' => array(
'currency_code' => $item_currency,
'value' => $item_total,
),
'quantity' => 1,
'description' => $item_description,
'sku' => $item_sku,
'category' => 'PHYSICAL_GOODS',
'tax' => array(
'currency_code' => 'EUR',
'value' => $tax_total,
),
'tax_rate' => number_format( $tax_rate, 2, '.', '' ),
);
$total_amount = $data['purchase_units'][0]['amount']['value'];
$breakdown_total = $item_total + $tax_total + $shipping;
$diff = round( $total_amount - $breakdown_total, 2 );
if ( $diff === -0.01 || $diff === 0.01 ) {
$data['purchase_units'][0]['amount']['value'] = number_format( $breakdown_total, 2, '.', '' );
}
return $data;
}
}

View file

@ -268,9 +268,11 @@ class PurchaseUnit {
/**
* Returns the object as array.
*
* @param bool $ditch_items_when_mismatch Whether ditch items when mismatch or not.
*
* @return array
*/
public function to_array(): array {
public function to_array( bool $ditch_items_when_mismatch = true ): array {
$purchase_unit = array(
'reference_id' => $this->reference_id(),
'amount' => $this->amount()->to_array(),
@ -282,7 +284,7 @@ class PurchaseUnit {
$this->items()
),
);
if ( $this->ditch_items_when_mismatch( $this->amount(), ...$this->items() ) ) {
if ( $ditch_items_when_mismatch && $this->ditch_items_when_mismatch( $this->amount(), ...$this->items() ) ) {
unset( $purchase_unit['items'] );
unset( $purchase_unit['amount']['breakdown'] );
}

View file

@ -140,4 +140,24 @@ class Token {
}
return true;
}
/**
* Checks if tracking is available in access token scope.
*
* @return bool Whether tracking features are enabled or not.
*/
public function is_tracking_available(): bool {
if ( ! isset( $this->json->scope ) ) {
return false;
}
if ( strpos(
$this->json->scope,
'https://uri.paypal.com/services/shipping/trackers/readwrite'
) !== false ) {
return true;
}
return false;
}
}

View file

@ -77,6 +77,18 @@ class DccApplies {
return $applies;
}
/**
* Returns whether WooCommerce Payments plugin is available for the store country.
*
* @return bool
*/
public function for_wc_payments(): bool {
$countries = array_keys( $this->allowed_country_currency_matrix );
array_push( $countries, 'AT', 'BE', 'HK', 'IE', 'NL', 'PL', 'PT', 'SG', 'CH' );
return in_array( $this->country, $countries, true );
}
/**
* Returns credit cards, which can be used.
*

View file

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

View file

@ -7,16 +7,15 @@
"deepmerge": "^4.2.2"
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"babel-loader": "^8.1.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"@babel/core": "^7.19",
"@babel/preset-env": "^7.19",
"babel-loader": "^8.2",
"cross-env": "^7.0.3",
"file-loader": "^6.2.0",
"sass": "^1.42.1",
"sass-loader": "^12.1.0",
"webpack": "^5.55.0",
"webpack-cli": "^4.8.0"
"webpack": "^5.74",
"webpack-cli": "^4.10"
},
"scripts": {
"build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",

View file

@ -66,7 +66,7 @@ const bootstrap = () => {
errorHandler.clear();
if (messages.length) {
messages.forEach(s => errorHandler.message(s));
errorHandler.messages(messages);
} else {
errorHandler.message(PayPalCommerceGateway.labels.error.required.generic);
}

View file

@ -17,21 +17,48 @@ class ErrorHandler {
appendPreparedErrorMessageElement(errorMessageElement)
{
if(this.messagesList === null) {
this.prepareMessagesList();
if (this.messagesList === null) {
this._prepareMessagesList();
}
this.messagesList.replaceWith(errorMessageElement);
}
/**
* @param {String} text
* @param {Boolean} persist
*/
message(text, persist = false)
{
if(! typeof String || text.length === 0){
this._addMessage(text, persist);
this._scrollToMessages();
}
/**
* @param {Array} texts
* @param {Boolean} persist
*/
messages(texts, persist = false)
{
texts.forEach(t => this._addMessage(t, persist));
this._scrollToMessages();
}
/**
* @private
* @param {String} text
* @param {Boolean} persist
*/
_addMessage(text, persist = false)
{
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 (this.messagesList === null){
this._prepareMessagesList();
}
if (persist) {
@ -40,15 +67,24 @@ class ErrorHandler {
this.wrapper.classList.remove('ppcp-persist');
}
let messageNode = this.prepareMessagesListItem(text);
let messageNode = this._prepareMessagesListItem(text);
this.messagesList.appendChild(messageNode);
jQuery.scroll_to_notices(jQuery('.woocommerce-notices-wrapper'))
}
prepareMessagesList()
/**
* @private
*/
_scrollToMessages()
{
if(this.messagesList === null){
jQuery.scroll_to_notices(jQuery('.woocommerce-notices-wrapper'));
}
/**
* @private
*/
_prepareMessagesList()
{
if (this.messagesList === null) {
this.messagesList = document.createElement('ul');
this.messagesList.setAttribute('class', 'woocommerce-error');
this.messagesList.setAttribute('role', 'alert');
@ -56,7 +92,10 @@ class ErrorHandler {
}
}
prepareMessagesListItem(message)
/**
* @private
*/
_prepareMessagesListItem(message)
{
const li = document.createElement('li');
li.innerHTML = message;
@ -64,13 +103,6 @@ class ErrorHandler {
return li;
}
sanitize(text)
{
const textarea = document.createElement('textarea');
textarea.innerHTML = text;
return textarea.value.replace('Error: ', '');
}
clear()
{
if (this.messagesList === null) {

View file

@ -233,7 +233,10 @@ class CreateOrderEndpoint implements EndpointInterface {
$this->set_bn_code( $data );
if ( 'checkout' === $data['context'] ) {
if ( 'pay-now' === $data['context'] && get_option( 'woocommerce_terms_page_id', '' ) !== '' ) {
$this->validate_paynow_form( $data['form'] );
}
try {
$order = $this->create_paypal_order( $wc_order );
} catch ( Exception $exception ) {
@ -241,6 +244,7 @@ class CreateOrderEndpoint implements EndpointInterface {
throw $exception;
}
if ( 'checkout' === $data['context'] ) {
if (
! $this->early_order_handler->should_create_early_order()
|| $this->registration_needed
@ -251,12 +255,6 @@ class CreateOrderEndpoint implements EndpointInterface {
$this->early_order_handler->register_for_order( $order );
}
if ( 'pay-now' === $data['context'] && get_option( 'woocommerce_terms_page_id', '' ) !== '' ) {
$this->validate_paynow_form( $data['form'] );
}
$order = $this->create_paypal_order( $wc_order );
if ( 'pay-now' === $data['context'] && is_a( $wc_order, \WC_Order::class ) ) {
$wc_order->update_meta_data( PayPalGateway::ORDER_ID_META_KEY, $order->id() );
$wc_order->update_meta_data( PayPalGateway::INTENT_META_KEY, $order->intent() );

File diff suppressed because it is too large Load diff

View file

@ -32,10 +32,22 @@ return array(
return new PPEC\SubscriptionsHandler( $ppcp_renewal_handler, $gateway );
},
'compat.ppec.settings_importer' => static function( $container ) : PPEC\SettingsImporter {
'compat.ppec.settings_importer' => static function( ContainerInterface $container ) : PPEC\SettingsImporter {
$settings = $container->get( 'wcgateway.settings' );
return new PPEC\SettingsImporter( $settings );
},
'compat.plugin-script-names' => static function( ContainerInterface $container ) : array {
return array(
'ppcp-smart-button',
'ppcp-oxxo',
'ppcp-pay-upon-invoice',
'ppcp-vaulting-myaccount-payments',
'ppcp-gateway-settings',
'ppcp-webhooks-status-page',
'ppcp-tracking',
);
},
);

View file

@ -33,12 +33,11 @@ class CompatModule implements ModuleInterface {
}
/**
* Run the compatibility module.
*
* @param ContainerInterface|null $c The Container.
* {@inheritDoc}
*/
public function run( ContainerInterface $c ): void {
$this->initialize_ppec_compat_layer( $c );
$this->fix_site_ground_optimizer_compatibility( $c );
}
/**
@ -52,10 +51,10 @@ class CompatModule implements ModuleInterface {
/**
* Sets up the PayPal Express Checkout compatibility layer.
*
* @param ContainerInterface|null $container The Container.
* @param ContainerInterface $container The Container.
* @return void
*/
private function initialize_ppec_compat_layer( $container ): void {
private function initialize_ppec_compat_layer( ContainerInterface $container ): void {
// Process PPEC subscription renewals through PayPal Payments.
$handler = $container->get( 'compat.ppec.subscriptions-handler' );
$handler->maybe_hook();
@ -76,4 +75,20 @@ class CompatModule implements ModuleInterface {
}
/**
* Fixes the compatibility issue for <a href="https://wordpress.org/plugins/sg-cachepress/">SiteGround Optimizer plugin</a>.
*
* @link https://wordpress.org/plugins/sg-cachepress/
*
* @param ContainerInterface $c The Container.
*/
protected function fix_site_ground_optimizer_compatibility( ContainerInterface $c ): void {
$ppcp_script_names = $c->get( 'compat.plugin-script-names' );
add_filter(
'sgo_js_minify_exclude',
function ( array $scripts ) use ( $ppcp_script_names ) {
return array_merge( $scripts, $ppcp_script_names );
}
);
}
}

View file

@ -55,6 +55,7 @@ ul.ppcp-onboarding-options, ul.ppcp-onboarding-options-sublist {
ul.ppcp-onboarding-options-sublist {
margin-left: 15px;
margin-top: 15px;
}
.ppcp-muted-text {
@ -168,3 +169,53 @@ ul.ppcp-onboarding-options-sublist {
height: 23px;
}
}
.ppcp-settings-page-header {
display: flex;
align-items: center;
max-width: 1200px;
margin-top: 10px;
}
.ppcp-settings-page-header img {
height: 30px;
}
.ppcp-settings-page-header h4 {
margin: 0 15px 0 5px;
}
.ppcp-settings-page-header .button, .ppcp-settings-page-header a {
margin: 0 5px;
}
.ppcp-right-align {
margin-left: auto;
}
.ppcp-settings-page-header a {
text-decoration: none;
}
@media (max-width: 1200px) {
.ppcp-settings-page-header {
display: block;
}
.ppcp-settings-page-header .ppcp-right-align {
display: block;
margin-left: 0;
}
.ppcp-settings-page-header .button, .ppcp-settings-page-header a {
margin: 5px 10px 5px 0;
}
.ppcp-settings-page-header .ppcp-inline-only {
display: none;
}
.ppcp-settings-page-header h4 {
margin-left: 0;
}
}

View file

@ -158,6 +158,8 @@ function ppcp_onboarding_productionCallback(...args) {
input.disabled = !cardsChk.checked;
});
document.querySelector('.ppcp-onboarding-cards-options').style.display = !cardsChk.checked ? 'none' : '';
const basicRb = document.querySelector('#ppcp-onboarding-dcc-basic');
const isExpress = !cardsChk.checked || basicRb.checked;
@ -245,6 +247,8 @@ function ppcp_onboarding_productionCallback(...args) {
}
);
sandboxSwitchElement.checked = ! sandboxSwitchElement.checked;
isDisconnecting = true;
document.querySelector('.woocommerce-save-button').click();

View file

@ -13,6 +13,7 @@ use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
use WooCommerce\PayPalCommerce\Onboarding\Environment;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
/**
* Class OnboardingAssets
@ -172,6 +173,6 @@ class OnboardingAssets {
* @return bool
*/
private function should_render_onboarding_script(): bool {
return PayPalGateway::ID === $this->page_id;
return PayPalGateway::ID === $this->page_id || Settings::CONNECTION_TAB_ID === $this->page_id;
}
}

View file

@ -56,6 +56,7 @@ class OnboardingOptionsRenderer {
* @param bool $is_shop_supports_dcc Whether the shop can use DCC (country, currency).
*/
public function render( bool $is_shop_supports_dcc ): string {
$checked = $is_shop_supports_dcc ? '' : 'checked';
return '
<ul class="ppcp-onboarding-options">
<li>
@ -64,9 +65,7 @@ class OnboardingOptionsRenderer {
</label>
</li>
<li>
<label><input type="checkbox" id="ppcp-onboarding-accept-cards" checked> ' .
__( 'Securely accept all major credit & debit cards on the strength of the PayPal network', 'woocommerce-paypal-payments' ) . '
</label>
<label><input type="checkbox" id="ppcp-onboarding-accept-cards" ' . $checked . '> ' . __( 'Securely accept all major credit & debit cards on the strength of the PayPal network', 'woocommerce-paypal-payments' ) . '</label>
</li>
<li>' . $this->render_dcc( $is_shop_supports_dcc ) . '</li>' .
$this->render_pui_option()
@ -103,6 +102,44 @@ class OnboardingOptionsRenderer {
$is_us_shop = 'US' === $this->country;
$basic_table_rows = array(
$this->render_table_row(
__( 'Credit & Debit Card form fields', 'woocommerce-paypal-payments' ),
__( 'Prebuilt user experience', 'woocommerce-paypal-payments' )
),
! $is_us_shop ? '' : $this->render_table_row(
__( 'Credit & Debit Card pricing', 'woocommerce-paypal-payments' ),
__( '3.49% + $0.49', 'woocommerce-paypal-payments' ),
'',
__( 'for US domestic transactions', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Seller Protection', 'woocommerce-paypal-payments' ),
__( 'Yes', 'woocommerce-paypal-payments' ),
__( 'No matter what you sell, Seller Protection can help you avoid chargebacks, reversals, and fees on eligible PayPal payment transactions — even when a customer has filed a dispute.', 'woocommerce-paypal-payments' ),
__( 'for eligible PayPal transactions', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Seller Account Type', 'woocommerce-paypal-payments' ),
__( 'Business or Casual', 'woocommerce-paypal-payments' ),
__( 'For Standard payments, Casual sellers may connect their Personal PayPal account in eligible countries to sell on WooCommerce. For Advanced payments, a Business PayPal account is required.', 'woocommerce-paypal-payments' )
),
);
$items[] = '
<li>
<label>
<input type="radio" id="ppcp-onboarding-dcc-basic" name="ppcp_onboarding_dcc" value="basic" checked ' .
( ! $is_shop_supports_dcc ? 'checked' : '' ) .
' data-screen-url="' . $this->get_screen_url( 'basic' ) . '"' .
'> ' .
__( 'Standard Card Processing', 'woocommerce-paypal-payments' ) . '
</label>
' . $this->render_tooltip( __( 'Card transactions are managed by PayPal, which simplifies compliance requirements for you.', 'woocommerce-paypal-payments' ) ) . '
<table>
' . implode( $basic_table_rows ) . '
</table>
</li>';
if ( $is_shop_supports_dcc ) {
$dcc_table_rows = array(
$this->render_table_row(
@ -146,7 +183,7 @@ class OnboardingOptionsRenderer {
$items[] = '
<li>
<label>
<input type="radio" id="ppcp-onboarding-dcc-acdc" name="ppcp_onboarding_dcc" value="acdc" checked ' .
<input type="radio" id="ppcp-onboarding-dcc-acdc" name="ppcp_onboarding_dcc" value="acdc" ' .
'data-screen-url="' . $this->get_screen_url( 'acdc' ) . '"> ' .
__( 'Advanced Card Processing', 'woocommerce-paypal-payments' ) . '
</label>
@ -157,53 +194,13 @@ class OnboardingOptionsRenderer {
</li>';
}
$basic_table_rows = array(
$this->render_table_row(
__( 'Credit & Debit Card form fields', 'woocommerce-paypal-payments' ),
__( 'Prebuilt user experience', 'woocommerce-paypal-payments' )
),
! $is_us_shop ? '' : $this->render_table_row(
__( 'Credit & Debit Card pricing', 'woocommerce-paypal-payments' ),
__( '3.49% + $0.49', 'woocommerce-paypal-payments' ),
'',
__( 'for US domestic transactions', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Seller Protection', 'woocommerce-paypal-payments' ),
__( 'Yes', 'woocommerce-paypal-payments' ),
__( 'No matter what you sell, Seller Protection can help you avoid chargebacks, reversals, and fees on eligible PayPal payment transactions — even when a customer has filed a dispute.', 'woocommerce-paypal-payments' ),
__( 'for eligible PayPal transactions', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Seller Account Type', 'woocommerce-paypal-payments' ),
__( 'Business or Casual', 'woocommerce-paypal-payments' ),
__( 'For Standard payments, Casual sellers may connect their Personal PayPal account in eligible countries to sell on WooCommerce. For Advanced payments, a Business PayPal account is required.', 'woocommerce-paypal-payments' )
),
);
$items[] = '
<li ' . ( ! $is_shop_supports_dcc ? 'style="display: none;"' : '' ) . '>
<label>
<input type="radio" id="ppcp-onboarding-dcc-basic" name="ppcp_onboarding_dcc" value="basic" ' .
( ! $is_shop_supports_dcc ? 'checked' : '' ) .
' data-screen-url="' . $this->get_screen_url( 'basic' ) . '"' .
'> ' .
__( 'Standard Card Processing', 'woocommerce-paypal-payments' ) . '
</label>
' . $this->render_tooltip( __( 'Card transactions are managed by PayPal, which simplifies compliance requirements for you.', 'woocommerce-paypal-payments' ) ) . '
<table>
' . implode( $basic_table_rows ) . '
</table>
</li>';
return '
<div class="ppcp-onboarding-cards-options">
<ul id="ppcp-onboarding-dcc-options" class="ppcp-onboarding-options-sublist">' .
implode( '', $items ) .
'
</ul>
<div class="ppcp-onboarding-cards-screen">' .
( $is_shop_supports_dcc ? '<img id="ppcp-onboarding-cards-screen-img" />' : '' ) . '
</div>
<div class="ppcp-onboarding-cards-screen"><img id="ppcp-onboarding-cards-screen-img" /></div>
</div>';
}

View file

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

View file

@ -0,0 +1,612 @@
<?php
/**
* The order tracking carriers.
*
* @package WooCommerce\PayPalCommerce\OrderTracking
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\OrderTracking;
use Psr\Container\ContainerInterface;
return array(
'global' => array(
'name' => 'Global',
'items' => array(
'B_TWO_C_EUROPE' => _x( 'B2C Europe', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CJ_LOGISTICS' => _x( 'CJ Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CORREOS_EXPRESS' => _x( 'Correos Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_ACTIVE_TRACING' => _x( 'DHL Active Tracing', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_BENELUX' => _x( 'DHL Benelux', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_GLOBAL_MAIL' => _x( 'DHL ecCommerce US', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_GLOBAL_MAIL_ASIA' => _x( 'DHL eCommerce Asia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL' => _x( 'DHL Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_GLOBAL_ECOMMERCE' => _x( 'DHL Global eCommerce', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_PACKET' => _x( 'DHL Packet', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD' => _x( 'DPD Global', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD_LOCAL' => _x( 'DPD Local', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD_LOCAL_REF' => _x( 'DPD Local Reference', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPE_EXPRESS' => _x( 'DPE Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPEX' => _x( 'DPEX Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DTDC_EXPRESS' => _x( 'DTDC Express Global', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ESHOPWORLD' => _x( 'EShopWorld', 'Name of carrier', 'woocommerce-paypal-payments' ),
'FEDEX' => _x( 'FedEx', 'Name of carrier', 'woocommerce-paypal-payments' ),
'FLYT_EXPRESS' => _x( 'FLYT Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GLS' => _x( 'GLS', 'Name of carrier', 'woocommerce-paypal-payments' ),
'IMX' => _x( 'IMX France', 'Name of carrier', 'woocommerce-paypal-payments' ),
'INT_SUER' => _x( 'International SEUR', 'Name of carrier', 'woocommerce-paypal-payments' ),
'LANDMARK_GLOBAL' => _x( 'Landmark Global', 'Name of carrier', 'woocommerce-paypal-payments' ),
'MATKAHUOLTO' => _x( 'Matkahuoloto', 'Name of carrier', 'woocommerce-paypal-payments' ),
'OMNIPARCEL' => _x( 'Omni Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ONE_WORLD' => _x( 'One World', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POSTI' => _x( 'Posti', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RABEN_GROUP' => _x( 'Raben Group', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SF_EXPRESS' => _x( 'SF EXPRESS', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SKYNET_Worldwide' => _x( 'SkyNet Worldwide Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SPREADEL' => _x( 'Spreadel', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT' => _x( 'TNT Global', 'Name of carrier', 'woocommerce-paypal-payments' ),
'UPS' => _x( 'UPS', 'Name of carrier', 'woocommerce-paypal-payments' ),
'UPS_MI' => _x( 'UPS Mail Innovations', 'Name of carrier', 'woocommerce-paypal-payments' ),
'WEBINTERPRET' => _x( 'WebInterpret', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'AG' => array(
'name' => _x( 'Antigua and Barbuda', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'CORREOS_AG' => _x( 'Correos Antigua and Barbuda', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'AR' => array(
'name' => _x( 'Argentina', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'EMIRATES_POST' => _x( 'Emirates Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'OCA_AR ' => _x( 'OCA Argentina', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'AU' => array(
'name' => _x( 'Australia', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ADSONE' => _x( 'Adsone', 'Name of carrier', 'woocommerce-paypal-payments' ),
'AUSTRALIA_POST' => _x( 'Australia Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TOLL_AU' => _x( 'Australia Toll', 'Name of carrier', 'woocommerce-paypal-payments' ),
'BONDS_COURIERS' => _x( 'Bonds Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ),
'COURIERS_PLEASE' => _x( 'Couriers Please', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_AU' => _x( 'DHL Australia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DTDC_AU' => _x( 'DTDC Australia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'FASTWAY_AU' => _x( 'Fastway Australia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'HUNTER_EXPRESS ' => _x( 'Hunter Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SENDLE' => _x( 'Sendle', 'Name of carrier', 'woocommerce-paypal-payments' ),
'STARTRACK' => _x( 'Star Track', 'Name of carrier', 'woocommerce-paypal-payments' ),
'STARTRACK_EXPRESS' => _x( 'Star Track Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_AU ' => _x( 'TNT Australia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TOLL' => _x( 'Toll', 'Name of carrier', 'woocommerce-paypal-payments' ),
'UBI_LOGISTICS' => _x( 'UBI Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'AT' => array(
'name' => _x( 'Austria', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'AUSTRIAN_POST_EXPRESS' => _x( 'Austrian Post Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'AUSTRIAN_POST' => _x( 'Austrian Post Registered', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_AT' => _x( 'DHL Austria', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'BE' => array(
'name' => _x( 'Belgium', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'BPOST' => _x( 'bpost', 'Name of carrier', 'woocommerce-paypal-payments' ),
'BPOST_INT' => _x( 'bpost International', 'Name of carrier', 'woocommerce-paypal-payments' ),
'MONDIAL_BE' => _x( 'Mondial Belgium', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TAXIPOST' => _x( 'TaxiPost', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'BR' => array(
'name' => _x( 'Brazil', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'CORREOS_BR' => _x( 'Correos Brazil', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DIRECTLOG_BR' => _x( 'Directlog', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'BG' => array(
'name' => _x( 'Bulgaria', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'BULGARIAN_POST' => _x( 'Bulgarian Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'CA' => array(
'name' => _x( 'Canada', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'CANADA_POST' => _x( 'Canada Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CANPAR' => _x( 'Canpar', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GREYHOUND' => _x( 'Greyhound', 'Name of carrier', 'woocommerce-paypal-payments' ),
'LOOMIS' => _x( 'Loomis', 'Name of carrier', 'woocommerce-paypal-payments' ),
'PUROLATOR' => _x( 'Purolator', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'CL' => array(
'name' => _x( 'Chile', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'CORREOS_CL' => _x( 'Correos Chile', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'CN' => array(
'name' => _x( 'China', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'FOUR_PX_EXPRESS' => _x( 'Correos', 'Name of carrier', 'woocommerce-paypal-payments' ),
'AUPOST_CN' => _x( 'AUPOST CHINA', 'Name of carrier', 'woocommerce-paypal-payments' ),
'BQC_EXPRESS' => _x( 'BQC Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'BUYLOGIC' => _x( 'Buylogic', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CHINA_POST' => _x( 'China Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CNEXPS' => _x( 'CN Exps', 'Name of carrier', 'woocommerce-paypal-payments' ),
'EC_CN' => _x( 'EC China', 'Name of carrier', 'woocommerce-paypal-payments' ),
'EFS' => _x( 'EFS', 'Name of carrier', 'woocommerce-paypal-payments' ),
'EMPS_CN' => _x( 'EMPS China', 'Name of carrier', 'woocommerce-paypal-payments' ),
'EMS_CN' => _x( 'EMS China', 'Name of carrier', 'woocommerce-paypal-payments' ),
'HUAHAN_EXPRESS' => _x( 'Huahan Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SFC_EXPRESS' => _x( 'SFC Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_CN' => _x( 'TNT China', 'Name of carrier', 'woocommerce-paypal-payments' ),
'WINIT' => _x( 'WinIt', 'Name of carrier', 'woocommerce-paypal-payments' ),
'YANWEN_CN' => _x( 'Yanwen', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'CR' => array(
'name' => _x( 'Costa Rica', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'CORREOS_CR' => _x( 'Correos De Costa Rica', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'HR' => array(
'name' => _x( 'Croatia', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'HRVATSKA_HR' => _x( 'Hrvatska', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'CY' => array(
'name' => _x( 'Cyprus', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'CYPRUS_POST_CYP' => _x( 'Cyprus Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'CZ' => array(
'name' => _x( 'Czech Republic', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'CESKA_CZ' => _x( 'Ceska', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GLS_CZ' => _x( 'GLS Czech Republic', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'FR' => array(
'name' => _x( 'France', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'BERT' => _x( 'BERT TRANSPORT', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CHRONOPOST_FR' => _x( 'Chronopost France', 'Name of carrier', 'woocommerce-paypal-payments' ),
'COLIPOSTE' => _x( 'Coliposte', 'Name of carrier', 'woocommerce-paypal-payments' ),
'COLIS' => _x( 'Colis France', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_FR' => _x( 'DHL France', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD_FR' => _x( 'DPD France', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GEODIS' => _x( 'GEODIS - Distribution & Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GLS_FR' => _x( 'GLS France', 'Name of carrier', 'woocommerce-paypal-payments' ),
'LAPOSTE' => _x( 'LA Poste', 'Name of carrier', 'woocommerce-paypal-payments' ),
'MONDIAL' => _x( 'Mondial Relay', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RELAIS_COLIS_FR' => _x( 'Relais Colis', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TELIWAY' => _x( 'Teliway', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_FR' => _x( 'TNT France', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'DE' => array(
'name' => _x( 'Germany', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ASENDIA_DE' => _x( 'Asendia Germany', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DELTEC_DE' => _x( 'Deltec Germany', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DEUTSCHE_DE' => _x( 'Deutsche', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_DEUTSCHE_POST' => _x( 'DHL Deutsche Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD_DE' => _x( 'DPD Germany', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GLS_DE' => _x( 'GLS Germany', 'Name of carrier', 'woocommerce-paypal-payments' ),
'HERMES_DE' => _x( 'Hermes Germany', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_DE' => _x( 'TNT Germany', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'GR' => array(
'name' => _x( 'Greece', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ELTA_GR' => _x( 'ELTA Greece', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GENIKI_GR' => _x( 'Geniki Greece', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ACS_GR' => _x( 'GRC Greece', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'HK' => array(
'name' => _x( 'Hong Kong', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ASENDIA_HK' => _x( 'Asendia Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_HK' => _x( 'DHL Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD_HK' => _x( 'DPD Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ),
'HK_POST' => _x( 'Hong Kong Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'KERRY_EXPRESS_HK' => _x( 'Kerry Express Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ),
'LOGISTICSWORLDWIDE_HK' => _x( 'Logistics Worldwide Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ),
'QUANTIUM' => _x( 'Quantium', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SEKOLOGISTICS' => _x( 'Seko Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TAQBIN_HK' => _x( 'TA-Q-BIN Parcel Hong Kong', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'HU' => array(
'name' => _x( 'Hungary', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'MAGYAR_HU' => _x( 'Magyar', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'IS' => array(
'name' => _x( 'Iceland', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'POSTUR_IS' => _x( 'Postur', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'IN' => array(
'name' => _x( 'India', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'BLUEDART' => _x( 'Bluedart', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DELHIVERY_IN' => _x( 'Delhivery', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DOTZOT' => _x( 'DotZot', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DTDC_IN' => _x( 'DTDC India', 'Name of carrier', 'woocommerce-paypal-payments' ),
'EKART' => _x( 'Ekart', 'Name of carrier', 'woocommerce-paypal-payments' ),
'INDIA_POST' => _x( 'India Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'PROFESSIONAL_COURIERS' => _x( 'Professional Couriers', 'Name of carrier', 'woocommerce-paypal-payments' ),
'REDEXPRESS' => _x( 'Red Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SWIFTAIR' => _x( 'Swift Air', 'Name of carrier', 'woocommerce-paypal-payments' ),
'XPRESSBEES' => _x( 'Xpress Bees', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'ID' => array(
'name' => _x( 'Indonesia', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'FIRST_LOGISITCS' => _x( 'First Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ),
'JNE_IDN' => _x( 'JNE Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'LION_PARCEL' => _x( 'Lion Parcel', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NINJAVAN_ID' => _x( 'Ninjavan Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'PANDU' => _x( 'Pandu Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POS_ID' => _x( 'Pos Indonesia Domestic', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POS_INT' => _x( 'Pos Indonesia International', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RPX_ID' => _x( 'RPX Indonesia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RPX' => _x( 'RPX International', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TIKI_ID' => _x( 'Tiki', 'Name of carrier', 'woocommerce-paypal-payments' ),
'WAHANA_ID' => _x( 'Wahana', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'IE' => array(
'name' => _x( 'Ireland', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'AN_POST' => _x( 'AN POST Ireland', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD_IR' => _x( 'DPD Ireland', 'Name of carrier', 'woocommerce-paypal-payments' ),
'MASTERLINK' => _x( 'Masterlink', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TPG' => _x( 'TPG', 'Name of carrier', 'woocommerce-paypal-payments' ),
'WISELOADS' => _x( 'Wiseloads', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'IL' => array(
'name' => _x( 'Israel', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ISRAEL_POST' => _x( 'Israel Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'IT' => array(
'name' => _x( 'Italy', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'BRT_IT' => _x( 'BRT Bartolini', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_IT' => _x( 'DHL Italy', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DMM_NETWORK' => _x( 'DMM Network', 'Name of carrier', 'woocommerce-paypal-payments' ),
'FERCAM_IT' => _x( 'FERCAM Logistics & Transport', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GLS_IT' => _x( 'GLS Italy', 'Name of carrier', 'woocommerce-paypal-payments' ),
'HERMES_IT' => _x( 'Hermes Italy', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POSTE_ITALIANE' => _x( 'Poste Italiane', 'Name of carrier', 'woocommerce-paypal-payments' ),
'REGISTER_MAIL_IT' => _x( 'Register Mail IT', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SDA_IT' => _x( 'SDA Italy', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SGT_IT' => _x( 'SGT Corriere Espresso', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_CLICK_IT' => _x( 'TNT Click Italy', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_IT' => _x( 'TNT Italy', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'JP' => array(
'name' => _x( 'Japan', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'DHL_JP' => _x( 'DHL Japan', 'Name of carrier', 'woocommerce-paypal-payments' ),
'JP_POST' => _x( 'JP Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'JAPAN_POST' => _x( 'Japan Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POCZTEX' => _x( 'Pocztex', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SAGAWA' => _x( 'Sagawa', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SAGAWA_JP' => _x( 'Sagawa JP', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_JP' => _x( 'TNT Japan', 'Name of carrier', 'woocommerce-paypal-payments' ),
'YAMATO' => _x( 'Yamato Japan', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'KR' => array(
'name' => _x( 'Korea', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ECARGO' => _x( 'Ecargo', 'Name of carrier', 'woocommerce-paypal-payments' ),
'EPARCEL_KR' => _x( 'eParcel Korea', 'Name of carrier', 'woocommerce-paypal-payments' ),
'KOREA_POST' => _x( 'Korea Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'KOR_KOREA_POST' => _x( 'KOR Korea Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CJ_KR' => _x( 'Korea Thai CJ', 'Name of carrier', 'woocommerce-paypal-payments' ),
'LOGISTICSWORLDWIDE_KR' => _x( 'Logistics Worldwide Korea', 'Name of carrier', 'woocommerce-paypal-payments' ),
'PANTOS' => _x( 'Pantos', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RINCOS' => _x( 'Rincos', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ROCKET_PARCEL' => _x( 'Rocket Parcel International', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SRE_KOREA' => _x( 'SRE Korea', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'LT' => array(
'name' => _x( 'Lithuania', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'LIETUVOS_LT' => _x( 'Lietuvos Pastas', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'MY' => array(
'name' => _x( 'Malaysia', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'AIRPAK_MY' => _x( 'Airpak', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CITYLINK_MY' => _x( 'CityLink Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CJ_MY' => _x( 'CJ Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CJ_INT_MY' => _x( 'CJ Malaysia International', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CUCKOOEXPRESS' => _x( 'Cuckoo Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'JETSHIP_MY' => _x( 'Jet Ship Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'KANGAROO_MY' => _x( 'Kangaroo Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'LOGISTICSWORLDWIDE_MY' => _x( 'Logistics Worldwide Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'MALAYSIA_POST' => _x( 'Malaysia Post EMS / Pos Laju', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NATIONWIDE' => _x( 'Nationwide', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NINJAVAN_MY' => _x( 'Ninjavan Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SKYNET_MY' => _x( 'Skynet Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TAQBIN_MY' => _x( 'TA-Q-BIN Parcel Malaysia', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'MX' => array(
'name' => _x( 'Mexico', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'CORREOS_MX' => _x( 'Correos De Mexico', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ESTAFETA' => _x( 'Estafeta', 'Name of carrier', 'woocommerce-paypal-payments' ),
'AEROFLASH' => _x( 'Mexico Aeroflash', 'Name of carrier', 'woocommerce-paypal-payments' ),
'REDPACK' => _x( 'Mexico Redpack', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SENDA_MX' => _x( 'Mexico Senda Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'NL' => array(
'name' => _x( 'Netherlands', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'DHL_NL' => _x( 'DHL Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_PARCEL_NL' => _x( 'DHL Parcel Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GLS_NL' => _x( 'GLS Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ),
'KIALA' => _x( 'Kiala', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POSTNL' => _x( 'PostNL', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POSTNL_INT' => _x( 'PostNl International', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POSTNL_INT_3_S' => _x( 'PostNL International 3S', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_NL' => _x( 'TNT Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TRANSMISSION' => _x( 'Transmission Netherlands', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'NZ' => array(
'name' => _x( 'New Zealand', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'COURIER_POST' => _x( 'Courier Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'FASTWAY_NZ' => _x( 'Fastway New Zealand', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NZ_POST' => _x( 'New Zealand Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TOLL_IPEC' => _x( 'Toll IPEC', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'NG' => array(
'name' => _x( 'Nigeria', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'COURIERPLUS' => _x( 'Courier Plus', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NIPOST_NG' => _x( 'NiPost', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'NO' => array(
'name' => _x( 'Norway', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'POSTEN_NORGE' => _x( 'Posten Norge', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'PH' => array(
'name' => _x( 'Philippines', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'TWO_GO' => _x( '2GO', 'Name of carrier', 'woocommerce-paypal-payments' ),
'AIR_21' => _x( 'Air 21', 'Name of carrier', 'woocommerce-paypal-payments' ),
'AIRSPEED' => _x( 'Airspeed', 'Name of carrier', 'woocommerce-paypal-payments' ),
'JAMEXPRESS_PH' => _x( 'Jam Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'LBC_PH' => _x( 'LBC Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NINJAVAN_PH' => _x( 'Ninjavan Philippines', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RAF_PH' => _x( 'RAF Philippines', 'Name of carrier', 'woocommerce-paypal-payments' ),
'XEND_EXPRESS_PH' => _x( 'Xend Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'PL' => array(
'name' => _x( 'Poland', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'DHL_PL' => _x( 'DHL Poland', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD_PL' => _x( 'DPD Poland', 'Name of carrier', 'woocommerce-paypal-payments' ),
'INPOST_PACZKOMATY' => _x( 'InPost Paczkomaty', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POCZTA_POLSKA' => _x( 'Poczta Polska', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SIODEMKA' => _x( 'Siodemka', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_PL' => _x( 'TNT Poland', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'PT' => array(
'name' => _x( 'Portugal', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ADICIONAL_PT' => _x( 'Adicional Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CHRONOPOST_PT' => _x( 'Chronopost Portugal', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CTT_PT' => _x( 'Portugal PTT', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SEUR_PT' => _x( 'Portugal Seur', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'RO' => array(
'name' => _x( 'Romania', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'DPD_RO' => _x( 'DPD Romania', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POSTA_RO' => _x( 'Postaromana', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'RU' => array(
'name' => _x( 'Russia', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'DPD_RU' => _x( 'DPD Russia', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RUSSIAN_POST' => _x( 'Russian Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'SA' => array(
'name' => _x( 'Saudi Arabia', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'DAWN_WING' => _x( 'Dawn Wing', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RAM' => _x( 'Ram', 'Name of carrier', 'woocommerce-paypal-payments' ),
'THE_COURIER_GUY' => _x( 'The Courier Guy', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'CS' => array(
'name' => _x( 'Serbia', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'POST_SERBIA_CS' => _x( 'Serbia Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'SG' => array(
'name' => _x( 'Singapore', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'DHL_SG' => _x( 'DHL Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ),
'JETSHIP_SG' => _x( 'JetShip Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NINJAVAN_SG' => _x( 'Ninjavan Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ),
'PARCELPOST_SG' => _x( 'Parcel Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SINGPOST' => _x( 'Singapore Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TAQBIN_SG' => _x( 'TA-Q-BIN Parcel Singapore', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'ZA' => array(
'name' => _x( 'South Africa', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'FASTWAY_ZA' => _x( 'Fastway South Africa', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'ES' => array(
'name' => _x( 'Spain', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ASM_ES' => _x( 'ASM', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CBL_LOGISTICA' => _x( 'CBL Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CORREOS_ES' => _x( 'Correos De Spain', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_ES ' => _x( 'DHL Spain', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_PARCEL_ES' => _x( 'DHL Parcel Spain', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GLS_ES' => _x( 'GLS Spain', 'Name of carrier', 'woocommerce-paypal-payments' ),
'INT_SEUR' => _x( 'International Suer', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ITIS' => _x( 'ITIS', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NACEX_ES' => _x( 'Nacex Spain', 'Name of carrier', 'woocommerce-paypal-payments' ),
'REDUR_ES' => _x( 'Redur Spain', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SEUR_ES' => _x( 'Spanish Seur', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_ES' => _x( 'TNT Spain', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'SE' => array(
'name' => _x( 'Sweden', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'DBSCHENKER_SE' => _x( 'DB Schenker Sweden', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DIRECTLINK_SE' => _x( 'DirectLink Sweden', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POSTNORD_LOGISTICS_GLOBAL' => _x( 'PostNord Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POSTNORD_LOGISTICS_DK' => _x( 'PostNord Logistics Denmark', 'Name of carrier', 'woocommerce-paypal-payments' ),
'POSTNORD_LOGISTICS_SE' => _x( 'PostNord Logistics Sweden', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'CH' => array(
'name' => _x( 'Switzerland', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'SWISS_POST' => _x( 'Swiss Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'TW' => array(
'name' => _x( 'Taiwan', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'CHUNGHWA_POST' => _x( 'Chunghwa Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TAIWAN_POST_TW' => _x( 'Taiwan Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'TH' => array(
'name' => _x( 'Thailand', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ACOMMMERCE' => _x( 'Acommerce', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ALPHAFAST' => _x( 'Alphafast', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CJ_TH' => _x( 'CJ Thailand', 'Name of carrier', 'woocommerce-paypal-payments' ),
'FASTRACK' => _x( 'FastTrack Thailand', 'Name of carrier', 'woocommerce-paypal-payments' ),
'KERRY_EXPRESS_TH' => _x( 'Kerry Express Thailand', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NIM_EXPRESS' => _x( 'NIM Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NINJAVAN_THAI' => _x( 'Ninjavan Thailand', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SENDIT' => _x( 'SendIt', 'Name of carrier', 'woocommerce-paypal-payments' ),
'THAILAND_POST' => _x( 'Thailand Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'TR' => array(
'name' => _x( 'Turkey', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'PTT_POST' => _x( 'PTT Posta', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'UA' => array(
'name' => _x( 'Ukraine', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'NOVA_POSHTA' => _x( 'Nova Poshta', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NOVA_POSHTA_INT' => _x( 'Nova Poshta International', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'AE' => array(
'name' => _x( 'United Arab Emirates', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'AXL' => _x( 'AXL Express & Logistics', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CONTINENTAL' => _x( 'Continental', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SKYNET_UAE' => _x( 'Skynet Worldwide Express UAE', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'GB' => array(
'name' => _x( 'United Kingdom', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'AIRBORNE_EXPRESS_UK' => _x( 'Airborne Express UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'AIRSURE' => _x( 'Airsure', 'Name of carrier', 'woocommerce-paypal-payments' ),
'APC_OVERNIGHT' => _x( 'APC Overnight', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ASENDIA_UK' => _x( 'Asendia UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'COLLECTPLUS' => _x( 'CollectPlus', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DELTEC_UK' => _x( 'Deltec UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DHL_UK' => _x( 'DHL UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD_DELISTRACK' => _x( 'DPD Delistrack', 'Name of carrier', 'woocommerce-paypal-payments' ),
'DPD_UK' => _x( 'DPD UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'FASTWAY_UK' => _x( 'Fastway UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'HERMESWORLD_UK' => _x( 'HermesWorld', 'Name of carrier', 'woocommerce-paypal-payments' ),
'INTERLINK' => _x( 'Interlink Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'MYHERMES' => _x( 'MyHermes UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'NIGHTLINE_UK' => _x( 'Nightline UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'PARCELFORCE' => _x( 'Parcel Force', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ROYAL_MAIL' => _x( 'Royal Mail', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RPD_2_MAN' => _x( 'RPD2man Deliveries', 'Name of carrier', 'woocommerce-paypal-payments' ),
'SKYNET_UK' => _x( 'Skynet Worldwide Express UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'TNT_UK' => _x( 'TNT UK', 'Name of carrier', 'woocommerce-paypal-payments' ),
'UK_MAIL' => _x( 'UK Mail', 'Name of carrier', 'woocommerce-paypal-payments' ),
'YODEL' => _x( 'Yodel', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'US' => array(
'name' => _x( 'United States', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'ABC_PACKAGE' => _x( 'ABC Package Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'AIRBORNE_EXPRESS' => _x( 'Airborne Express', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ASENDIA_US' => _x( 'Asendia USA', 'Name of carrier', 'woocommerce-paypal-payments' ),
'CPACKET' => _x( 'Cpacket', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ENSENDA' => _x( 'Ensenda USA', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ESTES' => _x( 'Estes', 'Name of carrier', 'woocommerce-paypal-payments' ),
'FASTWAY_US' => _x( 'Fastway USA', 'Name of carrier', 'woocommerce-paypal-payments' ),
'GLOBEGISTICS' => _x( 'Globegistics USA', 'Name of carrier', 'woocommerce-paypal-payments' ),
'INTERNATIONAL_BRIDGE' => _x( 'International Bridge', 'Name of carrier', 'woocommerce-paypal-payments' ),
'ONTRAC' => _x( 'OnTrac', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RL_US' => _x( 'RL Carriers', 'Name of carrier', 'woocommerce-paypal-payments' ),
'RRDONNELLEY' => _x( 'RR Donnelley', 'Name of carrier', 'woocommerce-paypal-payments' ),
'USPS' => _x( 'USPS', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
'VN' => array(
'name' => _x( 'Vietnam', 'Name of carrier country', 'woocommerce-paypal-payments' ),
'items' => array(
'KERRY_EXPRESS_VN' => _x( 'Kerry Express Vietnam', 'Name of carrier', 'woocommerce-paypal-payments' ),
'VIETNAM_POST' => _x( 'Vietnam Post', 'Name of carrier', 'woocommerce-paypal-payments' ),
'VNPOST_EMS' => _x( 'Vietnam Post EMS', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
);

View file

@ -0,0 +1,17 @@
{
"name": "woocommerce/ppcp-order-tracking",
"type": "dhii-mod",
"description": "Order tracking module for PPCP",
"license": "GPL-2.0",
"require": {
"php": "^7.1 | ^8.0",
"dhii/module-interface": "^0.3.0-alpha1"
},
"autoload": {
"psr-4": {
"WooCommerce\\PayPalCommerce\\OrderTracking\\": "src"
}
},
"minimum-stability": "dev",
"prefer-stable": true
}

View file

@ -0,0 +1,12 @@
<?php
/**
* The order tracking module extensions.
*
* @package WooCommerce\PayPalCommerce\OrderTracking
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\OrderTracking;
return array();

View file

@ -0,0 +1,16 @@
<?php
/**
* The order tracking module.
*
* @package WooCommerce\PayPalCommerce\OrderTracking
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\OrderTracking;
use Dhii\Modular\Module\ModuleInterface;
return static function (): ModuleInterface {
return new OrderTrackingModule();
};

View file

@ -0,0 +1,23 @@
{
"name": "ppcp-order-tracking",
"version": "1.0.0",
"license": "GPL-3.0-or-later",
"main": "resources/js/order-edit-page.js",
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/preset-env": "^7.9.5",
"babel-loader": "^8.1.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"cross-env": "^7.0.3",
"file-loader": "^6.2.0",
"sass": "^1.42.1",
"sass-loader": "^12.1.0",
"webpack": "^5.55.0",
"webpack-cli": "^4.8.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 @@
#ppcp_order-tracking {
.tracking-info-message {
padding-left: 20px;
}
.error {
color: red;
font-weight: bold;
}
.success {
color: green;
font-weight: bold;
}
input,select {
width: 100%;
}
}

View file

@ -0,0 +1,49 @@
import {PaymentMethods} from "../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState";
document.addEventListener(
'DOMContentLoaded',
() => {
const config = PayPalCommerceGatewayOrderTrackingInfo;
if (!typeof (PayPalCommerceGatewayOrderTrackingInfo)) {
console.error('trackign cannot be set.');
return;
}
const transactionId = document.querySelector('.ppcp-tracking-transaction_id');
const trackingNumber = document.querySelector('.ppcp-tracking-tracking_number');
const status = document.querySelector('.ppcp-tracking-status');
const carrier = document.querySelector('.ppcp-tracking-carrier');
const orderId = document.querySelector('.ppcp-order_id');
const submitButton = document.querySelector('.submit_tracking_info');
submitButton.addEventListener('click', function (event) {
submitButton.setAttribute('disabled', 'disabled');
fetch(config.ajax.tracking_info.endpoint, {
method: 'POST',
body: JSON.stringify({
nonce: config.ajax.tracking_info.nonce,
transaction_id: transactionId ? transactionId.value : null,
tracking_number: trackingNumber ? trackingNumber.value : null,
status: status ? status.value : null,
carrier: carrier ? carrier.value : null,
order_id: orderId ? orderId.value : null,
action: submitButton ? submitButton.dataset.action : null,
})
}).then(function (res) {
return res.json();
}).then(function (data) {
if (!data.success) {
console.error(data);
throw Error(data.data.message);
}
jQuery( "<span class='success tracking-info-message'>" + data.data.message + "</span>" ).insertAfter(submitButton);
setTimeout(()=> jQuery('.tracking-info-message').remove(),3000);
submitButton.dataset.action = 'update';
submitButton.textContent = 'update';
submitButton.removeAttribute('disabled');
});
})
},
);

View file

@ -0,0 +1,82 @@
<?php
/**
* The order tracking module services.
*
* @package WooCommerce\PayPalCommerce\OrderTracking
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\OrderTracking;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\OrderTracking\Assets\OrderEditPageAssets;
use WooCommerce\PayPalCommerce\OrderTracking\Endpoint\OrderTrackingEndpoint;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
return array(
'order-tracking.assets' => function( ContainerInterface $container ) : OrderEditPageAssets {
return new OrderEditPageAssets(
$container->get( 'order-tracking.module.url' ),
$container->get( 'ppcp.asset-version' )
);
},
'order-tracking.endpoint.controller' => static function ( ContainerInterface $container ) : OrderTrackingEndpoint {
return new OrderTrackingEndpoint(
$container->get( 'api.host' ),
$container->get( 'api.bearer' ),
$container->get( 'woocommerce.logger.woocommerce' ),
$container->get( 'button.request-data' )
);
},
'order-tracking.module.url' => static function ( ContainerInterface $container ): string {
/**
* The path cannot be false.
*
* @psalm-suppress PossiblyFalseArgument
*/
return plugins_url(
'/modules/ppcp-order-tracking/',
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
);
},
'order-tracking.meta-box.renderer' => static function ( ContainerInterface $container ): MetaBoxRenderer {
return new MetaBoxRenderer(
$container->get( 'order-tracking.endpoint.controller' ),
$container->get( 'order-tracking.allowed-shipping-statuses' ),
$container->get( 'order-tracking.available-carriers' )
);
},
'order-tracking.allowed-shipping-statuses' => static function ( ContainerInterface $container ): array {
return array( 'SHIPPED', 'ON_HOLD', 'DELIVERED', 'CANCELLED' );
},
'order-tracking.allowed-carriers' => static function ( ContainerInterface $container ): array {
return require __DIR__ . '/carriers.php';
},
'order-tracking.available-carriers' => static function ( ContainerInterface $container ): array {
$api_shop_country = $container->get( 'api.shop.country' );
$allowed_carriers = $container->get( 'order-tracking.allowed-carriers' );
$selected_country_carriers = $allowed_carriers[ $api_shop_country ] ?? array();
return array(
$api_shop_country => $selected_country_carriers ?? array(),
'global' => $allowed_carriers['global'] ?? array(),
'other' => array(
'name' => 'Other',
'items' => array(
'OTHER' => _x( 'Other', 'Name of carrier', 'woocommerce-paypal-payments' ),
),
),
);
},
'order-tracking.is-paypal-order-edit-page' => static function ( ContainerInterface $container ): bool {
$order_id = isset( $_GET['post'] ) ? (int) $_GET['post'] : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( empty( $order_id ) ) {
return false;
}
$meta = get_post_meta( $order_id, PayPalGateway::ORDER_ID_META_KEY, true );
return ! empty( $meta );
},
);

View file

@ -0,0 +1,100 @@
<?php
/**
* Register and configure assets for order edit page.
*
* @package WooCommerce\PayPalCommerce\OrderTracking\Assets
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\OrderTracking\Assets;
use WooCommerce\PayPalCommerce\OrderTracking\Endpoint\OrderTrackingEndpoint;
/**
* Class OrderEditPageAssets
*/
class OrderEditPageAssets {
/**
* The URL to the module.
*
* @var string
*/
private $module_url;
/**
* The assets version.
*
* @var string
*/
private $version;
/**
* WebhooksStatusPageAssets constructor.
*
* @param string $module_url The URL to the module.
* @param string $version The assets version.
*/
public function __construct(
string $module_url,
string $version
) {
$this->module_url = $module_url;
$this->version = $version;
}
/**
* Registers the scripts and styles.
*
* @return void
*/
public function register(): void {
wp_register_style(
'ppcp-webhooks-order-edit-page-style',
untrailingslashit( $this->module_url ) . '/assets/css/order-edit-page.css',
array(),
$this->version
);
wp_register_script(
'ppcp-tracking',
untrailingslashit( $this->module_url ) . '/assets/js/order-edit-page.js',
array( 'jquery' ),
$this->version,
true
);
wp_localize_script(
'ppcp-tracking',
'PayPalCommerceGatewayOrderTrackingInfo',
$this->get_script_data()
);
}
/**
* Returns the data for the script.
*
* @return array a map of script data.
*/
public function get_script_data(): array {
return array(
'ajax' => array(
'tracking_info' => array(
'endpoint' => \WC_AJAX::get_endpoint( OrderTrackingEndpoint::ENDPOINT ),
'nonce' => wp_create_nonce( OrderTrackingEndpoint::nonce() ),
),
),
);
}
/**
* Enqueues the necessary scripts.
*
* @return void
*/
public function enqueue(): void {
wp_enqueue_style( 'ppcp-webhooks-order-edit-page-style' );
wp_enqueue_script( 'ppcp-tracking' );
}
}

View file

@ -0,0 +1,356 @@
<?php
/**
* The order tracking Endpoint.
*
* @package WooCommerce\PayPalCommerce\OrderTracking\Endpoint
*/
declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\OrderTracking\Endpoint;
use Exception;
use Psr\Log\LoggerInterface;
use WC_Order;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
/**
* The OrderTrackingEndpoint.
*
* @psalm-type SupportedStatuses = 'SHIPPED'|'ON_HOLD'|'DELIVERED'|'CANCELLED'
* @psalm-type TrackingInfo = array{transaction_id: string, status: SupportedStatuses, tracking_number?: string, carrier?: string}
* @psalm-type RequestValues = array{transaction_id: string, status: SupportedStatuses, order_id: int, action: 'create'|'update', tracking_number?: string, carrier?: string}
* Class OrderTrackingEndpoint
*/
class OrderTrackingEndpoint {
use RequestTrait, TransactionIdHandlingTrait;
const ENDPOINT = 'ppc-tracking-info';
/**
* The RequestData.
*
* @var RequestData
*/
protected $request_data;
/**
* The Host URL.
*
* @var string
*/
private $host;
/**
* The bearer.
*
* @var Bearer
*/
private $bearer;
/**
* The logger.
*
* @var LoggerInterface
*/
private $logger;
/**
* PartnersEndpoint constructor.
*
* @param string $host The host.
* @param Bearer $bearer The bearer.
* @param LoggerInterface $logger The logger.
* @param RequestData $request_data The Request data.
*/
public function __construct(
string $host,
Bearer $bearer,
LoggerInterface $logger,
RequestData $request_data
) {
$this->host = $host;
$this->bearer = $bearer;
$this->logger = $logger;
$this->request_data = $request_data;
}
/**
* Handles the request.
*/
public function handle_request(): void {
try {
$data = $this->request_data->read_request( $this->nonce() );
$action = $data['action'];
$request_body = $this->extract_tracking_information( $data );
$order_id = (int) $data['order_id'];
$action === 'create' ? $this->add_tracking_information( $request_body, $order_id ) : $this->update_tracking_information( $data, $order_id );
$action_message = $action === 'create' ? 'created' : 'updated';
$message = sprintf(
// translators: %1$s is the action message (created or updated).
_x( 'successfully %1$s', 'tracking info success message', 'woocommerce-paypal-payments' ),
esc_html( $action_message )
);
wp_send_json_success( array( 'message' => $message ) );
} catch ( Exception $error ) {
wp_send_json_error( $error->getMessage(), 500 );
}
}
/**
* Creates the tracking information of a given order with the given data.
*
* @param array $data The tracking information to add.
* @psalm-param TrackingInfo $data
* @param int $order_id The order ID.
* @throws RuntimeException If problem creating.
*/
public function add_tracking_information( array $data, int $order_id ) : void {
$url = trailingslashit( $this->host ) . 'v1/shipping/trackers-batch';
$body = array(
'trackers' => array( $data ),
);
$args = array(
'method' => 'POST',
'headers' => $this->request_headers(),
'body' => wp_json_encode( $body ),
);
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
$error = new RuntimeException(
'Could not create order tracking information.'
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
/**
* Need to ignore Method WP_Error::offsetGet does not exist
*
* @psalm-suppress UndefinedMethod
*/
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
$error = new PayPalApiException(
$json,
$status_code
);
$this->logger->log(
'warning',
sprintf(
'Failed to create order tracking information. PayPal API response: %1$s',
$error->getMessage()
),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
update_post_meta( $order_id, '_ppcp_paypal_tracking_number', $data['tracking_number'] ?? '' );
}
/**
* Gets the tracking information of a given order.
*
* @param int $wc_order_id The order ID.
* @return array|null The tracking information.
* @psalm-return TrackingInfo|null
* @throws RuntimeException If problem getting.
*/
public function get_tracking_information( int $wc_order_id ) : ?array {
$wc_order = wc_get_order( $wc_order_id );
if ( ! is_a( $wc_order, WC_Order::class ) ) {
throw new RuntimeException( 'wrong order ID' );
}
$transaction_id = $wc_order->get_transaction_id();
$tracking_number = get_post_meta( $wc_order_id, '_ppcp_paypal_tracking_number', true );
$url = trailingslashit( $this->host ) . 'v1/shipping/trackers/' . $this->find_tracker_id( $transaction_id, $tracking_number );
$args = array(
'method' => 'GET',
'headers' => $this->request_headers(),
);
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
$error = new RuntimeException(
'Could not fetch the tracking information.'
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
/**
* Need to ignore Method WP_Error::offsetGet does not exist
*
* @psalm-suppress UndefinedMethod
*/
$data = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
return null;
}
return $this->extract_tracking_information( (array) $data );
}
/**
* Updates the tracking information of a given order with the given data.
*
* @param array $data The tracking information to update.
* @psalm-param TrackingInfo $data
* @param int $order_id The order ID.
* @throws RuntimeException If problem updating.
*/
public function update_tracking_information( array $data, int $order_id ) : void {
$tracking_info = $this->get_tracking_information( $order_id );
$transaction_id = $tracking_info['transaction_id'] ?? '';
$tracking_number = $tracking_info['tracking_number'] ?? '';
$url = trailingslashit( $this->host ) . 'v1/shipping/trackers/' . $this->find_tracker_id( $transaction_id, $tracking_number );
$args = array(
'method' => 'PUT',
'headers' => $this->request_headers(),
'body' => wp_json_encode( $data ),
);
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
$error = new RuntimeException(
'Could not update order tracking information.'
);
$this->logger->log(
'warning',
$error->getMessage(),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
/**
* Need to ignore Method WP_Error::offsetGet does not exist
*
* @psalm-suppress UndefinedMethod
*/
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 204 !== $status_code ) {
$error = new PayPalApiException(
$json,
$status_code
);
$this->logger->log(
'warning',
sprintf(
'Failed to update the order tracking information. PayPal API response: %1$s',
$error->getMessage()
),
array(
'args' => $args,
'response' => $response,
)
);
throw $error;
}
update_post_meta( $order_id, '_ppcp_paypal_tracking_number', $data['tracking_number'] ?? '' );
}
/**
* The nonce.
*
* @return string
*/
public static function nonce(): string {
return self::ENDPOINT;
}
/**
* Extracts the needed tracking information from given data.
*
* @param array $data The request data map.
* @psalm-param RequestValues $data
* @return array A map of tracking information keys to values.
* @psalm-return TrackingInfo
* @throws RuntimeException If problem extracting.
*/
protected function extract_tracking_information( array $data ): array {
if ( empty( $data['transaction_id'] ) || empty( $data['status'] ) ) {
$this->logger->log( 'warning', 'Missing transaction_id or status.' );
throw new RuntimeException( 'Missing transaction_id or status.' );
}
$tracking_info = array(
'transaction_id' => $data['transaction_id'],
'status' => $data['status'],
);
if ( ! empty( $data['tracking_number'] ) ) {
$tracking_info['tracking_number'] = $data['tracking_number'];
}
if ( ! empty( $data['carrier'] ) ) {
$tracking_info['carrier'] = $data['carrier'];
}
return $tracking_info;
}
/**
* Creates the request headers.
*
* @return array The request headers.
*/
protected function request_headers(): array {
return array(
'Authorization' => 'Bearer ' . $this->bearer->bearer()->token(),
'Content-Type' => 'application/json',
);
}
/**
* Finds the tracker ID from given transaction ID and tracking number.
*
* @param string $transaction_id The transaction ID.
* @param string $tracking_number The tracking number.
* @return string The tracker ID.
*/
protected function find_tracker_id( string $transaction_id, string $tracking_number ): string {
return ! empty( $tracking_number ) ? "{$transaction_id}-{$tracking_number}" : "{$transaction_id}-NOTRACKER";
}
}

View file

@ -0,0 +1,131 @@
<?php
/**
* The order tracking MetaBox renderer.
*
* @package WooCommerce\PayPalCommerce\OrderTracking
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\OrderTracking;
use WC_Order;
use WooCommerce\PayPalCommerce\OrderTracking\Endpoint\OrderTrackingEndpoint;
use WP_Post;
/**
* Class MetaBoxRenderer
*
* @psalm-type CarrierType = string
* @psalm-type CarrierItemCode = string
* @psalm-type CarrierItemName = string
* @psalm-type Carrier = array{name: string, items: array<CarrierItemCode, CarrierItemName>}
* @psalm-type Carriers = array<CarrierType, Carrier>
*/
class MetaBoxRenderer {
public const NAME_PREFIX = 'ppcp-tracking';
/**
* The OrderTrackingEndpoint.
*
* @var OrderTrackingEndpoint
*/
protected $order_tracking_endpoint;
/**
* Allowed shipping statuses.
*
* @var string[]
*/
protected $allowed_statuses;
/**
* Available shipping carriers.
*
* @var array
* @psalm-var Carriers
*/
protected $carriers;
/**
* MetaBoxRenderer constructor.
*
* @param OrderTrackingEndpoint $order_tracking_endpoint The OrderTrackingEndpoint.
* @param string[] $allowed_statuses Allowed shipping statuses.
* @param array $carriers Available shipping carriers.
* @psalm-param Carriers $carriers
*/
public function __construct(
OrderTrackingEndpoint $order_tracking_endpoint,
array $allowed_statuses,
array $carriers
) {
$this->order_tracking_endpoint = $order_tracking_endpoint;
$this->allowed_statuses = $allowed_statuses;
$this->carriers = $carriers;
}
/**
* Renders the order tracking MetaBox.
*
* @param WP_Post $post The post object.
*/
public function render( WP_Post $post ): void {
$wc_order = wc_get_order( $post->ID );
if ( ! is_a( $wc_order, WC_Order::class ) ) {
return;
}
$tracking_info = $this->order_tracking_endpoint->get_tracking_information( $wc_order->get_id() );
$tracking_is_not_added = empty( $tracking_info );
$transaction_id = $tracking_info['transaction_id'] ?? $wc_order->get_transaction_id() ?: '';
$tracking_number = $tracking_info['tracking_number'] ?? '';
$status_value = $tracking_info['status'] ?? 'SHIPPED';
$carrier_value = $tracking_info['carrier'] ?? '';
$carriers = (array) apply_filters( 'ppcp_tracking_carriers', $this->carriers );
$statuses = (array) apply_filters( 'ppcp_tracking_statuses', $this->allowed_statuses );
$action = $tracking_is_not_added ? 'create' : 'update';
?>
<p>
<label for="<?php echo esc_attr( self::NAME_PREFIX ); ?>-transaction_id"><?php echo esc_html__( 'Transaction ID', 'woocommerce-paypal-payments' ); ?></label>
<input type="text" disabled class="<?php echo esc_attr( self::NAME_PREFIX ); ?>-transaction_id" id="<?php echo esc_attr( self::NAME_PREFIX ); ?>-transaction_id" name="<?php echo esc_attr( self::NAME_PREFIX ); ?>[transaction_id]" value="<?php echo esc_html( $transaction_id ); ?>"/></p>
<p>
<label for="<?php echo esc_attr( self::NAME_PREFIX ); ?>-tracking_number"><?php echo esc_html__( 'Tracking Number', 'woocommerce-paypal-payments' ); ?></label>
<input type="text" class="<?php echo esc_attr( self::NAME_PREFIX ); ?>-tracking_number" id="<?php echo esc_attr( self::NAME_PREFIX ); ?>-tracking_number" name="<?php echo esc_attr( self::NAME_PREFIX ); ?>[tracking_number]" value="<?php echo esc_html( $tracking_number ); ?>"/></p>
<p>
<label for="<?php echo esc_attr( self::NAME_PREFIX ); ?>-status"><?php echo esc_html__( 'Status', 'woocommerce-paypal-payments' ); ?></label>
<select class="<?php echo esc_attr( self::NAME_PREFIX ); ?>-status" id="<?php echo esc_attr( self::NAME_PREFIX ); ?>-status" name="<?php echo esc_attr( self::NAME_PREFIX ); ?>[status]">
<?php foreach ( $statuses as $status ) : ?>
<option value="<?php echo esc_attr( $status ); ?>" <?php selected( $status_value, $status ); ?>><?php echo esc_html( $status ); ?></option>
<?php endforeach; ?>
</select>
</p>
<p>
<label for="ppcp-tracking-carrier"><?php echo esc_html__( 'Carrier', 'woocommerce-paypal-payments' ); ?></label>
<select class="ppcp-tracking-carrier" id="ppcp-tracking-carrier" name="ppcp-tracking[carrier]">
<option value=""><?php echo esc_html__( 'Select Carrier', 'woocommerce-paypal-payments' ); ?></option>
<?php
foreach ( $carriers as $carrier ) :
$country = $carrier['name'] ?? '';
$carrier_items = $carrier['items'] ?? array();
?>
<optgroup label="<?php echo esc_attr( $country ); ?>">
<?php foreach ( $carrier_items as $carrier_code => $carrier_name ) : ?>
<option value="<?php echo esc_attr( $carrier_code ); ?>" <?php selected( $carrier_value, $carrier_code ); ?>><?php echo esc_html( $carrier_name ); ?></option>
<?php endforeach; ?>
</optgroup>
<?php endforeach; ?>
</select>
</p>
<input type="hidden" class="ppcp-order_id" name="<?php echo esc_attr( self::NAME_PREFIX ); ?>[order_id]" value="<?php echo intval( $post->ID ); ?>"/>
<p>
<button type="button" class="button submit_tracking_info" data-action="<?php echo esc_attr( $action ); ?>"><?php echo esc_html( ucfirst( $action ) ); ?></button></p>
<?php
}
}

View file

@ -0,0 +1,149 @@
<?php
/**
* The order tracking module.
*
* @package WooCommerce\PayPalCommerce\OrderTracking
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\OrderTracking;
use Dhii\Container\ServiceProvider;
use Dhii\Modular\Module\ModuleInterface;
use Exception;
use Interop\Container\ServiceProviderInterface;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use WC_Order;
use WooCommerce\PayPalCommerce\OrderTracking\Assets\OrderEditPageAssets;
use WooCommerce\PayPalCommerce\OrderTracking\Endpoint\OrderTrackingEndpoint;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceHelper;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
/**
* Class OrderTrackingModule
*/
class OrderTrackingModule implements ModuleInterface {
/**
* {@inheritDoc}
*/
public function setup(): ServiceProviderInterface {
return new ServiceProvider(
require __DIR__ . '/../services.php',
require __DIR__ . '/../extensions.php'
);
}
/**
* {@inheritDoc}
*
* @param ContainerInterface $c A services container instance.
* @throws NotFoundException
*/
public function run( ContainerInterface $c ): void {
$settings = $c->get( 'wcgateway.settings' );
assert( $settings instanceof Settings );
$pui_helper = $c->get( 'wcgateway.pay-upon-invoice-helper' );
assert( $pui_helper instanceof PayUponInvoiceHelper );
if ( $pui_helper->is_pui_enabled() ) {
$settings->set( 'tracking_enabled', true );
$settings->persist();
}
$tracking_enabled = $settings->has( 'tracking_enabled' ) && $settings->get( 'tracking_enabled' );
if ( ! $tracking_enabled ) {
return;
}
$asset_loader = $c->get( 'order-tracking.assets' );
assert( $asset_loader instanceof OrderEditPageAssets );
$is_paypal_order_edit_page = $c->get( 'order-tracking.is-paypal-order-edit-page' );
$endpoint = $c->get( 'order-tracking.endpoint.controller' );
assert( $endpoint instanceof OrderTrackingEndpoint );
$logger = $c->get( 'woocommerce.logger.woocommerce' );
assert( $logger instanceof LoggerInterface );
add_action(
'init',
static function () use ( $asset_loader, $is_paypal_order_edit_page ) {
if ( ! $is_paypal_order_edit_page ) {
return;
}
$asset_loader->register();
}
);
add_action(
'admin_enqueue_scripts',
static function () use ( $asset_loader, $is_paypal_order_edit_page ) {
if ( ! $is_paypal_order_edit_page ) {
return;
}
$asset_loader->enqueue();
}
);
add_action(
'wc_ajax_' . OrderTrackingEndpoint::ENDPOINT,
array( $endpoint, 'handle_request' )
);
$meta_box_renderer = $c->get( 'order-tracking.meta-box.renderer' );
add_action(
'add_meta_boxes',
static function() use ( $meta_box_renderer, $is_paypal_order_edit_page ) {
if ( ! $is_paypal_order_edit_page ) {
return;
}
add_meta_box( 'ppcp_order-tracking', __( 'Tracking Information', 'woocommerce-paypal-payments' ), array( $meta_box_renderer, 'render' ), 'shop_order', 'side' );
},
10,
2
);
add_action(
'woocommerce_order_status_completed',
static function( int $order_id ) use ( $endpoint, $logger ) {
$tracking_information = $endpoint->get_tracking_information( $order_id );
if ( $tracking_information ) {
return;
}
$wc_order = wc_get_order( $order_id );
if ( ! is_a( $wc_order, WC_Order::class ) ) {
return;
}
$transaction_id = $wc_order->get_transaction_id();
if ( empty( $transaction_id ) ) {
return;
}
$tracking_data = array(
'transaction_id' => $transaction_id,
'status' => 'SHIPPED',
);
try {
$endpoint->add_tracking_information( $tracking_data, $order_id );
} catch ( Exception $exception ) {
$logger->error( "Couldn't create tracking information: " . $exception->getMessage() );
throw $exception;
}
}
);
}
}

View file

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

File diff suppressed because it is too large Load diff

View file

@ -72,6 +72,8 @@ class StatusReportModule implements ModuleInterface {
$had_ppec_plugin = PPECHelper::is_plugin_configured();
$is_tracking_available = $c->get( 'order-tracking.is-tracking-available' );
$items = array(
array(
'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ),
@ -149,6 +151,12 @@ class StatusReportModule implements ModuleInterface {
$had_ppec_plugin
),
),
array(
'label' => esc_html__( 'Tracking enabled', 'woocommerce-paypal-payments' ),
'exported_label' => 'Tracking enabled',
'description' => esc_html__( 'Whether tracking is enabled on PayPal account or not.', 'woocommerce-paypal-payments' ),
'value' => $this->bool_to_html( $is_tracking_available ),
),
);
echo wp_kses_post(

View file

@ -0,0 +1,439 @@
<?php
/**
* The services of the Gateway module.
*
* @package WooCommerce\PayPalCommerce\WcGateway
*/
// phpcs:disable WordPress.Security.NonceVerification.Recommended
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
use WooCommerce\PayPalCommerce\Onboarding\Environment;
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
return function ( ContainerInterface $container, array $fields ): array {
$state = $container->get( 'onboarding.state' );
assert( $state instanceof State );
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
assert( $dcc_applies instanceof DccApplies );
$is_shop_supports_dcc = $dcc_applies->for_country_currency() || $dcc_applies->for_wc_payments();
$onboarding_options_renderer = $container->get( 'onboarding.render-options' );
assert( $onboarding_options_renderer instanceof OnboardingOptionsRenderer );
$module_url = $container->get( 'wcgateway.url' );
$connection_fields = array(
'ppcp_onboarading_header' => array(
'type' => 'ppcp-text',
'classes' => array( 'ppcp-onboarding-element' ),
'text' => '
<div class="ppcp-onboarding-header">
<div class="ppcp-onboarding-header-left">
<img alt="PayPal" src="' . esc_url( $module_url ) . 'assets/images/paypal.png"/>
<h2>The all-in-one checkout solution</h2>
</div>
<div class="ppcp-onboarding-header-right">
<div class="ppcp-onboarding-header-paypal-logos">
<img alt="PayPal" src="' . esc_url( $module_url ) . 'assets/images/paypal-button.svg"/>
<img alt="Venmo" src="' . esc_url( $module_url ) . 'assets/images/venmo.svg"/>
<img alt="Pay Later" src="' . esc_url( $module_url ) . 'assets/images/paylater.svg"/>
</div>
<div class="ppcp-onboarding-header-cards">
<img alt="Visa" src="' . esc_url( $module_url ) . 'assets/images/visa-dark.svg"/>
<img alt="Mastercard" src="' . esc_url( $module_url ) . 'assets/images/mastercard-dark.svg"/>
<img alt="American Express" src="' . esc_url( $module_url ) . 'assets/images/amex.svg"/>
<img alt="Discover" src="' . esc_url( $module_url ) . 'assets/images/discover.svg"/>
<img alt="iDEAL" src="' . esc_url( $module_url ) . 'assets/images/ideal-dark.svg"/>
<img alt="Sofort" src="' . esc_url( $module_url ) . 'assets/images/sofort.svg"/>
</div>
</div>
</div>',
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'credentials_production_heading' => array(
'heading' => __( 'API Credentials', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::PRODUCTION,
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'credentials_sandbox_heading' => array(
'heading' => __( 'Sandbox API Credentials', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::SANDBOX,
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Your account is connected to sandbox, no real charging takes place. To accept live payments, turn off sandbox mode and connect your live PayPal account.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarading_options' => array(
'type' => 'ppcp-text',
'classes' => array( 'ppcp-onboarding-element' ),
'text' => $onboarding_options_renderer->render( $is_shop_supports_dcc ),
'raw' => true,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
// We need to have a button for each option (ppcp, express)
// because currently the only documented way to use the PayPal onboarding JS library
// is to have the buttons before loading the script.
'ppcp_onboarding_production_ppcp' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::PRODUCTION,
'env' => Environment::PRODUCTION,
'products' => array( 'PPCP' ),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'ppcp_onboarding_production_express' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::PRODUCTION,
'env' => Environment::PRODUCTION,
'products' => array( 'EXPRESS_CHECKOUT' ),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'ppcp_onboarding_sandbox_ppcp' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::SANDBOX,
'env' => Environment::SANDBOX,
'products' => array( 'PPCP' ),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Prior to accepting live payments, you can test payments on your WooCommerce platform in a safe PayPal sandbox environment.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarding_sandbox_express' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::SANDBOX,
'env' => Environment::SANDBOX,
'products' => array( 'EXPRESS_CHECKOUT' ),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Prior to accepting live payments, you can test payments on your WooCommerce platform in a safe PayPal sandbox environment.', 'woocommerce-paypal-payments' ),
),
'ppcp_disconnect_production' => array(
'title' => __( 'Disconnect from PayPal', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => sprintf(
'<p>%1$s <span class="dashicons dashicons-yes"></span></p><p><button type="button" class="button ppcp-disconnect production">%2$s</button></p>',
esc_html__( 'Status: Connected', 'woocommerce-paypal-payments' ),
esc_html__( 'Disconnect Account', 'woocommerce-paypal-payments' )
),
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::PRODUCTION,
'env' => Environment::PRODUCTION,
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Click to reset current credentials and use another account.', 'woocommerce-paypal-payments' ),
),
'ppcp_disconnect_sandbox' => array(
'title' => __( 'Disconnect from PayPal Sandbox', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => sprintf(
'<p>%1$s <span class="dashicons dashicons-yes"></span></p><p><button type="button" class="button ppcp-disconnect sandbox">%2$s</button></p>',
esc_html__( 'Status: Connected', 'woocommerce-paypal-payments' ),
esc_html__( 'Disconnect Account', 'woocommerce-paypal-payments' )
),
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::SANDBOX,
'env' => Environment::SANDBOX,
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Click to reset current credentials and use another account.', 'woocommerce-paypal-payments' ),
),
'toggle_manual_input' => array(
'type' => 'ppcp-text',
'text' => '<button type="button" id="ppcp[toggle_manual_input]">' . __( 'Toggle to manual credential input', 'woocommerce-paypal-payments' ) . '</button>',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'error_label' => array(
'type' => 'ppcp-text',
'text' => '<label class="error" id="ppcp-form-errors-label"></label>',
'classes' => array( 'hide', 'ppcp-always-shown-element' ),
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'sandbox_on' => array(
'title' => __( 'Sandbox', 'woocommerce-paypal-payments' ),
'classes' => array( 'ppcp-onboarding-element', 'ppcp-always-shown-element' ),
'type' => 'checkbox',
'label' => __( 'To test your WooCommerce installation, you can use the sandbox mode.', 'woocommerce-paypal-payments' ),
'default' => 0,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'merchant_email_production' => array(
'title' => __( 'Live Email address', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'text',
'required' => true,
'desc_tip' => true,
'description' => __( 'The email address of your PayPal account.', 'woocommerce-paypal-payments' ),
'default' => '',
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'merchant_id_production' => array(
'title' => __( 'Live Merchant Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The merchant id of your account ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'client_id_production' => array(
'title' => __( 'Live Client Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The client id of your api ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'client_secret_production' => array(
'title' => __( 'Live Secret Key', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-password',
'desc_tip' => true,
'description' => __( 'The secret key of your api', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'merchant_email_sandbox' => array(
'title' => __( 'Sandbox Email address', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'text',
'required' => true,
'desc_tip' => true,
'description' => __( 'The email address of your PayPal account.', 'woocommerce-paypal-payments' ),
'default' => '',
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'merchant_id_sandbox' => array(
'title' => __( 'Sandbox Merchant Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The merchant id of your account ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'client_id_sandbox' => array(
'title' => __( 'Sandbox Client Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The client id of your api ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'client_secret_sandbox' => array(
'title' => __( 'Sandbox Secret Key', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-password',
'desc_tip' => true,
'description' => __( 'The secret key of your api', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'credentials_feature_onboarding_heading' => array(
'heading' => __( 'Feature Onboarding', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'See which features are available.', 'woocommerce-paypal-payments' ),
),
'ppcp_dcc_status' => array(
'title' => __( 'Advanced Credit and Debit Card Payments', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => $container->get( 'wcgateway.settings.connection.dcc-status-text' ),
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array( 'dcc' ),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'ppcp_pui_status' => array(
'title' => __( 'Pay Upon Invoice', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => $container->get( 'wcgateway.settings.connection.pui-status-text' ),
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array( 'pui_ready' ),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'tracking_enabled' => array(
'title' => __( 'Tracking', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
'desc_tip' => true,
'label' => $container->get( 'wcgateway.settings.tracking-label' ),
'description' => __( 'Allows to send shipment tracking numbers to PayPal for PayPal transactions.', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'input_class' => $container->get( 'wcgateway.settings.should-disable-tracking-checkbox' ) ? array( 'ppcp-disabled-checkbox' ) : array(),
),
'credentials_integration_configuration_heading' => array(
'heading' => __( 'Integration configuration', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'See which features are available.', 'woocommerce-paypal-payments' ),
),
'prefix' => array(
'title' => __( 'Invoice prefix', 'woocommerce-paypal-payments' ),
'type' => 'text',
'desc_tip' => true,
'description' => __( 'If you use your PayPal account with more than one installation, please use a distinct prefix to separate those installations. Please use only English letters and "-", "_" characters.', 'woocommerce-paypal-payments' ),
'maxlength' => 15,
'custom_attributes' => array(
'pattern' => '[a-zA-Z_-]+',
),
'default' => ( static function (): string {
$site_url = get_site_url( get_current_blog_id() );
$hash = md5( $site_url );
$letters = preg_replace( '~\d~', '', $hash ) ?? '';
$prefix = substr( $letters, 0, 6 );
return $prefix ? $prefix . '-' : '';
} )(),
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'logging_enabled' => array(
'title' => __( 'Logging', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
'desc_tip' => true,
'label' => __( 'Enable logging. ', 'woocommerce-paypal-payments' ) .
' <a href="' . admin_url( 'admin.php?page=wc-status&tab=logs' ) . '">' . __( 'View logs', 'woocommerce-paypal-payments' ) . '</a>',
'description' => __( 'Enable logging of unexpected behavior. This can also log private data and should only be enabled in a development or stage environment.', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
);
return array_merge( $fields, $connection_fields );
};

View file

@ -98,4 +98,6 @@ return array(
$source
);
},
'wcgateway.settings.fields' => require __DIR__ . '/connection-tab-settings.php',
);

View file

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PayUponInvoiceOrderEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
@ -53,6 +54,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Notice\GatewayWithoutPayPalAdminNotice;
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Settings\HeaderRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SectionsRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
@ -141,11 +143,15 @@ return array(
$settings = $container->get( 'wcgateway.settings' );
return new DisableGateways( $session_handler, $settings );
},
'wcgateway.is-wc-payments-page' => static function ( ContainerInterface $container ): bool {
$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
$tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : '';
return 'wc-settings' === $page && 'checkout' === $tab;
},
'wcgateway.is-wc-gateways-list-page' => static function ( ContainerInterface $container ): bool {
return $container->get( 'wcgateway.is-wc-payments-page' ) && ! isset( $_GET['section'] );
},
'wcgateway.is-ppcp-settings-page' => static function ( ContainerInterface $container ): bool {
if ( ! $container->get( 'wcgateway.is-wc-payments-page' ) ) {
@ -153,7 +159,7 @@ return array(
}
$section = isset( $_GET['section'] ) ? sanitize_text_field( wp_unslash( $_GET['section'] ) ) : '';
return in_array( $section, array( PayPalGateway::ID, CreditCardGateway::ID, WebhooksStatusPage::ID, PayUponInvoiceGateway::ID, CardButtonGateway::ID, OXXOGateway::ID ), true );
return in_array( $section, array( Settings::CONNECTION_TAB_ID, PayPalGateway::ID, CreditCardGateway::ID, WebhooksStatusPage::ID, PayUponInvoiceGateway::ID, CardButtonGateway::ID, OXXOGateway::ID ), true );
},
'wcgateway.current-ppcp-settings-page-id' => static function ( ContainerInterface $container ): string {
@ -200,11 +206,19 @@ return array(
'wcgateway.settings.sections-renderer' => static function ( ContainerInterface $container ): SectionsRenderer {
return new SectionsRenderer(
$container->get( 'wcgateway.current-ppcp-settings-page-id' ),
$container->get( 'wcgateway.settings.sections' )
$container->get( 'wcgateway.settings.sections' ),
$container->get( 'onboarding.state' )
);
},
'wcgateway.settings.header-renderer' => static function ( ContainerInterface $container ): HeaderRenderer {
return new HeaderRenderer(
$container->get( 'wcgateway.current-ppcp-settings-page-id' ),
$container->get( 'wcgateway.url' )
);
},
'wcgateway.settings.sections' => static function ( ContainerInterface $container ): array {
$sections = array(
Settings::CONNECTION_TAB_ID => __( 'Connection', 'woocommerce-paypal-payments' ),
PayPalGateway::ID => __( 'PayPal Checkout', 'woocommerce-paypal-payments' ),
CreditCardGateway::ID => __( 'PayPal Card Processing', 'woocommerce-paypal-payments' ),
CardButtonGateway::ID => __( 'PayPal Card Button', 'woocommerce-paypal-payments' ),
@ -217,7 +231,7 @@ return array(
$gateways = WC()->payment_gateways->payment_gateways();
foreach ( array_diff(
array_keys( $sections ),
array( PayPalGateway::ID, CreditCardGateway::ID, WebhooksStatusPage::ID )
array( Settings::CONNECTION_TAB_ID, PayPalGateway::ID, CreditCardGateway::ID, WebhooksStatusPage::ID )
) as $id ) {
if ( ! isset( $gateways[ $id ] ) ) {
unset( $sections[ $id ] );
@ -239,6 +253,7 @@ return array(
$dcc_product_status = $container->get( 'wcgateway.helper.dcc-product-status' );
$settings_status = $container->get( 'wcgateway.settings.status' );
$page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' );
$api_shop_country = $container->get( 'api.shop.country' );
return new SettingsRenderer(
$settings,
$state,
@ -247,7 +262,8 @@ return array(
$messages_apply,
$dcc_product_status,
$settings_status,
$page_id
$page_id,
$api_shop_country
);
},
'wcgateway.settings.listener' => static function ( ContainerInterface $container ): SettingsListener {
@ -345,313 +361,10 @@ return array(
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
assert( $dcc_applies instanceof DccApplies );
$is_shop_supports_dcc = $dcc_applies->for_country_currency();
$onboarding_options_renderer = $container->get( 'onboarding.render-options' );
assert( $onboarding_options_renderer instanceof OnboardingOptionsRenderer );
$module_url = $container->get( 'wcgateway.url' );
$fields = array(
'ppcp_onboarading_header' => array(
'type' => 'ppcp-text',
'classes' => array( 'ppcp-onboarding-element' ),
'text' => '
<div class="ppcp-onboarding-header">
<div class="ppcp-onboarding-header-left">
<img alt="PayPal" src="' . esc_url( $module_url ) . 'assets/images/paypal.png"/>
<h2>The all-in-one checkout solution</h2>
</div>
<div class="ppcp-onboarding-header-right">
<div class="ppcp-onboarding-header-paypal-logos">
<img alt="PayPal" src="' . esc_url( $module_url ) . 'assets/images/paypal-button.svg"/>
<img alt="Venmo" src="' . esc_url( $module_url ) . 'assets/images/venmo.svg"/>
<img alt="Pay Later" src="' . esc_url( $module_url ) . 'assets/images/paylater.svg"/>
</div>
<div class="ppcp-onboarding-header-cards">
<img alt="Visa" src="' . esc_url( $module_url ) . 'assets/images/visa-dark.svg"/>
<img alt="Mastercard" src="' . esc_url( $module_url ) . 'assets/images/mastercard-dark.svg"/>
<img alt="American Express" src="' . esc_url( $module_url ) . 'assets/images/amex.svg"/>
<img alt="Discover" src="' . esc_url( $module_url ) . 'assets/images/discover.svg"/>
<img alt="iDEAL" src="' . esc_url( $module_url ) . 'assets/images/ideal-dark.svg"/>
<img alt="Sofort" src="' . esc_url( $module_url ) . 'assets/images/sofort.svg"/>
</div>
</div>
</div>',
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'credentials_production_heading' => array(
'heading' => __( 'API Credentials', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::PRODUCTION,
'requirements' => array(),
'gateway' => 'paypal',
),
'credentials_sandbox_heading' => array(
'heading' => __( 'Sandbox API Credentials', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::SANDBOX,
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Your account is connected to sandbox, no real charging takes place. To accept live payments, turn off sandbox mode and connect your live PayPal account.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarading_options' => array(
'type' => 'ppcp-text',
'classes' => array( 'ppcp-onboarding-element' ),
'text' => $onboarding_options_renderer->render( $is_shop_supports_dcc ),
'raw' => true,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
// We need to have a button for each option (ppcp, express)
// because currently the only documented way to use the PayPal onboarding JS library
// is to have the buttons before loading the script.
'ppcp_onboarding_production_ppcp' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::PRODUCTION,
'env' => Environment::PRODUCTION,
'products' => array( 'PPCP' ),
'requirements' => array(),
'gateway' => 'paypal',
),
'ppcp_onboarding_production_express' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::PRODUCTION,
'env' => Environment::PRODUCTION,
'products' => array( 'EXPRESS_CHECKOUT' ),
'requirements' => array(),
'gateway' => 'paypal',
),
'ppcp_onboarding_sandbox_ppcp' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::SANDBOX,
'env' => Environment::SANDBOX,
'products' => array( 'PPCP' ),
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Prior to accepting live payments, you can test payments on your WooCommerce platform in a safe PayPal sandbox environment.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarding_sandbox_express' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::SANDBOX,
'env' => Environment::SANDBOX,
'products' => array( 'EXPRESS_CHECKOUT' ),
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Prior to accepting live payments, you can test payments on your WooCommerce platform in a safe PayPal sandbox environment.', 'woocommerce-paypal-payments' ),
),
'ppcp_disconnect_production' => array(
'title' => __( 'Disconnect from PayPal', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => '<button type="button" class="button ppcp-disconnect production">' . esc_html__( 'Disconnect', 'woocommerce-paypal-payments' ) . '</button>',
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::PRODUCTION,
'env' => Environment::PRODUCTION,
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Click to reset current credentials and use another account.', 'woocommerce-paypal-payments' ),
),
'ppcp_disconnect_sandbox' => array(
'title' => __( 'Disconnect from PayPal Sandbox', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => '<button type="button" class="button ppcp-disconnect sandbox">' . esc_html__( 'Disconnect', 'woocommerce-paypal-payments' ) . '</button>',
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::SANDBOX,
'env' => Environment::SANDBOX,
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Click to reset current credentials and use another account.', 'woocommerce-paypal-payments' ),
),
'toggle_manual_input' => array(
'type' => 'ppcp-text',
'text' => '<button type="button" id="ppcp[toggle_manual_input]">' . __( 'Toggle to manual credential input', 'woocommerce-paypal-payments' ) . '</button>',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'error_label' => array(
'type' => 'ppcp-text',
'text' => '<label class="error" id="ppcp-form-errors-label"></label>',
'classes' => array( 'hide', 'ppcp-always-shown-element' ),
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'sandbox_on' => array(
'title' => __( 'Sandbox', 'woocommerce-paypal-payments' ),
'classes' => array( 'ppcp-onboarding-element', 'ppcp-always-shown-element' ),
'type' => 'checkbox',
'label' => __( 'To test your WooCommerce installation, you can use the sandbox mode.', 'woocommerce-paypal-payments' ),
'default' => 0,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'merchant_email_production' => array(
'title' => __( 'Live Email address', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'text',
'required' => true,
'desc_tip' => true,
'description' => __( 'The email address of your PayPal account.', 'woocommerce-paypal-payments' ),
'default' => '',
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'merchant_id_production' => array(
'title' => __( 'Live Merchant Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The merchant id of your account ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'client_id_production' => array(
'title' => __( 'Live Client Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The client id of your api ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'client_secret_production' => array(
'title' => __( 'Live Secret Key', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-password',
'desc_tip' => true,
'description' => __( 'The secret key of your api', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'merchant_email_sandbox' => array(
'title' => __( 'Sandbox Email address', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'text',
'required' => true,
'desc_tip' => true,
'description' => __( 'The email address of your PayPal account.', 'woocommerce-paypal-payments' ),
'default' => '',
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'merchant_id_sandbox' => array(
'title' => __( 'Sandbox Merchant Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The merchant id of your account ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'client_id_sandbox' => array(
'title' => __( 'Sandbox Client Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The client id of your api ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'client_secret_sandbox' => array(
'title' => __( 'Sandbox Secret Key', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-password',
'desc_tip' => true,
'description' => __( 'The secret key of your api', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'checkout_settings_heading' => array(
'heading' => __( 'PayPal Checkout Settings', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
@ -861,62 +574,6 @@ return array(
'gateway' => array( 'paypal', 'dcc' ),
'input_class' => $container->get( 'wcgateway.helper.vaulting-scope' ) ? array() : array( 'ppcp-disabled-checkbox' ),
),
'subscription_behavior_when_vault_fails' => array(
'title' => __( 'Subscription capture behavior if Vault fails', 'woocommerce-paypal-payments' ),
'type' => 'select',
'class' => array(),
'input_class' => array( 'wc-enhanced-select' ),
'default' => 'void_auth',
'desc_tip' => true,
'description' => __( 'By default, subscription payments are captured only when saving the payment method was successful. Without a saved payment method, automatic renewal payments are not possible.', 'woocommerce-paypal-payments' ),
'description_with_tip' => __( 'Determines whether authorized payments for subscription orders are captured or voided if there is no saved payment method. This only applies when the intent Capture is used for the subscription order.', 'woocommerce-paypal-payments' ),
'options' => array(
'void_auth' => __( 'Void authorization & fail the order/subscription', 'woocommerce-paypal-payments' ),
'capture_auth' => __( 'Capture authorized payment & set subscription to Manual Renewal', 'woocommerce-paypal-payments' ),
),
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => array( 'paypal', 'dcc' ),
),
'logging_enabled' => array(
'title' => __( 'Logging', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
'desc_tip' => true,
'label' => __( 'Enable logging. ', 'woocommerce-paypal-payments' ) .
' <a href="' . admin_url( 'admin.php?page=wc-status&tab=logs' ) . '">' . __( 'View logs', 'woocommerce-paypal-payments' ) . '</a>',
'description' => __( 'Enable logging of unexpected behavior. This can also log private data and should only be enabled in a development or stage environment.', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'prefix' => array(
'title' => __( 'Invoice prefix', 'woocommerce-paypal-payments' ),
'type' => 'text',
'desc_tip' => true,
'description' => __( 'If you use your PayPal account with more than one installation, please use a distinct prefix to separate those installations. Please use only English letters and "-", "_" characters.', 'woocommerce-paypal-payments' ),
'maxlength' => 15,
'custom_attributes' => array(
'pattern' => '[a-zA-Z_-]+',
),
'default' => ( static function (): string {
$site_url = get_site_url( get_current_blog_id() );
$hash = md5( $site_url );
$letters = preg_replace( '~\d~', '', $hash );
return substr( $letters, 0, 6 ) . '-';
} )(),
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'card_billing_data_mode' => array(
'title' => __( 'Card billing data handling', 'woocommerce-paypal-payments' ),
'type' => 'select',
@ -2294,7 +1951,8 @@ return array(
},
'wcgateway.pay-upon-invoice-helper' => static function( ContainerInterface $container ): PayUponInvoiceHelper {
return new PayUponInvoiceHelper(
$container->get( 'wcgateway.checkout-helper' )
$container->get( 'wcgateway.checkout-helper' ),
$container->get( 'wcgateway.settings' )
);
},
'wcgateway.pay-upon-invoice-product-status' => static function( ContainerInterface $container ): PayUponInvoiceProductStatus {
@ -2368,12 +2026,7 @@ return array(
},
'button.helper.vaulting-label' => static function ( ContainerInterface $container ): string {
$vaulting_label = sprintf(
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag.
__( 'Enable saved cards, PayPal accounts, and subscription features on your store. Payment methods are saved in the secure %1$sPayPal Vault%2$s.', 'woocommerce-paypal-payments' ),
'<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#vaulting-saving-a-payment-method" target="_blank">',
'</a>'
);
$vaulting_label = __( 'Enable saved cards and subscription features on your store.', 'woocommerce-paypal-payments' );
if ( ! $container->get( 'wcgateway.helper.vaulting-scope' ) ) {
$vaulting_label .= sprintf(
@ -2388,20 +2041,7 @@ return array(
}
$vaulting_label .= '<p class="description">';
$vaulting_label .= sprintf(
// translators: %1$s, %2$s, %3$s and %4$s are the opening and closing of HTML <a> tag.
__( 'This will disable all %1$sPay Later%2$s features and %3$sAlternative Payment Methods%4$s on your site.', 'woocommerce-paypal-payments' ),
'<a
href="https://woocommerce.com/document/woocommerce-paypal-payments/#pay-later"
target="_blank"
>',
'</a>',
'<a
href="https://woocommerce.com/document/woocommerce-paypal-payments/#alternative-payment-methods"
target="_blank"
>',
'</a>'
);
$vaulting_label .= __( 'This will disable all Pay Later messaging on your site.', 'woocommerce-paypal-payments' );
$vaulting_label .= '</p>';
return $vaulting_label;
@ -2443,4 +2083,132 @@ return array(
(bool) $settings->get( 'allow_card_button_gateway' ) :
$container->get( 'wcgateway.settings.allow_card_button_gateway.default' );
},
'order-tracking.is-tracking-available' => static function ( ContainerInterface $container ): bool {
try {
$bearer = $container->get( 'api.bearer' );
assert( $bearer instanceof Bearer );
$token = $bearer->bearer();
return $token->is_tracking_available();
} catch ( RuntimeException $exception ) {
return false;
}
},
'wcgateway.settings.should-disable-tracking-checkbox' => static function ( ContainerInterface $container ): bool {
$pui_helper = $container->get( 'wcgateway.pay-upon-invoice-helper' );
assert( $pui_helper instanceof PayUponInvoiceHelper );
$is_tracking_available = $container->get( 'order-tracking.is-tracking-available' );
if ( ! $is_tracking_available ) {
return true;
}
if ( $pui_helper->is_pui_enabled() ) {
return true;
}
return false;
},
'wcgateway.settings.tracking-label' => static function ( ContainerInterface $container ): string {
$tracking_label = __( 'Enable tracking information feature on your store.', 'woocommerce-paypal-payments' );
$is_tracking_available = $container->get( 'order-tracking.is-tracking-available' );
if ( $is_tracking_available ) {
return $tracking_label;
}
$tracking_label .= sprintf(
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag.
__(
' To use tracking features, you must %1$senable tracking on your account%2$s.',
'woocommerce-paypal-payments'
),
'<a
href="https://docs.woocommerce.com/document/woocommerce-paypal-payments/#enable-tracking-on-your-live-account"
target="_blank"
>',
'</a>'
);
return $tracking_label;
},
'wcgateway.enable-dcc-url-sandbox' => static function ( ContainerInterface $container ): string {
return 'https://www.sandbox.paypal.com/bizsignup/entry/product/ppcp';
},
'wcgateway.enable-dcc-url-live' => static function ( ContainerInterface $container ): string {
return 'https://www.paypal.com/bizsignup/entry/product/ppcp';
},
'wcgateway.enable-pui-url-sandbox' => static function ( ContainerInterface $container ): string {
return 'https://www.sandbox.paypal.com/bizsignup/entry?country.x=DE&product=payment_methods&capabilities=PAY_UPON_INVOICE';
},
'wcgateway.enable-pui-url-live' => static function ( ContainerInterface $container ): string {
return 'https://www.paypal.com/bizsignup/entry?country.x=DE&product=payment_methods&capabilities=PAY_UPON_INVOICE';
},
'wcgateway.settings.connection.dcc-status-text' => static function ( ContainerInterface $container ): string {
$dcc_product_status = $container->get( 'wcgateway.helper.dcc-product-status' );
assert( $dcc_product_status instanceof DCCProductStatus );
$environment = $container->get( 'onboarding.environment' );
assert( $environment instanceof Environment );
$dcc_enabled = $dcc_product_status->dcc_is_active();
$enabled_status_text = esc_html__( 'Status: Enabled', 'woocommerce-paypal-payments' );
$disabled_status_text = esc_html__( 'Status: Not yet enabled', 'woocommerce-paypal-payments' );
$dcc_button_text = $dcc_enabled
? esc_html__( 'Settings', 'woocommerce-paypal-payments' )
: esc_html__( 'Enable Advanced Card Payments', 'woocommerce-paypal-payments' );
$enable_dcc_url = $environment->current_environment_is( Environment::PRODUCTION )
? $container->get( 'wcgateway.enable-dcc-url-live' )
: $container->get( 'wcgateway.enable-dcc-url-sandbox' );
$dcc_button_url = $dcc_enabled
? admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway&ppcp-tab=ppcp-credit-card-gateway' )
: $enable_dcc_url;
return sprintf(
'<p>%1$s %2$s</p><p><a target="%3$s" href="%4$s" class="button">%5$s</a></p>',
$dcc_enabled ? $enabled_status_text : $disabled_status_text,
$dcc_enabled ? '<span class="dashicons dashicons-yes"></span>' : '<span class="dashicons dashicons-no"></span>',
$dcc_enabled ? '_self' : '_blank',
esc_url( $dcc_button_url ),
esc_html( $dcc_button_text )
);
},
'wcgateway.settings.connection.pui-status-text' => static function ( ContainerInterface $container ): string {
$pui_product_status = $container->get( 'wcgateway.pay-upon-invoice-product-status' );
assert( $pui_product_status instanceof PayUponInvoiceProductStatus );
$environment = $container->get( 'onboarding.environment' );
assert( $environment instanceof Environment );
$pui_enabled = $pui_product_status->pui_is_active();
$enabled_status_text = esc_html__( 'Status: Enabled', 'woocommerce-paypal-payments' );
$disabled_status_text = esc_html__( 'Status: Not yet enabled', 'woocommerce-paypal-payments' );
$enable_pui_url = $environment->current_environment_is( Environment::PRODUCTION )
? $container->get( 'wcgateway.enable-pui-url-live' )
: $container->get( 'wcgateway.enable-pui-url-sandbox' );
$pui_button_url = $pui_enabled
? admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-pay-upon-invoice-gateway' )
: $enable_pui_url;
$pui_button_text = $pui_enabled
? esc_html__( 'Settings', 'woocommerce-paypal-payments' )
: esc_html__( 'Enable Pay Upon Invoice', 'woocommerce-paypal-payments' );
return sprintf(
'<p>%1$s %2$s</p><p><a target="%3$s" href="%4$s" class="button">%5$s</a></p>',
$pui_enabled ? $enabled_status_text : $disabled_status_text,
$pui_enabled ? '<span class="dashicons dashicons-yes"></span>' : '<span class="dashicons dashicons-no"></span>',
$pui_enabled ? '_self' : '_blank',
esc_url( $pui_button_url ),
esc_html( $pui_button_text )
);
},
);

View file

@ -88,9 +88,12 @@ class DisableGateways {
* @return bool
*/
private function disable_all_gateways() : bool {
if ( ! $this->settings->has( 'enabled' ) || ! $this->settings->get( 'enabled' ) ) {
foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) {
if ( PayPalGateway::ID === $gateway->id && $gateway->enabled !== 'yes' ) {
return true;
}
}
if ( ! $this->settings->has( 'merchant_email' ) || ! is_email( $this->settings->get( 'merchant_email' ) ) ) {
return true;
}

View file

@ -26,6 +26,7 @@ use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice\PayUponInvoiceGateway;
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\Webhooks\Status\WebhooksStatusPage;
@ -290,6 +291,9 @@ class PayPalGateway extends \WC_Payment_Gateway {
* @return string
*/
private function define_method_title(): string {
if ( $this->is_connection_tab() ) {
return __( 'Account Setup', 'woocommerce-paypal-payments' );
}
if ( $this->is_credit_card_tab() ) {
return __( 'PayPal Card Processing', 'woocommerce-paypal-payments' );
}
@ -312,6 +316,10 @@ class PayPalGateway extends \WC_Payment_Gateway {
* @return string
*/
private function define_method_description(): string {
if ( $this->is_connection_tab() ) {
return '';
}
if ( $this->is_credit_card_tab() ) {
return __(
'Accept debit and credit cards, and local payment methods.',
@ -374,6 +382,16 @@ class PayPalGateway extends \WC_Payment_Gateway {
&& WebhooksStatusPage::ID === $this->page_id;
}
/**
* Whether we are on the connection tab.
*
* @return bool true if is connection tab, otherwise false
*/
protected function is_connection_tab() : bool {
return is_admin()
&& Settings::CONNECTION_TAB_ID === $this->page_id;
}
/**
* Whether we are on the PayPal settings tab.
*

View file

@ -226,7 +226,7 @@ class PayUponInvoiceGateway extends WC_Payment_Gateway {
$payment_source = $this->payment_source_factory->from_wc_order( $wc_order, $birth_date );
try {
$order = $this->order_endpoint->create( array( $purchase_unit ), $payment_source );
$order = $this->order_endpoint->create( array( $purchase_unit ), $payment_source, $wc_order );
$this->add_paypal_meta( $wc_order, $order, $this->environment );
as_schedule_single_action(

View file

@ -9,9 +9,9 @@ declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Helper;
use Throwable;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
/**
@ -22,7 +22,7 @@ class DCCProductStatus {
/**
* Caches the status for the current load.
*
* @var string|null
* @var bool|null
*/
private $current_status_cache;
/**
@ -57,12 +57,12 @@ class DCCProductStatus {
* Whether the active/subscribed products support DCC.
*
* @return bool
* @throws \WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException Should a setting not be found.
*/
public function dcc_is_active() : bool {
if ( is_bool( $this->current_status_cache ) ) {
return $this->current_status_cache;
}
if ( $this->settings->has( 'products_dcc_enabled' ) && $this->settings->get( 'products_dcc_enabled' ) ) {
$this->current_status_cache = true;
return true;
@ -70,7 +70,7 @@ class DCCProductStatus {
try {
$seller_status = $this->partners_endpoint->seller_status();
} catch ( RuntimeException $error ) {
} catch ( Throwable $error ) {
$this->current_status_cache = false;
return false;
}

View file

@ -10,6 +10,8 @@ declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Helper;
use WC_Order;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
/**
* Class PayUponInvoiceHelper
@ -23,13 +25,23 @@ class PayUponInvoiceHelper {
*/
protected $checkout_helper;
/**
* The settings.
*
* @var Settings
*/
protected $settings;
/**
* PayUponInvoiceHelper constructor.
*
* @param CheckoutHelper $checkout_helper The checkout helper.
* @param Settings $settings The Settings.
*/
public function __construct( CheckoutHelper $checkout_helper ) {
public function __construct( CheckoutHelper $checkout_helper, Settings $settings ) {
$this->checkout_helper = $checkout_helper;
$this->settings = $settings;
}
/**
@ -78,4 +90,14 @@ class PayUponInvoiceHelper {
return false;
}
/**
* Checks whether PUI is enabled.
*
* @return bool True if PUI is active, otherwise false.
* @throws NotFoundException If problem when checking the settings.
*/
public function is_pui_enabled(): bool {
return $this->settings->has( 'products_pui_enabled' ) && $this->settings->get( 'products_pui_enabled' );
}
}

View file

@ -9,11 +9,10 @@ declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Helper;
use Throwable;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
/**
* Class PayUponInvoiceProductStatus
@ -70,7 +69,7 @@ class PayUponInvoiceProductStatus {
try {
$seller_status = $this->partners_endpoint->seller_status();
} catch ( RuntimeException $error ) {
} catch ( Throwable $error ) {
$this->current_status_cache = false;
return false;
}

View file

@ -0,0 +1,82 @@
<?php
/**
* Renders the settings page header.
*
* @package WooCommerce\PayPalCommerce\WcGateway\Settings
*/
declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Settings;
/**
* Class HeaderRenderer
*/
class HeaderRenderer {
const KEY = 'ppcp-tab';
/**
* ID of the current PPCP gateway settings page, or empty if it is not such page.
*
* @var string
*/
private $page_id;
/**
* The URL to the module.
*
* @var string
*/
private $module_url;
/**
* HeaderRenderer constructor.
*
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
* @param string $module_url The URL to the module.
*/
public function __construct( string $page_id, string $module_url ) {
$this->page_id = $page_id;
$this->module_url = $module_url;
}
/**
* Whether the sections tab should be rendered.
*
* @return bool
*/
public function should_render() : bool {
return ! empty( $this->page_id );
}
/**
* Renders the Sections tab.
*/
public function render(): string {
if ( ! $this->should_render() ) {
return '';
}
return '
<div class="ppcp-settings-page-header">
<img alt="PayPal" src="' . esc_url( $this->module_url ) . 'assets/images/paypal.png"/>
<h4> <span class="ppcp-inline-only">-</span> ' . __( 'The all-in-one checkout solution for WooCommerce', 'woocommerce-paypal-payments' ) . '</h4>
<a class="button" target="_blank" href="https://woocommerce.com/document/woocommerce-paypal-payments/">'
. __( 'Documentation', 'woocommerce-paypal-payments' ) .
'</a>
<a class="button" target="_blank" href="https://woocommerce.com/document/woocommerce-paypal-payments/#get-help">'
. __( 'Get Help', 'woocommerce-paypal-payments' ) .
'</a>
<span class="ppcp-right-align">
<a target="_blank" href="https://woocommerce.com/feature-requests/woocommerce-paypal-payments/">'
. __( 'Request a feature', 'woocommerce-paypal-payments' ) .
'</a>
<a target="_blank" href="https://github.com/woocommerce/woocommerce-paypal-payments/issues/new?assignees=&labels=type%3A+bug&template=bug_report.md">'
. __( 'Submit a bug', 'woocommerce-paypal-payments' ) .
'</a>
</span>
</div>
';
}
}

View file

@ -33,6 +33,7 @@ trait PageMatcherTrait {
}
$gateway_page_id_map = array(
Settings::CONNECTION_TAB_ID => Settings::CONNECTION_TAB_ID,
PayPalGateway::ID => 'paypal',
CreditCardGateway::ID => 'dcc', // TODO: consider using just the gateway ID for PayPal and DCC too.
CardButtonGateway::ID => CardButtonGateway::ID,

View file

@ -9,6 +9,7 @@ declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Settings;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\Webhooks\Status\WebhooksStatusPage;
@ -33,15 +34,24 @@ class SectionsRenderer {
*/
protected $sections;
/**
* The onboarding state.
*
* @var State
*/
private $state;
/**
* SectionsRenderer constructor.
*
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
* @param array<string, string> $sections Key - page/gateway ID, value - displayed text.
* @param State $state The onboarding state.
*/
public function __construct( string $page_id, array $sections ) {
public function __construct( string $page_id, array $sections, State $state ) {
$this->page_id = $page_id;
$this->sections = $sections;
$this->state = $state;
}
/**
@ -50,7 +60,9 @@ class SectionsRenderer {
* @return bool
*/
public function should_render() : bool {
return ! empty( $this->page_id );
return ! empty( $this->page_id ) &&
( $this->state->production_state() === State::STATE_ONBOARDED ||
$this->state->sandbox_state() === State::STATE_ONBOARDED );
}
/**
@ -65,7 +77,7 @@ class SectionsRenderer {
foreach ( $this->sections as $id => $label ) {
$url = admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . $id );
if ( in_array( $id, array( CreditCardGateway::ID, WebhooksStatusPage::ID ), true ) ) {
if ( in_array( $id, array( Settings::CONNECTION_TAB_ID, CreditCardGateway::ID, WebhooksStatusPage::ID ), true ) ) {
// We need section=ppcp-gateway for the webhooks page because it is not a gateway,
// and for DCC because otherwise it will not render the page if gateway is not available (country/currency).
// Other gateways render fields differently, and their pages are not expected to work when gateway is not available.

View file

@ -18,6 +18,7 @@ use Psr\Container\ContainerInterface;
class Settings implements ContainerInterface {
const KEY = 'woocommerce-ppcp-settings';
const CONNECTION_TAB_ID = 'ppcp-connection';
/**
* The settings.

View file

@ -174,7 +174,7 @@ class SettingsListener {
/**
* The URL opened at the end of onboarding after saving the merchant ID/email.
*/
$redirect_url = apply_filters( 'woocommerce_paypal_payments_onboarding_redirect_url', admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway' ) );
$redirect_url = apply_filters( 'woocommerce_paypal_payments_onboarding_redirect_url', admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway&ppcp-tab=ppcp-connection' ) );
if ( ! $this->settings->has( 'client_id' ) || ! $this->settings->get( 'client_id' ) ) {
$redirect_url = add_query_arg( 'ppcp-onboarding-error', '1', $redirect_url );
}
@ -235,7 +235,7 @@ class SettingsListener {
*
* @throws \WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException When a setting was not found.
*/
public function listen() {
public function listen(): void {
if ( ! $this->is_valid_update_request() ) {
return;
@ -259,7 +259,7 @@ class SettingsListener {
$credentials_change_status = null; // Cannot detect on Card Processing page.
if ( PayPalGateway::ID === $this->page_id ) {
if ( PayPalGateway::ID === $this->page_id || Settings::CONNECTION_TAB_ID === $this->page_id ) {
$settings['enabled'] = isset( $_POST['woocommerce_ppcp-gateway_enabled'] )
&& 1 === absint( $_POST['woocommerce_ppcp-gateway_enabled'] );
@ -267,7 +267,6 @@ class SettingsListener {
}
// phpcs:enable phpcs:disable WordPress.Security.NonceVerification.Missing
// phpcs:enable phpcs:disable WordPress.Security.NonceVerification.Missing
if ( $credentials_change_status ) {
if ( self::CREDENTIALS_UNCHANGED !== $credentials_change_status ) {
$this->settings->set( 'products_dcc_enabled', null );
@ -473,4 +472,36 @@ class SettingsListener {
}
return true;
}
/**
* Prevent enabling tracking if it is not enabled for merchant account.
*/
public function listen_for_tracking_enabled(): void {
if ( State::STATE_ONBOARDED !== $this->state->current_state() ) {
return;
}
try {
$token = $this->bearer->bearer();
if ( ! $token->is_tracking_available() ) {
$this->settings->set( 'tracking_enabled', false );
$this->settings->persist();
return;
}
} catch ( RuntimeException $exception ) {
$this->settings->set( 'tracking_enabled', false );
$this->settings->persist();
add_action(
'admin_notices',
function () use ( $exception ) {
printf(
'<div class="notice notice-error"><p>%1$s</p><p>%2$s</p></div>',
esc_html__( 'Authentication with PayPal failed: ', 'woocommerce-paypal-payments' ) . esc_attr( $exception->getMessage() ),
wp_kses_post( __( 'Please verify your API Credentials and try again to connect your PayPal business account. Visit the <a href="https://docs.woocommerce.com/document/woocommerce-paypal-payments/" target="_blank">plugin documentation</a> for more information about the setup.', 'woocommerce-paypal-payments' ) )
);
}
);
}
}
}

View file

@ -33,6 +33,13 @@ class SettingsRenderer {
*/
protected $settings_status;
/**
* The api shop country.
*
* @var string
*/
protected $api_shop_country;
/**
* The settings.
*
@ -93,6 +100,7 @@ class SettingsRenderer {
* @param DCCProductStatus $dcc_product_status The product status.
* @param SettingsStatus $settings_status The Settings status helper.
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
* @param string $api_shop_country The api shop country.
*/
public function __construct(
ContainerInterface $settings,
@ -102,7 +110,8 @@ class SettingsRenderer {
MessagesApply $messages_apply,
DCCProductStatus $dcc_product_status,
SettingsStatus $settings_status,
string $page_id
string $page_id,
string $api_shop_country
) {
$this->settings = $settings;
@ -113,6 +122,7 @@ class SettingsRenderer {
$this->dcc_product_status = $dcc_product_status;
$this->settings_status = $settings_status;
$this->page_id = $page_id;
$this->api_shop_country = $api_shop_country;
}
/**
@ -348,7 +358,7 @@ $data_rows_html
/**
* Renders the settings.
*/
public function render() {
public function render(): void {
$is_dcc = CreditCardGateway::ID === $this->page_id;
//phpcs:enable WordPress.Security.NonceVerification.Recommended
@ -381,14 +391,14 @@ $data_rows_html
continue;
}
if (
in_array( 'dcc', $config['requirements'], true )
&& ! $this->dcc_product_status->dcc_is_active()
in_array( 'messages', $config['requirements'], true )
&& ! $this->messages_apply->for_country()
) {
continue;
}
if (
in_array( 'messages', $config['requirements'], true )
&& ! $this->messages_apply->for_country()
in_array( 'pui_ready', $config['requirements'], true )
&& $this->api_shop_country !== 'DE'
) {
continue;
}

View file

@ -17,6 +17,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn;
use WooCommerce\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail;
@ -28,9 +29,12 @@ use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceProductStatus;
use WooCommerce\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice;
use WooCommerce\PayPalCommerce\WcGateway\Notice\GatewayWithoutPayPalAdminNotice;
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Settings\HeaderRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SectionsRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
@ -65,11 +69,14 @@ class WCGatewayModule implements ModuleInterface {
add_action(
'woocommerce_sections_checkout',
function() use ( $c ) {
$header_renderer = $c->get( 'wcgateway.settings.header-renderer' );
assert( $header_renderer instanceof HeaderRenderer );
$section_renderer = $c->get( 'wcgateway.settings.sections-renderer' );
assert( $section_renderer instanceof SectionsRenderer );
// phpcs:ignore WordPress.Security.EscapeOutput
echo $section_renderer->render();
echo $header_renderer->render() . $section_renderer->render();
},
20
);
@ -298,14 +305,35 @@ class WCGatewayModule implements ModuleInterface {
$paypal_gateway_enabled = wc_string_to_bool( $paypal_gateway->get_option( 'enabled' ) );
$methods[] = $paypal_gateway;
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
/**
* The DCC Applies object.
*
* @var DccApplies $dcc_applies
*/
if ( $dcc_applies->for_country_currency() ) {
$onboarding_state = $container->get( 'onboarding.state' );
assert( $onboarding_state instanceof State );
$settings = $container->get( 'wcgateway.settings' );
assert( $settings instanceof ContainerInterface );
$is_our_page = $container->get( 'wcgateway.is-ppcp-settings-page' );
$is_gateways_list_page = $container->get( 'wcgateway.is-wc-gateways-list-page' );
if ( $onboarding_state->current_state() !== State::STATE_ONBOARDED ) {
return $methods;
}
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
assert( $dcc_applies instanceof DccApplies );
$dcc_product_status = $container->get( 'wcgateway.helper.dcc-product-status' );
assert( $dcc_product_status instanceof DCCProductStatus );
if ( $dcc_applies->for_country_currency() &&
// Show only if allowed in PayPal account, except when on our settings pages.
// Performing the full DCCProductStatus check only when on the gateway list page
// to avoid sending the API requests all the time.
( $is_our_page ||
( $is_gateways_list_page && $dcc_product_status->dcc_is_active() ) ||
( $settings->has( 'products_dcc_enabled' ) && $settings->get( 'products_dcc_enabled' ) )
)
) {
$methods[] = $container->get( 'wcgateway.credit-card-gateway' );
}
@ -313,11 +341,21 @@ class WCGatewayModule implements ModuleInterface {
$methods[] = $container->get( 'wcgateway.card-button-gateway' );
}
if ( 'DE' === $container->get( 'api.shop.country' ) ) {
$pui_product_status = $container->get( 'wcgateway.pay-upon-invoice-product-status' );
assert( $pui_product_status instanceof PayUponInvoiceProductStatus );
$shop_country = $container->get( 'api.shop.country' );
if ( 'DE' === $shop_country &&
( $is_our_page ||
( $is_gateways_list_page && $pui_product_status->pui_is_active() ) ||
( $settings->has( 'products_pui_enabled' ) && $settings->get( 'products_pui_enabled' ) )
)
) {
$methods[] = $container->get( 'wcgateway.pay-upon-invoice-gateway' );
}
if ( defined( 'PPCP_FLAG_OXXO' ) && PPCP_FLAG_OXXO === true ) {
if ( defined( 'PPCP_FLAG_OXXO' ) && PPCP_FLAG_OXXO === true && 'MX' === $shop_country ) {
$methods[] = $container->get( 'wcgateway.oxxo-gateway' );
}
@ -349,6 +387,7 @@ class WCGatewayModule implements ModuleInterface {
*/
$listener->listen_for_merchant_id();
$listener->listen_for_vaulting_enabled();
$listener->listen_for_tracking_enabled();
}
);

14
package-lock.json generated Normal file
View file

@ -0,0 +1,14 @@
{
"name": "woocommerce-paypal-payments",
"version": "1.7.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "woocommerce-paypal-payments",
"version": "1.7.0",
"license": "GPL-2.0",
"devDependencies": {}
}
}
}

View file

@ -1,6 +1,6 @@
{
"name": "woocommerce-paypal-payments",
"version": "1.9.2",
"version": "1.9.3",
"description": "WooCommerce PayPal Payments",
"repository": "https://github.com/woocommerce/woocommerce-paypal-payments",
"license": "GPL-2.0",
@ -10,12 +10,14 @@
"install:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn install && cd -",
"install:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn install && cd -",
"install:modules:ppcp-vaulting": "cd modules/ppcp-vaulting && yarn install && cd -",
"install:modules": "yarn run install:modules:ppcp-button && yarn run install:modules:ppcp-wc-gateway && yarn run install:modules:ppcp-webhooks && yarn run install:modules:ppcp-vaulting",
"install:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn install && cd -",
"install:modules": "yarn run install:modules:ppcp-button && yarn run install:modules:ppcp-wc-gateway && yarn run install:modules:ppcp-webhooks && yarn run install:modules:ppcp-vaulting && yarn run install:modules:ppcp-order-tracking",
"build:modules:ppcp-button": "cd modules/ppcp-button && yarn run build && cd -",
"build:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run build && cd -",
"build:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run build && cd -",
"build:modules:ppcp-vaulting": "cd modules/ppcp-vaulting && yarn run build && cd -",
"build:modules": "yarn run build:modules:ppcp-button && yarn build:modules:ppcp-wc-gateway && yarn build:modules:ppcp-webhooks && yarn build:modules:ppcp-vaulting",
"build:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run build && cd -",
"build:modules": "yarn run build:modules:ppcp-button && yarn build:modules:ppcp-wc-gateway && yarn build:modules:ppcp-webhooks && yarn build:modules:ppcp-vaulting && yarn build:modules:ppcp-order-tracking",
"build:dev": "yarn run install:modules && yarn run build:modules",
"ddev:setup": "ddev start && ddev orchestrate",

View file

@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, e-commerce, store, sales, sell,
Requires at least: 5.3
Tested up to: 6.0
Requires PHP: 7.1
Stable tag: 1.9.2
Stable tag: 1.9.3
License: GPLv2
License URI: http://www.gnu.org/licenses/gpl-2.0.html
@ -81,6 +81,21 @@ Follow the steps below to connect the plugin to your PayPal account:
== Changelog ==
= 1.9.3 =
* Add - Tracking API #792
* Fix - Improve compatibility with Siteground Optimizer plugin #797
* Fix - Transaction ID in order not updated when manually capturing authorized payment from WC #766
* Fix - Failed form validation on Checkout page causing page to be sticky #781
* Fix - Do not include full path in exception #779
* Fix - PUI conflict with Germanized plugin and taxes #808
* Enhancement - Enable ACDC by default only in locations where WooCommerce Payments is not available #799
* Enhancement - Add links to docs & support in plugin #782
* Enhancement - Put gateway sub-options into tabs #772
* Enhancement - Show tabs only after onboarding #789
* Enhancement - Add header on settings page #790
* Enhancement - PUI add option for a phone number field next to the Birth Date field #742
* Enhancement - PUI gateway availability on pay for order page with unsupported currency #744
= 1.9.2 =
* Fix - Do not allow birth date older than 100 years for PUI. #743
* Fix - Store the customer id for vaulted payment method in usermeta to not lose vaulted methods after the invoice prefix change. #698

View file

@ -6,6 +6,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
use Mockery;
use Psr\Log\LoggerInterface;
use Requests_Utility_CaseInsensitiveDictionary;
use WC_Order;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
@ -50,6 +51,7 @@ class PayUponInvoiceOrderEndpointTest extends TestCase
public function testCreateOrder()
{
$this->markTestSkipped('must be revisited.');
list($items, $paymentSource, $headers) = $this->setStubs();
$response = [
@ -61,12 +63,16 @@ class PayUponInvoiceOrderEndpointTest extends TestCase
$this->logger->shouldReceive('debug');
$result = $this->testee->create($items, $paymentSource, '');
$wc_order = Mockery::mock(WC_Order::class);
$result = $this->testee->create($items, $paymentSource, $wc_order );
$this->assertInstanceOf(Order::class, $result);
}
public function testCreateOrderWpError()
{
$this->markTestSkipped('must be revisited.');
list($items, $paymentSource) = $this->setStubsForError();
$wpError = Mockery::mock(\WP_Error::class);
@ -75,13 +81,15 @@ class PayUponInvoiceOrderEndpointTest extends TestCase
expect('wp_remote_get')->andReturn($wpError);
$this->logger->shouldReceive('debug');
$wc_order = Mockery::mock(WC_Order::class);
$this->expectException(\RuntimeException::class);
$this->testee->create($items, $paymentSource, '');
$this->testee->create($items, $paymentSource, $wc_order);
}
public function testCreateOrderApiError()
{
$this->markTestSkipped('must be revisited.');
list($items, $paymentSource) = $this->setStubsForError();
$headers = Mockery::mock(Requests_Utility_CaseInsensitiveDictionary::class);
@ -97,8 +105,9 @@ class PayUponInvoiceOrderEndpointTest extends TestCase
$this->logger->shouldReceive('debug');
$wc_order = Mockery::mock(WC_Order::class);
$this->expectException(PayPalApiException::class);
$this->testee->create($items, $paymentSource, '');
$this->testee->create($items, $paymentSource, $wc_order);
}
/**

View file

@ -58,6 +58,7 @@ class PayUponInvoiceGatewayTest extends TestCase
public function testProcessPayment()
{
$this->markTestSkipped('must be revisited.');
list($order, $purchase_unit, $payment_source) = $this->setTestStubs();
$this->order_endpoint->shouldReceive('create')->with(

View file

@ -2,6 +2,7 @@
namespace WooCommerce\PayPalCommerce\WcGateway\Settings;
use Requests_Utility_CaseInsensitiveDictionary;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
use WooCommerce\PayPalCommerce\ModularTestCase;
@ -9,17 +10,14 @@ use WooCommerce\PayPalCommerce\Onboarding\State;
use Mockery;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\Webhooks\WebhookRegistrar;
use function Brain\Monkey\Functions\expect;
use function Brain\Monkey\Functions\when;
class SettingsListenerTest extends ModularTestCase
{
private $appContainer;
public function setUp(): void
{
parent::setUp();
$this->appContainer = $this->bootstrapModule();
}
public function testListen()
@ -27,7 +25,7 @@ class SettingsListenerTest extends ModularTestCase
$settings = Mockery::mock(Settings::class);
$settings->shouldReceive('set');
$setting_fields = $this->appContainer->get('wcgateway.settings.fields');
$setting_fields = [];
$webhook_registrar = Mockery::mock(WebhookRegistrar::class);
$webhook_registrar->shouldReceive('unregister')->andReturnTrue();

View file

@ -3,13 +3,13 @@
* Plugin Name: WooCommerce PayPal Payments
* Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/
* 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.9.2
* Version: 1.9.3
* Author: WooCommerce
* Author URI: https://woocommerce.com/
* License: GPL-2.0
* Requires PHP: 7.1
* WC requires at least: 3.9
* WC tested up to: 6.7
* WC tested up to: 6.8
* Text Domain: woocommerce-paypal-payments
*
* @package WooCommerce\PayPalCommerce
@ -143,6 +143,44 @@ define( 'PPCP_FLAG_SEPARATE_APM_BUTTONS', apply_filters( 'woocommerce_paypal_pay
}
);
// Add links below the description on the Plugins page.
add_filter(
'plugin_row_meta',
function( $links, $file ) {
if ( plugin_basename( __FILE__ ) !== $file ) {
return $links;
}
return array_merge(
$links,
array(
sprintf(
'<a target="_blank" href="%1$s">%2$s</a>',
'https://woocommerce.com/document/woocommerce-paypal-payments/',
__( 'Documentation', 'woocommerce-paypal-payments' )
),
sprintf(
'<a target="_blank" href="%1$s">%2$s</a>',
'https://woocommerce.com/document/woocommerce-paypal-payments/#get-help',
__( 'Get help', 'woocommerce-paypal-payments' )
),
sprintf(
'<a target="_blank" href="%1$s">%2$s</a>',
'https://woocommerce.com/feature-requests/woocommerce-paypal-payments/',
__( 'Request a feature', 'woocommerce-paypal-payments' )
),
sprintf(
'<a target="_blank" href="%1$s">%2$s</a>',
'https://github.com/woocommerce/woocommerce-paypal-payments/issues/new?assignees=&labels=type%3A+bug&template=bug_report.md',
__( 'Submit a bug', 'woocommerce-paypal-payments' )
),
)
);
},
10,
2
);
/**
* Check if WooCommerce is active.
*