From 6d797ef6866db76ca15a2194507b924c9cc08714 Mon Sep 17 00:00:00 2001 From: jknapp Date: Fri, 29 Aug 2025 18:54:14 -0700 Subject: [PATCH] Adding more functionality --- .../page-2025-08-29T02-49-20-380Z.png | Bin 0 -> 171859 bytes CLAUDE.md | 4 +- admin/class-wpdd-admin-payouts.php | 413 +++++++++ admin/class-wpdd-admin.php | 381 ++++++++- admin/class-wpdd-settings.php | 409 +++++++-- admin/views/order-details.php | 261 ++++++ assets/js/admin-payouts.js | 124 +++ docs/developer-integration-guide.md | 420 ++++++++++ includes/class-wpdd-api.php | 785 ++++++++++++++++++ includes/class-wpdd-install.php | 105 ++- includes/class-wpdd-license-manager.php | 399 +++++++++ includes/class-wpdd-metaboxes.php | 200 +++++ includes/class-wpdd-paypal.php | 24 +- includes/class-wpdd-setup.php | 169 ++++ includes/wpdd-plugin-updater.php | 471 +++++++++++ tests/webhook-samples.md | 136 +++ wp-digital-download.php | 21 + 17 files changed, 4237 insertions(+), 85 deletions(-) create mode 100644 .playwright-mcp/page-2025-08-29T02-49-20-380Z.png create mode 100644 admin/views/order-details.php create mode 100644 assets/js/admin-payouts.js create mode 100644 docs/developer-integration-guide.md create mode 100644 includes/class-wpdd-api.php create mode 100644 includes/class-wpdd-license-manager.php create mode 100644 includes/class-wpdd-setup.php create mode 100644 includes/wpdd-plugin-updater.php create mode 100644 tests/webhook-samples.md diff --git a/.playwright-mcp/page-2025-08-29T02-49-20-380Z.png b/.playwright-mcp/page-2025-08-29T02-49-20-380Z.png new file mode 100644 index 0000000000000000000000000000000000000000..7cdba0fc9e34842b62d9f72568c38410b04797f6 GIT binary patch literal 171859 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%0D;}x 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 z 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 literal 0 HcmV?d00001 diff --git a/CLAUDE.md b/CLAUDE.md index e96e5e2..b844676 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -139,4 +139,6 @@ Plugin automatically includes `wpdd_product` post type in WordPress search resul ### PayPal Sandbox Customer Credentials These are sandbox only PayPal Test account. The credentials should be used to test the purchase process. - sb-a7cpw45634739@personal.example.com -- 3[I$ppb? \ No newline at end of file +- 3[I$ppb? +- When copying files to ~/remote-sftp you MUST check if the file "THIS-IS-REMOTE" exists. If it does not exist, tell the user they need to mount the remote path. +- When using the playwright MCP, please use headless if possible. \ No newline at end of file diff --git a/admin/class-wpdd-admin-payouts.php b/admin/class-wpdd-admin-payouts.php index 3ba64db..35beedc 100644 --- a/admin/class-wpdd-admin-payouts.php +++ b/admin/class-wpdd-admin-payouts.php @@ -10,6 +10,10 @@ class WPDD_Admin_Payouts { add_action('admin_menu', array(__CLASS__, 'add_menu_page')); add_action('admin_post_wpdd_process_payout', array(__CLASS__, 'process_payout')); add_action('admin_post_wpdd_bulk_payouts', array(__CLASS__, 'process_bulk_payouts')); + add_action('admin_post_wpdd_process_payout_request', array(__CLASS__, 'process_payout_request')); + add_action('admin_post_wpdd_reject_payout_request', array(__CLASS__, 'reject_payout_request')); + add_action('admin_post_wpdd_manual_payout', array(__CLASS__, 'process_manual_payout')); + add_action('admin_post_wpdd_adjust_balance', array(__CLASS__, 'adjust_creator_balance')); add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts')); } @@ -50,6 +54,15 @@ class WPDD_Admin_Payouts { $currency = get_option('wpdd_currency', 'USD'); $threshold = floatval(get_option('wpdd_payout_threshold', 0)); + // Get payout requests (requested status) + $payout_requests = $wpdb->get_results( + "SELECT p.*, u.display_name, u.user_email + FROM {$wpdb->prefix}wpdd_payouts p + INNER JOIN {$wpdb->users} u ON p.creator_id = u.ID + WHERE p.status = 'requested' + ORDER BY p.created_at ASC" + ); + // Get payout history $query = "SELECT p.*, u.display_name, u.user_email FROM {$wpdb->prefix}wpdd_payouts p @@ -81,9 +94,172 @@ class WPDD_Admin_Payouts {

+ +
+

+
+ +
+

()

+

+ + + + + + + + + + + + + + + + + + + + + + +
+ display_name); ?>
+ user_email); ?> +
amount, $request->currency); ?>paypal_email); ?>created_at))); ?> +
+ + + id, 'wpdd_nonce'); ?> + +
+
+ + + id, 'wpdd_nonce'); ?> + +
+
+
+ + + +
+ +
+

+

+ +
+ + + + + + + + + + + + + + + + +
+ +
+ + +
+ +
+ +

+ +

+
+
+ + +
+

+

+ +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + +
+ +
+ +

+ +

+
+
+
+

@@ -432,4 +608,241 @@ class WPDD_Admin_Payouts { return false; } } + + public static function process_payout_request() { + if (!current_user_can('manage_options')) { + wp_die(__('You do not have permission to perform this action.', 'wp-digital-download')); + } + + $payout_id = isset($_POST['payout_id']) ? intval($_POST['payout_id']) : 0; + + if (!$payout_id || !wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_process_payout_request_' . $payout_id)) { + wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error')); + exit; + } + + global $wpdb; + + // Get the payout request + $payout = $wpdb->get_row($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_payouts WHERE id = %d AND status = 'requested'", + $payout_id + )); + + if (!$payout) { + wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error')); + exit; + } + + // Process via PayPal API + $result = WPDD_PayPal_Payouts::process_payout($payout_id); + + if ($result['success']) { + // Update payout status + $wpdb->update( + $wpdb->prefix . 'wpdd_payouts', + array( + 'status' => 'completed', + 'transaction_id' => $result['transaction_id'], + 'processed_by' => get_current_user_id(), + 'processed_at' => current_time('mysql') + ), + array('id' => $payout_id), + array('%s', '%s', '%d', '%s'), + array('%d') + ); + + wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=success')); + } else { + // Update with error + $wpdb->update( + $wpdb->prefix . 'wpdd_payouts', + array( + 'status' => 'failed', + 'notes' => $result['error'] + ), + array('id' => $payout_id), + array('%s', '%s'), + array('%d') + ); + + wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error')); + } + exit; + } + + public static function reject_payout_request() { + if (!current_user_can('manage_options')) { + wp_die(__('You do not have permission to perform this action.', 'wp-digital-download')); + } + + $payout_id = isset($_POST['payout_id']) ? intval($_POST['payout_id']) : 0; + + if (!$payout_id || !wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_reject_payout_request_' . $payout_id)) { + wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error')); + exit; + } + + global $wpdb; + + // Get the payout request + $payout = $wpdb->get_row($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_payouts WHERE id = %d AND status = 'requested'", + $payout_id + )); + + if (!$payout) { + wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error')); + exit; + } + + // Update status to failed/rejected + $wpdb->update( + $wpdb->prefix . 'wpdd_payouts', + array( + 'status' => 'failed', + 'notes' => 'Request rejected by administrator', + 'processed_by' => get_current_user_id(), + 'processed_at' => current_time('mysql') + ), + array('id' => $payout_id), + array('%s', '%s', '%d', '%s'), + array('%d') + ); + + // Restore balance to creator + update_user_meta($payout->creator_id, 'wpdd_creator_balance', $payout->amount); + + wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=success')); + exit; + } + + public static function process_manual_payout() { + if (!current_user_can('manage_options') || + !wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_manual_payout')) { + wp_die(__('Security check failed', 'wp-digital-download')); + } + + $creator_id = intval($_POST['creator_id']); + $amount = floatval($_POST['payout_amount']); + $reason = sanitize_textarea_field($_POST['payout_reason']); + + if (!$creator_id || $amount <= 0) { + wp_redirect(add_query_arg('message', 'error', wp_get_referer())); + exit; + } + + $creator = get_userdata($creator_id); + if (!$creator || !in_array('wpdd_creator', $creator->roles)) { + wp_redirect(add_query_arg('message', 'error', wp_get_referer())); + exit; + } + + $paypal_email = get_user_meta($creator_id, 'wpdd_paypal_email', true); + if (empty($paypal_email)) { + wp_redirect(add_query_arg('message', 'error', wp_get_referer())); + exit; + } + + global $wpdb; + + // Create the payout record + $result = $wpdb->insert( + $wpdb->prefix . 'wpdd_payouts', + array( + 'creator_id' => $creator_id, + 'amount' => $amount, + 'currency' => get_option('wpdd_currency', 'USD'), + 'paypal_email' => $paypal_email, + 'status' => 'pending', + 'payout_method' => 'manual', + 'notes' => $reason, + 'created_at' => current_time('mysql'), + 'processed_by' => get_current_user_id() + ), + array('%d', '%f', '%s', '%s', '%s', '%s', '%s', '%s', '%d') + ); + + if (!$result) { + wp_redirect(add_query_arg('message', 'error', wp_get_referer())); + exit; + } + + $payout_id = $wpdb->insert_id; + + // Try to process via PayPal + if (class_exists('WPDD_PayPal_Payouts')) { + $paypal_result = WPDD_PayPal_Payouts::process_payout($payout_id); + + if (!$paypal_result) { + // Update status to failed + $wpdb->update( + $wpdb->prefix . 'wpdd_payouts', + array('status' => 'failed'), + array('id' => $payout_id), + array('%s'), + array('%d') + ); + } + } + + wp_redirect(add_query_arg('message', 'success', wp_get_referer())); + exit; + } + + public static function adjust_creator_balance() { + if (!current_user_can('manage_options') || + !wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_adjust_balance')) { + wp_die(__('Security check failed', 'wp-digital-download')); + } + + $creator_id = intval($_POST['creator_id']); + $adjustment_type = sanitize_text_field($_POST['adjustment_type']); + $amount = floatval($_POST['adjustment_amount']); + $reason = sanitize_textarea_field($_POST['adjustment_reason']); + + if (!$creator_id || $amount <= 0 || !in_array($adjustment_type, array('add', 'subtract'))) { + wp_redirect(add_query_arg('message', 'error', wp_get_referer())); + exit; + } + + $creator = get_userdata($creator_id); + if (!$creator || !in_array('wpdd_creator', $creator->roles)) { + wp_redirect(add_query_arg('message', 'error', wp_get_referer())); + exit; + } + + // Get current balance + $current_balance = floatval(get_user_meta($creator_id, 'wpdd_balance', true)); + + // Calculate new balance + if ($adjustment_type === 'add') { + $new_balance = $current_balance + $amount; + } else { + $new_balance = max(0, $current_balance - $amount); // Don't allow negative balance + } + + // Update the balance + update_user_meta($creator_id, 'wpdd_balance', $new_balance); + + // Create a record of this adjustment + global $wpdb; + $wpdb->insert( + $wpdb->prefix . 'wpdd_balance_adjustments', + array( + 'creator_id' => $creator_id, + 'adjustment_type' => $adjustment_type, + 'amount' => $amount, + 'previous_balance' => $current_balance, + 'new_balance' => $new_balance, + 'reason' => $reason, + 'adjusted_by' => get_current_user_id(), + 'created_at' => current_time('mysql') + ), + array('%d', '%s', '%f', '%f', '%f', '%s', '%d', '%s') + ); + + wp_redirect(add_query_arg('message', 'balance_adjusted', wp_get_referer())); + exit; + } } \ No newline at end of file diff --git a/admin/class-wpdd-admin.php b/admin/class-wpdd-admin.php index 7ef9d78..db27ba9 100644 --- a/admin/class-wpdd-admin.php +++ b/admin/class-wpdd-admin.php @@ -12,6 +12,7 @@ class WPDD_Admin { add_action('manage_wpdd_product_posts_custom_column', array(__CLASS__, 'render_product_columns'), 10, 2); add_filter('manage_edit-wpdd_product_sortable_columns', array(__CLASS__, 'make_columns_sortable')); add_action('pre_get_posts', array(__CLASS__, 'sort_products_by_column')); + add_action('pre_get_posts', array(__CLASS__, 'filter_creator_products')); add_action('admin_init', array(__CLASS__, 'handle_admin_actions')); // Initialize admin payouts @@ -21,41 +22,70 @@ class WPDD_Admin { } public static function add_admin_menus() { - add_submenu_page( - 'edit.php?post_type=wpdd_product', - __('Orders', 'wp-digital-download'), - __('Orders', 'wp-digital-download'), - 'wpdd_manage_orders', - 'wpdd-orders', - array(__CLASS__, 'render_orders_page') - ); + // Show different menus based on user role + $user = wp_get_current_user(); + $is_creator = in_array('wpdd_creator', (array) $user->roles); + $is_admin = current_user_can('manage_options'); - add_submenu_page( - 'edit.php?post_type=wpdd_product', - __('Reports', 'wp-digital-download'), - __('Reports', 'wp-digital-download'), - 'wpdd_view_reports', - 'wpdd-reports', - array(__CLASS__, 'render_reports_page') - ); + if ($is_admin) { + // Full admin menus + add_submenu_page( + 'edit.php?post_type=wpdd_product', + __('Orders', 'wp-digital-download'), + __('Orders', 'wp-digital-download'), + 'wpdd_manage_orders', + 'wpdd-orders', + array(__CLASS__, 'render_orders_page') + ); + + add_submenu_page( + 'edit.php?post_type=wpdd_product', + __('Reports', 'wp-digital-download'), + __('Reports', 'wp-digital-download'), + 'wpdd_view_reports', + 'wpdd-reports', + array(__CLASS__, 'render_reports_page') + ); + + add_submenu_page( + 'edit.php?post_type=wpdd_product', + __('Customers', 'wp-digital-download'), + __('Customers', 'wp-digital-download'), + 'wpdd_manage_orders', + 'wpdd-customers', + array(__CLASS__, 'render_customers_page') + ); + + add_submenu_page( + 'edit.php?post_type=wpdd_product', + __('Shortcodes', 'wp-digital-download'), + __('Shortcodes', 'wp-digital-download'), + 'edit_wpdd_products', + 'wpdd-shortcodes', + array(__CLASS__, 'render_shortcodes_page') + ); + } - add_submenu_page( - 'edit.php?post_type=wpdd_product', - __('Customers', 'wp-digital-download'), - __('Customers', 'wp-digital-download'), - 'wpdd_manage_orders', - 'wpdd-customers', - array(__CLASS__, 'render_customers_page') - ); - - add_submenu_page( - 'edit.php?post_type=wpdd_product', - __('Shortcodes', 'wp-digital-download'), - __('Shortcodes', 'wp-digital-download'), - 'edit_wpdd_products', - 'wpdd-shortcodes', - array(__CLASS__, 'render_shortcodes_page') - ); + if ($is_creator || $is_admin) { + // Creator-specific menus + add_submenu_page( + 'edit.php?post_type=wpdd_product', + __('My Sales', 'wp-digital-download'), + __('My Sales', 'wp-digital-download'), + 'wpdd_view_own_sales', + 'wpdd-creator-sales', + array(__CLASS__, 'render_creator_sales_page') + ); + + add_submenu_page( + 'edit.php?post_type=wpdd_product', + __('My Payouts', 'wp-digital-download'), + __('My Payouts', 'wp-digital-download'), + 'wpdd_view_own_sales', + 'wpdd-creator-payouts', + array(__CLASS__, 'render_creator_payouts_page') + ); + } } public static function add_product_columns($columns) { @@ -917,4 +947,289 @@ class WPDD_Admin { is_main_query()) { + return; + } + + if (!isset($_GET['post_type']) || $_GET['post_type'] !== 'wpdd_product') { + return; + } + + $user = wp_get_current_user(); + $is_creator = in_array('wpdd_creator', (array) $user->roles); + $is_admin = current_user_can('manage_options'); + + // Only filter for creators, not admins + if ($is_creator && !$is_admin) { + $query->set('author', get_current_user_id()); + } + } + + public static function render_creator_sales_page() { + global $wpdb; + + $user_id = get_current_user_id(); + $currency = get_option('wpdd_currency', 'USD'); + $commission_rate = floatval(get_option('wpdd_commission_rate', 0)); + + // Get creator's sales data + $sales = $wpdb->get_results($wpdb->prepare( + "SELECT o.*, p.post_title as product_name, + (o.total * %f / 100) as platform_fee, + (o.total * (100 - %f) / 100) as creator_earning + FROM {$wpdb->prefix}wpdd_orders o + INNER JOIN {$wpdb->posts} p ON o.product_id = p.ID + WHERE p.post_author = %d + AND o.status = 'completed' + ORDER BY o.purchase_date DESC + LIMIT 100", + $commission_rate, + $commission_rate, + $user_id + )); + + // Get totals + $total_sales = $wpdb->get_var($wpdb->prepare( + "SELECT SUM(o.total) + FROM {$wpdb->prefix}wpdd_orders o + INNER JOIN {$wpdb->posts} p ON o.product_id = p.ID + WHERE p.post_author = %d + AND o.status = 'completed'", + $user_id + )); + + $total_earnings = $total_sales * (1 - ($commission_rate / 100)); + $current_balance = WPDD_Creator::get_creator_balance($user_id); + + ?> +
+

