Skip to content

Commit 8a2d026

Browse files
committed
First commit
0 parents  commit 8a2d026

17 files changed

+1087
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.idea
2+
*.patch
3+
*.rej
4+
*.orig

LICENSE.txt

Lines changed: 339 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Stripe API Drupal module
2+
------------------------
3+
Provider Stripe as forked from: https://www.drupal.org/project/stripe_api
4+
5+
This module provides a simple abstraction to use the Stripe PHP SDK.

composer.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "wasare/provider_stripe",
3+
"type": "drupal-module",
4+
"description": "Provides an integration to use the Stripe API library",
5+
"keywords": [
6+
"Drupal"
7+
],
8+
"license": "GPL-2.0+",
9+
"homepage": "https://github.com/wasare/provider_stripe",
10+
"minimum-stability": "dev",
11+
"support": {
12+
"issues": "https://github.com/wasare/provider_stripe/issues",
13+
"source": "https://github.com/wasare/provider_stripe"
14+
},
15+
"repositories": {
16+
"wasare": {
17+
"type": "path",
18+
"url": "https://github.com/wasare/provider_stripe"
19+
}
20+
},
21+
"require": {
22+
"stripe/stripe-php": "^7.36",
23+
"drupal/key": "^1.1"
24+
},
25+
"extra": {
26+
"branch-alias": {
27+
"dev-master": "1.x-dev"
28+
}
29+
}
30+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
test_secret_key: ''
2+
test_public_key: ''
3+
live_secret_key: ''
4+
live_public_key: ''
5+
log_webhooks: TRUE
6+
enable_webhooks: TRUE
7+
mode: 'test'

provider_stripe.info.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
name: '[Provider] Stripe'
2+
description: 'Provides an integration to use the Stripe API library'
3+
core_version_requirement: ^9
4+
type: module
5+
package: Provider
6+
configure: provider_stripe.admin
7+
dependencies:
8+
- key:key

provider_stripe.links.menu.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
provider_stripe.admin:
2+
title: 'Provider Stripe'
3+
description: 'Edit Provider Stripe API credentials.'
4+
parent: system.admin_config_services
5+
route_name: provider_stripe.admin

provider_stripe.module

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
/**
4+
* Implements hook_preprocess_HOOK().
5+
*/
6+
function provider_stripe_preprocess_page(&$variables) {
7+
$admin_context = \Drupal::service('router.admin_context');
8+
if ($admin_context->isAdminRoute()) {
9+
/** @var $stripe_api \Drupal\provider_stripe\StripeApiService **/
10+
$stripe_api = \Drupal::service('provider_stripe.stripe_api');
11+
if ($stripe_api->getMode() === 'test') {
12+
\Drupal::messenger()
13+
->addMessage(t('Provider Stripe is running in test mode.'),
14+
\Drupal\Core\Messenger\MessengerInterface::TYPE_WARNING);
15+
}
16+
}
17+
// $module_data = \Drupal::config('core.extension')->get('module');
18+
// unset($module_data['subscription_manager']);
19+
// \Drupal::configFactory()->getEditable('core.extension')->set('module', $module_data)->save();
20+
}

provider_stripe.permissions.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
administer provider stripe:
2+
title: 'Administer Provider Stripe'

provider_stripe.routing.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
provider_stripe.admin:
2+
path: '/admin/config/services/provider/stripe'
3+
defaults:
4+
_form: '\Drupal\provider_stripe\Form\StripeApiAdminForm'
5+
_title: 'Provider Stripe Settings'
6+
requirements:
7+
_permission: 'administer provider stripe'
8+
options:
9+
_admin_route: TRUE
10+
11+
provider_stripe.webhook:
12+
path: '/provider/stripe/webhook'
13+
methods: [POST]
14+
defaults:
15+
_controller: '\Drupal\provider_stripe\Controller\StripeApiWebhook::handleIncomingWebhook'
16+
requirements:
17+
_permission: 'access content'
18+
_content_type_format: json
19+
20+
provider_stripe.webhook_redirect:
21+
path: '/provider/stripe/webhook'
22+
methods: [GET, HEAD, PUT, DELETE]
23+
defaults:
24+
_controller: '\Drupal\provider_stripe\Controller\StripeApiWebhookRedirect::webhookRedirect'
25+
requirements:
26+
_permission: 'access content'

provider_stripe.services.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
services:
2+
provider_stripe.webhook_subscriber:
3+
class: Drupal\provider_stripe\Event\StripeApiWebhookSubscriber
4+
tags:
5+
- {name: event_subscriber}
6+
7+
provider_stripe.stripe_api:
8+
class: Drupal\provider_stripe\StripeApiService
9+
arguments: ["@config.factory", "@entity_type.manager", "@logger.channel.provider_stripe", "@key.repository"]
10+
11+
logger.channel.provider_stripe:
12+
parent: logger.channel_base
13+
arguments: ['provider_stripe']

src/Controller/StripeApiWebhook.php

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
3+
namespace Drupal\provider_stripe\Controller;
4+
5+
use Drupal\Core\Controller\ControllerBase;
6+
use Drupal\provider_stripe\Event\StripeApiWebhookEvent;
7+
use Drupal\provider_stripe\StripeApiService;
8+
use Stripe\Event;
9+
use Symfony\Component\DependencyInjection\ContainerInterface;
10+
use Symfony\Component\HttpFoundation\Request;
11+
use Symfony\Component\HttpFoundation\Response;
12+
13+
/**
14+
* Class StripeApiWebhook.
15+
*
16+
* Provides the route functionality for provider_stripe.webhook route.
17+
*/
18+
class StripeApiWebhook extends ControllerBase {
19+
20+
/**
21+
* Fake ID from Stripe we can check against.
22+
*
23+
* @var string
24+
*/
25+
const FAKE_EVENT_ID = 'evt_00000000000000';
26+
27+
/**
28+
* Stripe API service.
29+
*
30+
* @var \Drupal\provider_stripe\StripeApiService
31+
*/
32+
protected $stripeApi;
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
public function __construct(StripeApiService $stripe_api) {
38+
$this->stripeApi = $stripe_api;
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
public static function create(ContainerInterface $container) {
45+
return new static(
46+
$container->get('provider_stripe.stripe_api')
47+
);
48+
}
49+
50+
/**
51+
* Captures the incoming webhook request.
52+
*
53+
* @param \Symfony\Component\HttpFoundation\Request $request
54+
* The current request.
55+
*
56+
* @return \Symfony\Component\HttpFoundation\Response
57+
* A Response object.
58+
*/
59+
public function handleIncomingWebhook(Request $request) {
60+
$config = $this->config('provider_stripe.settings');
61+
if ($config->get('enable_webooks') === FALSE) {
62+
return new Response('Incoming webhooks are disabled by the Stripe API module configuration.', Response::HTTP_FORBIDDEN);
63+
}
64+
65+
$input = $request->getContent();
66+
$decoded_input = json_decode($input);
67+
68+
if (!$event = $this->isValidWebhook($decoded_input)) {
69+
$this->getLogger('provider_stripe')
70+
->error('Invalid webhook event: @data', [
71+
'@data' => $input,
72+
]);
73+
return new Response(NULL, Response::HTTP_FORBIDDEN);
74+
}
75+
76+
if ($config->get('log_webhooks')) {
77+
/** @var \Drupal\Core\Logger\LoggerChannelInterface $logger */
78+
$logger = $this->getLogger('provider_stripe');
79+
$logger->info("Stripe webhook received event:\n @event", ['@event' => (string)$event]);
80+
}
81+
82+
// Dispatch the webhook event.
83+
$dispatcher = \Drupal::service('event_dispatcher');
84+
$webhook_event = new StripeApiWebhookEvent($event->type, $decoded_input->data, $event);
85+
$dispatcher->dispatch('provider_stripe.webhook', $webhook_event);
86+
87+
return new Response('Okay', Response::HTTP_OK);
88+
}
89+
90+
/**
91+
* Determines if a webhook is valid.
92+
*
93+
* @param object $event_json
94+
* Stripe event object parsed from JSON.
95+
*
96+
* @return bool|\Stripe\Event
97+
* Returns a Stripe Event object or false if validation fails.
98+
*/
99+
private function isValidWebhook(object $event_json) {
100+
if (!empty($event_json->id)) {
101+
102+
if ($this->stripeApi->getMode() === 'test' && $event_json->livemode === FALSE && $event_json->id === self::FAKE_EVENT_ID) {
103+
// Don't try to verify this event, as it doesn't exist at stripe.
104+
return Event::constructFrom($event_json->object);
105+
}
106+
107+
// Verify the event by fetching it from Stripe.
108+
return Event::retrieve($event_json->id);
109+
}
110+
111+
return FALSE;
112+
}
113+
114+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Drupal\provider_stripe\Controller;
4+
5+
use Drupal\Core\Controller\ControllerBase;
6+
use Drupal\Core\Url;
7+
use Symfony\Component\HttpFoundation\RedirectResponse;
8+
9+
/**
10+
* Class StripeApiWebhookRedirect.
11+
*/
12+
class StripeApiWebhookRedirect extends ControllerBase {
13+
14+
/**
15+
* Redirects the user to home page and show the message.
16+
*
17+
* @return \Symfony\Component\HttpFoundation\RedirectResponse
18+
* A redirect response object.
19+
*/
20+
public function webhookRedirect() {
21+
$this->messenger()
22+
->addMessage($this->t('The webhook route works properly.'));
23+
return new RedirectResponse(Url::fromRoute('<front>')
24+
->setAbsolute()
25+
->toString());
26+
}
27+
28+
}

src/Event/StripeApiWebhookEvent.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace Drupal\provider_stripe\Event;
4+
5+
use Stripe\Event;
6+
use Symfony\Component\EventDispatcher\Event as SymfonyEvent;
7+
8+
/**
9+
* Class StripeApiWebhookEvent.
10+
*
11+
* Provides the Stripe API Webhook Event.
12+
*/
13+
class StripeApiWebhookEvent extends SymfonyEvent {
14+
15+
/**
16+
* Webhook event type.
17+
*
18+
* @var string
19+
*/
20+
public $type;
21+
22+
/**
23+
* Webhook event data.
24+
*
25+
* @var array
26+
*/
27+
public $data;
28+
29+
/**
30+
* Stripe event object.
31+
*
32+
* @var \Stripe\Event
33+
*/
34+
public $event;
35+
36+
/**
37+
* Sets the default values for the event.
38+
*
39+
* @param string $type
40+
* Webhook event type.
41+
* @param object $data
42+
* Webhook event data.
43+
* @param \Stripe\Event $event
44+
* Stripe event object.
45+
*/
46+
public function __construct(string $type, $data, Event $event = NULL) {
47+
$this->type = $type;
48+
$this->data = $data;
49+
$this->event = $event;
50+
}
51+
52+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Drupal\provider_stripe\Event;
4+
5+
use Drupal\Component\Serialization\Json;
6+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
7+
8+
/**
9+
* Class StripeApiWebhookSubscriber.
10+
*
11+
* Provides the webhook subscriber functionality.
12+
*/
13+
class StripeApiWebhookSubscriber implements EventSubscriberInterface {
14+
15+
/**
16+
* {@inheritdoc}
17+
*/
18+
public static function getSubscribedEvents() {
19+
$events['provider_stripe.webhook'][] = ['onIncomingWebhook'];
20+
return $events;
21+
}
22+
23+
/**
24+
* Process an incoming webhook.
25+
*
26+
* @param \Drupal\provider_stripe\Event\StripeApiWebhookEvent $event
27+
* Logs an incoming webhook of the setting is on.
28+
*/
29+
public function onIncomingWebhook(StripeApiWebhookEvent $event) {
30+
$config = \Drupal::config('provider_stripe.settings');
31+
if ($config->get('log_webhooks')) {
32+
\Drupal::logger('provider_stripe')
33+
->info('Processed webhook: @name<br /><br />Data: @data', [
34+
'@name' => $event->type,
35+
'@data' => Json::encode($event->data),
36+
]);
37+
}
38+
}
39+
40+
}

0 commit comments

Comments
 (0)