namespace = CF7PA_ADDONS_REST_API . 'admin'; $this->rest_base = 'settings'; } public function register_routes() { register_rest_route( $this->namespace, $this->rest_base, array( array( 'methods' => \WP_REST_Server::READABLE, 'callback' => array($this, 'get_settings'), 'permission_callback' => array($this, 'verify_admin'), ), array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array($this, 'update_settings'), 'permission_callback' => array($this, 'verify_admin'), ), ) ); register_rest_route( $this->namespace, $this->rest_base . '/import-test', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array($this, 'import_test_settings'), 'permission_callback' => array($this, 'verify_admin'), ), ) ); register_rest_route( $this->namespace, $this->rest_base . '/test-webhook-connection', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array($this, 'test_webhook_connection'), 'permission_callback' => array($this, 'verify_admin'), ), ) ); register_rest_route( $this->namespace, $this->rest_base . '/create-webhook-endpoint', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array($this, 'create_webhook_endpoint'), 'permission_callback' => array($this, 'verify_admin'), ), ) ); register_rest_route( $this->namespace, 'templates/import', array( array( 'methods' => \WP_REST_Server::CREATABLE, 'callback' => array($this, 'import_template'), 'permission_callback' => array($this, 'verify_admin'), 'args' => array( 'index' => array( 'required' => true, 'type' => 'integer', 'sanitize_callback' => 'absint', ), ), ), ) ); } /** * Import a CF7 template: creates a wpcf7_contact_form post and writes * Stripe payment settings meta so the form is immediately configured. * * @param \WP_REST_Request $request * @return \WP_REST_Response|\WP_Error */ public function import_template( \WP_REST_Request $request ) { $index = (int) $request->get_param( 'index' ); $json_path = CF7PA_ADDONS_PATH . 'includes/templates/cf7/templates.json'; if ( ! file_exists( $json_path ) ) { return new \WP_Error( 'not_found', 'Templates file not found.', array( 'status' => 404 ) ); } $templates = json_decode( file_get_contents( $json_path ), true ); if ( ! isset( $templates[ $index ] ) ) { return new \WP_Error( 'not_found', 'Template not found.', array( 'status' => 404 ) ); } $template = $templates[ $index ]; if ( 'pro' === $template['plan'] && ! \CF7PA_Pay_Addons\Shared\Security_Utils::is_pro() ) { return new \WP_Error( 'forbidden', 'A Pro licence is required for this template.', array( 'status' => 403 ) ); } $form_id = wp_insert_post( array( 'post_title' => sanitize_text_field( $template['name'] ), 'post_status' => 'publish', 'post_type' => 'wpcf7_contact_form', ) ); if ( is_wp_error( $form_id ) ) { return new \WP_Error( 'create_failed', 'Failed to create the contact form.', array( 'status' => 500 ) ); } update_post_meta( $form_id, '_form', $template['form_code'] ); update_post_meta( $form_id, '_locale', get_locale() ); $domain = wp_parse_url( get_bloginfo( 'url' ), PHP_URL_HOST ); $default_sender = get_bloginfo( 'name' ) . ' '; update_post_meta( $form_id, '_mail', array( 'active' => true, 'recipient' => '[_site_admin_email]', 'subject' => get_bloginfo( 'name' ) . ': ' . sanitize_text_field( $template['name'] ), 'sender' => $default_sender, 'body' => "From: [your-name] <[your-email]>\n\n[your-message]\n\n--\nThis e-mail was sent from a contact form on [_site_title] ([_site_url])", 'additional_headers' => 'Reply-To: [your-email]', 'attachments' => '', 'use_html' => false, 'exclude_blank' => false, ) ); if ( ! empty( $template['payment_settings'] ) ) { $ps = $template['payment_settings']; if ( ! empty( $ps['redirect_setting'] ) ) { update_post_meta( $form_id, 'cf7pa_checkout_redirect_setting', $ps['redirect_setting'] ); } if ( ! empty( $ps['form_setting'] ) ) { update_post_meta( $form_id, 'cf7pa_checkout_form_setting', $ps['form_setting'] ); } } return rest_ensure_response( array( 'form_id' => $form_id, 'edit_url' => esc_url_raw( admin_url( 'admin.php?page=wpcf7&action=edit&post=' . $form_id ) ), ) ); } function verify_admin(\WP_REST_Request $request) { return Security_Utils::admin_check($request); } /** * import test setting. * * @param WP_REST_Request $request Full data about the request. */ public function import_test_settings(\WP_REST_Request $request) { $configs = self::load_config(); $config = $configs['setting']; $stripe_settings = get_option('cf7pa_stripe_settings', []); $stripe_settings['test_publishable_key'] = $config['test_key']; $stripe_settings['test_secret_key'] = $config['test_secret']; $stripe_settings['default_currency'] = $config['currency']; $stripe_settings['test_mode'] = true; update_option('cf7pa_stripe_settings', $stripe_settings); return new \WP_REST_Response($config, 200); } static function load_config() { $configs = get_transient('cf7pa_stripe_configs'); if (false === $configs || empty($configs)) { try { $response = wp_remote_get(CF7PA_PLUGIN_TEMPLATE_URL); $configs = json_decode(wp_remote_retrieve_body($response), true); set_transient('cf7pa_stripe_configs', $configs, 60 * MINUTE_IN_SECONDS); } catch (\Exception $ex) { // try again $response = wp_remote_get(CF7PA_PLUGIN_TEMPLATE_URL); $configs = json_decode(wp_remote_retrieve_body($response), true); Logger::error('fetch configs error ' . $ex->getMessage()); } } return $configs; } /** * Retrieve settings. * * @return WP_REST_Response */ public function get_settings() { $stripe_settings = get_option('cf7pa_stripe_settings', array()); $sys_settings = get_option('cf7pa_sys_settings', array()); return new \WP_REST_Response( array( 'test_mode' => $stripe_settings['test_mode'] ?? true, 'test_publishable_key' => $stripe_settings['test_publishable_key'], 'live_publishable_key' => $stripe_settings['live_publishable_key'], 'test_secret_key' => $stripe_settings['test_secret_key'], 'live_secret_key' => $stripe_settings['live_secret_key'], 'webhook_secret' => $stripe_settings['webhook_secret'], 'test_webhook_secret' => $stripe_settings['test_webhook_secret'], 'default_currency' => $stripe_settings['default_currency'] ?? 'USD', 'enable_logging' => $sys_settings['enable_logging'], 'enable_keep_data' => $sys_settings['enable_keep_data'], ) ); } /** * Update settings. * * @param WP_REST_Request $request Full data about the request. */ public function update_settings(\WP_REST_Request $request) { $params = sanitize_post($request->get_params()); $stripe_settings = get_option('cf7pa_stripe_settings', []); $stripe_settings['test_mode'] = $params['test_mode']; $stripe_settings['default_currency'] = $params['default_currency']; if ($params['test_publishable_key'] !== null) { $stripe_settings['test_publishable_key'] = $params['test_publishable_key']; } if ($params['live_publishable_key'] !== null) { $stripe_settings['live_publishable_key'] = $params['live_publishable_key']; } if ($params['test_secret_key'] !== null) { $stripe_settings['test_secret_key'] = $params['test_secret_key']; } if ($params['live_secret_key'] !== null) { $stripe_settings['live_secret_key'] = $params['live_secret_key']; } if ($params['webhook_secret'] !== null) { $stripe_settings['webhook_secret'] = $params['webhook_secret']; } if ($params['test_webhook_secret'] !== null) { $stripe_settings['test_webhook_secret'] = $params['test_webhook_secret']; } update_option('cf7pa_stripe_settings', $stripe_settings); $sys_settings = get_option('cf7pa_sys_settings', []); $sys_settings['enable_logging'] = $params['enable_logging']; $sys_settings['enable_keep_data'] = $params['enable_keep_data']; update_option('cf7pa_sys_settings', $sys_settings); return new \WP_REST_Response($params, 200); } public function test_webhook_connection(\WP_REST_Request $request) { $params = sanitize_post($request->get_params()); $secret_key = $params['secret_key']; $webhook_url = rest_url(CF7PA_ADDONS_REST_API . 'stripe/webhook'); $stripe = new \Stripe\StripeClient($secret_key); try { $endpoints = $stripe->webhookEndpoints->all(); $found = false; foreach ($endpoints->data as $endpoint) { if ($endpoint->url === $webhook_url && $endpoint->status === 'enabled') { $found = true; break; } } if ($found) { return new \WP_REST_Response(['success' => true], 200); } else { return new \WP_REST_Response(['success' => false, 'message' => 'Webhook endpoint not found. Please add webhook endpoint: ' . $webhook_url], 400); } } catch (\Exception $ex) { return new \WP_REST_Response(['success' => false, 'message' => '' . $ex->getMessage()], 400); } } public function create_webhook_endpoint(\WP_Rest_Request $request) { $params = sanitize_post($request->get_params()); $secret_key = $params['secret_key']; $webhook_url = 'https://stage.payaddons.com/wp-json/cf7pa/v1/stripe/webhook'; //rest_url(CF7PA_ADDONS_REST_API . 'stripe/webhook'); $result = []; $stripe = new \Stripe\StripeClient($secret_key); try { $endpoints = $stripe->webhookEndpoints->all(); $found = false; foreach ($endpoints->data as $endpoint) { if ($endpoint->url === $webhook_url && $endpoint->status === 'enabled') { $found = true; break; } } if ($found) { return new \WP_REST_Response(['success' => false, 'message' => __('This URL is already registered. Please check your existing webhooks in the Stripe Dashboard.', 'accept-stripe-for-contact-form-7')], 400); } $endpoint = $stripe->webhookEndpoints->create([ 'url' => $webhook_url, 'enabled_events' => [ 'checkout.session.completed', 'checkout.session.async_payment_succeeded', 'checkout.session.async_payment_failed', 'checkout.session.expired', 'payment_intent.payment_failed', 'payment_intent.succeeded', 'payment_intent.amount_capturable_updated', 'payment_intent.requires_action', 'invoice.payment_succeeded', 'invoice.payment_failed', ], ]); $result['secret'] = $endpoint->secret; $result['livemode'] = $endpoint->livemode; $stripe_settings = get_option('cf7pa_stripe_settings', []); if ($endpoint->livemode) { $stripe_settings['test_webhook_secret'] = $endpoint->secret; } else { $stripe_settings['webhook_secret'] = $endpoint->secret; } update_option('cf7pa_stripe_settings', $stripe_settings); return new \WP_REST_Response(['success' => true, 'data' => $result], 200); } catch (\Exception $ex) { return new \WP_REST_Response(['success' => false, 'message' => '' . $ex->getMessage()], 400); } } }