commit a0d918ab0d772271aa5fd4546964660710692c6b Author: MrAkells Date: Tue Feb 3 11:15:43 2026 +0200 first commit diff --git a/assets/scs-checkout.js b/assets/scs-checkout.js new file mode 100644 index 0000000..bfc5db8 --- /dev/null +++ b/assets/scs-checkout.js @@ -0,0 +1,69 @@ +(function () { + function parsePayload(element) { + var raw = element.getAttribute('data-scs') || '{}'; + try { + return JSON.parse(raw); + } catch (error) { + return null; + } + } + + function setBusy(button, busy) { + button.disabled = !!busy; + button.setAttribute('data-loading', busy ? '1' : '0'); + } + + document.addEventListener('click', function (event) { + var button = event.target.closest('.scs-checkout-button'); + if (!button) { + return; + } + + event.preventDefault(); + if (button.getAttribute('data-loading') === '1') { + return; + } + + var payload = parsePayload(button); + if (!payload || !payload.nonce) { + alert((window.scs_ajax && scs_ajax.error_text) || 'Unable to start payment.'); + return; + } + + setBusy(button, true); + + var formData = new FormData(); + formData.append('action', 'scs_create_session'); + formData.append('nonce', payload.nonce); + formData.append('payload', JSON.stringify(payload)); + + var ajaxUrl = (window.scs_ajax && scs_ajax.ajax_url) || ''; + + fetch(ajaxUrl, { + method: 'POST', + credentials: 'same-origin', + body: formData + }) + .then(function (response) { + return response.json(); + }) + .then(function (data) { + if (data && data.success && data.data && data.data.url) { + window.location.href = data.data.url; + return; + } + + var message = (data && data.data && data.data.message) + ? data.data.message + : ((window.scs_ajax && scs_ajax.error_text) || 'Unable to start payment.'); + + alert(message); + }) + .catch(function () { + alert((window.scs_ajax && scs_ajax.error_text) || 'Unable to start payment.'); + }) + .finally(function () { + setBusy(button, false); + }); + }); +})(); diff --git a/stripe-checkout-simple.php b/stripe-checkout-simple.php new file mode 100644 index 0000000..0af38ee --- /dev/null +++ b/stripe-checkout-simple.php @@ -0,0 +1,304 @@ + '', + 'success_url' => '', + 'cancel_url' => '', + 'currency' => 'usd', + 'product_name' => 'Order', + 'amount' => '', + ); + + $settings = get_option('scs_settings', array()); + if (!is_array($settings)) { + $settings = array(); + } + + return wp_parse_args($settings, $defaults); +} + +function scs_register_settings() { + register_setting('scs_settings_group', 'scs_settings', 'scs_sanitize_settings'); + + add_settings_section( + 'scs_main', + 'Stripe Checkout', + '__return_false', + 'scs_settings' + ); + + add_settings_field('scs_secret_key', 'Secret key', 'scs_field_secret_key', 'scs_settings', 'scs_main'); + add_settings_field('scs_success_url', 'Success URL', 'scs_field_success_url', 'scs_settings', 'scs_main'); + add_settings_field('scs_cancel_url', 'Cancel URL', 'scs_field_cancel_url', 'scs_settings', 'scs_main'); + add_settings_field('scs_product_name', 'Product name', 'scs_field_product_name', 'scs_settings', 'scs_main'); + add_settings_field('scs_amount', 'Price (USD)', 'scs_field_amount', 'scs_settings', 'scs_main'); +} +add_action('admin_init', 'scs_register_settings'); + +function scs_sanitize_settings($input) { + $output = array(); + $output['secret_key'] = isset($input['secret_key']) ? sanitize_text_field($input['secret_key']) : ''; + $output['success_url'] = isset($input['success_url']) ? sanitize_text_field($input['success_url']) : ''; + $output['cancel_url'] = isset($input['cancel_url']) ? sanitize_text_field($input['cancel_url']) : ''; + $output['currency'] = 'usd'; + $output['product_name'] = isset($input['product_name']) ? sanitize_text_field($input['product_name']) : ''; + $output['amount'] = isset($input['amount']) ? sanitize_text_field($input['amount']) : ''; + return $output; +} + +function scs_field_secret_key() { + $settings = scs_get_settings(); + $value = esc_attr($settings['secret_key']); + echo ''; + echo '

Use your Stripe secret key (sk_test_... or sk_live_...).

'; +} + +function scs_field_success_url() { + $settings = scs_get_settings(); + $value = esc_attr($settings['success_url']); + echo ''; + echo '

Required. You can include {CHECKOUT_SESSION_ID} in the URL.

'; +} + +function scs_field_cancel_url() { + $settings = scs_get_settings(); + $value = esc_attr($settings['cancel_url']); + echo ''; + echo '

Required.

'; +} + +function scs_field_product_name() { + $settings = scs_get_settings(); + $value = esc_attr($settings['product_name']); + echo ''; +} + +function scs_field_amount() { + $settings = scs_get_settings(); + $value = esc_attr($settings['amount']); + echo ''; + echo '

Enter the price in USD (e.g., 59.00).

'; +} + +function scs_add_admin_menu() { + add_options_page('Stripe Checkout', 'Stripe Checkout', 'manage_options', 'scs_settings', 'scs_render_settings_page'); +} +add_action('admin_menu', 'scs_add_admin_menu'); + +function scs_render_settings_page() { + echo '
'; + echo '

Stripe Checkout

'; + echo '

Use the shortcode [stripe_checkout] or pass attributes like button_text and button_class.

'; + echo '

Example:

'; + echo '

[stripe_checkout button_text="Pay now" button_class="btn btn-main"]

'; + echo '
'; + settings_fields('scs_settings_group'); + do_settings_sections('scs_settings'); + submit_button(); + echo '
'; + echo '

Author: MrAkells

'; + echo '
'; +} + +function scs_enqueue_assets() { + wp_register_script( + 'scs-checkout', + SCS_PLUGIN_URL . 'assets/scs-checkout.js', + array(), + SCS_VERSION, + true + ); + + wp_localize_script('scs-checkout', 'scs_ajax', array( + 'ajax_url' => admin_url('admin-ajax.php'), + 'error_text' => __('Unable to start payment. Please try again.', 'scs'), + )); + + wp_enqueue_script('scs-checkout'); +} + +function scs_checkout_shortcode($atts) { + $settings = scs_get_settings(); + + if (empty($settings['secret_key'])) { + if (current_user_can('manage_options')) { + return '
Stripe secret key is not configured.
'; + } + return '
Payment is unavailable.
'; + } + + $atts = shortcode_atts(array( + 'button_text' => 'Pay', + 'button_class' => '', + 'customer_email' => '', + 'client_reference_id' => '', + ), $atts, 'stripe_checkout'); + + $payload = array( + 'customer_email' => $atts['customer_email'] !== '' ? sanitize_email($atts['customer_email']) : '', + 'client_reference_id' => $atts['client_reference_id'] !== '' ? sanitize_text_field($atts['client_reference_id']) : '', + 'nonce' => wp_create_nonce('scs_create_session'), + ); + + scs_enqueue_assets(); + + $button_text = $atts['button_text'] !== '' ? sanitize_text_field($atts['button_text']) : 'Pay'; + $button_class = 'scs-checkout-button'; + if ($atts['button_class'] !== '') { + $tokens = preg_split('/\s+/', $atts['button_class']); + $tokens = array_filter($tokens); + $tokens = array_map('sanitize_html_class', $tokens); + if (!empty($tokens)) { + $button_class .= ' ' . implode(' ', $tokens); + } + } + $payload_json = esc_attr(wp_json_encode($payload)); + + return ''; +} +add_shortcode('stripe_checkout', 'scs_checkout_shortcode'); + +function scs_validate_url($url) { + $url = trim((string) $url); + if ($url === '') { + return ''; + } + + $placeholder = '{CHECKOUT_SESSION_ID}'; + $test_url = str_replace($placeholder, 'TEST_SESSION_ID', $url); + $test_url = esc_url_raw($test_url); + if ($test_url === '') { + return ''; + } + + if (function_exists('wp_http_validate_url')) { + return wp_http_validate_url($test_url) ? $url : ''; + } + + return filter_var($test_url, FILTER_VALIDATE_URL) ? $url : ''; +} + +function scs_to_unit_amount($amount, $currency) { + $currency = strtolower((string) $currency); + $amount = str_replace(',', '.', trim((string) $amount)); + if ($amount === '') { + return 0; + } + + $number = floatval($amount); + if ($number <= 0) { + return 0; + } + + $zero_decimal = array('bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'ugx', 'vnd', 'vuv', 'xaf', 'xof', 'xpf'); + $multiplier = in_array($currency, $zero_decimal, true) ? 1 : 100; + + return (int) round($number * $multiplier); +} + +function scs_ajax_create_session() { + if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'scs_create_session')) { + wp_send_json_error(array('message' => 'Invalid request.'), 400); + } + + $raw_payload = isset($_POST['payload']) ? wp_unslash($_POST['payload']) : ''; + $payload = json_decode($raw_payload, true); + + if (!is_array($payload)) { + $payload = array(); + } + + $settings = scs_get_settings(); + $secret_key = $settings['secret_key']; + + if (empty($secret_key)) { + wp_send_json_error(array('message' => 'Stripe secret key is not configured.'), 400); + } + + $amount = $settings['amount']; + $currency = 'usd'; + $name = $settings['product_name']; + + $success_url = scs_validate_url($settings['success_url']); + $cancel_url = scs_validate_url($settings['cancel_url']); + + if ($success_url === '' || $cancel_url === '') { + wp_send_json_error(array('message' => 'Success and cancel URLs are required.'), 400); + } + + $body = array( + 'mode' => 'payment', + 'success_url' => $success_url, + 'cancel_url' => $cancel_url, + ); + + if (!empty($payload['customer_email'])) { + $body['customer_email'] = sanitize_email($payload['customer_email']); + } + + if (!empty($payload['client_reference_id'])) { + $body['client_reference_id'] = sanitize_text_field($payload['client_reference_id']); + } + + $unit_amount = scs_to_unit_amount($amount, $currency); + if ($unit_amount <= 0 || $name === '') { + wp_send_json_error(array('message' => 'Provide a valid amount and product name in settings.'), 400); + } + + $body['line_items[0][price_data][currency]'] = $currency; + $body['line_items[0][price_data][unit_amount]'] = $unit_amount; + $body['line_items[0][price_data][product_data][name]'] = $name; + $body['line_items[0][quantity]'] = 1; + + $response = wp_remote_post('https://api.stripe.com/v1/checkout/sessions', array( + 'headers' => array( + 'Authorization' => 'Bearer ' . $secret_key, + ), + 'body' => $body, + 'timeout' => 60, + )); + + if (is_wp_error($response)) { + wp_send_json_error(array('message' => $response->get_error_message()), 500); + } + + $status = wp_remote_retrieve_response_code($response); + $response_body = wp_remote_retrieve_body($response); + $data = json_decode($response_body, true); + + if ($status < 200 || $status >= 300) { + $message = 'Stripe error.'; + if (is_array($data) && isset($data['error']['message'])) { + $message = $data['error']['message']; + } + wp_send_json_error(array('message' => $message), 400); + } + + if (!is_array($data) || empty($data['url'])) { + wp_send_json_error(array('message' => 'Stripe did not return a Checkout URL.'), 500); + } + + wp_send_json_success(array('url' => $data['url'])); +} +add_action('wp_ajax_scs_create_session', 'scs_ajax_create_session'); +add_action('wp_ajax_nopriv_scs_create_session', 'scs_ajax_create_session'); + + + +