/** * Sets a Transaction ID in post meta for the given Payment ID * * @since 2.1 * @param int payment_id Payment ID * @param string transaction_id The transaciton ID from the gateway */ function edd_set_payment_transaction_id($payment_id = 0, $transaction_id = '') { if (empty($payment_id) || empty($transaction_id)) { return false; } $transaction_id = apply_filters('edd_set_payment_transaction_id', $transaction_id, $payment_id); return edd_update_payment_meta($payment_id, '_edd_payment_transaction_id', $transaction_id); }
/** * Process the purchase and create the charge in Amazon * * @access public * @since 2.4 * @param $purchase_data array Cart details * @return void */ public function process_purchase($purchase_data) { if (empty($purchase_data['post_data']['edd_amazon_reference_id'])) { edd_set_error('missing_reference_id', __('Missing Reference ID, please try again', 'edd')); } $errors = edd_get_errors(); if ($errors) { edd_send_back_to_checkout('?payment-mode=amazon'); } $args = apply_filters('edd_amazon_charge_args', array('merchant_id' => edd_get_option('amazon_seller_id', ''), 'amazon_reference_id' => $purchase_data['post_data']['edd_amazon_reference_id'], 'authorization_reference_id' => $purchase_data['purchase_key'], 'charge_amount' => $purchase_data['price'], 'currency_code' => edd_get_currency(), 'charge_note' => html_entity_decode(edd_get_purchase_summary($purchase_data, false)), 'charge_order_id' => $purchase_data['purchase_key'], 'store_name' => remove_accents(wp_specialchars_decode(get_bloginfo('name'), ENT_QUOTES)), 'transaction_timeout' => 0), $purchase_data); $args['platform_id'] = 'A3JST9YM1SX7LB'; $charge = $this->client->charge($args); if (200 == $charge->response['Status']) { $charge = new ResponseParser($charge->response); $charge = $charge->toArray(); $status = $charge['AuthorizeResult']['AuthorizationDetails']['AuthorizationStatus']['State']; if ('Declined' === $status) { $reason = $charge['AuthorizeResult']['AuthorizationDetails']['AuthorizationStatus']['ReasonCode']; edd_set_error('payment_declined', sprintf(__('Your payment could not be authorized, please try a different payment method. Reason: %s', 'edd'), $reason)); edd_send_back_to_checkout('?payment-mode=amazon&amazon_reference_id=' . $purchase_data['post_data']['edd_amazon_reference_id']); } // Setup payment data to be recorded $payment_data = array('price' => $purchase_data['price'], 'date' => $purchase_data['date'], 'user_email' => $purchase_data['user_email'], 'purchase_key' => $purchase_data['purchase_key'], 'currency' => edd_get_currency(), 'downloads' => $purchase_data['downloads'], 'user_info' => $purchase_data['user_info'], 'cart_details' => $purchase_data['cart_details'], 'gateway' => $this->gateway_id, 'status' => 'pending'); $payment_id = edd_insert_payment($payment_data); $authorization_id = $charge['AuthorizeResult']['AuthorizationDetails']['AmazonAuthorizationId']; $capture_id = str_replace('-A', '-C', $authorization_id); $reference_id = sanitize_text_field($_POST['edd_amazon_reference_id']); // Confirm the capture was completed $capture = $this->client->getCaptureDetails(array('merchant_id' => edd_get_option('amazon_seller_id', ''), 'amazon_capture_id' => $capture_id)); $capture = new ResponseParser($capture->response); $capture = $capture->toArray(); // Check capture status edd_update_payment_meta($payment_id, '_edd_amazon_authorization_id', $authorization_id); edd_update_payment_meta($payment_id, '_edd_amazon_capture_id', $capture_id); edd_set_payment_transaction_id($payment_id, $reference_id); edd_update_payment_status($payment_id, 'publish'); // Empty the shopping cart edd_empty_cart(); edd_send_to_success_page(); } else { // Set an error edd_set_error('amazon_error', sprintf(__('There was an issue processing your payment. Amazon error: %s', 'edd'), print_r($charge, true))); edd_send_back_to_checkout('?payment-mode=amazon&amazon_reference_id=' . $purchase_data['post_data']['edd_amazon_reference_id']); } }
/** * When a payment is inserted, possibly registers a user * * If this is the first purchase, disables the EDD Core user verification system * * @since 1.3 */ public function maybe_insert_user($payment_id, $payment_data) { // It's possible that a extension (like recurring) has already auto-inserted a user, let's verify if (!is_user_logged_in()) { $customer = new EDD_Customer($payment_data['user_info']['email']); $payment_ids = explode(',', $customer->payment_ids); if (is_array($payment_ids) && !empty($payment_ids)) { $payment_ids = array_map('absint', $payment_ids); // If the payment inserted is the only payment, we don't need verification if (1 === count($payment_ids) && in_array($payment_id, $payment_ids)) { remove_action('user_register', 'edd_connect_existing_customer_to_new_user', 10, 1); remove_action('user_register', 'edd_add_past_purchases_to_new_user', 10, 1); } } $user_id = $this->create_user($payment_data, $payment_id); } else { $user_id = get_current_user_id(); } // Validate inserted user if (is_wp_error($user_id) || empty($user_id)) { return; } $payment_meta = edd_get_payment_meta($payment_id); $payment_meta['user_info']['id'] = $user_id; edd_update_payment_meta($payment_id, '_edd_payment_user_id', $user_id); edd_update_payment_meta($payment_id, '_edd_payment_meta', $payment_meta); }
/** * Looks up purchases by email that match the registering user * * This is for users that purchased as a guest and then came * back and created an account. * * @access public * @since 1.6 * @param $user_id INT - the new user's ID * @return void */ function edd_add_past_purchases_to_new_user($user_id) { $email = get_the_author_meta('user_email', $user_id); $payments = edd_get_payments(array('s' => $email)); if ($payments) { foreach ($payments as $payment) { if (intval(edd_get_payment_user_id($payment->ID)) > 0) { continue; } // This payment already associated with an account $meta = edd_get_payment_meta($payment->ID); $meta['user_info'] = maybe_unserialize($meta['user_info']); $meta['user_info']['id'] = $user_id; $meta['user_info'] = $meta['user_info']; // Store the updated user ID in the payment meta edd_update_payment_meta($payment->ID, '_edd_payment_meta', $meta); edd_update_payment_meta($payment->ID, '_edd_payment_user_id', $user_id); } } }
/** * Process the payment details edit * * @access private * @since 1.9 * @return void */ function edd_update_payment_details($data) { if (!current_user_can('edit_shop_payment', $data['edd_payment_id'])) { wp_die(__('You do not have permission to edit this payment record', 'edd'), __('Error', 'edd')); } check_admin_referer('edd_update_payment_details_nonce'); // Retrieve the payment ID $payment_id = absint($data['edd_payment_id']); // Retrieve existing payment meta $meta = edd_get_payment_meta($payment_id); $user_info = edd_get_payment_meta_user_info($payment_id); $status = $data['edd-payment-status']; $unlimited = isset($data['edd-unlimited-downloads']) ? '1' : ''; $user_id = intval($data['edd-payment-user-id']); $date = sanitize_text_field($data['edd-payment-date']); $hour = sanitize_text_field($data['edd-payment-time-hour']); $minute = sanitize_text_field($data['edd-payment-time-min']); $email = sanitize_text_field($data['edd-payment-user-email']); $names = sanitize_text_field($data['edd-payment-user-name']); $address = array_map('trim', $data['edd-payment-address'][0]); $total = edd_sanitize_amount($_POST['edd-payment-total']); $tax = isset($_POST['edd-payment-tax']) ? edd_sanitize_amount($_POST['edd-payment-tax']) : 0; // Setup date from input values $date = date('Y-m-d', strtotime($date)) . ' ' . $hour . ':' . $minute . ':00'; // Setup first and last name from input values $names = explode(' ', $names); $first_name = !empty($names[0]) ? $names[0] : ''; $last_name = ''; if (!empty($names[1])) { unset($names[0]); $last_name = implode(' ', $names); } // Setup purchased Downloads and price options $updated_downloads = isset($_POST['edd-payment-details-downloads']) ? $_POST['edd-payment-details-downloads'] : false; if ($updated_downloads && !empty($_POST['edd-payment-downloads-changed'])) { $downloads = array(); $cart_details = array(); $i = 0; foreach ($updated_downloads as $download) { if (empty($download['amount'])) { $download['amount'] = '0.00'; } $item = array(); $item['id'] = absint($download['id']); $item['quantity'] = absint($download['quantity']) > 0 ? absint($download['quantity']) : 1; $price_id = (int) $download['price_id']; if ($price_id !== false && edd_has_variable_prices($item['id'])) { $item['options'] = array('price_id' => $price_id); } $downloads[] = $item; $cart_item = array(); $cart_item['item_number'] = $item; $item_price = round($download['amount'] / $item['quantity'], edd_currency_decimal_filter()); $cart_details[$i] = array('name' => get_the_title($download['id']), 'id' => $download['id'], 'item_number' => $item, 'price' => $download['amount'], 'item_price' => $item_price, 'quantity' => $download['quantity'], 'discount' => 0, 'tax' => 0); $i++; } $meta['downloads'] = $downloads; $meta['cart_details'] = $cart_details; } if ($user_id !== $user_info['id'] || $email !== $user_info['email']) { $user = get_user_by('id', $user_id); if (!empty($user) && strtolower($user->data->user_email) !== strtolower($email)) { // protect a purcahse from being assigned to a customer with a user ID and Email that belong to different users wp_die('User ID and User Email do not match.'); exit; } // Remove the stats and payment from the previous customer $previous_customer = EDD()->customers->get_by('email', $user_info['email']); EDD()->customers->remove_payment($previous_customer->id, $payment_id); // Attribute the payment to the new customer and update the payment post meta $new_customer_id = EDD()->customers->get_column_by('id', 'email', $email); if (!$new_customer) { // No customer exists for the given email so create one $new_customer_id = EDD()->customers->add(array('email' => $email, 'name' => $first_name . ' ' . $last_name)); } EDD()->customers->attach_payment($new_customer_id, $payment_id); // If purchase was completed and not ever refunded, adjust stats of customers if ('revoked' == $status || 'publish' == $status) { EDD()->customers->decrement_stats($previous_customer->id, $total); EDD()->customers->increment_stats($new_customer_id, $total); } update_post_meta($payment_id, '_edd_payment_customer_id', $new_customer_id); } // Set new meta values $user_info['id'] = $user_id; $user_info['email'] = $email; $user_info['first_name'] = $first_name; $user_info['last_name'] = $last_name; $user_info['address'] = $address; $meta['user_info'] = $user_info; $meta['tax'] = $tax; // Check for payment notes if (!empty($data['edd-payment-note'])) { $note = wp_kses($data['edd-payment-note'], array()); edd_insert_payment_note($payment_id, $note); } do_action('edd_update_edited_purchase', $payment_id); // Update main payment record wp_update_post(array('ID' => $payment_id, 'post_date' => $date)); // Set new status edd_update_payment_status($payment_id, $status); edd_update_payment_meta($payment_id, '_edd_payment_user_id', $user_id); edd_update_payment_meta($payment_id, '_edd_payment_user_email', $email); edd_update_payment_meta($payment_id, '_edd_payment_meta', $meta); edd_update_payment_meta($payment_id, '_edd_payment_total', $total); edd_update_payment_meta($payment_id, '_edd_payment_downloads', $total); edd_update_payment_meta($payment_id, '_edd_payment_unlimited_downloads', $unlimited); do_action('edd_updated_edited_purchase', $payment_id); wp_safe_redirect(admin_url('edit.php?post_type=download&page=edd-payment-history&view=view-order-details&edd-message=payment-updated&id=' . $payment_id)); exit; }
/** * Upgrades payment taxes for 2.3 * * @since 2.3 * @return void */ function edd_v23_upgrade_payment_taxes() { global $wpdb; if (!current_user_can('manage_shop_settings')) { wp_die(__('You do not have permission to do shop upgrades', 'edd'), __('Error', 'edd'), array('response' => 403)); } ignore_user_abort(true); if (!edd_is_func_disabled('set_time_limit') && !ini_get('safe_mode')) { @set_time_limit(0); } $step = isset($_GET['step']) ? absint($_GET['step']) : 1; $number = 50; $offset = $step == 1 ? 0 : ($step - 1) * $number; if ($step < 2) { // Check if we have any payments before moving on $sql = "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'edd_payment' LIMIT 1"; $has_payments = $wpdb->get_col($sql); if (empty($has_payments)) { // We had no payments, just complete update_option('edd_version', preg_replace('/[^0-9.].*/', '', EDD_VERSION)); edd_set_upgrade_complete('upgrade_payment_taxes'); delete_option('edd_doing_upgrade'); wp_redirect(admin_url()); exit; } } $total = isset($_GET['total']) ? absint($_GET['total']) : false; if (empty($total) || $total <= 1) { $total_sql = "SELECT COUNT(ID) as total_payments FROM {$wpdb->posts} WHERE post_type = 'edd_payment'"; $results = $wpdb->get_row($total_sql, 0); $total = $results->total_payments; } $payment_ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'edd_payment' ORDER BY post_date DESC LIMIT %d,%d;", $offset, $number)); if ($payment_ids) { foreach ($payment_ids as $payment_id) { // Add the new _edd_payment_meta item $payment_tax = edd_get_payment_tax($payment_id); edd_update_payment_meta($payment_id, '_edd_payment_tax', $payment_tax); } // Payments found so upgrade them $step++; $redirect = add_query_arg(array('page' => 'edd-upgrades', 'edd-upgrade' => 'upgrade_payment_taxes', 'step' => $step, 'number' => $number, 'total' => $total), admin_url('index.php')); wp_redirect($redirect); exit; } else { // No more payments found, finish up update_option('edd_version', preg_replace('/[^0-9.].*/', '', EDD_VERSION)); edd_set_upgrade_complete('upgrade_payment_taxes'); delete_option('edd_doing_upgrade'); wp_redirect(admin_url()); exit; } }
/** * Process the payment details edit * * @access private * @since 1.9 * @return void */ function edd_update_payment_details($data) { if (!current_user_can('edit_shop_payments', $data['edd_payment_id'])) { wp_die(__('You do not have permission to edit this payment record', 'easy-digital-downloads'), __('Error', 'easy-digital-downloads'), array('response' => 403)); } check_admin_referer('edd_update_payment_details_nonce'); // Retrieve the payment ID $payment_id = absint($data['edd_payment_id']); // Retrieve existing payment meta $meta = edd_get_payment_meta($payment_id); $user_info = edd_get_payment_meta_user_info($payment_id); $status = $data['edd-payment-status']; $unlimited = isset($data['edd-unlimited-downloads']) ? '1' : ''; $date = sanitize_text_field($data['edd-payment-date']); $hour = sanitize_text_field($data['edd-payment-time-hour']); // Restrict to our high and low if ($hour > 23) { $hour = 23; } elseif ($hour < 0) { $hour = 00; } $minute = sanitize_text_field($data['edd-payment-time-min']); // Restrict to our high and low if ($minute > 59) { $minute = 59; } elseif ($minute < 0) { $minute = 00; } $address = array_map('trim', $data['edd-payment-address'][0]); $curr_total = edd_sanitize_amount(edd_get_payment_amount($payment_id)); $new_total = edd_sanitize_amount($_POST['edd-payment-total']); $tax = isset($_POST['edd-payment-tax']) ? edd_sanitize_amount($_POST['edd-payment-tax']) : 0; $date = date('Y-m-d', strtotime($date)) . ' ' . $hour . ':' . $minute . ':00'; $curr_customer_id = sanitize_text_field($data['edd-current-customer']); $new_customer_id = sanitize_text_field($data['customer-id']); // Setup purchased Downloads and price options $updated_downloads = isset($_POST['edd-payment-details-downloads']) ? $_POST['edd-payment-details-downloads'] : false; if ($updated_downloads && !empty($_POST['edd-payment-downloads-changed'])) { $downloads = array(); $cart_details = array(); $i = 0; foreach ($updated_downloads as $download) { if (empty($download['amount'])) { $download['amount'] = '0.00'; } $item = array(); $item['id'] = absint($download['id']); $item['quantity'] = absint($download['quantity']) > 0 ? absint($download['quantity']) : 1; $price_id = (int) $download['price_id']; $has_log = absint($download['has_log']); if ($price_id !== false && edd_has_variable_prices($item['id'])) { $item['options'] = array('price_id' => $price_id); } $downloads[] = $item; $cart_item = array(); $cart_item['item_number'] = $item; $item_price = round($download['amount'] / $item['quantity'], edd_currency_decimal_filter()); $cart_details[$i] = array('name' => get_the_title($download['id']), 'id' => $download['id'], 'item_number' => $item, 'price' => $download['amount'], 'item_price' => $item_price, 'subtotal' => $download['amount'], 'quantity' => $download['quantity'], 'discount' => 0, 'tax' => 0); // If this item doesn't have a log yet, add one for each quantity count if (empty($has_log)) { $log_date = date('Y-m-d G:i:s', current_time('timestamp', true)); $price_id = $price_id !== false ? $price_id : 0; $y = 0; while ($y < $download['quantity']) { edd_record_sale_in_log($download['id'], $payment_id, $price_id, $log_date); $y++; } edd_increase_purchase_count($download['id'], $download['quantity']); edd_increase_earnings($download['id'], $download['amount']); } $i++; } $meta['downloads'] = $downloads; $meta['cart_details'] = $cart_details; $deleted_downloads = json_decode(stripcslashes($data['edd-payment-removed']), true); foreach ($deleted_downloads as $deleted_download) { $deleted_download = $deleted_download[0]; if (empty($deleted_download['id'])) { continue; } $price_id = empty($deleted_download['price_id']) ? 0 : (int) $deleted_download['price_id']; $log_args = array('post_type' => 'edd_log', 'post_parent' => $deleted_download['id'], 'numberposts' => $deleted_download['quantity'], 'meta_query' => array(array('key' => '_edd_log_payment_id', 'value' => $payment_id, 'compare' => '='), array('key' => '_edd_log_price_id', 'value' => $price_id, 'compare' => '='))); $found_logs = get_posts($log_args); foreach ($found_logs as $log) { wp_delete_post($log->ID, true); } edd_decrease_purchase_count($deleted_download['id'], $deleted_download['quantity']); edd_decrease_earnings($deleted_download['id'], $deleted_download['amount']); do_action('edd_remove_download_from_payment', $payment_id, $deleted_download['id']); } } do_action('edd_update_edited_purchase', $payment_id); // Update main payment record $updated = wp_update_post(array('ID' => $payment_id, 'post_date' => $date)); if (0 === $updated) { wp_die(__('Error Updating Payment', 'easy-digital-downloads'), __('Error', 'easy-digital-downloads'), array('response' => 400)); } $customer_changed = false; if (isset($data['edd-new-customer']) && $data['edd-new-customer'] == '1') { $email = isset($data['edd-new-customer-email']) ? sanitize_text_field($data['edd-new-customer-email']) : ''; $names = isset($data['edd-new-customer-name']) ? sanitize_text_field($data['edd-new-customer-name']) : ''; if (empty($email) || empty($names)) { wp_die(__('New Customers require a name and email address', 'easy-digital-downloads')); } $customer = new EDD_Customer($email); if (empty($customer->id)) { $customer_data = array('name' => $names, 'email' => $email); $user_id = email_exists($email); if (false !== $user_id) { $customer_data['user_id'] = $user_id; } if (!$customer->create($customer_data)) { // Failed to crete the new customer, assume the previous customer $customer_changed = false; $customer = new EDD_Customer($curr_customer_id); edd_set_error('edd-payment-new-customer-fail', __('Error creating new customer', 'easy-digital-downloads')); } } $new_customer_id = $customer->id; $previous_customer = new EDD_Customer($curr_customer_id); $customer_changed = true; } elseif ($curr_customer_id !== $new_customer_id) { $customer = new EDD_Customer($new_customer_id); $email = $customer->email; $names = $customer->name; $previous_customer = new EDD_Customer($curr_customer_id); $customer_changed = true; } else { $customer = new EDD_Customer($curr_customer_id); $email = $customer->email; $names = $customer->name; } // Setup first and last name from input values $names = explode(' ', $names); $first_name = !empty($names[0]) ? $names[0] : ''; $last_name = ''; if (!empty($names[1])) { unset($names[0]); $last_name = implode(' ', $names); } if ($customer_changed) { // Remove the stats and payment from the previous customer and attach it to the new customer $previous_customer->remove_payment($payment_id, false); $customer->attach_payment($payment_id, false); // If purchase was completed and not ever refunded, adjust stats of customers if ('revoked' == $status || 'publish' == $status) { $previous_customer->decrease_purchase_count(); $previous_customer->decrease_value($new_total); $customer->increase_purchase_count(); $customer->increase_value($new_total); } update_post_meta($payment_id, '_edd_payment_customer_id', $customer->id); } // Set new meta values $user_info['id'] = $customer->user_id; $user_info['email'] = $customer->email; $user_info['first_name'] = $first_name; $user_info['last_name'] = $last_name; $user_info['address'] = $address; $meta['user_info'] = $user_info; $meta['tax'] = $tax; // Check for payment notes if (!empty($data['edd-payment-note'])) { $note = wp_kses($data['edd-payment-note'], array()); edd_insert_payment_note($payment_id, $note); } // Set new status edd_update_payment_status($payment_id, $status); edd_update_payment_meta($payment_id, '_edd_payment_user_id', $customer->user_id); edd_update_payment_meta($payment_id, '_edd_payment_user_email', $customer->email); edd_update_payment_meta($payment_id, '_edd_payment_meta', $meta); edd_update_payment_meta($payment_id, '_edd_payment_total', $new_total); // Adjust total store earnings if the payment total has been changed if ($new_total !== $curr_total && ('publish' == $status || 'revoked' == $status)) { if ($new_total > $curr_total) { // Increase if our new total is higher $difference = $new_total - $curr_total; edd_increase_total_earnings($difference); } elseif ($curr_total > $new_total) { // Decrease if our new total is lower $difference = $curr_total - $new_total; edd_decrease_total_earnings($difference); } } edd_update_payment_meta($payment_id, '_edd_payment_downloads', $new_total); edd_update_payment_meta($payment_id, '_edd_payment_unlimited_downloads', $unlimited); do_action('edd_updated_edited_purchase', $payment_id); wp_safe_redirect(admin_url('edit.php?post_type=download&page=edd-payment-history&view=view-order-details&edd-message=payment-updated&id=' . $payment_id)); exit; }
/** * Process web accept (one time) payment IPNs * * @since 1.3.4 * @param array $data IPN Data * @return void */ function edd_process_paypal_web_accept_and_cart($data, $payment_id) { if ($data['txn_type'] != 'web_accept' && $data['txn_type'] != 'cart' && $data['payment_status'] != 'Refunded') { return; } if (empty($payment_id)) { return; } // Collect payment details $purchase_key = isset($data['invoice']) ? $data['invoice'] : $data['item_number']; $paypal_amount = $data['mc_gross']; $payment_status = strtolower($data['payment_status']); $currency_code = strtolower($data['mc_currency']); $business_email = isset($data['business']) && is_email($data['business']) ? trim($data['business']) : trim($data['receiver_email']); $payment_meta = edd_get_payment_meta($payment_id); if (edd_get_payment_gateway($payment_id) != 'paypal') { return; // this isn't a PayPal standard IPN } // Verify payment recipient if (strcasecmp($business_email, trim(edd_get_option('paypal_email', false))) != 0) { edd_record_gateway_error(__('IPN Error', 'edd'), sprintf(__('Invalid business email in IPN response. IPN data: %s', 'edd'), json_encode($data)), $payment_id); edd_update_payment_status($payment_id, 'failed'); edd_insert_payment_note($payment_id, __('Payment failed due to invalid PayPal business email.', 'edd')); return; } // Verify payment currency if ($currency_code != strtolower($payment_meta['currency'])) { edd_record_gateway_error(__('IPN Error', 'edd'), sprintf(__('Invalid currency in IPN response. IPN data: %s', 'edd'), json_encode($data)), $payment_id); edd_update_payment_status($payment_id, 'failed'); edd_insert_payment_note($payment_id, __('Payment failed due to invalid currency in PayPal IPN.', 'edd')); return; } if (!edd_get_payment_user_email($payment_id)) { // This runs when a Buy Now purchase was made. It bypasses checkout so no personal info is collected until PayPal // No email associated with purchase, so store from PayPal edd_update_payment_meta($payment_id, '_edd_payment_user_email', $data['payer_email']); // Setup and store the customers's details $address = array(); $address['line1'] = !empty($data['address_street']) ? sanitize_text_field($data['address_street']) : false; $address['city'] = !empty($data['address_city']) ? sanitize_text_field($data['address_city']) : false; $address['state'] = !empty($data['address_state']) ? sanitize_text_field($data['address_state']) : false; $address['country'] = !empty($data['address_country_code']) ? sanitize_text_field($data['address_country_code']) : false; $address['zip'] = !empty($data['address_zip']) ? sanitize_text_field($data['address_zip']) : false; $user_info = array('id' => '-1', 'email' => sanitize_text_field($data['payer_email']), 'first_name' => sanitize_text_field($data['first_name']), 'last_name' => sanitize_text_field($data['last_name']), 'discount' => '', 'address' => $address); $payment_meta['user_info'] = $user_info; edd_update_payment_meta($payment_id, '_edd_payment_meta', $payment_meta); } if ($payment_status == 'refunded' || $payment_status == 'reversed') { // Process a refund edd_process_paypal_refund($data, $payment_id); } else { if (get_post_status($payment_id) == 'publish') { return; // Only complete payments once } // Retrieve the total purchase amount (before PayPal) $payment_amount = edd_get_payment_amount($payment_id); if (number_format((double) $paypal_amount, 2) < number_format((double) $payment_amount, 2)) { // The prices don't match edd_record_gateway_error(__('IPN Error', 'edd'), sprintf(__('Invalid payment amount in IPN response. IPN data: %s', 'edd'), json_encode($data)), $payment_id); edd_update_payment_status($payment_id, 'failed'); edd_insert_payment_note($payment_id, __('Payment failed due to invalid amount in PayPal IPN.', 'edd')); return; } if ($purchase_key != edd_get_payment_key($payment_id)) { // Purchase keys don't match edd_record_gateway_error(__('IPN Error', 'edd'), sprintf(__('Invalid purchase key in IPN response. IPN data: %s', 'edd'), json_encode($data)), $payment_id); edd_update_payment_status($payment_id, 'failed'); edd_insert_payment_note($payment_id, __('Payment failed due to invalid purchase key in PayPal IPN.', 'edd')); return; } if ('completed' == $payment_status || edd_is_test_mode()) { edd_insert_payment_note($payment_id, sprintf(__('PayPal Transaction ID: %s', 'edd'), $data['txn_id'])); edd_set_payment_transaction_id($payment_id, $data['txn_id']); edd_update_payment_status($payment_id, 'publish'); } else { if ('pending' == $payment_status && isset($data['pending_reason'])) { // Look for possible pending reasons, such as an echeck $note = ''; switch (strtolower($data['pending_reason'])) { case 'echeck': $note = __('Payment made via eCheck and will clear automatically in 5-8 days', 'edd'); break; case 'address': $note = __('Payment requires a confirmed customer address and must be accepted manually through PayPal', 'edd'); break; case 'intl': $note = __('Payment must be accepted manually through PayPal due to international account regulations', 'edd'); break; case 'multi-currency': $note = __('Payment received in non-shop currency and must be accepted manually through PayPal', 'edd'); break; case 'paymentreview': case 'regulatory_review': $note = __('Payment is being reviewed by PayPal staff as high-risk or in possible violation of government regulations', 'edd'); break; case 'unilateral': $note = __('Payment was sent to non-confirmed or non-registered email address.', 'edd'); break; case 'upgrade': $note = __('PayPal account must be upgraded before this payment can be accepted', 'edd'); break; case 'verify': $note = __('PayPal account is not verified. Verify account in order to accept this payment', 'edd'); break; case 'other': $note = __('Payment is pending for unknown reasons. Contact PayPal support for assistance', 'edd'); break; } if (!empty($note)) { edd_insert_payment_note($payment_id, $note); } } } } }
/** * Process web accept (one time) payment IPNs * * @since 1.3.4 * @global $edd_options Array of all the EDD Options * @param array $data IPN Data * @return void */ function edd_process_paypal_web_accept_and_cart($data) { global $edd_options; if ($data['txn_type'] != 'web_accept' && $data['txn_type'] != 'cart' && $data['payment_status'] != 'Refunded') { return; } // Collect payment details $payment_id = $data['custom']; $purchase_key = isset($data['invoice']) ? $data['invoice'] : $data['item_number']; $paypal_amount = $data['mc_gross']; $payment_status = strtolower($data['payment_status']); $currency_code = strtolower($data['mc_currency']); $business_email = isset($data['business']) && is_email($data['business']) ? trim($data['business']) : trim($data['receiver_email']); if (edd_get_payment_gateway($payment_id) != 'paypal') { return; // this isn't a PayPal standard IPN } // Verify payment recipient if (strcasecmp($business_email, trim($edd_options['paypal_email'])) != 0) { edd_record_gateway_error(__('IPN Error', 'edd'), sprintf(__('Invalid business email in IPN response. IPN data: %s', 'edd'), json_encode($data)), $payment_id); edd_update_payment_status($payment_id, 'failed'); edd_insert_payment_note($payment_id, __('Payment failed due to invalid PayPal business email.', 'edd')); return; } // Verify payment currency if ($currency_code != strtolower(edd_get_currency())) { edd_record_gateway_error(__('IPN Error', 'edd'), sprintf(__('Invalid currency in IPN response. IPN data: %s', 'edd'), json_encode($data)), $payment_id); edd_update_payment_status($payment_id, 'failed'); edd_insert_payment_note($payment_id, __('Payment failed due to invalid currency in PayPal IPN.', 'edd')); return; } if (!edd_get_payment_user_email($payment_id)) { // This runs when a Buy Now purchase was made. It bypasses checkout so no personal info is collected until PayPal // No email associated with purchase, so store from PayPal edd_update_payment_meta($payment_id, '_edd_payment_user_email', $data['payer_email']); // Setup and store the customers's details $address = array(); $address['line1'] = !empty($data['address_street']) ? $data['address_street'] : false; $address['city'] = !empty($data['address_city']) ? $data['address_city'] : false; $address['state'] = !empty($data['address_state']) ? $data['address_state'] : false; $address['country'] = !empty($data['address_country_code']) ? $data['address_country_code'] : false; $address['zip'] = !empty($data['address_zip']) ? $data['address_zip'] : false; $user_info = array('id' => '-1', 'email' => $data['payer_email'], 'first_name' => $data['first_name'], 'last_name' => $data['last_name'], 'discount' => '', 'address' => $address); $payment_meta = get_post_meta($payment_id, '_edd_payment_meta', true); $payment_meta['user_info'] = $user_info; edd_update_payment_meta($payment_id, '_edd_payment_meta', $payment_meta); } if ($payment_status == 'refunded' || $payment_status == 'reversed') { // Process a refund edd_process_paypal_refund($data); } else { if (get_post_status($payment_id) == 'publish') { return; // Only complete payments once } // Retrieve the total purchase amount (before PayPal) $payment_amount = edd_get_payment_amount($payment_id); if (number_format((double) $paypal_amount, 2) < number_format((double) $payment_amount, 2)) { // The prices don't match edd_record_gateway_error(__('IPN Error', 'edd'), sprintf(__('Invalid payment amount in IPN response. IPN data: %s', 'edd'), json_encode($data)), $payment_id); edd_update_payment_status($payment_id, 'failed'); edd_insert_payment_note($payment_id, __('Payment failed due to invalid amount in PayPal IPN.', 'edd')); return; } if ($purchase_key != edd_get_payment_key($payment_id)) { // Purchase keys don't match edd_record_gateway_error(__('IPN Error', 'edd'), sprintf(__('Invalid purchase key in IPN response. IPN data: %s', 'edd'), json_encode($data)), $payment_id); edd_update_payment_status($payment_id, 'failed'); edd_insert_payment_note($payment_id, __('Payment failed due to invalid purchase key in PayPal IPN.', 'edd')); return; } if ($payment_status == 'completed' || edd_is_test_mode()) { edd_insert_payment_note($payment_id, sprintf(__('PayPal Transaction ID: %s', 'edd'), $data['txn_id'])); edd_set_payment_transaction_id($payment_id, $data['txn_id']); edd_update_payment_status($payment_id, 'publish'); } } }
/** * Looks up purchases by email that match the registering user * * This is for users that purchased as a guest and then came * back and created an account. * * @access public * @since 1.6 * @param $user_id INT - the new user's ID * @return void */ function edd_add_past_purchases_to_new_user($user_id) { $email = get_the_author_meta('user_email', $user_id); $payments = edd_get_payments(array('s' => $email)); if ($payments) { // Set a flag to force the account to be verified before purchase history can be accessed edd_set_user_to_pending($user_id); edd_send_user_verification_email($user_id); foreach ($payments as $payment) { if (intval(edd_get_payment_user_id($payment->ID)) > 0) { continue; // This payment already associated with an account } $meta = edd_get_payment_meta($payment->ID); $meta['user_info'] = maybe_unserialize($meta['user_info']); $meta['user_info']['id'] = $user_id; $meta['user_info'] = $meta['user_info']; // Store the updated user ID in the payment meta edd_update_payment_meta($payment->ID, '_edd_payment_meta', $meta); edd_update_payment_meta($payment->ID, '_edd_payment_user_id', $user_id); } } }
/** * Upgrades for EDD v2.0 and sequential payment numbers * * @since 2.0 * @return void */ function edd_v20_upgrade_sequential_payment_numbers() { ignore_user_abort(true); if (!edd_is_func_disabled('set_time_limit') && !ini_get('safe_mode')) { set_time_limit(0); } $step = isset($_GET['step']) ? absint($_GET['step']) : 1; $total = isset($_GET['total']) ? absint($_GET['total']) : false; if (empty($total) || $total <= 1) { $payments = edd_count_payments(); foreach ($payments as $status) { $total += $status; } } $args = array('number' => 100, 'page' => $step, 'status' => 'any', 'order' => 'ASC'); $payments = new EDD_Payments_Query($args); $payments = $payments->get_payments(); if ($payments) { $prefix = edd_get_option('sequential_prefix'); $postfix = edd_get_option('sequential_postfix'); $number = !empty($_GET['custom']) ? absint($_GET['custom']) : intval(edd_get_option('sequential_start', 1)); foreach ($payments as $payment) { // Re-add the prefix and postfix $payment_number = $prefix . $number . $postfix; edd_update_payment_meta($payment->ID, '_edd_payment_number', $payment_number); // Increment the payment number $number++; } // Payments found so upgrade them $step++; $redirect = add_query_arg(array('page' => 'edd-upgrades', 'edd-upgrade' => 'upgrade_sequential_payment_numbers', 'step' => $step, 'custom' => $number, 'total' => $total), admin_url('index.php')); wp_redirect($redirect); exit; } else { // No more payments found, finish up EDD()->session->set('upgrade_sequential', null); wp_redirect(admin_url()); exit; } }
function edd_ti_send_tracking($post) { $nonce = !empty($post['nonce']) ? $post['nonce'] : false; if (!wp_verify_nonce($nonce, 'edd-ti-send-tracking')) { wp_die(); } $tracking_id = edd_ti_get_payment_tracking_id($post['payment_id']); if (empty($tracking_id)) { return; } $from_name = edd_get_option('from_name', wp_specialchars_decode(get_bloginfo('name'), ENT_QUOTES)); $from_email = edd_get_option('from_email', get_bloginfo('admin_email')); $to_email = edd_get_payment_user_email($post['payment_id']); $subject = 'Your order has shipped'; $heading = 'Your order has shipped!'; $message = '<p>Your recent order ' . $post['payment_id'] . ' has been shipped.</p>'; $message .= '<p>Tracking ID: <a href="' . edd_ti_get_payment_tracking_link($post['payment_id']) . '">' . $tracking_id . '</a></p>'; $message .= '<p>Thank you!</p>'; $message .= '<p>The ' . $from_name . ' team</p>'; $headers = "From: " . stripslashes_deep(html_entity_decode($from_name, ENT_COMPAT, 'UTF-8')) . " <{$from_email}>\r\n"; $headers .= "Reply-To: " . $from_email . "\r\n"; $headers .= "MIME-Version: 1.0\r\n"; $headers .= "Content-Type: text/html; charset=utf-8\r\n"; $attachments = array(); $emails = EDD()->emails; $emails->__set('from_name', $from_name); $emails->__set('from_email', $from_email); $emails->__set('heading', $heading); $emails->__set('headers', $headers); $result = $emails->send($to_email, $subject, $message, $attachments); $response = array('success' => $result); $response['message'] = $result ? __('Email sent.', 'edd-tracking-info') : __('Error sending email. Try again later.', 'edd-tracking-info'); if ($result) { edd_update_payment_meta($post['payment_id'], 'edd_tracking_info_sent', true); edd_insert_payment_note($post['payment_id'], sprintf(__('Tracking information sent to %s.', 'edd-tracking-info'), $to_email)); } echo json_encode($response); die; }
/** * Set an email address as the customer's primary email * * This will move the customer's previous primary email to an additional email * * @since 2.6 * @param string $new_primary_email The email address to remove from the customer * @return bool If the email was set as primary successfully */ public function set_primary_email($new_primary_email = '') { if (!is_email($new_primary_email)) { return false; } do_action('edd_customer_pre_set_primary_email', $new_primary_email, $this->id, $this); $existing = new EDD_Customer($new_primary_email); if ($existing->id > 0 && (int) $existing->id !== (int) $this->id) { // This email belongs to another customer return false; } $old_email = $this->email; // Update customer record with new email $update = $this->update(array('email' => $new_primary_email)); // Remove new primary from list of additional emails $remove = $this->remove_email($new_primary_email); // Add old email to additional emails list $add = $this->add_email($old_email); $ret = $update && $remove && $add; if ($ret) { $this->email = $new_primary_email; $payment_ids = $this->get_payment_ids(); if ($payment_ids) { foreach ($payment_ids as $payment_id) { // Update payment emails to primary email edd_update_payment_meta($payment_id, 'email', $new_primary_email); } } } do_action('edd_customer_post_set_primary_email', $new_primary_email, $this->id, $this); return $ret; }
/** * Updates the email address of a customer record when the email on a user is updated * * @access public * @since 2.4 */ public function update_customer_email_on_user_update($user_id = 0, $old_user_data) { $customer = new EDD_Customer($user_id, true); if (!$customer) { return false; } $user = get_userdata($user_id); if (!empty($user) && $user->user_email !== $customer->email) { if (!$this->get_customer_by('email', $user->user_email)) { $success = $this->update($customer->id, array('email' => $user->user_email)); if ($success) { // Update some payment meta if we need to $payments_array = explode(',', $customer->payment_ids); if (!empty($payments_array)) { foreach ($payments_array as $payment_id) { edd_update_payment_meta($payment_id, 'email', $user->user_email); } } do_action('edd_update_customer_email_on_user_update', $user, $customer); } } } }
/** * Add the deposited amount to the wallet after payment * * @since 1.0.0 * @param int $payment_id The ID of the payment * @return void */ function edd_wallet_add_funds($payment_id) { $fees = edd_get_payment_fees($payment_id); if ($fees && count($fees) == 1) { if ($fees[0]['id'] == 'edd-wallet-deposit') { // Disable purchase receipts... we send our own emails remove_action('edd_complete_purchase', 'edd_trigger_purchase_receipt', 999); // Send our custom emails edd_wallet_send_email('user', $payment_id); // Get the ID of the purchaser $user_id = edd_get_payment_user_id($payment_id); // Deposit the funds edd_wallet()->wallet->deposit($user_id, $fees[0]['amount'], 'deposit', $payment_id); // Tag the payment so we can find it later edd_update_payment_meta($payment_id, '_edd_wallet_deposit', $user_id); } } }
/** * Maybe create a user when payment is created * * @since 1.3 */ public function maybe_insert_user($payment_id, $payment_data) { // User account already associated if ($payment_data['user_info']['id'] > 0) { return; } // User account already exists if (get_user_by('email', $payment_data['user_info']['email'])) { return; } $user_name = sanitize_user($payment_data['user_info']['email']); // Username already exists if (username_exists($user_name)) { return; } // Okay we need to create a user and possibly log them in $user_args = apply_filters('edd_auto_register_insert_user_args', array('user_login' => $user_name, 'user_pass' => wp_generate_password(32), 'user_email' => $payment_data['user_info']['email'], 'first_name' => $payment_data['user_info']['first_name'], 'last_name' => $payment_data['user_info']['last_name'], 'user_registered' => date('Y-m-d H:i:s'), 'role' => get_option('default_role')), $payment_id, $payment_data); // Insert new user $user_id = wp_insert_user($user_args); // Validate inserted user if (is_wp_error($user_id)) { return; } $payment_meta = edd_get_payment_meta($payment_id); $payment_meta['user_info']['id'] = $user_id; edd_update_payment_meta($payment_id, '_edd_payment_user_id', $user_id); edd_update_payment_meta($payment_id, '_edd_payment_meta', $payment_meta); $customer = new EDD_Customer($payment_data['user_info']['email']); $customer->update(array('user_id' => $user_id)); // Allow themes and plugins to hook do_action('edd_auto_register_insert_user', $user_id, $user_args, $payment_id); if (function_exists('did_action') && did_action('edd_purchase')) { // Only log user in if processing checkout screen edd_log_user_in($user_id, $user_args['user_login'], $user_args['user_pass']); } }
/** * Delete a customer * * @since 2.3 * @param array $args The $_POST array being passeed * @return int Wether it was a successful deletion */ function edd_customer_delete($args) { $customer_edit_role = apply_filters('edd_edit_customers_role', 'edit_shop_payments'); if (!is_admin() || !current_user_can($customer_edit_role)) { wp_die(__('You do not have permission to delete this customer.', 'edd')); } if (empty($args)) { return; } $customer_id = (int) $args['customer_id']; $confirm = !empty($args['edd-customer-delete-confirm']) ? true : false; $remove_data = !empty($args['edd-customer-delete-records']) ? true : false; $nonce = $args['_wpnonce']; if (!wp_verify_nonce($nonce, 'delete-customer')) { wp_die(__('Cheatin\' eh?!', 'edd')); } if (!$confirm) { edd_set_error('customer-delete-no-confirm', __('Please confirm you want to delete this customer', 'edd')); } if (edd_get_errors()) { wp_redirect(admin_url('edit.php?post_type=download&page=edd-customers&view=overview&id=' . $customer_id)); exit; } $customer = new EDD_Customer($customer_id); do_action('edd_pre_delete_customer', $customer_id, $confirm, $remove_data); $success = false; if ($customer->id > 0) { $payments_array = explode(',', $customer->payment_ids); $success = EDD()->customers->delete($customer->id); if ($success) { if ($remove_data) { // Remove all payments, logs, etc foreach ($payments_array as $payment_id) { edd_delete_purchase($payment_id, false, true); } } else { // Just set the payments to customer_id of 0 foreach ($payments_array as $payment_id) { edd_update_payment_meta($payment_id, '_edd_payment_customer_id', 0); } } $redirect = admin_url('edit.php?post_type=download&page=edd-customers&edd-message=customer-deleted'); } else { edd_set_error('edd-customer-delete-failed', __('Error deleting customer', 'edd')); $redirect = admin_url('edit.php?post_type=download&page=edd-customers&view=delete&id=' . $customer_id); } } else { edd_set_error('edd-customer-delete-invalid-id', __('Invalid Customer ID', 'edd')); $redirect = admin_url('edit.php?post_type=download&page=edd-customers'); } wp_redirect($redirect); exit; }
/** * Updates all old payments, prior to 1.2, with new * meta for the total purchase amount * * This is so that payments can be queried by their totals * * @since 1.2 * @param array $data Arguments passed * @return void */ function edd_update_old_payments_with_totals($data) { if (!wp_verify_nonce($data['_wpnonce'], 'edd_upgrade_payments_nonce')) { return; } if (get_option('edd_payment_totals_upgraded')) { return; } $payments = edd_get_payments(array('offset' => 0, 'number' => -1, 'mode' => 'all')); if ($payments) { foreach ($payments as $payment) { $meta = edd_get_payment_meta($payment->ID); edd_update_payment_meta($payment->ID, '_edd_payment_total', $meta['amount']); } } add_option('edd_payment_totals_upgraded', 1); }
public static function create_payment($data) { if (wp_verify_nonce($data['edd_create_payment_nonce'], 'edd_create_payment_nonce')) { global $edd_options; if (empty($data['downloads'][0]['id'])) { wp_die(sprintf(__('Please select at least one %s to add to the payment.', 'edd-manual-purchases'), edd_get_label_singular())); } $user = strip_tags(trim($data['user'])); if (empty($user)) { wp_die(__('Please enter a username, user ID, or email for the customer this payment belongs to.', 'edd-manual-purchases')); } if (is_numeric($user)) { $user = get_userdata($user); } elseif (is_email($user)) { $user = get_user_by('email', $user); } elseif (is_string($user)) { $user = get_user_by('login', $user); } else { return; } // no user assigned $user_id = $user ? $user->ID : 0; $email = $user ? $user->user_email : strip_tags(trim($data['user'])); if (isset($data['first'])) { $user_first = sanitize_text_field($data['first']); } else { $user_first = $user ? $user->first_name : ''; } if (isset($data['last'])) { $user_last = sanitize_text_field($data['last']); } else { $user_last = $user ? $user->last_name : ''; } $user_info = array('id' => $user_id, 'email' => $email, 'first_name' => $user_first, 'last_name' => $user_last, 'discount' => 'none'); $price = !empty($data['amount']) ? edd_sanitize_amount(strip_tags(trim($data['amount']))) : false; $cart_details = array(); $total = 0; foreach ($data['downloads'] as $key => $download) { // calculate total purchase cost if (isset($download['options'])) { $prices = get_post_meta($download['id'], 'edd_variable_prices', true); $price_key = $download['options']['price_id']; $item_price = $prices[$price_key]['amount']; } else { $item_price = edd_get_download_price($download['id']); } $cart_details[$key] = array('name' => get_the_title($download['id']), 'id' => $download['id'], 'item_number' => $download, 'price' => $price ? $price : $item_price, 'subtotal' => $price ? $price : $item_price, 'quantity' => 1, 'tax' => 0); $total += $item_price; } // assign total to the price given, if any if ($price) { $total = $price; } $date = !empty($data['date']) ? date('Y-m-d H:i:s', strtotime(strip_tags(trim($data['date'])))) : false; if (!$date) { $date = date('Y-m-d H:i:s', current_time('timestamp')); } if (strtotime($date, time()) > time()) { $date = date('Y-m-d H:i:s', current_time('timestamp')); } $status = isset($_POST['status']) ? sanitize_text_field($_POST['status']) : 'pending'; $tax = !empty($_POST['tax']) ? edd_sanitize_amount(sanitize_text_field($_POST['tax'])) : 0; $purchase_data = array('price' => edd_sanitize_amount($total), 'tax' => $tax, 'post_date' => $date, 'purchase_key' => strtolower(md5(uniqid())), 'user_email' => $email, 'user_info' => $user_info, 'currency' => edd_get_currency(), 'downloads' => $data['downloads'], 'cart_details' => $cart_details, 'status' => 'pending'); $payment_id = edd_insert_payment($purchase_data); edd_update_payment_meta($payment_id, '_edd_payment_tax', $tax); if (empty($data['receipt']) || $data['receipt'] != '1') { remove_action('edd_complete_purchase', 'edd_trigger_purchase_receipt', 999); } if (!empty($data['expiration']) && class_exists('EDD_Recurring_Customer') && $user_id > 0) { $expiration = strtotime($data['expiration'] . ' 23:59:59'); EDD_Recurring_Customer::set_as_subscriber($user_id); EDD_Recurring_Customer::set_customer_payment_id($user_id, $payment_id); EDD_Recurring_Customer::set_customer_status($user_id, 'active'); EDD_Recurring_Customer::set_customer_expiration($user_id, $expiration); } if (!empty($data['shipped'])) { update_post_meta($payment_id, '_edd_payment_shipping_status', '2'); } // increase stats and log earnings edd_update_payment_status($payment_id, $status); wp_redirect(admin_url('edit.php?post_type=download&page=edd-payment-history&edd-message=payment_created')); exit; } }