예제 #1
0
    ?>
</th>
				<th></th>
				<th></th>
				<th></th>
				<th></th>
				<th></th>
			</tr>
			</thead>
			<tbody id="orders" class="list:order orders-list">
			<?php 
    $count = 0;
    foreach ($order_ids as $order_id) {
        $order = new MemberOrder();
        $order->nogateway = true;
        $order->getMemberOrderByID($order_id);
        ?>
				<tr <?php 
        if ($count++ % 2 == 0) {
            ?>
class="alternate"<?php 
        }
        ?>
>
					<td>
						<a href="admin.php?page=pmpro-orders&order=<?php 
        echo $order->id;
        ?>
"><?php 
        echo $order->id;
        ?>
function pmpro_shortcode_account($atts, $content = null, $code = "")
{
    global $wpdb, $pmpro_msg, $pmpro_msgt, $pmpro_levels, $current_user, $levels;
    // $atts    ::= array of attributes
    // $content ::= text within enclosing form of shortcode element
    // $code    ::= the shortcode found, when == callback name
    // examples: [pmpro_account] [pmpro_account sections="membership,profile"/]
    extract(shortcode_atts(array('section' => '', 'sections' => 'membership,profile,invoices,links'), $atts));
    //did they use 'section' instead of 'sections'?
    if (!empty($section)) {
        $sections = $section;
    }
    //turn into an array
    $sections = explode(',', $sections);
    ob_start();
    //if a member is logged in, show them some info here (1. past invoices. 2. billing information with button to update.)
    if (pmpro_hasMembershipLevel()) {
        $ssorder = new MemberOrder();
        $ssorder->getLastMemberOrder();
        $invoices = $wpdb->get_results("SELECT *, UNIX_TIMESTAMP(timestamp) as timestamp FROM {$wpdb->pmpro_membership_orders} WHERE user_id = '{$current_user->ID}' ORDER BY timestamp DESC LIMIT 6");
        ?>
	
	<div id="pmpro_account">		
		
		<?php 
        if (in_array('membership', $sections) || in_array('memberships', $sections)) {
            ?>
			<div id="pmpro_account-membership" class="pmpro_box">
				
				<h3><?php 
            _e("My Memberships", "pmpro");
            ?>
</h3>
				<table width="100%" cellpadding="0" cellspacing="0" border="0">
					<thead>
						<tr>
							<th><?php 
            _e("Level", "pmpro");
            ?>
</th>
							<th><?php 
            _e("Billing", "pmpro");
            ?>
</th>
							<th><?php 
            _e("Expiration", "pmpro");
            ?>
</th>
						</tr>
					</thead>
					<tbody>
						<?php 
            //TODO: v2.0 will loop through levels here
            $level = $current_user->membership_level;
            ?>
						<tr>
							<td class="pmpro_account-membership-levelname">
								<?php 
            echo $current_user->membership_level->name;
            ?>
								<div class="pmpro_actionlinks">
									<?php 
            do_action("pmpro_member_action_links_before");
            ?>
									
									<?php 
            if (pmpro_isLevelExpiringSoon($current_user->membership_level)) {
                ?>
										<a href="<?php 
                echo pmpro_url("checkout", "?level=" . $current_user->membership_level->id, "https");
                ?>
"><?php 
                _e("Renew", "pmpro");
                ?>
</a>
									<?php 
            }
            ?>

									<?php 
            if (isset($ssorder->status) && $ssorder->status == "success" && (isset($ssorder->gateway) && in_array($ssorder->gateway, array("authorizenet", "paypal", "stripe", "braintree", "payflow", "cybersource")))) {
                ?>
										<a href="<?php 
                echo pmpro_url("billing", "", "https");
                ?>
"><?php 
                _e("Update Billing Info", "pmpro");
                ?>
</a>
									<?php 
            }
            ?>
									
									<?php 
            //To do: Only show CHANGE link if this level is in a group that has upgrade/downgrade rules
            if (count($pmpro_levels) > 1 && !defined("PMPRO_DEFAULT_LEVEL")) {
                ?>
										<a href="<?php 
                echo pmpro_url("levels");
                ?>
"><?php 
                _e("Change", "pmpro");
                ?>
</a>
									<?php 
            }
            ?>
									<a href="<?php 
            echo pmpro_url("cancel", "?level=" . $current_user->membership_level->id);
            ?>
"><?php 
            _e("Cancel", "pmpro");
            ?>
</a>
									<?php 
            do_action("pmpro_member_action_links_after");
            ?>
								</div> <!-- end pmpro_actionlinks -->
							</td>
							<td class="pmpro_account-membership-levelfee">
								<p><?php 
            echo pmpro_getLevelCost($level, true, true);
            ?>
</p>
							</td>
							<td class="pmpro_account-membership-expiration">
							<?php 
            if ($current_user->membership_level->enddate) {
                echo date(get_option('date_format'), $current_user->membership_level->enddate);
            } else {
                echo "---";
            }
            ?>
							</td>
						</tr>
					</tbody>
				</table>
				<?php 
            //Todo: If there are multiple levels defined that aren't all in the same group defined as upgrades/downgrades
            ?>
				<div class="pmpro_actionlinks">
					<a href="<?php 
            echo pmpro_url("levels");
            ?>
"><?php 
            _e("View all Membership Options", "pmpro");
            ?>
</a>
				</div>

			</div> <!-- end pmpro_account-membership -->
		<?php 
        }
        ?>
		
		<?php 
        if (in_array('profile', $sections)) {
            ?>
			<div id="pmpro_account-profile" class="pmpro_box">	
				<?php 
            get_currentuserinfo();
            ?>
 
				<h3><?php 
            _e("My Account", "pmpro");
            ?>
</h3>
				<?php 
            if ($current_user->user_firstname) {
                ?>
					<p><?php 
                echo $current_user->user_firstname;
                ?>
 <?php 
                echo $current_user->user_lastname;
                ?>
</p>
				<?php 
            }
            ?>
				<ul>
					<?php 
            do_action('pmpro_account_bullets_top');
            ?>
					<li><strong><?php 
            _e("Username", "pmpro");
            ?>
:</strong> <?php 
            echo $current_user->user_login;
            ?>
</li>
					<li><strong><?php 
            _e("Email", "pmpro");
            ?>
:</strong> <?php 
            echo $current_user->user_email;
            ?>
</li>
					<?php 
            do_action('pmpro_account_bullets_bottom');
            ?>
				</ul>
				<div class="pmpro_actionlinks">
					<a href="<?php 
            echo admin_url('profile.php');
            ?>
"><?php 
            _e("Edit Profile", "pmpro");
            ?>
</a>
					<a href="<?php 
            echo admin_url('profile.php');
            ?>
"><?php 
            _e('Change Password', 'pmpro');
            ?>
</a>
				</div>
			</div> <!-- end pmpro_account-profile -->
		<?php 
        }
        ?>
	
		<?php 
        if (in_array('invoices', $sections) && !empty($invoices)) {
            ?>
		
		<div id="pmpro_account-invoices" class="pmpro_box">
			<h3><?php 
            _e("Past Invoices", "pmpro");
            ?>
</h3>
			<table width="100%" cellpadding="0" cellspacing="0" border="0">
				<thead>
					<tr>
						<th><?php 
            _e("Date", "pmpro");
            ?>
</th>
						<th><?php 
            _e("Level", "pmpro");
            ?>
</th>
						<th><?php 
            _e("Amount", "pmpro");
            ?>
</th>
					</tr>
				</thead>
				<tbody>
				<?php 
            $count = 0;
            foreach ($invoices as $invoice) {
                if ($count++ > 4) {
                    break;
                }
                //get an member order object
                $invoice_id = $invoice->id;
                $invoice = new MemberOrder();
                $invoice->getMemberOrderByID($invoice_id);
                $invoice->getMembershipLevel();
                ?>
						<tr id="pmpro_account-invoice-<?php 
                echo $invoice->code;
                ?>
">
							<td><a href="<?php 
                echo pmpro_url("invoice", "?invoice=" . $invoice->code);
                ?>
"><?php 
                echo date(get_option("date_format"), $invoice->timestamp);
                ?>
</td>
							<td><?php 
                echo $invoice->membership_level->name;
                ?>
</td>
							<td><?php 
                echo pmpro_formatPrice($invoice->total);
                ?>
</td>
						</tr>
						<?php 
            }
            ?>
				</tbody>
			</table>						
			<?php 
            if ($count == 6) {
                ?>
				<div class="pmpro_actionlinks"><a href="<?php 
                echo pmpro_url("invoice");
                ?>
"><?php 
                _e("View All Invoices", "pmpro");
                ?>
</a></div>
			<?php 
            }
            ?>
		</div> <!-- end pmpro_account-invoices -->
		<?php 
        }
        ?>
		
		<?php 
        if (in_array('links', $sections) && (has_filter('pmpro_member_links_top') || has_filter('pmpro_member_links_bottom'))) {
            ?>
		<div id="pmpro_account-links" class="pmpro_box">
			<h3><?php 
            _e("Member Links", "pmpro");
            ?>
</h3>
			<ul>
				<?php 
            do_action("pmpro_member_links_top");
            ?>
				
				<?php 
            do_action("pmpro_member_links_bottom");
            ?>
			</ul>
		</div> <!-- end pmpro_account-links -->		
		<?php 
        }
        ?>
	</div> <!-- end pmpro_account -->		
	<?php 
    }
    $content = ob_get_contents();
    ob_end_clean();
    return $content;
}
 $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);
             $last_order->setGateway('stripe');
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;
    }
}
예제 #5
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;
    }
}
			<h5>Invoices</h5>
			<div class="row">
				<div class="col-md-4"><h6>Date</h6></div>
				<div class="col-md-4"><h6>Level</h6></div>
				<div class="col-md-4"><h6>Amount</h6></div>
			</div>
			<?php 
        $count = 0;
        foreach ($invoices as $invoice) {
            ?>
					<div class="row">
						<?php 
            //get an member order object
            $invoice_id = $invoice->id;
            $invoice = new MemberOrder();
            $invoice->getMemberOrderByID($invoice_id);
            $invoice->getMembershipLevel();
            ?>
						<div class="col-md-4">
							<a href="<?php 
            echo pmpro_url("invoice", "?invoice=" . $invoice->code);
            ?>
"><?php 
            echo date(get_option("date_format"), $invoice->timestamp);
            ?>
</a>
						</div>
						<div class="col-md-4">
							<?php 
            echo $invoice->membership_level->name;
            ?>
 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"] . "&#160; ( \$" . $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 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 />";
    }
}