| @@ -202,9 +202,10 @@ | ||
| 202 | 202 | ->set_amount( $amount ) |
| 203 | 203 | ->set_description( $agreement->product_name ?? get_bloginfo() ) |
| 204 | 204 | ->set_transaction_type( WC_Vipps_Charge::TRANSACTION_TYPE_DIRECT_CAPTURE ) |
| 205 | 205 | ->set_due( $due_at ) |
| 206 | - ->set_retry_days( $this->retry_days ); | |
| 206 | + ->set_retry_days( $this->retry_days ) | |
| 207 | + ->set_processing_mode( $this->retry_days > 0 ? WC_Vipps_Charge::PROCESSING_MODE_MULTIPLE_ATTEMPTS : WC_Vipps_Charge::PROCESSING_MODE_SINGLE_ATTEMPT ); | |
| 207 | 208 | |
| 208 | 209 | $data = apply_filters( 'wc_vipps_recurring_create_charge_data', $charge->to_array(), $agreement->id, $order_id ); |
| 209 | 210 | |
| 210 | 211 | return $this->http_call( 'recurring/v3/agreements/' . $agreement->id . '/charges', 'POST', $data, $headers ); |
| @@ -541,12 +542,29 @@ | ||
| 541 | 542 | if ( $status < 300 && $status > 199 ) { |
| 542 | 543 | return $body; |
| 543 | 544 | } |
| 544 | 545 | |
| 545 | - // Rate limiting, temporary error | |
| 546 | - if ( $status === 429 ) { | |
| 547 | - $error_msg = __( "We hit Vipps/MobilePay's rate limit, we will retry later.", 'woo-vipps' ); | |
| 548 | - throw new WC_Vipps_Recurring_Temporary_Exception( $error_msg ); | |
| 546 | + // A transport error or a retryable HTTP response does not tell us whether a | |
| 547 | + // state-changing request reached Vipps/MobilePay. Treat it as temporary so | |
| 548 | + // callers can retry with the same idempotency key instead of failing the order. | |
| 549 | + if ( $status === 0 || in_array( $status, [ 408, 425, 429 ], true ) || $status >= 500 ) { | |
| 550 | + $error_msg = trim( (string) $default_error ); | |
| 551 | + if ( ! $error_msg ) { | |
| 552 | + $error_msg = sprintf( 'HTTP %d', $status ); | |
| 553 | + } | |
| 554 | + | |
| 555 | + $localized_msg = __( 'Vipps/MobilePay is temporarily unavailable. Please try again.', 'woo-vipps' ); | |
| 556 | + if ( $status === 429 ) { | |
| 557 | + $localized_msg = __( "We hit Vipps/MobilePay's rate limit. Please try again shortly.", 'woo-vipps' ); | |
| 558 | + } | |
| 559 | + | |
| 560 | + $log_body = is_array( $body ) ? json_encode( $body ) : $body; | |
| 561 | + WC_Vipps_Recurring_Logger::log( sprintf( 'HTTP Response Temporary Error (%s): %s (%s) with request body: %s. The response was: %s', $status, $error_msg, $endpoint, $request_body, $log_body ) ); | |
| 562 | + | |
| 563 | + $exception = new WC_Vipps_Recurring_Temporary_Exception( $error_msg, $localized_msg ); | |
| 564 | + $exception->response_code = $status; | |
| 565 | + | |
| 566 | + throw $exception; | |
| 549 | 567 | } |
| 550 | 568 | |
| 551 | 569 | // error handling |
| 552 | 570 | $error_msg = $default_error ?? ''; |