PluginProbe ʕ •ᴥ•ʔ
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress / 4.16.19
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress v4.16.19
4.16.19 4.16.18 4.16.17 4.16.16 trunk 1.0 1.0.1 1.0.2 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5a 1.1.6 1.1.7 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.4 1.4.1 1.4.2 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.7 1.7.1 1.7.2 1.8 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.1.9 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.2 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 3.0 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.13.3 4.13.4 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.15.0 4.15.1 4.15.10 4.15.11 4.15.12 4.15.13 4.15.14 4.15.15 4.15.16 4.15.17 4.15.18 4.15.19 4.15.2 4.15.20 4.15.20.1 4.15.21 4.15.22 4.15.23 4.15.24 4.15.25 4.15.3 4.15.4 4.15.5 4.15.6 4.15.7 4.15.8 4.15.9 4.16.0 4.16.1 4.16.10 4.16.11 4.16.12 4.16.13 4.16.14 4.16.15 4.16.2 4.16.3 4.16.4 4.16.5 4.16.6 4.16.7 4.16.8 4.16.9 4.2.0 4.3.0 4.3.1 4.3.2 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.7.0 4.8.0 4.9.0
wp-user-avatar / src / Membership / PaymentMethods / Stripe / WebhookHelpers.php
wp-user-avatar / src / Membership / PaymentMethods / Stripe Last commit date
WebhookHandlers 4 months ago APIClass.php 3 years ago Helpers.php 1 month ago PaymentHelpers.php 3 months ago Stripe.php 2 months ago WebhookHelpers.php 8 months ago index.php 3 years ago
WebhookHelpers.php
304 lines
1 <?php
2
3 namespace ProfilePress\Core\Membership\PaymentMethods\Stripe;
4
5 use ProfilePress\Core\Membership\PaymentMethods\Stripe\WebhookHandlers\ChargeRefunded;
6 use ProfilePress\Core\Membership\PaymentMethods\Stripe\WebhookHandlers\CheckoutSessionAsyncPaymentFailed;
7 use ProfilePress\Core\Membership\PaymentMethods\Stripe\WebhookHandlers\CheckoutSessionAsyncPaymentSucceeded;
8 use ProfilePress\Core\Membership\PaymentMethods\Stripe\WebhookHandlers\CheckoutSessionCompleted;
9 use ProfilePress\Core\Membership\PaymentMethods\Stripe\WebhookHandlers\CustomerSubscriptionCreated;
10 use ProfilePress\Core\Membership\PaymentMethods\Stripe\WebhookHandlers\CustomerSubscriptionDeleted;
11 use ProfilePress\Core\Membership\PaymentMethods\Stripe\WebhookHandlers\CustomerSubscriptionUpdated;
12 use ProfilePress\Core\Membership\PaymentMethods\Stripe\WebhookHandlers\InvoicePaymentSucceeded;
13 use ProfilePress\Core\Membership\PaymentMethods\Stripe\WebhookHandlers\PaymentIntentSucceeded;
14
15 class WebhookHelpers
16 {
17 public static function valid_events()
18 {
19 return apply_filters('ppress_stripe_webhooks_whitelist', [
20 'checkout.session.completed' => new CheckoutSessionCompleted(),
21 'checkout.session.async_payment_succeeded' => new CheckoutSessionAsyncPaymentSucceeded(),
22 'checkout.session.async_payment_failed' => new CheckoutSessionAsyncPaymentFailed(),
23 'customer.subscription.created' => new CustomerSubscriptionCreated(),
24 'customer.subscription.updated' => new CustomerSubscriptionUpdated(),
25 'customer.subscription.deleted' => new CustomerSubscriptionDeleted(), //triggers when sub is cancelled
26 'invoice.payment_succeeded' => new InvoicePaymentSucceeded(),
27 'payment_intent.succeeded' => new PaymentIntentSucceeded(),
28 'charge.refunded' => new ChargeRefunded()
29 ]);
30 }
31
32 public static function webhook_url()
33 {
34 return add_query_arg(['ppress-listener' => 'stripe'], home_url('/'));
35 }
36
37 public static function add_update_endpoint()
38 {
39 try {
40
41 $endpoint = self::exists();
42
43 if ( ! $endpoint) {
44 self::create();
45
46 return;
47 }
48
49 if (false === self::is_valid($endpoint)) {
50 self::update($endpoint);
51
52 return;
53 }
54
55 } catch (\Exception $e) {
56 // Fail silently.
57 }
58 }
59
60 /**
61 * Determines if the current payment mode has an up-to-date webhook endpoint.
62 *
63 * @return mixed|bool
64 */
65 public static function exists()
66 {
67 $mode = ppress_is_test_mode() ? 'test' : 'live';
68
69 $endpoint_id = ppress_get_payment_method_setting('stripe_' . $mode . '_webhook_endpoint_id', '');
70
71 if (empty($endpoint_id)) return false;
72
73 try {
74 $endpoint = self::get($endpoint_id);
75 } catch (\Exception $e) {
76 return false;
77 }
78
79 return $endpoint;
80 }
81
82 /**
83 * Determines if a Stripe webhook endpoint is still valid.
84 *
85 * @param mixed $endpoint
86 *
87 * @return bool True if the webhook does not need to be updated.
88 *
89 */
90 public static function is_valid($endpoint)
91 {
92 $enabled_events = $endpoint['enabled_events'];
93
94 // Enabled events are not * and do not match the defined whitelist.
95 if ( ! in_array('*', $enabled_events, true) && $enabled_events != self::get_event_whitelist()) {
96 return false;
97 }
98
99 if ($endpoint['url'] !== self::webhook_url()) return false;
100
101 if ('enabled' !== $endpoint['status']) return false;
102
103 return true;
104 }
105
106 /**
107 * Retrieves a Stripe webhook endpoint.
108 *
109 * @param string $endpoint_id Stripe endpoint ID.
110 *
111 * @return array
112 *
113 * @throws \Exception
114 */
115 public static function get($endpoint_id)
116 {
117 return APIClass::stripeClient()->webhookEndpoints->retrieve($endpoint_id)->toArray();
118 }
119
120 /**
121 * Creates a Stripe webhook endpoint with the current plugin and site settings.
122 *
123 * @return false|mixed
124 *
125 * @throws \Exception
126 */
127 public static function create()
128 {
129 // Use an existing endpoint if one already exists from a previous setup.
130 $endpoint = self::get_manual_endpoint();
131
132 if ( ! $endpoint) {
133
134 $endpoint = APIClass::stripeClient()->webhookEndpoints->create([
135 'url' => self::webhook_url(),
136 'enabled_events' => self::get_event_whitelist(),
137 'connect' => false,
138 'api_version' => PPRESS_STRIPE_API_VERSION,
139 'description' => sprintf(
140 'ProfilePress (WordPress plugin) endpoint (%s Mode)',
141 ppress_is_test_mode() ? 'Test' : 'Live'
142 ),
143 ])->toArray();
144 }
145
146 self::persist($endpoint);
147
148 return $endpoint;
149 }
150
151 /**
152 * Creates a Stripe webhook endpoint with the current plugin and site settings.
153 *
154 * @param $endpoint_id
155 * @param bool $without_persist
156 *
157 * @return void
158 * @throws \Exception
159 */
160 public static function delete($endpoint_id, $without_persist = false)
161 {
162 if ( ! empty($endpoint_id)) {
163
164 try {
165
166 $endpoint = APIClass::stripeClient()->webhookEndpoints->delete($endpoint_id);
167
168 if ( ! $without_persist) {
169 self::persist($endpoint, true);
170 }
171
172 } catch (\Exception $e) {
173 }
174 }
175 }
176
177 /**
178 * Updates a Stripe webhook endpoint with the current site and plugin settings.
179 *
180 * @param $endpoint
181 *
182 * @return array
183 * @throws \Exception
184 */
185 public static function update($endpoint)
186 {
187 $enabled_events = $endpoint['enabled_events'];
188
189 // Existing webhook does not accept all events. Merge the new whitelist.
190 if ( ! in_array('*', $enabled_events, true)) {
191 $enabled_events = array_values(
192 array_unique(
193 array_merge(
194 $enabled_events,
195 self::get_event_whitelist()
196 )
197 )
198 );
199 }
200
201 $endpoint = APIClass::stripeClient()->webhookEndpoints->update(
202 $endpoint['id'],
203 [
204 'url' => self::webhook_url(),
205 'enabled_events' => $enabled_events,
206 'disabled' => false,
207 ]
208 )->toArray();
209
210 self::persist($endpoint);
211
212 return $endpoint;
213 }
214
215 /**
216 * Returns a list of Stripe webhook events that are supported by the plugin.
217 *
218 * @return array
219 *
220 */
221 public static function get_event_whitelist()
222 {
223 return array_keys(self::valid_events());
224 }
225
226 /**
227 * Persists a Stripe webhook endpoint's information.
228 *
229 * @param $endpoint
230 *
231 */
232 private static function persist($endpoint, $clearOutVal = false)
233 {
234 $mode = ppress_is_test_mode() ? 'test' : 'live';
235
236 ppress_update_payment_method_setting(
237 'stripe_' . $mode . '_webhook_endpoint_id',
238 $clearOutVal ? '' : $endpoint['id']
239 );
240
241 ppress_update_payment_method_setting(
242 "stripe_{$mode}_webhook_endpoint_events",
243 $clearOutVal ? '' : $endpoint['enabled_events']
244 );
245
246 ppress_update_payment_method_setting(
247 "stripe_{$mode}_webhook_endpoint_url",
248 $clearOutVal ? '' : $endpoint['url']
249 );
250
251 // Secret is only returned on initial creation.
252 if (isset($endpoint['secret']) || $clearOutVal) {
253 ppress_update_payment_method_setting(
254 "stripe_{$mode}_webhook_secret",
255 $clearOutVal ? '' : $endpoint['secret']
256 );
257
258 // Clear out from a previous connection.
259 } else {
260 ppress_update_payment_method_setting(
261 "stripe_{$mode}_webhook_secret",
262 ''
263 );
264 }
265
266 ppress_update_payment_method_setting(
267 "stripe_{$mode}_webhook_api_version",
268 $clearOutVal ? '' : PPRESS_STRIPE_API_VERSION
269 );
270 }
271
272 /**
273 * Attempts to locate an endpoint that was manually created.
274 *
275 * If we find an endpoint with an exact URL match, persist it and return it.
276 *
277 * @return bool|mixed
278 *
279 * @throws \Exception
280 */
281 private static function get_manual_endpoint()
282 {
283 $endpoints = APIClass::stripeClient()->webhookEndpoints->all(['limit' => 100])->toArray();
284
285 foreach ($endpoints['data'] as $endpoint) {
286
287 if ($endpoint['url'] === self::webhook_url()) {
288
289 $remote_events = $endpoint['enabled_events'];
290 $local_events = self::get_event_whitelist();
291
292 if (count($remote_events) < count($local_events)) {
293 $endpoint = self::update($endpoint);
294 }
295
296 self::persist($endpoint);
297
298 return $endpoint;
299 }
300 }
301
302 return false;
303 }
304 }