public function handle_stripe_ipn()
 {
     SwpmLog::log_simple_debug("Stripe Buy Now IPN received. Processing request...", true);
     //SwpmLog::log_simple_debug(print_r($_REQUEST, true), true);//Useful for debugging purpose
     //Include the Stripe library.
     include SIMPLE_WP_MEMBERSHIP_PATH . 'lib/stripe-gateway/init.php';
     //Read and sanitize the request parameters.
     $button_id = sanitize_text_field($_REQUEST['item_number']);
     $button_id = absint($button_id);
     $button_title = sanitize_text_field($_REQUEST['item_name']);
     $payment_amount = sanitize_text_field($_REQUEST['item_price']);
     $price_in_cents = $payment_amount * 100;
     //The amount (in cents). This value is used in Stripe API.
     $currency_code = sanitize_text_field($_REQUEST['currency_code']);
     $stripe_token = sanitize_text_field($_POST['stripeToken']);
     $stripe_token_type = sanitize_text_field($_POST['stripeTokenType']);
     $stripe_email = sanitize_email($_POST['stripeEmail']);
     //Retrieve the CPT for this button
     $button_cpt = get_post($button_id);
     if (!$button_cpt) {
         //Fatal error. Could not find this payment button post object.
         SwpmLog::log_simple_debug("Fatal Error! Failed to retrieve the payment button post object for the given button ID: " . $button_id, false);
         wp_die("Fatal Error! Payment button (ID: " . $button_id . ") does not exist. This request will fail.");
     }
     $membership_level_id = get_post_meta($button_id, 'membership_level_id', true);
     //Validate and verify some of the main values.
     $true_payment_amount = get_post_meta($button_id, 'payment_amount', true);
     if ($payment_amount != $true_payment_amount) {
         //Fatal error. Payment amount may have been tampered with.
         $error_msg = 'Fatal Error! Received payment amount (' . $payment_amount . ') does not match with the original amount (' . $true_payment_amount . ')';
         SwpmLog::log_simple_debug($error_msg, false);
         wp_die($error_msg);
     }
     $true_currency_code = get_post_meta($button_id, 'payment_currency', true);
     if ($currency_code != $true_currency_code) {
         //Fatal error. Currency code may have been tampered with.
         $error_msg = 'Fatal Error! Received currency code (' . $currency_code . ') does not match with the original code (' . $true_currency_code . ')';
         SwpmLog::log_simple_debug($error_msg, false);
         wp_die($error_msg);
     }
     //Validation passed. Go ahead with the charge.
     //Sandbox and other settings
     $settings = SwpmSettings::get_instance();
     $sandbox_enabled = $settings->get_value('enable-sandbox-testing');
     if ($sandbox_enabled) {
         SwpmLog::log_simple_debug("Sandbox payment mode is enabled. Using test API key details.", true);
         $secret_key = get_post_meta($button_id, 'stripe_test_secret_key', true);
         //Use sandbox API key
     } else {
         $secret_key = get_post_meta($button_id, 'stripe_live_secret_key', true);
         //Use live API key
     }
     //Set secret API key in the Stripe library
     \Stripe\Stripe::setApiKey($secret_key);
     // Get the credit card details submitted by the form
     $token = $stripe_token;
     // Create the charge on Stripe's servers - this will charge the user's card
     try {
         $charge = \Stripe\Charge::create(array("amount" => $price_in_cents, "currency" => strtolower($currency_code), "source" => $token, "description" => $button_title));
     } catch (\Stripe\Error\Card $e) {
         // The card has been declined
         SwpmLog::log_simple_debug("Stripe Charge Error! The card has been declined. " . $e->getMessage(), false);
         $body = $e->getJsonBody();
         $error = $body['error'];
         $error_string = print_r($error, true);
         SwpmLog::log_simple_debug("Error details: " . $error_string, false);
         wp_die("Stripe Charge Error! Card charge has been declined. " . $e->getMessage() . $error_string);
     }
     //Everything went ahead smoothly with the charge.
     SwpmLog::log_simple_debug("Stripe Buy Now charge successful.", true);
     //Grab the charge ID and set it as the transaction ID.
     $txn_id = $charge->id;
     //$charge->balance_transaction;
     //The charge ID can be used to retrieve the transaction details using hte following call.
     //\Stripe\Charge::retrieve($charge->id);
     $custom = sanitize_text_field($_REQUEST['custom']);
     $custom_var = SwpmTransactions::parse_custom_var($custom);
     $swpm_id = isset($custom_var['swpm_id']) ? $custom_var['swpm_id'] : '';
     //Create the $ipn_data array.
     $ipn_data = array();
     $ipn_data['mc_gross'] = $payment_amount;
     $ipn_data['first_name'] = '';
     $ipn_data['last_name'] = '';
     $ipn_data['payer_email'] = $stripe_email;
     $ipn_data['membership_level'] = $membership_level_id;
     $ipn_data['txn_id'] = $txn_id;
     $ipn_data['subscr_id'] = $txn_id;
     $ipn_data['swpm_id'] = $swpm_id;
     $ipn_data['ip'] = $custom_var['user_ip'];
     $ipn_data['custom'] = $custom;
     $ipn_data['gateway'] = 'stripe';
     $ipn_data['status'] = 'completed';
     $ipn_data['address_street'] = '';
     $ipn_data['address_city'] = '';
     $ipn_data['address_state'] = '';
     $ipn_data['address_zipcode'] = '';
     $ipn_data['country'] = '';
     //Handle the membership signup related tasks.
     swpm_handle_subsc_signup_stand_alone($ipn_data, $membership_level_id, $txn_id, $swpm_id);
     //Save the transaction record
     SwpmTransactions::save_txn_record($ipn_data);
     SwpmLog::log_simple_debug('Transaction data saved.', true);
     //Trigger the stripe IPN processed action hook (so other plugins can can listen for this event).
     do_action('swpm_stripe_ipn_processed', $ipn_data);
     do_action('swpm_payment_ipn_processed', $ipn_data);
     //Redirect the user to the return URL (or to the homepage if a return URL is not specified for this payment button).
     $return_url = get_post_meta($button_id, 'return_url', true);
     if (empty($return_url)) {
         $return_url = SIMPLE_WP_MEMBERSHIP_SITE_HOME_URL;
     }
     SwpmLog::log_simple_debug("Redirecting customer to: " . $return_url, true);
     SwpmLog::log_simple_debug("End of Stripe Buy Now IPN processing.", true, true);
     SwpmMiscUtils::redirect_to_url($return_url);
 }
 function swpm_validate_and_create_membership()
 {
     // Check Product Name , Price , Currency , Receivers email ,
     $error_msg = "";
     // Read the IPN and validate
     $gross_total = $this->ipn_data['mc_gross'];
     $transaction_type = $this->ipn_data['txn_type'];
     $txn_id = $this->ipn_data['txn_id'];
     $payment_status = $this->ipn_data['payment_status'];
     //Check payment status
     if (!empty($payment_status)) {
         if ($payment_status == "Denied") {
             $this->debug_log("Payment status for this transaction is DENIED. You denied the transaction... most likely a cancellation of an eCheque. Nothing to do here.", false);
             return false;
         }
         if ($payment_status == "Canceled_Reversal") {
             $this->debug_log("This is a dispute closed notification in your favour. The plugin will not do anyting.", false);
             return true;
         }
         if ($payment_status != "Completed" && $payment_status != "Processed" && $payment_status != "Refunded" && $payment_status != "Reversed") {
             $error_msg .= 'Funds have not been cleared yet. Transaction will be processed when the funds clear!';
             $this->debug_log($error_msg, false);
             return false;
         }
     }
     //Check txn type
     if ($transaction_type == "new_case") {
         $this->debug_log('This is a dispute case. Nothing to do here.', true);
         return true;
     }
     $custom = $this->ipn_data['custom'];
     $delimiter = "&";
     $customvariables = array();
     $namevaluecombos = explode($delimiter, $custom);
     foreach ($namevaluecombos as $keyval_unparsed) {
         $equalsignposition = strpos($keyval_unparsed, '=');
         if ($equalsignposition === false) {
             $customvariables[$keyval_unparsed] = '';
             continue;
         }
         $key = substr($keyval_unparsed, 0, $equalsignposition);
         $value = substr($keyval_unparsed, $equalsignposition + 1);
         $customvariables[$key] = $value;
     }
     //Handle refunds
     if ($gross_total < 0) {
         // This is a refund or reversal
         $this->debug_log('This is a refund notification. Refund amount: ' . $gross_total, true);
         swpm_handle_subsc_cancel_stand_alone($this->ipn_data, true);
         return true;
     }
     if (isset($this->ipn_data['reason_code']) && $this->ipn_data['reason_code'] == 'refund') {
         $this->debug_log('This is a refund notification. Refund amount: ' . $gross_total, true);
         swpm_handle_subsc_cancel_stand_alone($this->ipn_data, true);
         return true;
     }
     if ($transaction_type == "subscr_signup") {
         $this->debug_log('Subscription signup IPN received... nothing to do here(handled by the subscription IPN handler)', true);
         // Code to handle the signup IPN for subscription
         $subsc_ref = $customvariables['subsc_ref'];
         if (!empty($subsc_ref)) {
             $this->debug_log('swpm integration is being used... creating member account...', true);
             $swpm_id = $customvariables['swpm_id'];
             swpm_handle_subsc_signup_stand_alone($this->ipn_data, $subsc_ref, $this->ipn_data['subscr_id'], $swpm_id);
             //Handle customized subscription signup
         }
         return true;
     } else {
         if ($transaction_type == "subscr_cancel" || $transaction_type == "subscr_eot" || $transaction_type == "subscr_failed") {
             // Code to handle the IPN for subscription cancellation
             swpm_handle_subsc_cancel_stand_alone($this->ipn_data);
             $this->debug_log('Subscription cancellation IPN received... nothing to do here(handled by the subscription IPN handler)', true);
             return true;
         } else {
             $cart_items = array();
             $this->debug_log('Transaction Type: Buy Now/Subscribe', true);
             $item_number = $this->ipn_data['item_number'];
             $item_name = $this->ipn_data['item_name'];
             $quantity = $this->ipn_data['quantity'];
             $mc_gross = $this->ipn_data['mc_gross'];
             $mc_currency = $this->ipn_data['mc_currency'];
             $current_item = array('item_number' => $item_number, 'item_name' => $item_name, 'quantity' => $quantity, 'mc_gross' => $mc_gross, 'mc_currency' => $mc_currency);
             array_push($cart_items, $current_item);
         }
     }
     $counter = 0;
     foreach ($cart_items as $current_cart_item) {
         $cart_item_data_num = $current_cart_item['item_number'];
         $cart_item_data_name = trim($current_cart_item['item_name']);
         $cart_item_data_quantity = $current_cart_item['quantity'];
         $cart_item_data_total = $current_cart_item['mc_gross'];
         $cart_item_data_currency = $current_cart_item['mc_currency'];
         if (empty($cart_item_data_quantity)) {
             $cart_item_data_quantity = 1;
         }
         $this->debug_log('Item Number: ' . $cart_item_data_num, true);
         $this->debug_log('Item Name: ' . $cart_item_data_name, true);
         $this->debug_log('Item Quantity: ' . $cart_item_data_quantity, true);
         $this->debug_log('Item Total: ' . $cart_item_data_total, true);
         $this->debug_log('Item Currency: ' . $cart_item_data_currency, true);
         //Get the button id
         $button_id = $cart_item_data_num;
         //Button id is the item number.
         //*** Handle Membership Payment ***
         //--------------------------------------------------------------------------------------
         // ========= Need to find the (level ID) in the custom variable ============
         $subsc_ref = $customvariables['subsc_ref'];
         //Membership level ID
         $this->debug_log('Membership payment paid for membership level ID: ' . $subsc_ref, true);
         if (!empty($subsc_ref)) {
             $swpm_id = "";
             if (isset($customvariables['swpm_id'])) {
                 $swpm_id = $customvariables['swpm_id'];
             }
             if ($transaction_type == "web_accept") {
                 $this->debug_log('swpm integration is being used... creating member account...', true);
                 swpm_handle_subsc_signup_stand_alone($this->ipn_data, $subsc_ref, $this->ipn_data['txn_id'], $swpm_id);
             } else {
                 if ($transaction_type == "subscr_payment") {
                     $this->debug_log('swpm subscr_payment type transaction. Checking if the member profile needed to be updated', true);
                     swpm_update_member_subscription_start_date_if_applicable($this->ipn_data);
                 }
             }
         } else {
             $this->debug_log('Membership level ID is missing in the payment notification! Cannot process this notification.', false);
         }
         //== End of Membership payment handling ==
         $counter++;
     }
     /*** Do Post payment operation and cleanup ***/
     //Save the transaction data
     $this->debug_log('Saving transaction data to the database table.', true);
     $this->ipn_data['gateway'] = 'paypal';
     $this->ipn_data['status'] = $this->ipn_data['payment_status'];
     SwpmTransactions::save_txn_record($this->ipn_data, $cart_items);
     $this->debug_log('Transaction data saved.', true);
     //Trigger the PayPal IPN processed action hook (so other plugins can can listen for this event).
     do_action('swpm_paypal_ipn_processed', $this->ipn_data);
     do_action('swpm_payment_ipn_processed', $this->ipn_data);
     return true;
 }