Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: add API for gateway webhook events #7664

Draft
wants to merge 17 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions give.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ final class Give
Give\DonationSpam\ServiceProvider::class,
Give\Settings\ServiceProvider::class,
Give\FeatureFlags\OptionBasedFormEditor\ServiceProvider::class,
Give\Framework\PaymentGateways\ServiceProvider::class,
];

/**
Expand Down
21 changes: 21 additions & 0 deletions src/Framework/PaymentGateways/PaymentGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Give\Framework\PaymentGateways\Routes\RouteSignature;
use Give\Framework\PaymentGateways\Traits\HandleHttpResponses;
use Give\Framework\PaymentGateways\Traits\HasRouteMethods;
use Give\Framework\PaymentGateways\Webhooks\WebhookEvents;
use Give\Framework\Support\ValueObjects\Money;
use Give\Log\Log;
use Give\Subscriptions\Models\Subscription;
Expand Down Expand Up @@ -43,6 +44,15 @@ abstract class PaymentGateway implements PaymentGatewayInterface,
public $subscriptionModule;

/**
* @unreleased
*
* @var WebhookEvents $webhookEvents
*/
public $webhookEvents;

/**
* @unreleased Add the webhookEvents property
*
* @since 2.20.0 Change first argument type to SubscriptionModule abstract class.
* @since 2.18.0
*
Expand All @@ -55,6 +65,17 @@ public function __construct(SubscriptionModule $subscriptionModule = null)
}

$this->subscriptionModule = $subscriptionModule;
$this->webhookEvents = new WebhookEvents($this::id());
}

/**
* @unreleased
*/
public static function webhookEvents(): WebhookEvents
{
$instance = new static();

return $instance->webhookEvents;
}

/**
Expand Down
99 changes: 99 additions & 0 deletions src/Framework/PaymentGateways/ServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

namespace Give\Framework\PaymentGateways;

use Give\Donations\ValueObjects\DonationStatus;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\Actions\GetEventHandlerClassByDonationStatus;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\Actions\GetEventHandlerClassBySubscriptionStatus;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionFirstDonationCompleted;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionRenewalDonationCreated;
use Give\Helpers\Hooks;
use Give\ServiceProviders\ServiceProvider as ServiceProviderInterface;
use Give\Subscriptions\ValueObjects\SubscriptionStatus;

/**
* @unreleased
*/
class ServiceProvider implements ServiceProviderInterface
{
/**
* @unreleased
*/
public function register()
{
// TODO: Implement register() method.
}

/**
* @unreleased
*/
public function boot()
{
$this->registerWebhookEventHandlers();
}

private function registerWebhookEventHandlers()
{
add_action('give_init', function () {
$registeredPaymentGatewayIds = give()->gateways->getPaymentGateways();
foreach ($registeredPaymentGatewayIds as $gatewayId) {
$this->addDonationStatusEventHandlers($gatewayId);
$this->addSubscriptionStatusEventHandlers($gatewayId);
$this->addSubscriptionFirstDonationEventHandler($gatewayId);
$this->addSubscriptionRenewalDonationEventHandler($gatewayId);
}
}, 999);
}

/**
* @unreleased
*/
private function addDonationStatusEventHandlers(string $gatewayId)
{
foreach (DonationStatus::values() as $status) {
if ($eventHandlerClass = (new GetEventHandlerClassByDonationStatus())($status)) {
Hooks::addAction(
sprintf('givewp_%s_webhook_event_donation_status_%s', $gatewayId, $status->getValue()),
$eventHandlerClass
);
}
}
}

/**
* @unreleased
*/
private function addSubscriptionStatusEventHandlers(string $gatewayId)
{
foreach (SubscriptionStatus::values() as $status) {
if ($eventHandlerClass = (new GetEventHandlerClassBySubscriptionStatus())($status)) {
Hooks::addAction(
sprintf('givewp_%s_webhook_event_subscription_status_%s', $gatewayId, $status->getValue()),
$eventHandlerClass
);
}
}
}

/**
* @unreleased
*/
private function addSubscriptionFirstDonationEventHandler(string $gatewayId)
{
Hooks::addAction(
sprintf('givewp_%s_webhook_event_subscription_first_donation', $gatewayId),
SubscriptionFirstDonationCompleted::class
);
}

/**
* @unreleased
*/
private function addSubscriptionRenewalDonationEventHandler(string $gatewayId)
{
Hooks::addAction(
sprintf('givewp_%s_webhook_event_subscription_renewal_donation', $gatewayId),
SubscriptionRenewalDonationCreated::class
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Give\Framework\PaymentGateways\Webhooks\EventHandlers\Actions;

use Give\Donations\ValueObjects\DonationStatus;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\DonationAbandoned;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\DonationCancelled;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\DonationCompleted;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\DonationFailed;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\DonationPending;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\DonationPreapproval;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\DonationProcessing;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\DonationRefunded;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\DonationRevoked;

/**
* @unreleased
*/
class GetEventHandlerClassByDonationStatus
{
/**
* @unreleased
*/
public function __invoke(DonationStatus $status): string
{
switch ($status) {
case $status->isAbandoned():
return DonationAbandoned::class;
case $status->isCancelled():
return DonationCancelled::class;
case $status->isComplete():
return DonationCompleted::class;
case $status->isFailed():
return DonationFailed::class;
case $status->isPending():
return DonationPending::class;
case $status->isPreapproval():
return DonationPreapproval::class;
case $status->isProcessing():
return DonationProcessing::class;
case $status->isRefunded():
return DonationRefunded::class;
case $status->isRevoked():
return DonationRevoked::class;
default:
return '';
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Give\Framework\PaymentGateways\Webhooks\EventHandlers\Actions;

use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionActive;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionCancelled;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionCompleted;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionExpired;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionFailing;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionPaused;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionPending;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\SubscriptionSuspended;
use Give\Subscriptions\ValueObjects\SubscriptionStatus;

/**
* @unreleased
*/
class GetEventHandlerClassBySubscriptionStatus
{
/**
* @unreleased
*/
public function __invoke(SubscriptionStatus $status): string
{
switch ($status) {
case $status->isActive():
return SubscriptionActive::class;
case $status->isCancelled():
return SubscriptionCancelled::class;
case $status->isCompleted():
return SubscriptionCompleted::class;
case $status->isExpired():
return SubscriptionExpired::class;
case $status->isFailing():
return SubscriptionFailing::class;
case $status->isPaused():
return SubscriptionPaused::class;
case $status->isPending():
return SubscriptionPending::class;
case $status->isSuspended():
return SubscriptionSuspended::class;
default:
return '';
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public function __invoke(


/**
* @unreleased Add support for PAUSED and PENDING statuses
* @since 3.6.0
*/
protected function getMessageFromStatus(SubscriptionStatus $status): string
Expand All @@ -63,6 +64,12 @@ protected function getMessageFromStatus(SubscriptionStatus $status): string
case ($status->isFailing()):
$message = __('Subscription Failing.', 'give');
break;
case ($status->isPaused()):
$message = __('Subscription Paused.', 'give');
break;
case ($status->isPending()):
$message = __('Subscription Pending.', 'give');
break;
case ($status->isSuspended()):
$message = __('Subscription Suspended.', 'give');
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Give\Framework\PaymentGateways\Webhooks\EventHandlers;

use Exception;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\Actions\UpdateSubscriptionStatus;
use Give\Subscriptions\ValueObjects\SubscriptionStatus;

/**
* @unreleased
*/
class SubscriptionPaused
{
/**
* @unreleased
*
* @throws Exception
*/
public function __invoke(string $gatewaySubscriptionId, string $message = '')
{
$subscription = give()->subscriptions->getByGatewaySubscriptionId($gatewaySubscriptionId);

if ( ! $subscription || $subscription->status->isPaused()) {
return;
}

(new UpdateSubscriptionStatus())($subscription, SubscriptionStatus::PAUSED(), $message);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Give\Framework\PaymentGateways\Webhooks\EventHandlers;

use Exception;
use Give\Framework\PaymentGateways\Webhooks\EventHandlers\Actions\UpdateSubscriptionStatus;
use Give\Subscriptions\ValueObjects\SubscriptionStatus;

/**
* @unreleased
*/
class SubscriptionPending
{
/**
* @unreleased
*
* @throws Exception
*/
public function __invoke(string $gatewaySubscriptionId, string $message = '')
{
$subscription = give()->subscriptions->getByGatewaySubscriptionId($gatewaySubscriptionId);

if ( ! $subscription || $subscription->status->isPending()) {
return;
}

(new UpdateSubscriptionStatus())($subscription, SubscriptionStatus::PENDING(), $message);
}
}
Loading
Loading