| @@ -9,26 +9,11 @@ | ||
| 9 | 9 | * @var string |
| 10 | 10 | */ |
| 11 | 11 | public static $events_to_skip_option_name = 'frm_strp_events_to_skip'; |
| 12 | 12 | |
| 13 | - /** | |
| 14 | - * @var object|null | |
| 15 | - */ | |
| 16 | 13 | private $event; |
| 17 | - | |
| 18 | - /** | |
| 19 | - * @var object|null | |
| 20 | - */ | |
| 21 | 14 | private $invoice; |
| 22 | - | |
| 23 | - /** | |
| 24 | - * @var string|null | |
| 25 | - */ | |
| 26 | 15 | private $charge; |
| 27 | - | |
| 28 | - /** | |
| 29 | - * @var string|null | |
| 30 | - */ | |
| 31 | 16 | private $status; |
| 32 | 17 | |
| 33 | 18 | /** |
| 34 | 19 | * @return void |
| @@ -91,9 +76,8 @@ | ||
| 91 | 76 | 'response' => 'Payment ' . $payment->id . ' was updated', |
| 92 | 77 | 'success' => true, |
| 93 | 78 | ) |
| 94 | 79 | ); |
| 95 | - | |
| 96 | 80 | if ( ! $is_partial_refund ) { |
| 97 | 81 | $run_triggers = true; |
| 98 | 82 | } |
| 99 | 83 | }//end if |
| @@ -114,9 +98,8 @@ | ||
| 114 | 98 | * |
| 115 | 99 | * @since 6.5, introduced in v2.07 of the Stripe add on. |
| 116 | 100 | * |
| 117 | 101 | * @param stdClass $payment |
| 118 | - * | |
| 119 | 102 | * @return bool |
| 120 | 103 | */ |
| 121 | 104 | private function should_skip_status_update_for_first_recurring_payment( $payment ) { |
| 122 | 105 | if ( ! in_array( $this->event->type, array( 'payment_intent.succeeded', 'payment_intent.payment_failed' ), true ) ) { |
| @@ -163,16 +146,14 @@ | ||
| 163 | 146 | /** |
| 164 | 147 | * When a customer is deleted in Stripe, remove the link to a user. |
| 165 | 148 | * |
| 166 | 149 | * @since 6.5, introduced in v2.01 of the Stripe add on. |
| 167 | - * | |
| 168 | 150 | * @return void |
| 169 | 151 | */ |
| 170 | 152 | private function reset_customer() { |
| 171 | 153 | global $wpdb; |
| 172 | 154 | $customer_id = $this->invoice->id; |
| 173 | - | |
| 174 | - if ( ! $customer_id ) { | |
| 155 | + if ( empty( $customer_id ) ) { | |
| 175 | 156 | return; |
| 176 | 157 | } |
| 177 | 158 | $wpdb->query( |
| 178 | 159 | $wpdb->prepare( |
| @@ -186,9 +167,8 @@ | ||
| 186 | 167 | /** |
| 187 | 168 | * @return void |
| 188 | 169 | */ |
| 189 | 170 | private function maybe_subscription_canceled() { |
| 190 | - // phpcs:ignore Universal.Operators.StrictComparisons | |
| 191 | 171 | if ( $this->invoice->cancel_at_period_end == true ) { |
| 192 | 172 | $this->subscription_canceled( 'future_cancel' ); |
| 193 | 173 | } |
| 194 | 174 | } |
| @@ -194,14 +174,12 @@ | ||
| 194 | 174 | } |
| 195 | 175 | |
| 196 | 176 | /** |
| 197 | 177 | * @param string $status |
| 198 | - * | |
| 199 | 178 | * @return bool |
| 200 | 179 | */ |
| 201 | 180 | private function subscription_canceled( $status = 'canceled' ) { |
| 202 | 181 | $sub = $this->get_subscription( $this->invoice->id ); |
| 203 | - | |
| 204 | 182 | if ( ! $sub ) { |
| 205 | 183 | return false; |
| 206 | 184 | } |
| 207 | 185 | |
| @@ -224,14 +202,12 @@ | ||
| 224 | 202 | ); |
| 225 | 203 | return true; |
| 226 | 204 | } |
| 227 | 205 | |
| 228 | - /** | |
| 229 | - * @return false|object | |
| 230 | - */ | |
| 231 | 206 | private function prepare_from_invoice() { |
| 232 | 207 | if ( empty( $this->invoice->subscription ) ) { |
| 233 | 208 | // This isn't a subscription. |
| 209 | + FrmTransLiteLog::log_message( 'Stripe Webhook Message', 'No action taken since this is not a subscription.' ); | |
| 234 | 210 | echo json_encode( |
| 235 | 211 | array( |
| 236 | 212 | 'response' => 'Invoice missing', |
| 237 | 213 | 'success' => false, |
| @@ -240,9 +216,8 @@ | ||
| 240 | 216 | return false; |
| 241 | 217 | } |
| 242 | 218 | |
| 243 | 219 | $sub = $this->get_subscription( $this->invoice->subscription ); |
| 244 | - | |
| 245 | 220 | if ( ! $sub ) { |
| 246 | 221 | return false; |
| 247 | 222 | } |
| 248 | 223 | |
| @@ -264,9 +239,11 @@ | ||
| 264 | 239 | } |
| 265 | 240 | |
| 266 | 241 | $this->maybe_cancel_subscription( $sub ); |
| 267 | 242 | $this->update_next_bill_date( $sub, $payment_values ); |
| 268 | - return $frm_payment->get_one( $payment_id ); | |
| 243 | + | |
| 244 | + $payment = $frm_payment->get_one( $payment_id ); | |
| 245 | + return $payment; | |
| 269 | 246 | } |
| 270 | 247 | |
| 271 | 248 | /** |
| 272 | 249 | * Check if a subscription has reached its payment limit. |
| @@ -274,14 +251,12 @@ | ||
| 274 | 251 | * |
| 275 | 252 | * @since 6.11 |
| 276 | 253 | * |
| 277 | 254 | * @param object $sub |
| 278 | - * | |
| 279 | 255 | * @return void |
| 280 | 256 | */ |
| 281 | 257 | private function maybe_cancel_subscription( $sub ) { |
| 282 | 258 | $action = FrmFormAction::get_single_action_type( $sub->action_id, 'payment' ); |
| 283 | - | |
| 284 | 259 | // @phpstan-ignore-next-line |
| 285 | 260 | if ( ! is_object( $action ) || empty( $action->post_content['payment_limit'] ) ) { |
| 286 | 261 | return; |
| 287 | 262 | } |
| @@ -291,9 +266,8 @@ | ||
| 291 | 266 | // Form ID. |
| 292 | 267 | (int) $action->menu_order, |
| 293 | 268 | (int) $sub->item_id |
| 294 | 269 | ); |
| 295 | - | |
| 296 | 270 | if ( is_wp_error( $payment_limit ) ) { |
| 297 | 271 | FrmTransLiteLog::log_message( 'Invalid payment limit value', $payment_limit->get_error_message() ); |
| 298 | 272 | return; |
| 299 | 273 | } |
| @@ -310,9 +284,8 @@ | ||
| 310 | 284 | }; |
| 311 | 285 | |
| 312 | 286 | add_filter( $hook, $filter, 99 ); |
| 313 | 287 | $cancelled = FrmStrpLiteApiHelper::cancel_subscription( $sub->sub_id ); |
| 314 | - | |
| 315 | 288 | if ( $cancelled ) { |
| 316 | 289 | FrmTransLiteSubscriptionsController::change_subscription_status( |
| 317 | 290 | array( |
| 318 | 291 | 'status' => 'future_cancel', |
| @@ -319,9 +292,8 @@ | ||
| 319 | 292 | 'sub' => $sub, |
| 320 | 293 | ) |
| 321 | 294 | ); |
| 322 | 295 | } |
| 323 | - | |
| 324 | 296 | remove_filter( $hook, $filter, 99 ); |
| 325 | 297 | } |
| 326 | 298 | |
| 327 | 299 | /** |
| @@ -329,16 +301,16 @@ | ||
| 329 | 301 | * |
| 330 | 302 | * @since 6.11 |
| 331 | 303 | * |
| 332 | 304 | * @param string $sub_id Stripe subscriptino id prefixed with 'sub_'. |
| 333 | - * | |
| 334 | 305 | * @return int |
| 335 | 306 | */ |
| 336 | 307 | private function get_payments_count( $sub_id ) { |
| 337 | 308 | $frm_payment = new FrmTransLitePayment(); |
| 338 | 309 | $all_payments = $frm_payment->get_all_by( $sub_id, 'sub_id' ); |
| 310 | + $count = FrmTransLiteAppHelper::count_completed_payments( $all_payments ); | |
| 339 | 311 | |
| 340 | - return FrmTransLiteAppHelper::count_completed_payments( $all_payments ); | |
| 312 | + return $count; | |
| 341 | 313 | } |
| 342 | 314 | |
| 343 | 315 | /** |
| 344 | 316 | * @since 6.5, introduced in v2.07 of the Stripe add on. |
| @@ -343,24 +315,17 @@ | ||
| 343 | 315 | /** |
| 344 | 316 | * @since 6.5, introduced in v2.07 of the Stripe add on. |
| 345 | 317 | * |
| 346 | 318 | * @param stdClass $payment |
| 347 | - * | |
| 348 | 319 | * @return bool |
| 349 | 320 | */ |
| 350 | 321 | private function is_first_payment( $payment ) { |
| 351 | - return ! $payment->receipt_id || str_starts_with( $payment->receipt_id, 'pi_' ); | |
| 322 | + return ! $payment->receipt_id || 0 === strpos( $payment->receipt_id, 'pi_' ); | |
| 352 | 323 | } |
| 353 | 324 | |
| 354 | - /** | |
| 355 | - * @param string $sub_id | |
| 356 | - * | |
| 357 | - * @return object|null | |
| 358 | - */ | |
| 359 | 325 | private function get_subscription( $sub_id ) { |
| 360 | 326 | $frm_sub = new FrmTransLiteSubscription(); |
| 361 | 327 | $sub = $frm_sub->get_one_by( $sub_id, 'sub_id' ); |
| 362 | - | |
| 363 | 328 | if ( ! $sub ) { |
| 364 | 329 | // If this isn't an existing subscription, it must be a charge for another site/plugin. |
| 365 | 330 | FrmTransLiteLog::log_message( 'Stripe Webhook Message', 'No action taken since there is not a matching subscription for ' . $sub_id ); |
| 366 | 331 | echo json_encode( |
| @@ -373,13 +338,8 @@ | ||
| 373 | 338 | |
| 374 | 339 | return $sub; |
| 375 | 340 | } |
| 376 | 341 | |
| 377 | - /** | |
| 378 | - * @param string $sub_id | |
| 379 | - * | |
| 380 | - * @return object|null | |
| 381 | - */ | |
| 382 | 342 | private function get_payment_for_sub( $sub_id ) { |
| 383 | 343 | $frm_payment = new FrmTransLitePayment(); |
| 384 | 344 | return $frm_payment->get_one_by( $sub_id, 'sub_id' ); |
| 385 | 345 | } |
| @@ -385,9 +345,8 @@ | ||
| 385 | 345 | } |
| 386 | 346 | |
| 387 | 347 | /** |
| 388 | 348 | * @param array $payment_values |
| 389 | - * | |
| 390 | 349 | * @return void |
| 391 | 350 | */ |
| 392 | 351 | private function set_payment_values( &$payment_values ) { |
| 393 | 352 | $payment_values['begin_date'] = gmdate( 'Y-m-d' ); |
| @@ -409,14 +368,12 @@ | ||
| 409 | 368 | |
| 410 | 369 | /** |
| 411 | 370 | * @param object $sub |
| 412 | 371 | * @param array $payment |
| 413 | - * | |
| 414 | 372 | * @return void |
| 415 | 373 | */ |
| 416 | 374 | private function update_next_bill_date( $sub, $payment ) { |
| 417 | 375 | $frm_sub = new FrmTransLiteSubscription(); |
| 418 | - | |
| 419 | 376 | if ( $payment['status'] === 'complete' ) { |
| 420 | 377 | $frm_sub->update( $sub->id, array( 'next_bill_date' => $payment['expire_date'] ) ); |
| 421 | 378 | } elseif ( $payment['status'] === 'refunded' ) { |
| 422 | 379 | $frm_sub->update( $sub->id, array( 'next_bill_date' => $payment['begin_date'] ) ); |
| @@ -426,20 +383,19 @@ | ||
| 426 | 383 | /** |
| 427 | 384 | * @return bool |
| 428 | 385 | */ |
| 429 | 386 | private function is_partial_refund() { |
| 430 | - if ( $this->status !== 'refunded' ) { | |
| 431 | - return false; | |
| 387 | + $partial = false; | |
| 388 | + if ( $this->status === 'refunded' ) { | |
| 389 | + $amount = $this->invoice->amount; | |
| 390 | + $amount_refunded = $this->invoice->amount_refunded; | |
| 391 | + $partial = $amount != $amount_refunded; | |
| 432 | 392 | } |
| 433 | - | |
| 434 | - $amount = $this->invoice->amount; | |
| 435 | - $amount_refunded = $this->invoice->amount_refunded; | |
| 436 | - return $amount !== $amount_refunded; | |
| 393 | + return $partial; | |
| 437 | 394 | } |
| 438 | 395 | |
| 439 | 396 | /** |
| 440 | 397 | * @param array $payment_values |
| 441 | - * | |
| 442 | 398 | * @return void |
| 443 | 399 | */ |
| 444 | 400 | private function set_partial_refund( &$payment_values ) { |
| 445 | 401 | $payment_values['amount'] = $this->invoice->amount - $this->invoice->amount_refunded; |
| @@ -452,13 +408,11 @@ | ||
| 452 | 408 | public function process_connect_events() { |
| 453 | 409 | $this->flush_response(); |
| 454 | 410 | |
| 455 | 411 | $unprocessed_event_ids = FrmStrpLiteConnectHelper::get_unprocessed_event_ids(); |
| 456 | - | |
| 457 | 412 | if ( $unprocessed_event_ids ) { |
| 458 | 413 | $this->process_event_ids( $unprocessed_event_ids ); |
| 459 | 414 | } |
| 460 | - | |
| 461 | 415 | wp_send_json_success(); |
| 462 | 416 | } |
| 463 | 417 | |
| 464 | 418 | /** |
| @@ -464,9 +418,8 @@ | ||
| 464 | 418 | /** |
| 465 | 419 | * @since 6.5, introduced in v2.07 of the Stripe add on. |
| 466 | 420 | * |
| 467 | 421 | * @param array<string> $event_ids |
| 468 | - * | |
| 469 | 422 | * @return void |
| 470 | 423 | */ |
| 471 | 424 | private function process_event_ids( $event_ids ) { |
| 472 | 425 | foreach ( $event_ids as $event_id ) { |
| @@ -476,17 +429,15 @@ | ||
| 476 | 429 | |
| 477 | 430 | set_transient( 'frm_last_process_' . $event_id, time(), 60 ); |
| 478 | 431 | |
| 479 | 432 | $this->event = FrmStrpLiteConnectHelper::get_event( $event_id ); |
| 480 | - | |
| 481 | - if ( ! is_object( $this->event ) ) { | |
| 433 | + if ( is_object( $this->event ) ) { | |
| 434 | + $this->handle_event(); | |
| 435 | + $this->track_handled_event( $event_id ); | |
| 436 | + FrmStrpLiteConnectHelper::process_event( $event_id ); | |
| 437 | + } else { | |
| 482 | 438 | $this->count_failed_event( $event_id ); |
| 483 | - continue; | |
| 484 | 439 | } |
| 485 | - | |
| 486 | - $this->handle_event(); | |
| 487 | - $this->track_handled_event( $event_id ); | |
| 488 | - FrmStrpLiteConnectHelper::process_event( $event_id ); | |
| 489 | 440 | } |
| 490 | 441 | } |
| 491 | 442 | |
| 492 | 443 | /** |
| @@ -492,9 +443,8 @@ | ||
| 492 | 443 | /** |
| 493 | 444 | * @since 6.5, introduced in v2.07 of the Stripe add on. |
| 494 | 445 | * |
| 495 | 446 | * @param string $event_id |
| 496 | - * | |
| 497 | 447 | * @return bool True if the event should be skipped. |
| 498 | 448 | */ |
| 499 | 449 | private function should_skip_event( $event_id ) { |
| 500 | 450 | if ( $this->last_attempt_to_process_event_is_too_recent( $event_id ) ) { |
| @@ -501,15 +451,17 @@ | ||
| 501 | 451 | return true; |
| 502 | 452 | } |
| 503 | 453 | |
| 504 | 454 | $option = get_option( self::$events_to_skip_option_name ); |
| 455 | + if ( ! is_array( $option ) ) { | |
| 456 | + return false; | |
| 457 | + } | |
| 505 | 458 | |
| 506 | - return is_array( $option ) && in_array( $event_id, $option, true ); | |
| 459 | + return in_array( $event_id, $option, true ); | |
| 507 | 460 | } |
| 508 | 461 | |
| 509 | 462 | /** |
| 510 | 463 | * @param string $event_id |
| 511 | - * | |
| 512 | 464 | * @return bool |
| 513 | 465 | */ |
| 514 | 466 | private function last_attempt_to_process_event_is_too_recent( $event_id ) { |
| 515 | 467 | $last_process_attempt = get_transient( 'frm_last_process_' . $event_id ); |
| @@ -519,21 +471,24 @@ | ||
| 519 | 471 | /** |
| 520 | 472 | * @since 6.5, introduced in v2.07 of the Stripe add on. |
| 521 | 473 | * |
| 522 | 474 | * @param string $event_id |
| 523 | - * | |
| 524 | 475 | * @return void |
| 525 | 476 | */ |
| 526 | 477 | private function count_failed_event( $event_id ) { |
| 527 | - $transient_name = 'frm_failed_event_' . $event_id; | |
| 528 | - $transient = get_transient( $transient_name ); | |
| 529 | - $failed_count = is_int( $transient ) ? $transient + 1 : 1; | |
| 478 | + $transient_name = 'frm_failed_event_' . $event_id; | |
| 479 | + $transient = get_transient( $transient_name ); | |
| 480 | + if ( is_int( $transient ) ) { | |
| 481 | + $failed_count = $transient + 1; | |
| 482 | + } else { | |
| 483 | + $failed_count = 1; | |
| 484 | + } | |
| 485 | + | |
| 530 | 486 | $maximum_retries = 3; |
| 531 | - | |
| 532 | 487 | if ( $failed_count >= $maximum_retries ) { |
| 533 | 488 | $this->track_handled_event( $event_id ); |
| 534 | 489 | } else { |
| 535 | - set_transient( $transient_name, $failed_count, 4 * DAY_IN_SECONDS ); | |
| 490 | + set_transient( $transient_name, $failed_count ); | |
| 536 | 491 | } |
| 537 | 492 | } |
| 538 | 493 | |
| 539 | 494 | /** |
| @@ -542,9 +497,8 @@ | ||
| 542 | 497 | * |
| 543 | 498 | * @since 6.5, introduced in v2.07 of the Stripe add on. |
| 544 | 499 | * |
| 545 | 500 | * @param string $event_id |
| 546 | - * | |
| 547 | 501 | * @return void |
| 548 | 502 | */ |
| 549 | 503 | private function track_handled_event( $event_id ) { |
| 550 | 504 | $option = get_option( self::$events_to_skip_option_name ); |
| @@ -566,10 +520,9 @@ | ||
| 566 | 520 | * @return void |
| 567 | 521 | */ |
| 568 | 522 | private function handle_event() { |
| 569 | 523 | $this->invoice = $this->event->data->object; |
| 570 | - $this->charge = $this->invoice->charge ?? false; | |
| 571 | - | |
| 524 | + $this->charge = isset( $this->invoice->charge ) ? $this->invoice->charge : false; | |
| 572 | 525 | if ( ! $this->charge && $this->invoice->object === 'payment_intent' ) { |
| 573 | 526 | $this->charge = $this->invoice->id; |
| 574 | 527 | } |
| 575 | 528 | |