+ +
+
+

+
+
+
+

+
+ +
+
+

+
+ +
+
+ + +
+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
purchase_date))); ?>product_name); ?>customer_name); ?>total, $currency); ?>platform_fee, $currency); ?>creator_earning, $currency); ?> + + status)); ?> + +
+
+ +
+

+

+
+ +
+ get_results($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_payouts + WHERE creator_id = %d + ORDER BY created_at DESC + LIMIT 50", + $user_id + )); + + ?> +
+

+ + +
+

+
+ + +
+ + +
+

+ + + + + + + + + + + + + + + + + + + + + + + +
created_at))); ?>amount, $payout->currency); ?>paypal_email); ?> + '#fef3c7; color: #92400e;', + 'completed' => '#d1fae5; color: #065f46;', + 'failed' => '#fee2e2; color: #991b1b;', + 'requested' => '#dbeafe; color: #1e40af;' + ); + $status_color = isset($status_colors[$payout->status]) ? $status_colors[$payout->status] : '#f3f4f6; color: #374151;'; + ?> + + status)); ?> + + transaction_id ?: '-'); ?> + processed_at + ? esc_html(date_i18n(get_option('date_format'), strtotime($payout->processed_at))) + : '-'; + ?> +
+
+ +
+

+

+
+ +
+ insert( + $wpdb->prefix . 'wpdd_payouts', + array( + 'creator_id' => $user_id, + 'amount' => $balance, + 'currency' => $currency, + 'paypal_email' => $paypal_email, + 'status' => 'requested', + 'payout_method' => 'request', + 'created_at' => current_time('mysql') + ), + array('%d', '%f', '%s', '%s', '%s', '%s', '%s') + ); + + // Reset balance to 0 since it's now requested + update_user_meta($user_id, 'wpdd_creator_balance', 0); + + // Redirect to avoid resubmission + wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-creator-payouts&message=payout_requested')); + exit; + } } \ No newline at end of file diff --git a/admin/class-wpdd-settings.php b/admin/class-wpdd-settings.php index 07a729e..6240a4d 100644 --- a/admin/class-wpdd-settings.php +++ b/admin/class-wpdd-settings.php @@ -16,7 +16,7 @@ class WPDD_Settings { 'edit.php?post_type=wpdd_product', __('Settings', 'wp-digital-download'), __('Settings', 'wp-digital-download'), - 'wpdd_manage_settings', + 'manage_options', 'wpdd-settings', array(__CLASS__, 'render_settings_page') ); @@ -26,9 +26,16 @@ class WPDD_Settings { register_setting('wpdd_settings', 'wpdd_paypal_mode'); register_setting('wpdd_settings', 'wpdd_paypal_client_id'); register_setting('wpdd_settings', 'wpdd_paypal_secret'); + register_setting('wpdd_settings', 'wpdd_paypal_payout_email'); register_setting('wpdd_settings', 'wpdd_admin_email'); register_setting('wpdd_settings', 'wpdd_from_name'); register_setting('wpdd_settings', 'wpdd_from_email'); + register_setting('wpdd_settings', 'wpdd_smtp_enabled'); + register_setting('wpdd_settings', 'wpdd_smtp_host'); + register_setting('wpdd_settings', 'wpdd_smtp_port'); + register_setting('wpdd_settings', 'wpdd_smtp_username'); + register_setting('wpdd_settings', 'wpdd_smtp_password'); + register_setting('wpdd_settings', 'wpdd_smtp_encryption'); register_setting('wpdd_settings', 'wpdd_currency'); register_setting('wpdd_settings', 'wpdd_enable_guest_checkout'); register_setting('wpdd_settings', 'wpdd_default_download_limit'); @@ -193,6 +200,18 @@ class WPDD_Settings { 'wpdd_paypal_settings', array('name' => 'wpdd_paypal_secret') ); + + add_settings_field( + 'wpdd_paypal_payout_email', + __('PayPal Payout Account Email', 'wp-digital-download'), + array(__CLASS__, 'email_field'), + 'wpdd_settings', + 'wpdd_paypal_settings', + array( + 'name' => 'wpdd_paypal_payout_email', + 'description' => __('PayPal account email that will send payouts to creators', 'wp-digital-download') + ) + ); } private static function add_email_fields() { @@ -231,6 +250,94 @@ class WPDD_Settings { 'description' => __('Email address shown in email headers', 'wp-digital-download') ) ); + + add_settings_field( + 'wpdd_smtp_enabled', + __('Enable SMTP', 'wp-digital-download'), + array(__CLASS__, 'checkbox_field'), + 'wpdd_settings', + 'wpdd_email_settings', + array( + 'name' => 'wpdd_smtp_enabled', + 'label' => __('Use SMTP for sending emails instead of PHP mail()', 'wp-digital-download') + ) + ); + + add_settings_field( + 'wpdd_smtp_host', + __('SMTP Host', 'wp-digital-download'), + array(__CLASS__, 'text_field'), + 'wpdd_settings', + 'wpdd_email_settings', + array( + 'name' => 'wpdd_smtp_host', + 'description' => __('SMTP server hostname (e.g., smtp.gmail.com)', 'wp-digital-download') + ) + ); + + add_settings_field( + 'wpdd_smtp_port', + __('SMTP Port', 'wp-digital-download'), + array(__CLASS__, 'number_field'), + 'wpdd_settings', + 'wpdd_email_settings', + array( + 'name' => 'wpdd_smtp_port', + 'description' => __('SMTP server port number (common ports: 25, 465, 587)', 'wp-digital-download'), + 'min' => 1, + 'max' => 65535 + ) + ); + + add_settings_field( + 'wpdd_smtp_encryption', + __('SMTP Encryption', 'wp-digital-download'), + array(__CLASS__, 'select_field'), + 'wpdd_settings', + 'wpdd_email_settings', + array( + 'name' => 'wpdd_smtp_encryption', + 'options' => array( + '' => __('None', 'wp-digital-download'), + 'tls' => __('TLS', 'wp-digital-download'), + 'ssl' => __('SSL', 'wp-digital-download') + ), + 'description' => __('Select encryption method - TLS is recommended for most providers', 'wp-digital-download') + ) + ); + + add_settings_field( + 'wpdd_smtp_autodetect', + __('Auto-Detect Settings', 'wp-digital-download'), + array(__CLASS__, 'smtp_autodetect_field'), + 'wpdd_settings', + 'wpdd_email_settings', + array() + ); + + add_settings_field( + 'wpdd_smtp_username', + __('SMTP Username', 'wp-digital-download'), + array(__CLASS__, 'text_field'), + 'wpdd_settings', + 'wpdd_email_settings', + array( + 'name' => 'wpdd_smtp_username', + 'description' => __('SMTP authentication username', 'wp-digital-download') + ) + ); + + add_settings_field( + 'wpdd_smtp_password', + __('SMTP Password', 'wp-digital-download'), + array(__CLASS__, 'password_field'), + 'wpdd_settings', + 'wpdd_email_settings', + array( + 'name' => 'wpdd_smtp_password', + 'description' => __('SMTP authentication password', 'wp-digital-download') + ) + ); } private static function add_download_fields() { @@ -305,59 +412,101 @@ class WPDD_Settings { } public static function render_settings_page() { + $active_tab = isset($_GET['tab']) ? $_GET['tab'] : 'general'; ?>

-
-
-

-

-
    -
  1. -
  2. -
  3. -
  4. -
