$morder->getMemberOrderByID($morder->id); //email the user their invoice $pmproemail = new PMProEmail(); $pmproemail->sendInvoiceEmail($user, $morder); $logstr .= "Created new order with ID #" . $morder->id . ". Event ID #" . $event->id . "."; /* Checking if there is an update "after next payment" for this user. */ $user_updates = $user->pmpro_stripe_updates; if (!empty($user_updates)) { foreach ($user_updates as $key => $update) { if ($update['when'] == 'payment') { //get current plan at Stripe to get payment date $last_order = new MemberOrder(); $last_order->getLastMemberOrder($user_id); $last_order->setGateway('stripe'); $last_order->Gateway->getCustomer(); if (!empty($last_order->Gateway->customer)) { //find the first subscription if (!empty($last_order->Gateway->customer->subscriptions['data'][0])) { $first_sub = $last_order->Gateway->customer->subscriptions['data'][0]->__toArray(); $end_timestamp = $first_sub['current_period_end']; } } //if we didn't get an end date, let's set one one cycle out $end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period']); //build order object $update_order = new MemberOrder(); $update_order->setGateway('stripe'); $update_order->user_id = $user->ID; $update_order->membership_id = $user->membership_level->id;
/** * Cron job for subscription updates. * * @since 1.8 */ static function pmpro_cron_stripe_subscription_updates() { global $wpdb; //get all updates for today (or before today) $sqlQuery = "SELECT *\n\t\t\t\t\t\t FROM {$wpdb->usermeta}\n\t\t\t\t\t\t WHERE meta_key = 'pmpro_stripe_next_on_date_update'\n\t\t\t\t\t\t\tAND meta_value IS NOT NULL\n\t\t\t\t\t\t\tAND meta_value <> ''\n\t\t\t\t\t\t\tAND meta_value < '" . date("Y-m-d", strtotime("+1 day")) . "'"; $updates = $wpdb->get_results($sqlQuery); if (!empty($updates)) { //loop through foreach ($updates as $update) { //pull values from update $user_id = $update->user_id; $user = get_userdata($user_id); //if user is missing, delete the update info and continue if (empty($user) || empty($user->ID)) { delete_user_meta($user_id, "pmpro_stripe_updates"); delete_user_meta($user_id, "pmpro_stripe_next_on_date_update"); continue; } $user_updates = $user->pmpro_stripe_updates; $next_on_date_update = ""; //loop through updates looking for updates happening today or earlier if (!empty($user_updates)) { foreach ($user_updates as $key => $update) { if ($update['when'] == 'date' && $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day'] <= date("Y-m-d")) { //get level for user $user_level = pmpro_getMembershipLevelForUser($user_id); //get current plan at Stripe to get payment date $last_order = new MemberOrder(); $last_order->getLastMemberOrder($user_id); $last_order->setGateway('stripe'); $last_order->Gateway->getCustomer($last_order); if (!empty($last_order->Gateway->customer)) { //find the first subscription if (!empty($last_order->Gateway->customer->subscriptions['data'][0])) { $first_sub = $last_order->Gateway->customer->subscriptions['data'][0]->__toArray(); $end_timestamp = $first_sub['current_period_end']; } } //if we didn't get an end date, let's set one one cycle out $end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period']); //build order object $update_order = new MemberOrder(); $update_order->setGateway('stripe'); $update_order->user_id = $user_id; $update_order->membership_id = $user_level->id; $update_order->membership_name = $user_level->name; $update_order->InitialPayment = 0; $update_order->PaymentAmount = $update['billing_amount']; $update_order->ProfileStartDate = date("Y-m-d", $end_timestamp); $update_order->BillingPeriod = $update['cycle_period']; $update_order->BillingFrequency = $update['cycle_number']; //update subscription $update_order->Gateway->subscribe($update_order, false); //update membership $sqlQuery = "UPDATE {$wpdb->pmpro_memberships_users}\n\t\t\t\t\t\t\t\t\t\t\t\tSET billing_amount = '" . esc_sql($update['billing_amount']) . "',\n\t\t\t\t\t\t\t\t\t\t\t\t\tcycle_number = '" . esc_sql($update['cycle_number']) . "',\n\t\t\t\t\t\t\t\t\t\t\t\t\tcycle_period = '" . esc_sql($update['cycle_period']) . "'\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE user_id = '" . esc_sql($user_id) . "'\n\t\t\t\t\t\t\t\t\t\t\t\t\tAND membership_id = '" . esc_sql($last_order->membership_id) . "'\n\t\t\t\t\t\t\t\t\t\t\t\t\tAND status = 'active'\n\t\t\t\t\t\t\t\t\t\t\t\tLIMIT 1"; $wpdb->query($sqlQuery); //save order $update_order->status = "success"; $update_order->save(); //remove update from list unset($user_updates[$key]); } elseif ($update['when'] == 'date') { //this is an on date update for the future, update the next on date update if (!empty($next_on_date_update)) { $next_on_date_update = min($next_on_date_update, $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day']); } else { $next_on_date_update = $update['date_year'] . "-" . $update['date_month'] . "-" . $update['date_day']; } } } } //save updates in case we removed some update_user_meta($user_id, "pmpro_stripe_updates", $user_updates); //save date of next on-date update to make it easier to query for these in cron job update_user_meta($user_id, "pmpro_stripe_next_on_date_update", $next_on_date_update); } } }
//sometimes we need these split up $morder->FirstName = $bfirstname; $morder->LastName = $blastname; $morder->Address1 = $baddress1; $morder->Address2 = $baddress2; //other values $morder->billing->name = $bfirstname . " " . $blastname; $morder->billing->street = trim($baddress1 . " " . $baddress2); $morder->billing->city = $bcity; $morder->billing->state = $bstate; $morder->billing->country = $bcountry; $morder->billing->zip = $bzipcode; $morder->billing->phone = $bphone; //$gateway = pmpro_getOption("gateway"); $morder->gateway = $gateway; $morder->setGateway(); $worked = $morder->updateBilling(); if ($worked) { //send email to member $pmproemail = new PMProEmail(); $pmproemail->sendBillingEmail($current_user, $morder); //send email to admin $pmproemail = new PMProEmail(); $pmproemail->sendBillingAdminEmail($current_user, $morder); } } else { $worked = true; } if ($worked) { //update the user meta too $meta_keys = array("pmpro_bfirstname", "pmpro_blastname", "pmpro_baddress1", "pmpro_baddress2", "pmpro_bcity", "pmpro_bstate", "pmpro_bzipcode", "pmpro_bphone", "pmpro_bemail", "pmpro_CardType", "pmpro_AccountNumber", "pmpro_ExpirationMonth", "pmpro_ExpirationYear");
function pmproues_wp_ajax() { //make sure the user is an admin if (!current_user_can('manage_options')) { exit; } //get values $gateway = $_REQUEST['gateway']; $level = $_REQUEST['level']; $billing_amount = $_REQUEST['billing_amount']; $cycle_number = $_REQUEST['cycle_number']; $cycle_period = $_REQUEST['cycle_period']; $live = $_REQUEST['live']; if (empty($_REQUEST['limit'])) { $limit = 5; } else { $limit = intval($_REQUEST['limit']); } //continue progress? $hash = substr(md5($gateway . $level . $billing_amount . $cycle_number . $cycle_period . $live), 0, 16); $last_user = get_transient('pmproues_update_last_row_' . $hash); if (empty($last_user)) { $last_user = 0; } //find members global $wpdb; $sqlQuery = "SELECT user_id FROM {$wpdb->pmpro_memberships_users} WHERE user_id > {$last_user} AND membership_id = '" . intval($level) . "' AND status = 'active' ORDER BY user_id LIMIT {$limit}"; $member_ids = $wpdb->get_col($sqlQuery); if (empty($member_ids)) { delete_transient('pmproues_update_last_row_' . $hash); echo "done"; exit; } else { //update subs foreach ($member_ids as $member_id) { $last_user = $member_id; echo "\n----\nMember ID #" . $member_id . ". "; //get user $user = get_userdata($member_id); //no user? if (empty($user) || empty($user->ID)) { echo "Could not find user. "; continue; } else { echo "User found. (" . $user->user_email . ") "; } //get order $order = new MemberOrder(); $order->getLastMemberOrder($user->ID); //no order? if (empty($order->id)) { echo "Could not find order. "; continue; } else { echo "Order found. (" . $order->code . ") "; } //different gateway? if ($order->gateway != $gateway) { echo "Different gateway. "; continue; } else { echo "Gateway matches. "; } //okay find the sub if (empty($order->subscription_transaction_id)) { echo "No subscription transaction ID. "; continue; } else { echo "Subscription ID found. "; } if (empty($live)) { echo "Would have updated the subscription here, but we're just testing. "; continue; } //let's do it live! if ($gateway == "stripe") { /* Note: This code is copied and modified from the user_profile_fields_save method. */ //get level for user $user_level = pmpro_getMembershipLevelForUser($user->ID); //get current plan at Stripe to get payment date $order->Gateway->getCustomer($order); $subscription = $order->Gateway->getSubscription($order); if (!empty($subscription)) { $end_timestamp = $subscription->current_period_end; //cancel the old subscription if (!$order->Gateway->cancelSubscriptionAtGateway($subscription)) { echo "Could not cancel the old subscription. Skipping. "; continue; } } //if we didn't get an end date, let's set one one cycle out if (empty($end_timestamp)) { $end_timestamp = strtotime("+" . $cycle_number . " " . $cycle_period, current_time('timestamp')); } //build order object $update_order = new MemberOrder(); $update_order->setGateway('stripe'); $update_order->user_id = $user->ID; $update_order->Email = $user->user_email; $update_order->membership_id = $user_level->id; $update_order->membership_name = $user_level->name; $update_order->InitialPayment = 0; $update_order->PaymentAmount = $billing_amount; $update_order->ProfileStartDate = date("Y-m-d", $end_timestamp); $update_order->BillingPeriod = $cycle_period; $update_order->BillingFrequency = $cycle_number; //need filter to reset ProfileStartDate add_filter('pmpro_profile_start_date', create_function('$startdate, $order', 'return "' . $update_order->ProfileStartDate . 'T0:0:0";'), 10, 2); //update subscription $update_order->Gateway->subscribe($update_order, false); //update membership $sqlQuery = "UPDATE {$wpdb->pmpro_memberships_users}\r\n\t\t\t\t\t\t\t\tSET billing_amount = '" . esc_sql($billing_amount) . "',\r\n\t\t\t\t\t\t\t\t\tcycle_number = '" . esc_sql($cycle_number) . "',\r\n\t\t\t\t\t\t\t\t\tcycle_period = '" . esc_sql($cycle_period) . "',\r\n\t\t\t\t\t\t\t\t\ttrial_amount = '',\r\n\t\t\t\t\t\t\t\t\ttrial_limit = ''\r\n\t\t\t\t\t\t\t\tWHERE user_id = '" . esc_sql($user->ID) . "'\r\n\t\t\t\t\t\t\t\t\tAND membership_id = '" . esc_sql($order->membership_id) . "'\r\n\t\t\t\t\t\t\t\t\tAND status = 'active'\r\n\t\t\t\t\t\t\t\tLIMIT 1"; $wpdb->query($sqlQuery); //save order so we know which plan to look for at stripe (order code = plan id) $update_order->status = "success"; $update_order->saveOrder(); echo "ORDER UPDATED!"; } } } set_transient('pmproues_update_last_row_' . $hash, $last_user, 60 * 60 * 24); exit; }
function pmpropbc_recurring_orders() { global $wpdb; //make sure we only run once a day $now = current_time('timestamp'); $today = date("Y-m-d", $now); //have to run for each level, so get levels $levels = pmpro_getAllLevels(true, true); if (empty($levels)) { return; } foreach ($levels as $level) { //get options $options = pmpropbc_getOptions($level->id); if (!empty($options['renewal_days'])) { $date = date("Y-m-d", strtotime("+ " . $options['renewal_days'] . " days", $now)); } else { $date = $today; } //need to get all combos of pay cycle and period $sqlQuery = "SELECT DISTINCT(CONCAT(cycle_number, ' ', cycle_period)) FROM {$wpdb->pmpro_memberships_users} WHERE membership_id = '" . $level->id . "' AND cycle_number > 0 AND status = 'active'"; $combos = $wpdb->get_col($sqlQuery); if (empty($combos)) { continue; } foreach ($combos as $combo) { //check if it's been one pay period since the last payment /* - Check should create an invoice X days before expiration based on a setting on the levels page. - Set invoice date based on cycle and the day of the month of the member start date. - Send a reminder email Y days after initial invoice is created if it's still pending. - Cancel membership after Z days if invoice is not paid. Send email. */ //get all check orders still pending after X days $sqlQuery = "\r\n\t\t\t\tSELECT o1.id FROM\r\n\t\t\t\t (SELECT id, user_id, timestamp\r\n\t\t\t\t FROM {$wpdb->pmpro_membership_orders}\r\n\t\t\t\t WHERE membership_id = {$level->id}\r\n\t\t\t\t AND gateway = 'check' \r\n\t\t\t\t AND status IN('pending', 'success')\r\n\t\t\t\t ) as o1\r\n\r\n\t\t\t\t\tLEFT OUTER JOIN \r\n\t\t\t\t\t\r\n\t\t\t\t\t(SELECT id, user_id, timestamp\r\n\t\t\t\t FROM {$wpdb->pmpro_membership_orders}\r\n\t\t\t\t WHERE membership_id = {$level->id}\r\n\t\t\t\t AND gateway = 'check' \r\n\t\t\t\t AND status IN('pending', 'success')\r\n\t\t\t\t ) as o2\r\n\r\n\t\t\t\t\tON o1.user_id = o2.user_id\r\n\t\t\t\t\tAND o1.timestamp < o2.timestamp\r\n\t\t\t\t\tOR (o1.timestamp = o2.timestamp AND o1.id < o2.id)\r\n\t\t\t\tWHERE\r\n\t\t\t\t\to2.id IS NULL\r\n\t\t\t\t\tAND DATE_ADD(o1.timestamp, INTERVAL {$combo}) <= '" . $date . "'\r\n\t\t\t"; if (defined('PMPRO_CRON_LIMIT')) { $sqlQuery .= " LIMIT " . PMPRO_CRON_LIMIT; } $orders = $wpdb->get_col($sqlQuery); if (empty($orders)) { continue; } foreach ($orders as $order_id) { $order = new MemberOrder($order_id); $user = get_userdata($order->user_id); $user->membership_level = pmpro_getMembershipLevelForUser($order->user_id); //check that user still has same level? if (empty($user->membership_level) || $order->membership_id != $user->membership_level->id) { continue; } //create new pending order $morder = new MemberOrder(); $morder->user_id = $order->user_id; $morder->membership_id = $user->membership_level->id; $morder->InitialPayment = $user->membership_level->billing_amount; $morder->PaymentAmount = $user->membership_level->billing_amount; $morder->BillingPeriod = $user->membership_level->cycle_period; $morder->BillingFrequency = $user->membership_level->cycle_number; $morder->subscription_transaction_id = $order->subscription_transaction_id; $morder->gateway = "check"; $morder->setGateway(); $morder->payment_type = "Check"; $morder->status = "pending"; //get timestamp for new order $order_timestamp = strtotime("+" . $combo, $order->timestamp); //let's skip if there is already an order for this user/level/timestamp $sqlQuery = "SELECT id FROM {$wpdb->pmpro_membership_orders} WHERE user_id = '" . $order->user_id . "' AND membership_id = '" . $order->membership_id . "' AND timestamp = '" . date('d', $order_timestamp) . "' LIMIT 1"; $dupe = $wpdb->get_var("SELECT id FROM {$wpdb->pmpro_membership_orders} WHERE user_id = '" . $order->user_id . "' AND membership_id = '" . $order->membership_id . "' AND timestamp = '" . $order_timestamp . "' LIMIT 1"); if (!empty($dupe)) { continue; } //save it $morder->process(); $morder->saveOrder(); //update the timestamp $morder->updateTimestamp(date("Y", $order_timestamp), date("m", $order_timestamp), date("d", $order_timestamp)); //send emails $email = new PMProEmail(); $email->template = "check_pending"; $email->email = $user->user_email; $email->subject = sprintf(__("New Invoice for %s at %s", "pmpropbc"), $user->membership_level->name, get_option("blogname")); } } } }
$end_timestamp = $old_subscription->current_period_end; //cancel the old subscription if (!$last_order->Gateway->cancelSubscriptionAtGateway($old_subscription)) { //email admin that the old subscription could not be canceled $pmproemail = new PMProEmail(); $pmproemail->data = array("body" => "<p>" . sprintf(__("While processing an update to the subscription for %s, we failed to cancel their old subscription in Stripe. Please check that this user's original subscription (%s) is cancelled in the Stripe dashboard.", "pmpro"), $user->display_name . " (" . $user->user_login . ", " . $user->user_email . ")", $old_subscription->id) . "</p>"); $pmproemail->sendEmail(get_bloginfo("admin_email")); } } //if we didn't get an end date, let's set one one cycle out if (empty($end_timestamp)) { $end_timestamp = strtotime("+" . $update['cycle_number'] . " " . $update['cycle_period']); } //build order object $update_order = new MemberOrder(); $update_order->setGateway('stripe'); $update_order->user_id = $user->ID; $update_order->membership_id = $user->membership_level->id; $update_order->membership_name = $user->membership_level->name; $update_order->InitialPayment = 0; $update_order->PaymentAmount = $update['billing_amount']; $update_order->ProfileStartDate = date_i18n("Y-m-d", $end_timestamp); $update_order->BillingPeriod = $update['cycle_period']; $update_order->BillingFrequency = $update['cycle_number']; //create new subscription $update_order->Gateway->subscribe($update_order); //update membership $sqlQuery = "UPDATE {$wpdb->pmpro_memberships_users}\n\t\t\t\t\t\t\t\t\t\t\t\tSET billing_amount = '" . esc_sql($update['billing_amount']) . "',\n\t\t\t\t\t\t\t\t\t\t\t\t\tcycle_number = '" . esc_sql($update['cycle_number']) . "',\n\t\t\t\t\t\t\t\t\t\t\t\t\tcycle_period = '" . esc_sql($update['cycle_period']) . "'\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE user_id = '" . esc_sql($user_id) . "'\n\t\t\t\t\t\t\t\t\t\t\t\t\tAND membership_id = '" . esc_sql($last_order->membership_id) . "'\n\t\t\t\t\t\t\t\t\t\t\t\t\tAND status = 'active'\n\t\t\t\t\t\t\t\t\t\t\t\tLIMIT 1"; $wpdb->query($sqlQuery); //save order so we know which plan to look for at stripe (order code = plan id) $update_order->status = "success";