324 lines
12 KiB
PHP
324 lines
12 KiB
PHP
<?php
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class WPDD_PayPal {
|
|
|
|
public static function init() {
|
|
add_action('wp_enqueue_scripts', array(__CLASS__, 'enqueue_paypal_sdk'));
|
|
add_action('wp_ajax_wpdd_create_paypal_order', array(__CLASS__, 'create_order'));
|
|
add_action('wp_ajax_nopriv_wpdd_create_paypal_order', array(__CLASS__, 'create_order'));
|
|
add_action('wp_ajax_wpdd_capture_paypal_order', array(__CLASS__, 'capture_order'));
|
|
add_action('wp_ajax_nopriv_wpdd_capture_paypal_order', array(__CLASS__, 'capture_order'));
|
|
}
|
|
|
|
public static function enqueue_paypal_sdk() {
|
|
// 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;
|
|
}
|
|
|
|
$client_id = get_option('wpdd_paypal_client_id');
|
|
$mode = get_option('wpdd_paypal_mode', 'sandbox');
|
|
|
|
if (!$client_id) {
|
|
return;
|
|
}
|
|
|
|
wp_enqueue_script(
|
|
'paypal-sdk',
|
|
'https://www.paypal.com/sdk/js?client-id=' . $client_id . '¤cy=USD',
|
|
array(),
|
|
null,
|
|
true
|
|
);
|
|
|
|
wp_enqueue_script(
|
|
'wpdd-paypal',
|
|
WPDD_PLUGIN_URL . 'assets/js/paypal.js',
|
|
array('jquery', 'paypal-sdk'),
|
|
WPDD_VERSION,
|
|
true
|
|
);
|
|
|
|
wp_localize_script('wpdd-paypal', 'wpdd_paypal', array(
|
|
'ajax_url' => admin_url('admin-ajax.php'),
|
|
'nonce' => wp_create_nonce('wpdd-paypal-nonce'),
|
|
'mode' => $mode
|
|
));
|
|
}
|
|
|
|
public static function create_order() {
|
|
check_ajax_referer('wpdd-paypal-nonce', 'nonce');
|
|
|
|
$product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;
|
|
|
|
if (!$product_id) {
|
|
wp_send_json_error('Invalid product');
|
|
}
|
|
|
|
$product = get_post($product_id);
|
|
|
|
if (!$product || $product->post_type !== 'wpdd_product') {
|
|
wp_send_json_error('Product not found');
|
|
}
|
|
|
|
$price = get_post_meta($product_id, '_wpdd_price', true);
|
|
$sale_price = get_post_meta($product_id, '_wpdd_sale_price', true);
|
|
$final_price = ($sale_price && $sale_price < $price) ? $sale_price : $price;
|
|
|
|
$order_data = array(
|
|
'intent' => 'CAPTURE',
|
|
'purchase_units' => array(
|
|
array(
|
|
'reference_id' => 'wpdd_' . $product_id . '_' . time(),
|
|
'description' => substr($product->post_title, 0, 127),
|
|
'amount' => array(
|
|
'currency_code' => 'USD',
|
|
'value' => number_format($final_price, 2, '.', '')
|
|
)
|
|
)
|
|
),
|
|
'application_context' => array(
|
|
'brand_name' => get_bloginfo('name'),
|
|
'return_url' => add_query_arg('wpdd_paypal_return', '1', get_permalink(get_option('wpdd_thank_you_page_id'))),
|
|
'cancel_url' => add_query_arg('wpdd_paypal_cancel', '1', get_permalink(get_option('wpdd_checkout_page_id')))
|
|
)
|
|
);
|
|
|
|
$paypal_order = self::api_request('/v2/checkout/orders', $order_data, 'POST');
|
|
|
|
if (isset($paypal_order['id'])) {
|
|
$_SESSION['wpdd_paypal_order_' . $paypal_order['id']] = array(
|
|
'product_id' => $product_id,
|
|
'amount' => $final_price,
|
|
'customer_email' => sanitize_email($_POST['customer_email'] ?? ''),
|
|
'customer_name' => sanitize_text_field($_POST['customer_name'] ?? '')
|
|
);
|
|
|
|
wp_send_json_success(array('orderID' => $paypal_order['id']));
|
|
} else {
|
|
wp_send_json_error('Failed to create PayPal order');
|
|
}
|
|
}
|
|
|
|
public static function capture_order() {
|
|
check_ajax_referer('wpdd-paypal-nonce', 'nonce');
|
|
|
|
$paypal_order_id = isset($_POST['orderID']) ? sanitize_text_field($_POST['orderID']) : '';
|
|
|
|
if (!$paypal_order_id) {
|
|
wp_send_json_error('Invalid order ID');
|
|
}
|
|
|
|
$capture_response = self::api_request('/v2/checkout/orders/' . $paypal_order_id . '/capture', array(), 'POST');
|
|
|
|
if (isset($capture_response['status']) && $capture_response['status'] === 'COMPLETED') {
|
|
$session_data = $_SESSION['wpdd_paypal_order_' . $paypal_order_id] ?? array();
|
|
|
|
// Add error logging for debugging session issues
|
|
if (empty($session_data)) {
|
|
error_log('WPDD PayPal Error: No session data found for PayPal order ' . $paypal_order_id);
|
|
error_log('WPDD PayPal Debug: Session ID: ' . session_id());
|
|
error_log('WPDD PayPal Debug: Available sessions: ' . print_r($_SESSION ?? array(), true));
|
|
wp_send_json_error('Session data not found - order cannot be processed');
|
|
return;
|
|
}
|
|
|
|
$order_number = 'WPDD-' . strtoupper(uniqid());
|
|
|
|
global $wpdb;
|
|
|
|
$customer_id = 0;
|
|
$customer_email = $session_data['customer_email'];
|
|
$customer_name = $session_data['customer_name'];
|
|
|
|
if (is_user_logged_in()) {
|
|
$current_user = wp_get_current_user();
|
|
$customer_id = $current_user->ID;
|
|
$customer_email = $current_user->user_email;
|
|
$customer_name = $current_user->display_name;
|
|
} elseif (!empty($_POST['create_account']) && !empty($customer_email)) {
|
|
$username = strstr($customer_email, '@', true) . '_' . wp_rand(1000, 9999);
|
|
$password = wp_generate_password();
|
|
|
|
$user_id = wp_create_user($username, $password, $customer_email);
|
|
|
|
if (!is_wp_error($user_id)) {
|
|
$customer_id = $user_id;
|
|
wp_update_user(array(
|
|
'ID' => $user_id,
|
|
'display_name' => $customer_name,
|
|
'first_name' => $customer_name
|
|
));
|
|
|
|
$user = new WP_User($user_id);
|
|
$user->set_role('wpdd_customer');
|
|
|
|
wp_new_user_notification($user_id, null, 'both');
|
|
}
|
|
}
|
|
|
|
$product = get_post($session_data['product_id']);
|
|
|
|
$wpdb->insert(
|
|
$wpdb->prefix . 'wpdd_orders',
|
|
array(
|
|
'order_number' => $order_number,
|
|
'product_id' => $session_data['product_id'],
|
|
'customer_id' => $customer_id,
|
|
'creator_id' => $product->post_author,
|
|
'status' => 'completed',
|
|
'payment_method' => 'paypal',
|
|
'transaction_id' => $capture_response['id'],
|
|
'amount' => $session_data['amount'],
|
|
'currency' => 'USD',
|
|
'customer_email' => $customer_email,
|
|
'customer_name' => $customer_name,
|
|
'purchase_date' => current_time('mysql')
|
|
),
|
|
array('%s', '%d', '%d', '%d', '%s', '%s', '%s', '%f', '%s', '%s', '%s', '%s')
|
|
);
|
|
|
|
$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);
|
|
|
|
update_post_meta($session_data['product_id'], '_wpdd_sales_count',
|
|
intval(get_post_meta($session_data['product_id'], '_wpdd_sales_count', true)) + 1);
|
|
|
|
unset($_SESSION['wpdd_paypal_order_' . $paypal_order_id]);
|
|
|
|
wp_send_json_success(array(
|
|
'redirect_url' => add_query_arg(
|
|
'order_id',
|
|
$order_number,
|
|
get_permalink(get_option('wpdd_thank_you_page_id'))
|
|
)
|
|
));
|
|
} else {
|
|
wp_send_json_error('Payment capture failed');
|
|
}
|
|
}
|
|
|
|
private static function api_request($endpoint, $data = array(), $method = 'GET') {
|
|
$mode = get_option('wpdd_paypal_mode', 'sandbox');
|
|
$client_id = get_option('wpdd_paypal_client_id');
|
|
$secret = get_option('wpdd_paypal_secret');
|
|
|
|
if (!$client_id || !$secret) {
|
|
return false;
|
|
}
|
|
|
|
$base_url = $mode === 'live'
|
|
? 'https://api.paypal.com'
|
|
: 'https://api.sandbox.paypal.com';
|
|
|
|
$auth = base64_encode($client_id . ':' . $secret);
|
|
|
|
$args = array(
|
|
'method' => $method,
|
|
'headers' => array(
|
|
'Authorization' => 'Basic ' . $auth,
|
|
'Content-Type' => 'application/json'
|
|
),
|
|
'timeout' => 30
|
|
);
|
|
|
|
if (!empty($data)) {
|
|
$args['body'] = json_encode($data);
|
|
}
|
|
|
|
$response = wp_remote_request($base_url . $endpoint, $args);
|
|
|
|
if (is_wp_error($response)) {
|
|
return false;
|
|
}
|
|
|
|
$body = wp_remote_retrieve_body($response);
|
|
return json_decode($body, true);
|
|
}
|
|
|
|
private static function generate_download_link($order_id) {
|
|
global $wpdb;
|
|
|
|
$token = wp_hash(uniqid() . $order_id . time());
|
|
$expires_at = date('Y-m-d H:i:s', strtotime('+7 days'));
|
|
|
|
$wpdb->insert(
|
|
$wpdb->prefix . 'wpdd_download_links',
|
|
array(
|
|
'order_id' => $order_id,
|
|
'token' => $token,
|
|
'expires_at' => $expires_at,
|
|
'max_downloads' => 5,
|
|
'created_at' => current_time('mysql')
|
|
),
|
|
array('%d', '%s', '%s', '%d', '%s')
|
|
);
|
|
|
|
return $token;
|
|
}
|
|
|
|
private static function send_purchase_email($order_id) {
|
|
global $wpdb;
|
|
|
|
$order = $wpdb->get_row($wpdb->prepare(
|
|
"SELECT o.*, p.post_title as product_name, dl.token
|
|
FROM {$wpdb->prefix}wpdd_orders o
|
|
LEFT JOIN {$wpdb->posts} p ON o.product_id = p.ID
|
|
LEFT JOIN {$wpdb->prefix}wpdd_download_links dl ON o.id = dl.order_id
|
|
WHERE o.id = %d",
|
|
$order_id
|
|
));
|
|
|
|
if (!$order) {
|
|
return;
|
|
}
|
|
|
|
$download_url = add_query_arg(array(
|
|
'wpdd_download_token' => $order->token
|
|
), home_url());
|
|
|
|
$subject = sprintf(__('Your Purchase from %s', 'wp-digital-download'), get_bloginfo('name'));
|
|
|
|
$message = sprintf(
|
|
__("Hi %s,\n\nThank you for your purchase!\n\n", 'wp-digital-download'),
|
|
$order->customer_name
|
|
);
|
|
$message .= sprintf(__("Order Number: %s\n", 'wp-digital-download'), $order->order_number);
|
|
$message .= sprintf(__("Product: %s\n", 'wp-digital-download'), $order->product_name);
|
|
$message .= sprintf(__("Amount: $%s\n\n", 'wp-digital-download'), number_format($order->amount, 2));
|
|
$message .= __("Download your product here:\n", 'wp-digital-download');
|
|
$message .= $download_url . "\n\n";
|
|
$message .= __("This download link will expire in 7 days.\n\n", 'wp-digital-download');
|
|
$message .= sprintf(__("Best regards,\n%s", 'wp-digital-download'), get_bloginfo('name'));
|
|
|
|
wp_mail($order->customer_email, $subject, $message);
|
|
}
|
|
} |