| @@ -145,13 +145,36 @@ | ||
| 145 | 145 | } |
| 146 | 146 | |
| 147 | 147 | self::maybe_update_intent( $intent, $action, $entry ); |
| 148 | 148 | |
| 149 | - $frm_payment->update( $payment->id, $new_payment_values ); | |
| 150 | - FrmTransLiteActionsController::trigger_payment_status_change( compact( 'status', 'payment' ) ); | |
| 149 | + // A webhook event may have already updated this payment, so check the status again before running triggers. | |
| 150 | + $needs_triggers = $status !== $payment->status && self::payment_status_still_needs_to_update( $payment->id, $status ); | |
| 151 | + $updated = $frm_payment->update( $payment->id, $new_payment_values ); | |
| 151 | 152 | |
| 153 | + if ( $needs_triggers && $updated ) { | |
| 154 | + FrmTransLiteActionsController::trigger_payment_status_change( compact( 'status', 'payment' ) ); | |
| 155 | + } | |
| 156 | + | |
| 152 | 157 | $redirect_helper->handle_success( $entry, isset( $charge ) ? $charge->id : '' ); |
| 153 | 158 | die(); |
| 159 | + } | |
| 160 | + | |
| 161 | + /** | |
| 162 | + * Check that the payment status has not been updated by another request already. | |
| 163 | + * This is to avoid running the payment actions twice. | |
| 164 | + * | |
| 165 | + * @since 6.35 | |
| 166 | + * | |
| 167 | + * @param int $payment_id The id of the payment to check. | |
| 168 | + * @param string $status The status the payment is about to be updated to. | |
| 169 | + * | |
| 170 | + * @return bool | |
| 171 | + */ | |
| 172 | + private static function payment_status_still_needs_to_update( $payment_id, $status ) { | |
| 173 | + $frm_payment = new FrmTransLitePayment(); | |
| 174 | + $payment = $frm_payment->get_one( $payment_id ); | |
| 175 | + | |
| 176 | + return $payment && $payment->status !== $status; | |
| 154 | 177 | } |
| 155 | 178 | |
| 156 | 179 | /** |
| 157 | 180 | * Try to add the description to a Stripe link payment after it was confirmed. |