+ + +
+
+
+ +
-
-

-
    -
  • [wpdd_shop] -
  • -
  • [wpdd_customer_purchases] -
  • -
  • [wpdd_checkout] -
  • -
  • [wpdd_thank_you] -
  • -
  • [wpdd_product id="123"] -
  • -
-
- -
-

- +
+ +
+

+

+
    +
  1. +
  2. +
  3. +
  4. +
+
+ +
+

+
    +
  • [wpdd_shop] -
  • +
  • [wpdd_customer_purchases] -
  • +
  • [wpdd_checkout] -
  • +
  • [wpdd_thank_you] -
  • +
  • [wpdd_product id="123"] -
  • +
+
+ + +
+

+ +
- -
- -
@@ -584,9 +739,98 @@ class WPDD_Settings { )); } + public static function smtp_autodetect_field($args) { + ?> + + +

+ +

+ + + __('Plugin Constants', 'wp-digital-download'), + 'value' => __('Not Loaded', 'wp-digital-download'), + 'class' => 'wpdd-status-error' + ); + echo '
    '; + foreach ($status as $item) { + printf( + '
  • %s: %s
  • ', + esc_html($item['label']), + esc_attr($item['class']), + esc_html($item['value']) + ); + } + echo '
'; + return; + } + $upload_dir = wp_upload_dir(); $protected_dir = trailingslashit($upload_dir['basedir']) . WPDD_UPLOADS_DIR; @@ -659,6 +903,73 @@ class WPDD_Settings { echo ''; } + public static function render_general_tab() { + ?> +
+

+ +
+ +
+

+ +
+ +
+

+ +
+ +
+

+ +
+ +
+

+ +
+ '; + do_settings_fields('wpdd_settings', $section_id); + echo ''; + } + public static function sanitize_commission_rate($input) { $value = floatval($input); if ($value < 0) { diff --git a/admin/views/order-details.php b/admin/views/order-details.php new file mode 100644 index 0000000..a8c5ab7 --- /dev/null +++ b/admin/views/order-details.php @@ -0,0 +1,261 @@ + +
+

+ +
+ +
+

+ + + + + + + + + + + + + + + + + + + + transaction_id)) : ?> + + + + + + + + + + +
order_number); ?>
+ + status)); ?> + +
purchase_date))); ?>
+ 'PayPal', + 'free' => 'Free Download', + 'manual' => 'Manual Payment' + ); + echo esc_html($payment_methods[$order->payment_method] ?? ucfirst($order->payment_method)); + ?> +
transaction_id); ?>
+ + amount, $order->currency); ?> + +
+
+ +
+

+ + + + + + + + + + + + customer_id > 0) : ?> + + + + + + +
customer_name); ?>
+ + customer_email); ?> + +
+ + + +
+
+ +
+

+ + + + + + + + + + + + creator_id > 0) : ?> + + + + + + +
+ + product_name); ?> + +
product_id); ?>
+ creator_id); + if ($creator) : ?> + + display_name); ?> + + + + +
+
+ + get_results($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_download_links WHERE order_id = %d ORDER BY created_at DESC", + $order->id + )); + ?> + + + + + + get_results($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_downloads WHERE order_id = %d ORDER BY download_date DESC LIMIT 20", + $order->id + )); + ?> + + +
+

+ () +

