如何在WooCommerce订单邮件中加入与FileMaker匹配的JS生成许可证号?
问题
我需要在WordPress(WooCommerce)站点上生成与独立无服务器FileMaker数据库完全一致的许可证号,并在订单完成时通过邮件发送给客户。Web端与FileMaker唯一通用的语言是JavaScript,我已在FileMaker中通过网页视图抓取客户姓名生成许可证号,但在网站上实现匹配流程的尝试全部失败。
核心疑问:能否用JavaScript生成许可证号,并将结果纳入WooCommerce订单完成邮件?
已尝试的方案及问题
- 将FileMaker的许可证生成逻辑转译为PHP并添加到主题
functions.php:能生成并发送许可证号,但生成的号码与FileMaker内JS或原生生成的完全不匹配。 - 尝试通过PHP调用JavaScript生成许可证号再发送邮件(使用
functions.php、代码片段或自制插件):完全无效,且无法生成调试文件排查问题。
现有代码片段
PHP代码(用于调用JS的后端逻辑)
add_action('wp_enqueue_scripts', 'enqueue_custom_js'); function enqueue_custom_js() { wp_enqueue_script('custom-reg-code-js', plugin_dir_url(__FILE__) . 'reg-code.js', array('jquery'), null, true); wp_localize_script('custom-reg-code-js', 'customData', array( 'ajaxUrl' => admin_url('admin-ajax.php'), )); } add_action('wp_ajax_custom_send_email', 'custom_send_email'); add_action('wp_ajax_nopriv_custom_send_email', 'custom_send_email'); function custom_send_email() { $regName = sanitize_text_field($_POST['regName']); $users = intval($_POST['users']); $email = sanitize_email($_POST['email']); $regCode = sanitize_text_field($_POST['regCode']); error_log("Received AJAX: RegName - $regName, Users - $users, Email - $email, RegCode - $regCode"); if (empty($regCode) || empty($email)) { error_log("Registration code or email is empty."); wp_send_json_error('Registration code or email is empty.'); return; } $email_sent = send_registration_email($email, $regName, $regCode); if ($email_sent) { error_log("Email sent successfully."); wp_send_json_success('Email sent successfully.'); } else { error_log("Failed to send email."); wp_send_json_error('Failed to send email.'); } } function send_registration_email($to, $name, $registration_code) { $subject = 'Your Registration Code New'; $message = "<html><body><h2>Thank you for your purchase!</h2><p>Dear {$name},</p><p>Your registration code is: <strong>{$registration_code}</strong></p><p>Please use this code to activate your new software.</p><p>If you have any questions, please don't hesitate to contact our support team.</p><p>Best regards,<br>Your Company Name</p></body></html>"; $headers = array('Content-Type: text/html; charset=UTF-8'); return wp_mail($to, $subject, $message, $headers); }
JavaScript代码(许可证生成逻辑)
function generateRegistrationCode(regName, users) { const solutionKey = 'tcuXd6A4WQ'; if (!regName || !solutionKey) { console.error('Registration name or solution key is empty.'); return ''; } // Always append users (which is set to 1) regName += users; let len = regName.length; let chr = 0, pos = 0; for (let loop = 0; loop < len; loop++) { const ascii = regName.charCodeAt(loop); chr += ascii; pos += (ascii * (loop + 1)); } const sum = chr + pos + len; const numString = `${sum}${pos}${chr}${len}${sum * sum}`; let codePreFormatted = ''; let loop = 0; while (loop < numString.length) { const convertNum = (parseInt(numString.substr(loop, 2)) > 56) ? parseInt(numString.substr(loop, 1)) : parseInt(numString.substr(loop, 2)); codePreFormatted += (convertNum == 0) ? solutionKey[0] + solutionKey[1] : solutionKey[convertNum]; loop += convertNum.toString().length; } let codeFormatted = ''; for (let loop = 0; loop < codePreFormatted.length; loop += 4) { if (codeFormatted) codeFormatted += '-'; codeFormatted += codePreFormatted.substr(loop, 4); } // Append users (always 1) to the final code codeFormatted += `-[${users}]`; console.log(`Generated registration code: ${codeFormatted}`); // Append the registration code to the checkout page document.getElementById('registration-code-display').innerText = codeFormatted || 'Registration code generation failed.'; return codeFormatted; } // Send registration code via AJAX function sendRegistrationCode(email, regName, users) { const regCode = generateRegistrationCode(regName, users); if (!regCode) { alert("Registration code generation failed. Please check the input."); console.error("Failed to generate registration code."); return; } // Perform AJAX request to send the email jQuery.ajax({ url: customData.ajaxUrl, method: 'POST', data: { action: 'custom_send_email', regName: regName, users: users, email: email, regCode: regCode, }, success: function(response) { if (response.success) { alert('Registration code sent successfully!'); } else { alert('Failed to send the registration code: ' + response.data); console.error('Failed to send the registration code:', response.data); } }, error: function(xhr, status, error) { alert('An error occurred: ' + error); console.error('AJAX error:', error); } }); }
额外说明
- JavaScript代码中的
users参数可移除,因为当前始终仅1个用户。 - 客户付款后订单会自动完成。
可行解决方案
由于PHP转译逻辑无法匹配FileMaker的结果,建议直接复用已验证的JavaScript生成逻辑,通过以下两种方式实现:
方案1:使用PHP的V8JS扩展(服务器支持时优先)
若服务器安装了v8js扩展,可直接在PHP后端执行JS生成逻辑,确保与FileMaker结果一致:
add_action('woocommerce_order_status_completed', 'generate_and_send_license_on_completion', 10, 1); function generate_and_send_license_on_completion($order_id) { $order = wc_get_order($order_id); $email = $order->get_billing_email(); $regName = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(); $users = 1; // 固定为1,可移除 // 复用FileMaker验证过的JS逻辑 $js_code = <<<JS function generateRegistrationCode(regName, users) { const solutionKey = 'tcuXd6A4WQ'; if (!regName || !solutionKey) { return ''; } regName += users; let len = regName.length; let chr = 0, pos = 0; for (let loop = 0; loop < len; loop++) { const ascii = regName.charCodeAt(loop); chr += ascii; pos += (ascii * (loop + 1)); } const sum = chr + pos + len; const numString = `${sum}${pos}${chr}${len}${sum * sum}`; let codePreFormatted = ''; let loop = 0; while (loop < numString.length) { const convertNum = (parseInt(numString.substr(loop, 2)) > 56) ? parseInt(numString.substr(loop, 1)) : parseInt(numString.substr(loop, 2)); codePreFormatted += (convertNum == 0) ? solutionKey[0] + solutionKey[1] : solutionKey[convertNum]; loop += convertNum.toString().length; } let codeFormatted = ''; for (let loop = 0; loop < codePreFormatted.length; loop += 4) { if (codeFormatted) codeFormatted += '-'; codeFormatted += codePreFormatted.substr(loop, 4); } codeFormatted += `-[${users}]`; return codeFormatted; } generateRegistrationCode('{$regName}', {$users}); JS; $v8 = new V8Js(); $regCode = $v8->executeString($js_code); // 发送邮件并保存许可证到订单备注 if (!empty($regCode) && !empty($email)) { send_registration_email($email, $regName, $regCode); $order->add_order_note('Generated license code: ' . $regCode); $order->save(); } }
方案2:前端订单完成页面触发(适合无法安装V8JS的情况)
修改前端逻辑,在订单完成页面自动触发许可证生成和邮件发送:
- 更新JavaScript代码,监听订单完成页面加载:
jQuery(document).ready(function() { // 检测是否为订单完成页面 if (jQuery('body').hasClass('woocommerce-order-received')) { // 从页面获取订单信息 const email = jQuery('.woocommerce-customer-details .email').text().trim(); const regName = jQuery('.woocommerce-customer-details .name').text().trim(); const users = 1; // 生成并发送许可证号 sendRegistrationCode(email, regName, users); } });
- 在PHP中添加订单完成页面的必要数据支持:
add_action('woocommerce_thankyou', 'add_order_data_for_license_generation', 10, 1); function add_order_data_for_license_generation($order_id) { $order = wc_get_order($order_id); // 确保页面元素包含订单信息 echo '<div class="woocommerce-customer-details"> <p class="name">' . esc_html($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()) . '</p> <p class="email">' . esc_html($order->get_billing_email()) . '</p> </div>'; }
内容的提问来源于stack exchange,提问作者Richard Morley
相关产品推荐
相关产品推荐

