Formidable Form自定义HelloAsso结账时frm_after_create_entry致条目重复
Formidable Form自定义HelloAsso结账动作:条目重复创建问题
我正在为Formidable Form开发自定义动作,实现用户完成HelloAsso结账流程,跳转至感谢页时完成注册。原本计划使用frm_after_create_entry钩子获取已创建的条目ID,并重定向用户到携带该ID作为参数的页面,但现在遇到条目被创建两次的问题。
以下是我的代码:
<?php require_once __DIR__ . '/../http-query-functions.php'; require_once __DIR__ . '/helloAsso-actions/HelloAssoAuthenticator.php'; class HelloAssoCheckoutAction extends FrmFormAction { private string $user_form_id; private string $access_token; private string $data_to_send_for_checkout; private array $action_parameters; private array $user_form_values; function __construct() { $action_ops = array( 'classes' => 'dashicons dashicons-format-aside', 'limit' => 99, 'priority' => 50, 'event' => array('create'), ); $this->FrmFormAction('HelloAssoCheckoutAction', __('HelloAsso Checkout', 'formidable'), $action_ops); add_filter('frm_validate_entry', array($this, 'prepare_checkout'), 10, 2); add_action('frm_after_create_entry', array($this, 'checkout'), 50, 2); add_action('init', array($this, 'register_helloasso_shortcodes')); } function register_helloasso_shortcodes() { add_shortcode('helloasso_checkout_status', array($this, 'set_checkout_status')); } function form($form_action, $args = array()) { //... HTML form to set action parameters } function get_defaults() { return array( 'template_name' => '', 'my_content' => '', ); } function prepare_checkout($errors, $values) { $this->user_form_id = $values['form_id']; $form_actions = FrmFormAction::get_action_for_form($this->user_form_id, 'helloassocheckoutaction'); if (empty($form_actions)) { return; } $form_action = reset($form_actions); $this->action_parameters = $form_action->post_content; $this->user_form_values = $values; $this->connect_to_hello_asso($this->action_parameters['token_endpoint'], $this->action_parameters['client_id'], $this->action_parameters['client_secret']); return $errors; } private function connect_to_hello_asso($token_endpoint, $client_id, $client_secret) { $helloAsso_ahthenticator = new HelloAssoAuthenticator(); $this->access_token = $helloAsso_ahthenticator->get_access_token($token_endpoint, $client_id, $client_secret); } function checkout($entry_id, $form_id) { $form_actions = FrmFormAction::get_action_for_form($form_id, 'helloassocheckoutaction'); if (empty($form_actions)) { echo 'No action for this form, return errors'; return; } $this->set_post_data($entry_id); $this->redirect_to_helloAsso_checkout($this->action_parameters['checkout_endpoint'], $this->access_token, $this->data_to_send_for_checkout); } private function set_post_data($entry_id) { $this->data_to_send_for_checkout = json_encode(array( "totalAmount" => $this->action_parameters['initial_amount'] * 100, // Amount in cents "initialAmount" => $this->action_parameters['initial_amount'] * 100, "itemName" => $this->action_parameters['campain_name'], "backUrl" => sanitize_url($this->action_parameters['back_url']), "errorUrl" => sanitize_url($this->action_parameters['error_url']), "returnUrl" => sanitize_url($this->action_parameters['success_url'] . "?entry=" . $entry_id), "containsDonation" => true, "payer" => array( "firstName" => sanitize_text_field($this->user_form_values['item_meta'][$this->action_parameters['name_field']]['first']), "lastName" => sanitize_text_field($this->user_form_values['item_meta'][$this->action_parameters['name_field']]['last']), "email" => sanitize_email($this->user_form_values['item_meta'][$this->action_parameters['mail_field']]), "dateOfBirth" => sanitize_text_field($this->user_form_values['item_meta'][$this->action_parameters['birthdate_field']]), "address" => sanitize_text_field($this->user_form_values['item_meta'][$this->action_parameters['address_field']]['line1']), "city" => sanitize_text_field($this->user_form_values['item_meta'][$this->action_parameters['address_field']]['city']), "zipCode" => sanitize_text_field($this->user_form_values['item_meta'][$this->action_parameters['address_field']]['zip']), "country" => "FRA" ) ), true); } private function redirect_to_helloAsso_checkout($checkout_endpoint, $access_token, $form_data_json) { $response = create_curl_post_and_return_json_response($checkout_endpoint, $form_data_json, array( 'Content-Type: application/json', 'Authorization: Bearer ' . $access_token )); if (isset($response['error'])) { throw new Exception($response['error'] . ' ' . $response['message']); } header('Location: ' . wp_sanitize_redirect($response['redirectUrl'])); } function set_checkout_status($atts) { if (isset($_GET['entry']) && isset($_GET['orderId']) && isset($_GET['code'])) { echo "paiement status for entry " . $_GET['entry'] . " is " . $_GET['code'] . " for order " . $_GET['orderId']; //TODO update the entry status } else { echo "no entry id or code or order id"; } } }
为确认问题源于frm_after_create_entry的使用,我进行了以下测试:
- 移除该钩子后,条目仅保存一次;
- 保留钩子但移除逻辑仅留占位代码,问题仍存在;
- 尝试添加条目存在性检查以避免重复,但返回URL中的条目ID不正确。
我已寻找其他可获取条目ID的动作钩子,但未找到合适的替代方案。我并非PHP和WordPress技术栈的开发者,开发过程中大量借助了大语言模型。
内容的提问来源于stack exchange,提问作者Maxime MOHANDI
相关产品推荐
相关产品推荐