+ + + + + + + + + + + + + + + + + + +
download_date))); ?>ip_address); ?> + user_agent, 10)); ?> +
+
+ + +
+ + + + + status === 'completed') : ?> + + + + +
+ +
+
+ + \ No newline at end of file diff --git a/assets/js/admin-payouts.js b/assets/js/admin-payouts.js new file mode 100644 index 0000000..a5447b3 --- /dev/null +++ b/assets/js/admin-payouts.js @@ -0,0 +1,124 @@ +jQuery(document).ready(function($) { + // Handle individual payout processing + $('.wpdd-process-payout').on('click', function(e) { + e.preventDefault(); + + var $button = $(this); + var payoutId = $button.data('payout-id'); + var originalText = $button.text(); + + // Disable button and show loading + $button.prop('disabled', true).text('Processing...'); + + $.ajax({ + url: ajaxurl, + type: 'POST', + data: { + action: 'wpdd_process_payout', + payout_id: payoutId, + nonce: wpdd_admin_nonce + }, + success: function(response) { + if (response.success) { + $button.closest('tr').find('.payout-status').text('Processing'); + $button.text('Processed').removeClass('wpdd-process-payout').addClass('button-disabled'); + } else { + alert('Error: ' + (response.data || 'Unknown error occurred')); + $button.prop('disabled', false).text(originalText); + } + }, + error: function() { + alert('Ajax request failed'); + $button.prop('disabled', false).text(originalText); + } + }); + }); + + // Handle payout request approval + $('.wpdd-approve-request').on('click', function(e) { + e.preventDefault(); + + var $button = $(this); + var requestId = $button.data('request-id'); + var originalText = $button.text(); + + // Disable button and show loading + $button.prop('disabled', true).text('Processing...'); + + $.ajax({ + url: ajaxurl, + type: 'POST', + data: { + action: 'wpdd_approve_payout_request', + request_id: requestId, + nonce: wpdd_admin_nonce + }, + success: function(response) { + if (response.success) { + location.reload(); // Reload to show updated status + } else { + alert('Error: ' + (response.data || 'Unknown error occurred')); + $button.prop('disabled', false).text(originalText); + } + }, + error: function() { + alert('Ajax request failed'); + $button.prop('disabled', false).text(originalText); + } + }); + }); + + // Handle bulk payout processing + $('#wpdd-process-bulk-payouts').on('click', function(e) { + e.preventDefault(); + + var checkedPayouts = $('.wpdd-payout-checkbox:checked'); + + if (checkedPayouts.length === 0) { + alert('Please select at least one payout to process.'); + return; + } + + if (!confirm('Are you sure you want to process ' + checkedPayouts.length + ' payout(s)?')) { + return; + } + + var $button = $(this); + var originalText = $button.text(); + var payoutIds = []; + + checkedPayouts.each(function() { + payoutIds.push($(this).val()); + }); + + // Disable button and show loading + $button.prop('disabled', true).text('Processing...'); + + $.ajax({ + url: ajaxurl, + type: 'POST', + data: { + action: 'wpdd_process_bulk_payouts', + payout_ids: payoutIds, + nonce: wpdd_admin_nonce + }, + success: function(response) { + if (response.success) { + location.reload(); // Reload to show updated status + } else { + alert('Error: ' + (response.data || 'Unknown error occurred')); + $button.prop('disabled', false).text(originalText); + } + }, + error: function() { + alert('Ajax request failed'); + $button.prop('disabled', false).text(originalText); + } + }); + }); + + // Handle select all checkboxes + $('#wpdd-select-all-payouts').on('change', function() { + $('.wpdd-payout-checkbox').prop('checked', $(this).prop('checked')); + }); +}); \ No newline at end of file diff --git a/docs/developer-integration-guide.md b/docs/developer-integration-guide.md new file mode 100644 index 0000000..2f1e439 --- /dev/null +++ b/docs/developer-integration-guide.md @@ -0,0 +1,420 @@ +# WP Digital Download - Software Licensing Integration Guide + +This guide shows developers how to integrate their WordPress plugins with the WP Digital Download licensing and update system. + +## Quick Start + +### 1. Download the Integration Library + +Download `wpdd-plugin-updater.php` from your product page and include it in your plugin. + +### 2. Basic Integration + +```php +init_updater(); + } + + private function init_updater() { + // Only initialize updater in admin area + if (!is_admin()) { + return; + } + + $license_key = get_option('my_plugin_license_key', ''); + + $this->updater = new WPDD_Plugin_Updater( + __FILE__, // Main plugin file + $license_key, // License key from user + 'https://your-store.com', // Your store URL + array( + 'add_settings_page' => true // Add license settings page + ) + ); + } +} + +new My_Awesome_Plugin(); +``` + +## Advanced Integration + +### Custom License Settings Page + +If you want to integrate license management into your existing settings: + +```php +class My_Plugin_Settings { + + private $updater; + + public function __construct() { + $this->init_updater(); + add_action('admin_menu', array($this, 'add_settings_page')); + add_action('admin_init', array($this, 'handle_license_actions')); + } + + private function init_updater() { + $license_key = get_option('my_plugin_license_key', ''); + + $this->updater = new WPDD_Plugin_Updater( + MY_PLUGIN_FILE, + $license_key, + 'https://your-store.com', + array('add_settings_page' => false) // We'll handle settings ourselves + ); + } + + public function handle_license_actions() { + if (isset($_POST['activate_license'])) { + $license_key = sanitize_text_field($_POST['license_key']); + $result = $this->updater->activate_license($license_key); + + if ($result['success']) { + update_option('my_plugin_license_key', $license_key); + add_settings_error('my_plugin', 'activated', 'License activated!', 'updated'); + } else { + add_settings_error('my_plugin', 'error', $result['message'], 'error'); + } + } + + if (isset($_POST['deactivate_license'])) { + $result = $this->updater->deactivate_license(); + if ($result['success']) { + delete_option('my_plugin_license_key'); + add_settings_error('my_plugin', 'deactivated', 'License deactivated!', 'updated'); + } + } + } + + public function render_license_section() { + $license_key = get_option('my_plugin_license_key', ''); + $is_valid = $this->updater->validate_license(); + + ?> +

License Settings

+ + + + + +
+ + + + ✓ Active + + ✗ Invalid + + +

+ Enter your license key to receive automatic updates. +

+
+ + +

+ +

+ +

+ +

+ + updater = new WPDD_Plugin_Updater( + MY_PLUGIN_FILE, + $license_key, + 'https://your-store.com' + ); + + // Only enable premium features if license is valid + if ($this->is_license_valid()) { + $this->enable_premium_features(); + } else { + $this->show_license_notice(); + } + } + + private function is_license_valid() { + return $this->updater->validate_license(); + } + + private function enable_premium_features() { + // Add your premium functionality here + add_action('init', array($this, 'init_premium_features')); + } + + private function show_license_notice() { + add_action('admin_notices', function() { + ?> +
+

+ My Awesome Plugin: + Please + activate your license to access premium features and receive updates. +

+
+ validate_license(); +// Returns: boolean +``` + +##### activate_license($license_key) +Activates a license key for the current site. +```php +$result = $updater->activate_license('XXXX-XXXX-XXXX-XXXX'); +// Returns: array with 'success', 'message', and additional data +``` + +##### deactivate_license() +Deactivates the current license from this site. +```php +$result = $updater->deactivate_license(); +// Returns: array with 'success' and 'message' +``` + +## Repository Setup (For Store Owners) + +### 1. Create Software Product + +1. Go to your WordPress admin → Digital Products → Add New Product +2. Select "Software License" as product type +3. Fill in the software licensing fields: + - Git Repository URL + - License settings (max activations, duration) + - Version information + +### 2. Configure Git Webhook + +Add the generated webhook URL to your repository settings. The system receives webhook notifications FROM your Git platform when releases are published: + +**Gitea:** +1. Go to Settings → Webhooks +2. Add webhook with the URL from your product page +3. Set Content-Type to `application/json` +4. Select "Release events" as the trigger +5. Ensure webhook is active + +**GitHub:** +1. Go to Settings → Webhooks +2. Add webhook with the URL from your product page +3. Set Content-Type to `application/json` +4. Select "Releases" events (or "Just the push event" for tag-based releases) + +**GitLab:** +1. Go to Settings → Webhooks +2. Add the webhook URL +3. Select "Tag push events" or "Releases events" + +### 3. Release Process + +**Option 1: Using Git Platform Releases (Recommended for Gitea/GitHub)** +1. Create a release through your Git platform's web interface: + - Navigate to Releases section + - Click "Create Release" or "New Release" + - Set tag name (e.g., `v1.2.0`) + - Add release notes in the description + - Publish the release + +2. The webhook automatically receives the release notification and: + - Detects the new version from the release + - Clones the repository at the specific tag + - Creates distribution packages (removes dev files, creates ZIP) + - Stores version info and changelog in the database + - Makes update available to customers with active licenses + +**Option 2: Using Git Tags (Alternative)** +1. Create and push a git tag: + ```bash + git tag -a v1.2.0 -m "Version 1.2.0" + git push origin v1.2.0 + ``` + +2. The webhook receives the tag push notification and processes the release similarly + +## API Endpoints + +### License Validation +``` +POST /wp-json/wpdd/v1/validate-license +Body: { + "license_key": "XXXX-XXXX-XXXX-XXXX", + "product_slug": "my-plugin", + "site_url": "https://example.com" +} +``` + +### Update Check +``` +GET /wp-json/wpdd/v1/check-update/my-plugin?license_key=XXXX&version=1.0.0 +``` + +### Download Update +``` +GET /wp-json/wpdd/v1/download-update/my-plugin?license_key=XXXX +``` + +## Testing Your Integration + +### 1. Local Testing + +```php +// Add this to your plugin for testing +if (defined('WP_DEBUG') && WP_DEBUG) { + add_action('admin_notices', function() { + $license_key = get_option('my_plugin_license_key', ''); + $updater = new WPDD_Plugin_Updater(__FILE__, $license_key, 'https://your-store.com'); + $is_valid = $updater->validate_license(); + + echo '
'; + echo '

License Status: ' . ($is_valid ? 'Valid' : 'Invalid') . '

'; + echo '
'; + }); +} +``` + +### 2. Force Update Check + +```php +// Add this temporarily to force update check +add_action('admin_init', function() { + if (isset($_GET['force_update_check'])) { + delete_transient('wpdd_update_my-plugin'); + delete_site_transient('update_plugins'); + wp_redirect(admin_url('plugins.php')); + exit; + } +}); +``` + +Then visit: `wp-admin/plugins.php?force_update_check=1` + +## Best Practices + +### 1. Error Handling +Always handle API failures gracefully: + +```php +$result = $updater->validate_license(); +if ($result === false) { + // Network error or server down - allow functionality to continue + // but maybe show a notice +} +``` + +### 2. Caching +The updater automatically caches responses. Don't call validation on every page load: + +```php +// Good - check once per day +$last_check = get_option('my_plugin_license_check', 0); +if (time() - $last_check > DAY_IN_SECONDS) { + $is_valid = $updater->validate_license(); + update_option('my_plugin_license_check', time()); + update_option('my_plugin_license_valid', $is_valid); +} else { + $is_valid = get_option('my_plugin_license_valid', false); +} +``` + +### 3. Graceful Degradation +Design your plugin to work without a valid license, but with reduced functionality: + +```php +if ($this->is_license_valid()) { + // Full functionality + $this->enable_all_features(); +} else { + // Basic functionality only + $this->enable_basic_features(); + $this->show_upgrade_notice(); +} +``` + +## Troubleshooting + +### Common Issues + +1. **Updates not showing:** Check that the plugin slug matches the product slug in your store +2. **License validation fails:** Ensure the update server URL is correct and accessible +3. **Download fails:** Verify the license is activated and not expired + +### Debug Mode + +Enable WordPress debug logging and check for WPDD Updater messages: + +```php +// wp-config.php +define('WP_DEBUG', true); +define('WP_DEBUG_LOG', true); +``` + +Check `/wp-content/debug.log` for error messages. + +## Support + +For integration support: +- Check the troubleshooting section above +- Enable debug logging and check for error messages +- Contact support with your store URL and plugin details + +## Example Files + +Complete example plugins are available in the `/examples/` directory of this package. \ No newline at end of file diff --git a/includes/class-wpdd-api.php b/includes/class-wpdd-api.php new file mode 100644 index 0000000..818d088 --- /dev/null +++ b/includes/class-wpdd-api.php @@ -0,0 +1,785 @@ + 'POST', + 'callback' => array(__CLASS__, 'validate_license'), + 'permission_callback' => '__return_true', + 'args' => array( + 'license_key' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field' + ), + 'product_slug' => array( + 'required' => false, + 'sanitize_callback' => 'sanitize_text_field' + ), + 'site_url' => array( + 'required' => false, + 'sanitize_callback' => 'esc_url_raw' + ) + ) + )); + + // License activation + register_rest_route('wpdd/v1', '/activate-license', array( + 'methods' => 'POST', + 'callback' => array(__CLASS__, 'activate_license'), + 'permission_callback' => '__return_true', + 'args' => array( + 'license_key' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field' + ), + 'site_url' => array( + 'required' => true, + 'sanitize_callback' => 'esc_url_raw' + ), + 'site_name' => array( + 'required' => false, + 'sanitize_callback' => 'sanitize_text_field' + ), + 'wp_version' => array( + 'required' => false, + 'sanitize_callback' => 'sanitize_text_field' + ), + 'php_version' => array( + 'required' => false, + 'sanitize_callback' => 'sanitize_text_field' + ) + ) + )); + + // License deactivation + register_rest_route('wpdd/v1', '/deactivate-license', array( + 'methods' => 'POST', + 'callback' => array(__CLASS__, 'deactivate_license'), + 'permission_callback' => '__return_true', + 'args' => array( + 'license_key' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field' + ), + 'site_url' => array( + 'required' => true, + 'sanitize_callback' => 'esc_url_raw' + ) + ) + )); + + // Check for updates + register_rest_route('wpdd/v1', '/check-update/(?P[a-zA-Z0-9-]+)', array( + 'methods' => 'GET', + 'callback' => array(__CLASS__, 'check_update'), + 'permission_callback' => '__return_true', + 'args' => array( + 'product_slug' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field' + ), + 'license_key' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field' + ), + 'version' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field' + ) + ) + )); + + // Download update + register_rest_route('wpdd/v1', '/download-update/(?P[a-zA-Z0-9-]+)', array( + 'methods' => 'GET', + 'callback' => array(__CLASS__, 'download_update'), + 'permission_callback' => '__return_true', + 'args' => array( + 'product_slug' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field' + ), + 'license_key' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field' + ) + ) + )); + + // Webhook endpoint with secure passcode + register_rest_route('wpdd/v1', '/webhook/(?P\d+)/(?P[a-zA-Z0-9]+)', array( + 'methods' => 'POST', + 'callback' => array(__CLASS__, 'handle_webhook'), + 'permission_callback' => '__return_true', + 'args' => array( + 'product_id' => array( + 'required' => true, + 'sanitize_callback' => 'absint' + ), + 'passcode' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field' + ) + ) + )); + } + + /** + * Validate license endpoint + */ + public static function validate_license($request) { + $license_key = $request->get_param('license_key'); + $product_slug = $request->get_param('product_slug'); + $site_url = $request->get_param('site_url'); + + if (!class_exists('WPDD_License_Manager')) { + require_once WPDD_PLUGIN_PATH . 'includes/class-wpdd-license-manager.php'; + } + + $result = WPDD_License_Manager::validate_license($license_key, $product_slug, $site_url); + + if ($result['valid']) { + return new WP_REST_Response(array( + 'success' => true, + 'message' => $result['message'], + 'license' => array( + 'status' => $result['license']->status, + 'expires_at' => $result['license']->expires_at, + 'activations' => $result['license']->activations_count, + 'max_activations' => $result['license']->max_activations + ) + ), 200); + } else { + return new WP_REST_Response(array( + 'success' => false, + 'error' => $result['error'], + 'message' => $result['message'] + ), 400); + } + } + + /** + * Activate license endpoint + */ + public static function activate_license($request) { + $license_key = $request->get_param('license_key'); + $site_url = $request->get_param('site_url'); + $site_name = $request->get_param('site_name'); + $wp_version = $request->get_param('wp_version'); + $php_version = $request->get_param('php_version'); + + if (!class_exists('WPDD_License_Manager')) { + require_once WPDD_PLUGIN_PATH . 'includes/class-wpdd-license-manager.php'; + } + + $result = WPDD_License_Manager::activate_license($license_key, $site_url, $site_name, $wp_version, $php_version); + + if ($result['success']) { + return new WP_REST_Response($result, 200); + } else { + return new WP_REST_Response($result, 400); + } + } + + /** + * Deactivate license endpoint + */ + public static function deactivate_license($request) { + $license_key = $request->get_param('license_key'); + $site_url = $request->get_param('site_url'); + + if (!class_exists('WPDD_License_Manager')) { + require_once WPDD_PLUGIN_PATH . 'includes/class-wpdd-license-manager.php'; + } + + $result = WPDD_License_Manager::deactivate_license($license_key, $site_url); + + if ($result['success']) { + return new WP_REST_Response($result, 200); + } else { + return new WP_REST_Response($result, 400); + } + } + + /** + * Check for updates endpoint + */ + public static function check_update($request) { + global $wpdb; + + $product_slug = $request->get_param('product_slug'); + $license_key = $request->get_param('license_key'); + $current_version = $request->get_param('version'); + + // Validate license first + if (!class_exists('WPDD_License_Manager')) { + require_once WPDD_PLUGIN_PATH . 'includes/class-wpdd-license-manager.php'; + } + + $validation = WPDD_License_Manager::validate_license($license_key, $product_slug); + if (!$validation['valid']) { + return new WP_REST_Response(array( + 'success' => false, + 'error' => $validation['error'], + 'message' => $validation['message'] + ), 403); + } + + // Get product by slug + $product = get_page_by_path($product_slug, OBJECT, 'wpdd_product'); + if (!$product) { + return new WP_REST_Response(array( + 'success' => false, + 'message' => __('Product not found.', 'wp-digital-download') + ), 404); + } + + // Get latest version + $latest_version = $wpdb->get_row($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_software_versions + WHERE product_id = %d + ORDER BY release_date DESC + LIMIT 1", + $product->ID + )); + + if (!$latest_version) { + return new WP_REST_Response(array( + 'success' => true, + 'update_available' => false, + 'message' => __('No updates available.', 'wp-digital-download') + ), 200); + } + + // Compare versions + if (version_compare($latest_version->version, $current_version, '>')) { + // Update available + $update_data = array( + 'success' => true, + 'update_available' => true, + 'version' => $latest_version->version, + 'download_url' => home_url("/wp-json/wpdd/v1/download-update/{$product_slug}?license_key={$license_key}"), + 'package' => home_url("/wp-json/wpdd/v1/download-update/{$product_slug}?license_key={$license_key}"), + 'url' => get_permalink($product->ID), + 'tested' => $latest_version->tested_wp_version ?: get_bloginfo('version'), + 'requires' => $latest_version->min_wp_version ?: '5.0', + 'requires_php' => $latest_version->min_php_version ?: '7.0', + 'new_version' => $latest_version->version, + 'slug' => $product_slug, + 'plugin' => $product_slug . '/' . $product_slug . '.php', // Adjust based on your naming convention + 'changelog' => $latest_version->changelog, + 'release_notes' => $latest_version->release_notes + ); + + return new WP_REST_Response($update_data, 200); + } else { + return new WP_REST_Response(array( + 'success' => true, + 'update_available' => false, + 'message' => __('You have the latest version.', 'wp-digital-download') + ), 200); + } + } + + /** + * Download update endpoint + */ + public static function download_update($request) { + global $wpdb; + + $product_slug = $request->get_param('product_slug'); + $license_key = $request->get_param('license_key'); + + // Validate license + if (!class_exists('WPDD_License_Manager')) { + require_once WPDD_PLUGIN_PATH . 'includes/class-wpdd-license-manager.php'; + } + + $validation = WPDD_License_Manager::validate_license($license_key, $product_slug); + if (!$validation['valid']) { + return new WP_REST_Response(array( + 'success' => false, + 'error' => $validation['error'], + 'message' => $validation['message'] + ), 403); + } + + // Get product + $product = get_page_by_path($product_slug, OBJECT, 'wpdd_product'); + if (!$product) { + return new WP_REST_Response(array( + 'success' => false, + 'message' => __('Product not found.', 'wp-digital-download') + ), 404); + } + + // Get latest version + $latest_version = $wpdb->get_row($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_software_versions + WHERE product_id = %d + ORDER BY release_date DESC + LIMIT 1", + $product->ID + )); + + if (!$latest_version || !$latest_version->package_url) { + return new WP_REST_Response(array( + 'success' => false, + 'message' => __('Update package not available.', 'wp-digital-download') + ), 404); + } + + // Get package file path + $upload_dir = wp_upload_dir(); + $package_path = str_replace($upload_dir['baseurl'], $upload_dir['basedir'], $latest_version->package_url); + + if (!file_exists($package_path)) { + return new WP_REST_Response(array( + 'success' => false, + 'message' => __('Update package file not found.', 'wp-digital-download') + ), 404); + } + + // Log download + $wpdb->insert( + $wpdb->prefix . 'wpdd_downloads', + array( + 'order_id' => $validation['license']->order_id, + 'product_id' => $product->ID, + 'customer_id' => $validation['license']->customer_id, + 'file_id' => $latest_version->version, + 'download_date' => current_time('mysql'), + 'ip_address' => $_SERVER['REMOTE_ADDR'], + 'user_agent' => $_SERVER['HTTP_USER_AGENT'] + ), + array('%d', '%d', '%d', '%s', '%s', '%s', '%s') + ); + + // Serve file + $filename = basename($package_path); + header('Content-Type: application/zip'); + header('Content-Disposition: attachment; filename="' . $filename . '"'); + header('Content-Length: ' . filesize($package_path)); + header('Pragma: no-cache'); + header('Expires: 0'); + readfile($package_path); + exit; + } + + /** + * Handle Git webhook for new releases (receives notifications FROM Git platforms like Gitea) + */ + public static function handle_webhook($request) { + global $wpdb; + + $product_id = $request->get_param('product_id'); + $passcode = $request->get_param('passcode'); + + // Validate passcode + $stored_passcode = get_post_meta($product_id, '_wpdd_webhook_passcode', true); + if (!$stored_passcode || $stored_passcode !== $passcode) { + return new WP_REST_Response(array( + 'success' => false, + 'message' => __('Invalid webhook passcode.', 'wp-digital-download') + ), 403); + } + + // Get payload from Git platform (Gitea, GitHub, GitLab, etc.) + $payload = $request->get_body(); + $data = json_decode($payload, true); + + if (!$data) { + return new WP_REST_Response(array( + 'success' => false, + 'message' => __('Invalid JSON payload.', 'wp-digital-download') + ), 400); + } + + // Determine event type based on payload structure + $event_type = 'unknown'; + $is_release = false; + + // Gitea release webhook + if (isset($data['action']) && isset($data['release'])) { + $event_type = 'release'; + $is_release = ($data['action'] === 'published' || $data['action'] === 'created'); + } + // GitHub/GitLab push with tags + elseif (isset($data['ref']) && strpos($data['ref'], 'refs/tags/') === 0) { + $event_type = 'tag_push'; + $is_release = true; + } + // GitHub release webhook + elseif (isset($data['action']) && isset($data['release']) && $data['action'] === 'published') { + $event_type = 'github_release'; + $is_release = true; + } + + // Log webhook event + $wpdb->insert( + $wpdb->prefix . 'wpdd_webhook_events', + array( + 'product_id' => $product_id, + 'event_type' => $event_type, + 'payload' => $payload, + 'processed' => 'pending', + 'received_at' => current_time('mysql') + ), + array('%d', '%s', '%s', '%s', '%s') + ); + + $event_id = $wpdb->insert_id; + + if (!$is_release) { + // Mark as ignored - not a release event + $wpdb->update( + $wpdb->prefix . 'wpdd_webhook_events', + array( + 'processed' => 'ignored', + 'processed_at' => current_time('mysql'), + 'error_message' => 'Not a release event' + ), + array('id' => $event_id), + array('%s', '%s', '%s'), + array('%d') + ); + + return new WP_REST_Response(array( + 'success' => true, + 'message' => __('Webhook received but not a release event.', 'wp-digital-download') + ), 200); + } + + // Extract version information based on platform + $version = ''; + $tag = ''; + + if ($event_type === 'release' || $event_type === 'github_release') { + // Gitea or GitHub release + $tag = $data['release']['tag_name'] ?? ''; + $version = ltrim($tag, 'v'); + } elseif ($event_type === 'tag_push') { + // Git tag push + $tag = str_replace('refs/tags/', '', $data['ref']); + $version = ltrim($tag, 'v'); + } + + if (empty($version)) { + // Mark as error + $wpdb->update( + $wpdb->prefix . 'wpdd_webhook_events', + array( + 'processed' => 'error', + 'processed_at' => current_time('mysql'), + 'error_message' => 'Could not extract version from payload' + ), + array('id' => $event_id), + array('%s', '%s', '%s'), + array('%d') + ); + + return new WP_REST_Response(array( + 'success' => false, + 'message' => __('Could not extract version from webhook payload.', 'wp-digital-download') + ), 400); + } + + // Check if this version already exists + $existing = $wpdb->get_var($wpdb->prepare( + "SELECT id FROM {$wpdb->prefix}wpdd_software_versions + WHERE product_id = %d AND version = %s", + $product_id, + $version + )); + + if (!$existing) { + // Process new release + $success = self::process_new_release($product_id, $version, $tag, $data); + + if ($success) { + // Mark webhook as processed + $wpdb->update( + $wpdb->prefix . 'wpdd_webhook_events', + array( + 'processed' => 'completed', + 'processed_at' => current_time('mysql') + ), + array('id' => $event_id), + array('%s', '%s'), + array('%d') + ); + } else { + // Mark as error + $wpdb->update( + $wpdb->prefix . 'wpdd_webhook_events', + array( + 'processed' => 'error', + 'processed_at' => current_time('mysql'), + 'error_message' => 'Failed to process release' + ), + array('id' => $event_id), + array('%s', '%s', '%s'), + array('%d') + ); + } + } else { + // Mark as duplicate + $wpdb->update( + $wpdb->prefix . 'wpdd_webhook_events', + array( + 'processed' => 'duplicate', + 'processed_at' => current_time('mysql'), + 'error_message' => 'Version already exists' + ), + array('id' => $event_id), + array('%s', '%s', '%s'), + array('%d') + ); + } + + return new WP_REST_Response(array( + 'success' => true, + 'message' => __('Webhook received and processed.', 'wp-digital-download') + ), 200); + } + + /** + * Process new release from webhook (receives data FROM Git platforms like Gitea) + */ + private static function process_new_release($product_id, $version, $tag, $webhook_data) { + global $wpdb; + + // Get Git repository settings + $git_url = get_post_meta($product_id, '_wpdd_git_repository', true); + $git_username = get_post_meta($product_id, '_wpdd_git_username', true); + $git_token = get_post_meta($product_id, '_wpdd_git_token', true); + + if (!$git_url) { + error_log('WPDD: No Git URL configured for product ' . $product_id); + return false; + } + + // Build package from Git repository at the specific tag + $package_url = self::build_package_from_git($product_id, $git_url, $tag, $git_username, $git_token); + + if (!$package_url) { + error_log('WPDD: Failed to build package for product ' . $product_id . ' version ' . $version); + return false; + } + + // Extract changelog based on webhook source + $changelog = ''; + $git_commit = null; + + // Gitea/GitHub release with description + if (isset($webhook_data['release'])) { + $changelog = $webhook_data['release']['body'] ?? $webhook_data['release']['note'] ?? ''; + $git_commit = $webhook_data['release']['target_commitish'] ?? null; + } + // Git push webhook - use commit messages + elseif (isset($webhook_data['commits']) && is_array($webhook_data['commits'])) { + $messages = array(); + foreach ($webhook_data['commits'] as $commit) { + if (isset($commit['message'])) { + $messages[] = '- ' . $commit['message']; + } + } + $changelog = implode("\n", $messages); + $git_commit = $webhook_data['after'] ?? $webhook_data['head_commit']['id'] ?? null; + } + // Fallback - try to get from head commit + elseif (isset($webhook_data['head_commit']['message'])) { + $changelog = '- ' . $webhook_data['head_commit']['message']; + $git_commit = $webhook_data['head_commit']['id'] ?? null; + } + + // Insert new version + $result = $wpdb->insert( + $wpdb->prefix . 'wpdd_software_versions', + array( + 'product_id' => $product_id, + 'version' => $version, + 'changelog' => $changelog, + 'package_url' => $package_url, + 'git_tag' => $tag, + 'git_commit' => $git_commit, + 'release_date' => current_time('mysql') + ), + array('%d', '%s', '%s', '%s', '%s', '%s', '%s') + ); + + if ($result === false) { + error_log('WPDD: Failed to insert version record for product ' . $product_id . ' version ' . $version); + return false; + } + + // Update product version meta + update_post_meta($product_id, '_wpdd_current_version', $version); + + // Notify customers about update (optional) + self::notify_customers_about_update($product_id, $version); + + error_log('WPDD: Successfully processed new release for product ' . $product_id . ' version ' . $version); + return true; + } + + /** + * Build package from Git repository at specific tag + */ + private static function build_package_from_git($product_id, $git_url, $tag, $username = null, $token = null) { + $upload_dir = wp_upload_dir(); + $package_dir = trailingslashit($upload_dir['basedir']) . 'wpdd-packages/' . $product_id; + + if (!file_exists($package_dir)) { + wp_mkdir_p($package_dir); + } + + $package_filename = sanitize_file_name("package-{$tag}.zip"); + $package_path = trailingslashit($package_dir) . $package_filename; + $package_url = trailingslashit($upload_dir['baseurl']) . 'wpdd-packages/' . $product_id . '/' . $package_filename; + + // Skip if package already exists + if (file_exists($package_path)) { + return $package_url; + } + + // Create temporary directory for cloning + $temp_dir = trailingslashit(sys_get_temp_dir()) . 'wpdd-build-' . $product_id . '-' . uniqid(); + + // Build authentication URL if credentials provided + $auth_url = $git_url; + if ($username && $token) { + $parsed_url = parse_url($git_url); + if ($parsed_url) { + $auth_url = $parsed_url['scheme'] . '://' . urlencode($username) . ':' . urlencode($token) . '@' . $parsed_url['host']; + if (isset($parsed_url['port'])) { + $auth_url .= ':' . $parsed_url['port']; + } + $auth_url .= $parsed_url['path']; + } + } + + // Clone repository at specific tag + $clone_cmd = sprintf( + 'git clone --depth 1 --branch %s %s %s 2>&1', + escapeshellarg($tag), + escapeshellarg($auth_url), + escapeshellarg($temp_dir) + ); + + $output = array(); + $return_code = 0; + exec($clone_cmd, $output, $return_code); + + if ($return_code !== 0) { + error_log('WPDD: Git clone failed for ' . $git_url . ' tag ' . $tag . ': ' . implode(' ', $output)); + return false; + } + + // Remove .git directory and other development files + $cleanup_files = array('.git', '.gitignore', '.gitattributes', 'tests', 'test', '.phpunit.xml', 'composer.json', 'package.json'); + foreach ($cleanup_files as $cleanup_file) { + $cleanup_path = trailingslashit($temp_dir) . $cleanup_file; + if (file_exists($cleanup_path)) { + if (is_dir($cleanup_path)) { + self::remove_directory($cleanup_path); + } else { + unlink($cleanup_path); + } + } + } + + // Create ZIP package + if (class_exists('ZipArchive')) { + $zip = new ZipArchive(); + if ($zip->open($package_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) { + self::add_directory_to_zip($zip, $temp_dir, ''); + $zip->close(); + + // Clean up temporary directory + self::remove_directory($temp_dir); + + return $package_url; + } + } + + // Fallback: tar command if ZipArchive not available + $tar_cmd = sprintf( + 'cd %s && tar -czf %s . 2>&1', + escapeshellarg($temp_dir), + escapeshellarg($package_path . '.tar.gz') + ); + + exec($tar_cmd, $output, $return_code); + self::remove_directory($temp_dir); + + if ($return_code === 0 && file_exists($package_path . '.tar.gz')) { + return $package_url . '.tar.gz'; + } + + error_log('WPDD: Failed to create package for ' . $git_url . ' tag ' . $tag); + return false; + } + + /** + * Recursively add directory to ZIP archive + */ + private static function add_directory_to_zip($zip, $dir, $base_path) { + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); + foreach ($iterator as $file) { + if ($file->isFile()) { + $file_path = $file->getPathname(); + $relative_path = $base_path . substr($file_path, strlen($dir) + 1); + $zip->addFile($file_path, $relative_path); + } + } + } + + /** + * Recursively remove directory + */ + private static function remove_directory($dir) { + if (!is_dir($dir)) { + return; + } + + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), + RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($iterator as $file) { + if ($file->isDir()) { + rmdir($file->getPathname()); + } else { + unlink($file->getPathname()); + } + } + + rmdir($dir); + } + + /** + * Notify customers about new update + */ + private static function notify_customers_about_update($product_id, $version) { + // Optional: Send email notifications to customers with active licenses + // This could be a separate scheduled job to avoid timeout issues + } +} \ No newline at end of file diff --git a/includes/class-wpdd-install.php b/includes/class-wpdd-install.php index 19302f5..15abe82 100644 --- a/includes/class-wpdd-install.php +++ b/includes/class-wpdd-install.php @@ -20,9 +20,13 @@ class WPDD_Install { WPDD_Post_Types::register_taxonomies(); self::create_tables(); - self::create_pages(); self::create_upload_protection(); + // Set flag to show setup notice instead of creating pages automatically + if (!get_option('wpdd_setup_completed')) { + add_option('wpdd_show_setup_notice', true); + } + WPDD_Roles::create_roles(); // Flush rewrite rules after post types are registered @@ -126,6 +130,96 @@ class WPDD_Install { KEY transaction_id (transaction_id) ) $charset_collate;"; + $sql[] = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}wpdd_balance_adjustments ( + id bigint(20) NOT NULL AUTO_INCREMENT, + creator_id bigint(20) NOT NULL, + adjustment_type varchar(20) NOT NULL, + amount decimal(10,2) NOT NULL, + previous_balance decimal(10,2) NOT NULL, + new_balance decimal(10,2) NOT NULL, + reason text NOT NULL, + adjusted_by bigint(20) NOT NULL, + created_at datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id), + KEY creator_id (creator_id), + KEY adjusted_by (adjusted_by) + ) $charset_collate;"; + + // Software Licensing Tables + $sql[] = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}wpdd_licenses ( + id bigint(20) NOT NULL AUTO_INCREMENT, + license_key varchar(64) NOT NULL, + product_id bigint(20) NOT NULL, + order_id bigint(20) NOT NULL, + customer_id bigint(20) NOT NULL, + customer_email varchar(100) NOT NULL, + status varchar(20) NOT NULL DEFAULT 'active', + activations_count int(11) DEFAULT 0, + max_activations int(11) DEFAULT 1, + expires_at datetime DEFAULT NULL, + created_at datetime DEFAULT CURRENT_TIMESTAMP, + last_checked datetime DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE KEY license_key (license_key), + KEY product_id (product_id), + KEY order_id (order_id), + KEY customer_id (customer_id), + KEY status (status) + ) $charset_collate;"; + + $sql[] = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}wpdd_license_activations ( + id bigint(20) NOT NULL AUTO_INCREMENT, + license_id bigint(20) NOT NULL, + license_key varchar(64) NOT NULL, + site_url varchar(255) NOT NULL, + site_name varchar(255) DEFAULT NULL, + activated_at datetime DEFAULT CURRENT_TIMESTAMP, + last_checked datetime DEFAULT NULL, + wp_version varchar(20) DEFAULT NULL, + php_version varchar(20) DEFAULT NULL, + status varchar(20) NOT NULL DEFAULT 'active', + PRIMARY KEY (id), + KEY license_id (license_id), + KEY license_key (license_key), + KEY site_url (site_url), + KEY status (status) + ) $charset_collate;"; + + $sql[] = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}wpdd_software_versions ( + id bigint(20) NOT NULL AUTO_INCREMENT, + product_id bigint(20) NOT NULL, + version varchar(20) NOT NULL, + changelog text DEFAULT NULL, + release_notes text DEFAULT NULL, + download_url text DEFAULT NULL, + package_url text DEFAULT NULL, + min_wp_version varchar(20) DEFAULT NULL, + tested_wp_version varchar(20) DEFAULT NULL, + min_php_version varchar(20) DEFAULT NULL, + release_date datetime DEFAULT CURRENT_TIMESTAMP, + git_tag varchar(100) DEFAULT NULL, + git_commit varchar(100) DEFAULT NULL, + PRIMARY KEY (id), + KEY product_id (product_id), + KEY version (version), + KEY release_date (release_date) + ) $charset_collate;"; + + $sql[] = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}wpdd_webhook_events ( + id bigint(20) NOT NULL AUTO_INCREMENT, + product_id bigint(20) NOT NULL, + event_type varchar(50) NOT NULL, + payload text DEFAULT NULL, + processed varchar(20) NOT NULL DEFAULT 'pending', + error_message text DEFAULT NULL, + received_at datetime DEFAULT CURRENT_TIMESTAMP, + processed_at datetime DEFAULT NULL, + PRIMARY KEY (id), + KEY product_id (product_id), + KEY processed (processed), + KEY received_at (received_at) + ) $charset_collate;"; + require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); foreach ($sql as $query) { @@ -135,6 +229,10 @@ class WPDD_Install { update_option('wpdd_db_version', WPDD_VERSION); } + public static function create_pages_optional() { + return self::create_pages(); + } + private static function create_pages() { $pages = array( 'shop' => array( @@ -159,6 +257,8 @@ class WPDD_Install { ) ); + $created_pages = array(); + foreach ($pages as $slug => $page) { // Check if page already exists $existing_page_id = get_option($page['option']); @@ -184,8 +284,11 @@ class WPDD_Install { if ($page_id && !is_wp_error($page_id)) { update_option($page['option'], $page_id); + $created_pages[] = $page_id; } } + + return $created_pages; } private static function create_upload_protection() { diff --git a/includes/class-wpdd-license-manager.php b/includes/class-wpdd-license-manager.php new file mode 100644 index 0000000..1ed1a31 --- /dev/null +++ b/includes/class-wpdd-license-manager.php @@ -0,0 +1,399 @@ +product_id, '_wpdd_product_type', true); + if ($product_type !== 'software_license') { + return; + } + + // Check if license already exists for this order + $existing = $wpdb->get_var($wpdb->prepare( + "SELECT id FROM {$wpdb->prefix}wpdd_licenses WHERE order_id = %d", + $order_id + )); + + if ($existing) { + return; + } + + // Generate unique license key + $license_key = self::generate_license_key(); + + // Ensure it's unique + while (self::license_key_exists($license_key)) { + $license_key = self::generate_license_key(); + } + + // Get license settings from product + $max_activations = get_post_meta($order->product_id, '_wpdd_max_activations', true) ?: 1; + $license_duration = get_post_meta($order->product_id, '_wpdd_license_duration', true); // in days + + $expires_at = null; + if ($license_duration && $license_duration > 0) { + $expires_at = date('Y-m-d H:i:s', strtotime("+{$license_duration} days")); + } + + // Insert license + $wpdb->insert( + $wpdb->prefix . 'wpdd_licenses', + array( + 'license_key' => $license_key, + 'product_id' => $order->product_id, + 'order_id' => $order_id, + 'customer_id' => $order->customer_id, + 'customer_email' => $order->customer_email, + 'status' => 'active', + 'max_activations' => $max_activations, + 'expires_at' => $expires_at, + 'created_at' => current_time('mysql') + ), + array('%s', '%d', '%d', '%d', '%s', '%s', '%d', '%s', '%s') + ); + + // Send license key to customer + self::send_license_email($order, $license_key); + + return $license_key; + } + + /** + * Check if license key exists + */ + public static function license_key_exists($license_key) { + global $wpdb; + return $wpdb->get_var($wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_licenses WHERE license_key = %s", + $license_key + )) > 0; + } + + /** + * Validate license key + */ + public static function validate_license($license_key, $product_slug = null, $site_url = null) { + global $wpdb; + + // Get license details + $license = $wpdb->get_row($wpdb->prepare( + "SELECT l.*, p.post_name as product_slug + FROM {$wpdb->prefix}wpdd_licenses l + LEFT JOIN {$wpdb->prefix}posts p ON l.product_id = p.ID + WHERE l.license_key = %s", + $license_key + )); + + if (!$license) { + return array( + 'valid' => false, + 'error' => 'invalid_license', + 'message' => __('Invalid license key.', 'wp-digital-download') + ); + } + + // Check product match + if ($product_slug && $license->product_slug !== $product_slug) { + return array( + 'valid' => false, + 'error' => 'product_mismatch', + 'message' => __('License key is not valid for this product.', 'wp-digital-download') + ); + } + + // Check status + if ($license->status !== 'active') { + return array( + 'valid' => false, + 'error' => 'license_' . $license->status, + 'message' => sprintf(__('License is %s.', 'wp-digital-download'), $license->status) + ); + } + + // Check expiration + if ($license->expires_at && strtotime($license->expires_at) < time()) { + // Update status to expired + $wpdb->update( + $wpdb->prefix . 'wpdd_licenses', + array('status' => 'expired'), + array('id' => $license->id), + array('%s'), + array('%d') + ); + + return array( + 'valid' => false, + 'error' => 'license_expired', + 'message' => __('License has expired.', 'wp-digital-download'), + 'expired_at' => $license->expires_at + ); + } + + // Check activation limit if site_url provided + if ($site_url) { + $activation_count = $wpdb->get_var($wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_license_activations + WHERE license_id = %d AND status = 'active'", + $license->id + )); + + $is_activated = $wpdb->get_var($wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_license_activations + WHERE license_id = %d AND site_url = %s AND status = 'active'", + $license->id, + $site_url + )); + + if (!$is_activated && $activation_count >= $license->max_activations) { + return array( + 'valid' => false, + 'error' => 'activation_limit', + 'message' => sprintf(__('License activation limit reached (%d/%d).', 'wp-digital-download'), + $activation_count, $license->max_activations), + 'activations' => $activation_count, + 'max_activations' => $license->max_activations + ); + } + } + + // Update last checked + $wpdb->update( + $wpdb->prefix . 'wpdd_licenses', + array('last_checked' => current_time('mysql')), + array('id' => $license->id), + array('%s'), + array('%d') + ); + + return array( + 'valid' => true, + 'license' => $license, + 'message' => __('License is valid.', 'wp-digital-download') + ); + } + + /** + * Activate license for a site + */ + public static function activate_license($license_key, $site_url, $site_name = null, $wp_version = null, $php_version = null) { + global $wpdb; + + // Validate license first + $validation = self::validate_license($license_key, null, $site_url); + if (!$validation['valid']) { + return $validation; + } + + $license = $validation['license']; + + // Check if already activated for this site + $existing = $wpdb->get_row($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_license_activations + WHERE license_id = %d AND site_url = %s", + $license->id, + $site_url + )); + + if ($existing && $existing->status === 'active') { + return array( + 'success' => true, + 'already_active' => true, + 'message' => __('License already activated for this site.', 'wp-digital-download') + ); + } + + if ($existing) { + // Reactivate + $wpdb->update( + $wpdb->prefix . 'wpdd_license_activations', + array( + 'status' => 'active', + 'activated_at' => current_time('mysql'), + 'last_checked' => current_time('mysql'), + 'wp_version' => $wp_version, + 'php_version' => $php_version, + 'site_name' => $site_name + ), + array('id' => $existing->id), + array('%s', '%s', '%s', '%s', '%s', '%s'), + array('%d') + ); + } else { + // New activation + $wpdb->insert( + $wpdb->prefix . 'wpdd_license_activations', + array( + 'license_id' => $license->id, + 'license_key' => $license_key, + 'site_url' => $site_url, + 'site_name' => $site_name, + 'activated_at' => current_time('mysql'), + 'last_checked' => current_time('mysql'), + 'wp_version' => $wp_version, + 'php_version' => $php_version, + 'status' => 'active' + ), + array('%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') + ); + } + + // Update activation count + $count = $wpdb->get_var($wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_license_activations + WHERE license_id = %d AND status = 'active'", + $license->id + )); + + $wpdb->update( + $wpdb->prefix . 'wpdd_licenses', + array('activations_count' => $count), + array('id' => $license->id), + array('%d'), + array('%d') + ); + + return array( + 'success' => true, + 'message' => __('License activated successfully.', 'wp-digital-download'), + 'activations' => $count, + 'max_activations' => $license->max_activations + ); + } + + /** + * Deactivate license for a site + */ + public static function deactivate_license($license_key, $site_url) { + global $wpdb; + + // Get license + $license = $wpdb->get_row($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_licenses WHERE license_key = %s", + $license_key + )); + + if (!$license) { + return array( + 'success' => false, + 'error' => 'invalid_license', + 'message' => __('Invalid license key.', 'wp-digital-download') + ); + } + + // Deactivate + $updated = $wpdb->update( + $wpdb->prefix . 'wpdd_license_activations', + array('status' => 'deactivated'), + array( + 'license_id' => $license->id, + 'site_url' => $site_url + ), + array('%s'), + array('%d', '%s') + ); + + if (!$updated) { + return array( + 'success' => false, + 'error' => 'not_activated', + 'message' => __('License not activated for this site.', 'wp-digital-download') + ); + } + + // Update activation count + $count = $wpdb->get_var($wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_license_activations + WHERE license_id = %d AND status = 'active'", + $license->id + )); + + $wpdb->update( + $wpdb->prefix . 'wpdd_licenses', + array('activations_count' => $count), + array('id' => $license->id), + array('%d'), + array('%d') + ); + + return array( + 'success' => true, + 'message' => __('License deactivated successfully.', 'wp-digital-download') + ); + } + + /** + * Send license email to customer + */ + private static function send_license_email($order, $license_key) { + $product = get_post($order->product_id); + $subject = sprintf(__('Your License Key for %s', 'wp-digital-download'), $product->post_title); + + $message = sprintf( + __("Hi %s,\n\nThank you for your purchase!\n\nHere is your license key for %s:\n\n%s\n\nPlease keep this key safe. You will need it to activate and receive updates for your software.\n\nBest regards,\n%s", 'wp-digital-download'), + $order->customer_name ?: $order->customer_email, + $product->post_title, + $license_key, + get_bloginfo('name') + ); + + wp_mail($order->customer_email, $subject, $message); + } + + /** + * Get license details for admin + */ + public static function get_license_details($license_key) { + global $wpdb; + + $license = $wpdb->get_row($wpdb->prepare( + "SELECT l.*, p.post_title as product_name + FROM {$wpdb->prefix}wpdd_licenses l + LEFT JOIN {$wpdb->prefix}posts p ON l.product_id = p.ID + WHERE l.license_key = %s", + $license_key + )); + + if (!$license) { + return null; + } + + // Get activations + $license->activations = $wpdb->get_results($wpdb->prepare( + "SELECT * FROM {$wpdb->prefix}wpdd_license_activations + WHERE license_id = %d + ORDER BY activated_at DESC", + $license->id + )); + + return $license; + } +} \ No newline at end of file diff --git a/includes/class-wpdd-metaboxes.php b/includes/class-wpdd-metaboxes.php index b4862be..13513b2 100644 --- a/includes/class-wpdd-metaboxes.php +++ b/includes/class-wpdd-metaboxes.php @@ -12,6 +12,15 @@ class WPDD_Metaboxes { } public static function add_meta_boxes() { + add_meta_box( + 'wpdd_product_type', + __('Product Type', 'wp-digital-download'), + array(__CLASS__, 'render_product_type_metabox'), + 'wpdd_product', + 'side', + 'high' + ); + add_meta_box( 'wpdd_product_pricing', __('Product Pricing', 'wp-digital-download'), @@ -30,6 +39,15 @@ class WPDD_Metaboxes { 'high' ); + add_meta_box( + 'wpdd_software_licensing', + __('Software Licensing', 'wp-digital-download'), + array(__CLASS__, 'render_software_licensing_metabox'), + 'wpdd_product', + 'normal', + 'high' + ); + add_meta_box( 'wpdd_product_settings', __('Product Settings', 'wp-digital-download'), @@ -78,6 +96,46 @@ class WPDD_Metaboxes { ID, '_wpdd_product_type', true) ?: 'digital_download'; + ?> +

+ +
+ +

+

+ +
+ +

+ + + ID, '_wpdd_files', true); if (!is_array($files)) { @@ -148,6 +206,101 @@ class WPDD_Metaboxes { ID, '_wpdd_git_repository', true); + $git_username = get_post_meta($post->ID, '_wpdd_git_username', true); + $git_token = get_post_meta($post->ID, '_wpdd_git_token', true); + $webhook_passcode = get_post_meta($post->ID, '_wpdd_webhook_passcode', true); + $max_activations = get_post_meta($post->ID, '_wpdd_max_activations', true) ?: 1; + $license_duration = get_post_meta($post->ID, '_wpdd_license_duration', true); + $current_version = get_post_meta($post->ID, '_wpdd_current_version', true); + $min_wp_version = get_post_meta($post->ID, '_wpdd_min_wp_version', true); + $tested_wp_version = get_post_meta($post->ID, '_wpdd_tested_wp_version', true); + + // Generate webhook passcode if not set + if (!$webhook_passcode) { + $webhook_passcode = wp_generate_password(32, false); + update_post_meta($post->ID, '_wpdd_webhook_passcode', $webhook_passcode); + } + + $webhook_url = home_url("/wp-json/wpdd/v1/webhook/{$post->ID}/{$webhook_passcode}"); + ?> +
+

+

+
+ + +

+ +

+
+ + +

+ +

+
+ + +

+ +

+

+
+ + +

+ +

+ +

+ +

+

+
+ + +

+ +

+
+ + +

+ +

+

+
+ +

+ +

+
+ +

+ +

+
+ +

+
+ + + ID, '_wpdd_download_limit', true); $download_expiry = get_post_meta($post->ID, '_wpdd_download_expiry', true); @@ -304,5 +457,52 @@ class WPDD_Metaboxes { update_post_meta($post_id, '_wpdd_watermark_text', sanitize_text_field($_POST['wpdd_watermark_text'])); } + + // Product type + if (isset($_POST['wpdd_product_type'])) { + update_post_meta($post_id, '_wpdd_product_type', + sanitize_text_field($_POST['wpdd_product_type'])); + } + + // Software licensing fields + if (isset($_POST['wpdd_git_repository'])) { + update_post_meta($post_id, '_wpdd_git_repository', + esc_url_raw($_POST['wpdd_git_repository'])); + } + + if (isset($_POST['wpdd_git_username'])) { + update_post_meta($post_id, '_wpdd_git_username', + sanitize_text_field($_POST['wpdd_git_username'])); + } + + if (isset($_POST['wpdd_git_token'])) { + update_post_meta($post_id, '_wpdd_git_token', + sanitize_text_field($_POST['wpdd_git_token'])); + } + + if (isset($_POST['wpdd_max_activations'])) { + update_post_meta($post_id, '_wpdd_max_activations', + intval($_POST['wpdd_max_activations'])); + } + + if (isset($_POST['wpdd_license_duration'])) { + update_post_meta($post_id, '_wpdd_license_duration', + intval($_POST['wpdd_license_duration'])); + } + + if (isset($_POST['wpdd_current_version'])) { + update_post_meta($post_id, '_wpdd_current_version', + sanitize_text_field($_POST['wpdd_current_version'])); + } + + if (isset($_POST['wpdd_min_wp_version'])) { + update_post_meta($post_id, '_wpdd_min_wp_version', + sanitize_text_field($_POST['wpdd_min_wp_version'])); + } + + if (isset($_POST['wpdd_tested_wp_version'])) { + update_post_meta($post_id, '_wpdd_tested_wp_version', + sanitize_text_field($_POST['wpdd_tested_wp_version'])); + } } } \ No newline at end of file diff --git a/includes/class-wpdd-paypal.php b/includes/class-wpdd-paypal.php index a7327cf..deff6c8 100644 --- a/includes/class-wpdd-paypal.php +++ b/includes/class-wpdd-paypal.php @@ -15,7 +15,26 @@ class WPDD_PayPal { } public static function enqueue_paypal_sdk() { - if (!is_page(get_option('wpdd_checkout_page_id'))) { + // Check if we're on a page with the checkout shortcode or if there's a product_id in the URL (checkout page) + global $post; + $is_checkout = false; + + // Check if we're on the configured checkout page + if (is_page(get_option('wpdd_checkout_page_id'))) { + $is_checkout = true; + } + + // Also check if the current page has the checkout shortcode + if ($post && has_shortcode($post->post_content, 'wpdd_checkout')) { + $is_checkout = true; + } + + // Also check if there's a product_id parameter (checkout flow) + if (isset($_GET['product_id']) || isset($_GET['wpdd_action'])) { + $is_checkout = true; + } + + if (!$is_checkout) { return; } @@ -183,6 +202,9 @@ class WPDD_PayPal { $order_id = $wpdb->insert_id; + // Trigger the order completed hook for balance tracking + do_action('wpdd_order_completed', $order_id); + self::generate_download_link($order_id); self::send_purchase_email($order_id); diff --git a/includes/class-wpdd-setup.php b/includes/class-wpdd-setup.php new file mode 100644 index 0000000..49a91ac --- /dev/null +++ b/includes/class-wpdd-setup.php @@ -0,0 +1,169 @@ +id, 'wpdd_product') === false && $screen->id !== 'dashboard') { + return; + } + + ?> +
+

+

+ +
+ + + + + + + +
+ +
+

+
    +
  • -
  • +
  • -
  • +
  • -
  • +
  • -
  • +
+
+ + +
+ + + $page->post_title, + 'edit_url' => admin_url('post.php?post=' . $page_id . '&action=edit'), + 'view_url' => get_permalink($page_id) + ); + } + } + + update_option('wpdd_setup_completed', true); + delete_option('wpdd_show_setup_notice'); + + wp_send_json_success(array( + 'message' => sprintf(__('%d pages created successfully!', 'wp-digital-download'), count($pages_info)), + 'pages' => $pages_info + )); + } else { + wp_send_json_error(__('No pages were created. They may already exist.', 'wp-digital-download')); + } + } + + public static function dismiss_setup_notice() { + check_ajax_referer('wpdd_setup_nonce', 'nonce'); + + if (!current_user_can('manage_options')) { + wp_send_json_error(__('Permission denied.', 'wp-digital-download')); + } + + update_option('wpdd_setup_completed', true); + delete_option('wpdd_show_setup_notice'); + + wp_send_json_success(); + } +} \ No newline at end of file diff --git a/includes/wpdd-plugin-updater.php b/includes/wpdd-plugin-updater.php new file mode 100644 index 0000000..44c88f0 --- /dev/null +++ b/includes/wpdd-plugin-updater.php @@ -0,0 +1,471 @@ +plugin_file = $plugin_file; + $this->plugin_slug = basename($plugin_file, '.php'); + $this->license_key = $license_key; + $this->update_server = trailingslashit($update_server); + + // Get plugin version from header + if (!function_exists('get_plugin_data')) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + $plugin_data = get_plugin_data($plugin_file); + $this->version = $plugin_data['Version']; + + $this->transient_key = 'wpdd_update_' . $this->plugin_slug; + + // Initialize hooks + $this->init_hooks(); + + // Add settings page if requested + if (isset($args['add_settings_page']) && $args['add_settings_page']) { + $this->add_settings_page(); + } + } + + /** + * Initialize WordPress hooks + */ + private function init_hooks() { + add_filter('pre_set_site_transient_update_plugins', array($this, 'check_for_update')); + add_filter('plugins_api', array($this, 'plugin_info'), 10, 3); + add_filter('upgrader_pre_download', array($this, 'maybe_download_package'), 10, 3); + + // Clean up transients on plugin activation/deactivation + register_activation_hook($this->plugin_file, array($this, 'delete_transients')); + register_deactivation_hook($this->plugin_file, array($this, 'delete_transients')); + } + + /** + * Check for plugin updates + */ + public function check_for_update($transient) { + if (empty($transient->checked)) { + return $transient; + } + + // Get cached update info + $update_cache = get_transient($this->transient_key); + if ($update_cache !== false) { + if (isset($update_cache->update_available) && $update_cache->update_available) { + $transient->response[$this->plugin_file] = $update_cache; + } + return $transient; + } + + // Check for update from server + $update_info = $this->request_update_info(); + + if ($update_info && isset($update_info['update_available']) && $update_info['update_available']) { + $plugin_data = array( + 'slug' => $this->plugin_slug, + 'plugin' => $this->plugin_file, + 'new_version' => $update_info['version'], + 'url' => $update_info['url'], + 'package' => $update_info['package'], + 'tested' => $update_info['tested'], + 'requires' => $update_info['requires'], + 'requires_php' => $update_info['requires_php'], + 'compatibility' => new stdClass() + ); + + $update_cache = (object) $plugin_data; + $update_cache->update_available = true; + + // Cache for 12 hours + set_transient($this->transient_key, $update_cache, 12 * HOUR_IN_SECONDS); + + $transient->response[$this->plugin_file] = $update_cache; + } else { + // No update available - cache negative result for 12 hours + $update_cache = new stdClass(); + $update_cache->update_available = false; + set_transient($this->transient_key, $update_cache, 12 * HOUR_IN_SECONDS); + } + + return $transient; + } + + /** + * Provide plugin information for the update screen + */ + public function plugin_info($false, $action, $args) { + if ($action !== 'plugin_information' || $args->slug !== $this->plugin_slug) { + return $false; + } + + $update_info = $this->request_update_info(); + + if (!$update_info) { + return $false; + } + + return (object) array( + 'slug' => $this->plugin_slug, + 'name' => $update_info['name'] ?? $this->plugin_slug, + 'version' => $update_info['version'] ?? $this->version, + 'author' => $update_info['author'] ?? '', + 'homepage' => $update_info['url'] ?? '', + 'requires' => $update_info['requires'] ?? '5.0', + 'tested' => $update_info['tested'] ?? get_bloginfo('version'), + 'requires_php' => $update_info['requires_php'] ?? '7.0', + 'download_link' => $update_info['package'] ?? '', + 'sections' => array( + 'changelog' => $update_info['changelog'] ?? '', + 'description' => $update_info['description'] ?? '' + ), + 'banners' => array(), + 'icons' => array() + ); + } + + /** + * Handle package download with license validation + */ + public function maybe_download_package($reply, $package, $upgrader) { + // Check if this is our plugin's package + if (strpos($package, $this->update_server) === false || strpos($package, $this->plugin_slug) === false) { + return $reply; + } + + // Validate license before download + $license_valid = $this->validate_license(); + if (!$license_valid) { + return new WP_Error('license_invalid', __('Your license key is invalid or expired. Please update your license key.')); + } + + return $reply; + } + + /** + * Request update information from server + */ + private function request_update_info() { + $url = $this->update_server . "wp-json/wpdd/v1/check-update/{$this->plugin_slug}"; + $url = add_query_arg(array( + 'license_key' => $this->license_key, + 'version' => $this->version, + 'site_url' => home_url() + ), $url); + + $response = wp_remote_get($url, array( + 'timeout' => 15, + 'headers' => array( + 'User-Agent' => 'WPDD-Updater/' . $this->version . '; ' . home_url() + ) + )); + + if (is_wp_error($response)) { + error_log('WPDD Updater: Failed to check for updates - ' . $response->get_error_message()); + return false; + } + + $body = wp_remote_retrieve_body($response); + $data = json_decode($body, true); + + if (!$data || !isset($data['success'])) { + error_log('WPDD Updater: Invalid response from update server'); + return false; + } + + if (!$data['success']) { + if (isset($data['error'])) { + error_log('WPDD Updater: ' . $data['error'] . ' - ' . ($data['message'] ?? '')); + } + return false; + } + + return $data; + } + + /** + * Validate license with server + */ + public function validate_license() { + if (empty($this->license_key)) { + return false; + } + + $url = $this->update_server . 'wp-json/wpdd/v1/validate-license'; + + $response = wp_remote_post($url, array( + 'timeout' => 15, + 'body' => array( + 'license_key' => $this->license_key, + 'product_slug' => $this->plugin_slug, + 'site_url' => home_url() + ), + 'headers' => array( + 'User-Agent' => 'WPDD-Updater/' . $this->version . '; ' . home_url() + ) + )); + + if (is_wp_error($response)) { + return false; + } + + $body = wp_remote_retrieve_body($response); + $data = json_decode($body, true); + + return $data && isset($data['success']) && $data['success']; + } + + /** + * Activate license + */ + public function activate_license($license_key = null) { + if ($license_key) { + $this->license_key = $license_key; + } + + if (empty($this->license_key)) { + return array( + 'success' => false, + 'message' => __('Please enter a license key.') + ); + } + + $url = $this->update_server . 'wp-json/wpdd/v1/activate-license'; + + $response = wp_remote_post($url, array( + 'timeout' => 15, + 'body' => array( + 'license_key' => $this->license_key, + 'site_url' => home_url(), + 'site_name' => get_bloginfo('name'), + 'wp_version' => get_bloginfo('version'), + 'php_version' => PHP_VERSION + ), + 'headers' => array( + 'User-Agent' => 'WPDD-Updater/' . $this->version . '; ' . home_url() + ) + )); + + if (is_wp_error($response)) { + return array( + 'success' => false, + 'message' => $response->get_error_message() + ); + } + + $body = wp_remote_retrieve_body($response); + $data = json_decode($body, true); + + if (!$data) { + return array( + 'success' => false, + 'message' => __('Invalid response from server.') + ); + } + + return $data; + } + + /** + * Deactivate license + */ + public function deactivate_license() { + if (empty($this->license_key)) { + return array( + 'success' => false, + 'message' => __('No license key to deactivate.') + ); + } + + $url = $this->update_server . 'wp-json/wpdd/v1/deactivate-license'; + + $response = wp_remote_post($url, array( + 'timeout' => 15, + 'body' => array( + 'license_key' => $this->license_key, + 'site_url' => home_url() + ), + 'headers' => array( + 'User-Agent' => 'WPDD-Updater/' . $this->version . '; ' . home_url() + ) + )); + + if (is_wp_error($response)) { + return array( + 'success' => false, + 'message' => $response->get_error_message() + ); + } + + $body = wp_remote_retrieve_body($response); + $data = json_decode($body, true); + + return $data ?: array( + 'success' => false, + 'message' => __('Invalid response from server.') + ); + } + + /** + * Add a simple settings page for license management + */ + private function add_settings_page() { + add_action('admin_menu', array($this, 'add_license_menu')); + add_action('admin_init', array($this, 'handle_license_actions')); + } + + /** + * Add license menu page + */ + public function add_license_menu() { + add_options_page( + sprintf(__('%s License', 'default'), $this->plugin_slug), + sprintf(__('%s License', 'default'), $this->plugin_slug), + 'manage_options', + $this->plugin_slug . '-license', + array($this, 'render_license_page') + ); + } + + /** + * Handle license activation/deactivation + */ + public function handle_license_actions() { + if (!current_user_can('manage_options')) { + return; + } + + $option_key = $this->plugin_slug . '_license_key'; + + if (isset($_POST['activate_license'])) { + if (!wp_verify_nonce($_POST['license_nonce'], 'wpdd_license_nonce')) { + return; + } + + $license_key = sanitize_text_field($_POST['license_key']); + $result = $this->activate_license($license_key); + + if ($result['success']) { + update_option($option_key, $license_key); + $this->license_key = $license_key; + add_settings_error('wpdd_license', 'activated', $result['message'], 'updated'); + } else { + add_settings_error('wpdd_license', 'activation_failed', $result['message'], 'error'); + } + } + + if (isset($_POST['deactivate_license'])) { + if (!wp_verify_nonce($_POST['license_nonce'], 'wpdd_license_nonce')) { + return; + } + + $result = $this->deactivate_license(); + + if ($result['success']) { + delete_option($option_key); + $this->license_key = ''; + add_settings_error('wpdd_license', 'deactivated', $result['message'], 'updated'); + } else { + add_settings_error('wpdd_license', 'deactivation_failed', $result['message'], 'error'); + } + } + } + + /** + * Render license management page + */ + public function render_license_page() { + $option_key = $this->plugin_slug . '_license_key'; + $license_key = get_option($option_key, ''); + $license_status = $this->validate_license(); + + ?> +
+

