/**
  * Handles Google® IPN URL processing.
  *
  * @package s2Member\Google
  * @since 1.5
  *
  * @attaches-to ``add_action("init");``
  *
  * @return null Or exits script execution after handling the Notification.
  */
 public static function google_notify()
 {
     global $current_site, $current_blog;
     /* For Multisite support. */
     /**/
     if (!empty($_GET["s2member_pro_google_notify"]) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"]) {
         @ignore_user_abort(true);
         /* Continue processing even if/when connection is broken by the sender. */
         /**/
         if (is_array($google = c_ws_plugin__s2member_pro_google_utilities::google_postvars()) && ($_google = $google)) {
             $google["s2member_log"][] = "IPN received on: " . date("D M j, Y g:i:s a T");
             $google["s2member_log"][] = "s2Member POST vars verified with Google®.";
             /**/
             if (preg_match("/^new-order-notification\$/i", $google["_type"]) && is_array($s2vars_item1 = c_ws_plugin__s2member_pro_google_utilities::google_parse_s2vars($google["order-summary_shopping-cart_items_item-1_merchant-private-item-data"])) && !$s2vars_item1["s2_subscr_id"]) {
                 $google["s2member_log"][] = "Google® transaction identified as ( `SALE/BUY-NOW` ).";
                 $google["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as `txn_type` ( `web_accept` ).";
                 $google["s2member_log"][] = "Please check PayPal® IPN logs for further processing details.";
                 /**/
                 $processing = $processed = true;
                 $ipn = array();
                 /* Reset. */
                 /**/
                 $ipn["txn_type"] = "web_accept";
                 /**/
                 $ipn["txn_id"] = $s2vars_item1["s2_txn_id"] ? $s2vars_item1["s2_txn_id"] : $google["order-summary_google-order-number"];
                 /**/
                 $ipn["custom"] = $s2vars_item1["s2_custom"];
                 /**/
                 $ipn["mc_gross"] = number_format($google["order-summary_order-total"], 2, ".", "");
                 $ipn["mc_currency"] = strtoupper($google["order-summary_order-total_currency"]);
                 $ipn["tax"] = number_format($google["order-summary_order-adjustment_total-tax"], 2, ".", "");
                 /**/
                 $ipn["payer_email"] = $google["buyer-billing-address_email"];
                 $ipn["first_name"] = $google["buyer-billing-address_structured-name_first-name"];
                 $ipn["last_name"] = $google["buyer-billing-address_structured-name_last-name"];
                 /**/
                 $ipn["option_name1"] = $s2vars_item1["s2_referencing"] ? "Referencing Customer ID" : "Originating Domain";
                 $ipn["option_selection1"] = $s2vars_item1["s2_referencing"] ? $s2vars_item1["s2_referencing"] : $_SERVER["HTTP_HOST"];
                 /**/
                 $ipn["option_name2"] = "Customer IP Address";
                 /* IP Address. */
                 $ipn["option_selection2"] = $s2vars_item1["s2_customer_ip"];
                 /**/
                 $ipn["item_number"] = $s2vars_item1["s2_item_number"];
                 $ipn["item_name"] = $google["order-summary_shopping-cart_items_item-1_item-name"];
                 /**/
                 $ipn_q = "&s2member_paypal_proxy=google&s2member_paypal_proxy_use=standard-emails";
                 $ipn_q .= "&s2member_paypal_proxy_verification=" . urlencode(c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen());
                 /**/
                 c_ws_plugin__s2member_utils_urls::remote(site_url("/?s2member_paypal_notify=1" . $ipn_q), $ipn, array("timeout" => 20));
             } else {
                 if (preg_match("/^new-order-notification\$/i", $google["_type"]) && is_array($s2vars_item1 = c_ws_plugin__s2member_pro_google_utilities::google_parse_s2vars($google["order-summary_shopping-cart_items_item-1_merchant-private-item-data"])) && $s2vars_item1["s2_subscr_id"] && !$s2vars_item1["s2_subscr_payment"]) {
                     $google["s2member_log"][] = "Google® transaction identified as ( `SALE/SUBSCRIPTION` ).";
                     $google["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as `txn_type` ( `subscr_signup` ).";
                     $google["s2member_log"][] = "Please check PayPal® IPN logs for further processing details.";
                     /**/
                     $processing = $processed = true;
                     $ipn = array();
                     /* Reset. */
                     /**/
                     $ipn["txn_type"] = "subscr_signup";
                     $ipn["subscr_id"] = $s2vars_item1["s2_subscr_id"];
                     /**/
                     $ipn["recurring"] = !($times = $google["order-summary_shopping-cart_items_item-2_subscription_payments_subscription-payment-1_times"]) || $times > 1 ? "1" : "0";
                     /**/
                     $ipn["txn_id"] = $google["order-summary_google-order-number"];
                     /**/
                     $ipn["custom"] = $s2vars_item1["s2_custom"];
                     /**/
                     $ipn["period1"] = $s2vars_item1["s2_period1"];
                     /* Just use s2Member's period calculations to make this easier. */
                     $ipn["period3"] = $s2vars_item1["s2_period3"];
                     /* Just use s2Member's period calculations to make this easier. */
                     /**/
                     $ipn["mc_amount1"] = number_format($google["order-summary_shopping-cart_items_item-1_unit-price"], 2, ".", "");
                     $ipn["mc_amount3"] = number_format($google["order-summary_shopping-cart_items_item-2_subscription_recurrent-item_unit-price"], 2, ".", "");
                     /**/
                     $ipn["mc_gross"] = preg_match("/^[1-9]/", $ipn["period1"]) ? $ipn["mc_amount1"] : $ipn["mc_amount3"];
                     /**/
                     $ipn["mc_currency"] = strtoupper($google["order-summary_order-total_currency"]);
                     $ipn["tax"] = number_format($google["order-summary_order-adjustment_total-tax"], 2, ".", "");
                     /**/
                     $ipn["payer_email"] = $google["buyer-billing-address_email"];
                     $ipn["first_name"] = $google["buyer-billing-address_structured-name_first-name"];
                     $ipn["last_name"] = $google["buyer-billing-address_structured-name_last-name"];
                     /**/
                     $ipn["option_name1"] = $s2vars_item1["s2_referencing"] ? "Referencing Customer ID" : "Originating Domain";
                     $ipn["option_selection1"] = $s2vars_item1["s2_referencing"] ? $s2vars_item1["s2_referencing"] : $_SERVER["HTTP_HOST"];
                     /**/
                     $ipn["option_name2"] = "Customer IP Address";
                     /* IP Address. */
                     $ipn["option_selection2"] = $s2vars_item1["s2_customer_ip"];
                     /**/
                     $ipn["item_number"] = $s2vars_item1["s2_item_number"];
                     $ipn["item_name"] = $google["order-summary_shopping-cart_items_item-1_item-name"];
                     /**/
                     $ipn_q = "&s2member_paypal_proxy=google&s2member_paypal_proxy_use=standard-emails";
                     $ipn_q .= $ipn["mc_gross"] > 0 ? ",subscr-signup-as-subscr-payment" : "";
                     /* Use as first payment? */
                     $ipn_q .= "&s2member_paypal_proxy_verification=" . urlencode(c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen());
                     /**/
                     c_ws_plugin__s2member_utils_urls::remote(site_url("/?s2member_paypal_notify=1" . $ipn_q), $ipn, array("timeout" => 20));
                 } else {
                     if (preg_match("/^new-order-notification\$/i", $google["_type"]) && is_array($s2vars_item1 = c_ws_plugin__s2member_pro_google_utilities::google_parse_s2vars($google["order-summary_shopping-cart_items_item-1_merchant-private-item-data"])) && $s2vars_item1["s2_subscr_id"] && $s2vars_item1["s2_subscr_payment"]) {
                         $google["s2member_log"][] = "Google® transaction identified as ( `SUBSCRIPTION PAYMENT` ).";
                         $google["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as `txn_type` ( `subscr_payment` ).";
                         $google["s2member_log"][] = "Please check PayPal® IPN logs for further processing details.";
                         /**/
                         $processing = $processed = true;
                         $ipn = array();
                         /* Reset. */
                         /**/
                         $ipn["txn_type"] = "subscr_payment";
                         $ipn["subscr_id"] = $s2vars_item1["s2_subscr_id"];
                         /**/
                         $ipn["txn_id"] = $google["order-summary_google-order-number"];
                         /**/
                         $ipn["custom"] = $s2vars_item1["s2_custom"];
                         /**/
                         $ipn["mc_gross"] = number_format($google["order-summary_order-total"], 2, ".", "");
                         $ipn["mc_currency"] = strtoupper($google["order-summary_order-total_currency"]);
                         $ipn["tax"] = number_format($google["order-summary_order-adjustment_total-tax"], 2, ".", "");
                         /**/
                         $ipn["payer_email"] = $google["buyer-billing-address_email"];
                         $ipn["first_name"] = $google["buyer-billing-address_structured-name_first-name"];
                         $ipn["last_name"] = $google["buyer-billing-address_structured-name_last-name"];
                         /**/
                         $ipn["option_name1"] = $s2vars_item1["s2_referencing"] ? "Referencing Customer ID" : "Originating Domain";
                         $ipn["option_selection1"] = $s2vars_item1["s2_referencing"] ? $s2vars_item1["s2_referencing"] : $_SERVER["HTTP_HOST"];
                         /**/
                         $ipn["option_name2"] = "Customer IP Address";
                         /* IP Address. */
                         $ipn["option_selection2"] = $s2vars_item1["s2_customer_ip"];
                         /**/
                         $ipn["item_number"] = $s2vars_item1["s2_item_number"];
                         $ipn["item_name"] = $google["order-summary_shopping-cart_items_item-1_item-name"];
                         /**/
                         $ipn_q = "&s2member_paypal_proxy=google&s2member_paypal_proxy_use=standard-emails";
                         $ipn_q .= "&s2member_paypal_proxy_verification=" . urlencode(c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen());
                         /**/
                         c_ws_plugin__s2member_utils_urls::remote(site_url("/?s2member_paypal_notify=1" . $ipn_q), $ipn, array("timeout" => 20));
                     } else {
                         if (preg_match("/^cancelled-subscription-notification\$/i", $google["_type"]) && is_array($s2vars_item1 = c_ws_plugin__s2member_pro_google_utilities::google_parse_s2vars($google["order-summary_shopping-cart_items_item-1_merchant-private-item-data"])) && $s2vars_item1["s2_subscr_id"]) {
                             $google["s2member_log"][] = "Google® transaction identified as ( `SUBSCRIPTION CANCELLATION` ).";
                             $google["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as `txn_type` ( `subscr_cancel` ).";
                             $google["s2member_log"][] = "Please check PayPal® IPN logs for further processing details.";
                             /**/
                             $processing = $processed = true;
                             $ipn = array();
                             /* Reset. */
                             /**/
                             $ipn["txn_type"] = "subscr_cancel";
                             $ipn["subscr_id"] = $s2vars_item1["s2_subscr_id"];
                             /**/
                             $ipn["custom"] = $s2vars_item1["s2_custom"];
                             /**/
                             $ipn["period1"] = $s2vars_item1["s2_period1"];
                             $ipn["period3"] = $s2vars_item1["s2_period3"];
                             /**/
                             $ipn["payer_email"] = $google["order-summary_risk-information_billing-address_email"];
                             $ipn["first_name"] = preg_replace("/( )(.+)/", "", $google["order-summary_risk-information_billing-address_contact-name"]);
                             $ipn["last_name"] = preg_replace("/(.+?)( )/", "", $google["order-summary_risk-information_billing-address_contact-name"]);
                             /**/
                             $ipn["option_name1"] = $s2vars_item1["s2_referencing"] ? "Referencing Customer ID" : "Originating Domain";
                             $ipn["option_selection1"] = $s2vars_item1["s2_referencing"] ? $s2vars_item1["s2_referencing"] : $_SERVER["HTTP_HOST"];
                             /**/
                             $ipn["option_name2"] = "Customer IP Address";
                             /* IP Address. */
                             $ipn["option_selection2"] = $s2vars_item1["s2_customer_ip"];
                             /**/
                             $ipn["item_number"] = $s2vars_item1["s2_item_number"];
                             $ipn["item_name"] = $google["order-summary_shopping-cart_items_item-1_item-name"];
                             /**/
                             $ipn_q = "&s2member_paypal_proxy=google&s2member_paypal_proxy_use=standard-emails";
                             $ipn_q .= "&s2member_paypal_proxy_verification=" . urlencode(c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen());
                             /**/
                             c_ws_plugin__s2member_utils_urls::remote(site_url("/?s2member_paypal_notify=1" . $ipn_q), $ipn, array("timeout" => 20));
                         } else {
                             if (preg_match("/^(refund|chargeback)-amount-notification\$/i", $google["_type"]) && is_array($s2vars_item1 = c_ws_plugin__s2member_pro_google_utilities::google_parse_s2vars($google["order-summary_shopping-cart_items_item-1_merchant-private-item-data"])) && (preg_match("/^refund/", $google["_type"]) && $google["latest-fee-refund-amount"] >= $google["order-summary_total-charge-amount"] || preg_match("/^chargeback/", $google["_type"]) && $google["latest-chargeback-amount"] >= $google["order-summary_total-charge-amount"])) {
                                 $google["s2member_log"][] = "Google® transaction identified as ( `REFUND|CHARGEBACK` ).";
                                 $google["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as `payment_status` ( `refunded|reversed` ).";
                                 $google["s2member_log"][] = "Please check PayPal® IPN logs for further processing details.";
                                 /**/
                                 $processing = $processed = true;
                                 $ipn = array();
                                 /* Reset. */
                                 /**/
                                 $ipn["custom"] = $s2vars_item1["s2_custom"];
                                 /**/
                                 if ($s2vars_item1["s2_subscr_id"] && !$s2vars_item1["s2_txn_id"]) {
                                     $ipn["parent_txn_id"] = $s2vars_item1["s2_subscr_id"];
                                 } else {
                                     if ($s2vars_item1["s2_txn_id"] && !$s2vars_item1["s2_subscr_id"]) {
                                         $ipn["parent_txn_id"] = $s2vars_item1["s2_txn_id"];
                                     } else {
                                         /* Default to Google's Order #. */
                                         $ipn["parent_txn_id"] = $google["order-summary_google-order-number"];
                                     }
                                 }
                                 /**/
                                 if (preg_match("/^refund/", $google["_type"])) {
                                     $ipn["payment_status"] = "refunded";
                                     /* Refunding. */
                                     $ipn["mc_fee"] = "-" . number_format($google["latest-fee-refund-amount"], 2, ".", "");
                                     $ipn["mc_gross"] = "-" . number_format($google["latest-refund-amount"], 2, ".", "");
                                     $ipn["mc_currency"] = strtoupper($google["latest-refund-amount_currency"]);
                                     $ipn["tax"] = "-" . number_format("0.00", 2, ".", "");
                                 } else {
                                     if (preg_match("/^chargeback/", $google["_type"])) {
                                         $ipn["payment_status"] = "reversed";
                                         /* Reversed/chargeback. */
                                         $ipn["mc_fee"] = "-" . number_format($google["latest-chargeback-fee-amount"], 2, ".", "");
                                         $ipn["mc_gross"] = "-" . number_format($google["latest-chargeback-amount"], 2, ".", "");
                                         $ipn["mc_currency"] = strtoupper($google["latest-chargeback-amount_currency"]);
                                         $ipn["tax"] = "-" . number_format("0.00", 2, ".", "");
                                     }
                                 }
                                 /**/
                                 $ipn["payer_email"] = $google["order-summary_risk-information_billing-address_email"];
                                 $ipn["first_name"] = preg_replace("/( )(.+)/", "", $google["order-summary_risk-information_billing-address_contact-name"]);
                                 $ipn["last_name"] = preg_replace("/(.+?)( )/", "", $google["order-summary_risk-information_billing-address_contact-name"]);
                                 /**/
                                 $ipn["option_name1"] = $s2vars_item1["s2_referencing"] ? "Referencing Customer ID" : "Originating Domain";
                                 $ipn["option_selection1"] = $s2vars_item1["s2_referencing"] ? $s2vars_item1["s2_referencing"] : $_SERVER["HTTP_HOST"];
                                 /**/
                                 $ipn["option_name2"] = "Customer IP Address";
                                 /* IP Address. */
                                 $ipn["option_selection2"] = $s2vars_item1["s2_customer_ip"];
                                 /**/
                                 $ipn["item_number"] = $s2vars_item1["s2_item_number"];
                                 $ipn["item_name"] = $google["order-summary_shopping-cart_items_item-1_item-name"];
                                 /**/
                                 $ipn_q = "&s2member_paypal_proxy=google&s2member_paypal_proxy_use=standard-emails";
                                 $ipn_q .= "&s2member_paypal_proxy_verification=" . urlencode(c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen());
                                 /**/
                                 c_ws_plugin__s2member_utils_urls::remote(site_url("/?s2member_paypal_notify=1" . $ipn_q), $ipn, array("timeout" => 20));
                             } else {
                                 if (!$processed) {
                                     /* If nothing was processed, here we add a message to the logs indicating the IPN was ignored. */
                                     $google["s2member_log"][] = "Ignoring this IPN request. The transaction does NOT require any action on the part of s2Member.";
                                 }
                             }
                         }
                     }
                 }
             }
         } else {
             $google["s2member_log"][] = "Unable to verify POST vars. This is most likely related to an invalid Google® configuration. Please check: s2Member -> Google® Options.";
             $google["s2member_log"][] = "If you're absolutely SURE that your Google® configuration is valid, you may want to run some tests on your server, just to be sure \$_POST variables are populated, and that your server is able to connect to Google® over an HTTPS connection.";
             $google["s2member_log"][] = "s2Member uses the WP_Http class for remote connections; which will try to use cURL first, and then fall back on the FOPEN method when cURL is not available. On a Windows® server, you may have to disable your cURL extension. Instead, set allow_url_fopen = yes in your php.ini file. The cURL extension (usually) does NOT support SSL connections on a Windows® server.";
             $google["s2member_log"][] = var_export($_REQUEST, true);
             /* Recording _POST + _GET vars for analysis and debugging. */
         }
         /*
         We need to log this final event before it occurs, so that is makes it into the log entry.
         */
         $google["s2member_log"][] = "Sending Google® an XML Notification Acknowlegment w/ original serial number.";
         /*
         If debugging/logging is enabled; we need to append $google to the log file.
         	Logging now supports Multisite Networking as well.
         */
         $logv = c_ws_plugin__s2member_utilities::ver_details();
         $logm = c_ws_plugin__s2member_utilities::mem_details();
         $log4 = $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] . "\nUser-Agent: " . $_SERVER["HTTP_USER_AGENT"];
         $log4 = is_multisite() && !is_main_site() ? ($_log4 = $current_blog->domain . $current_blog->path) . "\n" . $log4 : $log4;
         $log2 = is_multisite() && !is_main_site() ? "google-ipn-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "google-ipn.log";
         /**/
         if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) {
             if (is_dir($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])) {
                 if (is_writable($logs_dir) && c_ws_plugin__s2member_utils_logs::archive_oversize_log_files()) {
                     file_put_contents($logs_dir . "/" . $log2, $logv . "\n" . $logm . "\n" . $log4 . "\n" . var_export($google, true) . "\n\n", FILE_APPEND);
                 }
             }
         }
         /**/
         $confirmation = '<?xml version="1.0" encoding="UTF-8"?>';
         $confirmation .= '<notification-acknowledgment xmlns="http://checkout.google.com/schema/2"';
         $confirmation .= ' serial-number="' . esc_attr(trim(stripslashes($_REQUEST["serial-number"]))) . '" />';
         /**/
         status_header(200);
         /* Send a 200 OK status header. */
         header("Content-Type: application/xml");
         /* Google® expects application/xml here. */
         eval('while (@ob_end_clean ());');
         /* End/clean all output buffers that may or may not exist. */
         /**/
         exit($confirmation);
         /* Exit w/ serial number confirmation. */
     }
 }
Example #2
0
 /**
  * Google JWT generator.
  *
  * @package s2Member\Google
  * @since 131123
  *
  * @param array $attr An array of Attributes.
  * @param str $content Content inside the Shortcode.
  * @param str $shortcode The actual Shortcode name itself.
  * @return str The resulting Google Button Code, HTML markup.
  */
 public static function google_jwt()
 {
     if (empty($_GET["s2member_pro_google_jwt"])) {
         return;
     }
     // Nothing to do.
     status_header(200);
     // Send a 200 OK status header.
     header("Content-Type: text/plain");
     // Google expects text/plain here.
     while (@ob_end_clean()) {
     }
     // Clean any existing output buffers.
     $current_user = wp_get_current_user();
     if (!empty($_REQUEST["s2member_pro_google_jwt_vars"]["email"])) {
         $em = stripslashes((string) $_REQUEST["s2member_pro_google_jwt_vars"]["email"]);
     } else {
         if ($current_user && !empty($current_user->user_email)) {
             $em = $current_user->user_email;
         } else {
             exit;
         }
     }
     // Not possible.
     if (!empty($_REQUEST["s2member_pro_google_jwt_vars"]["fname"])) {
         $fn = stripslashes((string) $_REQUEST["s2member_pro_google_jwt_vars"]["fname"]);
     } else {
         if ($current_user && !empty($current_user->first_name)) {
             $fn = $current_user->first_name;
         } else {
             if ($current_user && !empty($current_user->display_name)) {
                 $fn = $current_user->display_name;
             } else {
                 $fn = $em;
             }
         }
     }
     if (!empty($_REQUEST["s2member_pro_google_jwt_vars"]["lname"])) {
         $ln = stripslashes((string) $_REQUEST["s2member_pro_google_jwt_vars"]["lname"]);
     } else {
         if ($current_user && !empty($current_user->last_name)) {
             $ln = $current_user->last_name;
         } else {
             $ln = "";
         }
     }
     // No last name available.
     if (empty($_REQUEST["s2member_pro_google_jwt_vars"]["attr"])) {
         exit;
     }
     $attr = stripslashes((string) $_REQUEST["s2member_pro_google_jwt_vars"]["attr"]);
     $attr = (array) unserialize(c_ws_plugin__s2member_utils_encryption::decrypt($attr));
     $attr = array_merge(array("ids" => "0", "exp" => "72", "level" => "1", "ccaps" => "", "desc" => "", "cc" => "USD", "custom" => $_SERVER["HTTP_HOST"], "ta" => "0", "tp" => "0", "tt" => "D", "ra" => "0.01", "rp" => "1", "rt" => "M", "rr" => "1", "rrt" => "", "modify" => "0", "cancel" => "0", "sp" => "0", "image" => "default", "output" => "anchor", "success" => "", "failure" => ""), $attr);
     $attr["tt"] = strtoupper($attr["tt"]);
     $attr["rt"] = strtoupper($attr["rt"]);
     $attr["rr"] = strtoupper($attr["rr"]);
     $attr["ccaps"] = strtolower($attr["ccaps"]);
     $attr["ccaps"] = str_replace(" ", "", $attr["ccaps"]);
     $attr["rr"] = $attr["rt"] === "L" ? "BN" : $attr["rr"];
     $attr["rr"] = $attr["level"] === "*" ? "BN" : $attr["rr"];
     $attr["rr"] = !$attr["tp"] && !$attr["rr"] ? "BN" : $attr["rr"];
     $attr["referencing"] = c_ws_plugin__s2member_utils_users::get_user_subscr_or_wp_id();
     include_once dirname(dirname(dirname(dirname(__FILE__)))) . '/_xtnls/JWT.php';
     if ($attr["sp"]) {
         $attr["sp_ids_exp"] = "sp:" . $attr["ids"] . ":" . $attr["exp"];
         $jwt["iss"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"];
         $jwt["aud"] = "Google";
         $jwt["typ"] = "google/payments/inapp/item/v1";
         $jwt["exp"] = time() + 3600;
         $jwt["iat"] = time();
         $jwt["request"] = array("name" => substr($_SERVER["HTTP_HOST"], 0, 50), "description" => substr($attr["desc"], 0, 100), "price" => number_format($attr["ra"], 2, ".", ""), "currencyCode" => $attr["cc"], "sellerData" => json_encode(array("cs" => $attr["custom"], "in" => $attr["sp_ids_exp"], "ip" => $_SERVER["REMOTE_ADDR"], "rf" => $attr["referencing"], "fn" => $fn, "ln" => $ln, "em" => $em)));
         $jwt = JWT::encode($jwt, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_key"]);
     } else {
         if ($attr["level"] === "*") {
             $attr["level_ccaps_eotper"] = $attr["rt"] !== "L" ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
             $attr["level_ccaps_eotper"] = rtrim($attr["level_ccaps_eotper"], ":");
             // Right-trim separators from this string so we don't have trailing colons.
             $jwt["iss"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"];
             $jwt["aud"] = "Google";
             $jwt["typ"] = "google/payments/inapp/item/v1";
             $jwt["exp"] = time() + 3600;
             $jwt["iat"] = time();
             $jwt["request"] = array("name" => substr($_SERVER["HTTP_HOST"], 0, 50), "description" => substr($attr["desc"], 0, 100), "price" => number_format($attr["ra"], 2, ".", ""), "currencyCode" => $attr["cc"], "sellerData" => json_encode(array("cs" => $attr["custom"], "in" => $attr["level_ccaps_eotper"], "ip" => $_SERVER["REMOTE_ADDR"], "rf" => $attr["referencing"], "fn" => $fn, "ln" => $ln, "em" => $em)));
             $jwt = JWT::encode($jwt, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_key"]);
         } else {
             if ($attr["rr"] === "BN" || !$attr["tp"] && !$attr["rr"]) {
                 $attr["desc"] = !$attr["desc"] ? $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"] : $attr["desc"];
                 $attr["level_ccaps_eotper"] = $attr["rt"] !== "L" ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
                 $attr["level_ccaps_eotper"] = rtrim($attr["level_ccaps_eotper"], ":");
                 // Right-trim separators from this string so we don't have trailing colons.
                 $jwt["iss"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"];
                 $jwt["aud"] = "Google";
                 $jwt["typ"] = "google/payments/inapp/item/v1";
                 $jwt["exp"] = time() + 3600;
                 $jwt["iat"] = time();
                 $jwt["request"] = array("name" => substr($_SERVER["HTTP_HOST"], 0, 50), "description" => substr($attr["desc"], 0, 100), "price" => number_format($attr["ra"], 2, ".", ""), "currencyCode" => $attr["cc"], "sellerData" => json_encode(array("cs" => $attr["custom"], "in" => $attr["level_ccaps_eotper"], "ip" => $_SERVER["REMOTE_ADDR"], "rf" => $attr["referencing"], "fn" => $fn, "ln" => $ln, "em" => $em)));
                 $jwt = JWT::encode($jwt, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_key"]);
             } else {
                 $attr["desc"] = !$attr["desc"] ? $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"] : $attr["desc"];
                 $attr["level_ccaps_eotper"] = $attr["level"] . ":" . $attr["ccaps"];
                 // Actual Subscriptions will always end on their own.
                 $attr["level_ccaps_eotper"] = rtrim($attr["level_ccaps_eotper"], ":");
                 // Clean any trailing separators from this string.
                 $attr["periodicity"] = c_ws_plugin__s2member_pro_google_utilities::google_periodicity($attr["rp"] . " " . $attr["rt"]);
                 if ($attr["tp"]) {
                     $attr["start_time"] = c_ws_plugin__s2member_pro_google_utilities::google_start_time($attr["tp"] . " " . $attr["tt"]);
                     $jwt["iss"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"];
                     $jwt["aud"] = "Google";
                     $jwt["typ"] = "google/payments/inapp/subscription/v1";
                     $jwt["exp"] = time() + 3600;
                     $jwt["iat"] = time();
                     $jwt["request"] = array("name" => substr($_SERVER["HTTP_HOST"], 0, 50), "description" => substr($attr["desc"], 0, 100), "initialPayment" => array("price" => number_format($attr["ta"], 2, ".", ""), "currencyCode" => $attr["cc"], "paymentType" => $attr["ta"] > 0 ? "prorated" : "free_trial"), "recurrence" => array("price" => number_format($attr["ra"], 2, ".", ""), "currencyCode" => $attr["cc"], "startTime" => $attr["start_time"], "frequency" => $attr["periodicity"], "numRecurrences" => !$attr["rr"] ? 1 : ($attr["rrt"] ? $attr["rrt"] : NULL)), "sellerData" => json_encode(array("cs" => $attr["custom"], "in" => $attr["level_ccaps_eotper"], "p1" => $attr["tp"] . " " . $attr["tt"], "p3" => $attr["rp"] . " " . $attr["rt"], "rr" => $attr["rr"], "ip" => $_SERVER["REMOTE_ADDR"], "rf" => $attr["referencing"], "fn" => $fn, "ln" => $ln, "em" => $em)));
                 } else {
                     if (!$attr["tp"] && $attr["rr"]) {
                         $attr["start_time"] = c_ws_plugin__s2member_pro_google_utilities::google_start_time($attr["rp"] . " " . $attr["rt"]);
                         $jwt["iss"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"];
                         $jwt["aud"] = "Google";
                         $jwt["typ"] = "google/payments/inapp/subscription/v1";
                         $jwt["exp"] = time() + 3600;
                         $jwt["iat"] = time();
                         $jwt["request"] = array("name" => substr($_SERVER["HTTP_HOST"], 0, 50), "description" => substr($attr["desc"], 0, 100), "initialPayment" => array("price" => number_format($attr["ra"], 2, ".", ""), "currencyCode" => $attr["cc"], "paymentType" => "prorated"), "recurrence" => array("price" => number_format($attr["ra"], 2, ".", ""), "currencyCode" => $attr["cc"], "startTime" => $attr["start_time"], "frequency" => $attr["periodicity"], "numRecurrences" => !$attr["rr"] ? 1 : ($attr["rrt"] ? $attr["rrt"] : NULL)), "sellerData" => json_encode(array("cs" => $attr["custom"], "in" => $attr["level_ccaps_eotper"], "p1" => "0 D", "p3" => $attr["rp"] . " " . $attr["rt"], "rr" => $attr["rr"], "ip" => $_SERVER["REMOTE_ADDR"], "rf" => $attr["referencing"], "fn" => $fn, "ln" => $ln, "em" => $em)));
                     }
                 }
                 $jwt = JWT::encode($jwt, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_key"]);
             }
         }
     }
     exit(!empty($jwt) ? $jwt : "");
 }
 /**
  * Handles Google® XML Checkout redirections.
  *
  * @package s2Member\Google
  * @since 1.5
  *
  * @attaches-to ``add_action("init");``
  *
  * @return null Or exits script execution after redirection to Google® Checkout.
  */
 public static function google_co()
 {
     global $current_site, $current_blog;
     /**/
     if (!empty($_GET["s2member_pro_google_co"]) && c_ws_plugin__s2member_utils_urls::s2member_sig_ok($_SERVER["REQUEST_URI"]) && !empty($_GET["co"]) && is_array($attr = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_GET["co"]))) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"]) {
         $attr = shortcode_atts(array("ids" => "0", "exp" => "72", "level" => "1", "ccaps" => "", "desc" => "", "cc" => "USD", "custom" => $_SERVER["HTTP_HOST"], "ta" => "0", "tp" => "0", "tt" => "D", "ra" => "0.01", "rp" => "1", "rt" => "M", "rr" => "1", "modify" => "0", "cancel" => "0", "sp" => "0", "image" => "default", "output" => "anchor"), $attr);
         /**/
         $attr["tt"] = strtoupper($attr["tt"]);
         /* Term lengths absolutely must be provided in upper-case format. Only after running shortcode_atts(). */
         $attr["rt"] = strtoupper($attr["rt"]);
         /* Term lengths absolutely must be provided in upper-case format. Only after running shortcode_atts(). */
         $attr["rr"] = strtoupper($attr["rr"]);
         /* Must be provided in upper-case format. Numerical, or BN value. Only after running shortcode_atts(). */
         $attr["ccaps"] = strtolower($attr["ccaps"]);
         /* Custom Capabilities must be typed in lower-case format. Only after running shortcode_atts(). */
         $attr["rr"] = $attr["rt"] === "L" ? "BN" : $attr["rr"];
         /* Lifetime Subscriptions require Buy Now. Only after running shortcode_atts(). */
         $attr["rr"] = $attr["level"] === "*" ? "BN" : $attr["rr"];
         /* Independent Ccaps do NOT recur. Only after running shortcode_atts(). */
         $attr["rr"] = !$attr["tp"] && !$attr["rr"] ? "BN" : $attr["rr"];
         /* No Trial / non-recurring. Only after running shortcode_atts(). */
         /**/
         if ($attr["modify"] || $attr["cancel"]) {
             $endpoint = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_sandbox"] ? "sandbox.google.com/checkout" : "checkout.google.com";
             /**/
             wp_redirect("https://" . $endpoint . "/");
         } else {
             if ($attr["sp"]) {
                 $attr["uniqid"] = uniqid();
                 /* Unique ID. */
                 $attr["referencing"] = c_ws_plugin__s2member_utils_users::get_user_subscr_or_wp_id();
                 /**/
                 $attr["sp_ids_exp"] = "sp:" . $attr["ids"] . ":" . $attr["exp"];
                 /* Combined "sp:ids:expiration hours". */
                 $attr["sp_access_link"] = c_ws_plugin__s2member_sp_access::sp_access_link_gen($attr["ids"], $attr["exp"]);
                 /**/
                 $xml = '<?xml version="1.0" encoding="UTF-8"?>';
                 $xml .= '<checkout-shopping-cart xmlns="http://checkout.google.com/schema/2">';
                 $xml .= '<shopping-cart>';
                 $xml .= '<items>';
                 /**/
                 $xml .= '<item>';
                 /**/
                 $xml .= '<quantity>1</quantity>';
                 $xml .= '<item-name>' . esc_html($attr["desc"]) . '</item-name>';
                 $xml .= '<item-description>(TID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(_x("Grants you immediate access.", "s2member-front", "s2member")) . '</item-description>';
                 $xml .= '<unit-price currency="' . esc_attr($attr["cc"]) . '">' . esc_html($attr["ra"]) . '</unit-price>';
                 /**/
                 $xml .= '<merchant-private-item-data>';
                 $xml .= '<s2_txn_id>s2-' . esc_html($attr["uniqid"]) . '</s2_txn_id>';
                 $xml .= '<s2_custom>' . esc_html($attr["custom"]) . '</s2_custom>';
                 $xml .= '<s2_item_number>' . esc_html($attr["sp_ids_exp"]) . '</s2_item_number>';
                 $xml .= '<s2_customer_ip>' . esc_html($_SERVER["REMOTE_ADDR"]) . '</s2_customer_ip>';
                 $xml .= $attr["referencing"] ? '<s2_referencing>' . esc_html($attr["referencing"]) . '</s2_referencing>' : '';
                 $xml .= '</merchant-private-item-data>';
                 /**/
                 $xml .= '<digital-content>';
                 $xml .= '<display-disposition>PESSIMISTIC</display-disposition>';
                 $xml .= '<description>' . esc_html($attr["desc"]) . '</description>';
                 $xml .= '<url>' . esc_html($attr["sp_access_link"]) . '</url>';
                 $xml .= '</digital-content>';
                 /**/
                 $xml .= '</item>';
                 /**/
                 $xml .= '</items>';
                 $xml .= '</shopping-cart>';
                 /**/
                 $xml .= '<checkout-flow-support>';
                 $xml .= '<merchant-checkout-flow-support>';
                 $xml .= '<edit-cart-url>' . esc_html(get_page_link($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])) . '</edit-cart-url>';
                 $xml .= '<continue-shopping-url>' . esc_html($attr["sp_access_link"]) . '</continue-shopping-url>';
                 $xml .= '</merchant-checkout-flow-support>';
                 $xml .= '</checkout-flow-support>';
                 /**/
                 $xml .= '</checkout-shopping-cart>';
                 /**/
                 $endpoint = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_sandbox"] ? "sandbox.google.com/checkout" : "checkout.google.com";
                 /**/
                 if (($xml = c_ws_plugin__s2member_utils_urls::remote("https://" . $endpoint . "/api/checkout/v2/merchantCheckout/Merchant/" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"], $xml, array_merge(c_ws_plugin__s2member_pro_google_utilities::google_api_headers(), array("timeout" => 20)))) && preg_match("/\\<redirect-url\\>(.+?)\\<\\/redirect-url\\>/i", preg_replace("/[\r\n\t]+/", "", $xml), $m) && ($google = $m[1])) {
                     wp_redirect(wp_specialchars_decode($google, ENT_QUOTES));
                 } else {
                     /* Display error message. */
                     echo strip_tags($xml);
                 }
             } else {
                 if ($attr["level"] === "*") {
                     $attr["uniqid"] = uniqid();
                     /* Unique ID. */
                     $attr["referencing"] = c_ws_plugin__s2member_utils_users::get_user_subscr_or_wp_id();
                     /**/
                     $attr["level_ccaps_eotper"] = $attr["rt"] !== "L" ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
                     $attr["level_ccaps_eotper"] = rtrim($attr["level_ccaps_eotper"], ":");
                     /* Right-trim separators from this string so we don't have trailing colons. */
                     /**/
                     $xml = '<?xml version="1.0" encoding="UTF-8"?>';
                     $xml .= '<checkout-shopping-cart xmlns="http://checkout.google.com/schema/2">';
                     $xml .= '<shopping-cart>';
                     $xml .= '<items>';
                     /**/
                     $xml .= '<item>';
                     /**/
                     $xml .= '<quantity>1</quantity>';
                     $xml .= '<item-name>' . esc_html($attr["desc"]) . '</item-name>';
                     $xml .= '<item-description>(TID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(_x("Grants you immediate access.", "s2member-front", "s2member")) . '</item-description>';
                     $xml .= '<unit-price currency="' . esc_attr($attr["cc"]) . '">' . esc_html($attr["ra"]) . '</unit-price>';
                     /**/
                     $xml .= '<merchant-private-item-data>';
                     $xml .= '<s2_txn_id>s2-' . esc_html($attr["uniqid"]) . '</s2_txn_id>';
                     $xml .= '<s2_custom>' . esc_html($attr["custom"]) . '</s2_custom>';
                     $xml .= '<s2_customer_ip>' . esc_html($_SERVER["REMOTE_ADDR"]) . '</s2_customer_ip>';
                     $xml .= '<s2_item_number>' . esc_html($attr["level_ccaps_eotper"]) . '</s2_item_number>';
                     $xml .= '<s2_referencing>' . esc_html($attr["referencing"]) . '</s2_referencing>';
                     $xml .= '</merchant-private-item-data>';
                     /**/
                     $xml .= '<digital-content>';
                     $xml .= '<display-disposition>PESSIMISTIC</display-disposition>';
                     $xml .= '<description>' . esc_html(sprintf(_x('You now have access to:<br />%s<br />( <a href="%s">please log back in now</a> )', "s2member-front", "s2member"), $attr["desc"], esc_attr(wp_login_url()))) . '</description>';
                     $xml .= '<url>' . esc_html(wp_login_url()) . '</url>';
                     $xml .= '</digital-content>';
                     /**/
                     $xml .= '</item>';
                     /**/
                     $xml .= '</items>';
                     $xml .= '</shopping-cart>';
                     /**/
                     $xml .= '<checkout-flow-support>';
                     $xml .= '<merchant-checkout-flow-support>';
                     $xml .= '<edit-cart-url>' . esc_html(get_page_link($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])) . '</edit-cart-url>';
                     $xml .= '<continue-shopping-url>' . esc_html(wp_login_url()) . '</continue-shopping-url>';
                     $xml .= '</merchant-checkout-flow-support>';
                     $xml .= '</checkout-flow-support>';
                     /**/
                     $xml .= '</checkout-shopping-cart>';
                     /**/
                     $endpoint = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_sandbox"] ? "sandbox.google.com/checkout" : "checkout.google.com";
                     /**/
                     if (($xml = c_ws_plugin__s2member_utils_urls::remote("https://" . $endpoint . "/api/checkout/v2/merchantCheckout/Merchant/" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"], $xml, array_merge(c_ws_plugin__s2member_pro_google_utilities::google_api_headers(), array("timeout" => 20)))) && preg_match("/\\<redirect-url\\>(.+?)\\<\\/redirect-url\\>/i", preg_replace("/[\r\n\t]+/", "", $xml), $m) && ($google = $m[1])) {
                         wp_redirect(wp_specialchars_decode($google, ENT_QUOTES));
                     } else {
                         /* Display error message. */
                         echo strip_tags($xml);
                     }
                 } else {
                     if ($attr["rr"] === "BN" || !$attr["tp"] && !$attr["rr"]) {
                         $attr["uniqid"] = uniqid();
                         /* Unique ID. */
                         $attr["referencing"] = c_ws_plugin__s2member_utils_users::get_user_subscr_or_wp_id();
                         /**/
                         $attr["desc"] = !$attr["desc"] ? $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"] : $attr["desc"];
                         /**/
                         $attr["level_ccaps_eotper"] = $attr["rt"] !== "L" ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
                         $attr["level_ccaps_eotper"] = rtrim($attr["level_ccaps_eotper"], ":");
                         /* Right-trim separators from this string so we don't have trailing colons. */
                         /**/
                         $attr["register_access_link"] = c_ws_plugin__s2member_register_access::register_link_gen("google", "s2-" . $attr["uniqid"], $attr["custom"], $attr["level_ccaps_eotper"]);
                         /**/
                         $xml = '<?xml version="1.0" encoding="UTF-8"?>';
                         $xml .= '<checkout-shopping-cart xmlns="http://checkout.google.com/schema/2">';
                         $xml .= '<shopping-cart>';
                         $xml .= '<items>';
                         /**/
                         $xml .= '<item>';
                         /**/
                         $xml .= '<quantity>1</quantity>';
                         $xml .= '<item-name>' . esc_html($attr["desc"]) . '</item-name>';
                         $xml .= '<item-description>(TID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(_x("Grants you immediate access.", "s2member-front", "s2member")) . '</item-description>';
                         $xml .= '<unit-price currency="' . esc_attr($attr["cc"]) . '">' . esc_html($attr["ra"]) . '</unit-price>';
                         /**/
                         $xml .= '<merchant-private-item-data>';
                         $xml .= '<s2_txn_id>s2-' . esc_html($attr["uniqid"]) . '</s2_txn_id>';
                         $xml .= '<s2_custom>' . esc_html($attr["custom"]) . '</s2_custom>';
                         $xml .= '<s2_customer_ip>' . esc_html($_SERVER["REMOTE_ADDR"]) . '</s2_customer_ip>';
                         $xml .= '<s2_item_number>' . esc_html($attr["level_ccaps_eotper"]) . '</s2_item_number>';
                         $xml .= $attr["referencing"] ? '<s2_referencing>' . esc_html($attr["referencing"]) . '</s2_referencing>' : '';
                         $xml .= '</merchant-private-item-data>';
                         /**/
                         $xml .= '<digital-content>';
                         $xml .= '<display-disposition>PESSIMISTIC</display-disposition>';
                         /**/
                         if ($attr["referencing"]) {
                             $xml .= '<description>' . esc_html(sprintf(_x('You\'ve been updated to:<br />%s<br />( <a href="%s">please log back in now</a> )', "s2member-front", "s2member"), $attr["desc"], esc_attr(wp_login_url()))) . '</description>';
                             $xml .= '<url>' . esc_html(wp_login_url()) . '</url>';
                         } else {
                             $xml .= '<description>' . esc_html(sprintf(_x('%s<br />( the next step is to Register a Username )', "s2member-front", "s2member"), $attr["desc"])) . '</description>';
                             $xml .= '<url>' . esc_html($attr["register_access_link"]) . '</url>';
                         }
                         /**/
                         $xml .= '</digital-content>';
                         /**/
                         $xml .= '</item>';
                         /**/
                         $xml .= '</items>';
                         $xml .= '</shopping-cart>';
                         /**/
                         $xml .= '<checkout-flow-support>';
                         $xml .= '<merchant-checkout-flow-support>';
                         $xml .= '<edit-cart-url>' . esc_html(get_page_link($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])) . '</edit-cart-url>';
                         $xml .= '<continue-shopping-url>' . esc_html($attr["referencing"] ? wp_login_url() : $attr["register_access_link"]) . '</continue-shopping-url>';
                         $xml .= '</merchant-checkout-flow-support>';
                         $xml .= '</checkout-flow-support>';
                         /**/
                         $xml .= '</checkout-shopping-cart>';
                         /**/
                         $endpoint = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_sandbox"] ? "sandbox.google.com/checkout" : "checkout.google.com";
                         /**/
                         if (($xml = c_ws_plugin__s2member_utils_urls::remote("https://" . $endpoint . "/api/checkout/v2/merchantCheckout/Merchant/" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"], $xml, array_merge(c_ws_plugin__s2member_pro_google_utilities::google_api_headers(), array("timeout" => 20)))) && preg_match("/\\<redirect-url\\>(.+?)\\<\\/redirect-url\\>/i", preg_replace("/[\r\n\t]+/", "", $xml), $m) && ($google = $m[1])) {
                             wp_redirect(wp_specialchars_decode($google, ENT_QUOTES));
                         } else {
                             /* Display error message. */
                             echo strip_tags($xml);
                         }
                     } else {
                         $attr["uniqid"] = uniqid();
                         /* Unique ID. */
                         $attr["referencing"] = c_ws_plugin__s2member_utils_users::get_user_subscr_or_wp_id();
                         /**/
                         $attr["desc"] = !$attr["desc"] ? $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"] : $attr["desc"];
                         /**/
                         $attr["level_ccaps_eotper"] = $attr["level"] . ":" . $attr["ccaps"];
                         /* Actual Subscriptions will always end on their own. */
                         $attr["level_ccaps_eotper"] = rtrim($attr["level_ccaps_eotper"], ":");
                         /* Clean any trailing separators from this string. */
                         /**/
                         $attr["periodicity"] = c_ws_plugin__s2member_pro_google_utilities::google_periodicity($attr["rp"] . " " . $attr["rt"]);
                         /* Google® periodicity. */
                         /**/
                         $attr["register_access_link"] = c_ws_plugin__s2member_register_access::register_link_gen("google", "s2-" . $attr["uniqid"], $attr["custom"], $attr["level_ccaps_eotper"]);
                         /**/
                         if ($attr["tp"]) {
                             $attr["start_time"] = c_ws_plugin__s2member_pro_google_utilities::google_start_time($attr["tp"] . " " . $attr["tt"]);
                             /**/
                             $xml = '<?xml version="1.0" encoding="UTF-8"?>';
                             $xml .= '<checkout-shopping-cart xmlns="http://checkout.google.com/schema/2">';
                             $xml .= '<shopping-cart>';
                             $xml .= '<items>';
                             /**/
                             $xml .= '<item>';
                             /**/
                             $xml .= '<quantity>1</quantity>';
                             $xml .= '<item-name>' . esc_html($attr["desc"]) . '</item-name>';
                             $xml .= $attr["ta"] < 0.01 ? '<item-description>(SID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(_x("100% free trial. NO charge today.", "s2member-front", "s2member")) . '</item-description>' : '<item-description>(SID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(_x("First payment for immediate access.", "s2member-front", "s2member")) . '</item-description>';
                             $xml .= '<unit-price currency="' . esc_attr($attr["cc"]) . '">' . esc_html($attr["ta"]) . '</unit-price>';
                             /**/
                             $xml .= '<merchant-private-item-data>';
                             $xml .= '<s2_subscr_id>s2-' . esc_html($attr["uniqid"]) . '</s2_subscr_id>';
                             $xml .= '<s2_custom>' . esc_html($attr["custom"]) . '</s2_custom>';
                             $xml .= '<s2_customer_ip>' . esc_html($_SERVER["REMOTE_ADDR"]) . '</s2_customer_ip>';
                             $xml .= '<s2_item_number>' . esc_html($attr["level_ccaps_eotper"]) . '</s2_item_number>';
                             $xml .= '<s2_period1>' . esc_html($attr["tp"] . " " . $attr["tt"]) . '</s2_period1>';
                             $xml .= '<s2_period3>' . esc_html($attr["rp"] . " " . $attr["rt"]) . '</s2_period3>';
                             $xml .= $attr["rr"] ? '<s2_recurring>' . esc_html($attr["rr"]) . '</s2_recurring>' : '';
                             $xml .= $attr["referencing"] ? '<s2_referencing>' . esc_html($attr["referencing"]) . '</s2_referencing>' : '';
                             $xml .= '</merchant-private-item-data>';
                             /**/
                             $xml .= '<digital-content>';
                             $xml .= '<display-disposition>PESSIMISTIC</display-disposition>';
                             $xml .= '<description>' . esc_html(_x("You'll receive an email confirmation within 15 minutes.", "s2member-front", "s2member")) . '</description>';
                             $xml .= '</digital-content>';
                             /**/
                             $xml .= '</item>';
                             /**/
                             $xml .= '<item>';
                             /**/
                             $xml .= '<quantity>1</quantity>';
                             $xml .= '<item-name>' . esc_html($attr["desc"]) . '</item-name>';
                             $xml .= '<item-description>(SID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(sprintf(_x("Cancel at any time to avoid %s.", "s2member-front", "s2member"), !$attr["rr"] ? _x("this charge", "s2member-front", "s2member") : _x("charges", "s2member-front", "s2member"))) . '</item-description>';
                             $xml .= '<unit-price currency="' . esc_attr($attr["cc"]) . '">0.00</unit-price>';
                             /**/
                             $xml .= '<merchant-private-item-data>';
                             $xml .= '<s2_subscr_id>s2-' . esc_html($attr["uniqid"]) . '</s2_subscr_id>';
                             $xml .= '<s2_custom>' . esc_html($attr["custom"]) . '</s2_custom>';
                             $xml .= '<s2_customer_ip>' . esc_html($_SERVER["REMOTE_ADDR"]) . '</s2_customer_ip>';
                             $xml .= '<s2_item_number>' . esc_html($attr["level_ccaps_eotper"]) . '</s2_item_number>';
                             $xml .= '<s2_period1>' . esc_html($attr["tp"] . " " . $attr["tt"]) . '</s2_period1>';
                             $xml .= '<s2_period3>' . esc_html($attr["rp"] . " " . $attr["rt"]) . '</s2_period3>';
                             $xml .= $attr["rr"] ? '<s2_recurring>' . esc_html($attr["rr"]) . '</s2_recurring>' : '';
                             $xml .= $attr["referencing"] ? '<s2_referencing>' . esc_html($attr["referencing"]) . '</s2_referencing>' : '';
                             $xml .= '</merchant-private-item-data>';
                             /**/
                             $xml .= '<digital-content>';
                             $xml .= '<display-disposition>PESSIMISTIC</display-disposition>';
                             /**/
                             if ($attr["referencing"]) {
                                 $xml .= '<description>' . esc_html(sprintf(_x('You\'ve been updated to:<br />%s<br />( <a href="%s">please log back in now</a> )', "s2member-front", "s2member"), $attr["desc"], esc_attr(wp_login_url()))) . '</description>';
                                 $xml .= '<url>' . esc_html(wp_login_url()) . '</url>';
                             } else {
                                 $xml .= '<description>' . esc_html(sprintf(_x('%s<br />( the next step is to Register a Username )', "s2member-front", "s2member"), $attr["desc"])) . '</description>';
                                 $xml .= '<url>' . esc_html($attr["register_access_link"]) . '</url>';
                             }
                             /**/
                             $xml .= '</digital-content>';
                             /**/
                             $xml .= '<subscription type="google" period="' . esc_attr($attr["periodicity"]) . '" start-date="' . esc_attr(date("Y-m-d", $attr["start_time"]) . "T00:00:00Z") . '">';
                             /**/
                             $xml .= '<payments>';
                             $xml .= '<subscription-payment' . (!$attr["rr"] ? ' times="1"' : '') . '>';
                             $xml .= '<maximum-charge currency="' . esc_attr($attr["cc"]) . '">' . esc_html($attr["ra"]) . '</maximum-charge>';
                             $xml .= '</subscription-payment>';
                             $xml .= '</payments>';
                             /**/
                             $xml .= '<recurrent-item>';
                             /**/
                             $xml .= '<quantity>1</quantity>';
                             $xml .= '<item-name>' . esc_html($attr["desc"]) . '</item-name>';
                             $xml .= '<item-description>(SID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(_x("Covers ongoing access.", "s2member-front", "s2member")) . '</item-description>';
                             $xml .= '<unit-price currency="' . esc_attr($attr["cc"]) . '">' . esc_html($attr["ra"]) . '</unit-price>';
                             /**/
                             $xml .= '<merchant-private-item-data>';
                             $xml .= '<s2_subscr_payment>1</s2_subscr_payment>';
                             $xml .= '<s2_subscr_id>s2-' . esc_html($attr["uniqid"]) . '</s2_subscr_id>';
                             $xml .= '<s2_custom>' . esc_html($attr["custom"]) . '</s2_custom>';
                             $xml .= '<s2_customer_ip>' . esc_html($_SERVER["REMOTE_ADDR"]) . '</s2_customer_ip>';
                             $xml .= '<s2_item_number>' . esc_html($attr["level_ccaps_eotper"]) . '</s2_item_number>';
                             $xml .= '<s2_period1>' . esc_html($attr["tp"] . " " . $attr["tt"]) . '</s2_period1>';
                             $xml .= '<s2_period3>' . esc_html($attr["rp"] . " " . $attr["rt"]) . '</s2_period3>';
                             $xml .= $attr["rr"] ? '<s2_recurring>' . esc_html($attr["rr"]) . '</s2_recurring>' : '';
                             $xml .= $attr["referencing"] ? '<s2_referencing>' . esc_html($attr["referencing"]) . '</s2_referencing>' : '';
                             $xml .= '</merchant-private-item-data>';
                             /**/
                             $xml .= '<digital-content>';
                             $xml .= '<display-disposition>PESSIMISTIC</display-disposition>';
                             $xml .= '<description>' . esc_html($attr["desc"]) . '</description>';
                             $xml .= '<url>' . esc_html(home_url("/")) . '</url>';
                             $xml .= '</digital-content>';
                             /**/
                             $xml .= '</recurrent-item>';
                             /**/
                             $xml .= '</subscription>';
                             /**/
                             $xml .= '</item>';
                             /**/
                             $xml .= '</items>';
                             $xml .= '</shopping-cart>';
                             /**/
                             $xml .= '<checkout-flow-support>';
                             $xml .= '<merchant-checkout-flow-support>';
                             $xml .= '<edit-cart-url>' . esc_html(get_page_link($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])) . '</edit-cart-url>';
                             $xml .= '<continue-shopping-url>' . esc_html($attr["referencing"] ? wp_login_url() : $attr["register_access_link"]) . '</continue-shopping-url>';
                             $xml .= '</merchant-checkout-flow-support>';
                             $xml .= '</checkout-flow-support>';
                             /**/
                             $xml .= '</checkout-shopping-cart>';
                         } else {
                             if (!$attr["tp"] && $attr["rr"]) {
                                 $attr["start_time"] = c_ws_plugin__s2member_pro_google_utilities::google_start_time($attr["rp"] . " " . $attr["rt"]);
                                 /**/
                                 $xml = '<?xml version="1.0" encoding="UTF-8"?>';
                                 $xml .= '<checkout-shopping-cart xmlns="http://checkout.google.com/schema/2">';
                                 $xml .= '<shopping-cart>';
                                 $xml .= '<items>';
                                 /**/
                                 $xml .= '<item>';
                                 /**/
                                 $xml .= '<quantity>1</quantity>';
                                 $xml .= '<item-name>' . esc_html($attr["desc"]) . '</item-name>';
                                 $xml .= '<item-description>(SID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(_x("First payment for immediate access.", "s2member-front", "s2member")) . '</item-description>';
                                 $xml .= '<unit-price currency="' . esc_attr($attr["cc"]) . '">' . esc_html($attr["ra"]) . '</unit-price>';
                                 /**/
                                 $xml .= '<merchant-private-item-data>';
                                 $xml .= '<s2_subscr_id>s2-' . esc_html($attr["uniqid"]) . '</s2_subscr_id>';
                                 $xml .= '<s2_custom>' . esc_html($attr["custom"]) . '</s2_custom>';
                                 $xml .= '<s2_customer_ip>' . esc_html($_SERVER["REMOTE_ADDR"]) . '</s2_customer_ip>';
                                 $xml .= '<s2_item_number>' . esc_html($attr["level_ccaps_eotper"]) . '</s2_item_number>';
                                 $xml .= '<s2_period1>0 D</s2_period1>';
                                 /* There is no Trial Period. */
                                 $xml .= '<s2_period3>' . esc_html($attr["rp"] . " " . $attr["rt"]) . '</s2_period3>';
                                 $xml .= '<s2_recurring>' . esc_html($attr["rr"]) . '</s2_recurring>';
                                 $xml .= $attr["referencing"] ? '<s2_referencing>' . esc_html($attr["referencing"]) . '</s2_referencing>' : '';
                                 $xml .= '</merchant-private-item-data>';
                                 /**/
                                 $xml .= '<digital-content>';
                                 $xml .= '<display-disposition>PESSIMISTIC</display-disposition>';
                                 $xml .= '<description>' . esc_html(_x("You'll receive an email confirmation within 15 minutes.", "s2member-front", "s2member")) . '</description>';
                                 $xml .= '</digital-content>';
                                 /**/
                                 $xml .= '</item>';
                                 /**/
                                 $xml .= '<item>';
                                 /**/
                                 $xml .= '<quantity>1</quantity>';
                                 $xml .= '<item-name>' . esc_html($attr["desc"]) . '</item-name>';
                                 $xml .= '<item-description>(SID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(_x("Cancel at any time to avoid charges.", "s2member-front", "s2member")) . '</item-description>';
                                 $xml .= '<unit-price currency="' . esc_attr($attr["cc"]) . '">0.00</unit-price>';
                                 /**/
                                 $xml .= '<merchant-private-item-data>';
                                 $xml .= '<s2_subscr_id>s2-' . esc_html($attr["uniqid"]) . '</s2_subscr_id>';
                                 $xml .= '<s2_custom>' . esc_html($attr["custom"]) . '</s2_custom>';
                                 $xml .= '<s2_customer_ip>' . esc_html($_SERVER["REMOTE_ADDR"]) . '</s2_customer_ip>';
                                 $xml .= '<s2_item_number>' . esc_html($attr["level_ccaps_eotper"]) . '</s2_item_number>';
                                 $xml .= '<s2_period1>0 D</s2_period1>';
                                 /* There is no Trial Period. */
                                 $xml .= '<s2_period3>' . esc_html($attr["rp"] . " " . $attr["rt"]) . '</s2_period3>';
                                 $xml .= '<s2_recurring>' . esc_html($attr["rr"]) . '</s2_recurring>';
                                 $xml .= $attr["referencing"] ? '<s2_referencing>' . esc_html($attr["referencing"]) . '</s2_referencing>' : '';
                                 $xml .= '</merchant-private-item-data>';
                                 /**/
                                 $xml .= '<digital-content>';
                                 $xml .= '<display-disposition>PESSIMISTIC</display-disposition>';
                                 /**/
                                 if ($attr["referencing"]) {
                                     $xml .= '<description>' . esc_html(sprintf(_x('You\'ve been updated to:<br />%s<br />( <a href="%s">please log back in now</a> )', "s2member-front", "s2member"), $attr["desc"], esc_attr(wp_login_url()))) . '</description>';
                                     $xml .= '<url>' . esc_html(wp_login_url()) . '</url>';
                                 } else {
                                     $xml .= '<description>' . esc_html(sprintf(_x('%s<br />( the next step is to Register a Username )', "s2member-front", "s2member"), $attr["desc"])) . '</description>';
                                     $xml .= '<url>' . esc_html($attr["register_access_link"]) . '</url>';
                                 }
                                 /**/
                                 $xml .= '</digital-content>';
                                 /**/
                                 $xml .= '<subscription type="google" period="' . esc_attr($attr["periodicity"]) . '" start-date="' . esc_attr(date("Y-m-d", $attr["start_time"]) . "T00:00:00Z") . '">';
                                 /**/
                                 $xml .= '<payments>';
                                 $xml .= '<subscription-payment>';
                                 $xml .= '<maximum-charge currency="' . esc_attr($attr["cc"]) . '">' . esc_html($attr["ra"]) . '</maximum-charge>';
                                 $xml .= '</subscription-payment>';
                                 $xml .= '</payments>';
                                 /**/
                                 $xml .= '<recurrent-item>';
                                 /**/
                                 $xml .= '<quantity>1</quantity>';
                                 $xml .= '<item-name>' . esc_html($attr["desc"]) . '</item-name>';
                                 $xml .= '<item-description>(SID:s2-' . esc_html($attr["uniqid"]) . ') ' . esc_html(_x("Covers ongoing access.", "s2member-front", "s2member")) . '</item-description>';
                                 $xml .= '<unit-price currency="' . esc_attr($attr["cc"]) . '">' . esc_html($attr["ra"]) . '</unit-price>';
                                 /**/
                                 $xml .= '<merchant-private-item-data>';
                                 $xml .= '<s2_subscr_payment>1</s2_subscr_payment>';
                                 $xml .= '<s2_subscr_id>s2-' . esc_html($attr["uniqid"]) . '</s2_subscr_id>';
                                 $xml .= '<s2_custom>' . esc_html($attr["custom"]) . '</s2_custom>';
                                 $xml .= '<s2_customer_ip>' . esc_html($_SERVER["REMOTE_ADDR"]) . '</s2_customer_ip>';
                                 $xml .= '<s2_item_number>' . esc_html($attr["level_ccaps_eotper"]) . '</s2_item_number>';
                                 $xml .= '<s2_period1>0 D</s2_period1>';
                                 /* There is no Trial Period. */
                                 $xml .= '<s2_period3>' . esc_html($attr["rp"] . " " . $attr["rt"]) . '</s2_period3>';
                                 $xml .= '<s2_recurring>' . esc_html($attr["rr"]) . '</s2_recurring>';
                                 $xml .= $attr["referencing"] ? '<s2_referencing>' . esc_html($attr["referencing"]) . '</s2_referencing>' : '';
                                 $xml .= '</merchant-private-item-data>';
                                 /**/
                                 $xml .= '<digital-content>';
                                 $xml .= '<display-disposition>PESSIMISTIC</display-disposition>';
                                 $xml .= '<description>' . esc_html($attr["desc"]) . '</description>';
                                 $xml .= '<url>' . esc_html(home_url("/")) . '</url>';
                                 $xml .= '</digital-content>';
                                 /**/
                                 $xml .= '</recurrent-item>';
                                 /**/
                                 $xml .= '</subscription>';
                                 /**/
                                 $xml .= '</item>';
                                 /**/
                                 $xml .= '</items>';
                                 $xml .= '</shopping-cart>';
                                 /**/
                                 $xml .= '<checkout-flow-support>';
                                 $xml .= '<merchant-checkout-flow-support>';
                                 $xml .= '<edit-cart-url>' . esc_html(get_page_link($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])) . '</edit-cart-url>';
                                 $xml .= '<continue-shopping-url>' . esc_html($attr["referencing"] ? wp_login_url() : $attr["register_access_link"]) . '</continue-shopping-url>';
                                 $xml .= '</merchant-checkout-flow-support>';
                                 $xml .= '</checkout-flow-support>';
                                 /**/
                                 $xml .= '</checkout-shopping-cart>';
                             }
                         }
                         /**/
                         $endpoint = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_sandbox"] ? "sandbox.google.com/checkout" : "checkout.google.com";
                         /**/
                         if (($xml = c_ws_plugin__s2member_utils_urls::remote("https://" . $endpoint . "/api/checkout/v2/merchantCheckout/Merchant/" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"], $xml, array_merge(c_ws_plugin__s2member_pro_google_utilities::google_api_headers(), array("timeout" => 20)))) && preg_match("/\\<redirect-url\\>(.+?)\\<\\/redirect-url\\>/i", preg_replace("/[\r\n\t]+/", "", $xml), $m) && ($google = $m[1])) {
                             wp_redirect(wp_specialchars_decode($google, ENT_QUOTES));
                         } else {
                             /* Display error message. */
                             echo strip_tags($xml);
                         }
                     }
                 }
             }
         }
         /**/
         exit;
         /* Clean exit. */
     }
 }
 /**
  * Handles Google IPN URL processing.
  *
  * @package s2Member\Google
  * @since 1.5
  *
  * @attaches-to ``add_action("init");``
  *
  * @return null Or exits script execution after handling the Notification.
  */
 public static function google_notify()
 {
     global $current_site, $current_blog;
     if (!empty($_GET["s2member_pro_google_notify"]) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"]) {
         @ignore_user_abort(true);
         // Continue processing even if/when connection is broken by the sender.
         if (is_array($google = c_ws_plugin__s2member_pro_google_utilities::google_postvars()) && ($_google = $google)) {
             $google["s2member_log"][] = "IPN received on: " . date("D M j, Y g:i:s a T");
             $google["s2member_log"][] = "s2Member POST vars verified with Google.";
             if (!empty($google["typ"]) && preg_match('/^google\\/payments\\/inapp\\/item\\/v[0-9]+\\/postback\\/buy$/i', $google["typ"]) && is_array($s2vars = c_ws_plugin__s2member_pro_google_utilities::google_parse_s2vars($google)) && !empty($google["response"]["orderId"])) {
                 $google["s2member_log"][] = "Google transaction identified as ( `SALE/BUY-NOW` ).";
                 $google["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal processor as `txn_type` ( `web_accept` ).";
                 $google["s2member_log"][] = "Please check PayPal IPN logs for further processing details.";
                 $processing = $processed = true;
                 $ipn = array();
                 // Reset.
                 $ipn["txn_type"] = "web_accept";
                 $ipn["txn_id"] = $google["response"]["orderId"];
                 $ipn["custom"] = $s2vars["cs"];
                 $ipn["mc_gross"] = number_format($google["request"]["price"], 2, ".", "");
                 $ipn["mc_currency"] = strtoupper($google["request"]["currencyCode"]);
                 $ipn["tax"] = number_format((double) @$google["request"]["tax"], 2, ".", "");
                 $ipn["payer_email"] = $s2vars["em"];
                 $ipn["first_name"] = $s2vars["fn"];
                 $ipn["last_name"] = $s2vars["ln"];
                 $ipn["option_name1"] = $s2vars["rf"] ? "Referencing Customer ID" : "Originating Domain";
                 $ipn["option_selection1"] = $s2vars["rf"] ? $s2vars["rf"] : $_SERVER["HTTP_HOST"];
                 $ipn["option_name2"] = "Customer IP Address";
                 // IP Address.
                 $ipn["option_selection2"] = $s2vars["ip"];
                 $ipn["item_number"] = $s2vars["in"];
                 $ipn["item_name"] = $google["request"]["description"];
                 $ipn["s2member_paypal_proxy"] = "google";
                 $ipn["s2member_paypal_proxy_use"] = "standard-emails";
                 $ipn["s2member_paypal_proxy_verification"] = c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen();
                 c_ws_plugin__s2member_utils_urls::remote(home_url("/?s2member_paypal_notify=1"), $ipn, array("timeout" => 20));
             } else {
                 if (!empty($google["typ"]) && preg_match('/^google\\/payments\\/inapp\\/subscription\\/v[0-9]+\\/postback\\/buy$/i', $google["typ"]) && is_array($s2vars = c_ws_plugin__s2member_pro_google_utilities::google_parse_s2vars($google)) && !empty($google["response"]["orderId"])) {
                     $google["s2member_log"][] = "Google transaction identified as ( `SALE/SUBSCRIPTION` ).";
                     $google["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal processor as `txn_type` ( `subscr_signup` ).";
                     $google["s2member_log"][] = "Please check PayPal IPN logs for further processing details.";
                     $processing = $processed = true;
                     $ipn = array();
                     // Reset.
                     $ipn["txn_type"] = "subscr_signup";
                     $ipn["subscr_id"] = $google["response"]["orderId"];
                     $ipn["txn_id"] = $google["response"]["orderId"];
                     $ipn["recurring"] = $s2vars["rr"];
                     $ipn["custom"] = $s2vars["cs"];
                     $ipn["period1"] = $s2vars["p1"];
                     $ipn["period3"] = $s2vars["p3"];
                     $ipn["mc_amount1"] = $ipn["mc_gross"] = number_format($google["request"]["initialPayment"]["price"], 2, ".", "");
                     $ipn["mc_currency"] = strtoupper($google["request"]["initialPayment"]["currencyCode"]);
                     $ipn["tax"] = number_format((double) @$google["request"]["initialPayment"]["tax"], 2, ".", "");
                     $ipn["mc_amount3"] = number_format($google["request"]["recurrence"]["price"], 2, ".", "");
                     $ipn["payer_email"] = $s2vars["em"];
                     $ipn["first_name"] = $s2vars["fn"];
                     $ipn["last_name"] = $s2vars["ln"];
                     $ipn["option_name1"] = $s2vars["rf"] ? "Referencing Customer ID" : "Originating Domain";
                     $ipn["option_selection1"] = $s2vars["rf"] ? $s2vars["rf"] : $_SERVER["HTTP_HOST"];
                     $ipn["option_name2"] = "Customer IP Address";
                     // IP Address.
                     $ipn["option_selection2"] = $s2vars["ip"];
                     $ipn["item_number"] = $s2vars["in"];
                     $ipn["item_name"] = $google["request"]["description"];
                     $ipn["s2member_paypal_proxy"] = "google";
                     $ipn["s2member_paypal_proxy_use"] = "standard-emails";
                     $ipn["s2member_paypal_proxy_use"] .= $ipn["mc_gross"] > 0 ? ",subscr-signup-as-subscr-payment" : "";
                     $ipn["s2member_paypal_proxy_verification"] = c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen();
                     c_ws_plugin__s2member_utils_urls::remote(home_url("/?s2member_paypal_notify=1"), $ipn, array("timeout" => 20));
                 } else {
                     if (!empty($google["typ"]) && preg_match('/^google\\/payments\\/inapp\\/subscription\\/v[0-9]+\\/canceled$/i', $google["typ"]) && !empty($google["response"]["statusCode"]) && preg_match("/^SUBSCRIPTION_CANCELED\$/i", $google["response"]["statusCode"]) && !empty($google["response"]["orderId"]) && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(false, $google["response"]["orderId"]))) {
                         $google["s2member_log"][] = "Google transaction identified as ( `SUBSCRIPTION_CANCELED` ).";
                         $google["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal processor as `txn_type` ( `subscr_cancel` ).";
                         $google["s2member_log"][] = "Please check PayPal IPN logs for further processing details.";
                         $processing = $processed = true;
                         $ipn = array();
                         // Reset.
                         $ipn["txn_type"] = "subscr_cancel";
                         $ipn["subscr_id"] = $google["response"]["orderId"];
                         $ipn["custom"] = $ipn_signup_vars["custom"];
                         $ipn["period1"] = $ipn_signup_vars["period1"];
                         $ipn["period3"] = $ipn_signup_vars["period3"];
                         $ipn["payer_email"] = $ipn_signup_vars["payer_email"];
                         $ipn["first_name"] = $ipn_signup_vars["first_name"];
                         $ipn["last_name"] = $ipn_signup_vars["last_name"];
                         $ipn["option_name1"] = $ipn_signup_vars["option_name1"];
                         $ipn["option_selection1"] = $ipn_signup_vars["option_selection1"];
                         $ipn["option_name2"] = $ipn_signup_vars["option_name2"];
                         $ipn["option_selection2"] = $ipn_signup_vars["option_selection2"];
                         $ipn["item_number"] = $ipn_signup_vars["item_number"];
                         $ipn["item_name"] = $ipn_signup_vars["item_name"];
                         $ipn["s2member_paypal_proxy"] = "google";
                         $ipn["s2member_paypal_proxy_use"] = "standard-emails";
                         $ipn["s2member_paypal_proxy_verification"] = c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen();
                         c_ws_plugin__s2member_utils_urls::remote(home_url("/?s2member_paypal_notify=1"), $ipn, array("timeout" => 20));
                     } else {
                         if (!$processed) {
                             // If nothing was processed, here we add a message to the logs indicating the IPN was ignored.
                             $google["s2member_log"][] = "Ignoring this IPN request. The transaction does NOT require any action on the part of s2Member.";
                         }
                     }
                 }
             }
         } else {
             $google["s2member_log"][] = "Unable to verify POST vars. This is most likely related to an invalid Google configuration. Please check: s2Member → Google Options.";
             $google["s2member_log"][] = "If you're absolutely SURE that your Google configuration is valid, you may want to run some tests on your server, just to be sure \$_POST variables are populated, and that your server is able to connect to Google over an HTTPS connection.";
             $google["s2member_log"][] = "s2Member uses the WP_Http class for remote connections; which will try to use cURL first, and then fall back on the FOPEN method when cURL is not available. On a Windows server, you may have to disable your cURL extension. Instead, set allow_url_fopen = yes in your php.ini file. The cURL extension (usually) does NOT support SSL connections on a Windows server.";
             $google["s2member_log"][] = var_export($_REQUEST, true);
             // Recording _POST + _GET vars for analysis and debugging.
         }
         /*
         We need to log this final event before it occurs.
         */
         $google["s2member_log"][] = "Sending Google an acknowlegment w/ order ID.";
         /*
         If debugging/logging is enabled; we need to append $google to the log file.
         	Logging now supports Multisite Networking as well.
         */
         $logt = c_ws_plugin__s2member_utilities::time_details();
         $logv = c_ws_plugin__s2member_utilities::ver_details();
         $logm = c_ws_plugin__s2member_utilities::mem_details();
         $log4 = $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] . "\nUser-Agent: " . @$_SERVER["HTTP_USER_AGENT"];
         $log4 = is_multisite() && !is_main_site() ? ($_log4 = $current_blog->domain . $current_blog->path) . "\n" . $log4 : $log4;
         $log2 = is_multisite() && !is_main_site() ? "google-ipn-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "google-ipn.log";
         if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) {
             if (is_dir($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])) {
                 if (is_writable($logs_dir) && c_ws_plugin__s2member_utils_logs::archive_oversize_log_files()) {
                     file_put_contents($logs_dir . "/" . $log2, "LOG ENTRY: " . $logt . "\n" . $logv . "\n" . $logm . "\n" . $log4 . "\n" . c_ws_plugin__s2member_utils_logs::conceal_private_info(var_export($google, true)) . "\n\n", FILE_APPEND);
                 }
             }
         }
         status_header(200);
         // Send a 200 OK status header.
         header("Content-Type: text/plain");
         // Google expects text/plain here.
         while (@ob_end_clean()) {
         }
         // Clean any existing output buffers.
         exit(!empty($google["response"]["orderId"]) ? $google["response"]["orderId"] : "");
     }
 }
 /**
  * Get ``$_POST`` or ``$_REQUEST`` vars from Google®.
  *
  * @package s2Member\Google
  * @since 1.5
  *
  * @return array|bool An array of verified ``$_POST`` or ``$_REQUEST`` variables, else false.
  *
  * @todo Continue optimizing this routine with ``empty()`` and ``isset()``.
  * @todo Candidate for the use of ``ifsetor()``?
  */
 public static function google_postvars()
 {
     if (!empty($_REQUEST["s2member_pro_google_notify"]) && !empty($_REQUEST["serial-number"])) {
         $postback["_type"] = "notification-history-request";
         $postback["serial-number"] = trim(stripslashes((string) $_REQUEST["serial-number"]));
         /**/
         $endpoint = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_sandbox"] ? "sandbox.google.com/checkout" : "checkout.google.com";
         /**/
         if (($response = c_ws_plugin__s2member_utils_urls::remote("https://" . $endpoint . "/api/checkout/v2/reportsForm/Merchant/" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_google_merchant_id"], $postback, array_merge(c_ws_plugin__s2member_pro_google_utilities::google_api_headers(), array("timeout" => 20)))) && wp_parse_str($response, $postvars) !== "nill" && !empty($postvars["_type"])) {
             return c_ws_plugin__s2member_utils_strings::trim_deep($postvars);
         } else {
             /* Nope. Return false. */
             return false;
         }
     } else {
         /* Nope. */
         return false;
     }
 }