Changeset 3385037
- Timestamp:
- 10/27/2025 08:28:24 AM (4 months ago)
- Location:
- formpays-pro
- Files:
-
- 5 added
- 7 edited
-
assets/screenshot-13.jpg (added)
-
trunk/CHANGELOG.md (modified) (1 diff)
-
trunk/README.txt (modified) (5 diffs)
-
trunk/admin/class-formpays-pro-admin.php (modified) (5 diffs)
-
trunk/admin/views/email-notifications.php (added)
-
trunk/assets/css/email-notifications.css (added)
-
trunk/assets/js/email-notifications.js (added)
-
trunk/assets/js/frontend.js (modified) (1 diff)
-
trunk/formpays-pro.php (modified) (10 diffs)
-
trunk/includes/class-formpays-pro-email-handler.php (added)
-
trunk/includes/class-formpays-pro-forms.php (modified) (8 diffs)
-
trunk/includes/gateways/class-formpays-pro-razorpay.php (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
formpays-pro/trunk/CHANGELOG.md
r3379943 r3385037 1 1 # FormPays Pro - Changelog 2 --- 3 4 ## [1.1.3] - 2024-12-19 5 6 ### Email Notifications & Payment Gateway Enhancements 7 **Comprehensive Email System & Razorpay Integration Improvements** 8 9 #### New Features 10 - **Email Notifications System**: 11 - Added "Email Notifications & Confirmations" admin menu 12 - 4 customizable email templates (Payment Success/Failed for Customer/Admin) 13 - Automatic email sending on payment events 14 - Test email functionality to verify settings 15 - Dynamic placeholders: `{transaction_id}`, `{amount}`, `{customer_name}`, `{customer_email}`, `{payment_date}`, `{payment_method}`, `{form_title}`, `{site_name}` 16 - **Smart Phone Number Formatting**: 17 - Automatically adds country code for Razorpay compatibility 18 - Formats numbers in `+{country code}{phone number}` format 19 - Handles various input formats (with/without country code) 20 21 #### Bug Fixes 22 - **Fixed Deprecated Property Warning**: Declared `$email_handler` property to fix PHP 8.2+ deprecation warning 23 - **Payment Method Selection**: Payment method selected on form now properly passed to Razorpay gateway 24 - **Phone Number Prefilling**: Customer phone number now correctly prefilled in Razorpay checkout page 25 - **Transaction Time Display**: Success page now shows correct transaction completion time 26 - **Success Page Enhancement**: Improved success page with more transaction details and better styling 27 28 #### Code Quality 29 - **WordPress Coding Standards**: Fixed placeholder ordering in translatable strings 30 - **Nonce Verification**: Added proper phpcs:ignore comments for email settings save 31 - **External Assets**: Moved email notifications JavaScript and CSS to external files (`assets/js/email-notifications.js`, `assets/css/email-notifications.css`) 32 2 33 --- 3 34 -
formpays-pro/trunk/README.txt
r3379943 r3385037 6 6 Requires PHP: 5.6 7 7 Requires PHP: 7.4 8 Stable tag: 1.1. 28 Stable tag: 1.1.3 9 9 Plugin URI: https://version-next.com/formpays-pro/ 10 10 Author URI: https://version-next.com/ … … 27 27 * **Transaction Management**: Complete payment tracking and management 28 28 * **Email Notifications**: Automatic notifications for payments and failures 29 * **Email Templates**: Customize notification emails for customers and admins 29 30 30 31 = Payment Gateways = … … 141 142 11. Analytics Dashboard 142 143 12. Drag and Drop Form Field 144 13. Notification Email Template 143 145 144 146 == External Services == … … 380 382 = Available Notifications = 381 383 382 * **Transaction Created**: Sent to customer and admin 383 * **Payment Success**: Sent to customer and admin 384 * **Payment Failure**: Sent to customer with retry information 384 * **Payment Success - Customer**: Confirmation email to customer with transaction details 385 * **Payment Success - Admin**: Notification to admin about successful payment 386 * **Payment Failed - Customer**: Failure notification with retry information 387 * **Payment Failed - Admin**: Alert to admin about failed payment 388 389 = Email Template Customization = 390 391 1. Go to **FormPays Pro → Email Notifications** 392 2. Customize email templates with dynamic placeholders: 393 - `{transaction_id}` - Transaction ID 394 - `{amount}` - Payment amount 395 - `{customer_name}` - Customer name 396 - `{customer_email}` - Customer email 397 - `{payment_date}` - Payment date and time 398 - `{payment_method}` - Selected payment method 399 - `{form_title}` - Form title 400 - `{site_name}` - Your site name 401 3. Enable/disable individual email notifications 402 4. Test email functionality to verify settings 385 403 386 404 = Customization = … … 449 467 450 468 == Changelog == 469 470 = 1.1.3 = 471 * **Features**: Added Email Notifications & Confirmations menu with customizable email templates 472 * **Features**: Automatic email notifications for payment success and failure to customers and admins 473 * **Features**: Test email functionality to verify email settings 474 * **Features**: Smart phone number formatting with country code for Razorpay integration 475 * **Bug Fix**: Fixed deprecated dynamic property warning for email_handler 476 * **Bug Fix**: Resolved payment method selection not being passed to Razorpay gateway 477 * **Bug Fix**: Fixed customer phone number not being prefilled in Razorpay checkout 478 * **Bug Fix**: Corrected transaction time display on success page 479 * **Enhancement**: Enhanced success page with more detailed transaction information 480 * **Code Quality**: Fixed placeholder ordering in translatable strings 481 * **Code Quality**: Added WordPress Coding Standards compliance for email notifications 451 482 452 483 = 1.1.2 = -
formpays-pro/trunk/admin/class-formpays-pro-admin.php
r3379943 r3385037 30 30 add_action( 'wp_ajax_formpays_pro_bulk_delete_transactions', array( $this, 'ajax_bulk_delete_transactions' ) ); 31 31 add_action( 'wp_ajax_formpays_pro_bulk_approve_transactions', array( $this, 'ajax_bulk_approve_transactions' ) ); 32 add_action( 'wp_ajax_formpays_pro_send_test_email', array( $this, 'ajax_send_test_email' ) ); 32 33 } 33 34 /** … … 93 94 'formpays-pro-analytics', 94 95 array( $this, 'analytics_page' ) 96 ); 97 add_submenu_page( 98 'formpays-pro', 99 __( 'Email Notifications', 'formpays-pro' ), 100 __( 'Email Notifications', 'formpays-pro' ), 101 'manage_options', 102 'formpays-pro-email-notifications', 103 array( $this, 'email_notifications_page' ) 95 104 ); 96 105 add_submenu_page( … … 216 225 'export_nonce' => wp_create_nonce( 'formpays_pro_export_transactions' ), 217 226 'debug' => defined( 'WP_DEBUG' ) && WP_DEBUG, 227 ) 228 ); 229 } 230 231 // Enqueue email notifications-specific styles and scripts 232 if ( strpos( $hook, 'formpays-pro-email-notifications' ) !== false ) { 233 wp_enqueue_style( 234 'formpays-pro-email-notifications', 235 FORMPAYS_PRO_PLUGIN_URL . 'assets/css/email-notifications.css', 236 array( 'formpays-pro-admin' ), 237 FORMPAYS_PRO_VERSION 238 ); 239 240 wp_enqueue_script( 241 'formpays-pro-email-notifications', 242 FORMPAYS_PRO_PLUGIN_URL . 'assets/js/email-notifications.js', 243 array( 'jquery', 'formpays-pro-admin' ), 244 FORMPAYS_PRO_VERSION, 245 true 246 ); 247 248 // Localize email notifications script 249 wp_localize_script( 250 'formpays-pro-email-notifications', 251 'formpays_pro_email_notifications', 252 array( 253 'ajax_url' => admin_url( 'admin-ajax.php' ), 254 'nonce' => wp_create_nonce( 'formpays_pro_test_email' ), 255 'please_enter_email' => esc_html__( 'Please enter a test email address.', 'formpays-pro' ), 256 'sending' => esc_html__( 'Sending...', 'formpays-pro' ), 257 'test_email_sent' => esc_html__( 'Test email sent successfully!', 'formpays-pro' ), 258 'failed_to_send' => esc_html__( 'Failed to send test email: ', 'formpays-pro' ), 259 'unknown_error' => esc_html__( 'Unknown error', 'formpays-pro' ), 260 'failed_to_send_error' => esc_html__( 'Failed to send test email. Please try again.', 'formpays-pro' ), 218 261 ) 219 262 ); … … 1132 1175 include FORMPAYS_PRO_PLUGIN_DIR . 'admin/views/analytics.php'; 1133 1176 } 1177 1178 /** 1179 * Email notifications page 1180 */ 1181 public function email_notifications_page() { 1182 // Handle form submission for email settings 1183 if ( isset( $_POST['formpays_pro_email_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['formpays_pro_email_nonce'] ) ), 'formpays_pro_email_settings' ) ) { 1184 $this->handle_email_settings_save(); 1185 } 1186 1187 // Get current email settings 1188 $email_settings = get_option( 'formpays_pro_email_settings', array() ); 1189 1190 // Default email templates 1191 $default_templates = array( 1192 'payment_success_customer' => array( 1193 'subject' => __( 'Payment Confirmation - Transaction #{transaction_id}', 'formpays-pro' ), 1194 'message' => __( 'Dear {customer_name}, 1195 1196 Thank you for your payment! Your transaction has been completed successfully. 1197 1198 Transaction Details: 1199 - Transaction ID: {transaction_id} 1200 - Amount: {amount} 1201 - Payment Date: {payment_date} 1202 - Payment Method: {payment_method} 1203 1204 If you have any questions, please contact us. 1205 1206 Best regards, 1207 {site_name}', 'formpays-pro' ), 1208 'enabled' => true, 1209 ), 1210 'payment_success_admin' => array( 1211 'subject' => __( 'New Payment Received - Transaction #{transaction_id}', 'formpays-pro' ), 1212 'message' => __( 'A new payment has been received: 1213 1214 Transaction Details: 1215 - Transaction ID: {transaction_id} 1216 - Amount: {amount} 1217 - Customer Name: {customer_name} 1218 - Customer Email: {customer_email} 1219 - Payment Date: {payment_date} 1220 - Payment Method: {payment_method} 1221 - Form: {form_title} 1222 1223 Please check your admin panel for more details.', 'formpays-pro' ), 1224 'enabled' => true, 1225 ), 1226 'payment_failed_customer' => array( 1227 'subject' => __( 'Payment Failed - Transaction #{transaction_id}', 'formpays-pro' ), 1228 'message' => __( 'Dear {customer_name}, 1229 1230 We were unable to process your payment for transaction #{transaction_id}. 1231 1232 Amount: {amount} 1233 Payment Date: {payment_date} 1234 1235 Please try again or contact us for assistance. 1236 1237 Best regards, 1238 {site_name}', 'formpays-pro' ), 1239 'enabled' => true, 1240 ), 1241 'payment_failed_admin' => array( 1242 'subject' => __( 'Payment Failed - Transaction #{transaction_id}', 'formpays-pro' ), 1243 'message' => __( 'A payment has failed: 1244 1245 Transaction Details: 1246 - Transaction ID: {transaction_id} 1247 - Amount: {amount} 1248 - Customer Name: {customer_name} 1249 - Customer Email: {customer_email} 1250 - Payment Date: {payment_date} 1251 - Form: {form_title} 1252 1253 Please check the transaction details in your admin panel.', 'formpays-pro' ), 1254 'enabled' => true, 1255 ), 1256 ); 1257 1258 // Merge with defaults 1259 $email_templates = array(); 1260 foreach ( $default_templates as $key => $default ) { 1261 $email_templates[ $key ] = isset( $email_settings[ $key ] ) ? wp_parse_args( $email_settings[ $key ], $default ) : $default; 1262 } 1263 1264 // Get admin email settings 1265 $admin_email = isset( $email_settings['admin_email'] ) ? $email_settings['admin_email'] : get_option( 'admin_email' ); 1266 $from_name = isset( $email_settings['from_name'] ) ? $email_settings['from_name'] : get_bloginfo( 'name' ); 1267 $from_email = isset( $email_settings['from_email'] ) ? $email_settings['from_email'] : get_option( 'admin_email' ); 1268 1269 // Include the email notifications view 1270 include FORMPAYS_PRO_PLUGIN_DIR . 'admin/views/email-notifications.php'; 1271 } 1272 1273 /** 1274 * Handle email settings save 1275 */ 1276 private function handle_email_settings_save() { 1277 if ( ! current_user_can( 'manage_options' ) ) { 1278 wp_die( esc_html__( 'You do not have permission to perform this action.', 'formpays-pro' ) ); 1279 } 1280 1281 $email_settings = array(); 1282 1283 // Save admin email settings 1284 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled in email_notifications_page() 1285 $email_settings['admin_email'] = sanitize_email( wp_unslash( $_POST['admin_email'] ?? '' ) ); 1286 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled in email_notifications_page() 1287 $email_settings['from_name'] = sanitize_text_field( wp_unslash( $_POST['from_name'] ?? '' ) ); 1288 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled in email_notifications_page() 1289 $email_settings['from_email'] = sanitize_email( wp_unslash( $_POST['from_email'] ?? '' ) ); 1290 1291 // Save email templates 1292 $template_keys = array( 'payment_success_customer', 'payment_success_admin', 'payment_failed_customer', 'payment_failed_admin' ); 1293 1294 foreach ( $template_keys as $key ) { 1295 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled in email_notifications_page() 1296 $email_settings[ $key ] = array( 1297 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled in email_notifications_page() 1298 'subject' => sanitize_text_field( wp_unslash( $_POST[ $key . '_subject' ] ?? '' ) ), 1299 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled in email_notifications_page() 1300 'message' => wp_kses_post( wp_unslash( $_POST[ $key . '_message' ] ?? '' ) ), 1301 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification handled in email_notifications_page() 1302 'enabled' => isset( $_POST[ $key . '_enabled' ] ), 1303 ); 1304 } 1305 1306 // Save settings 1307 update_option( 'formpays_pro_email_settings', $email_settings ); 1308 1309 // Add success notice 1310 add_action( 'admin_notices', function() { 1311 echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Email settings saved successfully!', 'formpays-pro' ) . '</p></div>'; 1312 }); 1313 } 1134 1314 /** 1135 1315 * AJAX: Save form … … 2353 2533 } 2354 2534 } 2535 2536 /** 2537 * AJAX: Send test email 2538 */ 2539 public function ajax_send_test_email() { 2540 // Verify nonce 2541 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ?? '' ) ), 'formpays_pro_test_email' ) ) { 2542 wp_send_json_error( esc_html__( 'Security check failed.', 'formpays-pro' ) ); 2543 } 2544 2545 // Check permissions 2546 if ( ! current_user_can( 'manage_options' ) ) { 2547 wp_send_json_error( esc_html__( 'You do not have permission to perform this action.', 'formpays-pro' ) ); 2548 } 2549 2550 $test_email = isset( $_POST['test_email'] ) ? sanitize_email( wp_unslash( $_POST['test_email'] ) ) : ''; 2551 if ( empty( $test_email ) ) { 2552 wp_send_json_error( esc_html__( 'Please provide a valid email address.', 'formpays-pro' ) ); 2553 } 2554 2555 // Get email settings 2556 $email_settings = get_option( 'formpays_pro_email_settings', array() ); 2557 $from_name = isset( $email_settings['from_name'] ) ? $email_settings['from_name'] : get_bloginfo( 'name' ); 2558 $from_email = isset( $email_settings['from_email'] ) ? $email_settings['from_email'] : get_option( 'admin_email' ); 2559 2560 // Sample data for testing 2561 $sample_data = array( 2562 'transaction_id' => 'TEST-' . wp_rand( 1000, 9999 ), 2563 'amount' => '$50.00', 2564 'customer_name' => 'John Doe', 2565 'customer_email' => $test_email, 2566 'payment_date' => gmdate( 'Y-m-d H:i:s' ), 2567 'payment_method' => 'Credit Card', 2568 'form_title' => 'Sample Form', 2569 'site_name' => get_bloginfo( 'name' ), 2570 ); 2571 2572 // Test email subject and message 2573 $subject = __( 'FormPays Pro - Test Email', 'formpays-pro' ); 2574 $message = sprintf( 2575 // translators: %1$s is the site name, %2$s is the transaction ID, %3$s is the amount, %4$s is the customer name, %5$s is the payment date, %6$s is the payment method, %7$s is the site name again 2576 __( 'This is a test email from %1$s to verify that email notifications are working correctly. 2577 2578 Sample Transaction Data: 2579 - Transaction ID: %2$s 2580 - Amount: %3$s 2581 - Customer Name: %4$s 2582 - Payment Date: %5$s 2583 - Payment Method: %6$s 2584 2585 If you received this email, your email settings are configured properly. 2586 2587 Best regards, 2588 %7$s', 'formpays-pro' ), 2589 get_bloginfo( 'name' ), 2590 $sample_data['transaction_id'], 2591 $sample_data['amount'], 2592 $sample_data['customer_name'], 2593 $sample_data['payment_date'], 2594 $sample_data['payment_method'], 2595 get_bloginfo( 'name' ) 2596 ); 2597 2598 // Set headers 2599 $headers = array( 2600 'Content-Type: text/html; charset=UTF-8', 2601 'From: ' . $from_name . ' <' . $from_email . '>', 2602 ); 2603 2604 // Send test email 2605 $sent = wp_mail( $test_email, $subject, $message, $headers ); 2606 2607 if ( $sent ) { 2608 wp_send_json_success( esc_html__( 'Test email sent successfully!', 'formpays-pro' ) ); 2609 } else { 2610 wp_send_json_error( esc_html__( 'Failed to send test email. Please check your email settings.', 'formpays-pro' ) ); 2611 } 2612 } 2355 2613 } -
formpays-pro/trunk/assets/js/frontend.js
r3379943 r3385037 2477 2477 label: $selectedInput.closest('.payment-method-option-wrapper').find('.payment-method-label').text() 2478 2478 }); 2479 2480 // Recalculate amount display (amount should stay the same, just ensure display is correct) 2481 FormPaysProFrontend.calculateTotalAmount($form); 2479 2482 }, 2480 2483 -
formpays-pro/trunk/formpays-pro.php
r3379944 r3385037 4 4 * Plugin URI: https://version-next.com/formpays-pro/ 5 5 * Description: Advanced payment form with multiple payment gateways support and conditional logic 6 * Version: 1.1. 26 * Version: 1.1.3 7 7 * Author: versionnext, codexdemon 8 8 * Author URI: https://version-next.com/ … … 79 79 80 80 /** 81 * Email handler instance 82 */ 83 public $email_handler; 84 85 /** 81 86 * Admin instance 82 87 */ … … 122 127 require_once FORMPAYS_PRO_PLUGIN_DIR . 'includes/class-formpays-pro-transactions.php'; 123 128 require_once FORMPAYS_PRO_PLUGIN_DIR . 'includes/class-formpays-pro-analytics.php'; 129 require_once FORMPAYS_PRO_PLUGIN_DIR . 'includes/class-formpays-pro-email-handler.php'; 124 130 125 131 if ( is_admin() ) { … … 165 171 $this->transactions = new FormPays_Pro_Transactions(); 166 172 $this->analytics = new FormPays_Pro_Analytics(); 173 $this->email_handler = new FormPays_Pro_Email_Handler(); 167 174 168 175 if ( is_admin() ) { … … 359 366 private function get_success_page_content() { 360 367 return ' 368 <style> 369 .formpays-pro-success-page { 370 min-height: 60vh; 371 display: flex; 372 align-items: center; 373 justify-content: center; 374 padding: 40px 20px; 375 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; 376 } 377 .formpays-pro-success-page .success-container { 378 max-width: 600px; 379 width: 100%; 380 text-align: center; 381 background: #fff; 382 padding: 40px; 383 border-radius: 8px; 384 box-shadow: 0 4px 6px rgba(0,0,0,0.1); 385 } 386 .formpays-pro-success-page .success-icon { 387 margin-bottom: 20px; 388 } 389 .formpays-pro-success-page h1 { 390 color: #2c3e50; 391 margin-bottom: 15px; 392 font-size: 32px; 393 } 394 .formpays-pro-success-page > .success-container > p:first-of-type { 395 color: #7f8c8d; 396 margin-bottom: 30px; 397 font-size: 16px; 398 } 399 .formpays-pro-success-page .success-details { 400 background: #f8f9fa; 401 padding: 25px; 402 border-radius: 6px; 403 margin: 30px 0; 404 text-align: left; 405 } 406 .formpays-pro-success-page .success-details p { 407 margin: 12px 0; 408 color: #34495e; 409 font-size: 15px; 410 } 411 .formpays-pro-success-page .success-actions { 412 margin-top: 30px; 413 display: flex; 414 gap: 15px; 415 justify-content: center; 416 flex-wrap: wrap; 417 } 418 .formpays-pro-success-page .btn { 419 padding: 12px 30px; 420 border: none; 421 border-radius: 6px; 422 text-decoration: none; 423 display: inline-block; 424 font-weight: 600; 425 transition: all 0.3s ease; 426 cursor: pointer; 427 } 428 .formpays-pro-success-page .btn-primary { 429 background: #528FF0; 430 color: white; 431 } 432 .formpays-pro-success-page .btn-primary:hover { 433 background: #4278d1; 434 color: white; 435 } 436 .formpays-pro-success-page .btn-secondary { 437 background: #95a5a6; 438 color: white; 439 } 440 .formpays-pro-success-page .btn-secondary:hover { 441 background: #7f8c8d; 442 color: white; 443 } 444 </style> 445 361 446 <div class="formpays-pro-success-page"> 362 447 <div class="success-container"> … … 371 456 <div class="success-details"> 372 457 <p><strong>Transaction ID:</strong> [TRANSACTION_ID]</p> 373 <p><strong>Amount:</strong> [AMOUNT]</p> 374 <p><strong>Date:</strong> [DATE]</p> 458 <p><strong>Amount Paid:</strong> [AMOUNT]</p> 459 <p><strong>Payment Date & Time:</strong> [DATE]</p> 460 <p><strong>Customer Name:</strong> [CUSTOMER_NAME]</p> 461 <p><strong>Customer Email:</strong> [CUSTOMER_EMAIL]</p> 462 <p><strong>Payment Status:</strong> [PAYMENT_STATUS]</p> 375 463 </div> 376 464 <div class="success-actions"> 377 <a href="' . home_url() . '" class="btn btn-primary">Return to Home</a>378 <a href="mailto:' . get_option( 'admin_email') . '" class="btn btn-secondary">Contact Support</a>465 <a href="' . esc_url( home_url() ) . '" class="btn btn-primary">Return to Home</a> 466 <a href="mailto:' . esc_attr( get_option( 'admin_email' ) ) . '" class="btn btn-secondary">Contact Support</a> 379 467 </div> 380 468 </div> … … 754 842 755 843 $this->transactions->update_transaction( $transaction_id, $update_data ); 844 845 // Send success emails 846 $this->send_payment_emails( $transaction_id, 'success' ); 756 847 } else { 757 848 // Payment failed … … 764 855 ) 765 856 ); 857 858 // Send failed emails 859 $this->send_payment_emails( $transaction_id, 'failed' ); 766 860 } 767 861 … … 793 887 } 794 888 795 // Replace placeholders with actual transaction data 889 // Replace placeholders with actual transaction data. 890 // Use updated_at for payment time (which is when status was updated), fallback to created_at if not available. 891 $payment_timestamp = ! empty( $transaction->updated_at ) ? $transaction->updated_at : $transaction->created_at; 892 796 893 $replacements = array( 797 894 '[TRANSACTION_ID]' => $transaction->transaction_id, 798 895 '[AMOUNT]' => $transaction->currency . ' ' . number_format( $transaction->amount, 2 ), 799 '[DATE]' => date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $ transaction->created_at) ),896 '[DATE]' => date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $payment_timestamp ) ), 800 897 '[CUSTOMER_NAME]' => $transaction->customer_name, 801 898 '[CUSTOMER_EMAIL]' => $transaction->customer_email, … … 926 1023 return ob_get_clean(); 927 1024 } 1025 1026 /** 1027 * Send payment emails based on status 1028 * 1029 * @param int $transaction_id Transaction ID. 1030 * @param string $status Payment status ('success' or 'failed'). 1031 * @return void 1032 */ 1033 private function send_payment_emails( $transaction_id, $status ) { 1034 if ( ! isset( $this->email_handler ) ) { 1035 return; 1036 } 1037 1038 // Get transaction data 1039 $transaction = $this->transactions->get_transaction( $transaction_id ); 1040 if ( ! $transaction ) { 1041 return; 1042 } 1043 1044 // Get form data 1045 $form = $this->forms->get_form( $transaction->form_id ); 1046 if ( ! $form ) { 1047 return; 1048 } 1049 1050 // Parse form data 1051 $form_data = is_string( $transaction->form_data ) ? json_decode( $transaction->form_data, true ) : $transaction->form_data; 1052 if ( ! is_array( $form_data ) ) { 1053 $form_data = array(); 1054 } 1055 1056 // Send emails based on status 1057 if ( 'success' === $status ) { 1058 $this->email_handler->send_payment_success_customer( $transaction, $form, $form_data ); 1059 $this->email_handler->send_payment_success_admin( $transaction, $form, $form_data ); 1060 } elseif ( 'failed' === $status ) { 1061 $this->email_handler->send_payment_failed_customer( $transaction, $form, $form_data ); 1062 $this->email_handler->send_payment_failed_admin( $transaction, $form, $form_data ); 1063 } 1064 } 928 1065 } 929 1066 -
formpays-pro/trunk/includes/class-formpays-pro-forms.php
r3379943 r3385037 370 370 ); 371 371 wp_add_inline_script( 'formpays-pro-frontend', $form_init_script ); 372 373 // Initialize payment method and amount display for forms with payment methods 374 if ( ! empty( $form->payment_methods ) && is_array( $form->payment_methods ) && ( ! isset( $form->payment_collection ) || $form->payment_collection !== 'disabled' ) ) { 375 $payment_init_script = sprintf( 376 'jQuery(document).ready(function($) { 377 var $form = $("#formpays_pro_form_%s"); 378 // Wait a bit for the form to be fully initialized 379 setTimeout(function() { 380 // Set default payment method data if not already set 381 if (!$form.data("selected-payment-method")) { 382 var $firstMethod = $form.find("input[name=\'payment_method\']:checked"); 383 if ($firstMethod.length) { 384 $form.data("selected-payment-method", $firstMethod.val()); 385 } 386 } 387 // Ensure amount is calculated and displayed 388 if (typeof FormPaysProFrontend.calculateTotalAmount === "function") { 389 FormPaysProFrontend.calculateTotalAmount($form); 390 } 391 }, 100); 392 });', 393 esc_js( $form_id ) 394 ); 395 wp_add_inline_script( 'formpays-pro-frontend', $payment_init_script ); 396 } 372 397 ?> 373 398 <?php endif; ?> … … 693 718 } 694 719 720 // Capture selected payment method if present. 721 $selected_payment_method = ''; 722 if ( isset( $_POST['payment_method'] ) && ! empty( $_POST['payment_method'] ) ) { 723 $selected_payment_method = sanitize_text_field( wp_unslash( $_POST['payment_method'] ) ); 724 } 725 695 726 // Validate form data with extracted field data only 696 727 $validation_result = $this->validate_form_data( $form, $form_field_data ); … … 716 747 ); 717 748 } else { 718 // Process payment 719 $payment_result = $this->process_payment( $form, $validation_result );749 // Process payment (pass selected payment method). 750 $payment_result = $this->process_payment( $form, $validation_result, $selected_payment_method ); 720 751 721 752 if ( is_wp_error( $payment_result ) ) { … … 1017 1048 * Process payment 1018 1049 */ 1019 private function process_payment( $form, $data ) {1050 private function process_payment( $form, $data, $selected_payment_method = '' ) { 1020 1051 global $formpays_pro; 1021 1052 … … 1055 1086 } elseif ( ! empty( $data['customer_phone'] ) ) { 1056 1087 $customer_mobile = $data['customer_phone']; 1088 } elseif ( ! empty( $data['contact'] ) ) { 1089 $customer_mobile = $data['contact']; 1057 1090 } else { 1058 1091 // No mobile field found - provide a default value … … 1061 1094 } 1062 1095 1096 // Format phone number to include country code for Razorpay 1097 $customer_mobile = $this->format_phone_number_for_razorpay( $customer_mobile ); 1098 1063 1099 // Gateway-specific field validation 1064 1100 $validation_result = $this->validate_gateway_requirements( $form->gateway, $data ); … … 1087 1123 // Create transaction record 1088 1124 $transaction_data = array( 1089 'form_id' => $form->id, 1090 'transaction_id' => $transaction_id, 1091 'gateway_name' => $form->gateway, 1092 'customer_name' => $customer_name, 1093 'customer_email' => $customer_email, 1094 'customer_mobile' => $customer_mobile, 1095 'amount' => $payment_amount, 1096 'currency' => $form->currency, 1097 'payment_status' => 'pending', 1098 'form_data' => wp_json_encode( $data ), 1099 'ip_address' => $this->get_user_ip_address(), 1100 'user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_textarea_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '', 1125 'form_id' => $form->id, 1126 'transaction_id' => $transaction_id, 1127 'gateway_name' => $form->gateway, 1128 'customer_name' => $customer_name, 1129 'customer_email' => $customer_email, 1130 'customer_mobile' => $customer_mobile, 1131 'amount' => $payment_amount, 1132 'currency' => $form->currency, 1133 'payment_status' => 'pending', 1134 'form_data' => wp_json_encode( $data ), 1135 'ip_address' => $this->get_user_ip_address(), 1136 'user_agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_textarea_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '', 1137 'selected_payment_method' => $selected_payment_method, // Pass selected payment method to gateway. 1101 1138 ); 1102 1139 … … 1652 1689 * Get human-readable field label 1653 1690 */ 1654 private function get_field_label( $field_id ) { 1655 $field_labels = array( 1656 'customer_name' => __( 'Customer Name', 'formpays-pro' ), 1657 'customer_email' => __( 'Customer Email', 'formpays-pro' ), 1658 'customer_mobile' => __( 'Customer Phone', 'formpays-pro' ), 1659 'form_id' => __( 'Form ID', 'formpays-pro' ), 1660 ); 1661 1662 return isset( $field_labels[ $field_id ] ) ? $field_labels[ $field_id ] : ucfirst( str_replace( '_', ' ', $field_id ) ); 1663 } 1664 } 1691 private function get_field_label( $field_id ) { 1692 $field_labels = array( 1693 'customer_name' => __( 'Customer Name', 'formpays-pro' ), 1694 'customer_email' => __( 'Customer Email', 'formpays-pro' ), 1695 'customer_mobile' => __( 'Customer Phone', 'formpays-pro' ), 1696 'form_id' => __( 'Form ID', 'formpays-pro' ), 1697 ); 1698 1699 return isset( $field_labels[ $field_id ] ) ? $field_labels[ $field_id ] : ucfirst( str_replace( '_', ' ', $field_id ) ); 1700 } 1701 1702 /** 1703 * Format phone number for Razorpay (add country code if missing) 1704 * 1705 * @param string $phone Phone number. 1706 * @return string 1707 */ 1708 private function format_phone_number_for_razorpay( $phone ) { 1709 // Remove any whitespace or special characters 1710 $phone = preg_replace( '/[^0-9+]/', '', $phone ); 1711 1712 // If phone already has country code (starts with +), return as is 1713 if ( strpos( $phone, '+' ) === 0 ) { 1714 return $phone; 1715 } 1716 1717 // If phone starts with 00, replace with + 1718 if ( strpos( $phone, '00' ) === 0 ) { 1719 return '+' . substr( $phone, 2 ); 1720 } 1721 1722 // Default: assume Indian number and add +91 1723 if ( strlen( $phone ) === 10 ) { 1724 return '+91' . $phone; 1725 } 1726 1727 // If 11 digits and starts with 0, assume Indian and add +91 1728 if ( strlen( $phone ) === 11 && substr( $phone, 0, 1 ) === '0' ) { 1729 return '+91' . substr( $phone, 1 ); 1730 } 1731 1732 // For numbers longer than 10 digits without +, assume they might have country code 1733 // Add + if not present and the number is already long enough 1734 if ( strlen( $phone ) > 10 && strpos( $phone, '+' ) === false ) { 1735 return '+' . $phone; 1736 } 1737 1738 // Return with default +91 for Indian numbers 1739 return '+91' . $phone; 1740 } 1741 } -
formpays-pro/trunk/includes/gateways/class-formpays-pro-razorpay.php
r3379943 r3385037 427 427 'description' => sprintf( 'Payment for %s', $payment_data['customer_name'] ), 428 428 'callback_url' => $callback_url, 429 'customer' => array( 430 'name' => $payment_data['customer_name'], 431 'email' => $payment_data['customer_email'], 432 'contact' => ! empty( $payment_data['customer_mobile'] ) ? $payment_data['customer_mobile'] : ( ! empty( $payment_data['customer_phone'] ) ? $payment_data['customer_phone'] : '' ), 433 ), 429 434 ); 430 435 … … 482 487 $cancel_url 483 488 ); 489 } 490 491 // Map internal payment methods to Razorpay methods. 492 $method_mapping = array( 493 'card' => 'card', 494 'upi' => 'upi', 495 'netbanking' => 'netbanking', 496 'wallet' => 'wallet', 497 'emi' => 'emi', 498 ); 499 500 // Handle selected payment method. 501 $method_options = array(); 502 if ( ! empty( $payment_data['selected_payment_method'] ) ) { 503 $selected_method = $payment_data['selected_payment_method']; 504 if ( isset( $method_mapping[ $selected_method ] ) ) { 505 $method_options = array( 506 'method' => $method_mapping[ $selected_method ], 507 ); 508 } 484 509 } 485 510 … … 495 520 'name' => $payment_data['customer_name'], 496 521 'email' => $payment_data['customer_email'], 497 'contact' => $payment_data['customer_mobile'] ?? '',522 'contact' => ! empty( $payment_data['customer_mobile'] ) ? $payment_data['customer_mobile'] : ( ! empty( $payment_data['customer_phone'] ) ? $payment_data['customer_phone'] : '' ), 498 523 ), 499 524 'notes' => array( … … 507 532 'cancel_url' => $cancel_url, 508 533 ); 534 535 // Add method filter if payment method is selected. 536 if ( ! empty( $method_options ) ) { 537 $checkout_data['method'] = $method_options['method']; 538 } 509 539 510 540 // Debug: Log checkout data (only in debug mode and not during activation)
Note: See TracChangeset
for help on using the changeset viewer.