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; }