function s2member_pro_clickbank_order($user_id = 0) { if (!$user_id) { $user_id = get_current_user_id(); } if (!$user_id) { return array(); } // Not possible. $subscr_id = get_user_option('s2member_subscr_id', $user_id); $subscr_gateway = get_user_option('s2member_subscr_gateway', $user_id); $ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars($user_id); if (!$subscr_id || $subscr_gateway !== 'clickbank') { return array(); } // Not applicable. if (!$ipn_signup_vars || empty($ipn_signup_vars['txn_id'])) { return array(); } // Not possible. return c_ws_plugin__s2member_pro_clickbank_utilities::clickbank_api_order($ipn_signup_vars['txn_id']); }
/** * Connect to and process ARB service information for Authorize.Net®. * * s2Member's Auto EOT System must be enabled for this to work properly. * * If you have a HUGE userbase, increase the max IPNs per process. * But NOTE, this runs ``$per_process`` *( per Blog )* on a Multisite Network. * To increase, use: ``add_filter ("ws_plugin__s2member_pro_arb_service_ipns_per_process");``. * * @package s2Member\AuthNet * @since 1.5 * * @attaches-to ``add_action("ws_plugin__s2member_after_auto_eot_system");`` * * @param array $vars Expects an array of defined variables to be passed in by the Action Hook. * @return null */ public static function authnet_arb_service($vars = FALSE) { global $wpdb; /* Need global DB obj. */ global $current_site, $current_blog; /* For Multisite support. */ /**/ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_authnet_api_login_id"]) { $scan_time = apply_filters("ws_plugin__s2member_pro_arb_service_status_scan_time", strtotime("-1 day"), get_defined_vars()); $per_process = apply_filters("ws_plugin__s2member_pro_arb_service_ipns_per_process", $vars["per_process"], get_defined_vars()); /**/ if (is_array($objs = $wpdb->get_results("SELECT `user_id` AS `ID` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_subscr_gateway' AND `meta_value` = 'authnet' AND `user_id` NOT IN(SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_last_status_scan' AND `meta_value` > '" . esc_sql($scan_time) . "')"))) { foreach ($objs as $obj) { if (($user_id = $obj->ID) && ($counter = (int) $counter + 1)) { unset($authnet, $subscr_id, $ipn_sv, $processing, $processed, $ipn, $ipn_q, $log4, $_log4, $log2, $logs_dir); /* Unset these. */ /**/ if (($authnet = array("x_method" => "status")) && ($authnet["x_subscription_id"] = $subscr_id = get_user_option("s2member_subscr_id", $user_id))) { if (!get_user_option("s2member_auto_eot_time", $user_id) && is_array($ipn_sv = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(false, $subscr_id))) { if (($authnet = c_ws_plugin__s2member_pro_authnet_utilities::authnet_arb_response($authnet)) && empty($authnet["__error"]) && $authnet["subscription_status"] && is_array($authnet["arb_ipn_signup_vars"] = $ipn_sv)) { if (preg_match("/^expired\$/i", $authnet["subscription_status"])) { $authnet["s2member_log"][] = "Authorize.Net® ARB/IPN processed on: " . date("D M j, Y g:i:s a T"); /**/ $authnet["s2member_log"][] = "Authorize.Net® transaction identified as ( `SUBSCRIPTION EXPIRATION` )."; $authnet["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as `txn_type` ( `subscr_eot` )."; $authnet["s2member_log"][] = "Please check PayPal® IPN logs for further processing details."; /**/ $processing = $processed = true; $ipn = array(); /* Reset. */ /**/ $ipn["txn_type"] = "subscr_eot"; $ipn["subscr_id"] = $authnet["arb_ipn_signup_vars"]["subscr_id"]; /**/ $ipn["custom"] = $authnet["arb_ipn_signup_vars"]["custom"]; /**/ $ipn["period1"] = $authnet["arb_ipn_signup_vars"]["period1"]; $ipn["period3"] = $authnet["arb_ipn_signup_vars"]["period3"]; /**/ $ipn["payer_email"] = $authnet["arb_ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $authnet["arb_ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $authnet["arb_ipn_signup_vars"]["last_name"]; /**/ $ipn["option_name1"] = $authnet["arb_ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $authnet["arb_ipn_signup_vars"]["option_selection1"]; /**/ $ipn["option_name2"] = $authnet["arb_ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $authnet["arb_ipn_signup_vars"]["option_selection2"]; /**/ $ipn["item_number"] = $authnet["arb_ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $authnet["arb_ipn_signup_vars"]["item_name"]; /**/ $ipn_q = "&s2member_paypal_proxy=authnet&s2member_paypal_proxy_use=pro-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("/^(suspended|canceled|terminated)\$/i", $authnet["subscription_status"])) { $authnet["s2member_log"][] = "Authorize.Net® ARB/IPN processed on: " . date("D M j, Y g:i:s a T"); /**/ $authnet["s2member_log"][] = "Authorize.Net® transaction identified as ( `SUBSCRIPTION " . strtoupper($authnet["subscription_status"]) . "` )."; $authnet["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as `txn_type` ( `subscr_cancel` )."; $authnet["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"] = $authnet["arb_ipn_signup_vars"]["subscr_id"]; /**/ $ipn["custom"] = $authnet["arb_ipn_signup_vars"]["custom"]; /**/ $ipn["period1"] = $authnet["arb_ipn_signup_vars"]["period1"]; $ipn["period3"] = $authnet["arb_ipn_signup_vars"]["period3"]; /**/ $ipn["payer_email"] = $authnet["arb_ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $authnet["arb_ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $authnet["arb_ipn_signup_vars"]["last_name"]; /**/ $ipn["option_name1"] = $authnet["arb_ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $authnet["arb_ipn_signup_vars"]["option_selection1"]; /**/ $ipn["option_name2"] = $authnet["arb_ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $authnet["arb_ipn_signup_vars"]["option_selection2"]; /**/ $ipn["item_number"] = $authnet["arb_ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $authnet["arb_ipn_signup_vars"]["item_name"]; /**/ $ipn_q = "&s2member_paypal_proxy=authnet&s2member_paypal_proxy_use=pro-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 status; which is being ignored by s2Member. */ $authnet["s2member_log"][] = "Ignoring this ARB/Status ( `" . $authnet["subscription_status"] . "` ). It does NOT require any action on the part of s2Member."; } } } /**/ $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() ? "authnet-arb-ipn-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "authnet-arb-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($authnet, true) . "\n\n", FILE_APPEND); } } } } } } /**/ update_user_option($user_id, "s2member_last_status_scan", time()); /**/ if ($counter >= $per_process) { /* Only this many. */ break; } /* Break the loop now. */ } } } } /**/ return; /* Return for uniformity. */ }
/** * Handles processing of Pro Form cancellations. * * @package s2Member\AuthNet * @since 1.5 * * @attaches-to ``add_action("init");`` * * @return null Or exits script execution after a custom URL redirection. */ public static function authnet_cancellation() { if (!empty($_POST["s2member_pro_authnet_cancellation"]["nonce"]) && ($nonce = $_POST["s2member_pro_authnet_cancellation"]["nonce"]) && wp_verify_nonce($nonce, "s2member-pro-authnet-cancellation")) { $GLOBALS["ws_plugin__s2member_pro_authnet_cancellation_response"] = array(); /* This holds the global response details. */ $global_response =& $GLOBALS["ws_plugin__s2member_pro_authnet_cancellation_response"]; /* This is a shorter reference. */ /**/ $post_vars = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST["s2member_pro_authnet_cancellation"])); $post_vars["attr"] = unserialize(c_ws_plugin__s2member_utils_encryption::decrypt($post_vars["attr"])); /* And run a Filter. */ $post_vars["attr"] = apply_filters("ws_plugin__s2member_pro_authnet_cancellation_post_attr", $post_vars["attr"], get_defined_vars()); /**/ $post_vars["recaptcha_challenge_field"] = !$post_vars["recaptcha_challenge_field"] ? trim(stripslashes($_POST["recaptcha_challenge_field"])) : $post_vars["recaptcha_challenge_field"]; $post_vars["recaptcha_response_field"] = !$post_vars["recaptcha_response_field"] ? trim(stripslashes($_POST["recaptcha_response_field"])) : $post_vars["recaptcha_response_field"]; /**/ if (!c_ws_plugin__s2member_pro_authnet_responses::authnet_form_attr_validation_errors($post_vars["attr"])) { if (!($error = c_ws_plugin__s2member_pro_authnet_responses::authnet_form_submission_validation_errors("cancellation", $post_vars))) { if (is_user_logged_in() && is_object($user = wp_get_current_user()) && ($user_id = $user->ID)) { if (($authnet = array("x_method" => "status")) && ($authnet["x_subscription_id"] = $cur__subscr_id = get_user_option("s2member_subscr_id"))) { if (($authnet = c_ws_plugin__s2member_pro_authnet_utilities::authnet_arb_response($authnet)) && empty($authnet["__error"]) && $authnet["subscription_status"]) { if (preg_match("/^(active|suspended)\$/i", $authnet["subscription_status"])) { if (!($ipn = array())) { /* With Authorize.Net®, we need their IPN signup vars. */ if (is_array($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars())) { $ipn["txn_type"] = "subscr_cancel"; $ipn["subscr_id"] = $ipn_signup_vars["subscr_id"]; $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_name"] = $ipn_signup_vars["item_name"]; $ipn["item_number"] = $ipn_signup_vars["item_number"]; /**/ $ipn_q = "&s2member_paypal_proxy=authnet&s2member_paypal_proxy_use=pro-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)); } } /**/ if ($authnet = array("x_method" => "cancel", "x_subscription_id" => $cur__subscr_id)) { c_ws_plugin__s2member_pro_authnet_utilities::authnet_arb_response($authnet); /**/ $global_response = array("response" => _x('<strong>Billing termination confirmed.</strong> Your account has been cancelled.', "s2member-front", "s2member")); /**/ if ($post_vars["attr"]["success"] && ($custom_success_url = str_ireplace(array("%%s_response%%", "%%response%%"), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response["response"])), urlencode($global_response["response"])), $post_vars["attr"]["success"])) && ($custom_success_url = trim(preg_replace("/%%(.+?)%%/i", "", $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, "s2p-v")) . exit; } } } else { $global_response = array("response" => _x('<strong>Billing terminated.</strong> Your account has been cancelled.', "s2member-front", "s2member")); /**/ if ($post_vars["attr"]["success"] && ($custom_success_url = str_ireplace(array("%%s_response%%", "%%response%%"), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response["response"])), urlencode($global_response["response"])), $post_vars["attr"]["success"])) && ($custom_success_url = trim(preg_replace("/%%(.+?)%%/i", "", $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, "s2p-v")) . exit; } } } else { $global_response = array("response" => _x('<strong>Billing terminated.</strong> Your account has been cancelled.', "s2member-front", "s2member")); /**/ if ($post_vars["attr"]["success"] && ($custom_success_url = str_ireplace(array("%%s_response%%", "%%response%%"), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response["response"])), urlencode($global_response["response"])), $post_vars["attr"]["success"])) && ($custom_success_url = trim(preg_replace("/%%(.+?)%%/i", "", $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, "s2p-v")) . exit; } } } else { $global_response = array("response" => _x('<strong>Billing terminated.</strong> Your account has been cancelled.', "s2member-front", "s2member")); /**/ if ($post_vars["attr"]["success"] && ($custom_success_url = str_ireplace(array("%%s_response%%", "%%response%%"), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response["response"])), urlencode($global_response["response"])), $post_vars["attr"]["success"])) && ($custom_success_url = trim(preg_replace("/%%(.+?)%%/i", "", $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, "s2p-v")) . exit; } } } else { $global_response = array("response" => _x('You\'re <strong>NOT</strong> logged in.', "s2member-front", "s2member"), "error" => true); } } else { $global_response = $error; } } } }
/** * Retrieves IPN Signup Var & validates their Subscription ID. * * The ``$user_id`` can be passed in directly; or a lookup can be performed with ``$subscr_id``. * * @package s2Member\Utilities * @since 110912 * * @param str $var Required. The requested Signup Var. * @param int|str $user_id Optional. A numeric WordPress User ID. * @param str $subscr_id Optional. Can be used instead of passing in a ``$user_id``. * If ``$subscr_id`` is passed in, it has to match the one found inside the resulting IPN Signup Vars collected by this routine. * If neither of these parameters are passed in, the current User is assumed instead, obtained through ``wp_get_current_user()``. * @return mixed|bool A User's IPN Signup Var on success, else false on failure. */ public static function get_user_ipn_signup_var($var = FALSE, $user_id = FALSE, $subscr_id = FALSE) { if (!empty($var) && is_array($user_ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars($user_id, $subscr_id))) { if (isset($user_ipn_signup_vars[$var])) { return $user_ipn_signup_vars[$var]; } } return false; }
/** * Connect to and process DataLink information for ccBill. * * s2Member's Auto EOT System must be enabled for this to work properly. * * If you have a HUGE userbase, increase the max IPNs per process. * But NOTE, this runs ``$per_process`` *(per Blog)* on a Multisite Network. * To increase, use: ``add_filter ("ws_plugin__s2member_pro_ccbill_datalink_ipns_per_process");``. * * @package s2Member\ccBill * @since 1.5 * * @attaches-to ``add_action("ws_plugin__s2member_after_auto_eot_system");`` * * @param array $vars Expects an array of defined variables passed in by the Action Hook. * @return null */ public static function ccbill_datalink($vars = FALSE) { global $wpdb; global $current_site, $current_blog; if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_client_id"]) { $mst_time_10m_ago = time() - 6 * 3600 - 600; $datalink = "https://datalink.ccbill.com/data/main.cgi"; if (!($last = get_transient("s2m_" . md5("s2member_pro_ccbill_last_datalink"))) || $last < $mst_time_10m_ago - 86400) { $start = $last && $last >= $mst_time_10m_ago - (86400 + 43200) ? $last : $mst_time_10m_ago - 86400; $end = $last = $start + 86400 <= $mst_time_10m_ago ? $start + 86400 : $mst_time_10m_ago; $dl_types = "REBILL" . ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_dl_cancellations"] || apply_filters("ws_plugin__s2member_pro_ccbill_datalink_pulls_cancellations", false) ? ",CANCELLATION" : "") . ",EXPIRE,REFUND,CHARGEBACK"; $qvrs = array("startTime" => date("YmdHis", $start), "endTime" => date("YmdHis", $end), "transactionTypes" => $dl_types, "clientAccnum" => $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_client_id"], "clientSubacc" => $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_client_sid"], "username" => $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_dl_user"], "password" => $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_dl_pass"]); if (($unprocessed_ipn_lines = trim(c_ws_plugin__s2member_utils_urls::remote($datalink = add_query_arg(urlencode_deep($qvrs), $datalink)))) && !preg_match("/^Error\\:/i", $unprocessed_ipn_lines)) { $ccbill["s2member_log"][] = "Storing last DataLink time: " . date("D M j, Y g:i:s a T", $last); set_transient("s2m_" . md5("s2member_pro_ccbill_last_datalink"), $last, 31556926); $ccbill["s2member_log"][] = "Storing new DataLink IPNs into a Transient Queue."; $ccbill["s2member_log"][] = $datalink; $ccbill["s2member_log"][] = $unprocessed_ipn_lines; set_transient("s2m_" . md5("s2member_pro_ccbill_datalink_ipns"), trim(trim(get_transient("s2m_" . md5("s2member_pro_ccbill_datalink_ipns"))) . "\n" . $unprocessed_ipn_lines), 31556926); } else { if (!preg_match("/^Error\\:/i", $unprocessed_ipn_lines)) { $ccbill["s2member_log"][] = "Storing last DataLink time: " . date("D M j, Y g:i:s a T", $last); set_transient("s2m_" . md5("s2member_pro_ccbill_last_datalink"), $last, 31556926); $ccbill["s2member_log"][] = "No new Datalink IPNs at this time: " . date("D M j, Y g:i:s a T"); $ccbill["s2member_log"][] = $datalink; $ccbill["s2member_log"][] = $unprocessed_ipn_lines; } else { $ccbill["s2member_log"][] = "Storing last DataLink time: " . date("D M j, Y g:i:s a T", $last); set_transient("s2m_" . md5("s2member_pro_ccbill_last_datalink"), $last, 31556926); $ccbill["s2member_log"][] = "Recording DataLink error at: " . date("D M j, Y g:i:s a T"); $ccbill["s2member_log"][] = "Recording server IP address: " . $_SERVER["SERVER_ADDR"]; $ccbill["s2member_log"][] = $datalink; $ccbill["s2member_log"][] = $unprocessed_ipn_lines; } } $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() ? "ccbill-dl-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "ccbill-dl.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($ccbill, true)) . "\n\n", FILE_APPEND); } } } } else { if ($unprocessed_ipn_lines = trim(get_transient("s2m_" . md5("s2member_pro_ccbill_datalink_ipns")))) { $per_process = apply_filters("ws_plugin__s2member_pro_ccbill_datalink_ipns_per_process", $vars["per_process"], get_defined_vars()); foreach ($unprocessed_lines = preg_split("/[\r\n]+/", $unprocessed_ipn_lines) as $line => $unprocessed_line) { unset($ccbill, $processing, $processed, $ipn, $log4, $_log4, $log2, $logs_dir); if (($unprocessed_line = trim($unprocessed_line)) && ($counter = (int) $counter + 1)) { $ccbill["s2member_log"][] = "DataLink IPN processed on: " . date("D M j, Y g:i:s a T"); $ccbill["dl_ipn"] = c_ws_plugin__s2member_utils_strings::trim_dq_deep(preg_split("/\",\"/", $unprocessed_line)); if (is_array($ccbill["dl_ipn_signup_vars"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(false, $ccbill["dl_ipn"][3]))) { if (preg_match("/^REBILL\$/i", $ccbill["dl_ipn"][0])) { $ccbill["s2member_log"][] = "ccBill transaction identified as (SUBSCRIPTION PAYMENT)."; $ccbill["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal processor as txn_type (subscr_payment)."; $ccbill["s2member_log"][] = "Please check PayPal IPN logs for further processing details."; $processing = $processed = true; $ipn = array(); $ipn["txn_type"] = "subscr_payment"; $ipn["subscr_id"] = $ccbill["dl_ipn_signup_vars"]["subscr_id"]; $ipn["custom"] = $ccbill["dl_ipn_signup_vars"]["custom"]; $ipn["txn_id"] = $ccbill["dl_ipn"][5]; $ipn["mc_gross"] = number_format($ccbill["dl_ipn"][6], 2, ".", ""); $ipn["mc_currency"] = strtoupper("USD"); $ipn["tax"] = number_format("0.00", 2, ".", ""); $ipn["payer_email"] = $ccbill["dl_ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $ccbill["dl_ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $ccbill["dl_ipn_signup_vars"]["last_name"]; $ipn["option_name1"] = $ccbill["dl_ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $ccbill["dl_ipn_signup_vars"]["option_selection1"]; $ipn["option_name2"] = $ccbill["dl_ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $ccbill["dl_ipn_signup_vars"]["option_selection2"]; $ipn["item_number"] = $ccbill["dl_ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $ccbill["dl_ipn_signup_vars"]["item_name"]; $ipn["s2member_paypal_proxy"] = "ccbill"; $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(site_url("/?s2member_paypal_notify=1"), $ipn, array("timeout" => 20)); } else { if (preg_match("/^CANCELLATION\$/i", $ccbill["dl_ipn"][0])) { $ccbill["s2member_log"][] = "ccBill transaction identified as (SUBSCRIPTION CANCELLATION)."; $ccbill["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal processor as txn_type (subscr_cancel)."; $ccbill["s2member_log"][] = "Please check PayPal IPN logs for further processing details."; $processing = $processed = true; $ipn = array(); $ipn["txn_type"] = "subscr_cancel"; $ipn["subscr_id"] = $ccbill["dl_ipn_signup_vars"]["subscr_id"]; $ipn["custom"] = $ccbill["dl_ipn_signup_vars"]["custom"]; $ipn["period1"] = $ccbill["dl_ipn_signup_vars"]["period1"]; $ipn["period3"] = $ccbill["dl_ipn_signup_vars"]["period3"]; $ipn["payer_email"] = $ccbill["dl_ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $ccbill["dl_ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $ccbill["dl_ipn_signup_vars"]["last_name"]; $ipn["option_name1"] = $ccbill["dl_ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $ccbill["dl_ipn_signup_vars"]["option_selection1"]; $ipn["option_name2"] = $ccbill["dl_ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $ccbill["dl_ipn_signup_vars"]["option_selection2"]; $ipn["item_number"] = $ccbill["dl_ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $ccbill["dl_ipn_signup_vars"]["item_name"]; $ipn["s2member_paypal_proxy"] = "ccbill"; $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(site_url("/?s2member_paypal_notify=1"), $ipn, array("timeout" => 20)); } else { if (preg_match("/^EXPIRE\$/i", $ccbill["dl_ipn"][0])) { $ccbill["s2member_log"][] = "ccBill transaction identified as (SUBSCRIPTION EXPIRATION)."; $ccbill["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal processor as txn_type (subscr_eot)."; $ccbill["s2member_log"][] = "Please check PayPal IPN logs for further processing details."; $processing = $processed = true; $ipn = array(); $ipn["txn_type"] = "subscr_eot"; $ipn["subscr_id"] = $ccbill["dl_ipn_signup_vars"]["subscr_id"]; $ipn["custom"] = $ccbill["dl_ipn_signup_vars"]["custom"]; $ipn["period1"] = $ccbill["dl_ipn_signup_vars"]["period1"]; $ipn["period3"] = $ccbill["dl_ipn_signup_vars"]["period3"]; $ipn["payer_email"] = $ccbill["dl_ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $ccbill["dl_ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $ccbill["dl_ipn_signup_vars"]["last_name"]; $ipn["option_name1"] = $ccbill["dl_ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $ccbill["dl_ipn_signup_vars"]["option_selection1"]; $ipn["option_name2"] = $ccbill["dl_ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $ccbill["dl_ipn_signup_vars"]["option_selection2"]; $ipn["item_number"] = $ccbill["dl_ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $ccbill["dl_ipn_signup_vars"]["item_name"]; $ipn["s2member_paypal_proxy"] = "ccbill"; $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(site_url("/?s2member_paypal_notify=1"), $ipn, array("timeout" => 20)); } else { if (preg_match("/^(REFUND|CHARGEBACK)\$/i", $ccbill["dl_ipn"][0])) { $ccbill["s2member_log"][] = "ccBill transaction identified as (REFUND|CHARGEBACK)."; $ccbill["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal processor as payment_status (refunded|reversed)."; $ccbill["s2member_log"][] = "Please check PayPal IPN logs for further processing details."; $processing = $processed = true; $ipn = array(); $ipn["custom"] = $ccbill["dl_ipn_signup_vars"]["custom"]; $ipn["parent_txn_id"] = $ccbill["dl_ipn_signup_vars"]["subscr_id"]; $ipn["payment_status"] = preg_match("/^CHARGEBACK\$/i", $ccbill["dl_ipn"][0]) ? "reversed" : "refunded"; $ipn["mc_fee"] = "-" . number_format("0.00", 2, ".", ""); $ipn["mc_gross"] = "-" . number_format($ccbill["dl_ipn"][5], 2, ".", ""); $ipn["mc_currency"] = strtoupper("USD"); $ipn["tax"] = "-" . number_format("0.00", 2, ".", ""); $ipn["payer_email"] = $ccbill["dl_ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $ccbill["dl_ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $ccbill["dl_ipn_signup_vars"]["last_name"]; $ipn["option_name1"] = $ccbill["dl_ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $ccbill["dl_ipn_signup_vars"]["option_selection1"]; $ipn["option_name2"] = $ccbill["dl_ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $ccbill["dl_ipn_signup_vars"]["option_selection2"]; $ipn["item_number"] = $ccbill["dl_ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $ccbill["dl_ipn_signup_vars"]["item_name"]; $ipn["s2member_paypal_proxy"] = "ccbill"; $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(site_url("/?s2member_paypal_notify=1"), $ipn, array("timeout" => 20)); } else { if (!$processed) { // Here we add a message to the logs indicating the IPN was ignored; no action taken. $ccbill["s2member_log"][] = "Ignoring this DataLink IPN. It does NOT require any action on the part of s2Member."; } } } } } } else { if (!$processed) { // Here we add a message to the logs indicating that no IPN vars are available. $ccbill["s2member_log"][] = "Ignoring this DataLink IPN. No IPN signup vars for Subscr. ID: " . $ccbill["dl_ipn"][3] . "."; } } $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() ? "ccbill-dl-ipn-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "ccbill-dl-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($ccbill, true)) . "\n\n", FILE_APPEND); } } } } unset($unprocessed_lines[$line]); // Remove this line and update the list of unprocessed IPN lines. set_transient("s2m_" . md5("s2member_pro_ccbill_datalink_ipns"), implode("\n", $unprocessed_lines), 31556926); if ($counter >= $per_process) { break; } // Break the loop now. } } } } return; }
/** * Retrieves IPN Signup Var & validates their Subscription ID. * * The ``$user_id`` can be passed in directly; or a lookup can be performed with ``$subscr_id``. * * @package s2Member\Utilities * @since 110912 * * @param string $var Required. The requested Signup Var. * @param int|string $user_id Optional. A numeric WordPress User ID. * @param string $subscr_txn_baid_cid_id Optional. Can be used instead of passing in a ``$user_id``. * If ``$subscr_id`` is passed in, it has to match the one found inside the resulting IPN Signup Vars collected by this routine. * If neither of these parameters are passed in, the current User is assumed instead, obtained through ``wp_get_current_user()``. * * @return mixed|bool A User's IPN Signup Var on success, else false on failure. */ public static function get_user_ipn_signup_var($var = '', $user_id = 0, $subscr_txn_baid_cid_id = '') { if (!empty($var) && is_array($user_ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars($user_id, $subscr_txn_baid_cid_id))) { if (isset($user_ipn_signup_vars[$var])) { return $user_ipn_signup_vars[$var]; } } return FALSE; // Otherwise, return false. }
/** * 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"] : ""); } }
/** * Connect to and process cancellations/refunds/chargebacks/etc via Payflow. * * s2Member's Auto EOT System must be enabled for this to work properly. * * If you have a HUGE userbase, increase the max IPNs per process. * But NOTE, this runs ``$per_process`` *(per Blog)* on a Multisite Network. * To increase, use: ``add_filter ("ws_plugin__s2member_pro_payflow_ipns_per_process");``. * * @package s2Member\PayPal * @since 120514 * * @attaches-to ``add_action("ws_plugin__s2member_after_auto_eot_system");`` * * @param array $vars Expects an array of defined variables to be passed in by the Action Hook. * @return null */ public static function payflow_service($vars = FALSE) { global $wpdb; // Need global DB obj. global $current_site, $current_blog; if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_payflow_api_username"]) { $scan_time = apply_filters("ws_plugin__s2member_pro_payflow_status_scan_time", strtotime("-1 day"), get_defined_vars()); $per_process = apply_filters("ws_plugin__s2member_pro_payflow_ipns_per_process", $vars["per_process"], get_defined_vars()); if (is_array($objs = $wpdb->get_results("SELECT `user_id` AS `ID` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_subscr_gateway' AND `meta_value` = 'paypal' AND `user_id` NOT IN(SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_last_status_scan' AND `meta_value` > '" . esc_sql($scan_time) . "')"))) { foreach ($objs as $obj) { if (($user_id = $obj->ID) && ($counter = (int) $counter + 1)) { unset($paypal, $subscr_id, $ipn_sv, $processing, $processed, $ipn, $log4, $_log4, $log2, $logs_dir); if (($subscr_id = get_user_option("s2member_subscr_id", $user_id)) && !get_user_option("s2member_auto_eot_time", $user_id)) { if (is_array($ipn_sv = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(false, $subscr_id)) && ($paypal = c_ws_plugin__s2member_pro_paypal_utilities::payflow_get_profile($subscr_id)) && is_array($paypal["ipn_signup_vars"] = $ipn_sv)) { if (preg_match("/expired/i", $paypal["STATUS"])) { $paypal["s2member_log"][] = "Payflow IPN via polling, processed on: " . date("D M j, Y g:i:s a T"); $paypal["s2member_log"][] = "Payflow transaction identified as ( `SUBSCRIPTION EXPIRATION` )."; $paypal["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal processor as `txn_type` ( `subscr_eot` )."; $paypal["s2member_log"][] = "Please check PayPal IPN logs for further processing details."; $processing = $processed = true; $ipn = array(); // Reset. $ipn["txn_type"] = "subscr_eot"; $ipn["subscr_id"] = $paypal["ipn_signup_vars"]["subscr_id"]; $ipn["custom"] = $paypal["ipn_signup_vars"]["custom"]; $ipn["period1"] = $paypal["ipn_signup_vars"]["period1"]; $ipn["period3"] = $paypal["ipn_signup_vars"]["period3"]; $ipn["payer_email"] = $paypal["ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $paypal["ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $paypal["ipn_signup_vars"]["last_name"]; $ipn["option_name1"] = $paypal["ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $paypal["ipn_signup_vars"]["option_selection1"]; $ipn["option_name2"] = $paypal["ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $paypal["ipn_signup_vars"]["option_selection2"]; $ipn["item_number"] = $paypal["ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $paypal["ipn_signup_vars"]["item_name"]; $ipn["s2member_paypal_proxy"] = "paypal"; $ipn["s2member_paypal_proxy_use"] = "pro-emails"; $ipn["s2member_paypal_proxy_verification"] = c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen(); c_ws_plugin__s2member_utils_urls::remote(site_url("/?s2member_paypal_notify=1"), $ipn, array("timeout" => 20)); } else { if (preg_match("/(suspended|canceled|terminated|deactivated)/i", $paypal["STATUS"])) { $paypal["s2member_log"][] = "Payflow IPN via polling, processed on: " . date("D M j, Y g:i:s a T"); $paypal["s2member_log"][] = "Payflow transaction identified as ( `SUBSCRIPTION " . strtoupper($paypal["STATUS"]) . "` )."; $paypal["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal processor as `txn_type` ( `subscr_cancel` )."; $paypal["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"] = $paypal["ipn_signup_vars"]["subscr_id"]; $ipn["custom"] = $paypal["ipn_signup_vars"]["custom"]; $ipn["period1"] = $paypal["ipn_signup_vars"]["period1"]; $ipn["period3"] = $paypal["ipn_signup_vars"]["period3"]; $ipn["payer_email"] = $paypal["ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $paypal["ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $paypal["ipn_signup_vars"]["last_name"]; $ipn["option_name1"] = $paypal["ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $paypal["ipn_signup_vars"]["option_selection1"]; $ipn["option_name2"] = $paypal["ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $paypal["ipn_signup_vars"]["option_selection2"]; $ipn["item_number"] = $paypal["ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $paypal["ipn_signup_vars"]["item_name"]; $ipn["s2member_paypal_proxy"] = "paypal"; $ipn["s2member_paypal_proxy_use"] = "pro-emails"; $ipn["s2member_paypal_proxy_verification"] = c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen(); c_ws_plugin__s2member_utils_urls::remote(site_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 status; which is being ignored. $paypal["s2member_log"][] = "Ignoring this status ( `" . $paypal["STATUS"] . "` ). It does NOT require any action on the part of s2Member."; } } } $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() ? "paypal-payflow-ipn-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "paypal-payflow-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($paypal, true)) . "\n\n", FILE_APPEND); } } } } } update_user_option($user_id, "s2member_last_status_scan", time()); if ($counter >= $per_process) { // Only this many. break; } // Break the loop now. } } } } return; }
/** * Handles processing of Pro-Form cancellations. * * @package s2Member\Stripe * @since 140617 * * @attaches-to ``add_action('init');`` */ public static function stripe_cancellation() { if (!empty($_POST['s2member_pro_stripe_cancellation']['nonce']) && ($nonce = $_POST['s2member_pro_stripe_cancellation']['nonce']) && wp_verify_nonce($nonce, 's2member-pro-stripe-cancellation')) { $GLOBALS['ws_plugin__s2member_pro_stripe_cancellation_response'] = array(); // This holds the global response details. $global_response =& $GLOBALS['ws_plugin__s2member_pro_stripe_cancellation_response']; $post_vars = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST['s2member_pro_stripe_cancellation'])); $post_vars['attr'] = !empty($post_vars['attr']) ? (array) unserialize(c_ws_plugin__s2member_utils_encryption::decrypt($post_vars['attr'])) : array(); $post_vars['attr'] = apply_filters('ws_plugin__s2member_pro_stripe_cancellation_post_attr', $post_vars['attr'], get_defined_vars()); $post_vars['recaptcha_challenge_field'] = isset($_POST['recaptcha_challenge_field']) ? trim(stripslashes($_POST['recaptcha_challenge_field'])) : ''; $post_vars['recaptcha_response_field'] = isset($_POST['recaptcha_response_field']) ? trim(stripslashes($_POST['recaptcha_response_field'])) : ''; if (!c_ws_plugin__s2member_pro_stripe_responses::stripe_form_attr_validation_errors($post_vars['attr'])) { if (!($form_submission_validation_errors = c_ws_plugin__s2member_pro_stripe_responses::stripe_form_submission_validation_errors('cancellation', $post_vars))) { if (is_user_logged_in() && is_object($user = wp_get_current_user()) && ($user_id = $user->ID)) { if (($cur__subscr_cid = get_user_option('s2member_subscr_cid')) && ($cur__subscr_id = get_user_option('s2member_subscr_id'))) { if (is_object($stripe_subscription = c_ws_plugin__s2member_pro_stripe_utilities::get_customer_subscription($cur__subscr_cid, $cur__subscr_id))) { if (!preg_match('/^canceled$/i', $stripe_subscription->status) && !$stripe_subscription->cancel_at_period_end) { if (is_object(c_ws_plugin__s2member_pro_stripe_utilities::cancel_customer_subscription($cur__subscr_cid, $cur__subscr_id))) { if (is_array($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars())) { $ipn['txn_type'] = 'subscr_cancel'; $ipn['subscr_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'stripe'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); } $global_response = array('response' => _x('<strong>Billing termination confirmed.</strong> Your account has been cancelled.', 's2member-front', 's2member')); if ($post_vars['attr']['success'] && ($custom_success_url = str_ireplace(array('%%s_response%%', '%%response%%'), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response['response'])), urlencode($global_response['response'])), $post_vars['attr']['success'])) && ($custom_success_url = trim(preg_replace('/%%(.+?)%%/i', '', $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, 's2p-v')) . exit; } } else { $global_response = array('response' => _x('API failure. Please contact Support for assistance.', 's2member-front', 's2member'), 'error' => TRUE); } } else { $global_response = array('response' => _x('<strong>Billing terminated.</strong> Your account has been cancelled.', 's2member-front', 's2member')); if ($post_vars['attr']['success'] && ($custom_success_url = str_ireplace(array('%%s_response%%', '%%response%%'), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response['response'])), urlencode($global_response['response'])), $post_vars['attr']['success'])) && ($custom_success_url = trim(preg_replace('/%%(.+?)%%/i', '', $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, 's2p-v')) . exit; } } } else { $global_response = array('response' => _x('<strong>Billing terminated.</strong> Your account has been cancelled.', 's2member-front', 's2member')); if ($post_vars['attr']['success'] && ($custom_success_url = str_ireplace(array('%%s_response%%', '%%response%%'), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response['response'])), urlencode($global_response['response'])), $post_vars['attr']['success'])) && ($custom_success_url = trim(preg_replace('/%%(.+?)%%/i', '', $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, 's2p-v')) . exit; } } } else { $global_response = array('response' => _x('<strong>Billing terminated.</strong> Your account has been cancelled.', 's2member-front', 's2member')); if ($post_vars['attr']['success'] && ($custom_success_url = str_ireplace(array('%%s_response%%', '%%response%%'), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response['response'])), urlencode($global_response['response'])), $post_vars['attr']['success'])) && ($custom_success_url = trim(preg_replace('/%%(.+?)%%/i', '', $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, 's2p-v')) . exit; } } if ($post_vars['attr']['unsub']) { c_ws_plugin__s2member_list_servers::process_list_server_removals_against_current_user(TRUE); } } else { $global_response = array('response' => _x('You\'re <strong>NOT</strong> logged in.', 's2member-front', 's2member'), 'error' => TRUE); } } else { // Input form field validation errors. $global_response = $form_submission_validation_errors; } } } }
/** * Retrieves IPN Signup Var & validates their Subscription ID. * * The ``$user_id`` can be passed in directly; or a lookup can be performed with ``$subscr_id``. * * @package s2Member\Utilities * @since 110912 * * @param str $var Required. The requested Signup Var. * @param int|str $user_id Optional. A numeric WordPress® User ID. * @param str $subscr_id Optional. Can be used instead of passing in a ``$user_id``. * If ``$subscr_id`` is passed in, it has to match the one found inside the resulting IPN Signup Vars collected by this routine. * If neither of these parameters are passed in, the current User is assumed instead, obtained through ``wp_get_current_user()``. * @return mixed|bool A User's IPN Signup Var on success, else false on failure. */ public static function get_user_ipn_signup_var($var = FALSE, $user_id = FALSE, $subscr_id = FALSE) { if (!empty($var) && is_array($user_ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars($user_id, $subscr_id))) { if (isset($user_ipn_signup_vars[$var])) { /* Available? */ return $user_ipn_signup_vars[$var]; } } /**/ return false; /* Otherwise, return false. */ }
/** * Handles processing of Pro-Form cancellations. * * @package s2Member\AuthNet * @since 1.5 * * @attaches-to ``add_action('init');`` * * @return null Or exits script execution after a custom URL redirection. */ public static function authnet_cancellation() { if (!empty($_POST['s2member_pro_authnet_cancellation']['nonce']) && ($nonce = $_POST['s2member_pro_authnet_cancellation']['nonce']) && wp_verify_nonce($nonce, 's2member-pro-authnet-cancellation')) { $GLOBALS['ws_plugin__s2member_pro_authnet_cancellation_response'] = array(); // This holds the global response details. $global_response =& $GLOBALS['ws_plugin__s2member_pro_authnet_cancellation_response']; $post_vars = c_ws_plugin__s2member_utils_strings::trim_deep(stripslashes_deep($_POST['s2member_pro_authnet_cancellation'])); $post_vars['attr'] = !empty($post_vars['attr']) ? (array) unserialize(c_ws_plugin__s2member_utils_encryption::decrypt($post_vars['attr'])) : array(); $post_vars['attr'] = apply_filters('ws_plugin__s2member_pro_authnet_cancellation_post_attr', $post_vars['attr'], get_defined_vars()); $post_vars = c_ws_plugin__s2member_utils_captchas::recaptcha_post_vars($post_vars); // Collect reCAPTCHA™ post vars. if (!c_ws_plugin__s2member_pro_authnet_responses::authnet_form_attr_validation_errors($post_vars['attr'])) { if (!($error = c_ws_plugin__s2member_pro_authnet_responses::authnet_form_submission_validation_errors('cancellation', $post_vars))) { if (is_user_logged_in() && is_object($user = wp_get_current_user()) && ($user_id = $user->ID)) { if (($authnet = array('x_method' => 'status')) && ($authnet['x_subscription_id'] = $cur__subscr_id = get_user_option('s2member_subscr_id'))) { if (($authnet = c_ws_plugin__s2member_pro_authnet_utilities::authnet_arb_response($authnet)) && empty($authnet['__error']) && $authnet['subscription_status']) { if (preg_match('/^(active|suspended)$/i', $authnet['subscription_status'])) { if (is_array($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars())) { $ipn['txn_type'] = 'subscr_cancel'; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'authnet'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); } if ($authnet = array('x_method' => 'cancel', 'x_subscription_id' => $cur__subscr_id)) { c_ws_plugin__s2member_pro_authnet_utilities::authnet_arb_response($authnet); $global_response = array('response' => _x('<strong>Billing termination confirmed.</strong> Your account has been cancelled.', 's2member-front', 's2member')); if ($post_vars['attr']['success'] && ($custom_success_url = str_ireplace(array('%%s_response%%', '%%response%%'), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response['response'])), urlencode($global_response['response'])), $post_vars['attr']['success'])) && ($custom_success_url = trim(preg_replace('/%%(.+?)%%/i', '', $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, 's2p-v')) . exit; } } } else { $global_response = array('response' => _x('<strong>Billing terminated.</strong> Your account has been cancelled.', 's2member-front', 's2member')); if ($post_vars['attr']['success'] && ($custom_success_url = str_ireplace(array('%%s_response%%', '%%response%%'), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response['response'])), urlencode($global_response['response'])), $post_vars['attr']['success'])) && ($custom_success_url = trim(preg_replace('/%%(.+?)%%/i', '', $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, 's2p-v')) . exit; } } } else { $global_response = array('response' => _x('<strong>Billing terminated.</strong> Your account has been cancelled.', 's2member-front', 's2member')); if ($post_vars['attr']['success'] && ($custom_success_url = str_ireplace(array('%%s_response%%', '%%response%%'), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response['response'])), urlencode($global_response['response'])), $post_vars['attr']['success'])) && ($custom_success_url = trim(preg_replace('/%%(.+?)%%/i', '', $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, 's2p-v')) . exit; } } } else { $global_response = array('response' => _x('<strong>Billing terminated.</strong> Your account has been cancelled.', 's2member-front', 's2member')); if ($post_vars['attr']['success'] && ($custom_success_url = str_ireplace(array('%%s_response%%', '%%response%%'), array(urlencode(c_ws_plugin__s2member_utils_encryption::encrypt($global_response['response'])), urlencode($global_response['response'])), $post_vars['attr']['success'])) && ($custom_success_url = trim(preg_replace('/%%(.+?)%%/i', '', $custom_success_url)))) { wp_redirect(c_ws_plugin__s2member_utils_urls::add_s2member_sig($custom_success_url, 's2p-v')) . exit; } } if ($post_vars['attr']['unsub']) { c_ws_plugin__s2member_list_servers::process_list_server_removals_against_current_user(TRUE); } } else { $global_response = array('response' => _x('You\'re <strong>NOT</strong> logged in.', 's2member-front', 's2member'), 'error' => TRUE); } } else { $global_response = $error; } } } }
/** * Connect to and process cancellations/refunds/chargebacks/etc via Payflow. * * s2Member's Auto EOT System must be enabled for this to work properly. * * If you have a HUGE userbase, increase the max IPNs per process. * But NOTE, this runs ``$per_process`` *(per Blog)* on a Multisite Network. * To increase, use: ``add_filter ('ws_plugin__s2member_pro_payflow_ipns_per_process');``. * * @package s2Member\PayPal * @since 120514 * * @attaches-to ``add_action('ws_plugin__s2member_after_auto_eot_system');`` * * @param array $vars Expects an array of defined variables to be passed in by the Action Hook. */ public static function payflow_service($vars) { global $wpdb; /** @var $wpdb \wpdb */ global $current_site, $current_blog; $counter = 0; // Initialize counter at zero. if ($GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_payflow_api_username']) { $scan_time = apply_filters('ws_plugin__s2member_pro_payflow_status_scan_time', strtotime('-1 day'), get_defined_vars()); $per_process = apply_filters('ws_plugin__s2member_pro_payflow_ipns_per_process', $vars['per_process'], get_defined_vars()); if (is_array($objs = $wpdb->get_results("SELECT `user_id` AS `ID` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_subscr_gateway' AND `meta_value` = 'paypal' AND `user_id` NOT IN(SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_last_status_scan' AND `meta_value` > '" . esc_sql($scan_time) . "')"))) { foreach ($objs as $obj) { if (($user_id = $obj->ID) && ($counter = (int) $counter + 1)) { $processed = FALSE; // Initialize and/or reset all of these variables. unset($paypal, $subscr_id, $processing, $ipn, $log4, $_log4, $log2, $logs_dir); if (($subscr_id = get_user_option('s2member_subscr_id', $user_id)) && !get_user_option('s2member_auto_eot_time', $user_id)) { if ($paypal = c_ws_plugin__s2member_pro_paypal_utilities::payflow_get_profile($subscr_id)) { $paypal['ipn_signup_vars'] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(FALSE, $subscr_id); if ($paypal['ipn_signup_vars'] && preg_match('/expired|too many failures/i', $paypal['STATUS'])) { $paypal['s2member_log'][] = 'Payflow IPN via polling, processed on: ' . date('D M j, Y g:i:s a T'); $paypal['s2member_log'][] = 'Payflow transaction identified as ( `SUBSCRIPTION EXPIRATION` ).'; $paypal['s2member_log'][] = 'IPN reformulated. Piping through s2Member\'s core/standard PayPal processor as `txn_type` ( `subscr_eot` ).'; $paypal['s2member_log'][] = 'Please check PayPal IPN logs for further processing details.'; $processing = $processed = TRUE; $ipn = array(); // Reset. $ipn['txn_type'] = 'subscr_eot'; $ipn['subscr_id'] = $paypal['ipn_signup_vars']['subscr_id']; $ipn['custom'] = $paypal['ipn_signup_vars']['custom']; $ipn['period1'] = $paypal['ipn_signup_vars']['period1']; $ipn['period3'] = $paypal['ipn_signup_vars']['period3']; $ipn['payer_email'] = $paypal['ipn_signup_vars']['payer_email']; $ipn['first_name'] = $paypal['ipn_signup_vars']['first_name']; $ipn['last_name'] = $paypal['ipn_signup_vars']['last_name']; $ipn['option_name1'] = $paypal['ipn_signup_vars']['option_name1']; $ipn['option_selection1'] = $paypal['ipn_signup_vars']['option_selection1']; $ipn['option_name2'] = $paypal['ipn_signup_vars']['option_name2']; $ipn['option_selection2'] = $paypal['ipn_signup_vars']['option_selection2']; $ipn['item_number'] = $paypal['ipn_signup_vars']['item_number']; $ipn['item_name'] = $paypal['ipn_signup_vars']['item_name']; $ipn['s2member_paypal_proxy'] = 'paypal'; $ipn['s2member_paypal_proxy_use'] = 'pro-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 ($paypal['ipn_signup_vars'] && preg_match('/(suspended|canceled|terminated|deactivated)/i', $paypal['STATUS'])) { $paypal['s2member_log'][] = 'Payflow IPN via polling, processed on: ' . date('D M j, Y g:i:s a T'); $paypal['s2member_log'][] = 'Payflow transaction identified as ( `SUBSCRIPTION ' . strtoupper($paypal['STATUS']) . '` ).'; $paypal['s2member_log'][] = 'IPN reformulated. Piping through s2Member\'s core/standard PayPal processor as `txn_type` ( `subscr_cancel` ).'; $paypal['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'] = $paypal['ipn_signup_vars']['subscr_id']; $ipn['custom'] = $paypal['ipn_signup_vars']['custom']; $ipn['period1'] = $paypal['ipn_signup_vars']['period1']; $ipn['period3'] = $paypal['ipn_signup_vars']['period3']; $ipn['payer_email'] = $paypal['ipn_signup_vars']['payer_email']; $ipn['first_name'] = $paypal['ipn_signup_vars']['first_name']; $ipn['last_name'] = $paypal['ipn_signup_vars']['last_name']; $ipn['option_name1'] = $paypal['ipn_signup_vars']['option_name1']; $ipn['option_selection1'] = $paypal['ipn_signup_vars']['option_selection1']; $ipn['option_name2'] = $paypal['ipn_signup_vars']['option_name2']; $ipn['option_selection2'] = $paypal['ipn_signup_vars']['option_selection2']; $ipn['item_number'] = $paypal['ipn_signup_vars']['item_number']; $ipn['item_name'] = $paypal['ipn_signup_vars']['item_name']; $ipn['s2member_paypal_proxy'] = 'paypal'; $ipn['s2member_paypal_proxy_use'] = 'pro-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 && !$paypal['ipn_signup_vars']) { $paypal['s2member_log'][] = 'Ignoring status (`' . $paypal['STATUS'] . '`).' . ' The user has no IPN Signup Vars recorded on-site by s2Member.'; } else { if (!$processed) { $paypal['s2member_log'][] = 'Ignoring status (`' . $paypal['STATUS'] . '`).' . ' It does NOT require any action on the part of s2Member.'; } } } } $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'] . "\n" . 'User-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() ? 'paypal-payflow-ipn-4-' . trim(preg_replace('/[^a-z0-9]/i', '-', !empty($_log4) ? $_log4 : ''), '-') . '.log' : 'paypal-payflow-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($paypal, TRUE)) . "\n\n", FILE_APPEND); } } } } } update_user_option($user_id, 's2member_last_status_scan', time()); if ($counter >= $per_process) { // Only this many. break; } // Break the loop now. } } } } }
/** * Handles Stripe Webhook/IPN event processing. * * @package s2Member\Stripe * @since 140617 * * @attaches-to ``add_action('init');`` */ public static function stripe_notify() { global $current_site, $current_blog; if (!empty($_GET['s2member_pro_stripe_notify']) && $GLOBALS['WS_PLUGIN__']['s2member']['o']['pro_stripe_api_secret_key']) { $stripe = array(); // Initialize array of Webhook/IPN event data and s2Member log details. @ignore_user_abort(TRUE); // Continue processing even if/when connection is broken. require_once dirname(__FILE__) . '/stripe-sdk/lib/Stripe.php'; Stripe::setApiKey($GLOBALS['WS_PLUGIN__']['s2member']['o']['pro_stripe_api_secret_key']); if (is_object($event = c_ws_plugin__s2member_pro_stripe_utilities::get_event()) && ($stripe['event'] = $event)) { switch ($event->type) { case 'invoice.payment_succeeded': // Subscription payments. if (!empty($event->data->object) && ($stripe_invoice = $event->data->object) instanceof Stripe_Invoice && !empty($stripe_invoice->customer) && !empty($stripe_invoice->subscription) && ($stripe_invoice_total = number_format(c_ws_plugin__s2member_pro_stripe_utilities::cents_to_dollar_amount($stripe_invoice->total, $stripe_invoice->currency), 2, '.', '')) > 0 && is_object($stripe_subscription = c_ws_plugin__s2member_pro_stripe_utilities::get_customer_subscription($stripe_invoice->customer, $stripe_invoice->subscription)) && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_subscription->id))) { $processing = TRUE; $ipn['txn_type'] = 'subscr_payment'; $ipn['txn_id'] = $stripe_invoice->id; $ipn['txn_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $ipn['custom'] = $ipn_signup_vars['custom']; $ipn['mc_gross'] = $stripe_invoice_total; $ipn['mc_currency'] = strtoupper($stripe_invoice->currency); $ipn['tax'] = number_format(0, 2, '.', ''); $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'stripe'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); if ($maybe_end_subscription = self::_maybe_end_subscription_after_payment($stripe_invoice->customer, $stripe_subscription)) { $stripe['s2member_log'][] = $maybe_end_subscription; } $stripe['s2member_log'][] = 'Webhook/IPN event `' . $event->type . '` reformulated. Piping through s2Member\'s core gateway processor as `txn_type` (`' . $ipn['txn_type'] . '`).'; $stripe['s2member_log'][] = 'Please check core IPN logs for further processing details.'; } break; // Break switch handler. // Break switch handler. case 'invoice.payment_failed': // Subscription payment failures. if (!empty($event->data->object) && ($stripe_invoice = $event->data->object) instanceof Stripe_Invoice && !empty($stripe_invoice->customer) && !empty($stripe_invoice->subscription) && ($stripe_invoice_total = number_format(c_ws_plugin__s2member_pro_stripe_utilities::cents_to_dollar_amount($stripe_invoice->total, $stripe_invoice->currency), 2, '.', '')) > 0 && is_object($stripe_subscription = c_ws_plugin__s2member_pro_stripe_utilities::get_customer_subscription($stripe_invoice->customer, $stripe_invoice->subscription)) && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_subscription->id))) { $processing = TRUE; $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); if ($maybe_end_subscription = self::_maybe_end_subscription_after_payment($stripe_invoice->customer, $stripe_subscription)) { $stripe['s2member_log'][] = $maybe_end_subscription; } $stripe['s2member_log'][] = 'Ignoring `' . $event->type . '`. s2Member does NOT respond to individual payment failures; only to subscription cancellations.'; $stripe['s2member_log'][] = 'You may control the behavior(s) associated w/ subscription payment failures from your Stripe Dashboard please.'; } break; // Break switch handler. // Break switch handler. case 'customer.deleted': // Customer deletions. if (!empty($event->data->object) && ($stripe_customer = $event->data->object) instanceof Stripe_Customer && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_customer->id))) { $processing = TRUE; $ipn['txn_type'] = 'subscr_eot'; $ipn['subscr_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'stripe'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); $stripe['s2member_log'][] = 'Webhook/IPN event `' . $event->type . '` reformulated. Piping through s2Member\'s core gateway processor as `txn_type` (`' . $ipn['txn_type'] . '`).'; $stripe['s2member_log'][] = 'Please check core IPN logs for further processing details.'; } break; // Break switch handler. // Break switch handler. case 'customer.subscription.deleted': // Customer subscription deletion. if (!empty($event->data->object) && ($stripe_subscription = $event->data->object) instanceof Stripe_Subscription && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_subscription->id))) { $processing = TRUE; $ipn['txn_type'] = 'subscr_eot'; $ipn['subscr_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'stripe'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); $stripe['s2member_log'][] = 'Webhook/IPN event `' . $event->type . '` reformulated. Piping through s2Member\'s core gateway processor as `txn_type` (`' . $ipn['txn_type'] . '`).'; $stripe['s2member_log'][] = 'Please check core IPN logs for further processing details.'; } break; // Break switch handler. } if (empty($processing)) { $stripe['s2member_log'][] = 'Ignoring this Webhook/IPN. The event does NOT require any action on the part of s2Member.'; } } else { $stripe['s2member_log'][] = 'Unable to verify Webhook/IPN event ID. This is most likely related to an invalid Stripe configuration. Please check: s2Member → Stripe Options.'; $stripe['s2member_log'][] = 'If you\'re absolutely SURE that your Stripe configuration is valid, you may want to run some tests on your server, just to be sure \\$_POST variables (and php://input) are populated; and that your server is able to connect to Stripe over an HTTPS connection.'; $stripe['s2member_log'][] = 's2Member uses the Stripe SDK for remote connections; which relies upon the cURL extension for PHP. Please make sure that your installation of PHP has the cURL extension; and that it\'s configured together with OpenSSL for HTTPS communication.'; $stripe['s2member_log'][] = var_export($_REQUEST, TRUE) . "\n" . var_export(json_decode(@file_get_contents('php://input')), TRUE); } $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'] . "\n" . 'User-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() ? 'stripe-ipn-4-' . trim(preg_replace('/[^a-z0-9]/i', '-', !empty($_log4) ? $_log4 : ''), '-') . '.log' : 'stripe-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($stripe, TRUE)) . "\n\n", FILE_APPEND); } } } status_header(200); // Send a 200 OK status header. header('Content-Type: text/plain; charset=UTF-8'); // Content-Type text/plain with UTF-8. while (@ob_end_clean()) { } // Clean any existing output buffers. exit; // Exit now. } }
protected static function fill_replacement_codes($user, $eot, &$recipients, &$subject, &$message) { $ipn_signup_vars = (array) c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars($user->ID); foreach (array('payer_email', 'first_name', 'last_name', 'subscr_id', 'subscr_cid', 'subscr_baid', 'subscr_gateway', 'currency', 'currency_symbol', 'initial', 'initial_term', 'regular', 'regular_term', 'recurring', 'item_name', 'item_number') as $_key) { if (isset($ipn_signup_vars[$_key])) { $_value = (string) $ipn_signup_vars[$_key]; $recipients = str_ireplace('%%' . $_key . '%%', $_value, $recipients); $subject = str_ireplace('%%' . $_key . '%%', $_value, $subject); $message = str_ireplace('%%' . $_key . '%%', $_value, $message); } } unset($_key, $_value); // Housekeeping. if (!empty($ipn_signup_vars['initial_term'])) { $initial_cycle = c_ws_plugin__s2member_utils_time::period_term($ipn_signup_vars['initial_term']); $recipients = str_ireplace('%%initial_cycle%%', $initial_cycle, $recipients); $subject = str_ireplace('%%initial_cycle%%', $initial_cycle, $subject); $message = str_ireplace('%%initial_cycle%%', $initial_cycle, $message); } if (!empty($ipn_signup_vars['regular_term'])) { if (!empty($ipn_signup_vars['recurring'])) { $regular_cycle = c_ws_plugin__s2member_utils_time::period_term($ipn_signup_vars['regular_term'], true); $recurring_regular_cycle = $ipn_signup_vars['recurring'] . ' / ' . c_ws_plugin__s2member_utils_time::period_term($ipn_signup_vars['regular_term'], true); } else { $regular_cycle = c_ws_plugin__s2member_utils_time::period_term($ipn_signup_vars['regular_term'], false); $recurring_regular_cycle = __('0 / non-recurring', 's2member-front', 's2member'); } $recipients = str_ireplace('%%regular_cycle%%', $regular_cycle, $recipients); $subject = str_ireplace('%%regular_cycle%%', $regular_cycle, $subject); $message = str_ireplace('%%regular_cycle%%', $regular_cycle, $message); $recipients = str_ireplace('%%recurring/regular_cycle%%', $recurring_regular_cycle, $recipients); $subject = str_ireplace('%%recurring/regular_cycle%%', $recurring_regular_cycle, $subject); $message = str_ireplace('%%recurring/regular_cycle%%', $recurring_regular_cycle, $message); } if (isset($ipn_signup_vars['first_name'], $ipn_signup_vars['last_name'])) { $full_name = trim($ipn_signup_vars['first_name'] . ' ' . $ipn_signup_vars['last_name']); $recipients = str_ireplace('%%full_name%%', $full_name, $recipients); $subject = str_ireplace('%%full_name%%', $full_name, $subject); $message = str_ireplace('%%full_name%%', $full_name, $message); } foreach (array('subscr_id', 'subscr_cid', 'subscr_baid', 'subscr_gateway') as $_key) { $_value = (string) get_user_option('s2member_' . $_key, $user->ID); $recipients = str_ireplace('%%' . $_key . '%%', $_value, $recipients); $subject = str_ireplace('%%' . $_key . '%%', $_value, $subject); $message = str_ireplace('%%' . $_key . '%%', $_value, $message); } unset($_key, $_value); // Housekeeping. foreach (array('ID', 'first_name', 'last_name', 'user_email', 'user_login') as $_property) { $_property_value = (string) $user->{$_property}; $_lc_property_wo_user_prefix = preg_replace('/^user_/i', '', strtolower($_property)); $recipients = str_ireplace('%%user_' . $_lc_property_wo_user_prefix . '%%', $_property_value, $recipients); $subject = str_ireplace('%%user_' . $_lc_property_wo_user_prefix . '%%', $_property_value, $subject); $message = str_ireplace('%%user_' . $_lc_property_wo_user_prefix . '%%', $_property_value, $message); } unset($_property, $_property_value, $_lc_property_wo_user_prefix); // Housekeeping. $first_name = $user->first_name; // If not yet filled above. $recipients = str_ireplace('%%first_name%%', $first_name, $recipients); $subject = str_ireplace('%%first_name%%', $first_name, $subject); $message = str_ireplace('%%first_name%%', $first_name, $message); $last_name = $user->last_name; // If not yet filled above. $recipients = str_ireplace('%%last_name%%', $last_name, $recipients); $subject = str_ireplace('%%last_name%%', $last_name, $subject); $message = str_ireplace('%%last_name%%', $last_name, $message); $full_name = trim($first_name . ' ' . $last_name); // Same here. $recipients = str_ireplace('%%full_name%%', $full_name, $recipients); $subject = str_ireplace('%%full_name%%', $full_name, $subject); $message = str_ireplace('%%full_name%%', $full_name, $message); $user_full_name = trim($user->first_name . ' ' . $user->last_name); $recipients = str_ireplace('%%user_full_name%%', $user_full_name, $recipients); $subject = str_ireplace('%%user_full_name%%', $user_full_name, $subject); $message = str_ireplace('%%user_full_name%%', $user_full_name, $message); $user_ip = get_user_option('s2member_registration_ip', $user->ID); $recipients = str_ireplace('%%user_ip%%', $user_ip, $recipients); $subject = str_ireplace('%%user_ip%%', $user_ip, $subject); $message = str_ireplace('%%user_ip%%', $user_ip, $message); $user_role = c_ws_plugin__s2member_user_access::user_access_role($user); $recipients = str_ireplace('%%user_role%%', $user_role, $recipients); $subject = str_ireplace('%%user_role%%', $user_role, $subject); $message = str_ireplace('%%user_role%%', $user_role, $message); $user_level = c_ws_plugin__s2member_user_access::user_access_level($user); $recipients = str_ireplace('%%user_level%%', $user_level, $recipients); $subject = str_ireplace('%%user_level%%', $user_level, $subject); $message = str_ireplace('%%user_level%%', $user_level, $message); $user_level_label = c_ws_plugin__s2member_user_access::user_access_label($user); $recipients = str_ireplace('%%user_level_label%%', $user_level_label, $recipients); $subject = str_ireplace('%%user_level_label%%', $user_level_label, $subject); $message = str_ireplace('%%user_level_label%%', $user_level_label, $message); $user_ccaps = implode(',', c_ws_plugin__s2member_user_access::user_access_ccaps($user)); $recipients = str_ireplace('%%user_ccaps%%', $user_ccaps, $recipients); $subject = str_ireplace('%%user_ccaps%%', $user_ccaps, $subject); $message = str_ireplace('%%user_ccaps%%', $user_ccaps, $message); if (is_array($fields = get_user_option('s2member_custom_fields', $user->ID))) { foreach ($fields as $_key => $_value) { $_serialized_value = maybe_serialize($_value); $recipients = str_ireplace('%%' . $_key . '%%', $_serialized_value, $recipients); $subject = str_ireplace('%%' . $_key . '%%', $_serialized_value, $subject); $message = str_ireplace('%%' . $_key . '%%', $_serialized_value, $message); } unset($_key, $_value, $_serialized_value); // Housekeeping. } foreach (preg_split('/\\|/', get_user_option('s2member_custom', $user->ID)) as $_key => $_value) { $recipients = str_ireplace('%%cv' . $_key . '%%', $_value, $recipients); $subject = str_ireplace('%%cv' . $_key . '%%', $_value, $subject); $message = str_ireplace('%%cv' . $_key . '%%', $_value, $message); } unset($_key, $_value); // Housekeeping. $eot_offset = get_option('gmt_offset') * HOUR_IN_SECONDS; $eot_local_time = $eot['time'] + $eot_offset; // `date_i18n()` $eot_date = date_i18n(get_option('date_format'), $eot_local_time); $recipients = str_ireplace('%%eot_date%%', $eot_date, $recipients); $subject = str_ireplace('%%eot_date%%', $eot_date, $subject); $message = str_ireplace('%%eot_date%%', $eot_date, $message); $eot_time = date_i18n(get_option('time_format'), $eot_local_time); $recipients = str_ireplace('%%eot_time%%', $eot_time, $recipients); $subject = str_ireplace('%%eot_time%%', $eot_time, $subject); $message = str_ireplace('%%eot_time%%', $eot_time, $message); $eot_tz = date_i18n('T', $eot_local_time); $recipients = str_ireplace('%%eot_tz%%', $eot_tz, $recipients); $subject = str_ireplace('%%eot_tz%%', $eot_tz, $subject); $message = str_ireplace('%%eot_tz%%', $eot_tz, $message); $eot_date_time_tz = $eot_date . ' ' . $eot_time . ' ' . $eot_tz; $recipients = str_ireplace('%%eot_date_time_tz%%', $eot_date_time_tz, $recipients); $subject = str_ireplace('%%eot_date_time_tz%%', $eot_date_time_tz, $subject); $message = str_ireplace('%%eot_date_time_tz%%', $eot_date_time_tz, $message); $eot_descriptive_time = c_ws_plugin__s2member_utils_time::approx_time_difference(self::$now, $eot['time'], 'floor'); $recipients = str_ireplace('%%eot_descriptive_time%%', $eot_descriptive_time, $recipients); $subject = str_ireplace('%%eot_descriptive_time%%', $eot_descriptive_time, $subject); $message = str_ireplace('%%eot_descriptive_time%%', $eot_descriptive_time, $message); // This allows developers to build a list of custom replacement codes if they'd like; using a WP filter. foreach (apply_filters('ws_plugin__s2member_pro_eot_reminder_email_custom_rcs', array(), get_defined_vars()) as $_custom_rc_key => $_custom_rc_value) { if (!is_string($_custom_rc_key) || !is_scalar($_custom_rc_value)) { continue; // Requires string key and scalar value. } $recipients = str_ireplace('%%' . $_custom_rc_key . '%%', (string) $_custom_rc_value, $recipients); $subject = str_ireplace('%%' . $_custom_rc_key . '%%', (string) $_custom_rc_value, $subject); $message = str_ireplace('%%' . $_custom_rc_key . '%%', (string) $_custom_rc_value, $message); } unset($_custom_rc_key, $_custom_rc_value); // Housekeeping. $recipients = trim(preg_replace('/%%(.+?)%%/i', '', $recipients)); // Remove remaining. $subject = trim(preg_replace('/%%(.+?)%%/i', '', $subject)); // Remove any remaining. $message = trim(preg_replace('/%%(.+?)%%/i', '', $message)); // Remove any remaining. if (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) { // $evl_vars = get_defined_vars(); // Defined vars; minus primaries. unset($evl_vars['recipients'], $evl_vars['subject'], $evl_vars['message']); $recipients = c_ws_plugin__s2member_utilities::evl($recipients, $evl_vars); $subject = c_ws_plugin__s2member_utilities::evl($subject, $evl_vars); $message = c_ws_plugin__s2member_utilities::evl($message, $evl_vars); } }
/** * Connect to and process DataLink information for ccBill®. * * s2Member's Auto EOT System must be enabled for this to work properly. * * If you have a HUGE userbase, increase the max IPNs per process. * But NOTE, this runs ``$per_process`` *( per Blog )* on a Multisite Network. * To increase, use: ``add_filter ("ws_plugin__s2member_pro_ccbill_datalink_ipns_per_process");``. * * @package s2Member\ccBill * @since 1.5 * * @attaches-to ``add_action("ws_plugin__s2member_after_auto_eot_system");`` * * @param array $vars Expects an array of defined variables passed in by the Action Hook. * @return null */ public static function ccbill_datalink($vars = FALSE) { global $wpdb; /* Need global DB obj. */ global $current_site, $current_blog; /* For Multisite support. */ /**/ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_client_id"]) { $datalink = "https://datalink.ccbill.com/data/main.cgi"; /* DataLink service. */ /**/ if (!($last = get_transient("s2m_" . md5("s2member_pro_ccbill_last_datalink"))) || $last < time() - 86400) { $start = $last && $last >= time() - (86400 + 43200) ? $last : time() - 86400; /* Don't let $start time be less than 1 day + 12 hours ago. */ $end = $last = $start + 86400; /* Sets $end time to exactly 1 day later. This also sets $last time; which is recorded later in this routine. */ /**/ $qvrs = array("startTime" => date("YmdHis", $start), "endTime" => date("YmdHis", $end), "transactionTypes" => "EXPIRE,REBILL,REFUND,CHARGEBACK", "clientAccnum" => $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_client_id"], "clientSubacc" => $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_client_sid"], "username" => $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_dl_user"], "password" => $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["pro_ccbill_dl_pass"]); /**/ if (($unprocessed_ipn_lines = trim(c_ws_plugin__s2member_utils_urls::remote($datalink = add_query_arg(urlencode_deep($qvrs), $datalink)))) && !preg_match("/^Error\\:/i", $unprocessed_ipn_lines)) { $ccbill["s2member_log"][] = "Storing last DataLink time: " . date("D M j, Y g:i:s a T", $last); /**/ set_transient("s2m_" . md5("s2member_pro_ccbill_last_datalink"), $last, 31556926); /**/ $ccbill["s2member_log"][] = "Storing new DataLink IPNs into a Transient Queue."; $ccbill["s2member_log"][] = $datalink; /* Record the full DataLink URL as well. */ $ccbill["s2member_log"][] = $unprocessed_ipn_lines; /* Record list in log. */ /**/ set_transient("s2m_" . md5("s2member_pro_ccbill_datalink_ipns"), trim(trim(get_transient("s2m_" . md5("s2member_pro_ccbill_datalink_ipns"))) . "\n" . $unprocessed_ipn_lines), 31556926); } else { if (!preg_match("/^Error\\:/i", $unprocessed_ipn_lines)) { $ccbill["s2member_log"][] = "Storing last DataLink time: " . date("D M j, Y g:i:s a T", $last); /**/ set_transient("s2m_" . md5("s2member_pro_ccbill_last_datalink"), $last, 31556926); /**/ $ccbill["s2member_log"][] = "No new Datalink IPNs at this time: " . date("D M j, Y g:i:s a T"); $ccbill["s2member_log"][] = $datalink; /* Record the full DataLink URL as well. */ $ccbill["s2member_log"][] = $unprocessed_ipn_lines; /* Log this; just in case. */ } else { $ccbill["s2member_log"][] = "Storing last DataLink time: " . date("D M j, Y g:i:s a T", $last); /**/ set_transient("s2m_" . md5("s2member_pro_ccbill_last_datalink"), $last, 31556926); /**/ $ccbill["s2member_log"][] = "Recording DataLink error at: " . date("D M j, Y g:i:s a T"); $ccbill["s2member_log"][] = "Recording server IP address: " . $_SERVER["SERVER_ADDR"]; $ccbill["s2member_log"][] = $datalink; /* Record the full DataLink URL as well. */ $ccbill["s2member_log"][] = $unprocessed_ipn_lines; /* Log error mesg. */ } } /**/ $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() ? "ccbill-dl-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "ccbill-dl.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($ccbill, true) . "\n\n", FILE_APPEND); } } } } else { if ($unprocessed_ipn_lines = trim(get_transient("s2m_" . md5("s2member_pro_ccbill_datalink_ipns")))) { $per_process = apply_filters("ws_plugin__s2member_pro_ccbill_datalink_ipns_per_process", $vars["per_process"], get_defined_vars()); /**/ foreach ($unprocessed_lines = preg_split("/[\r\n]+/", $unprocessed_ipn_lines) as $line => $unprocessed_line) { unset($ccbill, $processing, $processed, $ipn, $ipn_q, $log4, $_log4, $log2, $logs_dir); /* Unset/reset these variables each pass. */ /**/ if (($unprocessed_line = trim($unprocessed_line)) && ($counter = (int) $counter + 1)) { $ccbill["s2member_log"][] = "DataLink IPN processed on: " . date("D M j, Y g:i:s a T"); /**/ $ccbill["dl_ipn"] = c_ws_plugin__s2member_utils_strings::trim_dq_deep(preg_split("/\",\"/", $unprocessed_line)); /**/ if (is_array($ccbill["dl_ipn_signup_vars"] = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(false, $ccbill["dl_ipn"][3]))) { if (preg_match("/^REBILL\$/i", $ccbill["dl_ipn"][0])) { $ccbill["s2member_log"][] = "ccBill® transaction identified as (SUBSCRIPTION PAYMENT)."; $ccbill["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as txn_type (subscr_payment)."; $ccbill["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"] = $ccbill["dl_ipn_signup_vars"]["subscr_id"]; /**/ $ipn["custom"] = $ccbill["dl_ipn_signup_vars"]["custom"]; /**/ $ipn["txn_id"] = $ccbill["dl_ipn"][5]; /* Unique transaction ID. */ /**/ $ipn["mc_gross"] = number_format($ccbill["dl_ipn"][6], 2, ".", ""); $ipn["mc_currency"] = strtoupper("USD"); /* DataLink uses USD. */ $ipn["tax"] = number_format("0.00", 2, ".", ""); /**/ $ipn["payer_email"] = $ccbill["dl_ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $ccbill["dl_ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $ccbill["dl_ipn_signup_vars"]["last_name"]; /**/ $ipn["option_name1"] = $ccbill["dl_ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $ccbill["dl_ipn_signup_vars"]["option_selection1"]; /**/ $ipn["option_name2"] = $ccbill["dl_ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $ccbill["dl_ipn_signup_vars"]["option_selection2"]; /**/ $ipn["item_number"] = $ccbill["dl_ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $ccbill["dl_ipn_signup_vars"]["item_name"]; /**/ $ipn_q = "&s2member_paypal_proxy=ccbill&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("/^EXPIRE\$/i", $ccbill["dl_ipn"][0])) { $ccbill["s2member_log"][] = "ccBill® transaction identified as (SUBSCRIPTION EXPIRATION)."; $ccbill["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as txn_type (subscr_eot)."; $ccbill["s2member_log"][] = "Please check PayPal® IPN logs for further processing details."; /**/ $processing = $processed = true; $ipn = array(); /* Reset. */ /**/ $ipn["txn_type"] = "subscr_eot"; $ipn["subscr_id"] = $ccbill["dl_ipn_signup_vars"]["subscr_id"]; /**/ $ipn["custom"] = $ccbill["dl_ipn_signup_vars"]["custom"]; /**/ $ipn["period1"] = $ccbill["dl_ipn_signup_vars"]["period1"]; $ipn["period3"] = $ccbill["dl_ipn_signup_vars"]["period3"]; /**/ $ipn["payer_email"] = $ccbill["dl_ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $ccbill["dl_ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $ccbill["dl_ipn_signup_vars"]["last_name"]; /**/ $ipn["option_name1"] = $ccbill["dl_ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $ccbill["dl_ipn_signup_vars"]["option_selection1"]; /**/ $ipn["option_name2"] = $ccbill["dl_ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $ccbill["dl_ipn_signup_vars"]["option_selection2"]; /**/ $ipn["item_number"] = $ccbill["dl_ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $ccbill["dl_ipn_signup_vars"]["item_name"]; /**/ $ipn_q = "&s2member_paypal_proxy=ccbill&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)\$/i", $ccbill["dl_ipn"][0])) { $ccbill["s2member_log"][] = "ccBill® transaction identified as (REFUND|CHARGEBACK)."; $ccbill["s2member_log"][] = "IPN reformulated. Piping through s2Member's core/standard PayPal® processor as payment_status (refunded|reversed)."; $ccbill["s2member_log"][] = "Please check PayPal® IPN logs for further processing details."; /**/ $processing = $processed = true; $ipn = array(); /* Reset. */ /**/ $ipn["custom"] = $ccbill["dl_ipn_signup_vars"]["custom"]; /**/ $ipn["parent_txn_id"] = $ccbill["dl_ipn_signup_vars"]["subscr_id"]; /**/ $ipn["payment_status"] = preg_match("/^CHARGEBACK\$/i", $ccbill["dl_ipn"][0]) ? "reversed" : "refunded"; $ipn["mc_fee"] = "-" . number_format("0.00", 2, ".", ""); $ipn["mc_gross"] = "-" . number_format($ccbill["dl_ipn"][5], 2, ".", ""); $ipn["mc_currency"] = strtoupper("USD"); /* DataLink uses USD. */ $ipn["tax"] = "-" . number_format("0.00", 2, ".", ""); /**/ $ipn["payer_email"] = $ccbill["dl_ipn_signup_vars"]["payer_email"]; $ipn["first_name"] = $ccbill["dl_ipn_signup_vars"]["first_name"]; $ipn["last_name"] = $ccbill["dl_ipn_signup_vars"]["last_name"]; /**/ $ipn["option_name1"] = $ccbill["dl_ipn_signup_vars"]["option_name1"]; $ipn["option_selection1"] = $ccbill["dl_ipn_signup_vars"]["option_selection1"]; /**/ $ipn["option_name2"] = $ccbill["dl_ipn_signup_vars"]["option_name2"]; $ipn["option_selection2"] = $ccbill["dl_ipn_signup_vars"]["option_selection2"]; /**/ $ipn["item_number"] = $ccbill["dl_ipn_signup_vars"]["item_number"]; $ipn["item_name"] = $ccbill["dl_ipn_signup_vars"]["item_name"]; /**/ $ipn_q = "&s2member_paypal_proxy=ccbill&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) { /* Here we add a message to the logs indicating the IPN was ignored; no action taken. */ $ccbill["s2member_log"][] = "Ignoring this DataLink IPN. It does NOT require any action on the part of s2Member."; } } } } } else { if (!$processed) { /* Here we add a message to the logs indicating that no IPN vars are available. */ $ccbill["s2member_log"][] = "Ignoring this DataLink IPN. No IPN signup vars for Subscr. ID: " . $ccbill["dl_ipn"][3] . "."; } } /**/ $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() ? "ccbill-dl-ipn-4-" . trim(preg_replace("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "ccbill-dl-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($ccbill, true) . "\n\n", FILE_APPEND); } } } } /**/ unset($unprocessed_lines[$line]); /* Remove this line and update the list of unprocessed IPN lines. */ set_transient("s2m_" . md5("s2member_pro_ccbill_datalink_ipns"), implode("\n", $unprocessed_lines), 31556926); /**/ if ($counter >= $per_process) { /* Only this many. */ break; } /* Break the loop now. */ } } } } /**/ return; /* Return for uniformity. */ }
/** * Handles Stripe Webhook/IPN event processing. * * @package s2Member\Stripe * @since 140617 * * @attaches-to ``add_action('init');`` */ public static function stripe_notify() { global $current_site, $current_blog; if (!empty($_GET['s2member_pro_stripe_notify']) && $GLOBALS['WS_PLUGIN__']['s2member']['o']['pro_stripe_api_secret_key']) { $stripe = array(); // Initialize array of Webhook/IPN event data and s2Member log details. @ignore_user_abort(TRUE); // Continue processing even if/when connection is broken. if (!class_exists('Stripe')) { require_once dirname(__FILE__) . '/stripe-sdk/lib/Stripe.php'; } Stripe::setApiKey($GLOBALS['WS_PLUGIN__']['s2member']['o']['pro_stripe_api_secret_key']); if (is_object($event = c_ws_plugin__s2member_pro_stripe_utilities::get_event()) && ($stripe['event'] = $event)) { switch ($event->type) { case 'invoice.payment_succeeded': // Subscription payments. if (!empty($event->data->object) && ($stripe_invoice = $event->data->object) instanceof Stripe_Invoice && !empty($stripe_invoice->customer) && !empty($stripe_invoice->subscription) && ($stripe_invoice_total = number_format(c_ws_plugin__s2member_pro_stripe_utilities::cents_to_dollar_amount($stripe_invoice->total, $stripe_invoice->currency), 2, '.', '')) > 0 && is_object($stripe_subscription = c_ws_plugin__s2member_pro_stripe_utilities::get_customer_subscription($stripe_invoice->customer, $stripe_invoice->subscription)) && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_subscription->id))) { $processing = TRUE; $ipn['txn_type'] = 'subscr_payment'; $ipn['txn_id'] = $stripe_invoice->id; $ipn['txn_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $ipn['custom'] = $ipn_signup_vars['custom']; $ipn['mc_gross'] = $stripe_invoice_total; $ipn['mc_currency'] = strtoupper($stripe_invoice->currency); $ipn['tax'] = number_format(0, 2, '.', ''); $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'stripe'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); if ($maybe_end_subscription = self::_maybe_end_subscription_after_payment($stripe_invoice->customer, $stripe_subscription)) { $stripe['s2member_log'][] = $maybe_end_subscription; } $stripe['s2member_log'][] = 'Webhook/IPN event `' . $event->type . '` reformulated. Piping through s2Member\'s core gateway processor as `txn_type` (`' . $ipn['txn_type'] . '`).'; $stripe['s2member_log'][] = 'Please check core IPN logs for further processing details.'; } break; // Break switch handler. // Break switch handler. case 'invoice.payment_failed': // Subscription payment failures. if (!empty($event->data->object) && ($stripe_invoice = $event->data->object) instanceof Stripe_Invoice && !empty($stripe_invoice->customer) && !empty($stripe_invoice->subscription) && ($stripe_invoice_total = number_format(c_ws_plugin__s2member_pro_stripe_utilities::cents_to_dollar_amount($stripe_invoice->total, $stripe_invoice->currency), 2, '.', '')) > 0 && is_object($stripe_subscription = c_ws_plugin__s2member_pro_stripe_utilities::get_customer_subscription($stripe_invoice->customer, $stripe_invoice->subscription)) && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_subscription->id))) { $processing = TRUE; $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); if ($maybe_end_subscription = self::_maybe_end_subscription_after_payment($stripe_invoice->customer, $stripe_subscription)) { $stripe['s2member_log'][] = $maybe_end_subscription; } $stripe['s2member_log'][] = 'Ignoring `' . $event->type . '`. s2Member does NOT respond to individual payment failures; only to subscription cancellations.'; $stripe['s2member_log'][] = 'You may control the behavior(s) associated w/ subscription payment failures from your Stripe Dashboard please.'; } break; // Break switch handler. // Break switch handler. case 'customer.deleted': // Customer deletions. if (!empty($event->data->object) && ($stripe_customer = $event->data->object) instanceof Stripe_Customer && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_customer->id))) { $processing = TRUE; $ipn['txn_type'] = 'subscr_eot'; $ipn['subscr_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'stripe'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); $stripe['s2member_log'][] = 'Webhook/IPN event `' . $event->type . '` reformulated. Piping through s2Member\'s core gateway processor as `txn_type` (`' . $ipn['txn_type'] . '`).'; $stripe['s2member_log'][] = 'Please check core IPN logs for further processing details.'; } break; // Break switch handler. // Break switch handler. case 'customer.subscription.deleted': // Customer subscription deletion. if (!empty($event->data->object) && ($stripe_subscription = $event->data->object) instanceof Stripe_Subscription && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_subscription->id))) { $processing = TRUE; $ipn['txn_type'] = 'subscr_eot'; $ipn['subscr_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'stripe'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); $stripe['s2member_log'][] = 'Webhook/IPN event `' . $event->type . '` reformulated. Piping through s2Member\'s core gateway processor as `txn_type` (`' . $ipn['txn_type'] . '`).'; $stripe['s2member_log'][] = 'Please check core IPN logs for further processing details.'; } break; // Break switch handler. // Break switch handler. case 'charge.refunded': // Customer refund (partial or full). if (!empty($event->data->object) && ($stripe_charge = $event->data->object) instanceof Stripe_Charge && !empty($strip_charge->amount_refunded) && !empty($stripe_charge->customer) && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_charge->customer))) { $processing = TRUE; $ipn['payment_status'] = 'refunded'; $ipn['subscr_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $ipn['parent_txn_id'] = $ipn_signup_vars['subscr_id']; $ipn['custom'] = $ipn_signup_vars['custom']; $ipn['mc_fee'] = '-' . number_format('0.00', 2, '.', ''); $ipn['mc_gross'] = '-' . number_format(abs($strip_charge->amount), 2, '.', ''); $ipn['mc_currency'] = strtoupper($strip_charge->currency); $ipn['tax'] = '-' . number_format('0.00', 2, '.', ''); $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'stripe'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); $stripe['s2member_log'][] = 'Webhook/IPN event `' . $event->type . '` reformulated. Piping through s2Member\'s core gateway processor.'; $stripe['s2member_log'][] = 'Please check core IPN logs for further processing details.'; } break; // Break switch handler. // Break switch handler. case 'charge.dispute.created': // Customer dispute (chargeback). if (!empty($event->data->object->charge) && ($stripe_charge = c_ws_plugin__s2member_pro_stripe_utilities::get_charge($event->data->object->charge)) instanceof Stripe_Charge && !empty($stripe_charge->customer) && ($ipn_signup_vars = c_ws_plugin__s2member_utils_users::get_user_ipn_signup_vars(0, $stripe_charge->customer))) { $processing = TRUE; $ipn['payment_status'] = 'reversed'; $ipn['subscr_cid'] = $ipn_signup_vars['subscr_cid']; $ipn['subscr_id'] = $ipn_signup_vars['subscr_id']; $ipn['parent_txn_id'] = $ipn_signup_vars['subscr_id']; $ipn['custom'] = $ipn_signup_vars['custom']; $ipn['mc_fee'] = '-' . number_format('0.00', 2, '.', ''); $ipn['mc_gross'] = '-' . number_format(abs($strip_charge->amount), 2, '.', ''); $ipn['mc_currency'] = strtoupper($strip_charge->currency); $ipn['tax'] = '-' . number_format('0.00', 2, '.', ''); $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_name'] = $ipn_signup_vars['item_name']; $ipn['item_number'] = $ipn_signup_vars['item_number']; $ipn['s2member_paypal_proxy'] = 'stripe'; $ipn['s2member_paypal_proxy_use'] = 'pro-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)); $stripe['s2member_log'][] = 'Stripe Webhook/IPN event type identified as: `' . $event->type . '` on: ' . date('D M j, Y g:i:s a T'); $stripe['s2member_log'][] = 'Webhook/IPN event `' . $event->type . '` reformulated. Piping through s2Member\'s core gateway processor.'; $stripe['s2member_log'][] = 'Please check core IPN logs for further processing details.'; } break; // Break switch handler. } if (empty($processing)) { $stripe['s2member_log'][] = 'Ignoring this Webhook/IPN. The event does NOT require any action on the part of s2Member.'; } } else { $stripe['s2member_log'][] = 'Unable to verify Webhook/IPN event ID. This is most likely related to an invalid Stripe configuration. Please check: s2Member → Stripe Options.'; $stripe['s2member_log'][] = 'If you\'re absolutely SURE that your Stripe configuration is valid, you may want to run some tests on your server, just to be sure \\$_POST variables (and php://input) are populated; and that your server is able to connect to Stripe over an HTTPS connection.'; $stripe['s2member_log'][] = 's2Member uses the Stripe SDK for remote connections; which relies upon the cURL extension for PHP. Please make sure that your installation of PHP has the cURL extension; and that it\'s configured together with OpenSSL for HTTPS communication.'; $stripe['s2member_log'][] = var_export($_REQUEST, TRUE) . "\n" . var_export(json_decode(@file_get_contents('php://input')), TRUE); } c_ws_plugin__s2member_utils_logs::log_entry('stripe-ipn', $stripe); status_header(200); header('Content-Type: text/plain; charset=UTF-8'); while (@ob_end_clean()) { } exit; } }