PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | stripe/controllers/FrmTransLitePaymentsController.php +176 -21 6.5.3 → trunk View file →
@@ -8,29 +8,56 @@
8 8 /**
9 9 * @return void
10 10 */
11 11 public static function menu() {
12 - if ( FrmTransLiteAppHelper::should_fallback_to_paypal() ) {
13 - return;
14 - }
15 -
16 12 $frm_settings = FrmAppHelper::get_settings();
17 13
18 14 // Remove the PayPal submenu (PayPal payments will just appear in the regular Payments page).
19 15 remove_action( 'admin_menu', 'FrmPaymentsController::menu', 26 );
20 16
21 - add_submenu_page( 'formidable', $frm_settings->menu . ' | Payments', 'Payments', 'frm_view_entries', 'formidable-payments', 'FrmTransLitePaymentsController::route' );
17 + if ( in_array( FrmAppHelper::simple_get( 'action' ), array( 'edit', 'new', 'bulk_delete' ), true ) && is_callable( 'FrmPaymentsController::route' ) ) {
18 + // Use the PayPal addon for add new and edit routing if it is active.
19 + // This is required to support the "edit" link when using the Stripe Lite table view.
20 + // It is also required for the "Add New" button to work on the payments table page.
21 + $menu_route = 'FrmPaymentsController::route';
22 + } else {
23 + $menu_route = 'FrmTransLitePaymentsController::route';
24 + }
25 +
26 + $payments_string = __( 'Payments', 'formidable' );
27 + add_submenu_page(
28 + 'formidable',
29 + $frm_settings->menu . ' | ' . $payments_string,
30 + self::payments_menu_title( $payments_string ),
31 + 'frm_view_entries',
32 + 'formidable-payments',
33 + $menu_route
34 + );
22 35 }
23 36
24 37 /**
38 + * @since 6.11.1
39 + *
40 + * @param string $payments_string
41 + *
42 + * @return string
43 + */
44 + private static function payments_menu_title( $payments_string ) {
45 + ob_start();
46 + echo esc_html( $payments_string );
47 + FrmAppHelper::show_pill_text();
48 + return ob_get_clean();
49 + }
50 +
51 + /**
25 52 * @return void
26 53 */
27 54 public static function route() {
28 - $action = isset( $_REQUEST['frm_action'] ) ? 'frm_action' : 'action';
29 - $action = FrmAppHelper::get_param( $action, '', 'get', 'sanitize_title' );
30 - $type = FrmAppHelper::get_param( 'type', '', 'get', 'sanitize_title' );
55 + $action = isset( $_REQUEST['frm_action'] ) ? 'frm_action' : 'action';
56 + $action = FrmAppHelper::get_param( $action, '', 'get', 'sanitize_title' );
57 + $type = FrmAppHelper::get_param( 'type', '', 'get', 'sanitize_title' );
58 + $class_name = $type === 'subscriptions' ? 'FrmTransLiteSubscriptionsController' : 'FrmTransLitePaymentsController';
31 59
32 - $class_name = $type === 'subscriptions' ? 'FrmTransLiteSubscriptionsController' : 'FrmTransLitePaymentsController';
33 60 if ( method_exists( $class_name, $action ) ) {
34 61 $class_name::$action();
35 62 return;
36 63 }
@@ -39,8 +66,9 @@
39 66 }
40 67
41 68 /**
42 69 * @param object $payment
70 + *
43 71 * @return void
44 72 */
45 73 public static function load_sidebar_actions( $payment ) {
46 74 FrmTransLiteActionsController::actions_js();
@@ -53,8 +81,9 @@
53 81 /**
54 82 * Echo a receipt link.
55 83 *
56 84 * @param object $payment
85 + *
57 86 * @return void
58 87 */
59 88 public static function show_receipt_link( $payment ) {
60 89 $link = esc_html( $payment->receipt_id );
@@ -69,9 +98,9 @@
69 98 */
70 99 $link = apply_filters( 'frm_pay_' . $paysys . '_receipt', $link );
71 100 }
72 101
73 - echo FrmAppHelper::kses( $link, array( 'a' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
102 + FrmAppHelper::kses_echo( $link, array( 'a' ) );
74 103 }
75 104
76 105 /**
77 106 * @param string $paysys
@@ -86,8 +115,9 @@
86 115 /**
87 116 * Echo a refund link.
88 117 *
89 118 * @param object $payment
119 + *
90 120 * @return void
91 121 */
92 122 public static function show_refund_link( $payment ) {
93 123 $link = self::refund_link( $payment );
@@ -97,8 +127,9 @@
97 127 /**
98 128 * Show a link to a payment entry (unless it is deleted).
99 129 *
100 130 * @param object $payment
131 + *
101 132 * @return void
102 133 */
103 134 public static function show_entry_link( $payment ) {
104 135 $entry = FrmDb::get_col( 'frm_items', array( 'id' => $payment->item_id ) );
@@ -108,13 +139,15 @@
108 139 echo esc_html( sprintf( __( '%d (Deleted)', 'formidable' ), $payment->item_id ) );
109 140 return;
110 141 }
111 142
143 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
112 144 ?>
113 145 <a href="?page=formidable-entries&amp;action=show&amp;frm_action=show&amp;id=<?php echo absint( $payment->item_id ); ?>">
114 146 <?php echo absint( $payment->item_id ); ?>
115 147 </a>
116 148 <?php
149 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
117 150 }
118 151
119 152 /**
120 153 * Get a refund link.
@@ -119,8 +152,9 @@
119 152 /**
120 153 * Get a refund link.
121 154 *
122 155 * @param object $payment
156 + *
123 157 * @return string
124 158 */
125 159 public static function refund_link( $payment ) {
126 160 if ( $payment->status === 'refunded' ) {
@@ -126,16 +160,16 @@
126 160 if ( $payment->status === 'refunded' ) {
127 161 $link = esc_html__( 'Refunded', 'formidable' );
128 162 } else {
129 163 $confirm = __( 'Are you sure you want to refund that payment?', 'formidable' );
130 -
131 - $link = admin_url( 'admin-ajax.php?action=frm_trans_refund&payment_id=' . $payment->id . '&nonce=' . wp_create_nonce( 'frm_trans_ajax' ) );
132 - $link = '<a href="' . esc_url( $link ) . '" class="frm_trans_ajax_link" data-frmverify="' . esc_attr( $confirm ) . '">';
133 - $link .= esc_html__( 'Refund', 'formidable' );
134 - $link .= '</a>';
164 + $link = admin_url( 'admin-ajax.php?action=frm_trans_refund&payment_id=' . $payment->id . '&nonce=' . wp_create_nonce( 'frm_trans_ajax' ) );
165 + $link = '<a href="' . esc_url( $link ) . '" class="frm_trans_ajax_link" data-frmverify="' . esc_attr( $confirm ) . '">';
166 + $link .= esc_html__( 'Refund', 'formidable' );
167 + $link .= '</a>';
135 168 }
136 169
137 170 $paysys = $payment->paysys;
171 +
138 172 if ( self::should_filter_refund_link( $paysys ) ) {
139 173 /**
140 174 * Filter the refund link for a specific gateway.
141 175 * For example, Stripe uses frm_pay_stripe_refund_link.
@@ -142,9 +176,9 @@
142 176 *
143 177 * @param string $link
144 178 * @param object $payment
145 179 */
146 - $link = apply_filters( 'frm_pay_' . $paysys . '_refund_link', $link, $payment );
180 + return apply_filters( 'frm_pay_' . $paysys . '_refund_link', $link, $payment );
147 181 }
148 182
149 183 return $link;
150 184 }
@@ -168,31 +202,138 @@
168 202 FrmAppHelper::permission_check( 'frm_edit_entries' );
169 203 check_ajax_referer( 'frm_trans_ajax', 'nonce' );
170 204
171 205 $payment_id = FrmAppHelper::get_param( 'payment_id', '', 'get', 'absint' );
206 +
172 207 if ( ! $payment_id ) {
173 208 wp_die( esc_html__( 'Oops! No payment was selected for refund.', 'formidable' ) );
174 209 }
175 210
176 - $frm_payment = new FrmTransLitePayment();
177 - $payment = $frm_payment->get_one( $payment_id );
178 - $refunded = FrmStrpLiteAppHelper::call_stripe_helper_class( 'refund_payment', $payment->receipt_id );
211 + $payment = ( new FrmTransLitePayment() )->get_one( $payment_id );
179 212
213 + if ( ! $payment ) {
214 + wp_die( esc_html__( 'Oops! That payment does not exist.', 'formidable' ) );
215 + }
216 +
217 + $refunded = false;
218 + $reason = '';
219 + $debug_id = '';
220 + $paysys = $payment->paysys;
221 +
222 + switch ( $paysys ) {
223 + case 'stripe':
224 + $refunded = FrmStrpLiteAppHelper::call_stripe_helper_class( 'refund_payment', $payment->receipt_id );
225 + break;
226 + case 'square':
227 + $refunded = FrmSquareLiteConnectHelper::refund_payment( $payment->receipt_id );
228 + break;
229 + case 'paypal':
230 + $response = FrmPayPalLiteConnectHelper::refund_payment( $payment->receipt_id );
231 +
232 + // Check for structured error response with message and debug_id
233 + if ( is_object( $response ) && isset( $response->message ) && isset( $response->debug_id ) ) {
234 + $refunded = false;
235 + $reason = $response->message;
236 + $debug_id = $response->debug_id;
237 + } elseif ( false === $response ) {
238 + $refunded = false;
239 + $reason = self::get_paypal_refund_reason();
240 + $debug_id = FrmPayPalLiteConnectHelper::get_latest_debug_id_from_paypal_api();
241 + } elseif ( is_object( $response ) && isset( $response->refund_error ) ) {
242 + // Handle mock error responses from PayPal API
243 + $refunded = false;
244 + $reason = $response->message ?? '';
245 + $debug_id = $response->debug_id ?? '';
246 + } else {
247 + $refunded = true;
248 + }
249 +
250 + break;
251 + default:
252 + $refunded = false;
253 + break;
254 + }//end switch
255 +
180 256 if ( $refunded ) {
181 257 self::change_payment_status( $payment, 'refunded' );
182 258 $message = __( 'Refunded', 'formidable' );
259 + // phpcs:ignore Universal.ControlStructures.DisallowLonelyIf.Found
183 260 } else {
184 - $message = __( 'Failed', 'formidable' );
261 + // If the reason is already a complete error message, use it directly
262 + // instead of wrapping it redundantly in "Refund Failed (...)"
263 + if ( $reason && ! preg_match( '/^[A-Z_]+$/', $reason ) ) {
264 + $message = $reason;
265 + } else {
266 + $message = __( 'Refund Failed', 'formidable' );
267 +
268 + if ( $reason ) {
269 + $message .= ' (' . $reason . ')';
270 + }
271 + }
185 272 }
186 273
187 - wp_die( esc_html( $message ) );
274 + if ( $debug_id ) {
275 + $message .= '<br><br>Debug ID: ' . esc_html( $debug_id );
276 + }
277 +
278 + wp_die(
279 + sprintf(
280 + '<div class="%1$s">%2$s</div>',
281 + $refunded ? 'frm_updated_message' : 'frm_error_style',
282 + wp_kses_post( $message )
283 + )
284 + );
188 285 }
189 286
190 287 /**
288 + * Get a human-friendly reason from the latest PayPal refund error.
289 + *
290 + * Handles both uppercase issue codes (e.g. REFUND_FAILED_INSUFFICIENT_FUNDS)
291 + * and human-friendly description strings from the PayPal API.
292 + * Strips the {{debug_id:...}} token if present.
293 + *
294 + * @since 6.31
295 + *
296 + * @return string
297 + */
298 + private static function get_paypal_refund_reason() {
299 + $error = FrmPayPalLiteConnectHelper::get_latest_error_from_paypal_api();
300 +
301 + if ( ! $error ) {
302 + return '';
303 + }
304 +
305 + $error = preg_replace( '/\{\{debug_id:[^}]+\}\}/', '', $error );
306 + $error = trim( $error );
307 +
308 + if ( preg_match( '/^[A-Z_]+$/', $error ) ) {
309 + return self::convert_uppercase_underscores_to_ucwords( $error, array( 'REFUND_FAILED_', 'REFUND_' ) );
310 + }
311 +
312 + return $error;
313 + }
314 +
315 + /**
316 + * @param string $error The uppercase underscored string to convert.
317 + * @param array $prefixes_to_strip Prefixes to remove before converting.
318 + *
319 + * @return string
320 + */
321 + private static function convert_uppercase_underscores_to_ucwords( $error, $prefixes_to_strip = array() ) {
322 + if ( ! preg_match( '/^[A-Z_]+$/', $error ) ) {
323 + return '';
324 + }
325 +
326 + $reason = str_replace( $prefixes_to_strip, '', $error );
327 + return ucwords( strtolower( str_replace( '_', ' ', $reason ) ) );
328 + }
329 +
330 + /**
191 331 * Update the status of a payment.
192 332 *
193 333 * @param object $payment
194 334 * @param string $status
335 + *
195 336 * @return void
196 337 */
197 338 public static function change_payment_status( $payment, $status ) {
198 339 if ( $status === $payment->status ) {
@@ -202,6 +343,20 @@
202 343
203 344 $frm_payment = new FrmTransLitePayment();
204 345 $frm_payment->update( $payment->id, array( 'status' => $status ) );
205 346 FrmTransLiteActionsController::trigger_payment_status_change( compact( 'status', 'payment' ) );
347 + }
348 +
349 + /**
350 + * @since 6.31
351 + *
352 + * @param array|string $expected_gateways
353 + * @param array|string $selected_gateways
354 + *
355 + * @return void
356 + */
357 + public static function maybe_hide_payment_setting( $expected_gateways, $selected_gateways ) {
358 + if ( ! array_intersect( (array) $expected_gateways, (array) $selected_gateways ) ) {
359 + echo ' frm_hidden';
360 + }
206 361 }
207 362 }