-
Notifications
You must be signed in to change notification settings - Fork 41
Bring stripe add-on fixes into Stripe Lite #3274
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,7 +84,9 @@ private function set_payment_status() { | |
|
|
||
| FrmTransLiteAppHelper::add_note_to_payment( $payment_values, $note ); | ||
|
|
||
| $u = $frm_payment->update( $payment->id, $payment_values ); | ||
| // Read the status again right before the update, in case another request has already changed it. | ||
| $payment_status_still_does_not_match = $this->payment_status_still_does_not_match( $payment->id ); | ||
| $updated = $frm_payment->update( $payment->id, $payment_values ); | ||
|
|
||
| echo json_encode( | ||
| array( | ||
|
|
@@ -93,7 +95,7 @@ private function set_payment_status() { | |
| ) | ||
| ); | ||
|
|
||
| if ( ! $is_partial_refund ) { | ||
| if ( ! $is_partial_refund && $payment_status_still_does_not_match && $updated ) { | ||
| $run_triggers = true; | ||
| } | ||
| }//end if | ||
|
|
@@ -108,6 +110,24 @@ private function set_payment_status() { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Double check that the payment status has not changed. | ||
| * This is to avoid running actions twice by mistake, since a Stripe Link | ||
| * return URL and a webhook event can both process the same payment. | ||
| * | ||
| * @since x.x | ||
| * | ||
| * @param int $payment_id The id of the payment to check. | ||
| * | ||
| * @return bool | ||
| */ | ||
| private function payment_status_still_does_not_match( $payment_id ) { | ||
| $frm_payment = new FrmTransLitePayment(); | ||
| $payment = $frm_payment->get_one( $payment_id ); | ||
|
|
||
| return $payment && $payment->status !== $this->status; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
|
||
| /** | ||
| * Skip updating the payment object for the first recurring payment. | ||
| * This is to prevent double notifications because the first recurring payment creates an invoice and that invoice triggers the payment events. | ||
|
|
@@ -310,7 +330,9 @@ private function maybe_cancel_subscription( $sub ) { | |
| }; | ||
|
|
||
| add_filter( $hook, $filter, 99 ); | ||
| $cancelled = FrmStrpLiteApiHelper::cancel_subscription( $sub->sub_id ); | ||
|
|
||
| // There is no logged in user when a webhook event is processed, so the customer check has to be skipped here. | ||
| $cancelled = FrmStrpLiteAppHelper::call_stripe_helper_class( 'cancel_subscription_without_customer_check', $sub->sub_id ); | ||
|
|
||
| if ( $cancelled ) { | ||
| FrmTransLiteSubscriptionsController::change_subscription_status( | ||
|
|
@@ -319,6 +341,8 @@ private function maybe_cancel_subscription( $sub ) { | |
| 'sub' => $sub, | ||
| ) | ||
| ); | ||
| } else { | ||
| FrmTransLiteLog::log_message( 'Stripe Webhook Message', 'Unable to cancel subscription ' . $sub->sub_id . ' after it reached its payment limit.' ); | ||
| } | ||
|
|
||
| remove_filter( $hook, $filter, 99 ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -146,13 +146,36 @@ private static function handle_one_time_stripe_link_return_url( $intent_id, $cli | |
|
|
||
| self::maybe_update_intent( $intent, $action, $entry ); | ||
|
|
||
| $frm_payment->update( $payment->id, $new_payment_values ); | ||
| FrmTransLiteActionsController::trigger_payment_status_change( compact( 'status', 'payment' ) ); | ||
| // A webhook event may have already updated this payment, so check the status again before running triggers. | ||
| $needs_triggers = $status !== $payment->status && self::payment_status_still_needs_to_update( $payment->id, $status ); | ||
| $updated = $frm_payment->update( $payment->id, $new_payment_values ); | ||
|
|
||
| if ( $needs_triggers && $updated ) { | ||
| FrmTransLiteActionsController::trigger_payment_status_change( compact( 'status', 'payment' ) ); | ||
| } | ||
|
|
||
| $redirect_helper->handle_success( $entry, isset( $charge ) ? $charge->id : '' ); | ||
| die(); | ||
| } | ||
|
|
||
| /** | ||
| * Check that the payment status has not been updated by another request already. | ||
| * This is to avoid running the payment actions twice. | ||
| * | ||
| * @since x.x | ||
| * | ||
| * @param int $payment_id The id of the payment to check. | ||
| * @param string $status The status the payment is about to be updated to. | ||
| * | ||
| * @return bool | ||
| */ | ||
| private static function payment_status_still_needs_to_update( $payment_id, $status ) { | ||
| $frm_payment = new FrmTransLitePayment(); | ||
| $payment = $frm_payment->get_one( $payment_id ); | ||
|
|
||
| return $payment && $payment->status !== $status; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
|
||
| /** | ||
| * Try to add the description to a Stripe link payment after it was confirmed. | ||
| * | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🔎 Supported by static analysis
🏁 Script executed:
Repository: Strategy11/formidable-forms
Length of output: 18104
🏁 Script executed:
Repository: Strategy11/formidable-forms
Length of output: 31250
🏁 Script executed:
Repository: Strategy11/formidable-forms
Length of output: 264
🏁 Script executed:
Repository: Strategy11/formidable-forms
Length of output: 5232
Make payment status claiming atomic across both request paths.
Both paths perform a separate status read, then call
FrmTransLitePayment::update()throughFrmTransLiteDb::update(), which updates by payment ID only. Concurrent requests can both observe the old status, update the payment, and trigger actions. The webhook path also writes its stale full payment snapshot and can overwrite newer fields.Use a compare-and-set update in both paths. Use its result to trigger actions only for the request that claims the status.
📍 Affects 2 files
stripe/controllers/FrmStrpLiteEventsController.php#L87-L89(this comment)stripe/controllers/FrmStrpLiteLinkController.php#L149-L155🤖 Prompt for AI Agents