mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-08-30 05:00:51 +08:00
Merge pull request #1779 from woocommerce/PCP-1393-update-to-vault-v-3
Save payment methods (Vault v3) integration (1393)
This commit is contained in:
commit
45516d0075
100 changed files with 5204 additions and 1181 deletions
11
modules.php
11
modules.php
|
@ -20,13 +20,14 @@ return function ( string $root_dir ): iterable {
|
|||
( require "$modules_dir/ppcp-onboarding/module.php" )(),
|
||||
( require "$modules_dir/ppcp-session/module.php" )(),
|
||||
( require "$modules_dir/ppcp-status-report/module.php" )(),
|
||||
( require "$modules_dir/ppcp-subscription/module.php" )(),
|
||||
( require "$modules_dir/ppcp-wc-subscriptions/module.php" )(),
|
||||
( 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" )(),
|
||||
( require "$modules_dir/ppcp-uninstall/module.php" )(),
|
||||
( require "$modules_dir/ppcp-blocks/module.php" )(),
|
||||
( require "$modules_dir/ppcp-paypal-subscriptions/module.php" )(),
|
||||
);
|
||||
if ( apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
|
@ -60,5 +61,13 @@ return function ( string $root_dir ): iterable {
|
|||
$modules[] = ( require "$modules_dir/ppcp-card-fields/module.php" )();
|
||||
}
|
||||
|
||||
if ( apply_filters(
|
||||
//phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
'woocommerce.feature-flags.woocommerce_paypal_payments.save_payment_methods_enabled',
|
||||
getenv( 'PCP_SAVE_PAYMENT_METHODS' ) === '1'
|
||||
) ) {
|
||||
$modules[] = ( require "$modules_dir/ppcp-save-payment-methods/module.php" )();
|
||||
}
|
||||
|
||||
return $modules;
|
||||
};
|
||||
|
|
|
@ -9,12 +9,16 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient;
|
||||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
||||
use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\CatalogProducts;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingPlans;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerPayableBreakdown;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\BillingCycleFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentPreferencesFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\RefundFactory;
|
||||
|
@ -50,7 +54,6 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PatchCollectionFactory;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayeeFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentsFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentSourceFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenActionLinksFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PlatformFeeFactory;
|
||||
|
@ -74,39 +77,40 @@ use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
return array(
|
||||
'api.host' => function( ContainerInterface $container ) : string {
|
||||
'api.host' => function( ContainerInterface $container ) : string {
|
||||
return PAYPAL_API_URL;
|
||||
},
|
||||
'api.paypal-host' => function( ContainerInterface $container ) : string {
|
||||
'api.paypal-host' => function( ContainerInterface $container ) : string {
|
||||
return PAYPAL_API_URL;
|
||||
},
|
||||
'api.paypal-website-url' => function( ContainerInterface $container ) : string {
|
||||
// It seems this 'api.paypal-website-url' key is always overridden in ppcp-onboarding/services.php.
|
||||
'api.paypal-website-url' => function( ContainerInterface $container ) : string {
|
||||
return PAYPAL_URL;
|
||||
},
|
||||
'api.factory.paypal-checkout-url' => function( ContainerInterface $container ) : callable {
|
||||
'api.factory.paypal-checkout-url' => function( ContainerInterface $container ) : callable {
|
||||
return function ( string $id ) use ( $container ): string {
|
||||
return $container->get( 'api.paypal-website-url' ) . '/checkoutnow?token=' . $id;
|
||||
};
|
||||
},
|
||||
'api.partner_merchant_id' => static function () : string {
|
||||
'api.partner_merchant_id' => static function () : string {
|
||||
return '';
|
||||
},
|
||||
'api.merchant_email' => function () : string {
|
||||
'api.merchant_email' => function () : string {
|
||||
return '';
|
||||
},
|
||||
'api.merchant_id' => function () : string {
|
||||
'api.merchant_id' => function () : string {
|
||||
return '';
|
||||
},
|
||||
'api.key' => static function (): string {
|
||||
'api.key' => static function (): string {
|
||||
return '';
|
||||
},
|
||||
'api.secret' => static function (): string {
|
||||
'api.secret' => static function (): string {
|
||||
return '';
|
||||
},
|
||||
'api.prefix' => static function (): string {
|
||||
'api.prefix' => static function (): string {
|
||||
return 'WC-';
|
||||
},
|
||||
'api.bearer' => static function ( ContainerInterface $container ): Bearer {
|
||||
'api.bearer' => static function ( ContainerInterface $container ): Bearer {
|
||||
$cache = new Cache( 'ppcp-paypal-bearer' );
|
||||
$key = $container->get( 'api.key' );
|
||||
$secret = $container->get( 'api.secret' );
|
||||
|
@ -122,7 +126,7 @@ return array(
|
|||
$settings
|
||||
);
|
||||
},
|
||||
'api.endpoint.partners' => static function ( ContainerInterface $container ) : PartnersEndpoint {
|
||||
'api.endpoint.partners' => static function ( ContainerInterface $container ) : PartnersEndpoint {
|
||||
return new PartnersEndpoint(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
|
@ -133,10 +137,10 @@ return array(
|
|||
$container->get( 'api.helper.failure-registry' )
|
||||
);
|
||||
},
|
||||
'api.factory.sellerstatus' => static function ( ContainerInterface $container ) : SellerStatusFactory {
|
||||
'api.factory.sellerstatus' => static function ( ContainerInterface $container ) : SellerStatusFactory {
|
||||
return new SellerStatusFactory();
|
||||
},
|
||||
'api.endpoint.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenEndpoint {
|
||||
'api.endpoint.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenEndpoint {
|
||||
return new PaymentTokenEndpoint(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
|
@ -146,7 +150,14 @@ return array(
|
|||
$container->get( 'api.repository.customer' )
|
||||
);
|
||||
},
|
||||
'api.endpoint.webhook' => static function ( ContainerInterface $container ) : WebhookEndpoint {
|
||||
'api.endpoint.payment-tokens' => static function( ContainerInterface $container ) : PaymentTokensEndpoint {
|
||||
return new PaymentTokensEndpoint(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.endpoint.webhook' => static function ( ContainerInterface $container ) : WebhookEndpoint {
|
||||
|
||||
return new WebhookEndpoint(
|
||||
$container->get( 'api.host' ),
|
||||
|
@ -156,7 +167,7 @@ return array(
|
|||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.endpoint.partner-referrals' => static function ( ContainerInterface $container ) : PartnerReferrals {
|
||||
'api.endpoint.partner-referrals' => static function ( ContainerInterface $container ) : PartnerReferrals {
|
||||
|
||||
return new PartnerReferrals(
|
||||
$container->get( 'api.host' ),
|
||||
|
@ -164,7 +175,7 @@ return array(
|
|||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.endpoint.identity-token' => static function ( ContainerInterface $container ) : IdentityToken {
|
||||
'api.endpoint.identity-token' => static function ( ContainerInterface $container ) : IdentityToken {
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$customer_repository = $container->get( 'api.repository.customer' );
|
||||
|
@ -176,7 +187,7 @@ return array(
|
|||
$customer_repository
|
||||
);
|
||||
},
|
||||
'api.endpoint.payments' => static function ( ContainerInterface $container ): PaymentsEndpoint {
|
||||
'api.endpoint.payments' => static function ( ContainerInterface $container ): PaymentsEndpoint {
|
||||
$authorizations_factory = $container->get( 'api.factory.authorization' );
|
||||
$capture_factory = $container->get( 'api.factory.capture' );
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
|
@ -189,7 +200,7 @@ return array(
|
|||
$logger
|
||||
);
|
||||
},
|
||||
'api.endpoint.login-seller' => static function ( ContainerInterface $container ) : LoginSeller {
|
||||
'api.endpoint.login-seller' => static function ( ContainerInterface $container ) : LoginSeller {
|
||||
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
return new LoginSeller(
|
||||
|
@ -198,7 +209,7 @@ return array(
|
|||
$logger
|
||||
);
|
||||
},
|
||||
'api.endpoint.order' => static function ( ContainerInterface $container ): OrderEndpoint {
|
||||
'api.endpoint.order' => static function ( ContainerInterface $container ): OrderEndpoint {
|
||||
$order_factory = $container->get( 'api.factory.order' );
|
||||
$patch_collection_factory = $container->get( 'api.factory.patch-collection-factory' );
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
|
@ -212,7 +223,7 @@ return array(
|
|||
|
||||
$intent = $settings->has( 'intent' ) && strtoupper( (string) $settings->get( 'intent' ) ) === 'AUTHORIZE' ? 'AUTHORIZE' : 'CAPTURE';
|
||||
$application_context_repository = $container->get( 'api.repository.application-context' );
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
return new OrderEndpoint(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
|
@ -227,14 +238,14 @@ return array(
|
|||
$bn_code
|
||||
);
|
||||
},
|
||||
'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint {
|
||||
'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint {
|
||||
return new BillingAgreementsEndpoint(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.endpoint.catalog-products' => static function ( ContainerInterface $container ): CatalogProducts {
|
||||
'api.endpoint.catalog-products' => static function ( ContainerInterface $container ): CatalogProducts {
|
||||
return new CatalogProducts(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
|
@ -242,7 +253,7 @@ return array(
|
|||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.endpoint.billing-plans' => static function( ContainerInterface $container ): BillingPlans {
|
||||
'api.endpoint.billing-plans' => static function( ContainerInterface $container ): BillingPlans {
|
||||
return new BillingPlans(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
|
@ -251,53 +262,60 @@ return array(
|
|||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.endpoint.billing-subscriptions' => static function( ContainerInterface $container ): BillingSubscriptions {
|
||||
'api.endpoint.billing-subscriptions' => static function( ContainerInterface $container ): BillingSubscriptions {
|
||||
return new BillingSubscriptions(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.repository.application-context' => static function( ContainerInterface $container ) : ApplicationContextRepository {
|
||||
'api.endpoint.payment-method-tokens' => static function( ContainerInterface $container ): PaymentMethodTokensEndpoint {
|
||||
return new PaymentMethodTokensEndpoint(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.repository.application-context' => static function( ContainerInterface $container ) : ApplicationContextRepository {
|
||||
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
return new ApplicationContextRepository( $settings );
|
||||
},
|
||||
'api.repository.partner-referrals-data' => static function ( ContainerInterface $container ) : PartnerReferralsData {
|
||||
'api.repository.partner-referrals-data' => static function ( ContainerInterface $container ) : PartnerReferralsData {
|
||||
|
||||
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
|
||||
return new PartnerReferralsData( $dcc_applies );
|
||||
},
|
||||
'api.repository.payee' => static function ( ContainerInterface $container ): PayeeRepository {
|
||||
'api.repository.payee' => static function ( ContainerInterface $container ): PayeeRepository {
|
||||
$merchant_email = $container->get( 'api.merchant_email' );
|
||||
$merchant_id = $container->get( 'api.merchant_id' );
|
||||
return new PayeeRepository( $merchant_email, $merchant_id );
|
||||
},
|
||||
'api.repository.customer' => static function( ContainerInterface $container ): CustomerRepository {
|
||||
'api.repository.customer' => static function( ContainerInterface $container ): CustomerRepository {
|
||||
$prefix = $container->get( 'api.prefix' );
|
||||
return new CustomerRepository( $prefix );
|
||||
},
|
||||
'api.repository.order' => static function( ContainerInterface $container ): OrderRepository {
|
||||
'api.repository.order' => static function( ContainerInterface $container ): OrderRepository {
|
||||
return new OrderRepository(
|
||||
$container->get( 'api.endpoint.order' )
|
||||
);
|
||||
},
|
||||
'api.factory.application-context' => static function ( ContainerInterface $container ) : ApplicationContextFactory {
|
||||
'api.factory.application-context' => static function ( ContainerInterface $container ) : ApplicationContextFactory {
|
||||
return new ApplicationContextFactory();
|
||||
},
|
||||
'api.factory.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenFactory {
|
||||
'api.factory.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenFactory {
|
||||
return new PaymentTokenFactory();
|
||||
},
|
||||
'api.factory.payment-token-action-links' => static function ( ContainerInterface $container ) : PaymentTokenActionLinksFactory {
|
||||
'api.factory.payment-token-action-links' => static function ( ContainerInterface $container ) : PaymentTokenActionLinksFactory {
|
||||
return new PaymentTokenActionLinksFactory();
|
||||
},
|
||||
'api.factory.webhook' => static function ( ContainerInterface $container ): WebhookFactory {
|
||||
'api.factory.webhook' => static function ( ContainerInterface $container ): WebhookFactory {
|
||||
return new WebhookFactory();
|
||||
},
|
||||
'api.factory.webhook-event' => static function ( ContainerInterface $container ): WebhookEventFactory {
|
||||
'api.factory.webhook-event' => static function ( ContainerInterface $container ): WebhookEventFactory {
|
||||
return new WebhookEventFactory();
|
||||
},
|
||||
'api.factory.capture' => static function ( ContainerInterface $container ): CaptureFactory {
|
||||
'api.factory.capture' => static function ( ContainerInterface $container ): CaptureFactory {
|
||||
|
||||
$amount_factory = $container->get( 'api.factory.amount' );
|
||||
return new CaptureFactory(
|
||||
|
@ -306,7 +324,7 @@ return array(
|
|||
$container->get( 'api.factory.fraud-processor-response' )
|
||||
);
|
||||
},
|
||||
'api.factory.refund' => static function ( ContainerInterface $container ): RefundFactory {
|
||||
'api.factory.refund' => static function ( ContainerInterface $container ): RefundFactory {
|
||||
$amount_factory = $container->get( 'api.factory.amount' );
|
||||
return new RefundFactory(
|
||||
$amount_factory,
|
||||
|
@ -314,7 +332,7 @@ return array(
|
|||
$container->get( 'api.factory.refund_payer' )
|
||||
);
|
||||
},
|
||||
'api.factory.purchase-unit' => static function ( ContainerInterface $container ): PurchaseUnitFactory {
|
||||
'api.factory.purchase-unit' => static function ( ContainerInterface $container ): PurchaseUnitFactory {
|
||||
|
||||
$amount_factory = $container->get( 'api.factory.amount' );
|
||||
$item_factory = $container->get( 'api.factory.item' );
|
||||
|
@ -334,32 +352,32 @@ return array(
|
|||
$sanitizer
|
||||
);
|
||||
},
|
||||
'api.factory.patch-collection-factory' => static function ( ContainerInterface $container ): PatchCollectionFactory {
|
||||
'api.factory.patch-collection-factory' => static function ( ContainerInterface $container ): PatchCollectionFactory {
|
||||
return new PatchCollectionFactory();
|
||||
},
|
||||
'api.factory.payee' => static function ( ContainerInterface $container ): PayeeFactory {
|
||||
'api.factory.payee' => static function ( ContainerInterface $container ): PayeeFactory {
|
||||
return new PayeeFactory();
|
||||
},
|
||||
'api.factory.item' => static function ( ContainerInterface $container ): ItemFactory {
|
||||
'api.factory.item' => static function ( ContainerInterface $container ): ItemFactory {
|
||||
return new ItemFactory(
|
||||
$container->get( 'api.shop.currency' )
|
||||
);
|
||||
},
|
||||
'api.factory.shipping' => static function ( ContainerInterface $container ): ShippingFactory {
|
||||
'api.factory.shipping' => static function ( ContainerInterface $container ): ShippingFactory {
|
||||
return new ShippingFactory(
|
||||
$container->get( 'api.factory.address' ),
|
||||
$container->get( 'api.factory.shipping-option' )
|
||||
);
|
||||
},
|
||||
'api.factory.shipping-preference' => static function ( ContainerInterface $container ): ShippingPreferenceFactory {
|
||||
'api.factory.shipping-preference' => static function ( ContainerInterface $container ): ShippingPreferenceFactory {
|
||||
return new ShippingPreferenceFactory();
|
||||
},
|
||||
'api.factory.shipping-option' => static function ( ContainerInterface $container ): ShippingOptionFactory {
|
||||
'api.factory.shipping-option' => static function ( ContainerInterface $container ): ShippingOptionFactory {
|
||||
return new ShippingOptionFactory(
|
||||
$container->get( 'api.factory.money' )
|
||||
);
|
||||
},
|
||||
'api.factory.amount' => static function ( ContainerInterface $container ): AmountFactory {
|
||||
'api.factory.amount' => static function ( ContainerInterface $container ): AmountFactory {
|
||||
$item_factory = $container->get( 'api.factory.item' );
|
||||
return new AmountFactory(
|
||||
$item_factory,
|
||||
|
@ -367,86 +385,84 @@ return array(
|
|||
$container->get( 'api.shop.currency' )
|
||||
);
|
||||
},
|
||||
'api.factory.money' => static function ( ContainerInterface $container ): MoneyFactory {
|
||||
'api.factory.money' => static function ( ContainerInterface $container ): MoneyFactory {
|
||||
return new MoneyFactory();
|
||||
},
|
||||
'api.factory.payer' => static function ( ContainerInterface $container ): PayerFactory {
|
||||
'api.factory.payer' => static function ( ContainerInterface $container ): PayerFactory {
|
||||
$address_factory = $container->get( 'api.factory.address' );
|
||||
return new PayerFactory( $address_factory );
|
||||
},
|
||||
'api.factory.refund_payer' => static function ( ContainerInterface $container ): RefundPayerFactory {
|
||||
'api.factory.refund_payer' => static function ( ContainerInterface $container ): RefundPayerFactory {
|
||||
return new RefundPayerFactory();
|
||||
},
|
||||
'api.factory.address' => static function ( ContainerInterface $container ): AddressFactory {
|
||||
'api.factory.address' => static function ( ContainerInterface $container ): AddressFactory {
|
||||
return new AddressFactory();
|
||||
},
|
||||
'api.factory.payment-source' => static function ( ContainerInterface $container ): PaymentSourceFactory {
|
||||
return new PaymentSourceFactory();
|
||||
},
|
||||
'api.factory.order' => static function ( ContainerInterface $container ): OrderFactory {
|
||||
'api.factory.order' => static function ( ContainerInterface $container ): OrderFactory {
|
||||
$purchase_unit_factory = $container->get( 'api.factory.purchase-unit' );
|
||||
$payer_factory = $container->get( 'api.factory.payer' );
|
||||
$application_context_repository = $container->get( 'api.repository.application-context' );
|
||||
$application_context_factory = $container->get( 'api.factory.application-context' );
|
||||
$payment_source_factory = $container->get( 'api.factory.payment-source' );
|
||||
return new OrderFactory(
|
||||
$purchase_unit_factory,
|
||||
$payer_factory,
|
||||
$application_context_repository,
|
||||
$application_context_factory,
|
||||
$payment_source_factory
|
||||
$application_context_factory
|
||||
);
|
||||
},
|
||||
'api.factory.payments' => static function ( ContainerInterface $container ): PaymentsFactory {
|
||||
'api.factory.payments' => static function ( ContainerInterface $container ): PaymentsFactory {
|
||||
$authorizations_factory = $container->get( 'api.factory.authorization' );
|
||||
$capture_factory = $container->get( 'api.factory.capture' );
|
||||
$refund_factory = $container->get( 'api.factory.refund' );
|
||||
return new PaymentsFactory( $authorizations_factory, $capture_factory, $refund_factory );
|
||||
},
|
||||
'api.factory.authorization' => static function ( ContainerInterface $container ): AuthorizationFactory {
|
||||
'api.factory.authorization' => static function ( ContainerInterface $container ): AuthorizationFactory {
|
||||
return new AuthorizationFactory();
|
||||
},
|
||||
'api.factory.exchange-rate' => static function ( ContainerInterface $container ): ExchangeRateFactory {
|
||||
'api.factory.exchange-rate' => static function ( ContainerInterface $container ): ExchangeRateFactory {
|
||||
return new ExchangeRateFactory();
|
||||
},
|
||||
'api.factory.platform-fee' => static function ( ContainerInterface $container ): PlatformFeeFactory {
|
||||
'api.factory.platform-fee' => static function ( ContainerInterface $container ): PlatformFeeFactory {
|
||||
return new PlatformFeeFactory(
|
||||
$container->get( 'api.factory.money' ),
|
||||
$container->get( 'api.factory.payee' )
|
||||
);
|
||||
},
|
||||
'api.factory.seller-receivable-breakdown' => static function ( ContainerInterface $container ): SellerReceivableBreakdownFactory {
|
||||
'api.factory.seller-receivable-breakdown' => static function ( ContainerInterface $container ): SellerReceivableBreakdownFactory {
|
||||
return new SellerReceivableBreakdownFactory(
|
||||
$container->get( 'api.factory.money' ),
|
||||
$container->get( 'api.factory.exchange-rate' ),
|
||||
$container->get( 'api.factory.platform-fee' )
|
||||
);
|
||||
},
|
||||
'api.factory.seller-payable-breakdown' => static function ( ContainerInterface $container ): SellerPayableBreakdownFactory {
|
||||
'api.factory.seller-payable-breakdown' => static function ( ContainerInterface $container ): SellerPayableBreakdownFactory {
|
||||
return new SellerPayableBreakdownFactory(
|
||||
$container->get( 'api.factory.money' ),
|
||||
$container->get( 'api.factory.platform-fee' )
|
||||
);
|
||||
},
|
||||
'api.factory.fraud-processor-response' => static function ( ContainerInterface $container ): FraudProcessorResponseFactory {
|
||||
'api.factory.fraud-processor-response' => static function ( ContainerInterface $container ): FraudProcessorResponseFactory {
|
||||
return new FraudProcessorResponseFactory();
|
||||
},
|
||||
'api.factory.product' => static function( ContainerInterface $container ): ProductFactory {
|
||||
'api.factory.product' => static function( ContainerInterface $container ): ProductFactory {
|
||||
return new ProductFactory();
|
||||
},
|
||||
'api.factory.billing-cycle' => static function( ContainerInterface $container ): BillingCycleFactory {
|
||||
'api.factory.billing-cycle' => static function( ContainerInterface $container ): BillingCycleFactory {
|
||||
return new BillingCycleFactory( $container->get( 'api.shop.currency' ) );
|
||||
},
|
||||
'api.factory.payment-preferences' => static function( ContainerInterface $container ):PaymentPreferencesFactory {
|
||||
'api.factory.payment-preferences' => static function( ContainerInterface $container ):PaymentPreferencesFactory {
|
||||
return new PaymentPreferencesFactory( $container->get( 'api.shop.currency' ) );
|
||||
},
|
||||
'api.factory.plan' => static function( ContainerInterface $container ): PlanFactory {
|
||||
'api.factory.plan' => static function( ContainerInterface $container ): PlanFactory {
|
||||
return new PlanFactory(
|
||||
$container->get( 'api.factory.billing-cycle' ),
|
||||
$container->get( 'api.factory.payment-preferences' )
|
||||
);
|
||||
},
|
||||
'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies {
|
||||
'api.factory.card-authentication-result-factory' => static function( ContainerInterface $container ): CardAuthenticationResultFactory {
|
||||
return new CardAuthenticationResultFactory();
|
||||
},
|
||||
'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies {
|
||||
return new DccApplies(
|
||||
$container->get( 'api.dcc-supported-country-currency-matrix' ),
|
||||
$container->get( 'api.dcc-supported-country-card-matrix' ),
|
||||
|
@ -455,7 +471,7 @@ return array(
|
|||
);
|
||||
},
|
||||
|
||||
'api.shop.currency' => static function ( ContainerInterface $container ) : string {
|
||||
'api.shop.currency' => static function ( ContainerInterface $container ) : string {
|
||||
$currency = get_woocommerce_currency();
|
||||
if ( $currency ) {
|
||||
return $currency;
|
||||
|
@ -468,18 +484,18 @@ return array(
|
|||
|
||||
return $currency;
|
||||
},
|
||||
'api.shop.country' => static function ( ContainerInterface $container ) : string {
|
||||
'api.shop.country' => static function ( ContainerInterface $container ) : string {
|
||||
$location = wc_get_base_location();
|
||||
return $location['country'];
|
||||
},
|
||||
'api.shop.is-psd2-country' => static function ( ContainerInterface $container ) : bool {
|
||||
'api.shop.is-psd2-country' => static function ( ContainerInterface $container ) : bool {
|
||||
return in_array(
|
||||
$container->get( 'api.shop.country' ),
|
||||
$container->get( 'api.psd2-countries' ),
|
||||
true
|
||||
);
|
||||
},
|
||||
'api.shop.is-currency-supported' => static function ( ContainerInterface $container ) : bool {
|
||||
'api.shop.is-currency-supported' => static function ( ContainerInterface $container ) : bool {
|
||||
return in_array(
|
||||
$container->get( 'api.shop.currency' ),
|
||||
$container->get( 'api.supported-currencies' ),
|
||||
|
@ -488,7 +504,7 @@ return array(
|
|||
},
|
||||
|
||||
|
||||
'api.shop.is-latin-america' => static function ( ContainerInterface $container ): bool {
|
||||
'api.shop.is-latin-america' => static function ( ContainerInterface $container ): bool {
|
||||
return in_array(
|
||||
$container->get( 'api.shop.country' ),
|
||||
array(
|
||||
|
@ -546,7 +562,7 @@ return array(
|
|||
*
|
||||
* From https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/
|
||||
*/
|
||||
'api.supported-currencies' => static function ( ContainerInterface $container ) : array {
|
||||
'api.supported-currencies' => static function ( ContainerInterface $container ) : array {
|
||||
return array(
|
||||
'AUD',
|
||||
'BRL',
|
||||
|
@ -579,7 +595,7 @@ return array(
|
|||
/**
|
||||
* The matrix which countries and currency combinations can be used for DCC.
|
||||
*/
|
||||
'api.dcc-supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array {
|
||||
'api.dcc-supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array {
|
||||
/**
|
||||
* Returns which countries and currency combinations can be used for DCC.
|
||||
*/
|
||||
|
@ -901,7 +917,7 @@ return array(
|
|||
/**
|
||||
* Which countries support which credit cards. Empty credit card arrays mean no restriction on currency.
|
||||
*/
|
||||
'api.dcc-supported-country-card-matrix' => static function ( ContainerInterface $container ) : array {
|
||||
'api.dcc-supported-country-card-matrix' => static function ( ContainerInterface $container ) : array {
|
||||
/**
|
||||
* Returns which countries support which credit cards. Empty credit card arrays mean no restriction on currency.
|
||||
*/
|
||||
|
@ -1070,7 +1086,7 @@ return array(
|
|||
);
|
||||
},
|
||||
|
||||
'api.psd2-countries' => static function ( ContainerInterface $container ) : array {
|
||||
'api.psd2-countries' => static function ( ContainerInterface $container ) : array {
|
||||
return array(
|
||||
'AT',
|
||||
'BE',
|
||||
|
@ -1102,19 +1118,19 @@ return array(
|
|||
'SE',
|
||||
);
|
||||
},
|
||||
'api.order-helper' => static function( ContainerInterface $container ): OrderHelper {
|
||||
'api.order-helper' => static function( ContainerInterface $container ): OrderHelper {
|
||||
return new OrderHelper();
|
||||
},
|
||||
'api.helper.order-transient' => static function( ContainerInterface $container ): OrderTransient {
|
||||
'api.helper.order-transient' => static function( ContainerInterface $container ): OrderTransient {
|
||||
$cache = new Cache( 'ppcp-paypal-bearer' );
|
||||
$purchase_unit_sanitizer = $container->get( 'api.helper.purchase-unit-sanitizer' );
|
||||
return new OrderTransient( $cache, $purchase_unit_sanitizer );
|
||||
},
|
||||
'api.helper.failure-registry' => static function( ContainerInterface $container ): FailureRegistry {
|
||||
'api.helper.failure-registry' => static function( ContainerInterface $container ): FailureRegistry {
|
||||
$cache = new Cache( 'ppcp-paypal-api-status-cache' );
|
||||
return new FailureRegistry( $cache );
|
||||
},
|
||||
'api.helper.purchase-unit-sanitizer' => SingletonDecorator::make(
|
||||
'api.helper.purchase-unit-sanitizer' => SingletonDecorator::make(
|
||||
static function( ContainerInterface $container ): PurchaseUnitSanitizer {
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
assert( $settings instanceof Settings );
|
||||
|
@ -1124,4 +1140,11 @@ return array(
|
|||
return new PurchaseUnitSanitizer( $behavior, $line_name );
|
||||
}
|
||||
),
|
||||
'api.user-id-token' => static function( ContainerInterface $container ): UserIdToken {
|
||||
return new UserIdToken(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
105
modules/ppcp-api-client/src/Authentication/UserIdToken.php
Normal file
105
modules/ppcp-api-client/src/Authentication/UserIdToken.php
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
/**
|
||||
* Generates user ID token for payer.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Authentication
|
||||
*/
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Authentication;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Class UserIdToken
|
||||
*/
|
||||
class UserIdToken {
|
||||
|
||||
use RequestTrait;
|
||||
|
||||
/**
|
||||
* The host.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* The bearer.
|
||||
*
|
||||
* @var Bearer
|
||||
*/
|
||||
private $bearer;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* UserIdToken constructor.
|
||||
*
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
string $host,
|
||||
Bearer $bearer,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `id_token` which uniquely identifies the payer.
|
||||
*
|
||||
* @param string $target_customer_id Vaulted customer id.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws PayPalApiException If the request fails.
|
||||
* @throws RuntimeException If something unexpected happens.
|
||||
*/
|
||||
public function id_token( string $target_customer_id = '' ): string {
|
||||
$bearer = $this->bearer->bearer();
|
||||
|
||||
$url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials&response_type=id_token';
|
||||
if ( $target_customer_id ) {
|
||||
$url = add_query_arg(
|
||||
array(
|
||||
'target_customer_id' => $target_customer_id,
|
||||
),
|
||||
$url
|
||||
);
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
if ( $response instanceof WP_Error ) {
|
||||
throw new RuntimeException( $response->get_error_message() );
|
||||
}
|
||||
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( 200 !== $status_code ) {
|
||||
throw new PayPalApiException( $json, $status_code );
|
||||
}
|
||||
|
||||
return $json->id_token;
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PatchCollectionFactory;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Helper\ErrorResponse;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet;
|
||||
use WP_Error;
|
||||
|
||||
|
@ -178,8 +178,10 @@ class OrderEndpoint {
|
|||
* @param string $shipping_preference One of ApplicationContext::SHIPPING_PREFERENCE_ values.
|
||||
* @param Payer|null $payer The payer off the order.
|
||||
* @param PaymentToken|null $payment_token The payment token.
|
||||
* @param string $paypal_request_id The paypal request id.
|
||||
* @param string $paypal_request_id The PayPal request id.
|
||||
* @param string $user_action The user action.
|
||||
* @param string $payment_method WC payment method.
|
||||
* @param array $request_data Request data.
|
||||
*
|
||||
* @return Order
|
||||
* @throws RuntimeException If the request fails.
|
||||
|
@ -190,7 +192,9 @@ class OrderEndpoint {
|
|||
Payer $payer = null,
|
||||
PaymentToken $payment_token = null,
|
||||
string $paypal_request_id = '',
|
||||
string $user_action = ApplicationContext::USER_ACTION_CONTINUE
|
||||
string $user_action = ApplicationContext::USER_ACTION_CONTINUE,
|
||||
string $payment_method = '',
|
||||
array $request_data = array()
|
||||
): Order {
|
||||
$bearer = $this->bearer->bearer();
|
||||
$data = array(
|
||||
|
@ -221,7 +225,7 @@ class OrderEndpoint {
|
|||
/**
|
||||
* The filter can be used to modify the order creation request body data.
|
||||
*/
|
||||
$data = apply_filters( 'ppcp_create_order_request_body_data', $data );
|
||||
$data = apply_filters( 'ppcp_create_order_request_body_data', $data, $payment_method, $request_data );
|
||||
$url = trailingslashit( $this->host ) . 'v2/checkout/orders';
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
|
@ -260,26 +264,25 @@ class OrderEndpoint {
|
|||
);
|
||||
throw $error;
|
||||
}
|
||||
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( 201 !== $status_code ) {
|
||||
if ( ! in_array( $status_code, array( 200, 201 ), true ) ) {
|
||||
$error = new PayPalApiException(
|
||||
$json,
|
||||
$status_code
|
||||
);
|
||||
$this->logger->log(
|
||||
'warning',
|
||||
|
||||
$this->logger->warning(
|
||||
sprintf(
|
||||
'Failed to create order. PayPal API response: %1$s',
|
||||
$error->getMessage()
|
||||
),
|
||||
array(
|
||||
'args' => $args,
|
||||
'response' => $response,
|
||||
)
|
||||
);
|
||||
|
||||
throw $error;
|
||||
}
|
||||
|
||||
$order = $this->order_factory->from_paypal_response( $json );
|
||||
|
||||
do_action( 'woocommerce_paypal_payments_paypal_order_created', $order );
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
/**
|
||||
* The Payment Method Tokens endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use stdClass;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Class PaymentMethodTokensEndpoint
|
||||
*/
|
||||
class PaymentMethodTokensEndpoint {
|
||||
|
||||
use RequestTrait;
|
||||
|
||||
/**
|
||||
* The host.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* The bearer.
|
||||
*
|
||||
* @var Bearer
|
||||
*/
|
||||
private $bearer;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* PaymentMethodTokensEndpoint constructor.
|
||||
*
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct( string $host, Bearer $bearer, LoggerInterface $logger ) {
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a setup token.
|
||||
*
|
||||
* @param PaymentSource $payment_source The payment source.
|
||||
*
|
||||
* @return stdClass
|
||||
*
|
||||
* @throws RuntimeException When something when wrong with the request.
|
||||
* @throws PayPalApiException When something when wrong setting up the token.
|
||||
*/
|
||||
public function setup_tokens( PaymentSource $payment_source ): stdClass {
|
||||
$data = array(
|
||||
'payment_source' => array(
|
||||
$payment_source->name() => $payment_source->properties(),
|
||||
),
|
||||
);
|
||||
|
||||
$bearer = $this->bearer->bearer();
|
||||
$url = trailingslashit( $this->host ) . 'v3/vault/setup-tokens';
|
||||
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||
'Content-Type' => 'application/json',
|
||||
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
|
||||
),
|
||||
'body' => wp_json_encode( $data ),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) || ! is_array( $response ) ) {
|
||||
throw new RuntimeException( 'Not able to create setup token.' );
|
||||
}
|
||||
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( ! in_array( $status_code, array( 200, 201 ), true ) ) {
|
||||
throw new PayPalApiException(
|
||||
$json,
|
||||
$status_code
|
||||
);
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a payment token for the given payment source.
|
||||
*
|
||||
* @param PaymentSource $payment_source The payment source.
|
||||
*
|
||||
* @return stdClass
|
||||
*
|
||||
* @throws RuntimeException When something when wrong with the request.
|
||||
* @throws PayPalApiException When something when wrong setting up the token.
|
||||
*/
|
||||
public function payment_tokens( PaymentSource $payment_source ): stdClass {
|
||||
$data = array(
|
||||
'payment_source' => array(
|
||||
$payment_source->name() => $payment_source->properties(),
|
||||
),
|
||||
);
|
||||
|
||||
$bearer = $this->bearer->bearer();
|
||||
$url = trailingslashit( $this->host ) . 'v3/vault/payment-tokens';
|
||||
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||
'Content-Type' => 'application/json',
|
||||
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
|
||||
),
|
||||
'body' => wp_json_encode( $data ),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) || ! is_array( $response ) ) {
|
||||
throw new RuntimeException( 'Not able to create setup token.' );
|
||||
}
|
||||
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( ! in_array( $status_code, array( 200, 201 ), true ) ) {
|
||||
throw new PayPalApiException(
|
||||
$json,
|
||||
$status_code
|
||||
);
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
/**
|
||||
* Payment tokens version 3 endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Class PaymentTokensEndpoint
|
||||
*/
|
||||
class PaymentTokensEndpoint {
|
||||
|
||||
use RequestTrait;
|
||||
|
||||
/**
|
||||
* The bearer.
|
||||
*
|
||||
* @var Bearer
|
||||
*/
|
||||
private $bearer;
|
||||
|
||||
/**
|
||||
* The host.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* PaymentTokensEndpoint constructor.
|
||||
*
|
||||
* @param string $host The bearer.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
string $host,
|
||||
Bearer $bearer,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a payment token with the given id.
|
||||
*
|
||||
* @param string $id Payment token id.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws RuntimeException When something went wrong with the request.
|
||||
* @throws PayPalApiException When something went wrong deleting the payment token.
|
||||
*/
|
||||
public function delete( string $id ): void {
|
||||
$bearer = $this->bearer->bearer();
|
||||
$url = trailingslashit( $this->host ) . 'v3/vault/payment-tokens/' . $id;
|
||||
$args = array(
|
||||
'method' => 'DELETE',
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||
'Content-Type' => 'application/json',
|
||||
),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
if ( $response instanceof WP_Error ) {
|
||||
throw new RuntimeException( $response->get_error_message() );
|
||||
}
|
||||
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( 204 !== $status_code ) {
|
||||
throw new PayPalApiException( $json, $status_code );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
|||
*/
|
||||
class CardAuthenticationResult {
|
||||
|
||||
|
||||
const LIABILITY_SHIFT_POSSIBLE = 'POSSIBLE';
|
||||
const LIABILITY_SHIFT_NO = 'NO';
|
||||
const LIABILITY_SHIFT_UNKNOWN = 'UNKNOWN';
|
||||
|
|
|
@ -107,14 +107,6 @@ class Order {
|
|||
|
||||
$this->id = $id;
|
||||
$this->application_context = $application_context;
|
||||
$this->purchase_units = array_values(
|
||||
array_filter(
|
||||
$purchase_units,
|
||||
static function ( $unit ): bool {
|
||||
return is_a( $unit, PurchaseUnit::class );
|
||||
}
|
||||
)
|
||||
);
|
||||
$this->payer = $payer;
|
||||
$this->order_status = $order_status;
|
||||
$this->intent = ( 'CAPTURE' === $intent ) ? 'CAPTURE' : 'AUTHORIZE';
|
||||
|
@ -236,9 +228,6 @@ class Order {
|
|||
if ( $this->application_context() ) {
|
||||
$order['application_context'] = $this->application_context()->to_array();
|
||||
}
|
||||
if ( $this->payment_source() ) {
|
||||
$order['payment_source'] = $this->payment_source()->to_array();
|
||||
}
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
|
|
@ -15,14 +15,15 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
|||
* Class OrderStatus
|
||||
*/
|
||||
class OrderStatus {
|
||||
const INTERNAL = 'INTERNAL';
|
||||
const CREATED = 'CREATED';
|
||||
const SAVED = 'SAVED';
|
||||
const APPROVED = 'APPROVED';
|
||||
const VOIDED = 'VOIDED';
|
||||
const COMPLETED = 'COMPLETED';
|
||||
const PENDING_APPROVAL = 'PENDING_APPROVAL';
|
||||
const VALID_STATUS = array(
|
||||
const INTERNAL = 'INTERNAL';
|
||||
const CREATED = 'CREATED';
|
||||
const SAVED = 'SAVED';
|
||||
const APPROVED = 'APPROVED';
|
||||
const VOIDED = 'VOIDED';
|
||||
const COMPLETED = 'COMPLETED';
|
||||
const PENDING_APPROVAL = 'PENDING_APPROVAL';
|
||||
const PAYER_ACTION_REQUIRED = 'PAYER_ACTION_REQUIRED';
|
||||
const VALID_STATUS = array(
|
||||
self::INTERNAL,
|
||||
self::CREATED,
|
||||
self::SAVED,
|
||||
|
@ -30,6 +31,7 @@ class OrderStatus {
|
|||
self::VOIDED,
|
||||
self::COMPLETED,
|
||||
self::PENDING_APPROVAL,
|
||||
self::PAYER_ACTION_REQUIRED,
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,74 +9,53 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class PaymentSource
|
||||
*/
|
||||
class PaymentSource {
|
||||
|
||||
/**
|
||||
* The card.
|
||||
* Payment source name.
|
||||
*
|
||||
* @var PaymentSourceCard|null
|
||||
* @var string
|
||||
*/
|
||||
private $card;
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* The wallet.
|
||||
* Payment source properties.
|
||||
*
|
||||
* @var PaymentSourceWallet|null
|
||||
* @var stdClass
|
||||
*/
|
||||
private $wallet;
|
||||
private $properties;
|
||||
|
||||
/**
|
||||
* PaymentSource constructor.
|
||||
*
|
||||
* @param PaymentSourceCard|null $card The card.
|
||||
* @param PaymentSourceWallet|null $wallet The wallet.
|
||||
* @param string $name Payment source name.
|
||||
* @param stdClass $properties Payment source properties.
|
||||
*/
|
||||
public function __construct(
|
||||
PaymentSourceCard $card = null,
|
||||
PaymentSourceWallet $wallet = null
|
||||
) {
|
||||
|
||||
$this->card = $card;
|
||||
$this->wallet = $wallet;
|
||||
public function __construct( string $name, stdClass $properties ) {
|
||||
$this->name = $name;
|
||||
$this->properties = $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the card.
|
||||
* Payment source name.
|
||||
*
|
||||
* @return PaymentSourceCard|null
|
||||
* @return string
|
||||
*/
|
||||
public function card() {
|
||||
|
||||
return $this->card;
|
||||
public function name(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wallet.
|
||||
* Payment source properties.
|
||||
*
|
||||
* @return PaymentSourceWallet|null
|
||||
* @return stdClass
|
||||
*/
|
||||
public function wallet() {
|
||||
|
||||
return $this->wallet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array of the object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function to_array(): array {
|
||||
|
||||
$data = array();
|
||||
if ( $this->card() ) {
|
||||
$data['card'] = $this->card()->to_array();
|
||||
}
|
||||
if ( $this->wallet() ) {
|
||||
$data['wallet'] = $this->wallet()->to_array();
|
||||
}
|
||||
return $data;
|
||||
public function properties(): stdClass {
|
||||
return $this->properties;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* The PaymentSourceCard object.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||
|
||||
/**
|
||||
* Class PaymentSourceCard
|
||||
*/
|
||||
class PaymentSourceCard {
|
||||
|
||||
/**
|
||||
* The last digits of the card.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $last_digits;
|
||||
|
||||
/**
|
||||
* The brand.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $brand;
|
||||
|
||||
/**
|
||||
* The type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* The authentication result.
|
||||
*
|
||||
* @var CardAuthenticationResult|null
|
||||
*/
|
||||
private $authentication_result;
|
||||
|
||||
/**
|
||||
* PaymentSourceCard constructor.
|
||||
*
|
||||
* @param string $last_digits The last digits of the card.
|
||||
* @param string $brand The brand of the card.
|
||||
* @param string $type The type of the card.
|
||||
* @param CardAuthenticationResult|null $authentication_result The authentication result.
|
||||
*/
|
||||
public function __construct(
|
||||
string $last_digits,
|
||||
string $brand,
|
||||
string $type,
|
||||
CardAuthenticationResult $authentication_result = null
|
||||
) {
|
||||
|
||||
$this->last_digits = $last_digits;
|
||||
$this->brand = $brand;
|
||||
$this->type = $type;
|
||||
$this->authentication_result = $authentication_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last digits.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function last_digits(): string {
|
||||
|
||||
return $this->last_digits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the brand.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function brand(): string {
|
||||
|
||||
return $this->brand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function type(): string {
|
||||
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authentication result.
|
||||
*
|
||||
* @return CardAuthenticationResult|null
|
||||
*/
|
||||
public function authentication_result() {
|
||||
|
||||
return $this->authentication_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object as array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function to_array(): array {
|
||||
|
||||
$data = array(
|
||||
'last_digits' => $this->last_digits(),
|
||||
'brand' => $this->brand(),
|
||||
'type' => $this->type(),
|
||||
);
|
||||
if ( $this->authentication_result() ) {
|
||||
$data['authentication_result'] = $this->authentication_result()->to_array();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* The PaymentSourcewallet.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||
|
||||
/**
|
||||
* Class PaymentSourceWallet
|
||||
*/
|
||||
class PaymentSourceWallet {
|
||||
|
||||
/**
|
||||
* Returns the object as array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function to_array(): array {
|
||||
return array();
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\AmountBreakdown;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Item;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/**
|
||||
* The card authentication result factory.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||
|
||||
use stdClass;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult;
|
||||
|
||||
/**
|
||||
* Class CardAuthenticationResultFactory
|
||||
*/
|
||||
class CardAuthenticationResultFactory {
|
||||
|
||||
/**
|
||||
* Returns a card authentication result from the given response object.
|
||||
*
|
||||
* @param stdClass $authentication_result The authentication result object.
|
||||
* @return CardAuthenticationResult
|
||||
*/
|
||||
public function from_paypal_response( stdClass $authentication_result ): CardAuthenticationResult {
|
||||
return new CardAuthenticationResult(
|
||||
$authentication_result->liability_shift ?? '',
|
||||
$authentication_result->three_d_secure->enrollment_status ?? '',
|
||||
$authentication_result->three_d_secure->authentication_status ?? ''
|
||||
);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
|||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
|
||||
|
@ -48,13 +49,6 @@ class OrderFactory {
|
|||
*/
|
||||
private $application_context_factory;
|
||||
|
||||
/**
|
||||
* The PaymentSource factory.
|
||||
*
|
||||
* @var PaymentSourceFactory
|
||||
*/
|
||||
private $payment_source_factory;
|
||||
|
||||
/**
|
||||
* OrderFactory constructor.
|
||||
*
|
||||
|
@ -62,21 +56,18 @@ class OrderFactory {
|
|||
* @param PayerFactory $payer_factory The Payer factory.
|
||||
* @param ApplicationContextRepository $application_context_repository The Application Context repository.
|
||||
* @param ApplicationContextFactory $application_context_factory The Application Context factory.
|
||||
* @param PaymentSourceFactory $payment_source_factory The Payment Source factory.
|
||||
*/
|
||||
public function __construct(
|
||||
PurchaseUnitFactory $purchase_unit_factory,
|
||||
PayerFactory $payer_factory,
|
||||
ApplicationContextRepository $application_context_repository,
|
||||
ApplicationContextFactory $application_context_factory,
|
||||
PaymentSourceFactory $payment_source_factory
|
||||
ApplicationContextFactory $application_context_factory
|
||||
) {
|
||||
|
||||
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||
$this->payer_factory = $payer_factory;
|
||||
$this->application_context_repository = $application_context_repository;
|
||||
$this->application_context_factory = $application_context_factory;
|
||||
$this->payment_source_factory = $payment_source_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,9 +143,23 @@ class OrderFactory {
|
|||
$application_context = ( isset( $order_data->application_context ) ) ?
|
||||
$this->application_context_factory->from_paypal_response( $order_data->application_context )
|
||||
: null;
|
||||
$payment_source = ( isset( $order_data->payment_source ) ) ?
|
||||
$this->payment_source_factory->from_paypal_response( $order_data->payment_source ) :
|
||||
null;
|
||||
|
||||
$payment_source = null;
|
||||
if ( isset( $order_data->payment_source ) ) {
|
||||
$json_encoded_payment_source = wp_json_encode( $order_data->payment_source );
|
||||
if ( $json_encoded_payment_source ) {
|
||||
$payment_source_as_array = json_decode( $json_encoded_payment_source, true );
|
||||
if ( $payment_source_as_array ) {
|
||||
$name = array_key_first( $payment_source_as_array );
|
||||
if ( $name ) {
|
||||
$payment_source = new PaymentSource(
|
||||
$name,
|
||||
$order_data->payment_source->$name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Order(
|
||||
$order_data->id,
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* The PaymentSource factory.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSourceCard;
|
||||
|
||||
/**
|
||||
* Class PaymentSourceFactory
|
||||
*/
|
||||
class PaymentSourceFactory {
|
||||
|
||||
/**
|
||||
* Returns a PaymentSource for a PayPal Response.
|
||||
*
|
||||
* @param \stdClass $data The JSON object.
|
||||
*
|
||||
* @return PaymentSource
|
||||
*/
|
||||
public function from_paypal_response( \stdClass $data ): PaymentSource {
|
||||
|
||||
$card = null;
|
||||
$wallet = null;
|
||||
if ( isset( $data->card ) ) {
|
||||
$authentication_result = null;
|
||||
if ( isset( $data->card->authentication_result ) ) {
|
||||
$authentication_result = new CardAuthenticationResult(
|
||||
isset( $data->card->authentication_result->liability_shift ) ?
|
||||
(string) $data->card->authentication_result->liability_shift : '',
|
||||
isset( $data->card->authentication_result->three_d_secure->enrollment_status ) ?
|
||||
(string) $data->card->authentication_result->three_d_secure->enrollment_status : '',
|
||||
isset( $data->card->authentication_result->three_d_secure->authentication_status ) ?
|
||||
(string) $data->card->authentication_result->three_d_secure->authentication_status : ''
|
||||
);
|
||||
}
|
||||
$card = new PaymentSourceCard(
|
||||
isset( $data->card->last_digits ) ? (string) $data->card->last_digits : '',
|
||||
isset( $data->card->brand ) ? (string) $data->card->brand : '',
|
||||
isset( $data->card->type ) ? (string) $data->card->type : '',
|
||||
$authentication_result
|
||||
);
|
||||
}
|
||||
return new PaymentSource( $card, $wallet );
|
||||
}
|
||||
}
|
|
@ -56,6 +56,8 @@ class CheckoutActionHandler {
|
|||
const paymentMethod = getCurrentPaymentMethod();
|
||||
const fundingSource = window.ppcpFundingSource;
|
||||
|
||||
const savePaymentMethod = !!document.getElementById('wc-ppcp-credit-card-gateway-new-payment-method')?.checked;
|
||||
|
||||
return fetch(this.config.ajax.create_order.endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -72,7 +74,8 @@ class CheckoutActionHandler {
|
|||
funding_source: fundingSource,
|
||||
// send as urlencoded string to handle complex fields via PHP functions the same as normal form submit
|
||||
form_encoded: new URLSearchParams(formData).toString(),
|
||||
createaccount: createaccount
|
||||
createaccount: createaccount,
|
||||
save_payment_method: savePaymentMethod
|
||||
})
|
||||
}).then(function (res) {
|
||||
return res.json();
|
||||
|
|
|
@ -64,6 +64,12 @@ export const loadPaypalScript = (config, onLoaded, onError = null) => {
|
|||
return;
|
||||
}
|
||||
|
||||
// Adds data-user-id-token to script options.
|
||||
const userIdToken = config?.save_payment_methods?.id_token;
|
||||
if(userIdToken) {
|
||||
scriptOptions['data-user-id-token'] = userIdToken;
|
||||
}
|
||||
|
||||
// Load PayPal script
|
||||
loadScript(scriptOptions)
|
||||
.then(callback)
|
||||
|
|
|
@ -91,12 +91,30 @@ class CardFieldsRenderer {
|
|||
this.spinner.block();
|
||||
this.errorHandler.clear();
|
||||
|
||||
const paymentToken = document.querySelector('input[name="wc-ppcp-credit-card-gateway-payment-token"]:checked').value
|
||||
if(paymentToken !== 'new') {
|
||||
fetch(this.defaultConfig.ajax.capture_card_payment.endpoint, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify({
|
||||
nonce: this.defaultConfig.ajax.capture_card_payment.nonce,
|
||||
payment_token: paymentToken
|
||||
})
|
||||
}).then((res) => {
|
||||
return res.json();
|
||||
}).then((data) => {
|
||||
document.querySelector('#place_order').click();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cardField.submit()
|
||||
.catch((error) => {
|
||||
this.spinner.unblock();
|
||||
console.error(error)
|
||||
this.errorHandler.message(this.defaultConfig.hosted_fields.labels.fields_not_valid);
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -150,6 +168,9 @@ class CardFieldsRenderer {
|
|||
|
||||
return styles;
|
||||
}
|
||||
|
||||
disableFields() {}
|
||||
enableFields() {}
|
||||
}
|
||||
|
||||
export default CardFieldsRenderer;
|
||||
|
|
|
@ -119,7 +119,7 @@ return array(
|
|||
$request_data = $container->get( 'button.request-data' );
|
||||
$client_id = $container->get( 'button.client_id' );
|
||||
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
$messages_apply = $container->get( 'button.helper.messages-apply' );
|
||||
$environment = $container->get( 'onboarding.environment' );
|
||||
$payment_token_repository = $container->get( 'vaulting.repository.payment-token' );
|
||||
|
@ -294,8 +294,10 @@ return array(
|
|||
},
|
||||
|
||||
'button.helper.three-d-secure' => static function ( ContainerInterface $container ): ThreeDSecure {
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
return new ThreeDSecure( $logger );
|
||||
return new ThreeDSecure(
|
||||
$container->get( 'api.factory.card-authentication-result-factory' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'button.helper.messages-apply' => static function ( ContainerInterface $container ): MessagesApply {
|
||||
return new MessagesApply(
|
||||
|
|
|
@ -33,8 +33,8 @@ use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait;
|
|||
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
|
@ -303,7 +303,13 @@ class SmartButton implements SmartButtonInterface {
|
|||
add_filter(
|
||||
'woocommerce_credit_card_form_fields',
|
||||
function ( array $default_fields, $id ) use ( $subscription_helper ) : array {
|
||||
if ( is_user_logged_in() && $this->settings->has( 'vault_enabled_dcc' ) && $this->settings->get( 'vault_enabled_dcc' ) && CreditCardGateway::ID === $id ) {
|
||||
if (
|
||||
is_user_logged_in()
|
||||
&& $this->settings->has( 'vault_enabled_dcc' )
|
||||
&& $this->settings->get( 'vault_enabled_dcc' )
|
||||
&& CreditCardGateway::ID === $id
|
||||
&& apply_filters( 'woocommerce_paypal_payments_should_render_card_custom_fields', true )
|
||||
) {
|
||||
|
||||
$default_fields['card-vault'] = sprintf(
|
||||
'<p class="form-row form-row-wide"><label for="ppcp-credit-card-vault"><input class="ppcp-credit-card-vault" type="checkbox" id="ppcp-credit-card-vault" name="vault">%s</label></p>',
|
||||
|
@ -638,7 +644,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
return $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' )
|
||||
&& $this->settings->has( 'client_id' ) && $this->settings->get( 'client_id' )
|
||||
&& $this->dcc_applies->for_country_currency()
|
||||
&& in_array( $this->context(), array( 'checkout', 'pay-now' ), true );
|
||||
&& in_array( $this->context(), array( 'checkout', 'pay-now', 'add-payment-method' ), true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1162,7 +1168,8 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
}
|
||||
|
||||
$this->request_data->dequeue_nonce_fix();
|
||||
return $localize;
|
||||
|
||||
return apply_filters( 'woocommerce_paypal_payments_localized_script_data', $localize );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,6 +14,7 @@ use Exception;
|
|||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderHelper;
|
||||
|
@ -144,10 +145,11 @@ class ApproveOrderEndpoint implements EndpointInterface {
|
|||
|
||||
$order = $this->api_endpoint->order( $data['order_id'] );
|
||||
|
||||
if ( $order->payment_source() && $order->payment_source()->card() ) {
|
||||
$payment_source = $order->payment_source();
|
||||
if ( $payment_source && $payment_source->name() === 'card' ) {
|
||||
if ( $this->settings->has( 'disable_cards' ) ) {
|
||||
$disabled_cards = (array) $this->settings->get( 'disable_cards' );
|
||||
$card = strtolower( $order->payment_source()->card()->brand() );
|
||||
$card = strtolower( $payment_source->properties()->brand ?? '' );
|
||||
if ( 'master_card' === $card ) {
|
||||
$card = 'mastercard';
|
||||
}
|
||||
|
|
|
@ -25,12 +25,11 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderTransient;
|
||||
use WooCommerce\PayPalCommerce\Button\Exception\ValidationException;
|
||||
use WooCommerce\PayPalCommerce\Button\Validation\CheckoutFormValidator;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\CardBillingMode;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
|
@ -305,7 +304,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
}
|
||||
|
||||
try {
|
||||
$order = $this->create_paypal_order( $wc_order );
|
||||
$order = $this->create_paypal_order( $wc_order, $payment_method, $data );
|
||||
} catch ( Exception $exception ) {
|
||||
$this->logger->error( 'Order creation failed: ' . $exception->getMessage() );
|
||||
throw $exception;
|
||||
|
@ -416,6 +415,8 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
* Creates the order in the PayPal, uses data from WC order if provided.
|
||||
*
|
||||
* @param \WC_Order|null $wc_order WC order to get data from.
|
||||
* @param string $payment_method WC payment method.
|
||||
* @param array $data Request data.
|
||||
*
|
||||
* @return Order Created PayPal order.
|
||||
*
|
||||
|
@ -423,7 +424,7 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
* @throws PayPalApiException If create order request fails.
|
||||
* phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
|
||||
*/
|
||||
private function create_paypal_order( \WC_Order $wc_order = null ): Order {
|
||||
private function create_paypal_order( \WC_Order $wc_order = null, string $payment_method = '', array $data = array() ): Order {
|
||||
assert( $this->purchase_unit instanceof PurchaseUnit );
|
||||
|
||||
$funding_source = $this->parsed_request_data['funding_source'] ?? '';
|
||||
|
@ -465,7 +466,9 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|||
$payer,
|
||||
null,
|
||||
'',
|
||||
$action
|
||||
$action,
|
||||
$payment_method,
|
||||
$data
|
||||
);
|
||||
} catch ( PayPalApiException $exception ) {
|
||||
// Looks like currently there is no proper way to validate the shipping address for PayPal,
|
||||
|
|
|
@ -94,6 +94,10 @@ trait ContextTrait {
|
|||
return 'checkout';
|
||||
}
|
||||
|
||||
if ( $this->is_add_payment_method_page() ) {
|
||||
return 'add-payment-method';
|
||||
}
|
||||
|
||||
return 'mini-cart';
|
||||
}
|
||||
|
||||
|
@ -125,6 +129,11 @@ trait ContextTrait {
|
|||
* @return bool
|
||||
*/
|
||||
private function is_paypal_continuation(): bool {
|
||||
/**
|
||||
* Property is already defined in trait consumers.
|
||||
*
|
||||
* @psalm-suppress UndefinedThisPropertyFetch
|
||||
*/
|
||||
$order = $this->session_handler->order();
|
||||
if ( ! $order ) {
|
||||
return false;
|
||||
|
@ -137,7 +146,7 @@ trait ContextTrait {
|
|||
}
|
||||
|
||||
$source = $order->payment_source();
|
||||
if ( $source && $source->card() ) {
|
||||
if ( $source && $source->name() === 'card' ) {
|
||||
return false; // Ignore for DCC.
|
||||
}
|
||||
|
||||
|
@ -147,4 +156,22 @@ trait ContextTrait {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether current page is Add payment method.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_add_payment_method_page(): bool {
|
||||
/**
|
||||
* Needed for WordPress `query_vars`.
|
||||
*
|
||||
* @psalm-suppress InvalidGlobal
|
||||
*/
|
||||
global $wp;
|
||||
|
||||
$page_id = wc_get_page_id( 'myaccount' );
|
||||
|
||||
return $page_id && is_page( $page_id ) && isset( $wp->query_vars['add-payment-method'] );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\Button\Helper;
|
|||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult as AuthResult;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory;
|
||||
|
||||
/**
|
||||
* Class ThreeDSecure
|
||||
|
@ -23,6 +24,13 @@ class ThreeDSecure {
|
|||
const REJECT = 2;
|
||||
const RETRY = 3;
|
||||
|
||||
/**
|
||||
* Card authentication result factory.
|
||||
*
|
||||
* @var CardAuthenticationResultFactory
|
||||
*/
|
||||
private $card_authentication_result_factory;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
|
@ -33,10 +41,15 @@ class ThreeDSecure {
|
|||
/**
|
||||
* ThreeDSecure constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param CardAuthenticationResultFactory $card_authentication_result_factory Card authentication result factory.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct( LoggerInterface $logger ) {
|
||||
$this->logger = $logger;
|
||||
public function __construct(
|
||||
CardAuthenticationResultFactory $card_authentication_result_factory,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->logger = $logger;
|
||||
$this->card_authentication_result_factory = $card_authentication_result_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,29 +62,36 @@ class ThreeDSecure {
|
|||
* @return int
|
||||
*/
|
||||
public function proceed_with_order( Order $order ): int {
|
||||
if ( ! $order->payment_source() ) {
|
||||
return self::NO_DECISION;
|
||||
}
|
||||
if ( ! $order->payment_source()->card() ) {
|
||||
return self::NO_DECISION;
|
||||
}
|
||||
if ( ! $order->payment_source()->card()->authentication_result() ) {
|
||||
$payment_source = $order->payment_source();
|
||||
if ( ! $payment_source ) {
|
||||
return self::NO_DECISION;
|
||||
}
|
||||
|
||||
$result = $order->payment_source()->card()->authentication_result();
|
||||
$this->logger->info( '3DS authentication result: ' . wc_print_r( $result->to_array(), true ) );
|
||||
|
||||
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_POSSIBLE ) {
|
||||
return self::PROCCEED;
|
||||
if ( ! $payment_source->properties()->brand ?? '' ) {
|
||||
return self::NO_DECISION;
|
||||
}
|
||||
if ( ! $payment_source->properties()->authentication_result ?? '' ) {
|
||||
return self::NO_DECISION;
|
||||
}
|
||||
|
||||
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_UNKNOWN ) {
|
||||
return self::RETRY;
|
||||
}
|
||||
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_NO ) {
|
||||
return $this->no_liability_shift( $result );
|
||||
$authentication_result = $payment_source->properties()->authentication_result ?? null;
|
||||
if ( $authentication_result ) {
|
||||
$result = $this->card_authentication_result_factory->from_paypal_response( $authentication_result );
|
||||
|
||||
$this->logger->info( '3DS authentication result: ' . wc_print_r( $result->to_array(), true ) );
|
||||
|
||||
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_POSSIBLE ) {
|
||||
return self::PROCCEED;
|
||||
}
|
||||
|
||||
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_UNKNOWN ) {
|
||||
return self::RETRY;
|
||||
}
|
||||
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_NO ) {
|
||||
return $this->no_liability_shift( $result );
|
||||
}
|
||||
}
|
||||
|
||||
return self::NO_DECISION;
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,12 @@ class CardFieldsModule implements ModuleInterface {
|
|||
add_filter(
|
||||
'ppcp_create_order_request_body_data',
|
||||
function( array $data ) use ( $c ): array {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$payment_method = wc_clean( wp_unslash( $_POST['payment_method'] ?? '' ) );
|
||||
if ( $payment_method !== CreditCardGateway::ID ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
assert( $settings instanceof Settings );
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ return array(
|
|||
},
|
||||
|
||||
'compat.ppec.subscriptions-handler' => static function ( ContainerInterface $container ) {
|
||||
$ppcp_renewal_handler = $container->get( 'subscription.renewal-handler' );
|
||||
$ppcp_renewal_handler = $container->get( 'wc-subscriptions.renewal-handler' );
|
||||
$gateway = $container->get( 'compat.ppec.mock-gateway' );
|
||||
|
||||
return new PPEC\SubscriptionsHandler( $ppcp_renewal_handler, $gateway );
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace WooCommerce\PayPalCommerce\Compat\PPEC;
|
|||
|
||||
use Automattic\WooCommerce\Utilities\OrderUtil;
|
||||
use stdClass;
|
||||
use WooCommerce\PayPalCommerce\Subscription\RenewalHandler;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\RenewalHandler;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
|
||||
/**
|
||||
|
|
3
modules/ppcp-paypal-subscriptions/.gitignore
vendored
Normal file
3
modules/ppcp-paypal-subscriptions/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
node_modules
|
||||
assets/js
|
||||
assets/css
|
17
modules/ppcp-paypal-subscriptions/composer.json
Normal file
17
modules/ppcp-paypal-subscriptions/composer.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "woocommerce/ppcp-paypal-subscriptions",
|
||||
"type": "dhii-mod",
|
||||
"description": "Module for PayPal Subscriptions API integration",
|
||||
"license": "GPL-2.0",
|
||||
"require": {
|
||||
"php": "^7.2 | ^8.0",
|
||||
"dhii/module-interface": "^0.3.0-alpha1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WooCommerce\\PayPalCommerce\\PayPalSubscriptions\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
14
modules/ppcp-paypal-subscriptions/extensions.php
Normal file
14
modules/ppcp-paypal-subscriptions/extensions.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* The PayPalSubscriptions module extensions.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayPalSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayPalSubscriptions;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array();
|
16
modules/ppcp-paypal-subscriptions/module.php
Normal file
16
modules/ppcp-paypal-subscriptions/module.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* The PayPalSubscriptions module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayPalSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayPalSubscriptions;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
|
||||
return static function (): ModuleInterface {
|
||||
return new PayPalSubscriptionsModule();
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "ppcp-subscription",
|
||||
"name": "ppcp-paypal-subscriptions",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"browserslist": [
|
43
modules/ppcp-paypal-subscriptions/services.php
Normal file
43
modules/ppcp-paypal-subscriptions/services.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* The PayPalSubscriptions module services.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayPalSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayPalSubscriptions;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
'paypal-subscriptions.deactivate-plan-endpoint' => static function ( ContainerInterface $container ): DeactivatePlanEndpoint {
|
||||
return new DeactivatePlanEndpoint(
|
||||
$container->get( 'button.request-data' ),
|
||||
$container->get( 'api.endpoint.billing-plans' )
|
||||
);
|
||||
},
|
||||
'paypal-subscriptions.api-handler' => static function( ContainerInterface $container ): SubscriptionsApiHandler {
|
||||
return new SubscriptionsApiHandler(
|
||||
$container->get( 'api.endpoint.catalog-products' ),
|
||||
$container->get( 'api.factory.product' ),
|
||||
$container->get( 'api.endpoint.billing-plans' ),
|
||||
$container->get( 'api.factory.billing-cycle' ),
|
||||
$container->get( 'api.factory.payment-preferences' ),
|
||||
$container->get( 'api.shop.currency' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'paypal-subscriptions.module.url' => static function ( ContainerInterface $container ): string {
|
||||
/**
|
||||
* The path cannot be false.
|
||||
*
|
||||
* @psalm-suppress PossiblyFalseArgument
|
||||
*/
|
||||
return plugins_url(
|
||||
'/modules/ppcp-paypal-subscriptions/',
|
||||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
);
|
|
@ -2,12 +2,12 @@
|
|||
/**
|
||||
* The deactivate Subscription Plan Endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\OrderTracking\Endpoint
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare( strict_types=1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription;
|
||||
namespace WooCommerce\PayPalCommerce\PayPalSubscriptions;
|
||||
|
||||
use Exception;
|
||||
use WC_Product;
|
|
@ -1,50 +1,40 @@
|
|||
<?php
|
||||
/**
|
||||
* The subscription module.
|
||||
* The PayPalSubscriptions module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Subscription
|
||||
* @package WooCommerce\PayPalCommerce\PayPalSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription;
|
||||
namespace WooCommerce\PayPalCommerce\PayPalSubscriptions;
|
||||
|
||||
use ActionScheduler_Store;
|
||||
use Exception;
|
||||
use WC_Order;
|
||||
use WC_Product;
|
||||
use WC_Product_Subscription;
|
||||
use WC_Product_Subscription_Variation;
|
||||
use WC_Product_Variable;
|
||||
use WC_Product_Variable_Subscription;
|
||||
use WC_Subscription;
|
||||
use WC_Subscriptions_Product;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\OrderRepository;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Subscription;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* Class SubscriptionModule
|
||||
* Class SavedPaymentCheckerModule
|
||||
*/
|
||||
class SubscriptionModule implements ModuleInterface {
|
||||
|
||||
use TransactionIdHandlingTrait;
|
||||
class PayPalSubscriptionsModule implements ModuleInterface {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -60,470 +50,6 @@ class SubscriptionModule implements ModuleInterface {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
public function run( ContainerInterface $c ): void {
|
||||
add_action(
|
||||
'woocommerce_scheduled_subscription_payment_' . PayPalGateway::ID,
|
||||
function ( $amount, $order ) use ( $c ) {
|
||||
$this->renew( $order, $c );
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_scheduled_subscription_payment_' . CreditCardGateway::ID,
|
||||
function ( $amount, $order ) use ( $c ) {
|
||||
$this->renew( $order, $c );
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_subscription_payment_complete',
|
||||
function ( $subscription ) use ( $c ) {
|
||||
if ( ! in_array( $subscription->get_payment_method(), array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID ), true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$paypal_subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
|
||||
if ( $paypal_subscription_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$payment_token_repository = $c->get( 'vaulting.repository.payment-token' );
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
|
||||
$this->add_payment_token_id( $subscription, $payment_token_repository, $logger );
|
||||
|
||||
if ( count( $subscription->get_related_orders() ) === 1 ) {
|
||||
$parent_order = $subscription->get_parent();
|
||||
if ( is_a( $parent_order, WC_Order::class ) ) {
|
||||
$order_repository = $c->get( 'api.repository.order' );
|
||||
$order = $order_repository->for_wc_order( $parent_order );
|
||||
$transaction_id = $this->get_paypal_order_transaction_id( $order );
|
||||
if ( $transaction_id ) {
|
||||
$subscription->update_meta_data( 'ppcp_previous_transaction_reference', $transaction_id );
|
||||
$subscription->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_gateway_description',
|
||||
function ( $description, $id ) use ( $c ) {
|
||||
$payment_token_repository = $c->get( 'vaulting.repository.payment-token' );
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
$subscription_helper = $c->get( 'subscription.helper' );
|
||||
|
||||
return $this->display_saved_paypal_payments( $settings, (string) $id, $payment_token_repository, (string) $description, $subscription_helper );
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_credit_card_form_fields',
|
||||
function ( $default_fields, $id ) use ( $c ) {
|
||||
$payment_token_repository = $c->get( 'vaulting.repository.payment-token' );
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
$subscription_helper = $c->get( 'subscription.helper' );
|
||||
|
||||
return $this->display_saved_credit_cards( $settings, $id, $payment_token_repository, $default_fields, $subscription_helper );
|
||||
},
|
||||
20,
|
||||
2
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'ppcp_create_order_request_body_data',
|
||||
function( array $data ) use ( $c ) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$wc_order_action = wc_clean( wp_unslash( $_POST['wc_order_action'] ?? '' ) );
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$subscription_id = wc_clean( wp_unslash( $_POST['post_ID'] ?? '' ) );
|
||||
if ( ! $subscription_id ) {
|
||||
return $data;
|
||||
}
|
||||
$subscription = wc_get_order( $subscription_id );
|
||||
if ( ! is_a( $subscription, WC_Subscription::class ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (
|
||||
$wc_order_action === 'wcs_process_renewal' && $subscription->get_payment_method() === CreditCardGateway::ID
|
||||
&& isset( $data['payment_source']['token'] ) && $data['payment_source']['token']['type'] === 'PAYMENT_METHOD_TOKEN'
|
||||
&& isset( $data['payment_source']['token']['source']->card )
|
||||
) {
|
||||
$data['payment_source'] = array(
|
||||
'card' => array(
|
||||
'vault_id' => $data['payment_source']['token']['id'],
|
||||
'stored_credential' => array(
|
||||
'payment_initiator' => 'MERCHANT',
|
||||
'payment_type' => 'RECURRING',
|
||||
'usage' => 'SUBSEQUENT',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$previous_transaction_reference = $subscription->get_meta( 'ppcp_previous_transaction_reference' );
|
||||
if ( $previous_transaction_reference ) {
|
||||
$data['payment_source']['card']['stored_credential']['previous_transaction_reference'] = $previous_transaction_reference;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
);
|
||||
|
||||
$this->subscriptions_api_integration( $c );
|
||||
|
||||
add_action(
|
||||
'admin_enqueue_scripts',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( $hook ) use ( $c ) {
|
||||
if ( ! is_string( $hook ) ) {
|
||||
return;
|
||||
}
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
$subscription_mode = $settings->has( 'subscriptions_mode' ) ? $settings->get( 'subscriptions_mode' ) : '';
|
||||
if ( $hook !== 'post.php' || $subscription_mode !== 'subscriptions_api' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
$post_id = wc_clean( wp_unslash( $_GET['post'] ?? '' ) );
|
||||
$product = wc_get_product( $post_id );
|
||||
if ( ! ( is_a( $product, WC_Product::class ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscriptions_helper = $c->get( 'subscription.helper' );
|
||||
assert( $subscriptions_helper instanceof SubscriptionHelper );
|
||||
|
||||
if (
|
||||
! $subscriptions_helper->plugin_is_active()
|
||||
|| ! (
|
||||
is_a( $product, WC_Product_Subscription::class )
|
||||
|| is_a( $product, WC_Product_Variable_Subscription::class )
|
||||
|| is_a( $product, WC_Product_Subscription_Variation::class )
|
||||
)
|
||||
|| ! WC_Subscriptions_Product::is_subscription( $product )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$module_url = $c->get( 'subscription.module.url' );
|
||||
wp_enqueue_script(
|
||||
'ppcp-paypal-subscription',
|
||||
untrailingslashit( $module_url ) . '/assets/js/paypal-subscription.js',
|
||||
array( 'jquery' ),
|
||||
$c->get( 'ppcp.asset-version' ),
|
||||
true
|
||||
);
|
||||
|
||||
$products = array( $this->set_product_config( $product ) );
|
||||
if ( $product->get_type() === 'variable-subscription' ) {
|
||||
$products = array();
|
||||
|
||||
/**
|
||||
* Suppress pslam.
|
||||
*
|
||||
* @psalm-suppress TypeDoesNotContainType
|
||||
*
|
||||
* WC_Product_Variable_Subscription extends WC_Product_Variable.
|
||||
*/
|
||||
assert( $product instanceof WC_Product_Variable );
|
||||
$available_variations = $product->get_available_variations();
|
||||
foreach ( $available_variations as $variation ) {
|
||||
/**
|
||||
* The method is defined in WooCommerce.
|
||||
*
|
||||
* @psalm-suppress UndefinedMethod
|
||||
*/
|
||||
$variation = wc_get_product_object( 'variation', $variation['variation_id'] );
|
||||
$products[] = $this->set_product_config( $variation );
|
||||
}
|
||||
}
|
||||
|
||||
wp_localize_script(
|
||||
'ppcp-paypal-subscription',
|
||||
'PayPalCommerceGatewayPayPalSubscriptionProducts',
|
||||
$products
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
$endpoint = $c->get( 'subscription.deactivate-plan-endpoint' );
|
||||
assert( $endpoint instanceof DeactivatePlanEndpoint );
|
||||
add_action(
|
||||
'wc_ajax_' . DeactivatePlanEndpoint::ENDPOINT,
|
||||
array( $endpoint, 'handle_request' )
|
||||
);
|
||||
|
||||
add_action(
|
||||
'add_meta_boxes',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( string $post_type, $post_or_order_object ) use ( $c ) {
|
||||
if ( ! function_exists( 'wcs_get_subscription' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$order = ( $post_or_order_object instanceof WP_Post )
|
||||
? wc_get_order( $post_or_order_object->ID )
|
||||
: $post_or_order_object;
|
||||
|
||||
if ( ! is_a( $order, WC_Order::class ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscription = wcs_get_subscription( $order->get_id() );
|
||||
if ( ! is_a( $subscription, WC_Subscription::class ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
|
||||
if ( ! $subscription_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$screen_id = wc_get_page_screen_id( 'shop_subscription' );
|
||||
remove_meta_box( 'woocommerce-subscription-schedule', $screen_id, 'side' );
|
||||
|
||||
$environment = $c->get( 'onboarding.environment' );
|
||||
add_meta_box(
|
||||
'ppcp_paypal_subscription',
|
||||
__( 'PayPal Subscription', 'woocommerce-paypal-payments' ),
|
||||
function() use ( $subscription_id, $environment ) {
|
||||
$host = $environment->current_environment_is( Environment::SANDBOX ) ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com';
|
||||
$url = trailingslashit( $host ) . 'billing/subscriptions/' . $subscription_id;
|
||||
echo '<p>' . esc_html__( 'This subscription is linked to a PayPal Subscription, Cancel it to unlink.', 'woocommerce-paypal-payments' ) . '</p>';
|
||||
echo '<p><strong>' . esc_html__( 'Subscription:', 'woocommerce-paypal-payments' ) . '</strong> <a href="' . esc_url( $url ) . '" target="_blank">' . esc_attr( $subscription_id ) . '</a></p>';
|
||||
},
|
||||
$post_type,
|
||||
'side'
|
||||
);
|
||||
|
||||
},
|
||||
30,
|
||||
2
|
||||
);
|
||||
|
||||
add_action(
|
||||
'action_scheduler_before_execute',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( $action_id ) {
|
||||
/**
|
||||
* Class exist in WooCommerce.
|
||||
*
|
||||
* @psalm-suppress UndefinedClass
|
||||
*/
|
||||
$store = ActionScheduler_Store::instance();
|
||||
$action = $store->fetch_action( $action_id );
|
||||
|
||||
$subscription_id = $action->get_args()['subscription_id'] ?? null;
|
||||
if ( $subscription_id ) {
|
||||
$subscription = wcs_get_subscription( $subscription_id );
|
||||
if ( is_a( $subscription, WC_Subscription::class ) ) {
|
||||
$paypal_subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
|
||||
if ( $paypal_subscription_id ) {
|
||||
as_unschedule_action( $action->get_hook(), $action->get_args() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key for the module.
|
||||
*
|
||||
* @return string|void
|
||||
*/
|
||||
public function getKey() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Subscription product renewal.
|
||||
*
|
||||
* @param \WC_Order $order WooCommerce order.
|
||||
* @param ContainerInterface|null $container The container.
|
||||
* @return void
|
||||
*/
|
||||
protected function renew( $order, $container ) {
|
||||
if ( ! ( $order instanceof \WC_Order ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$handler = $container->get( 'subscription.renewal-handler' );
|
||||
$handler->renew( $order );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Payment token ID to subscription.
|
||||
*
|
||||
* @param \WC_Subscription $subscription The subscription.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment repository.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
protected function add_payment_token_id(
|
||||
\WC_Subscription $subscription,
|
||||
PaymentTokenRepository $payment_token_repository,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
try {
|
||||
$tokens = $payment_token_repository->all_for_user_id( $subscription->get_customer_id() );
|
||||
if ( $tokens ) {
|
||||
$latest_token_id = end( $tokens )->id() ? end( $tokens )->id() : '';
|
||||
$subscription->update_meta_data( 'payment_token_id', $latest_token_id );
|
||||
$subscription->save();
|
||||
}
|
||||
} catch ( RuntimeException $error ) {
|
||||
$message = sprintf(
|
||||
// translators: %1$s is the payment token Id, %2$s is the error message.
|
||||
__(
|
||||
'Could not add token Id to subscription %1$s: %2$s',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
$subscription->get_id(),
|
||||
$error->getMessage()
|
||||
);
|
||||
|
||||
$logger->log( 'warning', $message );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays saved PayPal payments.
|
||||
*
|
||||
* @param Settings $settings The settings.
|
||||
* @param string $id The payment gateway Id.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
||||
* @param string $description The payment gateway description.
|
||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||
* @return string
|
||||
*/
|
||||
protected function display_saved_paypal_payments(
|
||||
Settings $settings,
|
||||
string $id,
|
||||
PaymentTokenRepository $payment_token_repository,
|
||||
string $description,
|
||||
SubscriptionHelper $subscription_helper
|
||||
): string {
|
||||
if ( $settings->has( 'vault_enabled' )
|
||||
&& $settings->get( 'vault_enabled' )
|
||||
&& PayPalGateway::ID === $id
|
||||
&& $subscription_helper->is_subscription_change_payment()
|
||||
) {
|
||||
$tokens = $payment_token_repository->all_for_user_id( get_current_user_id() );
|
||||
if ( ! $tokens || ! $payment_token_repository->tokens_contains_paypal( $tokens ) ) {
|
||||
return esc_html__(
|
||||
'No PayPal payments saved, in order to use a saved payment you first need to create it through a purchase.',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
}
|
||||
|
||||
$output = sprintf(
|
||||
'<p class="form-row form-row-wide"><label>%1$s</label><select id="saved-paypal-payment" name="saved_paypal_payment">',
|
||||
esc_html__( 'Select a saved PayPal payment', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $token->source()->paypal ) ) {
|
||||
$output .= sprintf(
|
||||
'<option value="%1$s">%2$s</option>',
|
||||
$token->id(),
|
||||
$token->source()->paypal->payer->email_address
|
||||
);
|
||||
}
|
||||
}
|
||||
$output .= '</select></p>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
return $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays saved credit cards.
|
||||
*
|
||||
* @param Settings $settings The settings.
|
||||
* @param string $id The payment gateway Id.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
||||
* @param array $default_fields Default payment gateway fields.
|
||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||
* @return array|mixed|string
|
||||
* @throws NotFoundException When setting was not found.
|
||||
*/
|
||||
protected function display_saved_credit_cards(
|
||||
Settings $settings,
|
||||
string $id,
|
||||
PaymentTokenRepository $payment_token_repository,
|
||||
array $default_fields,
|
||||
SubscriptionHelper $subscription_helper
|
||||
) {
|
||||
|
||||
if ( $settings->has( 'vault_enabled_dcc' )
|
||||
&& $settings->get( 'vault_enabled_dcc' )
|
||||
&& $subscription_helper->is_subscription_change_payment()
|
||||
&& CreditCardGateway::ID === $id
|
||||
) {
|
||||
$tokens = $payment_token_repository->all_for_user_id( get_current_user_id() );
|
||||
if ( ! $tokens || ! $payment_token_repository->tokens_contains_card( $tokens ) ) {
|
||||
$default_fields = array();
|
||||
$default_fields['saved-credit-card'] = esc_html__(
|
||||
'No Credit Card saved, in order to use a saved Credit Card you first need to create it through a purchase.',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
return $default_fields;
|
||||
}
|
||||
|
||||
$output = sprintf(
|
||||
'<p class="form-row form-row-wide"><label>%1$s</label><select id="saved-credit-card" name="saved_credit_card">',
|
||||
esc_html__( 'Select a saved Credit Card payment', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $token->source()->card ) ) {
|
||||
$output .= sprintf(
|
||||
'<option value="%1$s">%2$s ...%3$s</option>',
|
||||
$token->id(),
|
||||
$token->source()->card->brand,
|
||||
$token->source()->card->last_digits
|
||||
);
|
||||
}
|
||||
}
|
||||
$output .= '</select></p>';
|
||||
|
||||
$default_fields = array();
|
||||
$default_fields['saved-credit-card'] = $output;
|
||||
return $default_fields;
|
||||
}
|
||||
|
||||
return $default_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds PayPal subscriptions API integration.
|
||||
*
|
||||
* @param ContainerInterface $c The container.
|
||||
* @return void
|
||||
* @throws Exception When something went wrong.
|
||||
*/
|
||||
protected function subscriptions_api_integration( ContainerInterface $c ): void {
|
||||
add_action(
|
||||
'save_post',
|
||||
/**
|
||||
|
@ -554,7 +80,7 @@ class SubscriptionModule implements ModuleInterface {
|
|||
return;
|
||||
}
|
||||
|
||||
$subscriptions_api_handler = $c->get( 'subscription.api-handler' );
|
||||
$subscriptions_api_handler = $c->get( 'paypal-subscriptions.api-handler' );
|
||||
assert( $subscriptions_api_handler instanceof SubscriptionsApiHandler );
|
||||
$this->update_subscription_product_meta( $product, $subscriptions_api_handler );
|
||||
},
|
||||
|
@ -571,7 +97,7 @@ class SubscriptionModule implements ModuleInterface {
|
|||
function( $variation_id ) use ( $c ) {
|
||||
$wcsnonce_save_variations = wc_clean( wp_unslash( $_POST['_wcsnonce_save_variations'] ?? '' ) );
|
||||
|
||||
$subscriptions_helper = $c->get( 'subscription.helper' );
|
||||
$subscriptions_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
assert( $subscriptions_helper instanceof SubscriptionHelper );
|
||||
|
||||
if (
|
||||
|
@ -588,7 +114,7 @@ class SubscriptionModule implements ModuleInterface {
|
|||
return;
|
||||
}
|
||||
|
||||
$subscriptions_api_handler = $c->get( 'subscription.api-handler' );
|
||||
$subscriptions_api_handler = $c->get( 'paypal-subscriptions.api-handler' );
|
||||
assert( $subscriptions_api_handler instanceof SubscriptionsApiHandler );
|
||||
$this->update_subscription_product_meta( $product, $subscriptions_api_handler );
|
||||
},
|
||||
|
@ -947,6 +473,236 @@ class SubscriptionModule implements ModuleInterface {
|
|||
10,
|
||||
3
|
||||
);
|
||||
|
||||
add_action(
|
||||
'admin_enqueue_scripts',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( $hook ) use ( $c ) {
|
||||
if ( ! is_string( $hook ) ) {
|
||||
return;
|
||||
}
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
$subscription_mode = $settings->has( 'subscriptions_mode' ) ? $settings->get( 'subscriptions_mode' ) : '';
|
||||
if ( $hook !== 'post.php' || $subscription_mode !== 'subscriptions_api' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
//phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
$post_id = wc_clean( wp_unslash( $_GET['post'] ?? '' ) );
|
||||
$product = wc_get_product( $post_id );
|
||||
if ( ! ( is_a( $product, WC_Product::class ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscriptions_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
assert( $subscriptions_helper instanceof SubscriptionHelper );
|
||||
|
||||
if (
|
||||
! $subscriptions_helper->plugin_is_active()
|
||||
|| ! (
|
||||
is_a( $product, WC_Product_Subscription::class )
|
||||
|| is_a( $product, WC_Product_Variable_Subscription::class )
|
||||
|| is_a( $product, WC_Product_Subscription_Variation::class )
|
||||
)
|
||||
|| ! WC_Subscriptions_Product::is_subscription( $product )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$module_url = $c->get( 'paypal-subscriptions.module.url' );
|
||||
wp_enqueue_script(
|
||||
'ppcp-paypal-subscription',
|
||||
untrailingslashit( $module_url ) . '/assets/js/paypal-subscription.js',
|
||||
array( 'jquery' ),
|
||||
$c->get( 'ppcp.asset-version' ),
|
||||
true
|
||||
);
|
||||
|
||||
$products = array( $this->set_product_config( $product ) );
|
||||
if ( $product->get_type() === 'variable-subscription' ) {
|
||||
$products = array();
|
||||
|
||||
/**
|
||||
* Suppress pslam.
|
||||
*
|
||||
* @psalm-suppress TypeDoesNotContainType
|
||||
*
|
||||
* WC_Product_Variable_Subscription extends WC_Product_Variable.
|
||||
*/
|
||||
assert( $product instanceof WC_Product_Variable );
|
||||
$available_variations = $product->get_available_variations();
|
||||
foreach ( $available_variations as $variation ) {
|
||||
/**
|
||||
* The method is defined in WooCommerce.
|
||||
*
|
||||
* @psalm-suppress UndefinedMethod
|
||||
*/
|
||||
$variation = wc_get_product_object( 'variation', $variation['variation_id'] );
|
||||
$products[] = $this->set_product_config( $variation );
|
||||
}
|
||||
}
|
||||
|
||||
wp_localize_script(
|
||||
'ppcp-paypal-subscription',
|
||||
'PayPalCommerceGatewayPayPalSubscriptionProducts',
|
||||
$products
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
$endpoint = $c->get( 'paypal-subscriptions.deactivate-plan-endpoint' );
|
||||
assert( $endpoint instanceof DeactivatePlanEndpoint );
|
||||
add_action(
|
||||
'wc_ajax_' . DeactivatePlanEndpoint::ENDPOINT,
|
||||
array( $endpoint, 'handle_request' )
|
||||
);
|
||||
|
||||
add_action(
|
||||
'add_meta_boxes',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( string $post_type, $post_or_order_object ) use ( $c ) {
|
||||
if ( ! function_exists( 'wcs_get_subscription' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$order = ( $post_or_order_object instanceof WP_Post )
|
||||
? wc_get_order( $post_or_order_object->ID )
|
||||
: $post_or_order_object;
|
||||
|
||||
if ( ! is_a( $order, WC_Order::class ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscription = wcs_get_subscription( $order->get_id() );
|
||||
if ( ! is_a( $subscription, WC_Subscription::class ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
|
||||
if ( ! $subscription_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$screen_id = wc_get_page_screen_id( 'shop_subscription' );
|
||||
remove_meta_box( 'woocommerce-subscription-schedule', $screen_id, 'side' );
|
||||
|
||||
$host = $c->get( 'api.paypal-website-url' );
|
||||
|
||||
add_meta_box(
|
||||
'ppcp_paypal_subscription',
|
||||
__( 'PayPal Subscription', 'woocommerce-paypal-payments' ),
|
||||
function() use ( $subscription_id, $host ) {
|
||||
$url = trailingslashit( $host ) . 'billing/subscriptions/' . $subscription_id;
|
||||
echo '<p>' . esc_html__( 'This subscription is linked to a PayPal Subscription, Cancel it to unlink.', 'woocommerce-paypal-payments' ) . '</p>';
|
||||
echo '<p><strong>' . esc_html__( 'Subscription:', 'woocommerce-paypal-payments' ) . '</strong> <a href="' . esc_url( $url ) . '" target="_blank">' . esc_attr( $subscription_id ) . '</a></p>';
|
||||
},
|
||||
$post_type,
|
||||
'side'
|
||||
);
|
||||
|
||||
},
|
||||
30,
|
||||
2
|
||||
);
|
||||
|
||||
add_action(
|
||||
'action_scheduler_before_execute',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( $action_id ) {
|
||||
/**
|
||||
* Class exist in WooCommerce.
|
||||
*
|
||||
* @psalm-suppress UndefinedClass
|
||||
*/
|
||||
$store = ActionScheduler_Store::instance();
|
||||
$action = $store->fetch_action( $action_id );
|
||||
|
||||
$subscription_id = $action->get_args()['subscription_id'] ?? null;
|
||||
if ( $subscription_id ) {
|
||||
$subscription = wcs_get_subscription( $subscription_id );
|
||||
if ( is_a( $subscription, WC_Subscription::class ) ) {
|
||||
$paypal_subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
|
||||
if ( $paypal_subscription_id ) {
|
||||
as_unschedule_action( $action->get_hook(), $action->get_args() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates subscription product meta.
|
||||
*
|
||||
* @param WC_Product $product The product.
|
||||
* @param SubscriptionsApiHandler $subscriptions_api_handler The subscription api handler.
|
||||
* @return void
|
||||
*/
|
||||
private function update_subscription_product_meta( WC_Product $product, SubscriptionsApiHandler $subscriptions_api_handler ): void {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification
|
||||
$enable_subscription_product = wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) );
|
||||
$product->update_meta_data( '_ppcp_enable_subscription_product', $enable_subscription_product );
|
||||
$product->save();
|
||||
|
||||
if ( ( $product->get_type() === 'subscription' || $product->get_type() === 'subscription_variation' ) && $enable_subscription_product === 'yes' ) {
|
||||
if ( $product->meta_exists( 'ppcp_subscription_product' ) && $product->meta_exists( 'ppcp_subscription_plan' ) ) {
|
||||
$subscriptions_api_handler->update_product( $product );
|
||||
$subscriptions_api_handler->update_plan( $product );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $product->meta_exists( 'ppcp_subscription_product' ) ) {
|
||||
$subscriptions_api_handler->create_product( $product );
|
||||
}
|
||||
|
||||
if ( $product->meta_exists( 'ppcp_subscription_product' ) && ! $product->meta_exists( 'ppcp_subscription_plan' ) ) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification
|
||||
$subscription_plan_name = wc_clean( wp_unslash( $_POST['_ppcp_subscription_plan_name'] ?? '' ) );
|
||||
if ( ! is_string( $subscription_plan_name ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product->update_meta_data( '_ppcp_subscription_plan_name', $subscription_plan_name );
|
||||
$product->save();
|
||||
|
||||
$subscriptions_api_handler->create_plan( $subscription_plan_name, $product );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns subscription product configuration.
|
||||
*
|
||||
* @param WC_Product $product The product.
|
||||
* @return array
|
||||
*/
|
||||
private function set_product_config( WC_Product $product ): array {
|
||||
$plan = $product->get_meta( 'ppcp_subscription_plan' ) ?? array();
|
||||
$plan_id = $plan['id'] ?? '';
|
||||
|
||||
return array(
|
||||
'product_connected' => $product->get_meta( '_ppcp_enable_subscription_product' ) ?? '',
|
||||
'plan_id' => $plan_id,
|
||||
'product_id' => $product->get_id(),
|
||||
'ajax' => array(
|
||||
'deactivate_plan' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( DeactivatePlanEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( DeactivatePlanEndpoint::ENDPOINT ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1019,66 +775,4 @@ class SubscriptionModule implements ModuleInterface {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates subscription product meta.
|
||||
*
|
||||
* @param WC_Product $product The product.
|
||||
* @param SubscriptionsApiHandler $subscriptions_api_handler The subscription api handler.
|
||||
* @return void
|
||||
*/
|
||||
private function update_subscription_product_meta( WC_Product $product, SubscriptionsApiHandler $subscriptions_api_handler ): void {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification
|
||||
$enable_subscription_product = wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) );
|
||||
$product->update_meta_data( '_ppcp_enable_subscription_product', $enable_subscription_product );
|
||||
$product->save();
|
||||
|
||||
if ( ( $product->get_type() === 'subscription' || $product->get_type() === 'subscription_variation' ) && $enable_subscription_product === 'yes' ) {
|
||||
if ( $product->meta_exists( 'ppcp_subscription_product' ) && $product->meta_exists( 'ppcp_subscription_plan' ) ) {
|
||||
$subscriptions_api_handler->update_product( $product );
|
||||
$subscriptions_api_handler->update_plan( $product );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $product->meta_exists( 'ppcp_subscription_product' ) ) {
|
||||
$subscriptions_api_handler->create_product( $product );
|
||||
}
|
||||
|
||||
if ( $product->meta_exists( 'ppcp_subscription_product' ) && ! $product->meta_exists( 'ppcp_subscription_plan' ) ) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification
|
||||
$subscription_plan_name = wc_clean( wp_unslash( $_POST['_ppcp_subscription_plan_name'] ?? '' ) );
|
||||
if ( ! is_string( $subscription_plan_name ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product->update_meta_data( '_ppcp_subscription_plan_name', $subscription_plan_name );
|
||||
$product->save();
|
||||
|
||||
$subscriptions_api_handler->create_plan( $subscription_plan_name, $product );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns subscription product configuration.
|
||||
*
|
||||
* @param WC_Product $product The product.
|
||||
* @return array
|
||||
*/
|
||||
private function set_product_config( WC_Product $product ): array {
|
||||
$plan = $product->get_meta( 'ppcp_subscription_plan' ) ?? array();
|
||||
$plan_id = $plan['id'] ?? '';
|
||||
|
||||
return array(
|
||||
'product_connected' => $product->get_meta( '_ppcp_enable_subscription_product' ) ?? '',
|
||||
'plan_id' => $plan_id,
|
||||
'product_id' => $product->get_id(),
|
||||
'ajax' => array(
|
||||
'deactivate_plan' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( DeactivatePlanEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( DeactivatePlanEndpoint::ENDPOINT ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,12 +2,12 @@
|
|||
/**
|
||||
* The subscription module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Subscription
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription;
|
||||
namespace WooCommerce\PayPalCommerce\PayPalSubscriptions;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Product;
|
14
modules/ppcp-save-payment-methods/.babelrc
Normal file
14
modules/ppcp-save-payment-methods/.babelrc
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": "usage",
|
||||
"corejs": "3.25.0"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@babel/preset-react"
|
||||
]
|
||||
]
|
||||
}
|
3
modules/ppcp-save-payment-methods/.gitignore
vendored
Normal file
3
modules/ppcp-save-payment-methods/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
node_modules
|
||||
assets/js
|
||||
assets/css
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "woocommerce/ppcp-subscription",
|
||||
"name": "woocommerce/ppcp-save-payment-methods",
|
||||
"type": "dhii-mod",
|
||||
"description": "Subscription module for PPCP",
|
||||
"description": "Save payment methods module for PPCP",
|
||||
"license": "GPL-2.0",
|
||||
"require": {
|
||||
"php": "^7.2 | ^8.0",
|
||||
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WooCommerce\\PayPalCommerce\\Subscription\\": "src"
|
||||
"WooCommerce\\PayPalCommerce\\SavePaymentMethods\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
14
modules/ppcp-save-payment-methods/extensions.php
Normal file
14
modules/ppcp-save-payment-methods/extensions.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* The save payment methods module extensions.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\SavePaymentMethods
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array();
|
16
modules/ppcp-save-payment-methods/module.php
Normal file
16
modules/ppcp-save-payment-methods/module.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* The save payment methods module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\SavePaymentMethods
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
|
||||
return static function (): ModuleInterface {
|
||||
return new SavePaymentMethodsModule();
|
||||
};
|
33
modules/ppcp-save-payment-methods/package.json
Normal file
33
modules/ppcp-save-payment-methods/package.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "ppcp-save-payment-methods",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"browserslist": [
|
||||
"> 0.5%",
|
||||
"Safari >= 8",
|
||||
"Chrome >= 41",
|
||||
"Firefox >= 43",
|
||||
"Edge >= 14"
|
||||
],
|
||||
"dependencies": {
|
||||
"core-js": "^3.25.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19",
|
||||
"@babel/preset-env": "^7.19",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@woocommerce/dependency-extraction-webpack-plugin": "^2.2.0",
|
||||
"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.76",
|
||||
"webpack-cli": "^4.10"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
import {
|
||||
getCurrentPaymentMethod,
|
||||
ORDER_BUTTON_SELECTOR,
|
||||
PaymentMethods
|
||||
} from "../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState";
|
||||
|
||||
import {
|
||||
setVisible,
|
||||
setVisibleByClass
|
||||
} from "../../../ppcp-button/resources/js/modules/Helper/Hiding";
|
||||
import {loadPaypalJsScript} from "../../../ppcp-button/resources/js/modules/Helper/ScriptLoading";
|
||||
|
||||
loadPaypalJsScript(
|
||||
{
|
||||
clientId: ppcp_add_payment_method.client_id,
|
||||
merchantId: ppcp_add_payment_method.merchant_id,
|
||||
dataUserIdToken: ppcp_add_payment_method.id_token,
|
||||
},
|
||||
{
|
||||
createVaultSetupToken: async () => {
|
||||
const response = await fetch(ppcp_add_payment_method.ajax.create_setup_token.endpoint, {
|
||||
method: "POST",
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nonce: ppcp_add_payment_method.ajax.create_setup_token.nonce,
|
||||
})
|
||||
})
|
||||
|
||||
const result = await response.json()
|
||||
|
||||
if(result.data.id) {
|
||||
return result.data.id
|
||||
}
|
||||
},
|
||||
onApprove: async ({ vaultSetupToken }) => {
|
||||
const response = await fetch(ppcp_add_payment_method.ajax.create_payment_token.endpoint, {
|
||||
method: "POST",
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nonce: ppcp_add_payment_method.ajax.create_payment_token.nonce,
|
||||
vault_setup_token: vaultSetupToken,
|
||||
})
|
||||
})
|
||||
|
||||
const result = await response.json()
|
||||
console.log(result)
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(error)
|
||||
}
|
||||
},
|
||||
`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`
|
||||
);
|
||||
|
||||
const init = () => {
|
||||
setVisibleByClass(ORDER_BUTTON_SELECTOR, getCurrentPaymentMethod() !== PaymentMethods.PAYPAL, 'ppcp-hidden');
|
||||
setVisible(`#ppc-button-${PaymentMethods.PAYPAL}-save-payment-method`, getCurrentPaymentMethod() === PaymentMethods.PAYPAL);
|
||||
}
|
||||
|
||||
document.addEventListener(
|
||||
'DOMContentLoaded',
|
||||
() => {
|
||||
jQuery(document.body).on('click init_add_payment_method', '.payment_methods input.input-radio', function () {
|
||||
init()
|
||||
});
|
||||
}
|
||||
);
|
||||
|
90
modules/ppcp-save-payment-methods/services.php
Normal file
90
modules/ppcp-save-payment-methods/services.php
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
/**
|
||||
* The save payment methods module services.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\SavePaymentMethods
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
||||
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CaptureCardPayment;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Helper\SavePaymentMethodsApplies;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
'save-payment-methods.eligible' => static function ( ContainerInterface $container ): bool {
|
||||
$save_payment_methods_applies = $container->get( 'save-payment-methods.helpers.save-payment-methods-applies' );
|
||||
assert( $save_payment_methods_applies instanceof SavePaymentMethodsApplies );
|
||||
|
||||
return $save_payment_methods_applies->for_country_currency();
|
||||
},
|
||||
'save-payment-methods.helpers.save-payment-methods-applies' => static function ( ContainerInterface $container ) : SavePaymentMethodsApplies {
|
||||
return new SavePaymentMethodsApplies(
|
||||
$container->get( 'save-payment-methods.supported-country-currency-matrix' ),
|
||||
$container->get( 'api.shop.currency' ),
|
||||
$container->get( 'api.shop.country' )
|
||||
);
|
||||
},
|
||||
'save-payment-methods.supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array {
|
||||
return apply_filters(
|
||||
'woocommerce_paypal_payments_save_payment_methods_supported_country_currency_matrix',
|
||||
array(
|
||||
'US' => array(
|
||||
'AUD',
|
||||
'CAD',
|
||||
'EUR',
|
||||
'GBP',
|
||||
'JPY',
|
||||
'USD',
|
||||
),
|
||||
)
|
||||
);
|
||||
},
|
||||
'save-payment-methods.module.url' => static function ( ContainerInterface $container ): string {
|
||||
/**
|
||||
* The path cannot be false.
|
||||
*
|
||||
* @psalm-suppress PossiblyFalseArgument
|
||||
*/
|
||||
return plugins_url(
|
||||
'/modules/ppcp-save-payment-methods/',
|
||||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
'save-payment-methods.endpoint.create-setup-token' => static function ( ContainerInterface $container ): CreateSetupToken {
|
||||
return new CreateSetupToken(
|
||||
$container->get( 'button.request-data' ),
|
||||
$container->get( 'api.endpoint.payment-method-tokens' )
|
||||
);
|
||||
},
|
||||
'save-payment-methods.wc-payment-tokens' => static function( ContainerInterface $container ): WooCommercePaymentTokens {
|
||||
return new WooCommercePaymentTokens(
|
||||
$container->get( 'vaulting.payment-token-helper' ),
|
||||
$container->get( 'vaulting.payment-token-factory' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'save-payment-methods.endpoint.create-payment-token' => static function ( ContainerInterface $container ): CreatePaymentToken {
|
||||
return new CreatePaymentToken(
|
||||
$container->get( 'button.request-data' ),
|
||||
$container->get( 'api.endpoint.payment-method-tokens' ),
|
||||
$container->get( 'save-payment-methods.wc-payment-tokens' )
|
||||
);
|
||||
},
|
||||
'save-payment-methods.endpoint.capture-card-payment' => static function( ContainerInterface $container ): CaptureCardPayment {
|
||||
return new CaptureCardPayment(
|
||||
$container->get( 'button.request-data' ),
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'api.factory.order' ),
|
||||
$container->get( 'api.factory.purchase-unit' ),
|
||||
$container->get( 'api.endpoint.order' ),
|
||||
$container->get( 'session.handler' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
);
|
|
@ -0,0 +1,219 @@
|
|||
<?php
|
||||
/**
|
||||
* The Capture Card Payment endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use stdClass;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Class CaptureCardPayment
|
||||
*/
|
||||
class CaptureCardPayment implements EndpointInterface {
|
||||
|
||||
use RequestTrait;
|
||||
|
||||
const ENDPOINT = 'ppc-capture-card-payment';
|
||||
|
||||
/**
|
||||
* The request data.
|
||||
*
|
||||
* @var RequestData
|
||||
*/
|
||||
private $request_data;
|
||||
|
||||
/**
|
||||
* The host.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* The bearer.
|
||||
*
|
||||
* @var Bearer
|
||||
*/
|
||||
private $bearer;
|
||||
|
||||
/**
|
||||
* The order factory.
|
||||
*
|
||||
* @var OrderFactory
|
||||
*/
|
||||
private $order_factory;
|
||||
|
||||
/**
|
||||
* The purchase unit factory.
|
||||
*
|
||||
* @var PurchaseUnitFactory
|
||||
*/
|
||||
private $purchase_unit_factory;
|
||||
|
||||
/**
|
||||
* The order endpoint.
|
||||
*
|
||||
* @var OrderEndpoint
|
||||
*/
|
||||
private $order_endpoint;
|
||||
|
||||
/**
|
||||
* The session handler.
|
||||
*
|
||||
* @var SessionHandler
|
||||
*/
|
||||
private $session_handler;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* CaptureCardPayment constructor.
|
||||
*
|
||||
* @param RequestData $request_data The request data.
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param OrderFactory $order_factory The order factory.
|
||||
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param SessionHandler $session_handler The session handler.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
RequestData $request_data,
|
||||
string $host,
|
||||
Bearer $bearer,
|
||||
OrderFactory $order_factory,
|
||||
PurchaseUnitFactory $purchase_unit_factory,
|
||||
OrderEndpoint $order_endpoint,
|
||||
SessionHandler $session_handler,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->request_data = $request_data;
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->order_factory = $order_factory;
|
||||
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->logger = $logger;
|
||||
$this->session_handler = $session_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nonce.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function nonce(): string {
|
||||
return self::ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function handle_request(): bool {
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
|
||||
$tokens = WC_Payment_Tokens::get_customer_tokens( get_current_user_id() );
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( $token->get_id() === (int) $data['payment_token'] ) {
|
||||
try {
|
||||
$order = $this->create_order( $token->get_token() );
|
||||
|
||||
$id = $order->id ?? '';
|
||||
$status = $order->status ?? '';
|
||||
$payment_source = isset( $order->payment_source->card ) ? 'card' : '';
|
||||
if ( $id && $status && $payment_source ) {
|
||||
WC()->session->set(
|
||||
'ppcp_saved_payment_card',
|
||||
array(
|
||||
'order_id' => $id,
|
||||
'status' => $status,
|
||||
'payment_source' => $payment_source,
|
||||
)
|
||||
);
|
||||
|
||||
wp_send_json_success();
|
||||
return true;
|
||||
}
|
||||
} catch ( RuntimeException $exception ) {
|
||||
wp_send_json_error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates PayPal order from the given card vault id.
|
||||
*
|
||||
* @param string $vault_id Vault id.
|
||||
* @return stdClass
|
||||
* @throws RuntimeException When request fails.
|
||||
*/
|
||||
private function create_order( string $vault_id ): stdClass {
|
||||
$items = array( $this->purchase_unit_factory->from_wc_cart() );
|
||||
|
||||
$data = array(
|
||||
'intent' => 'CAPTURE',
|
||||
'purchase_units' => array_map(
|
||||
static function ( PurchaseUnit $item ): array {
|
||||
return $item->to_array( true, false );
|
||||
},
|
||||
$items
|
||||
),
|
||||
'payment_source' => array(
|
||||
'card' => array(
|
||||
'vault_id' => $vault_id,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$bearer = $this->bearer->bearer();
|
||||
$url = trailingslashit( $this->host ) . 'v2/checkout/orders';
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||
'Content-Type' => 'application/json',
|
||||
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
|
||||
),
|
||||
'body' => wp_json_encode( $data ),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
if ( $response instanceof WP_Error ) {
|
||||
throw new RuntimeException( $response->get_error_message() );
|
||||
}
|
||||
|
||||
return json_decode( $response['body'] );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
/**
|
||||
* The Create Payment Token endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint;
|
||||
|
||||
use Exception;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\WooCommercePaymentTokens;
|
||||
|
||||
/**
|
||||
* Class CreatePaymentToken
|
||||
*/
|
||||
class CreatePaymentToken implements EndpointInterface {
|
||||
|
||||
const ENDPOINT = 'ppc-create-payment-token';
|
||||
|
||||
/**
|
||||
* The request data.
|
||||
*
|
||||
* @var RequestData
|
||||
*/
|
||||
private $request_data;
|
||||
|
||||
/**
|
||||
* The payment method tokens endpoint.
|
||||
*
|
||||
* @var PaymentMethodTokensEndpoint
|
||||
*/
|
||||
private $payment_method_tokens_endpoint;
|
||||
|
||||
/**
|
||||
* The WC payment tokens.
|
||||
*
|
||||
* @var WooCommercePaymentTokens
|
||||
*/
|
||||
private $wc_payment_tokens;
|
||||
|
||||
/**
|
||||
* CreatePaymentToken constructor.
|
||||
*
|
||||
* @param RequestData $request_data The request data.
|
||||
* @param PaymentMethodTokensEndpoint $payment_method_tokens_endpoint The payment method tokens endpoint.
|
||||
* @param WooCommercePaymentTokens $wc_payment_tokens The WC payment tokens.
|
||||
*/
|
||||
public function __construct(
|
||||
RequestData $request_data,
|
||||
PaymentMethodTokensEndpoint $payment_method_tokens_endpoint,
|
||||
WooCommercePaymentTokens $wc_payment_tokens
|
||||
) {
|
||||
$this->request_data = $request_data;
|
||||
$this->payment_method_tokens_endpoint = $payment_method_tokens_endpoint;
|
||||
$this->wc_payment_tokens = $wc_payment_tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nonce.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function nonce(): string {
|
||||
return self::ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the request.
|
||||
*
|
||||
* @return bool
|
||||
* @throws Exception On Error.
|
||||
*/
|
||||
public function handle_request(): bool {
|
||||
try {
|
||||
$data = $this->request_data->read_request( $this->nonce() );
|
||||
|
||||
/**
|
||||
* Suppress ArgumentTypeCoercion
|
||||
*
|
||||
* @psalm-suppress ArgumentTypeCoercion
|
||||
*/
|
||||
$payment_source = new PaymentSource(
|
||||
'token',
|
||||
(object) array(
|
||||
'id' => $data['vault_setup_token'],
|
||||
'type' => 'SETUP_TOKEN',
|
||||
)
|
||||
);
|
||||
|
||||
$result = $this->payment_method_tokens_endpoint->payment_tokens( $payment_source );
|
||||
|
||||
if ( is_user_logged_in() && isset( $result->customer->id ) ) {
|
||||
update_user_meta( get_current_user_id(), '_ppcp_target_customer_id', $result->customer->id );
|
||||
|
||||
$email = '';
|
||||
if ( isset( $result->payment_source->paypal->email_address ) ) {
|
||||
$email = $result->payment_source->paypal->email_address;
|
||||
}
|
||||
|
||||
$this->wc_payment_tokens->create_payment_token_paypal(
|
||||
get_current_user_id(),
|
||||
$result->id,
|
||||
$email
|
||||
);
|
||||
}
|
||||
|
||||
wp_send_json_success( $result );
|
||||
return true;
|
||||
} catch ( Exception $exception ) {
|
||||
wp_send_json_error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
/**
|
||||
* The Create Setup Token endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint;
|
||||
|
||||
use Exception;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
|
||||
/**
|
||||
* Class CreateSetupToken
|
||||
*/
|
||||
class CreateSetupToken implements EndpointInterface {
|
||||
|
||||
const ENDPOINT = 'ppc-create-setup-token';
|
||||
|
||||
/**
|
||||
* The request data helper.
|
||||
*
|
||||
* @var RequestData
|
||||
*/
|
||||
private $request_data;
|
||||
|
||||
/**
|
||||
* Payment Method Tokens endpoint.
|
||||
*
|
||||
* @var PaymentMethodTokensEndpoint
|
||||
*/
|
||||
private $payment_method_tokens_endpoint;
|
||||
|
||||
/**
|
||||
* CreateSetupToken constructor.
|
||||
*
|
||||
* @param RequestData $request_data The request data helper.
|
||||
* @param PaymentMethodTokensEndpoint $payment_method_tokens_endpoint Payment Method Tokens endpoint.
|
||||
*/
|
||||
public function __construct(
|
||||
RequestData $request_data,
|
||||
PaymentMethodTokensEndpoint $payment_method_tokens_endpoint
|
||||
) {
|
||||
$this->request_data = $request_data;
|
||||
$this->payment_method_tokens_endpoint = $payment_method_tokens_endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nonce.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function nonce(): string {
|
||||
return self::ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the request.
|
||||
*
|
||||
* @return bool
|
||||
* @throws Exception On Error.
|
||||
*/
|
||||
public function handle_request(): bool {
|
||||
try {
|
||||
$this->request_data->read_request( $this->nonce() );
|
||||
|
||||
/**
|
||||
* Suppress ArgumentTypeCoercion
|
||||
*
|
||||
* @psalm-suppress ArgumentTypeCoercion
|
||||
*/
|
||||
$payment_source = new PaymentSource(
|
||||
'paypal',
|
||||
(object) array(
|
||||
'usage_type' => 'MERCHANT',
|
||||
'experience_context' => (object) array(
|
||||
'return_url' => esc_url( wc_get_account_endpoint_url( 'payment-methods' ) ),
|
||||
'cancel_url' => esc_url( wc_get_account_endpoint_url( 'add-payment-method' ) ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$result = $this->payment_method_tokens_endpoint->setup_tokens( $payment_source );
|
||||
|
||||
wp_send_json_success( $result );
|
||||
return true;
|
||||
} catch ( Exception $exception ) {
|
||||
wp_send_json_error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
/**
|
||||
* Properties of the Save Payment Methods module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\SavePaymentMethods\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods\Helper;
|
||||
|
||||
/**
|
||||
* Class SavePaymentMethodsApplies
|
||||
*/
|
||||
class SavePaymentMethodsApplies {
|
||||
|
||||
/**
|
||||
* The matrix which countries and currency combinations can be used for Save Payment Methods.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $allowed_country_currency_matrix;
|
||||
|
||||
/**
|
||||
* 3-letter currency code of the shop.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $currency;
|
||||
|
||||
/**
|
||||
* 2-letter country code of the shop.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $country;
|
||||
|
||||
/**
|
||||
* SavePaymentMethodsApplies constructor.
|
||||
*
|
||||
* @param array $allowed_country_currency_matrix The matrix which countries and currency combinations can be used for Save Payment Methods.
|
||||
* @param string $currency 3-letter currency code of the shop.
|
||||
* @param string $country 2-letter country code of the shop.
|
||||
*/
|
||||
public function __construct(
|
||||
array $allowed_country_currency_matrix,
|
||||
string $currency,
|
||||
string $country
|
||||
) {
|
||||
$this->allowed_country_currency_matrix = $allowed_country_currency_matrix;
|
||||
$this->currency = $currency;
|
||||
$this->country = $country;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether Save Payment Methods can be used in the current country and the current currency used.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function for_country_currency(): bool {
|
||||
if ( ! in_array( $this->country, array_keys( $this->allowed_country_currency_matrix ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
return in_array( $this->currency, $this->allowed_country_currency_matrix[ $this->country ], true );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,369 @@
|
|||
<?php
|
||||
/**
|
||||
* The save payment methods module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Applepay
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CaptureCardPayment;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
* Class SavePaymentMethodsModule
|
||||
*/
|
||||
class SavePaymentMethodsModule implements ModuleInterface {
|
||||
|
||||
use ContextTrait;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setup(): ServiceProviderInterface {
|
||||
return new ServiceProvider(
|
||||
require __DIR__ . '/../services.php',
|
||||
require __DIR__ . '/../extensions.php'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function run( ContainerInterface $c ): void {
|
||||
if ( ! $c->get( 'save-payment-methods.eligible' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter(
|
||||
'woocommerce_paypal_payments_localized_script_data',
|
||||
function( array $localized_script_data ) use ( $c ) {
|
||||
$api = $c->get( 'api.user-id-token' );
|
||||
assert( $api instanceof UserIdToken );
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
assert( $logger instanceof LoggerInterface );
|
||||
|
||||
$localized_script_data = $this->add_id_token_to_script_data( $api, $logger, $localized_script_data );
|
||||
|
||||
$localized_script_data['ajax']['capture_card_payment'] = array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( CaptureCardPayment::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( CaptureCardPayment::nonce() ),
|
||||
);
|
||||
|
||||
return $localized_script_data;
|
||||
}
|
||||
);
|
||||
|
||||
// Adds attributes needed to save payment method.
|
||||
add_filter(
|
||||
'ppcp_create_order_request_body_data',
|
||||
function( array $data, string $payment_method, array $request_data ): array {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$wc_order_action = wc_clean( wp_unslash( $_POST['wc_order_action'] ?? '' ) );
|
||||
if ( $wc_order_action === 'wcs_process_renewal' ) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$subscription_id = wc_clean( wp_unslash( $_POST['post_ID'] ?? '' ) );
|
||||
$subscription = wcs_get_subscription( (int) $subscription_id );
|
||||
if ( $subscription ) {
|
||||
$customer_id = $subscription->get_customer_id();
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID );
|
||||
foreach ( $wc_tokens as $token ) {
|
||||
$data['payment_source'] = array(
|
||||
'paypal' => array(
|
||||
'vault_id' => $token->get_token(),
|
||||
),
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $payment_method === CreditCardGateway::ID ) {
|
||||
$save_payment_method = $request_data['save_payment_method'] ?? false;
|
||||
if ( $save_payment_method ) {
|
||||
$data['payment_source'] = array(
|
||||
'card' => array(
|
||||
'attributes' => array(
|
||||
'vault' => array(
|
||||
'store_in_vault' => 'ON_SUCCESS',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
|
||||
if ( $target_customer_id ) {
|
||||
$data['payment_source']['card']['attributes']['customer'] = array(
|
||||
'id' => $target_customer_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $payment_method === PayPalGateway::ID ) {
|
||||
$data['payment_source'] = array(
|
||||
'paypal' => array(
|
||||
'attributes' => array(
|
||||
'vault' => array(
|
||||
'store_in_vault' => 'ON_SUCCESS',
|
||||
'usage_type' => 'MERCHANT',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
},
|
||||
10,
|
||||
3
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_after_order_processor',
|
||||
function( WC_Order $wc_order, Order $order ) use ( $c ) {
|
||||
$payment_source = $order->payment_source();
|
||||
assert( $payment_source instanceof PaymentSource );
|
||||
|
||||
$payment_vault_attributes = $payment_source->properties()->attributes->vault ?? null;
|
||||
if ( $payment_vault_attributes ) {
|
||||
$customer_id = $payment_vault_attributes->customer->id ?? '';
|
||||
$token_id = $payment_vault_attributes->id ?? '';
|
||||
if ( ! $customer_id || ! $token_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
update_user_meta( $wc_order->get_customer_id(), '_ppcp_target_customer_id', $customer_id );
|
||||
|
||||
$wc_payment_tokens = $c->get( 'save-payment-methods.wc-payment-tokens' );
|
||||
assert( $wc_payment_tokens instanceof WooCommercePaymentTokens );
|
||||
|
||||
if ( $wc_order->get_payment_method() === CreditCardGateway::ID ) {
|
||||
$token = new \WC_Payment_Token_CC();
|
||||
$token->set_token( $token_id );
|
||||
$token->set_user_id( $wc_order->get_customer_id() );
|
||||
$token->set_gateway_id( CreditCardGateway::ID );
|
||||
|
||||
$token->set_last4( $payment_source->properties()->last_digits ?? '' );
|
||||
$expiry = explode( '-', $payment_source->properties()->expiry ?? '' );
|
||||
$token->set_expiry_year( $expiry[0] ?? '' );
|
||||
$token->set_expiry_month( $expiry[1] ?? '' );
|
||||
$token->set_card_type( $payment_source->properties()->brand ?? '' );
|
||||
|
||||
$token->save();
|
||||
}
|
||||
|
||||
if ( $wc_order->get_payment_method() === PayPalGateway::ID ) {
|
||||
$wc_payment_tokens->create_payment_token_paypal(
|
||||
$wc_order->get_customer_id(),
|
||||
$token_id,
|
||||
$payment_source->properties()->email_address ?? ''
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
add_filter( 'woocommerce_paypal_payments_disable_add_payment_method', '__return_false' );
|
||||
add_filter( 'woocommerce_paypal_payments_subscription_renewal_return_before_create_order_without_token', '__return_false' );
|
||||
add_filter( 'woocommerce_paypal_payments_should_render_card_custom_fields', '__return_false' );
|
||||
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
function() use ( $c ) {
|
||||
if ( ! is_user_logged_in() || ! $this->is_add_payment_method_page() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$module_url = $c->get( 'save-payment-methods.module.url' );
|
||||
wp_enqueue_script(
|
||||
'ppcp-add-payment-method',
|
||||
untrailingslashit( $module_url ) . '/assets/js/add-payment-method.js',
|
||||
array( 'jquery' ),
|
||||
$c->get( 'ppcp.asset-version' ),
|
||||
true
|
||||
);
|
||||
|
||||
$api = $c->get( 'api.user-id-token' );
|
||||
assert( $api instanceof UserIdToken );
|
||||
|
||||
try {
|
||||
$target_customer_id = '';
|
||||
if ( is_user_logged_in() ) {
|
||||
$target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
|
||||
}
|
||||
|
||||
$id_token = $api->id_token( $target_customer_id );
|
||||
|
||||
wp_localize_script(
|
||||
'ppcp-add-payment-method',
|
||||
'ppcp_add_payment_method',
|
||||
array(
|
||||
'client_id' => $c->get( 'button.client_id' ),
|
||||
'merchant_id' => $c->get( 'api.merchant_id' ),
|
||||
'id_token' => $id_token,
|
||||
'ajax' => array(
|
||||
'create_setup_token' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( CreateSetupToken::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( CreateSetupToken::nonce() ),
|
||||
),
|
||||
'create_payment_token' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( CreatePaymentToken::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( CreatePaymentToken::nonce() ),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
assert( $logger instanceof LoggerInterface );
|
||||
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger->error( $error );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_add_payment_method_form_bottom',
|
||||
function () {
|
||||
if ( ! is_user_logged_in() || ! is_add_payment_method_page() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div id="ppc-button-' . esc_attr( PayPalGateway::ID ) . '-save-payment-method"></div>';
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . CreateSetupToken::ENDPOINT,
|
||||
static function () use ( $c ) {
|
||||
$endpoint = $c->get( 'save-payment-methods.endpoint.create-setup-token' );
|
||||
assert( $endpoint instanceof CreateSetupToken );
|
||||
|
||||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . CreatePaymentToken::ENDPOINT,
|
||||
static function () use ( $c ) {
|
||||
$endpoint = $c->get( 'save-payment-methods.endpoint.create-payment-token' );
|
||||
assert( $endpoint instanceof CreatePaymentToken );
|
||||
|
||||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_before_delete_payment_token',
|
||||
function( string $token_id ) use ( $c ) {
|
||||
try {
|
||||
$endpoint = $c->get( 'api.endpoint.payment-tokens' );
|
||||
assert( $endpoint instanceof PaymentTokensEndpoint );
|
||||
|
||||
$endpoint->delete( $token_id );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
assert( $logger instanceof LoggerInterface );
|
||||
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger->error( $error );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_paypal_payments_credit_card_gateway_vault_supports',
|
||||
function( array $supports ) use ( $c ): array {
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
assert( $settings instanceof ContainerInterface );
|
||||
|
||||
if ( $settings->has( 'vault_enabled_dcc' ) && $settings->get( 'vault_enabled_dcc' ) ) {
|
||||
$supports[] = 'tokenization';
|
||||
}
|
||||
|
||||
return $supports;
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . CaptureCardPayment::ENDPOINT,
|
||||
static function () use ( $c ) {
|
||||
$endpoint = $c->get( 'save-payment-methods.endpoint.capture-card-payment' );
|
||||
assert( $endpoint instanceof CaptureCardPayment );
|
||||
|
||||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds id token to localized script data.
|
||||
*
|
||||
* @param UserIdToken $api User id token api.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param array $localized_script_data The localized script data.
|
||||
* @return array
|
||||
*/
|
||||
private function add_id_token_to_script_data(
|
||||
UserIdToken $api,
|
||||
LoggerInterface $logger,
|
||||
array $localized_script_data
|
||||
): array {
|
||||
try {
|
||||
$target_customer_id = '';
|
||||
if ( is_user_logged_in() ) {
|
||||
$target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
|
||||
}
|
||||
|
||||
$id_token = $api->id_token( $target_customer_id );
|
||||
$localized_script_data['save_payment_methods'] = array(
|
||||
'id_token' => $id_token,
|
||||
);
|
||||
|
||||
$localized_script_data['data_client_id']['set_attribute'] = false;
|
||||
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger->error( $error );
|
||||
}
|
||||
|
||||
return $localized_script_data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* Service to create WC Payment Tokens.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Applepay
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\SavePaymentMethods;
|
||||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Payment_Tokens;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenFactory;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenPayPal;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
* Class WooCommercePaymentTokens
|
||||
*/
|
||||
class WooCommercePaymentTokens {
|
||||
|
||||
/**
|
||||
* The payment token helper.
|
||||
*
|
||||
* @var PaymentTokenHelper
|
||||
*/
|
||||
private $payment_token_helper;
|
||||
|
||||
/**
|
||||
* The payment token factory.
|
||||
*
|
||||
* @var PaymentTokenFactory
|
||||
*/
|
||||
private $payment_token_factory;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* WooCommercePaymentTokens constructor.
|
||||
*
|
||||
* @param PaymentTokenHelper $payment_token_helper The payment token helper.
|
||||
* @param PaymentTokenFactory $payment_token_factory The payment token factory.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
PaymentTokenHelper $payment_token_helper,
|
||||
PaymentTokenFactory $payment_token_factory,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->payment_token_helper = $payment_token_helper;
|
||||
$this->payment_token_factory = $payment_token_factory;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a WC Payment Token for PayPal payment.
|
||||
*
|
||||
* @param int $customer_id The WC customer ID.
|
||||
* @param string $token The PayPal payment token.
|
||||
* @param string $email The PayPal customer email.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function create_payment_token_paypal(
|
||||
int $customer_id,
|
||||
string $token,
|
||||
string $email
|
||||
): void {
|
||||
|
||||
$wc_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id, PayPalGateway::ID );
|
||||
if ( $this->payment_token_helper->token_exist( $wc_tokens, $token ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$payment_token_paypal = $this->payment_token_factory->create( 'paypal' );
|
||||
assert( $payment_token_paypal instanceof PaymentTokenPayPal );
|
||||
|
||||
$payment_token_paypal->set_token( $token );
|
||||
$payment_token_paypal->set_user_id( $customer_id );
|
||||
$payment_token_paypal->set_gateway_id( PayPalGateway::ID );
|
||||
|
||||
if ( $email && is_email( $email ) ) {
|
||||
$payment_token_paypal->set_email( $email );
|
||||
}
|
||||
|
||||
try {
|
||||
$payment_token_paypal->save();
|
||||
} catch ( Exception $exception ) {
|
||||
$this->logger->error(
|
||||
"Could not create WC payment token PayPal for customer {$customer_id}. " . $exception->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
38
modules/ppcp-save-payment-methods/webpack.config.js
Normal file
38
modules/ppcp-save-payment-methods/webpack.config.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
const path = require('path');
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
const DependencyExtractionWebpackPlugin = require( '@woocommerce/dependency-extraction-webpack-plugin' );
|
||||
|
||||
module.exports = {
|
||||
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
||||
mode: isProduction ? 'production' : 'development',
|
||||
target: 'web',
|
||||
plugins: [ new DependencyExtractionWebpackPlugin() ],
|
||||
entry: {
|
||||
'add-payment-method': path.resolve('./resources/js/add-payment-method.js')
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'assets/'),
|
||||
filename: 'js/[name].js',
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.js?$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: 'css/[name].css',
|
||||
}
|
||||
},
|
||||
{loader:'sass-loader'}
|
||||
]
|
||||
}]
|
||||
}
|
||||
};
|
2235
modules/ppcp-save-payment-methods/yarn.lock
Normal file
2235
modules/ppcp-save-payment-methods/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
|
@ -10,12 +10,12 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\SavedPaymentChecker;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array {
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
assert( $subscription_helper instanceof SubscriptionHelper );
|
||||
|
||||
$insert_after = function( array $array, string $key, array $new ): array {
|
||||
|
|
|
@ -16,7 +16,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokenEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\OrderRepository;
|
||||
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace WooCommerce\PayPalCommerce\SavedPaymentChecker;
|
|||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
|
@ -43,7 +43,7 @@ class SavedPaymentCheckerModule implements ModuleInterface {
|
|||
add_filter(
|
||||
'woocommerce_paypal_payments_order_intent',
|
||||
function( string $intent ) use ( $c ) {
|
||||
$subscription_helper = $c->get( 'subscription.helper' );
|
||||
$subscription_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
assert( $subscription_helper instanceof SubscriptionHelper );
|
||||
|
||||
if ( $subscription_helper->cart_contains_subscription() || $subscription_helper->current_product_is_subscription() ) {
|
||||
|
@ -60,7 +60,7 @@ class SavedPaymentCheckerModule implements ModuleInterface {
|
|||
add_action(
|
||||
'woocommerce_paypal_payments_before_handle_payment_success',
|
||||
function( WC_Order $wc_order ) use ( $c ) {
|
||||
$subscription_helper = $c->get( 'subscription.helper' );
|
||||
$subscription_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
assert( $subscription_helper instanceof SubscriptionHelper );
|
||||
|
||||
if ( $subscription_helper->has_subscription( $wc_order->get_id() ) ) {
|
||||
|
@ -93,7 +93,7 @@ class SavedPaymentCheckerModule implements ModuleInterface {
|
|||
add_action(
|
||||
'woocommerce_email_before_order_table',
|
||||
function( WC_Order $order ) use ( $c ) {
|
||||
$subscription_helper = $c->get( 'subscription.helper' );
|
||||
$subscription_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
assert( $subscription_helper instanceof SubscriptionHelper );
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
assert( $logger instanceof LoggerInterface );
|
||||
|
@ -119,7 +119,7 @@ class SavedPaymentCheckerModule implements ModuleInterface {
|
|||
add_action(
|
||||
'woocommerce_email_after_order_table',
|
||||
function( WC_Order $order ) use ( $c ) {
|
||||
$subscription_helper = $c->get( 'subscription.helper' );
|
||||
$subscription_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
assert( $subscription_helper instanceof SubscriptionHelper );
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
assert( $logger instanceof LoggerInterface );
|
||||
|
|
|
@ -9,7 +9,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\StatusReport;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
|
@ -65,7 +65,7 @@ class StatusReportModule implements ModuleInterface {
|
|||
$messages_apply = $c->get( 'button.helper.messages-apply' );
|
||||
|
||||
/* @var SubscriptionHelper $subscription_helper The subscription helper class. */
|
||||
$subscription_helper = $c->get( 'subscription.helper' );
|
||||
$subscription_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
|
||||
$last_webhook_storage = $c->get( 'webhook.last-webhook-storage' );
|
||||
assert( $last_webhook_storage instanceof WebhookEventStorage );
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* The services
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Subscription
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
|
||||
return array(
|
||||
'subscription.helper' => static function ( ContainerInterface $container ): SubscriptionHelper {
|
||||
return new SubscriptionHelper( $container->get( 'wcgateway.settings' ) );
|
||||
},
|
||||
'subscription.renewal-handler' => static function ( ContainerInterface $container ): RenewalHandler {
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
$repository = $container->get( 'vaulting.repository.payment-token' );
|
||||
$endpoint = $container->get( 'api.endpoint.order' );
|
||||
$purchase_unit_factory = $container->get( 'api.factory.purchase-unit' );
|
||||
$payer_factory = $container->get( 'api.factory.payer' );
|
||||
$environment = $container->get( 'onboarding.environment' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' );
|
||||
return new RenewalHandler(
|
||||
$logger,
|
||||
$repository,
|
||||
$endpoint,
|
||||
$purchase_unit_factory,
|
||||
$container->get( 'api.factory.shipping-preference' ),
|
||||
$payer_factory,
|
||||
$environment,
|
||||
$settings,
|
||||
$authorized_payments_processor
|
||||
);
|
||||
},
|
||||
'subscription.repository.payment-token' => static function ( ContainerInterface $container ): PaymentTokenRepository {
|
||||
$factory = $container->get( 'api.factory.payment-token' );
|
||||
$endpoint = $container->get( 'api.endpoint.payment-token' );
|
||||
return new PaymentTokenRepository( $factory, $endpoint );
|
||||
},
|
||||
'subscription.api-handler' => static function( ContainerInterface $container ): SubscriptionsApiHandler {
|
||||
return new SubscriptionsApiHandler(
|
||||
$container->get( 'api.endpoint.catalog-products' ),
|
||||
$container->get( 'api.factory.product' ),
|
||||
$container->get( 'api.endpoint.billing-plans' ),
|
||||
$container->get( 'api.factory.billing-cycle' ),
|
||||
$container->get( 'api.factory.payment-preferences' ),
|
||||
$container->get( 'api.shop.currency' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'subscription.module.url' => static function ( ContainerInterface $container ): string {
|
||||
/**
|
||||
* The path cannot be false.
|
||||
*
|
||||
* @psalm-suppress PossiblyFalseArgument
|
||||
*/
|
||||
return plugins_url(
|
||||
'/modules/ppcp-subscription/',
|
||||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
'subscription.deactivate-plan-endpoint' => static function ( ContainerInterface $container ): DeactivatePlanEndpoint {
|
||||
return new DeactivatePlanEndpoint(
|
||||
$container->get( 'button.request-data' ),
|
||||
$container->get( 'api.endpoint.billing-plans' )
|
||||
);
|
||||
},
|
||||
);
|
|
@ -31,7 +31,7 @@ return array(
|
|||
},
|
||||
'vaulting.credit-card-handler' => function( ContainerInterface $container ): VaultedCreditCardHandler {
|
||||
return new VaultedCreditCardHandler(
|
||||
$container->get( 'subscription.helper' ),
|
||||
$container->get( 'wc-subscriptions.helper' ),
|
||||
$container->get( 'vaulting.repository.payment-token' ),
|
||||
$container->get( 'api.factory.purchase-unit' ),
|
||||
$container->get( 'api.factory.payer' ),
|
||||
|
|
|
@ -13,7 +13,7 @@ use Exception;
|
|||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokenEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\AlreadyVaultedException;
|
||||
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
|
||||
/**
|
||||
* Class CustomerApprovalListener
|
||||
|
|
|
@ -19,8 +19,8 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait;
|
||||
|
|
|
@ -51,7 +51,7 @@ class VaultingModule implements ModuleInterface {
|
|||
|
||||
$listener->listen();
|
||||
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
add_action(
|
||||
'woocommerce_created_customer',
|
||||
function( int $customer_id ) use ( $subscription_helper ) {
|
||||
|
@ -137,6 +137,8 @@ class VaultingModule implements ModuleInterface {
|
|||
}
|
||||
|
||||
try {
|
||||
do_action( 'woocommerce_paypal_payments_before_delete_payment_token', $token->get_token() );
|
||||
|
||||
$payment_token_endpoint = $container->get( 'api.endpoint.payment-token' );
|
||||
$payment_token_endpoint->delete_token_by_id( $token->get_token() );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
|
@ -191,7 +193,10 @@ class VaultingModule implements ModuleInterface {
|
|||
'woocommerce_available_payment_gateways',
|
||||
function( array $methods ): array {
|
||||
global $wp;
|
||||
if ( isset( $wp->query_vars['add-payment-method'] ) ) {
|
||||
if (
|
||||
isset( $wp->query_vars['add-payment-method'] )
|
||||
&& apply_filters( 'woocommerce_paypal_payments_disable_add_payment_method', true )
|
||||
) {
|
||||
unset( $methods[ PayPalGateway::ID ] );
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,6 @@ return array(
|
|||
$source
|
||||
);
|
||||
},
|
||||
|
||||
'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array {
|
||||
$files = array(
|
||||
'paypal-smart-button-fields.php',
|
||||
|
|
|
@ -21,7 +21,7 @@ use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator;
|
|||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn;
|
||||
|
@ -76,7 +76,7 @@ return array(
|
|||
$refund_processor = $container->get( 'wcgateway.processor.refunds' );
|
||||
$state = $container->get( 'onboarding.state' );
|
||||
$transaction_url_provider = $container->get( 'wcgateway.transaction-url-provider' );
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
$page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' );
|
||||
$payment_token_repository = $container->get( 'vaulting.repository.payment-token' );
|
||||
$environment = $container->get( 'onboarding.environment' );
|
||||
|
@ -111,7 +111,7 @@ return array(
|
|||
$refund_processor = $container->get( 'wcgateway.processor.refunds' );
|
||||
$state = $container->get( 'onboarding.state' );
|
||||
$transaction_url_provider = $container->get( 'wcgateway.transaction-url-provider' );
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
$payments_endpoint = $container->get( 'api.endpoint.payments' );
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
$vaulted_credit_card_handler = $container->get( 'vaulting.credit-card-handler' );
|
||||
|
@ -139,7 +139,7 @@ return array(
|
|||
$container->get( 'wcgateway.processor.refunds' ),
|
||||
$container->get( 'onboarding.state' ),
|
||||
$container->get( 'wcgateway.transaction-url-provider' ),
|
||||
$container->get( 'subscription.helper' ),
|
||||
$container->get( 'wc-subscriptions.helper' ),
|
||||
$container->get( 'wcgateway.settings.allow_card_button_gateway.default' ),
|
||||
$container->get( 'onboarding.environment' ),
|
||||
$container->get( 'vaulting.repository.payment-token' ),
|
||||
|
@ -152,7 +152,7 @@ return array(
|
|||
$session_handler = $container->get( 'session.handler' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$settings_status = $container->get( 'wcgateway.settings.status' );
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
return new DisableGateways( $session_handler, $settings, $settings_status, $subscription_helper );
|
||||
},
|
||||
|
||||
|
@ -344,7 +344,7 @@ return array(
|
|||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$environment = $container->get( 'onboarding.environment' );
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
$order_helper = $container->get( 'api.order-helper' );
|
||||
return new OrderProcessor(
|
||||
$session_handler,
|
||||
|
@ -375,7 +375,7 @@ return array(
|
|||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
$notice = $container->get( 'wcgateway.notice.authorize-order-action' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
return new AuthorizedPaymentsProcessor(
|
||||
$order_endpoint,
|
||||
$payments_endpoint,
|
||||
|
@ -455,7 +455,7 @@ return array(
|
|||
$onboarding_options_renderer = $container->get( 'onboarding.render-options' );
|
||||
assert( $onboarding_options_renderer instanceof OnboardingOptionsRenderer );
|
||||
|
||||
$subscription_helper = $container->get( 'subscription.helper' );
|
||||
$subscription_helper = $container->get( 'wc-subscriptions.helper' );
|
||||
assert( $subscription_helper instanceof SubscriptionHelper );
|
||||
|
||||
$fields = array(
|
||||
|
|
|
@ -10,7 +10,7 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\WcGateway\Assets;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Checkout;
|
|||
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
|
|
@ -17,8 +17,8 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
|||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\PayPalOrderMissingException;
|
||||
|
|
|
@ -11,14 +11,14 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
|||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Customer;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\VaultedCreditCardHandler;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException;
|
||||
|
@ -32,7 +32,7 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
|||
*/
|
||||
class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
||||
|
||||
use ProcessPaymentTrait, GatewaySettingsRendererTrait;
|
||||
use ProcessPaymentTrait, GatewaySettingsRendererTrait, TransactionIdHandlingTrait;
|
||||
|
||||
const ID = 'ppcp-credit-card-gateway';
|
||||
|
||||
|
@ -181,18 +181,25 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
);
|
||||
|
||||
if ( $this->config->has( 'vault_enabled_dcc' ) && $this->config->get( 'vault_enabled_dcc' ) ) {
|
||||
array_push(
|
||||
$supports = apply_filters(
|
||||
'woocommerce_paypal_payments_credit_card_gateway_vault_supports',
|
||||
array(
|
||||
'subscriptions',
|
||||
'subscription_cancellation',
|
||||
'subscription_suspension',
|
||||
'subscription_reactivation',
|
||||
'subscription_amount_changes',
|
||||
'subscription_date_changes',
|
||||
'subscription_payment_method_change',
|
||||
'subscription_payment_method_change_customer',
|
||||
'subscription_payment_method_change_admin',
|
||||
'multiple_subscriptions',
|
||||
)
|
||||
);
|
||||
|
||||
$this->supports = array_merge(
|
||||
$this->supports,
|
||||
'subscriptions',
|
||||
'subscription_cancellation',
|
||||
'subscription_suspension',
|
||||
'subscription_reactivation',
|
||||
'subscription_amount_changes',
|
||||
'subscription_date_changes',
|
||||
'subscription_payment_method_change',
|
||||
'subscription_payment_method_change_customer',
|
||||
'subscription_payment_method_change_admin',
|
||||
'multiple_subscriptions'
|
||||
$supports
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -358,6 +365,17 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|||
);
|
||||
}
|
||||
|
||||
$saved_payment_card = WC()->session->get( 'ppcp_saved_payment_card' );
|
||||
if ( $saved_payment_card ) {
|
||||
if ( $saved_payment_card['payment_source'] === 'card' && $saved_payment_card['status'] === 'COMPLETED' ) {
|
||||
$this->update_transaction_id( $saved_payment_card['order_id'], $wc_order );
|
||||
$wc_order->payment_complete();
|
||||
WC()->session->set( 'ppcp_saved_payment_card', null );
|
||||
|
||||
return $this->handle_payment_success( $wc_order );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If customer has chosen a saved credit card payment.
|
||||
*/
|
||||
|
|
|
@ -20,8 +20,8 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
|||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\PayPalOrderMissingException;
|
||||
|
|
|
@ -22,7 +22,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\CaptureStatus;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
|
||||
|
||||
|
|
|
@ -59,12 +59,7 @@ trait OrderMetaTrait {
|
|||
private function get_payment_source( Order $order ): ?string {
|
||||
$source = $order->payment_source();
|
||||
if ( $source ) {
|
||||
if ( $source->card() ) {
|
||||
return 'card';
|
||||
}
|
||||
if ( $source->wallet() ) {
|
||||
return 'wallet';
|
||||
}
|
||||
return $source->name();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -16,6 +16,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
||||
|
@ -25,7 +26,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderHelper;
|
|||
use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\PayPalOrderMissingException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
@ -265,6 +266,8 @@ class OrderProcessor {
|
|||
if ( $this->capture_authorized_downloads( $order ) ) {
|
||||
$this->authorized_payments_processor->capture_authorized_payment( $wc_order );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_paypal_payments_after_order_processor', $wc_order, $order );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -349,12 +352,16 @@ class OrderProcessor {
|
|||
* @return bool
|
||||
*/
|
||||
private function order_is_ready_for_process( Order $order ): bool {
|
||||
|
||||
if ( $order->status()->is( OrderStatus::APPROVED ) || $order->status()->is( OrderStatus::CREATED ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! $order->payment_source() || ! $order->payment_source()->card() ) {
|
||||
$payment_source = $order->payment_source();
|
||||
if ( ! $payment_source ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $payment_source->name() !== 'card' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use Psr\Log\LoggerInterface;
|
|||
use Throwable;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WC_Order;
|
||||
|
@ -177,7 +177,7 @@ class WCGatewayModule implements ModuleInterface {
|
|||
$assets = new SettingsPageAssets(
|
||||
$c->get( 'wcgateway.url' ),
|
||||
$c->get( 'ppcp.asset-version' ),
|
||||
$c->get( 'subscription.helper' ),
|
||||
$c->get( 'wc-subscriptions.helper' ),
|
||||
$c->get( 'button.client_id_for_admin' ),
|
||||
$c->get( 'api.shop.currency' ),
|
||||
$c->get( 'api.shop.country' ),
|
||||
|
|
17
modules/ppcp-wc-subscriptions/composer.json
Normal file
17
modules/ppcp-wc-subscriptions/composer.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "woocommerce/ppcp-wc-subscriptions",
|
||||
"type": "dhii-mod",
|
||||
"description": "Module for WC Subscriptions plugin integration",
|
||||
"license": "GPL-2.0",
|
||||
"require": {
|
||||
"php": "^7.2 | ^8.0",
|
||||
"dhii/module-interface": "^0.3.0-alpha1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WooCommerce\\PayPalCommerce\\WcSubscriptions\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* The extensions.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Subscription
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
|
@ -2,15 +2,15 @@
|
|||
/**
|
||||
* The module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Subscription
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription;
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
|
||||
return static function (): ModuleInterface {
|
||||
return new SubscriptionModule();
|
||||
return new WcSubscriptionsModule();
|
||||
};
|
48
modules/ppcp-wc-subscriptions/services.php
Normal file
48
modules/ppcp-wc-subscriptions/services.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/**
|
||||
* The services
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WooCommerce\PayPalCommerce\PayPalSubscriptions\DeactivatePlanEndpoint;
|
||||
use WooCommerce\PayPalCommerce\PayPalSubscriptions\SubscriptionsApiHandler;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
return array(
|
||||
'wc-subscriptions.helper' => static function ( ContainerInterface $container ): SubscriptionHelper {
|
||||
return new SubscriptionHelper( $container->get( 'wcgateway.settings' ) );
|
||||
},
|
||||
'wc-subscriptions.renewal-handler' => static function ( ContainerInterface $container ): RenewalHandler {
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
$repository = $container->get( 'vaulting.repository.payment-token' );
|
||||
$endpoint = $container->get( 'api.endpoint.order' );
|
||||
$purchase_unit_factory = $container->get( 'api.factory.purchase-unit' );
|
||||
$payer_factory = $container->get( 'api.factory.payer' );
|
||||
$environment = $container->get( 'onboarding.environment' );
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
$authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' );
|
||||
return new RenewalHandler(
|
||||
$logger,
|
||||
$repository,
|
||||
$endpoint,
|
||||
$purchase_unit_factory,
|
||||
$container->get( 'api.factory.shipping-preference' ),
|
||||
$payer_factory,
|
||||
$environment,
|
||||
$settings,
|
||||
$authorized_payments_processor
|
||||
);
|
||||
},
|
||||
'wc-subscriptions.repository.payment-token' => static function ( ContainerInterface $container ): PaymentTokenRepository {
|
||||
$factory = $container->get( 'api.factory.payment-token' );
|
||||
$endpoint = $container->get( 'api.endpoint.payment-token' );
|
||||
return new PaymentTokenRepository( $factory, $endpoint );
|
||||
},
|
||||
);
|
|
@ -2,12 +2,12 @@
|
|||
/**
|
||||
* Helper trait for the subscriptions handling.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Subscription
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription;
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WC_Order;
|
||||
use WC_Subscriptions_Product;
|
|
@ -4,12 +4,12 @@
|
|||
* whether the cart contains a subscription, the current product is
|
||||
* a subscription or the subscription plugin is activated in the first place.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Subscription\Helper
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription\Helper;
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions\Helper;
|
||||
|
||||
use WC_Product;
|
||||
use WC_Product_Subscription_Variation;
|
|
@ -2,12 +2,12 @@
|
|||
/**
|
||||
* Handles subscription renewals.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Subscription
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription;
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WC_Subscription;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
|
@ -181,13 +181,8 @@ class RenewalHandler {
|
|||
* @throws \Exception If customer cannot be read/found.
|
||||
*/
|
||||
private function process_order( \WC_Order $wc_order ): void {
|
||||
|
||||
$user_id = (int) $wc_order->get_customer_id();
|
||||
$customer = new \WC_Customer( $user_id );
|
||||
$token = $this->get_token_for_customer( $customer, $wc_order );
|
||||
if ( ! $token ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||
$payer = $this->payer_factory->from_customer( $customer );
|
||||
|
@ -196,36 +191,38 @@ class RenewalHandler {
|
|||
'renewal'
|
||||
);
|
||||
|
||||
$token = $this->get_token_for_customer( $customer, $wc_order );
|
||||
if ( $token ) {
|
||||
$order = $this->order_endpoint->create(
|
||||
array( $purchase_unit ),
|
||||
$shipping_preference,
|
||||
$payer,
|
||||
$token
|
||||
);
|
||||
|
||||
$this->handle_paypal_order( $wc_order, $order );
|
||||
|
||||
$this->logger->info(
|
||||
sprintf(
|
||||
'Renewal for order %d is completed.',
|
||||
$wc_order->get_id()
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_paypal_payments_subscription_renewal_return_before_create_order_without_token', true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$order = $this->order_endpoint->create(
|
||||
array( $purchase_unit ),
|
||||
$shipping_preference,
|
||||
$payer,
|
||||
$token
|
||||
$payer
|
||||
);
|
||||
|
||||
$this->add_paypal_meta( $wc_order, $order, $this->environment );
|
||||
|
||||
if ( $order->intent() === 'AUTHORIZE' ) {
|
||||
$order = $this->order_endpoint->authorize( $order );
|
||||
$wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'false' );
|
||||
}
|
||||
|
||||
$transaction_id = $this->get_paypal_order_transaction_id( $order );
|
||||
if ( $transaction_id ) {
|
||||
$this->update_transaction_id( $transaction_id, $wc_order );
|
||||
|
||||
$subscriptions = wcs_get_subscriptions_for_order( $wc_order->get_id(), array( 'order_type' => 'any' ) );
|
||||
foreach ( $subscriptions as $id => $subscription ) {
|
||||
$subscription->update_meta_data( 'ppcp_previous_transaction_reference', $transaction_id );
|
||||
$subscription->save();
|
||||
}
|
||||
}
|
||||
|
||||
$this->handle_new_order_status( $order, $wc_order );
|
||||
|
||||
if ( $this->capture_authorized_downloads( $order ) ) {
|
||||
$this->authorized_payments_processor->capture_authorized_payment( $wc_order );
|
||||
}
|
||||
$this->handle_paypal_order( $wc_order, $order );
|
||||
|
||||
$this->logger->info(
|
||||
sprintf(
|
||||
|
@ -317,4 +314,38 @@ class RenewalHandler {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles PayPal order creation and updates WC order accordingly.
|
||||
*
|
||||
* @param \WC_Order $wc_order WC order.
|
||||
* @param Order $order PayPal order.
|
||||
* @return void
|
||||
* @throws NotFoundException When something goes wrong while handling the order.
|
||||
*/
|
||||
private function handle_paypal_order( \WC_Order $wc_order, Order $order ): void {
|
||||
$this->add_paypal_meta( $wc_order, $order, $this->environment );
|
||||
|
||||
if ( $order->intent() === 'AUTHORIZE' ) {
|
||||
$order = $this->order_endpoint->authorize( $order );
|
||||
$wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'false' );
|
||||
}
|
||||
|
||||
$transaction_id = $this->get_paypal_order_transaction_id( $order );
|
||||
if ( $transaction_id ) {
|
||||
$this->update_transaction_id( $transaction_id, $wc_order );
|
||||
|
||||
$subscriptions = wcs_get_subscriptions_for_order( $wc_order->get_id(), array( 'order_type' => 'any' ) );
|
||||
foreach ( $subscriptions as $id => $subscription ) {
|
||||
$subscription->update_meta_data( 'ppcp_previous_transaction_reference', $transaction_id );
|
||||
$subscription->save();
|
||||
}
|
||||
}
|
||||
|
||||
$this->handle_new_order_status( $order, $wc_order );
|
||||
|
||||
if ( $this->capture_authorized_downloads( $order ) ) {
|
||||
$this->authorized_payments_processor->capture_authorized_payment( $wc_order );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,12 +2,12 @@
|
|||
/**
|
||||
* Helper trait for the free trial subscriptions handling.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Subscription
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription;
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WC_Subscriptions;
|
||||
|
353
modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php
Normal file
353
modules/ppcp-wc-subscriptions/src/WcSubscriptionsModule.php
Normal file
|
@ -0,0 +1,353 @@
|
|||
<?php
|
||||
/**
|
||||
* The subscription module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Subscription;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
/**
|
||||
* Class SubscriptionModule
|
||||
*/
|
||||
class WcSubscriptionsModule implements ModuleInterface {
|
||||
|
||||
use TransactionIdHandlingTrait;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setup(): ServiceProviderInterface {
|
||||
return new ServiceProvider(
|
||||
require __DIR__ . '/../services.php',
|
||||
require __DIR__ . '/../extensions.php'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function run( ContainerInterface $c ): void {
|
||||
add_action(
|
||||
'woocommerce_scheduled_subscription_payment_' . PayPalGateway::ID,
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $amount, $order ) use ( $c ) {
|
||||
$this->renew( $order, $c );
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_scheduled_subscription_payment_' . CreditCardGateway::ID,
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $amount, $order ) use ( $c ) {
|
||||
$this->renew( $order, $c );
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_subscription_payment_complete',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $subscription ) use ( $c ) {
|
||||
$paypal_subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
|
||||
if ( $paypal_subscription_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$payment_token_repository = $c->get( 'vaulting.repository.payment-token' );
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
|
||||
$this->add_payment_token_id( $subscription, $payment_token_repository, $logger );
|
||||
|
||||
if ( count( $subscription->get_related_orders() ) === 1 ) {
|
||||
$parent_order = $subscription->get_parent();
|
||||
if ( is_a( $parent_order, WC_Order::class ) ) {
|
||||
$order_repository = $c->get( 'api.repository.order' );
|
||||
$order = $order_repository->for_wc_order( $parent_order );
|
||||
$transaction_id = $this->get_paypal_order_transaction_id( $order );
|
||||
if ( $transaction_id ) {
|
||||
$subscription->update_meta_data( 'ppcp_previous_transaction_reference', $transaction_id );
|
||||
$subscription->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_gateway_description',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $description, $id ) use ( $c ) {
|
||||
$payment_token_repository = $c->get( 'vaulting.repository.payment-token' );
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
$subscription_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
|
||||
return $this->display_saved_paypal_payments( $settings, (string) $id, $payment_token_repository, (string) $description, $subscription_helper );
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_credit_card_form_fields',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $default_fields, $id ) use ( $c ) {
|
||||
$payment_token_repository = $c->get( 'vaulting.repository.payment-token' );
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
$subscription_helper = $c->get( 'wc-subscriptions.helper' );
|
||||
|
||||
return $this->display_saved_credit_cards( $settings, $id, $payment_token_repository, $default_fields, $subscription_helper );
|
||||
},
|
||||
20,
|
||||
2
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'ppcp_create_order_request_body_data',
|
||||
function( array $data ) use ( $c ) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$wc_order_action = wc_clean( wp_unslash( $_POST['wc_order_action'] ?? '' ) );
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$subscription_id = wc_clean( wp_unslash( $_POST['post_ID'] ?? '' ) );
|
||||
if ( ! $subscription_id ) {
|
||||
return $data;
|
||||
}
|
||||
$subscription = wc_get_order( $subscription_id );
|
||||
if ( ! is_a( $subscription, WC_Subscription::class ) ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (
|
||||
$wc_order_action === 'wcs_process_renewal' && $subscription->get_payment_method() === CreditCardGateway::ID
|
||||
&& isset( $data['payment_source']['token'] ) && $data['payment_source']['token']['type'] === 'PAYMENT_METHOD_TOKEN'
|
||||
&& isset( $data['payment_source']['token']['source']->card )
|
||||
) {
|
||||
$data['payment_source'] = array(
|
||||
'card' => array(
|
||||
'vault_id' => $data['payment_source']['token']['id'],
|
||||
'stored_credential' => array(
|
||||
'payment_initiator' => 'MERCHANT',
|
||||
'payment_type' => 'RECURRING',
|
||||
'usage' => 'SUBSEQUENT',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$previous_transaction_reference = $subscription->get_meta( 'ppcp_previous_transaction_reference' );
|
||||
if ( $previous_transaction_reference ) {
|
||||
$data['payment_source']['card']['stored_credential']['previous_transaction_reference'] = $previous_transaction_reference;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key for the module.
|
||||
*
|
||||
* @return string|void
|
||||
*/
|
||||
public function getKey() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Subscription product renewal.
|
||||
*
|
||||
* @param WC_Order $order WooCommerce order.
|
||||
* @param ContainerInterface $container The container.
|
||||
* @return void
|
||||
*/
|
||||
protected function renew( WC_Order $order, ContainerInterface $container ) {
|
||||
$handler = $container->get( 'wc-subscriptions.renewal-handler' );
|
||||
assert( $handler instanceof RenewalHandler );
|
||||
|
||||
$handler->renew( $order );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Payment token ID to subscription.
|
||||
*
|
||||
* @param \WC_Subscription $subscription The subscription.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment repository.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
protected function add_payment_token_id(
|
||||
\WC_Subscription $subscription,
|
||||
PaymentTokenRepository $payment_token_repository,
|
||||
LoggerInterface $logger
|
||||
): void {
|
||||
try {
|
||||
$tokens = $payment_token_repository->all_for_user_id( $subscription->get_customer_id() );
|
||||
if ( $tokens ) {
|
||||
$latest_token_id = end( $tokens )->id() ? end( $tokens )->id() : '';
|
||||
$subscription->update_meta_data( 'payment_token_id', $latest_token_id );
|
||||
$subscription->save();
|
||||
}
|
||||
} catch ( RuntimeException $error ) {
|
||||
$message = sprintf(
|
||||
// translators: %1$s is the payment token Id, %2$s is the error message.
|
||||
__(
|
||||
'Could not add token Id to subscription %1$s: %2$s',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
$subscription->get_id(),
|
||||
$error->getMessage()
|
||||
);
|
||||
|
||||
$logger->log( 'warning', $message );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays saved PayPal payments.
|
||||
*
|
||||
* @param Settings $settings The settings.
|
||||
* @param string $id The payment gateway Id.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
||||
* @param string $description The payment gateway description.
|
||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||
* @return string
|
||||
*/
|
||||
protected function display_saved_paypal_payments(
|
||||
Settings $settings,
|
||||
string $id,
|
||||
PaymentTokenRepository $payment_token_repository,
|
||||
string $description,
|
||||
SubscriptionHelper $subscription_helper
|
||||
): string {
|
||||
if ( $settings->has( 'vault_enabled' )
|
||||
&& $settings->get( 'vault_enabled' )
|
||||
&& PayPalGateway::ID === $id
|
||||
&& $subscription_helper->is_subscription_change_payment()
|
||||
) {
|
||||
$tokens = $payment_token_repository->all_for_user_id( get_current_user_id() );
|
||||
if ( ! $tokens || ! $payment_token_repository->tokens_contains_paypal( $tokens ) ) {
|
||||
return esc_html__(
|
||||
'No PayPal payments saved, in order to use a saved payment you first need to create it through a purchase.',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
}
|
||||
|
||||
$output = sprintf(
|
||||
'<p class="form-row form-row-wide"><label>%1$s</label><select id="saved-paypal-payment" name="saved_paypal_payment">',
|
||||
esc_html__( 'Select a saved PayPal payment', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $token->source()->paypal ) ) {
|
||||
$output .= sprintf(
|
||||
'<option value="%1$s">%2$s</option>',
|
||||
$token->id(),
|
||||
$token->source()->paypal->payer->email_address
|
||||
);
|
||||
}
|
||||
}
|
||||
$output .= '</select></p>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
return $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays saved credit cards.
|
||||
*
|
||||
* @param Settings $settings The settings.
|
||||
* @param string $id The payment gateway Id.
|
||||
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
||||
* @param array $default_fields Default payment gateway fields.
|
||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||
* @return array|mixed|string
|
||||
* @throws NotFoundException When setting was not found.
|
||||
*/
|
||||
protected function display_saved_credit_cards(
|
||||
Settings $settings,
|
||||
string $id,
|
||||
PaymentTokenRepository $payment_token_repository,
|
||||
array $default_fields,
|
||||
SubscriptionHelper $subscription_helper
|
||||
) {
|
||||
|
||||
if ( $settings->has( 'vault_enabled_dcc' )
|
||||
&& $settings->get( 'vault_enabled_dcc' )
|
||||
&& $subscription_helper->is_subscription_change_payment()
|
||||
&& CreditCardGateway::ID === $id
|
||||
) {
|
||||
$tokens = $payment_token_repository->all_for_user_id( get_current_user_id() );
|
||||
if ( ! $tokens || ! $payment_token_repository->tokens_contains_card( $tokens ) ) {
|
||||
$default_fields = array();
|
||||
$default_fields['saved-credit-card'] = esc_html__(
|
||||
'No Credit Card saved, in order to use a saved Credit Card you first need to create it through a purchase.',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
return $default_fields;
|
||||
}
|
||||
|
||||
$output = sprintf(
|
||||
'<p class="form-row form-row-wide"><label>%1$s</label><select id="saved-credit-card" name="saved_credit_card">',
|
||||
esc_html__( 'Select a saved Credit Card payment', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
foreach ( $tokens as $token ) {
|
||||
if ( isset( $token->source()->card ) ) {
|
||||
$output .= sprintf(
|
||||
'<option value="%1$s">%2$s ...%3$s</option>',
|
||||
$token->id(),
|
||||
$token->source()->card->brand,
|
||||
$token->source()->card->last_digits
|
||||
);
|
||||
}
|
||||
}
|
||||
$output .= '</select></p>';
|
||||
|
||||
$default_fields = array();
|
||||
$default_fields['saved-credit-card'] = $output;
|
||||
return $default_fields;
|
||||
}
|
||||
|
||||
return $default_fields;
|
||||
}
|
||||
}
|
|
@ -71,7 +71,6 @@ class BillingPlanPricingChangeActivated implements RequestHandler {
|
|||
|
||||
$plan_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) );
|
||||
if ( $plan_id && ! empty( $request['resource']['billing_cycles'] ) ) {
|
||||
$this->logger->info( 'Starting stuff...' );
|
||||
$args = array(
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery
|
||||
'meta_key' => 'ppcp_subscription_plan',
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
"install:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn install",
|
||||
"install:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn install",
|
||||
"install:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn install",
|
||||
"install:modules:ppcp-subscription": "cd modules/ppcp-subscription && yarn install",
|
||||
"install:modules:ppcp-paypal-subscriptions": "cd modules/ppcp-paypal-subscriptions && yarn install",
|
||||
"install:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn install",
|
||||
"install:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn install",
|
||||
"install:modules:ppcp-compat": "cd modules/ppcp-compat && yarn install",
|
||||
"install:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn install",
|
||||
|
@ -25,7 +26,8 @@
|
|||
"build:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run build",
|
||||
"build:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run build",
|
||||
"build:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run build",
|
||||
"build:modules:ppcp-subscription": "cd modules/ppcp-subscription && yarn run build",
|
||||
"build:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn run build",
|
||||
"build:modules:ppcp-paypal-subscriptions": "cd modules/ppcp-paypal-subscriptions && yarn run build",
|
||||
"build:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run build",
|
||||
"build:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run build",
|
||||
"build:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run build",
|
||||
|
@ -37,7 +39,8 @@
|
|||
"watch:modules:ppcp-wc-gateway": "cd modules/ppcp-wc-gateway && yarn run watch",
|
||||
"watch:modules:ppcp-webhooks": "cd modules/ppcp-webhooks && yarn run watch",
|
||||
"watch:modules:ppcp-order-tracking": "cd modules/ppcp-order-tracking && yarn run watch",
|
||||
"watch:modules:ppcp-subscription": "cd modules/ppcp-subscription && yarn run watch",
|
||||
"watch:modules:ppcp-paypal-subscriptions": "cd modules/ppcp-paypal-subscriptions && yarn run watch",
|
||||
"watch:modules:ppcp-save-payment-methods": "cd modules/ppcp-save-payment-methods && yarn run watch",
|
||||
"watch:modules:ppcp-onboarding": "cd modules/ppcp-onboarding && yarn run watch",
|
||||
"watch:modules:ppcp-compat": "cd modules/ppcp-compat && yarn run watch",
|
||||
"watch:modules:ppcp-uninstall": "cd modules/ppcp-uninstall && yarn run watch",
|
||||
|
|
|
@ -26,7 +26,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\ErrorResponse;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
|
||||
use Mockery;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet;
|
||||
use function Brain\Monkey\Functions\expect;
|
||||
|
@ -1149,6 +1149,7 @@ class OrderEndpointTest extends TestCase
|
|||
$logger = Mockery::mock(LoggerInterface::class);
|
||||
$logger->shouldReceive('log');
|
||||
$logger->shouldReceive('debug');
|
||||
$logger->shouldReceive('warning');
|
||||
$applicationContext = Mockery::mock(ApplicationContext::class);
|
||||
$applicationContext
|
||||
->expects('to_array')
|
||||
|
|
|
@ -34,9 +34,6 @@ class OrderTest extends TestCase
|
|||
->expects('to_array')
|
||||
->andReturn(['applicationContext']);
|
||||
$paymentSource = Mockery::mock(PaymentSource::class);
|
||||
$paymentSource
|
||||
->expects('to_array')
|
||||
->andReturn(['paymentSource']);
|
||||
|
||||
$testee = new Order(
|
||||
$id,
|
||||
|
@ -68,8 +65,7 @@ class OrderTest extends TestCase
|
|||
'create_time' => $createTime->format($this->dateFormat),
|
||||
'update_time' => $updateTime->format($this->dateFormat),
|
||||
'payer' => ['payer'],
|
||||
'application_context' => ['applicationContext'],
|
||||
'payment_source' => ['paymentSource']
|
||||
'application_context' => ['applicationContext']
|
||||
];
|
||||
$this->assertEquals($expected, $testee->to_array());
|
||||
}
|
||||
|
|
|
@ -3,15 +3,12 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\Button\Helper;
|
||||
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSourceCard;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use Mockery\Mock;
|
||||
use function Brain\Monkey\Functions\when;
|
||||
|
||||
class ThreeDSecureTest extends TestCase
|
||||
{
|
||||
|
@ -23,21 +20,35 @@ class ThreeDSecureTest extends TestCase
|
|||
*/
|
||||
public function testDefault(int $expected, string $liabilityShift, string $authenticationResult, string $enrollment)
|
||||
{
|
||||
$result = \Mockery::mock(CardAuthenticationResult::class);
|
||||
$result->shouldReceive('liability_shift')->andReturn($liabilityShift);
|
||||
$result->shouldReceive('authentication_result')->andReturn($authenticationResult);
|
||||
$result->shouldReceive('enrollment_status')->andReturn($enrollment);
|
||||
$result->shouldReceive('to_array')->andReturn(['foo' => 'bar',]);
|
||||
$card = \Mockery::mock(PaymentSourceCard::class);
|
||||
$card->shouldReceive('authentication_result')->andReturn($result);
|
||||
$source = \Mockery::mock(PaymentSource::class);
|
||||
$source->shouldReceive('card')->andReturn($card);
|
||||
$order = \Mockery::mock(Order::class);
|
||||
$order->shouldReceive('payment_source')->andReturn($source);
|
||||
$logger = \Mockery::mock(LoggerInterface::class);
|
||||
$logger->shouldReceive('info');
|
||||
$authResult = \Mockery::mock(CardAuthenticationResult::class);
|
||||
$authResult->shouldReceive('liability_shift')->andReturn($liabilityShift);
|
||||
$authResult->shouldReceive('authentication_result')->andReturn($authenticationResult);
|
||||
$authResult->shouldReceive('enrollment_status')->andReturn($enrollment);
|
||||
$authResult->shouldReceive('to_array')->andReturn(['foo' => 'bar',]);
|
||||
|
||||
$testee = new ThreeDSecure($logger);
|
||||
$authenticationResultFactory = \Mockery::mock(CardAuthenticationResultFactory::class);
|
||||
$authenticationResultFactory->shouldReceive('from_paypal_response')
|
||||
->andReturn($authResult);
|
||||
|
||||
$source = \Mockery::mock(PaymentSource::class);
|
||||
$authentication_result = (object)[
|
||||
'brand' => 'visa',
|
||||
'authentication_result' => (object)array(
|
||||
'liability_shift' => $liabilityShift,
|
||||
'authentication_result' => $authenticationResult,
|
||||
'enrollment_status' => $enrollment
|
||||
),
|
||||
];
|
||||
|
||||
$source->shouldReceive('properties')->andReturn($authentication_result);
|
||||
|
||||
$order = \Mockery::mock(Order::class);
|
||||
$order->shouldReceive('payment_source')->andReturn($source);
|
||||
|
||||
$logger = \Mockery::mock(LoggerInterface::class);
|
||||
$logger->shouldReceive('info');
|
||||
|
||||
$testee = new ThreeDSecure($authenticationResultFactory, $logger);
|
||||
$result = $testee->proceed_with_order($order);
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\VaultedCreditCardHandler;
|
||||
|
@ -118,10 +118,11 @@ class VaultedCreditCardHandlerTest extends TestCase
|
|||
$order = Mockery::mock(Order::class);
|
||||
$order->shouldReceive('id')->andReturn('1');
|
||||
$order->shouldReceive('intent')->andReturn('CAPTURE');
|
||||
|
||||
$paymentSource = Mockery::mock(PaymentSource::class);
|
||||
$paymentSourceCard = Mockery::mock(PaymentSourceCard::class);
|
||||
$paymentSource->shouldReceive('card')->andReturn($paymentSourceCard);
|
||||
$paymentSource->shouldReceive('name')->andReturn('card');
|
||||
$order->shouldReceive('payment_source')->andReturn($paymentSource);
|
||||
|
||||
$orderStatus = Mockery::mock(OrderStatus::class);
|
||||
$orderStatus->shouldReceive('is')->andReturn(true);
|
||||
$order->shouldReceive('status')->andReturn($orderStatus);
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Assets;
|
|||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use function Brain\Monkey\Functions\when;
|
||||
use Mockery;
|
||||
|
|
|
@ -10,7 +10,7 @@ use WC_Order;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\VaultedCreditCardHandler;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
|
||||
|
@ -83,6 +83,7 @@ class CreditCardGatewayTest extends TestCase
|
|||
when('WC')->justReturn($woocommerce);
|
||||
$woocommerce->session = $session;
|
||||
$session->shouldReceive('set')->andReturn([]);
|
||||
$session->shouldReceive('get')->andReturn('');
|
||||
|
||||
$this->orderProcessor->shouldReceive('process')
|
||||
->with($wc_order)
|
||||
|
@ -106,6 +107,7 @@ class CreditCardGatewayTest extends TestCase
|
|||
when('WC')->justReturn($woocommerce);
|
||||
$woocommerce->session = $session;
|
||||
$session->shouldReceive('set')->andReturn([]);
|
||||
$session->shouldReceive('get')->andReturn('');
|
||||
|
||||
$savedCreditCard = 'abc123';
|
||||
$_POST['saved_credit_card'] = $savedCreditCard;
|
||||
|
|
|
@ -11,7 +11,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
|||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
|
||||
|
|
|
@ -19,7 +19,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use Mockery;
|
||||
|
|
|
@ -3,7 +3,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Processor;
|
||||
|
||||
|
||||
use Exception;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
|
@ -24,7 +23,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderHelper;
|
|||
use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Subscription;
|
||||
namespace WooCommerce\PayPalCommerce\WcSubscriptions;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\Dictionary;
|
||||
use Exception;
|
42
tests/Playwright/tests/save-payment-methods.spec.js
Normal file
42
tests/Playwright/tests/save-payment-methods.spec.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
const {test, expect} = require('@playwright/test');
|
||||
const {loginAsCustomer} = require("./utils/user");
|
||||
const {openPaypalPopup, loginIntoPaypal, completePaypalPayment} = require("./utils/paypal-popup");
|
||||
const {fillCheckoutForm, expectOrderReceivedPage} = require("./utils/checkout");
|
||||
|
||||
const {
|
||||
PRODUCT_URL,
|
||||
} = process.env;
|
||||
|
||||
async function expectContinuation(page) {
|
||||
await expect(page.locator('#payment_method_ppcp-gateway')).toBeChecked();
|
||||
|
||||
await expect(page.locator('.component-frame')).toHaveCount(0);
|
||||
}
|
||||
|
||||
async function completeContinuation(page) {
|
||||
await expectContinuation(page);
|
||||
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
page.locator('#place_order').click(),
|
||||
]);
|
||||
}
|
||||
|
||||
test('Save during purchase', async ({page}) => {
|
||||
await loginAsCustomer(page)
|
||||
|
||||
await page.goto(PRODUCT_URL);
|
||||
const popup = await openPaypalPopup(page);
|
||||
|
||||
await loginIntoPaypal(popup);
|
||||
await completePaypalPayment(popup);
|
||||
await fillCheckoutForm(page);
|
||||
|
||||
await completeContinuation(page);
|
||||
|
||||
await expectOrderReceivedPage(page);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue