Пример #1
0
function pmproet_admin_init_test_order()
{
    global $current_user, $pmproet_test_order_id;
    //make sure PMPro is activated
    if (!class_exists('MemberOrder')) {
        return;
    }
    $pmproet_test_order_id = get_option('pmproet_test_order_id');
    $test_order = new MemberOrder($pmproet_test_order_id);
    if (empty($test_order->id)) {
        $all_levels = pmpro_getAllLevels();
        if (!empty($all_levels)) {
            $first_level = array_shift($all_levels);
            $test_order->membership_id = $first_level->id;
            $test_order->InitialPayment = $first_level->initial_payment;
        } else {
            $test_order->membership_id = 1;
            $test_order->InitialPayment = 1;
        }
        $test_order->user_id = $current_user->ID;
        $test_order->cardtype = "Visa";
        $test_order->accountnumber = "4111111111111111";
        $test_order->expirationmonth = date('m', current_time('timestamp'));
        $test_order->expirationyear = intval(date('Y', current_time('timestamp'))) + 1;
        $test_order->ExpirationDate = $test_order->expirationmonth . $test_order->expirationyear;
        $test_order->CVV2 = '123';
        $test_order->FirstName = 'Jane';
        $test_order->LastName = 'Doe';
        $test_order->Address1 = '123 Street';
        $test_order->billing = new stdClass();
        $test_order->billing->name = 'Jane Doe';
        $test_order->billing->street = '123 Street';
        $test_order->billing->city = 'City';
        $test_order->billing->state = 'ST';
        $test_order->billing->country = 'US';
        $test_order->billing->zip = '12345';
        $test_order->billing->phone = '5558675309';
        $test_order->gateway_environment = 'sandbox';
        $test_order->notes = __('This is a test order used with the PMPro Email Templates addon.', 'pmpro');
        $test_order->saveOrder();
        $pmproet_test_order_id = $test_order->id;
        update_option('pmproet_test_order_id', $pmproet_test_order_id);
    }
}
Пример #2
0
 public function mark_referral_complete($order)
 {
     if ('success' !== strtolower($order->status)) {
         return;
     }
     $this->complete_referral($order->id);
     $referral = affiliate_wp()->referrals->get_by('reference', $order->id, $this->context);
     $order = new MemberOrder($order->id);
     // Prevent infinite loop
     remove_action('pmpro_updated_order', array($this, 'mark_referral_complete'), 10);
     $order->affiliate_id = $referral->affiliate_id;
     $amount = html_entity_decode(affwp_currency_filter(affwp_format_amount($referral->amount)), ENT_QUOTES, 'UTF-8');
     $name = affiliate_wp()->affiliates->get_affiliate_name($referral->affiliate_id);
     $note = sprintf(__('Referral #%d for %s recorded for %s', 'affiliate-wp'), $referral->referral_id, $amount, $name);
     if (empty($order->notes)) {
         $order->notes = $note;
     } else {
         $order->notes = $order->notes . "\n\n" . $note;
     }
     $order->saveOrder();
 }
Пример #3
0
    }
    if (!in_array("notes", $read_only_fields) && isset($_POST['notes'])) {
        $order->notes = stripslashes($_POST['notes']);
    }
    //affiliate stuff
    $affiliates = apply_filters("pmpro_orders_show_affiliate_ids", false);
    if (!empty($affiliates)) {
        if (!in_array("affiliate_id", $read_only_fields)) {
            $order->affiliate_id = $_POST['affiliate_id'];
        }
        if (!in_array("affiliate_subid", $read_only_fields)) {
            $order->affiliate_subid = $_POST['affiliate_subid'];
        }
    }
    //save
    if ($order->saveOrder() !== false) {
        //handle timestamp
        if ($order->updateTimestamp($_POST['ts_year'], $_POST['ts_month'], $_POST['ts_day']) !== false) {
            $pmpro_msg = __("Order saved successfully.", "pmpro");
            $pmpro_msgt = "success";
        } else {
            $pmpro_msg = __("Error updating order timestamp.", "pmpro");
            $pmpro_msgt = "error";
        }
    } else {
        $pmpro_msg = __("Error saving order.", "pmpro");
        $pmpro_msgt = "error";
    }
} else {
    //order passed?
    if (!empty($_REQUEST['order'])) {
 $morder->billing->street = $old_order->billing->street;
 $morder->billing->city = $old_order->billing->city;
 $morder->billing->state = $old_order->billing->state;
 $morder->billing->zip = $old_order->billing->zip;
 $morder->billing->country = $old_order->billing->country;
 $morder->billing->phone = $old_order->billing->phone;
 //get CC info that is on file
 $morder->cardtype = get_user_meta($user_id, "pmpro_CardType", true);
 $morder->accountnumber = hideCardNumber(get_user_meta($user_id, "pmpro_AccountNumber", true), false);
 $morder->expirationmonth = get_user_meta($user_id, "pmpro_ExpirationMonth", true);
 $morder->expirationyear = get_user_meta($user_id, "pmpro_ExpirationYear", true);
 $morder->ExpirationDate = $morder->expirationmonth . $morder->expirationyear;
 $morder->ExpirationDate_YdashM = $morder->expirationyear . "-" . $morder->expirationmonth;
 //save
 $morder->status = "success";
 $morder->saveOrder();
 $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);
function pmprosm_addDiscountCodeUse($user_id, $level_id, $code_id)
{
    global $wpdb;
    $user = get_userdata($user_id);
    //add blank order
    $morder = new MemberOrder();
    $morder->InitialPayment = 0;
    $morder->Email = $user->user_email;
    $morder->gateway = "free";
    //sponsored
    $morder->user_id = $user_id;
    $morder->membership_id = $level_id;
    $morder->saveOrder();
    if (!empty($morder->id)) {
        $code_order_id = $morder->id;
    } else {
        $code_order_id = "";
    }
    global $wpdb;
    $wpdb->query("INSERT INTO {$wpdb->pmpro_discount_codes_uses} (code_id, user_id, order_id, timestamp) VALUES('" . esc_sql($code_id) . "', '" . esc_sql($user_id) . "', '" . intval($code_order_id) . "', now())");
}
function pmpro_insSaveOrder($txn_id, $last_order)
{
    global $wpdb;
    //check that txn_id has not been previously processed
    $old_txn = $wpdb->get_var("SELECT payment_transaction_id FROM {$wpdb->pmpro_membership_orders} WHERE payment_transaction_id = '" . $txn_id . "' LIMIT 1");
    if (empty($old_txn)) {
        //hook for successful subscription payments
        do_action("pmpro_subscription_payment_completed");
        //save order
        $morder = new MemberOrder();
        $morder->user_id = $last_order->user_id;
        $morder->membership_id = $last_order->membership_id;
        $morder->payment_transaction_id = $txn_id;
        $morder->subscription_transaction_id = $last_order->subscription_transaction_id;
        $morder->InitialPayment = $_POST['item_list_amount_1'];
        //not the initial payment, but the class is expecting that
        $morder->PaymentAmount = $_POST['item_list_amount_1'];
        $morder->FirstName = $_POST['customer_first_name'];
        $morder->LastName = $_POST['customer_last_name'];
        $morder->Email = $_POST['customer_email'];
        //save
        $morder->saveOrder();
        $morder->getMemberOrderByID($morder->id);
        //email the user their invoice
        $pmproemail = new PMProEmail();
        $pmproemail->sendInvoiceEmail(get_userdata($last_order->user_id), $morder);
        inslog("New order (" . $morder->code . ") created.");
        return true;
    } else {
        inslog("Duplicate Transaction ID: " . $txn_id);
        return false;
    }
}
Пример #7
0
function pmpro_ipnSaveOrder($txn_id, $last_order)
{
    global $wpdb;
    //check that txn_id has not been previously processed
    $old_txn = $wpdb->get_var("SELECT payment_transaction_id FROM {$wpdb->pmpro_membership_orders} WHERE payment_transaction_id = '" . $txn_id . "' LIMIT 1");
    if (empty($old_txn)) {
        //hook for successful subscription payments
        do_action("pmpro_subscription_payment_completed");
        //save order
        $morder = new MemberOrder();
        $morder->user_id = $last_order->user_id;
        $morder->membership_id = $last_order->membership_id;
        $morder->payment_transaction_id = $txn_id;
        $morder->subscription_transaction_id = $last_order->subscription_transaction_id;
        $morder->gateway = $last_order->gateway;
        $morder->gateway_environment = $last_order->gateway_environment;
        // Payment Status
        $morder->status = 'success';
        // We have confirmed that and thats the reason we are here.
        // Payment Type.
        $morder->payment_type = $last_order->payment_type;
        //set amount based on which PayPal type
        if ($last_order->gateway == "paypal") {
            $morder->InitialPayment = $_POST['amount'];
            //not the initial payment, but the class is expecting that
            $morder->PaymentAmount = $_POST['amount'];
        } elseif ($last_order->gateway == "paypalexpress") {
            $morder->InitialPayment = $_POST['amount'];
            //not the initial payment, but the class is expecting that
            $morder->PaymentAmount = $_POST['amount'];
        } elseif ($last_order->gateway == "paypalstandard") {
            $morder->InitialPayment = $_POST['mc_gross'];
            //not the initial payment, but the class is expecting that
            $morder->PaymentAmount = $_POST['mc_gross'];
        }
        $morder->FirstName = $_POST['first_name'];
        $morder->LastName = $_POST['last_name'];
        $morder->Email = $_POST['payer_email'];
        //get address info if appropriate
        if ($last_order->gateway == "paypal") {
            $morder->Address1 = get_user_meta($last_order->user_id, "pmpro_baddress1", true);
            $morder->City = get_user_meta($last_order->user_id, "pmpro_bcity", true);
            $morder->State = get_user_meta($last_order->user_id, "pmpro_bstate", true);
            $morder->CountryCode = "US";
            $morder->Zip = get_user_meta($last_order->user_id, "pmpro_bzip", true);
            $morder->PhoneNumber = get_user_meta($last_order->user_id, "pmpro_bphone", true);
            $morder->billing->name = $_POST['first_name'] . " " . $_POST['last_name'];
            $morder->billing->street = get_user_meta($last_order->user_id, "pmpro_baddress1", true);
            $morder->billing->city = get_user_meta($last_order->user_id, "pmpro_bcity", true);
            $morder->billing->state = get_user_meta($last_order->user_id, "pmpro_bstate", true);
            $morder->billing->zip = get_user_meta($last_order->user_id, "pmpro_bzip", true);
            $morder->billing->country = get_user_meta($last_order->user_id, "pmpro_bcountry", true);
            $morder->billing->phone = get_user_meta($last_order->user_id, "pmpro_bphone", true);
            //get CC info that is on file
            $morder->cardtype = get_user_meta($last_order->user_id, "pmpro_CardType", true);
            $morder->accountnumber = hideCardNumber(get_user_meta($last_order->user_id, "pmpro_AccountNumber", true), false);
            $morder->expirationmonth = get_user_meta($last_order->user_id, "pmpro_ExpirationMonth", true);
            $morder->expirationyear = get_user_meta($last_order->user_id, "pmpro_ExpirationYear", true);
            $morder->ExpirationDate = $morder->expirationmonth . $morder->expirationyear;
            $morder->ExpirationDate_YdashM = $morder->expirationyear . "-" . $morder->expirationmonth;
        }
        //save
        $morder->saveOrder();
        $morder->getMemberOrderByID($morder->id);
        //email the user their invoice
        $pmproemail = new PMProEmail();
        $pmproemail->sendInvoiceEmail(get_userdata($last_order->user_id), $morder);
        ipnlog("New order (" . $morder->code . ") created.");
        return true;
    } else {
        ipnlog("Duplicate Transaction ID: " . $txn_id);
        return false;
    }
}
function pap_pmpro_after_checkout($user_id)
{
    $morder = new MemberOrder();
    $morder->getLastMemberOrder($user_id);
    if (empty($_COOKIE['pap_pmpro_affiliate'])) {
        return;
    }
    $parts = explode(",", $_COOKIE['pap_pmpro_affiliate']);
    $affiliate_code = $parts[0];
    $campaign_id = $parts[1];
    $channel_id = $parts[2];
    $visitor_id = $parts[3];
    if (empty($visitor_id) && !empty($_COOKIE['PAPVisitorId'])) {
        $visitor_id = $_COOKIE['PAPVisitorId'];
    }
    if (!empty($morder->total)) {
        //api
        pap_pmpro_track_sale($morder->total, $morder->code, $affiliate_code, $campaign_id, $channel_id, $visitor_id);
        //save affiliate id in order
        $morder->affiliate_id = $affiliate_code;
        $morder->affiliate_subid = $campaign_id . "," . $channel_id . "," . $visitor_id;
        $morder->saveOrder();
    }
}
 function gourlpmpro_gourlcallback($user_id, $order_id, $payment_details, $box_status)
 {
     global $wpdb;
     if (!in_array($box_status, array("cryptobox_newrecord", "cryptobox_updated"))) {
         return false;
     }
     if (strpos($order_id, "order") === 0) {
         $order_id = intval(substr($order_id, 5));
     } else {
         return false;
     }
     if (!$user_id || $payment_details["status"] != "payment_received") {
         return false;
     }
     // Initialize
     $coinName = ucfirst($payment_details["coinname"]);
     $amount = $payment_details["amount"] . " " . $payment_details["coinlabel"] . "  ( \$" . $payment_details["amountusd"] . " )";
     $payID = $payment_details["paymentID"];
     $trID = $payment_details["tx"];
     $confirmed = $payment_details["is_confirmed"] ? __('Yes', GOURLPMP) : __('No', GOURLPMP);
     $order = new MemberOrder();
     $order->getMemberOrderByID($order_id);
     // New Payment Received
     if ($box_status == "cryptobox_newrecord") {
         update_option(GOURL . "PMPRO_INIT_" . $user_id . "_" . $order->membership_id, date("m F Y"));
         PMProGateway_gourl::add_order_note($order_id, sprintf(__("<b>%s</b> payment received <br>%s <br>Payment id <a href='%s'>#%s</a>. Awaiting network confirmation...", GOURLPMP), $coinName, $amount, GOURL_ADMIN . GOURL . "payments&s=payment_" . $payID, $payID));
     }
     // Existing Payment confirmed (6+ confirmations)
     if ($payment_details["is_confirmed"]) {
         PMProGateway_gourl::add_order_note($order_id, sprintf(__("%s Payment id <a href='%s'>#%s</a> Confirmed", GOURLPMP), $coinName, GOURL_ADMIN . GOURL . "payments&s=payment_" . $payID, $payID));
     }
     // Update User Membership
     if (!empty($order) && $order->gateway == "gourl" && in_array($order->status, array("pending", "review", "token"))) {
         $pmpro_level = $wpdb->get_row("SELECT * FROM {$wpdb->pmpro_membership_levels} WHERE id = '" . (int) $order->membership_id . "' LIMIT 1");
         $startdate = apply_filters("pmpro_checkout_start_date", "'" . current_time("mysql") . "'", $user_id, $pmpro_level);
         if (strlen($order->subscription_transaction_id) > 3) {
             $enddate = "'" . date("Y-m-d", strtotime("+ " . $order->subscription_transaction_id, current_time("timestamp"))) . "'";
         } elseif (!empty($pmpro_level->expiration_number)) {
             $enddate = "'" . date("Y-m-d", strtotime("+ " . $pmpro_level->expiration_number . " " . $pmpro_level->expiration_period, current_time("timestamp"))) . "'";
         } else {
             $enddate = "NULL";
         }
         $custom_level = array('user_id' => $user_id, 'membership_id' => $pmpro_level->id, 'code_id' => '', 'initial_payment' => $pmpro_level->initial_payment, 'billing_amount' => $pmpro_level->billing_amount, 'cycle_number' => $pmpro_level->cycle_number, 'cycle_period' => $pmpro_level->cycle_period, 'billing_limit' => $pmpro_level->billing_limit, 'trial_amount' => $pmpro_level->trial_amount, 'trial_limit' => $pmpro_level->trial_limit, 'startdate' => $startdate, 'enddate' => $enddate);
         if (pmpro_changeMembershipLevel($custom_level, $user_id, 'changed')) {
             $order->status = "success";
             $order->membership_id = $pmpro_level->id;
             $order->payment_transaction_id = strtoupper($coinName . $payID);
             $order->saveOrder();
         }
     }
     return true;
 }
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"));
            }
        }
    }
}
function pmpro_insSaveOrder($txnref, $last_order)
{
    global $wpdb;
    //check that txn_id has not been previously processed
    $old_txn = $wpdb->get_var("SELECT payment_transaction_id FROM {$wpdb->pmpro_membership_orders} WHERE payment_transaction_id = '" . $txnref . "' LIMIT 1");
    if (empty($old_txn)) {
        //hook for successful subscription payments
        do_action("pmpro_subscription_payment_completed");
        //save order
        $morder = new MemberOrder();
        $morder->user_id = $last_order->user_id;
        $morder->membership_id = $last_order->membership_id;
        $morder->payment_transaction_id = $txnref;
        $morder->subscription_transaction_id = $last_order->subscription_transaction_id;
        $morder->InitialPayment = $last_order->InitialPayment;
        //$_POST['item_list_amount_1'];	//not the initial payment, but the class is expecting that
        $morder->PaymentAmount = $last_order->PaymentAmount;
        //$_POST['item_list_amount_1'];
        $morder->gateway = $last_order->gateway;
        $morder->gateway_environment = $last_order->gateway_environment;
        //save
        $morder->saveOrder();
        $pmproemail = new PMProEmail();
        $pmproemail->sendInvoiceEmail($user_id, $morder);
        $user = get_userdata($morder->user_id);
        $user->membership_level = $morder->membership_level;
        //make sure they have the right level info
        //send email to member
        $pmproemail = new PMProEmail();
        $pmproemail->sendCheckoutEmail($user_id, $morder);
        //send email to admin
        $pmproemail = new PMProEmail();
        $pmproemail->sendCheckoutAdminEmail($user_id, $morder);
        $morder->getMemberOrderByID($morder->id);
        // //email the user their invoice
        $pmproemail = new PMProEmail();
        $pmproemail->sendInvoiceEmail(get_userdata($last_order->user_id), $morder);
        if (strpos(PMPRO_INS_DEBUG, "@")) {
            $log_email = PMPRO_INS_DEBUG;
        } else {
            $log_email = get_option("admin_email");
        }
        inslog("New order (" . $morder->code . ") created.");
        return true;
    } else {
        inslog("Duplicate Transaction ID: " . $txnref);
        return false;
    }
}
function pmpro_payflow_recurring_orders()
{
    //is PMPro even active?
    if (!function_exists('pmpro_hasMembershipLevel')) {
        return;
    }
    global $wpdb;
    $now = current_time('timestamp');
    //between what hours should the cron run?
    $cron_start = 1;
    //1 AM
    $cron_end = 6;
    //6 AM
    $current_hour = date('G', $now);
    if ($current_hour > $cron_end || $current_hour < $cron_start) {
        return;
    }
    //where did we leave off?
    if (isset($_REQUEST['start'])) {
        $start = intval($_REQUEST['start']);
        delete_option('pmpro_pfro_paused');
    } else {
        $start = get_option('payflow_recurring_orders_cron_count', 0);
    }
    //are we paused? value is timestamp. if set wait until then
    $paused = get_option('pmpro_pfro_paused', false);
    if (!empty($paused) && $paused > $now) {
        return;
    }
    //how many subscriptions to run at one time. based on your server speed and timeout limits/etc.
    $nper = 50;
    //next one
    $end = intval($start) + intval($nper);
    //get subs
    $sqlQuery = "\n\t\tSELECT SQL_CALC_FOUND_ROWS user_id FROM\n\t\t(\n\t\t\tSELECT mu.user_id,\n\t\t\t\tCASE mu.cycle_period\n\t\t\t\t\tWHEN 'Day' THEN date_add(mo.timestamp, INTERVAL mu.cycle_number DAY)\n\t\t\t\t\tWHEN 'Month' THEN date_add(mo.timestamp, INTERVAL mu.cycle_number MONTH)\n\t\t\t\t\tWHEN 'Week' THEN date_add(mo.timestamp, INTERVAL mu.cycle_number WEEK)\n\t\t\t\t\tWHEN 'Year' THEN date_add(mo.timestamp, INTERVAL mu.cycle_number YEAR)\n\t\t\t\tEND as next_payment_date\n\t\t\tFROM {$wpdb->pmpro_memberships_users} mu\n\t\t\t\tLEFT JOIN {$wpdb->pmpro_membership_orders} mo\n\t\t\t\t\tON mo.id = (\n\t\t\t\t\t\tSELECT id FROM {$wpdb->pmpro_membership_orders} WHERE gateway = 'payflowpro' AND status NOT IN('review', 'token', 'pending') AND user_id = mu.user_id ORDER BY id DESC LIMIT 1\n\t\t\t\t\t)\n\t\t\tWHERE mu.status = 'active'\n\t\t\t\tAND mo.subscription_transaction_id <> ''\n\t\t) members\n\t\tWHERE DATEDIFF('" . current_time('mysql') . "', next_payment_date) >= 0\n\t\tLIMIT {$start}, {$nper}\n\t";
    $sub_user_ids = $wpdb->get_col($sqlQuery);
    $count = $wpdb->get_var('SELECT FOUND_ROWS()');
    echo "Processing " . intval($start) . " to " . (intval($start) + intval($nper)) . " of " . $count . " subscriptions.<hr />";
    //if no more subs, pause until tomorrow
    if (empty($sub_user_ids)) {
        echo "All done. Pausing until tomorrow.<br />";
        $tomorrow = strtotime(date("Y-m-d 00:00:00", $now + 3600 * 24));
        update_option('pmpro_pfro_paused', $tomorrow);
        update_option('payflow_recurring_orders_cron_count', 0);
        return;
    }
    $failed_payment_emails = array();
    //loop through subs
    foreach ($sub_user_ids as $user_id) {
        $user = get_userdata($user_id);
        if (empty($user->ID)) {
            echo "Coundn't find user #" . $user_id . "...<br /><hr />";
            continue;
        }
        echo "Checking for recurring orders for user #" . $user->ID . " " . $user->user_login . " (" . $user->user_email . ")...<br />";
        $last_order = new MemberOrder();
        $last_order->getLastMemberOrder($user_id);
        if (!empty($last_order->id)) {
            echo "- Last order found. #" . $last_order->id . ", Code: " . $last_order->code . ", SubID: " . $last_order->subscription_transaction_id . ".<br />";
        } else {
            echo "- No last order. Skipping.";
            echo "<hr />";
            continue;
        }
        //is it even Payflow?
        if ($last_order->gateway != "payflowpro") {
            echo "- Order is for '" . $last_order->gateway . "' gateway.<br />";
            echo "<hr />";
            continue;
        }
        //check subscription
        if (!empty($last_order->subscription_transaction_id)) {
            echo "- Checking subscription #" . $last_order->subscription_transaction_id . ".<br />";
            $status = pmpropfro_getSubscriptionPayments($last_order);
            //find orders
            $payments = pmpropfro_processPaymentHistory($status);
            if (!empty($payments)) {
                foreach ($payments as $payment) {
                    if ($payment['P_TRANSTATE'] == 1 || $payment['P_TRANSTATE'] == 11) {
                        echo "- Failed payment #" . $payment['P_PNREF'] . ".";
                        //check if we have this one already
                        $old_order = new MemberOrder();
                        $old_order->getMemberOrderByPaymentTransactionID($payment['P_PNREF']);
                        if (empty($old_order->id)) {
                            $failed_payment_emails[] = $user->user_email;
                            //not there yet, add it
                            $morder = new MemberOrder();
                            $morder->user_id = $last_order->user_id;
                            $morder->membership_id = $last_order->membership_id;
                            $morder->payment_transaction_id = $payment['P_PNREF'];
                            $morder->subscription_transaction_id = $last_order->subscription_transaction_id;
                            $morder->InitialPayment = $payment['P_AMT'];
                            //not the initial payment, but the class is expecting that
                            $morder->PaymentAmount = $payment['P_AMT'];
                            $morder->status = "error";
                            //save
                            $morder->saveOrder();
                            $morder->getMemberOrderByID($morder->id);
                            echo " Saving order.";
                            //this will affect the main query, so need to roll back the "end" 1 space
                            $end--;
                            //unless there is another non-failed payment more recent, cancel their membership
                            if (!pmpropfro_paymentAfter($payments, strtotime($payment['P_TRANSTIME']))) {
                                //cancel membership
                                pmpro_changeMembershipLevel(0, $user_id);
                                echo " Membership cancelled. Member emailed.";
                                //notify them
                                $myemail = new PMProEmail();
                                $myemail->sendCancelEmail($user);
                            } else {
                                echo " More recent successful order. So not cancelling membership.";
                            }
                        } else {
                            echo " Already logged.";
                        }
                        echo "<br />";
                    } elseif ($payment['P_TRANSTATE'] == 8) {
                        //check if we have this one already
                        $old_order = new MemberOrder();
                        $old_order->getMemberOrderByPaymentTransactionID($payment['P_PNREF']);
                        if (empty($old_order->id)) {
                            //not there yet, add it
                            $morder = new MemberOrder();
                            $morder->user_id = $last_order->user_id;
                            $morder->membership_id = $last_order->membership_id;
                            $morder->payment_transaction_id = $payment['P_PNREF'];
                            $morder->subscription_transaction_id = $last_order->subscription_transaction_id;
                            $morder->InitialPayment = $payment['P_AMT'];
                            //not the initial payment, but the class is expecting that
                            $morder->PaymentAmount = $payment['P_AMT'];
                            $morder->status = "success";
                            //save
                            $morder->saveOrder();
                            $morder->getMemberOrderByID($morder->id);
                            //this will affect the main query, so need to roll back the "end" 1 space
                            $end--;
                            if (!empty($morder->id)) {
                                //update the timestamp
                                $timestamp = date("Y-m-d H:i:s", strtotime($payment['P_TRANSTIME']));
                                $wpdb->query("UPDATE {$wpdb->pmpro_membership_orders} SET timestamp = '" . $timestamp . "' WHERE id = '" . $morder->id . "' LIMIT 1");
                                echo "<strong>- Order added. #" . $morder->id . ".</strong><br />";
                                //email the user their invoice
                                $pmproemail = new PMProEmail();
                                $pmproemail->sendInvoiceEmail($user, $morder);
                                echo "- Invoice email sent to " . $user->user_email . ".";
                            } else {
                                echo "- Error adding order.";
                            }
                        } else {
                            echo "- Order already saved for #" . $payment['P_TRANSTATE'] . ".<br />";
                        }
                    } else {
                        echo "<strong>- Payment " . $payment['P_PNREF'] . " has status #" . $payment['P_TRANSTATE'] . " so not saving.</strong><br />";
                    }
                }
            } else {
                echo "- No payments found.<br />";
            }
        }
        echo "<hr />";
        echo "Going to start with #" . $end . " next time.";
        update_option('payflow_recurring_orders_cron_count', $end);
    }
    echo "<hr />";
    foreach ($failed_payment_emails as $email) {
        echo $email . "<br />";
    }
}