plugin_slug)); ?>

+ + + +
+ + + + + + + +
+ + + + + + + + + + + +
+ + +

+ +

+ +

+ +

+ +
+ +

+
    +
  1. +
  2. +
  3. +
+
+ transient_key); + delete_site_transient('update_plugins'); + } +} + +} // End class exists check \ No newline at end of file diff --git a/tests/webhook-samples.md b/tests/webhook-samples.md new file mode 100644 index 0000000..25905a2 --- /dev/null +++ b/tests/webhook-samples.md @@ -0,0 +1,136 @@ +# Gitea Webhook Integration Test Samples + +The corrected webhook implementation now properly receives and processes webhook notifications FROM Git platforms like Gitea when new releases are published. + +## Sample Gitea Release Webhook Payload + +When a release is published in Gitea, it sends a webhook payload like this: + +```json +{ + "action": "published", + "release": { + "id": 123, + "tag_name": "v1.2.0", + "target_commitish": "main", + "name": "Version 1.2.0", + "body": "## What's New\n- Added new feature X\n- Fixed bug Y\n- Improved performance\n\n## Breaking Changes\n- None", + "url": "https://git.example.com/user/repo/releases/tag/v1.2.0", + "html_url": "https://git.example.com/user/repo/releases/tag/v1.2.0", + "tarball_url": "https://git.example.com/user/repo/archive/v1.2.0.tar.gz", + "zipball_url": "https://git.example.com/user/repo/archive/v1.2.0.zip", + "draft": false, + "prerelease": false, + "created_at": "2025-01-15T10:30:00Z", + "published_at": "2025-01-15T10:30:00Z", + "author": { + "id": 1, + "login": "developer", + "full_name": "Developer Name" + } + }, + "repository": { + "id": 456, + "name": "my-wordpress-plugin", + "full_name": "user/my-wordpress-plugin", + "html_url": "https://git.example.com/user/my-wordpress-plugin", + "clone_url": "https://git.example.com/user/my-wordpress-plugin.git" + }, + "sender": { + "id": 1, + "login": "developer" + } +} +``` + +## How the Webhook Handler Processes This + +1. **Authentication**: Validates the passcode in the URL path +2. **Event Detection**: Identifies this as a Gitea release event (`action: "published"`) +3. **Version Extraction**: Extracts version "1.2.0" from `tag_name: "v1.2.0"` +4. **Changelog Processing**: Uses the release `body` field for changelog +5. **Package Creation**: Clones the repository at tag `v1.2.0` and creates distribution package +6. **Database Storage**: Stores the new version in `wpdd_software_versions` table +7. **Customer Updates**: Customers with valid licenses can now receive the update + +## Sample GitHub Release Webhook Payload + +GitHub uses a similar but slightly different structure: + +```json +{ + "action": "published", + "release": { + "tag_name": "v1.2.0", + "target_commitish": "main", + "name": "Version 1.2.0", + "body": "Release notes here...", + "draft": false, + "prerelease": false + }, + "repository": { + "name": "my-plugin", + "clone_url": "https://github.com/user/my-plugin.git" + } +} +``` + +## Sample Git Push with Tag Webhook + +For platforms that send tag push events instead of release events: + +```json +{ + "ref": "refs/tags/v1.2.0", + "repository": { + "clone_url": "https://git.example.com/user/repo.git" + }, + "commits": [ + { + "id": "abc123", + "message": "Release version 1.2.0" + } + ], + "head_commit": { + "id": "abc123", + "message": "Release version 1.2.0" + }, + "after": "abc123" +} +``` + +## Webhook URL Format + +The webhook URLs generated for each software product follow this format: + +``` +https://streamers.channel/wp-json/wpdd/v1/webhook/{product_id}/{passcode} +``` + +Example: +``` +https://streamers.channel/wp-json/wpdd/v1/webhook/123/a1b2c3d4e5f6 +``` + +Where: +- `123` is the WordPress post ID of the software product +- `a1b2c3d4e5f6` is the randomly generated passcode for security + +## Testing the Integration + +To test this webhook integration: + +1. Create a software product in WordPress admin +2. Set the product type to "Software License" +3. Configure the Git repository URL and credentials +4. Copy the generated webhook URL from the metabox +5. Add the webhook URL to your Gitea repository settings: + - Go to Settings → Webhooks + - Add new webhook with the WPDD URL + - Select "Release events" as the trigger + - Set Content-Type to "application/json" +6. Create and publish a new release in Gitea +7. Check the `wpdd_webhook_events` table to see the received payload +8. Check the `wpdd_software_versions` table to see the processed release + +This corrected implementation properly receives release notifications FROM Git platforms like Gitea, rather than attempting to push to them. \ No newline at end of file diff --git a/wp-digital-download.php b/wp-digital-download.php index 6ef98e2..2108d57 100644 --- a/wp-digital-download.php +++ b/wp-digital-download.php @@ -39,6 +39,7 @@ final class WP_Digital_Download { private function load_dependencies() { $files = array( 'includes/class-wpdd-install.php', + 'includes/class-wpdd-setup.php', 'includes/class-wpdd-post-types.php', 'includes/class-wpdd-roles.php', 'includes/class-wpdd-metaboxes.php', @@ -46,6 +47,8 @@ final class WP_Digital_Download { 'includes/class-wpdd-paypal.php', 'includes/class-wpdd-download-handler.php', 'includes/class-wpdd-customer.php', + 'includes/class-wpdd-license-manager.php', + 'includes/class-wpdd-api.php', 'includes/class-wpdd-orders.php', 'includes/class-wpdd-file-protection.php', 'includes/class-wpdd-watermark.php', @@ -168,7 +171,25 @@ final class WP_Digital_Download { error_log('WPDD Error: WPDD_Ajax class not found'); } + if (class_exists('WPDD_License_Manager')) { + WPDD_License_Manager::init(); + } else { + error_log('WPDD Error: WPDD_License_Manager class not found'); + } + + if (class_exists('WPDD_API')) { + WPDD_API::init(); + } else { + error_log('WPDD Error: WPDD_API class not found'); + } + if (is_admin()) { + if (class_exists('WPDD_Setup')) { + WPDD_Setup::init(); + } else { + error_log('WPDD Error: WPDD_Setup class not found'); + } + if (class_exists('WPDD_Admin')) { WPDD_Admin::init(); } else {