diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml
index 6d4d11f21..549501d41 100644
--- a/.github/workflows/package.yml
+++ b/.github/workflows/package.yml
@@ -4,7 +4,11 @@ on:
workflow_dispatch:
inputs:
packageVersion:
- description: 'Package Version'
+ description: 'Package version'
+ required: false
+ type: string
+ filePrefix:
+ description: 'File prefix'
required: false
type: string
@@ -12,6 +16,10 @@ jobs:
package:
runs-on: ubuntu-latest
+ env:
+ PACKAGE_VERSION: ${{ github.event.inputs.packageVersion }}
+ FILENAME: woocommerce-paypal-payments
+
name: Build package
steps:
- uses: actions/checkout@v2
@@ -22,11 +30,13 @@ jobs:
php-version: 7.1
tools: composer:v1
+ - name: Fix plugin version input # Add the version number if only suffix entered
+ run: echo "PACKAGE_VERSION=$(sed -nE '/Version:/s/.* ([0-9.]+).*/\1/p' woocommerce-paypal-payments.php)-$PACKAGE_VERSION" >> $GITHUB_ENV
+ if: env.PACKAGE_VERSION && !contains(env.PACKAGE_VERSION, '.')
+
- name: Set plugin version header
- env:
- PACKAGE_VERSION: ${{ github.event.inputs.packageVersion }}
run: 'sed -Ei "s/Version: .*/Version: ${PACKAGE_VERSION}/g" woocommerce-paypal-payments.php'
- if: github.event.inputs.packageVersion
+ if: env.PACKAGE_VERSION
- name: Build
run: yarn build
@@ -34,8 +44,14 @@ jobs:
- name: Unzip # GH currently always zips, so if we upload a zip we get a zip inside a zip
run: unzip woocommerce-paypal-payments.zip -d dist
+ - name: Set file name
+ env:
+ FILE_PREFIX: ${{ github.event.inputs.filePrefix }}
+ run: echo "FILENAME=$FILE_PREFIX-$FILENAME" >> $GITHUB_ENV
+ if: github.event.inputs.filePrefix
+
- name: Upload
uses: actions/upload-artifact@v3
with:
- name: woocommerce-paypal-payments
+ name: ${{ env.FILENAME }}
path: dist/
diff --git a/changelog.txt b/changelog.txt
index 423d52ab8..c6e693240 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,6 +1,6 @@
*** Changelog ***
-= 1.9.2 - TBD =
+= 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
* Fix - Capture Virtual-Only Orders setting did not auto-capture subscription renewal payments. #626
diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php
index b9502bbe8..2529afad4 100644
--- a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php
+++ b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoice.php
@@ -333,6 +333,23 @@ class PayUponInvoice {
)
);
+ $checkout_fields = WC()->checkout()->get_checkout_fields();
+ $checkout_phone_required = $checkout_fields['billing']['billing_phone']['required'] ?? false;
+ if ( ! array_key_exists( 'billing_phone', $checkout_fields['billing'] ) || $checkout_phone_required === false ) {
+ woocommerce_form_field(
+ 'billing_phone',
+ array(
+ // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
+ 'label' => __( 'Phone', 'woocommerce' ),
+ 'type' => 'tel',
+ 'class' => array( 'form-row-wide' ),
+ 'validate' => array( 'phone' ),
+ 'autocomplete' => 'tel',
+ 'required' => true,
+ )
+ );
+ }
+
echo '
';
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
@@ -376,6 +393,9 @@ class PayUponInvoice {
}
$national_number = filter_input( INPUT_POST, 'billing_phone', FILTER_SANITIZE_STRING );
+ if ( ! $national_number ) {
+ $errors->add( 'validation', __( 'Phone field cannot be empty.', 'woocommerce-paypal-payments' ) );
+ }
if ( $national_number ) {
$numeric_phone_number = preg_replace( '/[^0-9]/', '', $national_number );
if ( $numeric_phone_number && ! preg_match( '/^[0-9]{1,14}?$/', $numeric_phone_number ) ) {
diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php
index 4596bd321..68d4a19a7 100644
--- a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php
+++ b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PayUponInvoiceGateway.php
@@ -215,6 +215,12 @@ class PayUponInvoiceGateway extends WC_Payment_Gateway {
}
}
+ $phone_number = filter_input( INPUT_POST, 'billing_phone', FILTER_SANITIZE_STRING ) ?? '';
+ if ( $phone_number ) {
+ $wc_order->set_billing_phone( $phone_number );
+ $wc_order->save();
+ }
+
$wc_order->update_status( 'on-hold', __( 'Awaiting Pay upon Invoice payment.', 'woocommerce-paypal-payments' ) );
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
$payment_source = $this->payment_source_factory->from_wc_order( $wc_order, $birth_date );
diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PaymentSourceFactory.php b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PaymentSourceFactory.php
index 40bc9a15f..5e13ba0a8 100644
--- a/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PaymentSourceFactory.php
+++ b/modules/ppcp-wc-gateway/src/Gateway/PayUponInvoice/PaymentSourceFactory.php
@@ -24,8 +24,8 @@ class PaymentSourceFactory {
* @return PaymentSource
*/
public function from_wc_order( WC_Order $order, string $birth_date ) {
- $address = $order->get_address();
-
+ $address = $order->get_address();
+ $phone = filter_input( INPUT_POST, 'billing_phone', FILTER_SANITIZE_STRING ) ?? $address['phone'] ?: '';
$phone_country_code = WC()->countries->get_country_calling_code( $address['country'] );
$phone_country_code = is_array( $phone_country_code ) && ! empty( $phone_country_code ) ? $phone_country_code[0] : $phone_country_code;
if ( is_string( $phone_country_code ) && '' !== $phone_country_code ) {
@@ -44,7 +44,7 @@ class PaymentSourceFactory {
$address['last_name'] ?? '',
$address['email'] ?? '',
$birth_date,
- preg_replace( '/[^0-9]/', '', $address['phone'] ) ?? '',
+ preg_replace( '/[^0-9]/', '', $phone ) ?? '',
$phone_country_code,
$address['address_1'] ?? '',
$address['city'] ?? '',
diff --git a/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php b/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php
index f78871d1a..25902e227 100644
--- a/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php
+++ b/modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php
@@ -118,7 +118,7 @@ trait ProcessPaymentTrait {
* @return string
*/
protected function format_exception( Throwable $exception ): string {
- $output = $exception->getMessage() . ' ' . $exception->getFile() . ':' . $exception->getLine();
+ $output = $exception->getMessage() . ' ' . basename( $exception->getFile() ) . ':' . $exception->getLine();
$prev = $exception->getPrevious();
if ( ! $prev ) {
return $output;
diff --git a/modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php b/modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php
index 52ae85f3b..d87c18bfb 100644
--- a/modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php
+++ b/modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php
@@ -31,7 +31,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
*/
class AuthorizedPaymentsProcessor {
- use PaymentsStatusHandlingTrait;
+ use PaymentsStatusHandlingTrait, TransactionIdHandlingTrait;
const SUCCESSFUL = 'SUCCESSFUL';
const ALREADY_CAPTURED = 'ALREADY_CAPTURED';
@@ -200,6 +200,9 @@ class AuthorizedPaymentsProcessor {
$this->handle_capture_status( $capture, $wc_order );
+ $transaction_id = $capture->id();
+ $this->update_transaction_id( $transaction_id, $wc_order );
+
if ( self::SUCCESSFUL === $result_status ) {
if ( $capture->status()->is( CaptureStatus::COMPLETED ) ) {
$wc_order->add_order_note(
diff --git a/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php b/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php
index 275574e97..c92e72ee1 100644
--- a/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php
+++ b/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php
@@ -56,14 +56,12 @@ class SectionsRenderer {
/**
* Renders the Sections tab.
*/
- public function render(): void {
+ public function render(): string {
if ( ! $this->should_render() ) {
- return;
+ return '';
}
- echo '
';
-
- $array_keys = array_keys( $this->sections );
+ $html = '
';
+ $html .= '';
+
+ return $html;
}
}
diff --git a/modules/ppcp-wc-gateway/src/WCGatewayModule.php b/modules/ppcp-wc-gateway/src/WCGatewayModule.php
index d01287f67..853670025 100644
--- a/modules/ppcp-wc-gateway/src/WCGatewayModule.php
+++ b/modules/ppcp-wc-gateway/src/WCGatewayModule.php
@@ -66,13 +66,12 @@ class WCGatewayModule implements ModuleInterface {
'woocommerce_sections_checkout',
function() use ( $c ) {
$section_renderer = $c->get( 'wcgateway.settings.sections-renderer' );
- /**
- * The Section Renderer.
- *
- * @var SectionsRenderer $section_renderer
- */
- $section_renderer->render();
- }
+ assert( $section_renderer instanceof SectionsRenderer );
+
+ // phpcs:ignore WordPress.Security.EscapeOutput
+ echo $section_renderer->render();
+ },
+ 20
);
add_action(
@@ -292,7 +291,12 @@ class WCGatewayModule implements ModuleInterface {
add_filter(
'woocommerce_payment_gateways',
static function ( $methods ) use ( $container ): array {
- $methods[] = $container->get( 'wcgateway.paypal-gateway' );
+ $paypal_gateway = $container->get( 'wcgateway.paypal-gateway' );
+ assert( $paypal_gateway instanceof \WC_Payment_Gateway );
+
+ $paypal_gateway_enabled = wc_string_to_bool( $paypal_gateway->get_option( 'enabled' ) );
+
+ $methods[] = $paypal_gateway;
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
/**
@@ -304,7 +308,7 @@ class WCGatewayModule implements ModuleInterface {
$methods[] = $container->get( 'wcgateway.credit-card-gateway' );
}
- if ( $container->get( 'wcgateway.settings.allow_card_button_gateway' ) ) {
+ if ( $paypal_gateway_enabled && $container->get( 'wcgateway.settings.allow_card_button_gateway' ) ) {
$methods[] = $container->get( 'wcgateway.card-button-gateway' );
}
diff --git a/tests/PHPUnit/WcGateway/Processor/AuthorizedPaymentsProcessorTest.php b/tests/PHPUnit/WcGateway/Processor/AuthorizedPaymentsProcessorTest.php
index 946ade989..8ebd63794 100644
--- a/tests/PHPUnit/WcGateway/Processor/AuthorizedPaymentsProcessorTest.php
+++ b/tests/PHPUnit/WcGateway/Processor/AuthorizedPaymentsProcessorTest.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway\Processor;
+use Mockery\MockInterface;
use Psr\Container\ContainerInterface;
use Psr\Log\NullLogger;
use WC_Order;
@@ -26,7 +27,11 @@ use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
class AuthorizedPaymentsProcessorTest extends TestCase
{
+ /**
+ * @var WC_Order&MockInterface
+ */
private $wcOrder;
+
private $paypalOrderId = 'abc';
private $authorizationId = 'qwe';
private $amount = 42.0;
@@ -37,7 +42,7 @@ class AuthorizedPaymentsProcessorTest extends TestCase
private $paymentsEndpoint;
private $notice;
private $config;
- private $subscription_helperauthorization;
+ private $captureId = '123qwe';
private $testee;
public function setUp(): void {
@@ -79,7 +84,7 @@ class AuthorizedPaymentsProcessorTest extends TestCase
$this->paymentsEndpoint
->expects('capture')
->with($this->authorizationId, equalTo(new Money($this->amount, $this->currency)))
- ->andReturn($this->createCapture(CaptureStatus::COMPLETED));
+ ->andReturn($this->createCapture($this->captureId, CaptureStatus::COMPLETED));
$this->assertEquals(AuthorizedPaymentsProcessor::SUCCESSFUL, $this->testee->process($this->wcOrder));
}
@@ -99,7 +104,7 @@ class AuthorizedPaymentsProcessorTest extends TestCase
$this->paymentsEndpoint
->expects('capture')
->with($authorizations[2]->id(), equalTo(new Money($this->amount, $this->currency)))
- ->andReturn($this->createCapture(CaptureStatus::COMPLETED));
+ ->andReturn($this->createCapture($this->captureId, CaptureStatus::COMPLETED));
$this->assertEquals(AuthorizedPaymentsProcessor::SUCCESSFUL, $this->testee->process($this->wcOrder));
}
@@ -150,12 +155,13 @@ class AuthorizedPaymentsProcessorTest extends TestCase
$this->paymentsEndpoint
->expects('capture')
->with($this->authorizationId, equalTo(new Money($this->amount, $this->currency)))
- ->andReturn($this->createCapture(CaptureStatus::COMPLETED));
+ ->andReturn($this->createCapture($this->captureId, CaptureStatus::COMPLETED));
$this->wcOrder->shouldReceive('payment_complete')->andReturn(true);
- $this->wcOrder->expects('add_order_note');
+ $this->wcOrder->expects('add_order_note')->twice();
$this->wcOrder->expects('update_meta_data');
- $this->wcOrder->expects('save');
+ $this->wcOrder->expects('set_transaction_id')->with($this->captureId);
+ $this->wcOrder->shouldReceive('save')->atLeast()->times(1);
$this->assertTrue(
$this->testee->capture_authorized_payment($this->wcOrder)
@@ -248,8 +254,11 @@ class AuthorizedPaymentsProcessorTest extends TestCase
return new Authorization($id, new AuthorizationStatus($status));
}
- private function createCapture(string $status): Capture {
+ private function createCapture(string $id, string $status): Capture {
$capture = Mockery::mock(Capture::class);
+ $capture
+ ->shouldReceive('id')
+ ->andReturn($id);
$capture
->shouldReceive('status')
->andReturn(new CaptureStatus($status));