$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'); $last_order->Gateway->getCustomer(); if (!empty($last_order->Gateway->customer)) { //find the first subscription
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; } }
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 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_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)) { //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 (false !== stripos($last_order->gateway, "paypal")) { if (isset($_POST['amount']) && !empty($_POST['amount'])) { $morder->InitialPayment = $_POST['amount']; //not the initial payment, but the class is expecting that $morder->PaymentAmount = $_POST['amount']; } elseif (isset($_POST['mc_gross']) && !empty($_POST['mc_gross'])) { $morder->InitialPayment = $_POST['mc_gross']; //not the initial payment, but the class is expecting that $morder->PaymentAmount = $_POST['mc_gross']; } elseif (isset($_POST['payment_gross']) && !empty($_POST['payment_gross'])) { $morder->InitialPayment = $_POST['payment_gross']; //not the initial payment, but the class is expecting that $morder->PaymentAmount = $_POST['payment_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; } //figure out timestamp or default to none (today) if (!empty($_POST['payment_date'])) { $morder->timestamp = strtotime($_POST['payment_date']); } // Save the event ID for the last processed user/IPN (in case we want to be able to replay IPN requests) $ipn_id = isset($_POST['ipn_track_id']) ? sanitize_text_field($_POST['ipn_track_id']) : null; // Allow extraction of the IPN Track ID from the order notes (if needed) $morder->notes = "{$morder->notes} [IPN_ID]{$ipn_id}[/IPN_ID]"; /** * Post processing for a specific subscription related IPN event ID * * @param string $ipn_id - The ipn_track_id from the PayPal IPN request * @param MemberOrder $morder - The completed Member Order object for the IPN request */ do_action('pmpro_subscription_ipn_event_processed', $ipn_id, $morder); if (!is_null($ipn_id)) { if (false === update_user_meta($morder->user_id, "pmpro_last_{$morder->gateway}_ipn_id", $ipn_id)) { ipnlog("Unable to save the IPN event ID ({$ipn_id}) to usermeta for {$morder->user_id} "); } } //save $morder->saveOrder(); $morder->getMemberOrderByID($morder->id); //email the user their invoice $pmproemail = new PMProEmail(); $pmproemail->sendInvoiceEmail(get_userdata($last_order->user_id), $morder); //hook for successful subscription payments do_action("pmpro_subscription_payment_completed", $morder); ipnlog("New order (" . $morder->code . ") created."); return true; } else { ipnlog("Duplicate Transaction ID: " . $txn_id); 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 />"; } }