mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
move module.local to module
This commit is contained in:
parent
c443e4053c
commit
f8e82bdfaf
217 changed files with 8 additions and 2 deletions
8
modules/ppcp-subscription/composer.json
Normal file
8
modules/ppcp-subscription/composer.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "inpsyde/ppcp-subscription",
|
||||
"type": "inpsyde-module",
|
||||
"require": {
|
||||
"dhii/module-interface": "0.2.x-dev",
|
||||
"inpsyde/ppcp-api-client": "dev-master"
|
||||
}
|
||||
}
|
10
modules/ppcp-subscription/extensions.php
Normal file
10
modules/ppcp-subscription/extensions.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
/**
|
||||
* The extensions.
|
||||
*
|
||||
* @package Inpsyde\PayPalCommerce\Subscription
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
return array();
|
16
modules/ppcp-subscription/module.php
Normal file
16
modules/ppcp-subscription/module.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* The module.
|
||||
*
|
||||
* @package Inpsyde\PayPalCommerce\Subscription
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Inpsyde\PayPalCommerce\Subscription;
|
||||
|
||||
use Dhii\Modular\Module\ModuleInterface;
|
||||
|
||||
return static function (): ModuleInterface {
|
||||
return new SubscriptionModule();
|
||||
};
|
39
modules/ppcp-subscription/services.php
Normal file
39
modules/ppcp-subscription/services.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* The services
|
||||
*
|
||||
* @package Inpsyde\PayPalCommerce\Subscription
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Inpsyde\PayPalCommerce\Subscription;
|
||||
|
||||
use Inpsyde\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
||||
use Inpsyde\PayPalCommerce\Subscription\Repository\PaymentTokenRepository;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
'subscription.helper' => static function ( ContainerInterface $container ): SubscriptionHelper {
|
||||
return new SubscriptionHelper();
|
||||
},
|
||||
'subscription.renewal-handler' => static function ( ContainerInterface $container ): RenewalHandler {
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
$repository = $container->get( 'subscription.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' );
|
||||
return new RenewalHandler(
|
||||
$logger,
|
||||
$repository,
|
||||
$endpoint,
|
||||
$purchase_unit_factory,
|
||||
$payer_factory
|
||||
);
|
||||
},
|
||||
'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 );
|
||||
},
|
||||
);
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
/**
|
||||
* Helper class for the subscriptions. Contains methods to determine
|
||||
* whether the cart contains a subscription, the current product is
|
||||
* a subscription or the subscription plugin is activated in the first place.
|
||||
*
|
||||
* @package Inpsyde\PayPalCommerce\Subscription\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Inpsyde\PayPalCommerce\Subscription\Helper;
|
||||
|
||||
/**
|
||||
* Class SubscriptionHelper
|
||||
*/
|
||||
class SubscriptionHelper {
|
||||
|
||||
/**
|
||||
* Whether the current product is a subscription.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function current_product_is_subscription(): bool {
|
||||
if ( ! $this->plugin_is_active() ) {
|
||||
return false;
|
||||
}
|
||||
$product = wc_get_product();
|
||||
return is_a( $product, \WC_Product::class ) && $product->is_type( 'subscription' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the current cart contains subscriptions.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function cart_contains_subscription(): bool {
|
||||
if ( ! $this->plugin_is_active() ) {
|
||||
return false;
|
||||
}
|
||||
$cart = WC()->cart;
|
||||
if ( ! $cart || $cart->is_empty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $cart->get_cart() as $item ) {
|
||||
if ( ! isset( $item['data'] ) || ! is_a( $item['data'], \WC_Product::class ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( $item['data']->is_type( 'subscription' ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether only automatic payment gateways are accepted.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function accept_only_automatic_payment_gateways(): bool {
|
||||
|
||||
if ( ! $this->plugin_is_active() ) {
|
||||
return false;
|
||||
}
|
||||
$accept_manual_renewals = ( 'no' !== get_option(
|
||||
//phpcs:disable Inpsyde.CodeQuality.VariablesName.SnakeCaseVar
|
||||
\WC_Subscriptions_Admin::$option_prefix . '_accept_manual_renewals',
|
||||
//phpcs:enable Inpsyde.CodeQuality.VariablesName.SnakeCaseVar
|
||||
'no'
|
||||
) ) ? true : false;
|
||||
return ! $accept_manual_renewals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the subscription plugin is active or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function plugin_is_active(): bool {
|
||||
|
||||
return class_exists( \WC_Subscriptions::class );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* The payment token repository returns or deletes payment tokens for users.
|
||||
*
|
||||
* @package Inpsyde\PayPalCommerce\Subscription\Repository
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Inpsyde\PayPalCommerce\Subscription\Repository;
|
||||
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\PaymentTokenEndpoint;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
||||
|
||||
/**
|
||||
* Class PaymentTokenRepository
|
||||
*/
|
||||
class PaymentTokenRepository {
|
||||
|
||||
|
||||
public const USER_META = 'ppcp-vault-token';
|
||||
|
||||
/**
|
||||
* The payment token factory.
|
||||
*
|
||||
* @var PaymentTokenFactory
|
||||
*/
|
||||
private $factory;
|
||||
|
||||
/**
|
||||
* The payment token endpoint.
|
||||
*
|
||||
* @var PaymentTokenEndpoint
|
||||
*/
|
||||
private $endpoint;
|
||||
|
||||
/**
|
||||
* PaymentTokenRepository constructor.
|
||||
*
|
||||
* @param PaymentTokenFactory $factory The payment token factory.
|
||||
* @param PaymentTokenEndpoint $endpoint The payment token endpoint.
|
||||
*/
|
||||
public function __construct(
|
||||
PaymentTokenFactory $factory,
|
||||
PaymentTokenEndpoint $endpoint
|
||||
) {
|
||||
|
||||
$this->factory = $factory;
|
||||
$this->endpoint = $endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a token for a user.
|
||||
*
|
||||
* @param int $id The user id.
|
||||
*
|
||||
* @return PaymentToken|null
|
||||
*/
|
||||
public function for_user_id( int $id ): ?PaymentToken {
|
||||
try {
|
||||
$token = (array) get_user_meta( $id, self::USER_META, true );
|
||||
if ( ! $token || ! isset( $token['id'] ) ) {
|
||||
return $this->fetch_for_user_id( $id );
|
||||
}
|
||||
|
||||
$token = $this->factory->from_array( $token );
|
||||
return $token;
|
||||
} catch ( RuntimeException $error ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a token for a user.
|
||||
*
|
||||
* @param int $user_id The user id.
|
||||
* @param PaymentToken $token The token.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete_token( int $user_id, PaymentToken $token ): bool {
|
||||
delete_user_meta( $user_id, self::USER_META );
|
||||
return $this->endpoint->delete_token( $token );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch PaymentToken from PayPal for a user.
|
||||
*
|
||||
* @param int $id The user id.
|
||||
* @return PaymentToken
|
||||
*/
|
||||
private function fetch_for_user_id( int $id ): PaymentToken {
|
||||
|
||||
$tokens = $this->endpoint->for_user( $id );
|
||||
$token = current( $tokens );
|
||||
$token_array = $token->to_array();
|
||||
update_user_meta( $id, self::USER_META, $token_array );
|
||||
return $token;
|
||||
}
|
||||
}
|
222
modules/ppcp-subscription/src/class-renewalhandler.php
Normal file
222
modules/ppcp-subscription/src/class-renewalhandler.php
Normal file
|
@ -0,0 +1,222 @@
|
|||
<?php
|
||||
/**
|
||||
* Handles subscription renewals.
|
||||
*
|
||||
* @package Inpsyde\PayPalCommerce\Subscription
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Inpsyde\PayPalCommerce\Subscription;
|
||||
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
||||
use Inpsyde\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
use Inpsyde\PayPalCommerce\Subscription\Repository\PaymentTokenRepository;
|
||||
use Inpsyde\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Class RenewalHandler
|
||||
*/
|
||||
class RenewalHandler {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* The payment token repository.
|
||||
*
|
||||
* @var PaymentTokenRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* The order endpoint.
|
||||
*
|
||||
* @var OrderEndpoint
|
||||
*/
|
||||
private $order_endpoint;
|
||||
|
||||
/**
|
||||
* The purchase unit factory.
|
||||
*
|
||||
* @var PurchaseUnitFactory
|
||||
*/
|
||||
private $purchase_unit_factory;
|
||||
|
||||
/**
|
||||
* The payer factory.
|
||||
*
|
||||
* @var PayerFactory
|
||||
*/
|
||||
private $payer_factory;
|
||||
|
||||
/**
|
||||
* RenewalHandler constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param PaymentTokenRepository $repository The payment token repository.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
|
||||
* @param PayerFactory $payer_factory The payer factory.
|
||||
*/
|
||||
public function __construct(
|
||||
LoggerInterface $logger,
|
||||
PaymentTokenRepository $repository,
|
||||
OrderEndpoint $order_endpoint,
|
||||
PurchaseUnitFactory $purchase_unit_factory,
|
||||
PayerFactory $payer_factory
|
||||
) {
|
||||
|
||||
$this->logger = $logger;
|
||||
$this->repository = $repository;
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||
$this->payer_factory = $payer_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renew an order.
|
||||
*
|
||||
* @param \WC_Order $wc_order The Woocommerce order.
|
||||
*/
|
||||
public function renew( \WC_Order $wc_order ) {
|
||||
|
||||
$this->logger->log(
|
||||
'info',
|
||||
sprintf(
|
||||
// translators: %d is the id of the order.
|
||||
__( 'Start moneytransfer for order %d', 'paypal-for-woocommerce' ),
|
||||
(int) $wc_order->get_id()
|
||||
),
|
||||
array(
|
||||
'order' => $wc_order,
|
||||
)
|
||||
);
|
||||
|
||||
try {
|
||||
$this->process_order( $wc_order );
|
||||
} catch ( \Exception $error ) {
|
||||
$this->logger->log(
|
||||
'error',
|
||||
sprintf(
|
||||
// translators: %1$d is the order number, %2$s the error message.
|
||||
__(
|
||||
'An error occured while trying to renew the subscription for order %1$d: %2$s',
|
||||
'paypal-for-woocommerce'
|
||||
),
|
||||
(int) $wc_order->get_id(),
|
||||
$error->getMessage()
|
||||
),
|
||||
array(
|
||||
'order' => $wc_order,
|
||||
)
|
||||
);
|
||||
\WC_Subscriptions_Manager::process_subscription_payment_failure_on_order( $wc_order );
|
||||
return;
|
||||
}
|
||||
$this->logger->log(
|
||||
'info',
|
||||
sprintf(
|
||||
// translators: %d is the order number.
|
||||
__(
|
||||
'Moneytransfer for order %d is completed.',
|
||||
'paypal-for-woocommerce'
|
||||
),
|
||||
(int) $wc_order->get_id()
|
||||
),
|
||||
array(
|
||||
'order' => $wc_order,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a Woocommerce order.
|
||||
*
|
||||
* @param \WC_Order $wc_order The Woocommerce order.
|
||||
*
|
||||
* @throws \Exception If customer cannot be read/found.
|
||||
*/
|
||||
private function process_order( \WC_Order $wc_order ) {
|
||||
|
||||
$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 );
|
||||
$order = $this->order_endpoint->create(
|
||||
array( $purchase_unit ),
|
||||
$payer,
|
||||
$token,
|
||||
(string) $wc_order->get_id()
|
||||
);
|
||||
$this->capture_order( $order, $wc_order );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a payment token for a customer.
|
||||
*
|
||||
* @param \WC_Customer $customer The customer.
|
||||
* @param \WC_Order $wc_order The current Woocommerce order we want to process.
|
||||
*
|
||||
* @return PaymentToken|null
|
||||
*/
|
||||
private function get_token_for_customer( \WC_Customer $customer, \WC_Order $wc_order ): ?PaymentToken {
|
||||
|
||||
$token = $this->repository->for_user_id( (int) $customer->get_id() );
|
||||
if ( ! $token ) {
|
||||
$this->logger->log(
|
||||
'error',
|
||||
sprintf(
|
||||
// translators: %d is the customer id.
|
||||
__(
|
||||
'No payment token found for customer %d',
|
||||
'paypal-for-woocommerce'
|
||||
),
|
||||
(int) $customer->get_id()
|
||||
),
|
||||
array(
|
||||
'customer' => $customer,
|
||||
'order' => $wc_order,
|
||||
)
|
||||
);
|
||||
\WC_Subscriptions_Manager::process_subscription_payment_failure_on_order( $wc_order );
|
||||
}
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the PayPal order is captured/authorized the Woocommerce order gets updated accordingly.
|
||||
*
|
||||
* @param Order $order The PayPal order.
|
||||
* @param \WC_Order $wc_order The related Woocommerce order.
|
||||
*/
|
||||
private function capture_order( Order $order, \WC_Order $wc_order ) {
|
||||
|
||||
if ( $order->intent() === 'CAPTURE' && $order->status()->is( OrderStatus::COMPLETED ) ) {
|
||||
$wc_order->update_status(
|
||||
'processing',
|
||||
__( 'Payment received.', 'paypal-for-woocommerce' )
|
||||
);
|
||||
\WC_Subscriptions_Manager::process_subscription_payments_on_order( $wc_order );
|
||||
}
|
||||
|
||||
if ( $order->intent() === 'AUTHORIZE' ) {
|
||||
$this->order_endpoint->authorize( $order );
|
||||
$wc_order->update_meta_data( PayPalGateway::CAPTURED_META_KEY, 'false' );
|
||||
\WC_Subscriptions_Manager::process_subscription_payments_on_order( $wc_order );
|
||||
}
|
||||
}
|
||||
}
|
54
modules/ppcp-subscription/src/class-subscriptionmodule.php
Normal file
54
modules/ppcp-subscription/src/class-subscriptionmodule.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* The subscription module.
|
||||
*
|
||||
* @package Inpsyde\PayPalCommerce\Subscription
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Inpsyde\PayPalCommerce\Subscription;
|
||||
|
||||
use Dhii\Container\ServiceProvider;
|
||||
use Dhii\Modular\Module\ModuleInterface;
|
||||
use Inpsyde\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use Interop\Container\ServiceProviderInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class SubscriptionModule
|
||||
*/
|
||||
class SubscriptionModule implements ModuleInterface {
|
||||
|
||||
/**
|
||||
* Setup the module.
|
||||
*
|
||||
* @return ServiceProviderInterface
|
||||
*/
|
||||
public function setup(): ServiceProviderInterface {
|
||||
return new ServiceProvider(
|
||||
require __DIR__ . '/../services.php',
|
||||
require __DIR__ . '/../extensions.php'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the module.
|
||||
*
|
||||
* @param ContainerInterface $container The container.
|
||||
*/
|
||||
public function run( ContainerInterface $container ) {
|
||||
add_action(
|
||||
'woocommerce_scheduled_subscription_payment_' . PayPalGateway::ID,
|
||||
static function ( $amount, $order ) use ( $container ) {
|
||||
if ( ! is_a( $order, \WC_Order::class ) ) {
|
||||
return;
|
||||
}
|
||||
$handler = $container->get( 'subscription.renewal-handler' );
|
||||
$handler->renew( $order );
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue