public function external_hook($hook) { switch ($hook) { case 'event_ipn': $body = @file_get_contents('php://input'); $event_json = json_decode($body); ob_start(); echo "UCM coinbase DEBUG:<br><br>JSON: <br>\n"; print_r($event_json); echo "<br><br>\n"; $success = false; $bits = explode(':', isset($event_json->order->custom) ? $event_json->order->custom : ''); if (count($bits) == 4) { // we have our custom bits, invoice_id, invoice_payment_id and hash // check they are right $invoice_id = (int) $bits[0]; $invoice_payment_id = (int) $bits[1]; $invoice_payment_subscription_id = (int) $bits[2]; $hash = $bits[3]; $correct_hash = self::get_payment_key($invoice_id, $invoice_payment_id, $invoice_payment_subscription_id, true); if ($invoice_id && $invoice_payment_id && $hash == $correct_hash) { // This will send receipts on succesful invoices // todo - coinbase doesnt sent this callback correctly just yet if ($event_json && isset($event_json->recurring_payment) && $invoice_payment_subscription_id) { // status changes on a recurring payment. $invoice_payment_subscription = get_single('invoice_payment_subscription', 'invoice_payment_subscription_id', $invoice_payment_subscription_id); if (!$invoice_payment_subscription['date_start'] || $invoice_payment_subscription['date_start'] == '0000-00-00') { // no start date yet, set the start date now. if ($event_json->recurring_payment->status == 'active') { update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('status' => _INVOICE_SUBSCRIPTION_ACTIVE, 'date_start' => date('Y-m-d'))); } } if ($event_json->recurring_payment->status == 'paused' || $event_json->recurring_payment->status == 'canceled') { update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('status' => _INVOICE_SUBSCRIPTION_FAILED)); } } if ($event_json && isset($event_json->order->status) && $event_json->order->status == 'completed' && isset($event_json->order->total_native) && isset($event_json->order->custom)) { // crab out the custom bits so we know what to deal with. $invoice_payment_data = module_invoice::get_invoice_payment($invoice_payment_id); $currency = module_config::get_currency($invoice_payment_data['currency_id']); if ($invoice_payment_subscription_id) { // this API result is for a subscription payment. $invoice_payment_subscription = get_single('invoice_payment_subscription', 'invoice_payment_subscription_id', $invoice_payment_subscription_id); if ($invoice_payment_subscription && $invoice_payment_subscription['invoice_payment_subscription_id'] == $invoice_payment_subscription_id && $currency['code'] == $event_json->order->total_native->currency_iso) { if (!$invoice_payment_subscription['date_start'] || $invoice_payment_subscription['date_start'] == '0000-00-00') { // no start date yet, set the start date now (this should really happen in the above callback, but coinbase isn't working right now) update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('status' => _INVOICE_SUBSCRIPTION_ACTIVE, 'date_start' => date('Y-m-d'))); } // we have a subscription payment. woo! // this gets a bit tricky, we have to work out if the invoice has been generated for this subscription yet. // if this invoice hasn't been generated yet then we have to generate it. // pass this back to the invoice class so we can reuse this feature in the future. $data = module_invoice::create_new_invoice_for_subscription_payment($invoice_id, $invoice_payment_id, $invoice_payment_subscription_id); if ($data && $data['invoice_id'] && $data['invoice_payment_id']) { $next_time = time(); $next_time = strtotime('+' . abs((int) $invoice_payment_subscription['days']) . ' days', $next_time); $next_time = strtotime('+' . abs((int) $invoice_payment_subscription['months']) . ' months', $next_time); $next_time = strtotime('+' . abs((int) $invoice_payment_subscription['years']) . ' years', $next_time); update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('date_last_pay' => date('Y-m-d'), 'date_next' => date('Y-m-d', $next_time))); update_insert("invoice_payment_id", $data['invoice_payment_id'], "invoice_payment", array('date_paid' => date('Y-m-d'), 'amount' => $event_json->order->total_native->cents / 100, 'method' => self::get_payment_method_name() . ' (Subscription)', 'invoice_payment_subscription_id' => $invoice_payment_subscription_id)); self::add_payment_data($data['invoice_payment_id'], 'log', "Invoice Payment Subscription Received!"); self::add_payment_data($data['invoice_payment_id'], 'log', "API IP is " . $_SERVER['REMOTE_ADDR']); self::add_payment_data($data['invoice_payment_id'], 'log', "Received BTC: " . $event_json->order->total_btc->cents / 10000000); self::add_payment_data($data['invoice_payment_id'], 'log', "Received " . $event_json->order->total_native->currency_iso . ': ' . $event_json->order->total_native->cents / 100); self::add_payment_data($data['invoice_payment_id'], 'log', "Destination Address: " . $event_json->order->receive_address); self::add_payment_data($data['invoice_payment_id'], 'log', "Currency code matches, marking invoice as paid."); self::add_payment_data($data['invoice_payment_id'], 'log', "Raw Event Data: \n" . json_encode($event_json)); module_invoice::save_invoice($data['invoice_id'], array()); echo "Successful Subscription Payment!"; } else { send_error("Coinbase Subscription Error (failed to generate new invoice!) " . var_export($data, true)); } } else { send_error('Currency code missmatch on coinbase subscription payment'); } } else { // this is a normal once off payment. self::add_payment_data($invoice_payment_id, 'log', "API IP is " . $_SERVER['REMOTE_ADDR']); self::add_payment_data($invoice_payment_id, 'log', "Received BTC: " . $event_json->order->total_btc->cents / 10000000); self::add_payment_data($invoice_payment_id, 'log', "Received " . $event_json->order->total_native->currency_iso . ': ' . $event_json->order->total_native->cents / 100); self::add_payment_data($invoice_payment_id, 'log', "Destination Address: " . $event_json->order->receive_address); if ($currency['code'] == $event_json->order->total_native->currency_iso) { self::add_payment_data($invoice_payment_id, 'log', "Currency code matches, marking invoice as paid."); update_insert("invoice_payment_id", $invoice_payment_id, "invoice_payment", array('date_paid' => date('Y-m-d'), 'amount' => $event_json->order->total_native->cents / 100)); module_invoice::save_invoice($invoice_id, array()); echo "Successful Payment!"; $success = true; } else { self::add_payment_data($invoice_payment_id, 'log', "Currency code missmatch, please check settings!"); } self::add_payment_data($invoice_payment_id, 'log', "Raw Event Data: \n" . json_encode($event_json)); } } } } $debug = ob_get_clean(); if (module_config::c('coinbase_payment_debug', 0)) { send_error("Coinbase Debug: {$debug}"); } exit; break; case 'pay_subscription': $invoice_id = isset($_REQUEST['invoice_id']) ? $_REQUEST['invoice_id'] : false; $invoice_payment_id = isset($_REQUEST['invoice_payment_id']) ? $_REQUEST['invoice_payment_id'] : false; $invoice_payment_subscription_id = isset($_REQUEST['invoice_payment_subscription_id']) ? $_REQUEST['invoice_payment_subscription_id'] : false; $coinbase_plan_id = isset($_REQUEST['coinbase_plan_id']) ? $_REQUEST['coinbase_plan_id'] : false; $user_id = isset($_REQUEST['user_id']) ? $_REQUEST['user_id'] : false; if ($invoice_id && $invoice_payment_id && $coinbase_plan_id && $invoice_payment_subscription_id && $user_id && isset($_POST['coinbaseToken'])) { $user_data = module_user::get_user($user_id); $email = isset($_REQUEST['coinbaseEmail']) && strlen($_REQUEST['coinbaseEmail']) ? $_REQUEST['coinbaseEmail'] : $user_data['email']; if (!$email || !strpos($email, '@')) { die('Please ensure your user account has a valid email address before paying with coinbase'); } $invoice_payment = get_single('invoice_payment', 'invoice_payment_id', $invoice_payment_id); $invoice_payment_subscription = get_single('invoice_payment_subscription', 'invoice_payment_subscription_id', $invoice_payment_subscription_id); if (!$invoice_payment || !$invoice_payment_subscription || $invoice_payment['invoice_id'] != $invoice_id || $invoice_payment['invoice_payment_subscription_id'] != $invoice_payment_subscription_id) { die('Invalid invoice payment subscription id'); } $invoice_payment_data = module_invoice::get_invoice_payment($invoice_payment_id); $invoice_data = module_invoice::get_invoice($invoice_id); if ($invoice_payment_data && $invoice_data && $invoice_id == $invoice_data['invoice_id'] && $invoice_payment_data['invoice_id'] == $invoice_data['invoice_id']) { $currency = module_config::get_currency($invoice_payment_data['currency_id']); $currency_code = $currency['code']; $description = isset($_REQUEST['description']) ? $_REQUEST['description'] : 'N/A'; $template = new module_template(); ob_start(); require_once 'includes/plugin_paymethod_coinbase/coinbase-php/lib/coinbase.php'; $coinbase = array("secret_key" => module_config::c('payment_method_coinbase_api_key'), "publishable_key" => module_config::c('payment_method_coinbase_secret_key')); coinbase::setApiKey($coinbase['secret_key']); try { // todo- search for existing customer based on email address??? // todo: check if adding new plan to existing customer work?? $coinbase_customer = coinbase_Customer::create(array("card" => $_POST['coinbaseToken'], "email" => $email, 'metadata' => array('user_id' => $user_id))); if ($coinbase_customer && $coinbase_customer->id) { //} && $coinbase_customer->subscriptions){ $coinbase_subscription = $coinbase_customer->subscriptions->create(array('plan' => $coinbase_plan_id)); if ($coinbase_subscription && $coinbase_subscription->id) { update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('status' => _INVOICE_SUBSCRIPTION_ACTIVE, 'date_start' => date('Y-m-d'), 'coinbase_customer' => $coinbase_customer->id, 'coinbase_subscription' => $coinbase_subscription->id)); module_paymethod_coinbase::add_payment_data($invoice_payment_id, 'log', "Started coinbase Subscription: " . var_export(array('customer.id' => $coinbase_customer->id, 'plan.id' => $coinbase_plan_id, 'subscription.id' => $coinbase_subscription->id), true)); // success! // redirect to receipt page. redirect_browser(module_invoice::link_public_payment_complete($invoice_id)); } else { echo 'Failed to create subscription with coinbase'; } } $error = "Something went wrong during coinbase payment. Please confirm invoice payment went through: " . htmlspecialchars($description); send_error($error); echo $error; } catch (coinbase_CardError $e) { // The card has been declined $body = $e->getJsonBody(); $err = $body['error']; $error = "Sorry: Payment failed. <br><br>\n\n" . htmlspecialchars($description) . ". <br><br>\n\n"; $error .= $err['message']; echo $error; $error .= "\n\n\n" . var_export($err, true); send_error($error); } catch (Exception $e) { $body = $e->getJsonBody(); $err = $body['error']; $error = "Sorry: Payment failed. <br><br>\n\n" . htmlspecialchars($description) . ". <br><br>\n\n"; $error .= $err['message']; echo $error; $error .= "\n\n\n" . var_export($err, true); send_error($error); } $template->content = ob_get_clean(); echo $template->render('pretty_html'); exit; } } echo 'Error paying via coinbase'; exit; } }
public function run_cron($debug = false) { // we only want to perform these cron actions if we're after a certain time of day // because we dont want to be generating these renewals and sending them at midnight, can get confusing $after_time = module_config::c('invoice_automatic_after_time', 7); $time_of_day = date('G'); if ($time_of_day < $after_time) { if ($debug) { echo "Not performing automatic invoice operations until after {$after_time}:00 - it is currently {$time_of_day}:" . date('i') . "<br>\n"; } return; } // find automatic job renewals $sql = "SELECT p.* FROM `" . _DB_PREFIX . "job` p "; $sql .= " WHERE p.date_renew != '0000-00-00'"; $sql .= " AND p.date_start != '0000-00-00'"; $sql .= " AND p.date_renew <= '" . date('Y-m-d') . "'"; $sql .= " AND (p.renew_job_id IS NULL OR p.renew_job_id = 0)"; $sql .= " AND (p.renew_auto = 1)"; $renew_jobs = qa($sql); foreach ($renew_jobs as $renew_job) { // time to automatically renew this job! woo! if ($debug) { echo "Automatically Renewing Job " . module_job::link_open($renew_job['job_id'], true) . "<br>\n"; } //$job_details = $this->get_job($renew_job['job_id']); $job_invoices = module_invoice::get_invoices(array('job_id' => $renew_job['job_id'])); $unpaid_invoice = false; foreach ($job_invoices as $job_invoice) { $job_invoice = module_invoice::get_invoice($job_invoice['invoice_id']); if ($job_invoice['total_amount_due'] > 0) { $unpaid_invoice = true; } } if (module_config::c('invoice_auto_renew_only_paid_invoices', 1) && $unpaid_invoice) { if ($debug) { echo "Not automatically renewing this job because it has unpaid invoices. <br>\n"; } } else { $new_job_id = $this->renew_job($renew_job['job_id'], true); if ($new_job_id) { //module_cache::clear_cache(); if ($debug) { echo "Job Automatically Renewed: " . module_job::link_open($new_job_id, true) . "<br>\n"; } if ($renew_job['renew_invoice']) { // we want to tick all these tasks off and invoice this job, then send this invoice to the customer. $job_tasks = module_job::get_tasks($new_job_id); foreach ($job_tasks as $job_task_id => $job_task) { $job_tasks[$job_task_id]['fully_completed_t'] = 1; $job_tasks[$job_task_id]['fully_completed'] = 1; } $this->save_job_tasks($new_job_id, array('job_task' => $job_tasks)); //module_cache::clear_cache(); // generate an invoice for this job. $_REQUEST['job_id'] = $new_job_id; $new_invoice = module_invoice::get_invoice('new'); $new_invoice['date_create'] = $renew_job['date_renew']; $new_invoice['invoice_invoice_item'] = module_invoice::get_invoice_items('new', $new_invoice); $new_invoice_id = module_invoice::save_invoice('new', $new_invoice); //module_cache::clear_cache(); if ($debug) { echo "Generated new invoice for renewed job: " . module_invoice::link_open($new_invoice_id, true) . "<br/>"; } if ($debug) { echo "Emailing invoice to customer..."; } if (module_invoice::email_invoice_to_customer($new_invoice_id)) { if ($debug) { echo "send successfully"; } } else { if ($debug) { echo "send failed"; } } if ($debug) { echo "<br>\n"; } } } } } }
public static function generate_subscription_invoice($subscription_id, $owner_table, $owner_id, $date, $amount) { $subscription = self::get_subscription($subscription_id); if (!$subscription || $subscription['subscription_id'] != $subscription_id) { return false; } $members_subscriptions = module_subscription::get_subscriptions_by($owner_table, $owner_id); /*if($customer_hack){ $members_subscriptions = module_subscription::get_subscriptions_by_customer($member_id); }else{ $members_subscriptions = module_subscription::get_subscriptions_by_member($member_id); }*/ // we have an ammount! create an invoice for this amount/ // assign it to a subscription (but not necessary!) if ($subscription_id && !isset($members_subscriptions[$subscription_id])) { die('Shouldnt happen'); } $history = module_subscription::get_subscription_history($subscription_id, $owner_table, $owner_id); // we grab the history of this subscription. if this is the first subscription for this member and the $date is in the past then we update the date to today. if (strtotime($date) < strtotime(date('Y-m-d'))) { $has_history = false; foreach ($history as $h) { if (!$h['invoice_id']) { } else { $invoice_data = module_invoice::get_invoice($h['invoice_id']); if ($invoice_data['date_cancel'] != '0000-00-00') { continue; } $has_history = true; break; } } if (!$has_history) { $date = date('Y-m-d'); } } // does this one have a discount/trial ? $number_of_past_invoices = 0; foreach ($history as $h) { if (!$h['invoice_id']) { } else { $invoice_data = module_invoice::get_invoice($h['invoice_id']); if ($invoice_data['date_cancel'] != '0000-00-00') { continue; } $number_of_past_invoices++; } } //if(isset($subscription['settings']) && isset($subscription['settings']['trial_period']) && $subscription['settings']['trial_period'] > 0 && $number_of_past_invoices < $subscription['settings']['trial_period']){ //echo $number_of_past_invoices;print_r($subscription['settings']);print_r($history);exit; if ($number_of_past_invoices <= 0 && isset($subscription['settings']['trial_price_adjust']) && $subscription['settings']['trial_price_adjust'] != 0) { $amount += $subscription['settings']['trial_price_adjust']; } //} //$next_time = self::_calculate_next_time(strtotime($date), $subscription); if (isset($members_subscriptions[$subscription_id]['next_due_date']) && $members_subscriptions[$subscription_id]['next_due_date'] != '0000-00-00' && $members_subscriptions[$subscription_id]['next_due_date'] != $date) { $time_period = self::_calculate_next_time(strtotime($members_subscriptions[$subscription_id]['next_due_date']), $subscription, true); } else { $time_period = self::_calculate_next_time(strtotime($date), $subscription, true); } $subscription_owner_id = $members_subscriptions[$subscription_id]['subscription_owner_id']; $amount_currency = $subscription['currency_id']; //module_config::c('subscription_currency',1); $data = array('subscription_id' => $subscription_id, 'subscription_owner_id' => $subscription_owner_id, 'amount' => $amount, 'currency_id' => $amount_currency, 'invoice_id' => 0, 'from_next_due_date' => $members_subscriptions[$subscription_id]['next_due_date']); /*if($customer_hack){ unset($data['member_id']); $data['customer_id'] = $member_id; }*/ $subscription_history_id = update_insert('subscription_history_id', 0, 'subscription_history', $data); $customer_id = 0; switch ($owner_table) { case 'website': $website_data = module_website::get_website($owner_id); $customer_id = $website_data['customer_id']; break; case 'customer': $customer_id = $owner_id; break; } module_invoice::$new_invoice_number_date = $date; // we have to seed the customer id if it exists. $_REQUEST['customer_id'] = $customer_id; $invoice_data = module_invoice::get_invoice('new', true); $invoice_data['customer_id'] = $customer_id; // customer_id, website_id, member_id $invoice_data[$owner_table . '_id'] = $owner_id; /*if($customer_hack){ $invoice_data['member_id'] = 0; $invoice_data['customer_id'] = $member_id; }else{ $invoice_data['member_id'] = $member_id; // added in version 2.31 for invoice integration. eg: emailing invoice $invoice_data['customer_id'] = 0; }*/ $invoice_data['user_id'] = 0; $invoice_data['currency_id'] = $amount_currency; $invoice_data['date_sent'] = '0000-00-00'; $invoice_data['date_cancel'] = '0000-00-00'; $invoice_data['date_create'] = $date; $invoice_data['default_task_type'] = _TASK_TYPE_AMOUNT_ONLY; // todo - option this out to the subscription settings area. $invoice_data['date_due'] = date('Y-m-d', strtotime("+" . module_config::c('subscription_invoice_due_date', 0) . " days", strtotime($date))); if (strtotime($invoice_data['date_due']) < time()) { // due date in the past? hmm, update it from today instead. $invoice_data['date_due'] = date('Y-m-d', strtotime("+" . module_config::c('subscription_invoice_due_date', 0) . " days", time())); } $invoice_data['name'] = !$invoice_data['name'] || module_config::c('subscription_invoice_numeric', 0) ? 'S' . str_pad($subscription_history_id, 6, '0', STR_PAD_LEFT) : $invoice_data['name']; // pick a tax rate for this automatic invoice. $invoice_data['total_tax_name'] = isset($subscription['settings']) && isset($subscription['settings']['tax_name']) ? $subscription['settings']['tax_name'] : ''; $invoice_data['total_tax_rate'] = isset($subscription['settings']) && isset($subscription['settings']['tax_amount']) ? $subscription['settings']['tax_amount'] : ''; $invoice_data['tax_type'] = isset($subscription['settings']) && isset($subscription['settings']['tax_type']) ? $subscription['settings']['tax_type'] : module_config::c('invoice_tax_type', 0); $invoice_data['invoice_template_email'] = isset($subscription['settings']) && isset($subscription['settings']['invoice_template_email']) ? $subscription['settings']['invoice_template_email'] : ''; $invoice_data['invoice_template_print'] = isset($subscription['settings']) && isset($subscription['settings']['invoice_template_print']) ? $subscription['settings']['invoice_template_print'] : ''; $invoice_data['invoice_invoice_item'] = array('new' => array('description' => $members_subscriptions[$subscription_id]['name'] . $time_period, 'hourly_rate' => $amount, 'completed' => 1, 'manual_task_type' => _TASK_TYPE_AMOUNT_ONLY, 'date_done' => $date)); $invoice_id = module_invoice::save_invoice('new', $invoice_data); if ($invoice_id) { // limit payment methods if this has been set in the options area: $payment_methods = handle_hook('get_payment_methods'); foreach ($payment_methods as &$payment_method) { if ($payment_method->is_enabled()) { $enabled = isset($subscription['settings']['payment_methods'][$payment_method->module_name]) && $subscription['settings']['payment_methods'][$payment_method->module_name] ? true : (isset($subscription['settings']['payment_methods']) ? false : true); if ($enabled) { $payment_method->set_allowed_for_invoice($invoice_id, 1); } else { $payment_method->set_allowed_for_invoice($invoice_id, 0); } } } update_insert('subscription_history_id', $subscription_history_id, 'subscription_history', array('invoice_id' => $invoice_id)); module_invoice::add_history($invoice_id, 'Created invoice from subscription #' . str_pad($subscription_history_id, 6, '0', STR_PAD_LEFT) . ' from ' . $owner_table . ' ID# ' . $owner_id); self::update_next_due_date($subscription_id, $owner_table, $owner_id); } else { set_error('failed to create subscription invoice'); } return $invoice_id; }
public function run_cron($debug = false) { // check for payments. $sql = "SELECT * FROM `" . _DB_PREFIX . "invoice_payment` ip WHERE 1 "; $sql .= " AND `method` = 'paynl' "; $sql .= " AND `date_paid` = '0000-00-00' "; $sql .= " AND `other_id` != '' "; foreach (qa($sql) as $payment) { // check api status: $strUrl = 'https://*****:*****@rest-api.pay.nl/v5/Transaction/info/json?'; $arrArguments = array(); $arrArguments['transactionId'] = $payment['other_id']; # Prepare and call API URL $strUrl .= http_build_query($arrArguments); if ($debug) { echo "Checking URL {$strUrl} <br>\n"; $jsonResult = file_get_contents($strUrl); } else { $jsonResult = @file_get_contents($strUrl); } $json = @json_decode($jsonResult, true); if ($debug) { echo "Got result: <br>\n"; print_r($json); } if ($json && isset($json['paymentDetails']) && isset($json['paymentDetails']['stateName']) && isset($json['paymentDetails']['amount'])) { module_paymethod_paynl::add_payment_data($payment['invoice_payment_id'], 'log', "PayNL Status " . $json['paymentDetails']['stateName'] . ": \n " . var_export($json, true)); switch ($json['paymentDetails']['stateName']) { case 'PENDING': // defauly, still waiting for payment. break; case 'PAID': update_insert("invoice_payment_id", $payment['invoice_payment_id'], "invoice_payment", array('date_paid' => date('Y-m-d'), 'amount' => $json['paymentDetails']['amount'] / 100, 'other_id' => '')); module_invoice::save_invoice($payment['invoice_id'], array()); break; case 'CANCEL': update_insert("invoice_payment_id", $payment['invoice_payment_id'], "invoice_payment", array('other_id' => '')); module_invoice::save_invoice($payment['invoice_id'], array()); send_error('PayNL payment cancelled for invoice: ' . module_invoice::link_open($payment['invoice_id'], true)); break; } } else { module_paymethod_paynl::add_payment_data($payment['invoice_payment_id'], 'log', "PayNL Status ERROR: \n " . $jsonResult); } } }
function handle_paypal_ipn() { ob_end_clean(); if (!isset($_REQUEST['custom'])) { return; } $paypal_bits = explode("|", $_REQUEST['custom']); $user_id = (int) $paypal_bits[0]; $payment_id = (int) $paypal_bits[1]; $invoice_id = (int) $paypal_bits[2]; $invoice_payment_subscription_id = false; if (count($paypal_bits) == 4) { // normal IPN, single payment. } else { if (count($paypal_bits) == 5) { // subscription IPN, with subscription id. $invoice_payment_subscription_id = (int) $paypal_bits[3]; $invoice_payment_subscription = get_single('invoice_payment_subscription', 'invoice_payment_subscription_id', $invoice_payment_subscription_id); } } //send_error('bad?'); if ($payment_id && $invoice_id) { $hash = $this->paypal_custom($user_id, $payment_id, $invoice_id, $invoice_payment_subscription_id); if ($hash != $_REQUEST['custom']) { send_error("PayPal IPN Error (incorrect hash) it should be " . $hash); exit; } /*$sql = "SELECT * FROM `"._DB_PREFIX."user` WHERE user_id = '$user_id' LIMIT 1"; $res = qa($sql); if($res){ $user = array_shift($res); if($user && $user['user_id'] == $user_id){*/ // check for payment exists $payment = module_invoice::get_invoice_payment($payment_id); $invoice = module_invoice::get_invoice($invoice_id); if ($payment && $invoice) { /*if(isset($_REQUEST['fakepay'])){ if($invoice_payment_subscription_id){ // we have a subscription payment. woo! // this gets a bit tricky, we have to work out if the invoice has been generated for this subscription yet. // if this invoice hasn't been generated yet then we have to generate it. // pass this back to the invoice class so we can reuse this feature in the future. $data = module_invoice::create_new_invoice_for_subscription_payment($invoice_id, $payment_id, $invoice_payment_subscription_id); if($data && $data['invoice_id'] && $data['invoice_payment_id']){ $next_time = time(); $next_time = strtotime('+'.abs((int)$invoice_payment_subscription['days']).' days',$next_time); $next_time = strtotime('+'.abs((int)$invoice_payment_subscription['months']).' months',$next_time); $next_time = strtotime('+'.abs((int)$invoice_payment_subscription['years']).' years',$next_time); update_insert('invoice_payment_subscription_id',$invoice_payment_subscription_id,'invoice_payment_subscription',array( 'date_last_pay' => date('Y-m-d'), 'date_next' => date('Y-m-d',$next_time), )); $new_payment_details = array( 'date_paid' => date('Y-m-d'), 'amount' => $_REQUEST['mc_gross'], 'method' => 'PayPal (Subscription)', 'invoice_payment_subscription_id' => $invoice_payment_subscription_id, ); foreach(array('fee_percent','fee_amount','fee_description','fee_total') as $fee_field){ if(isset($payment[$fee_field])) { $new_payment_details[ $fee_field ] = $payment[ $fee_field ]; } } update_insert("invoice_payment_id",$data['invoice_payment_id'],"invoice_payment",$new_payment_details); module_invoice::save_invoice($data['invoice_id'],array()); echo "Successful Subscription Payment!"; }else{ send_error("PayPal IPN Subscription Error (failed to generate new invoice!) ".var_export($result,true)); } }else{ // mark a normal payment as paid update_insert("invoice_payment_id",$payment_id,"invoice_payment",array( 'date_paid' => date('Y-m-d'), 'amount' => $_REQUEST['mc_gross'], 'method' => 'PayPal (IPN)', )); module_invoice::save_invoice($invoice_id,array()); echo "Successful Payment!"; } echo 'fakepay done';exit; }*/ $invoice_currency = module_config::get_currency($invoice['currency_id']); $invoice_currency_code = $invoice_currency['code']; // check correct business if (!$_REQUEST['business'] && $_REQUEST['receiver_email']) { $_REQUEST['business'] = $_REQUEST['receiver_email']; } if ($_REQUEST['business'] != module_config::c('payment_method_paypal_email', _ERROR_EMAIL)) { send_error('PayPal error! Paid the wrong business name. ' . $_REQUEST['business'] . ' instead of ' . module_config::c('payment_method_paypal_email', _ERROR_EMAIL)); exit; } // check correct currency if ($invoice_currency_code && $_REQUEST['mc_currency'] != $invoice_currency_code) { send_error('PayPal error! Paid the wrong currency code. ' . $_REQUEST['mc_currency'] . ' instead of ' . $invoice_currency_code); exit; } switch ($_REQUEST['txn_type']) { // handle subscriptions first. // https://www.paypal.com/au/cgi-bin/webscr?cmd=p/acc/ipn-subscriptions-outside case "subscr_signup": // started! we update the start date of this one. if ($invoice_payment_subscription_id) { update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('status' => _INVOICE_SUBSCRIPTION_ACTIVE, 'date_start' => date('Y-m-d'))); } break; case "subscr_cancel": case "subscr_failed": case "subscr_eot": if ($invoice_payment_subscription_id) { update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('status' => _INVOICE_SUBSCRIPTION_FAILED)); } break; break; case "subscr_payment": case "web_accept": if ($_REQUEST['payment_status'] == "Canceled_Reversal" || $_REQUEST['payment_status'] == "Refunded") { // funky refund!! oh noes!! // TODO: store this in the database as a negative payment... should be easy. // populate $_REQUEST vars then do something like $payment_history_id = update_insert("payment_history_id","new","payment_history"); send_error("PayPal Error! The payment {$payment_id} has been refunded or reversed! BAD BAD! You have to follup up customer for money manually now."); } else { if ($_REQUEST['payment_status'] == "Completed") { // payment is completed! yeye getting closer... // running in paypal sandbox or not? //$sandbox = (self::is_sandbox())?"sandbox.":''; // quick check we're not getting a fake payment request. $url = 'https://www.' . (self::is_sandbox() ? 'sandbox.' : '') . 'paypal.com/cgi-bin/webscr'; $result = self::fsockPost($url, $_POST); //send_error('paypal sock post: '.$url."\n\n".var_export($result,true)); if (eregi("VERIFIED", $result)) { // finally have everything. // mark the payment as completed. if ($invoice_payment_subscription_id) { // we have a subscription payment. woo! // this gets a bit tricky, we have to work out if the invoice has been generated for this subscription yet. // if this invoice hasn't been generated yet then we have to generate it. // pass this back to the invoice class so we can reuse this feature in the future. $data = module_invoice::create_new_invoice_for_subscription_payment($invoice_id, $payment_id, $invoice_payment_subscription_id); if ($data && $data['invoice_id'] && $data['invoice_payment_id']) { $next_time = time(); $next_time = strtotime('+' . abs((int) $invoice_payment_subscription['days']) . ' days', $next_time); $next_time = strtotime('+' . abs((int) $invoice_payment_subscription['months']) . ' months', $next_time); $next_time = strtotime('+' . abs((int) $invoice_payment_subscription['years']) . ' years', $next_time); update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('date_last_pay' => date('Y-m-d'), 'date_next' => date('Y-m-d', $next_time))); $new_payment_details = array('date_paid' => date('Y-m-d'), 'amount' => $_REQUEST['mc_gross'], 'method' => 'PayPal (Subscription)', 'invoice_payment_subscription_id' => $invoice_payment_subscription_id); foreach (array('fee_percent', 'fee_amount', 'fee_description', 'fee_total') as $fee_field) { if (isset($payment[$fee_field])) { $new_payment_details[$fee_field] = $payment[$fee_field]; } } update_insert("invoice_payment_id", $data['invoice_payment_id'], "invoice_payment", $new_payment_details); module_invoice::save_invoice($data['invoice_id'], array()); echo "Successful Subscription Payment!"; } else { send_error("PayPal IPN Subscription Error (failed to generate new invoice!) " . var_export($result, true)); } } else { // mark a normal payment as paid update_insert("invoice_payment_id", $payment_id, "invoice_payment", array('date_paid' => date('Y-m-d'), 'amount' => $_REQUEST['mc_gross'], 'method' => 'PayPal (IPN)')); module_invoice::save_invoice($invoice_id, array()); echo "Successful Payment!"; } /*// send customer an email thanking them for their payment. $sql = "SELECT * FROM "._DB_PREFIX."users WHERE user_id = '"._ADMIN_USER_ID."'"; $res = qa($sql); $admin = array_shift($res); $from_email = $admin['email']; $from_name = $admin['real_name']; $mail_content = "Dear ".$user['real_name'].", \n\n"; $mail_content .= "Your ".dollar($payment['outstanding'])." payment for '".$payment['description']."' has been processed. \n\n"; $mail_content .= "We have successfully recorded your ".dollar($_REQUEST['mc_gross'])." payment in our system.\n\n"; $mail_content .= "You will receive another email shortly from PayPal with details of the transaction.\n\n"; $mail_content .= "Kind Regards,\n\n"; $mail_content .= $from_name."\n".$from_email; send_error("PayPal SUCCESS!! User has paid you ".$_REQUEST['mc_gross']." we have recorded this against the payment and sent them an email"); //$this->send_email( $payment_id, $user['email'], $mail_content, "Payment Successful", $from_email, $from_name ); send_email($user['email'], "Payment Successful", $mail_content, array("FROM"=>$from_email,"FROM_NAME"=>$from_name)); */ // check if it's been paid in full.. } else { send_error("PayPal IPN Error (paypal rejected the payment!) " . var_export($result, true)); } } else { send_error("PayPal info: This payment is not yet completed, this usually means it's an e-cheque, follow it up in a few days if you dont hear anything. This also means you may have to login to paypal and 'Accept' the payment. So check there first."); } } break; default: send_error("PayPal IPN Error (unknown transaction t ype!) "); break; } } else { send_error("PayPal IPN Error (no payment found in database!)"); } /*}else{ send_error("PayPal IPN Error (error with user that was found in database..)"); } }else{ send_error("PayPal IPN Error (no user found in database #1)"); }*/ } else { send_error("PayPal IPN Error (no payment or invoice id found)"); } exit; }
public function external_hook($hook) { switch ($hook) { case 'event_ipn': require_once 'includes/plugin_paymethod_stripe/stripe-php/lib/Stripe.php'; $stripe = array("secret_key" => module_config::c('payment_method_stripe_secret_key'), "publishable_key" => module_config::c('payment_method_stripe_publishable_key')); Stripe::setApiKey($stripe['secret_key']); $body = @file_get_contents('php://input'); $event_json = json_decode($body); ob_start(); // echo "INPUT: <br>\n"; // print_r($body); // echo "<br><br>\n"; echo "UCM STRIPE DEBUG:<br><br>JSON: <br>\n"; print_r($event_json); echo "<br><br>\n"; $event_id = $event_json->id; try { $event = Stripe_Event::retrieve($event_id); // This will send receipts on succesful invoices if ($event->type == 'charge.succeeded' && $event->data->object->invoice) { $paid_amount = $event->data->object->amount / 100; // get the invoice. $invoice = Stripe_Invoice::retrieve($event->data->object->invoice); echo "INVOICE: <br>\n"; print_r($invoice); echo "<br><br>\n"; if ($invoice && $invoice->subscription && $invoice->paid) { // this payment was for a subscription! which one though? $customer = Stripe_Customer::retrieve($invoice->customer); echo "CUSTOMER: <br>\n"; print_r($customer); echo "<br><br>\n"; $subscription = $customer->subscriptions->retrieve($invoice->subscription); echo "SUBSCRIPTION: <br>\n"; print_r($subscription); echo "<br><br>\n"; // now we have the Customer and Subscription we can look through our invoice_payment_subscription table for those values. /*update_insert('invoice_payment_subscription_id',$invoice_payment_subscription_id,'invoice_payment_subscription',array( 'status' => _INVOICE_SUBSCRIPTION_ACTIVE, 'date_start' => date('Y-m-d'), // we also have to store the stripe details here so we can easily search for them later on. 'stripe_customer' => $stripe_customer->id, 'stripe_subscription' => $stripe_subscription->id, ));*/ $invoice_payment_subscription = get_single('invoice_payment_subscription', array('stripe_customer', 'stripe_subscription'), array($customer->id, $subscription->id)); if ($invoice_payment_subscription) { // FIND THE linked invoice_payment for this original invoice payment subscription, this allows us to perform the same creatE_new_invoice as paypal below: $invoice_payment_subscription_id = $invoice_payment_subscription['invoice_payment_subscription_id']; $invoice_payment = get_single('invoice_payment', 'invoice_payment_subscription_id', $invoice_payment_subscription_id); if ($invoice_payment) { $payment_id = $invoice_payment['invoice_payment_id']; $invoice_id = $invoice_payment['invoice_id']; // we have a subscription payment. woo! // this gets a bit tricky, we have to work out if the invoice has been generated for this subscription yet. // if this invoice hasn't been generated yet then we have to generate it. // pass this back to the invoice class so we can reuse this feature in the future. $data = module_invoice::create_new_invoice_for_subscription_payment($invoice_id, $payment_id, $invoice_payment_subscription_id); if ($data && $data['invoice_id'] && $data['invoice_payment_id']) { $next_time = time(); $next_time = strtotime('+' . abs((int) $invoice_payment_subscription['days']) . ' days', $next_time); $next_time = strtotime('+' . abs((int) $invoice_payment_subscription['months']) . ' months', $next_time); $next_time = strtotime('+' . abs((int) $invoice_payment_subscription['years']) . ' years', $next_time); update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('date_last_pay' => date('Y-m-d'), 'date_next' => date('Y-m-d', $next_time))); update_insert("invoice_payment_id", $data['invoice_payment_id'], "invoice_payment", array('date_paid' => date('Y-m-d'), 'amount' => $paid_amount, 'method' => 'Stripe (Subscription)', 'invoice_payment_subscription_id' => $invoice_payment_subscription_id)); module_paymethod_stripe::add_payment_data($data['invoice_payment_id'], 'log', "Payment Received via Webhook: " . var_export(array('event.type' => $event->type, 'invoice.id' => $invoice->id, 'subscription.id' => $subscription->id, 'customer.id' => $customer->id, '$invoice_payment_subscription_id' => $invoice_payment_subscription_id, '$invoice_payment_id' => $payment_id), true)); module_invoice::save_invoice($data['invoice_id'], array()); echo "Successful Subscription Payment For Invoice " . $data['invoice_id']; } else { send_error("Stripe Webhook Subscription Error (failed to generate new invoice!) " . var_export($data, true)); } } else { echo 'Failed to find matching invoice payment in db'; } } else { echo 'Failed to find matching subscription payment in db'; } } } } catch (Exception $e) { $body = $e->getJsonBody(); $err = $body['error']; $error = "Sorry: Webhook failed. <br><br>\n\n"; $error .= $err['message']; $error .= "\n\n\n" . var_export($e, true); echo $error; } $debug = ob_get_clean(); //mail('*****@*****.**','Stripe Webhook debug',$debug); if (module_config::c('stripe_payment_debug', 0)) { echo $debug; } echo "Thanks! (set stripe_payment_debug to 1 in UCM to see more data here)"; exit; break; case 'pay_subscription': $invoice_id = isset($_REQUEST['invoice_id']) ? $_REQUEST['invoice_id'] : false; $invoice_payment_id = isset($_REQUEST['invoice_payment_id']) ? $_REQUEST['invoice_payment_id'] : false; $invoice_payment_subscription_id = isset($_REQUEST['invoice_payment_subscription_id']) ? $_REQUEST['invoice_payment_subscription_id'] : false; $stripe_plan_id = isset($_REQUEST['stripe_plan_id']) ? $_REQUEST['stripe_plan_id'] : false; $user_id = isset($_REQUEST['user_id']) ? $_REQUEST['user_id'] : false; if ($invoice_id && $invoice_payment_id && $stripe_plan_id && $invoice_payment_subscription_id && $user_id && isset($_POST['stripeToken'])) { $user_data = module_user::get_user($user_id); $email = isset($_REQUEST['stripeEmail']) && strlen($_REQUEST['stripeEmail']) ? $_REQUEST['stripeEmail'] : $user_data['email']; if (!$email || !strpos($email, '@')) { die('Please ensure your user account has a valid email address before paying with stripe'); } $invoice_payment = get_single('invoice_payment', 'invoice_payment_id', $invoice_payment_id); $invoice_payment_subscription = get_single('invoice_payment_subscription', 'invoice_payment_subscription_id', $invoice_payment_subscription_id); if (!$invoice_payment || !$invoice_payment_subscription || $invoice_payment['invoice_id'] != $invoice_id || $invoice_payment['invoice_payment_subscription_id'] != $invoice_payment_subscription_id) { die('Invalid invoice payment subscription id'); } $invoice_payment_data = module_invoice::get_invoice_payment($invoice_payment_id); $invoice_data = module_invoice::get_invoice($invoice_id); if ($invoice_payment_data && $invoice_data && $invoice_id == $invoice_data['invoice_id'] && $invoice_payment_data['invoice_id'] == $invoice_data['invoice_id']) { $currency = module_config::get_currency($invoice_payment_data['currency_id']); $currency_code = $currency['code']; $description = isset($_REQUEST['description']) ? $_REQUEST['description'] : 'N/A'; $template = new module_template(); ob_start(); require_once 'includes/plugin_paymethod_stripe/stripe-php/lib/Stripe.php'; $stripe = array("secret_key" => module_config::c('payment_method_stripe_secret_key'), "publishable_key" => module_config::c('payment_method_stripe_publishable_key')); Stripe::setApiKey($stripe['secret_key']); try { // todo- search for existing customer based on email address??? // todo: check if adding new plan to existing customer work?? $stripe_customer = Stripe_Customer::create(array("card" => $_POST['stripeToken'], "email" => $email, 'metadata' => array('user_id' => $user_id))); if ($stripe_customer && $stripe_customer->id) { //} && $stripe_customer->subscriptions){ $stripe_subscription = $stripe_customer->subscriptions->create(array('plan' => $stripe_plan_id)); if ($stripe_subscription && $stripe_subscription->id) { update_insert('invoice_payment_subscription_id', $invoice_payment_subscription_id, 'invoice_payment_subscription', array('status' => _INVOICE_SUBSCRIPTION_ACTIVE, 'date_start' => date('Y-m-d'), 'stripe_customer' => $stripe_customer->id, 'stripe_subscription' => $stripe_subscription->id)); module_paymethod_stripe::add_payment_data($invoice_payment_id, 'log', "Started Stripe Subscription: " . var_export(array('customer.id' => $stripe_customer->id, 'plan.id' => $stripe_plan_id, 'subscription.id' => $stripe_subscription->id), true)); // success! // redirect to receipt page. redirect_browser(module_invoice::link_public_payment_complete($invoice_id)); } else { echo 'Failed to create subscription with stripe'; } } $error = "Something went wrong during stripe payment. Please confirm invoice payment went through: " . htmlspecialchars($description); send_error($error); echo $error; } catch (Stripe_CardError $e) { // The card has been declined $body = $e->getJsonBody(); $err = $body['error']; $error = "Sorry: Payment failed. <br><br>\n\n" . htmlspecialchars($description) . ". <br><br>\n\n"; $error .= $err['message']; echo $error; $error .= "\n\n\n" . var_export($err, true); send_error($error); } catch (Exception $e) { $body = $e->getJsonBody(); $err = $body['error']; $error = "Sorry: Payment failed. <br><br>\n\n" . htmlspecialchars($description) . ". <br><br>\n\n"; $error .= $err['message']; echo $error; $error .= "\n\n\n" . var_export($err, true); send_error($error); } $template->content = ob_get_clean(); echo $template->render('pretty_html'); exit; } } echo 'Error paying via Stripe'; exit; case 'pay': $invoice_id = isset($_REQUEST['invoice_id']) ? $_REQUEST['invoice_id'] : false; $invoice_payment_id = isset($_REQUEST['invoice_payment_id']) ? $_REQUEST['invoice_payment_id'] : false; if ($invoice_id && $invoice_payment_id && isset($_POST['stripeToken'])) { $invoice_payment_data = module_invoice::get_invoice_payment($invoice_payment_id); $invoice_data = module_invoice::get_invoice($invoice_id); if ($invoice_payment_data && $invoice_data && $invoice_id == $invoice_data['invoice_id'] && $invoice_payment_data['invoice_id'] == $invoice_data['invoice_id']) { $currency = module_config::get_currency($invoice_payment_data['currency_id']); $currency_code = $currency['code']; $description = _l('Payment for invoice %s', $invoice_data['name']); $template = new module_template(); ob_start(); include module_theme::include_ucm('includes/plugin_paymethod_stripe/pages/stripe_form.php'); $template->content = ob_get_clean(); echo $template->render('pretty_html'); exit; } } echo 'Error paying via Stripe'; exit; } }
* Package Date: 2015-11-25 02:55:20 * IP Address: 67.79.165.254 */ require_once 'includes/plugin_paymethod_stripe/stripe-php/lib/Stripe.php'; $stripe = array("secret_key" => module_config::c('payment_method_stripe_secret_key'), "publishable_key" => module_config::c('payment_method_stripe_publishable_key')); Stripe::setApiKey($stripe['secret_key']); if (isset($_POST['stripeToken']) && isset($invoice_payment_data) && $invoice_payment_data['amount'] > 0) { $token = $_POST['stripeToken']; // Create the charge on Stripe's servers - this will charge the user's card try { $charge = Stripe_Charge::create(array("amount" => $invoice_payment_data['amount'] * 100, "currency" => $currency_code, "card" => $token, "description" => $description)); if ($charge && $charge->paid && $charge->captured) { // successfully paid! update_insert("invoice_payment_id", $invoice_payment_id, "invoice_payment", array('date_paid' => date('Y-m-d'), 'amount' => $charge->amount > 0 ? $charge->amount / 100 : 0, 'method' => 'Stripe')); module_paymethod_stripe::add_payment_data($invoice_payment_id, 'log', "Successfully paid: " . var_export($charge, true)); module_invoice::save_invoice($invoice_id, array()); // success! // redirect to receipt page. redirect_browser(module_invoice::link_receipt($invoice_payment_id)); } else { $error = "Something went wrong during strip payment. Please confirm invoice payment went through: " . htmlspecialchars($description); send_error($error); echo $error; } } catch (Stripe_CardError $e) { // The card has been declined $body = $e->getJsonBody(); $err = $body['error']; $error = "Sorry: Payment failed. <br><br>\n\n" . htmlspecialchars($description) . ". <br><br>\n\n"; $error .= $err['message']; echo $error;
public function generate_priority_invoice($ticket_id) { // call the invoice module and create an invoice for this ticket. // once this invoice is paid it will do a callback to the ticket. $ticket_data = $this->get_ticket($ticket_id); // check if no invoice exists. if (!$ticket_data['invoice_id']) { $task_name = module_config::c('ticket_priority_invoice_task', 'Priority Support Ticket'); $task_cost = module_config::c('ticket_priority_cost', 10); $task_currency = module_config::c('ticket_priority_currency', 1); // we do this hack so that the customer can have different invoice templates for support tickets. $old_customer_id = isset($_REQUEST['customer_id']) ? $_REQUEST['customer_id'] : false; $_REQUEST['customer_id'] = $ticket_data['customer_id']; $invoice_data = module_invoice::get_invoice('new', true); $_REQUEST['customer_id'] = $old_customer_id; // todo - if the ticket customer_id changes (a feature for later on) then we have to update any of these invoices. // maybe it's best we don't have a customer_id here? hmmmmmmmmmmmmmmmmmm // the user will have to enter their own invoice details anyway. // maybe we can read the customer_id from the user table if there is no customer_id in the invoice table? that might fix some things. $invoice_data['customer_id'] = $ticket_data['customer_id']; $invoice_data['user_id'] = $ticket_data['user_id']; $invoice_data['currency_id'] = $task_currency; $invoice_data['date_sent'] = date('Y-m-d'); $invoice_data['name'] = 'T' . $this->ticket_number($ticket_id); // don't set an automatic reminder on invoices $invoice_data['overdue_email_auto'] = module_config::c('ticket_priority_auto_overdue_email', 0); // pick a tax rate for this automatic invoice. //if(module_config::c('ticket_priority_tax_name','')){ $invoice_data['total_tax_name'] = module_config::c('ticket_priority_tax_name', ''); //} //if(module_config::c('ticket_priority_tax_rate','')){ $invoice_data['total_tax_rate'] = module_config::c('ticket_priority_tax_rate', ''); //} $invoice_data['invoice_invoice_item'] = array('new' => array('description' => $task_name . ' - ' . _l('Ticket #' . $this->ticket_number($ticket_id)), 'hourly_rate' => $task_cost, 'manual_task_type' => _TASK_TYPE_AMOUNT_ONLY, 'completed' => 1)); $invoice_id = module_invoice::save_invoice('new', $invoice_data); update_insert('ticket_id', $ticket_id, 'ticket', array('invoice_id' => $invoice_id)); module_invoice::add_history($invoice_id, 'Created invoice from support ticket #' . $this->ticket_number($ticket_id)); return $invoice_id; } return $ticket_data['invoice_id']; }
function handle_multisafepay_ipn() { ob_end_clean(); ini_set('display_errors', false); include 'MultiSafepay.combined.php'; $msp = new MultiSafepay(); // transaction id (same as the transaction->id given in the transaction request) $transactionid = isset($_GET['transactionid']) ? $_GET['transactionid'] : false; if (!$transactionid) { send_error('No MultiSafepay transaction ID'); } $multisafepay_bits = explode("|", $transactionid); $user_id = $multisafepay_bits[0]; $payment_id = (int) $multisafepay_bits[1]; $invoice_id = (int) $multisafepay_bits[2]; //send_error('bad?'); //send_error($payment_id.' multisafepay IPN check started',var_export($_REQUEST,true)); if ($payment_id && $invoice_id) { $hash = $this->multisafepay_custom($user_id, $payment_id, $invoice_id); if ($hash != $transactionid) { send_error("Multisafepay IPN Error (incorrect hash)"); exit; } $user_id = (int) $user_id; // sometimes userid is '' $paymetn_history = get_single('invoice_payment', 'invoice_payment_id', $payment_id); if (!$paymetn_history) { send_error("Unknown Multisafe Payment - maybe a history was deleted?"); exit; } // (notify.php?type=initial is used as notification_url and should output a link) $initial = isset($_GET['type']) && $_GET['type'] == "initial"; /* * Merchant Settings */ // $msp->test = MSP_TEST_API; // $msp->merchant['account_id'] = MSP_ACCOUNT_ID; // $msp->merchant['site_id'] = MSP_SITE_ID; // $msp->merchant['site_code'] = MSP_SITE_CODE; $msp->test = self::is_sandbox(); $msp->merchant['account_id'] = module_config::c('payment_method_multisafepay_account', ''); $msp->merchant['site_id'] = module_config::c('payment_method_multisafepay_site_id', ''); $msp->merchant['site_code'] = module_config::c('payment_method_multisafepay_side_code', ''); /* * Transaction Details */ $msp->transaction['id'] = $transactionid; // returns the status $status = $msp->getStatus(); if ($msp->error && !$initial) { // only show error if we dont need to display the link echo "Error " . $msp->error_code . ": " . $msp->error; exit; } //send_error($payment_id.' MultiSafepay Status of '.$status,var_export($_REQUEST,true)); $payment_history_data = isset($paymetn_history['data']) && strlen($paymetn_history['data']) ? unserialize($paymetn_history['data']) : array(); if (!is_array($payment_history_data)) { $payment_history_data = array(); } if (!isset($payment_history_data['log'])) { $payment_history_data['log'] = array(); } $payment_history_data['log'][] = 'Payment ' . $status . ' at ' . print_date(time(), true); update_insert("invoice_payment_id", $payment_id, "invoice_payment", array('data' => serialize($payment_history_data))); switch ($status) { case "initialized": // waiting break; case "completed": // payment complete update_insert("invoice_payment_id", $payment_id, "invoice_payment", array('date_paid' => date('Y-m-d'), 'method' => 'MultiSafepay')); module_invoice::save_invoice($invoice_id, array()); break; case "uncleared": // waiting (credit cards or direct debit) break; case "void": // canceled break; case "declined": // declined break; case "refunded": // refunded send_error("Multisafepay Error! The payment {$payment_id} has been refunded or reversed! BAD BAD! You have to follup up customer for money manually now."); break; case "expired": // expired break; default: } if ($initial) { // displayed at the last page of the transaction proces (if no redirect_url is set) echo '<a href="' . module_invoice::link_public($invoice_id) . '">Return to Invoice</a>'; } else { // link to notify.php for MultiSafepay back-end (for delayed payment notifications) // backend expects an "ok" if no error occurred echo "ok"; } } else { send_error('No bits in transaction id'); } exit; $multisafepay_bits = explode("|", $_REQUEST['custom']); $user_id = (int) $multisafepay_bits[0]; $payment_id = (int) $multisafepay_bits[1]; $invoice_id = (int) $multisafepay_bits[2]; //send_error('bad?'); if ($user_id && $payment_id && $invoice_id) { $hash = $this->multisafepay_custom($user_id, $payment_id, $invoice_id); if ($hash != $_REQUEST['custom']) { send_error("Multisafepay IPN Error (incorrect hash)"); exit; } $sql = "SELECT * FROM `" . _DB_PREFIX . "user` WHERE user_id = '{$user_id}' LIMIT 1"; $res = qa($sql); if ($res) { $user = array_shift($res); if ($user && $user['user_id'] == $user_id) { // check for payment exists $payment = module_invoice::get_invoice_payment($payment_id); $invoice = module_invoice::get_invoice($invoice_id); if ($payment && $invoice) { $invoice_currency = module_config::get_currency($invoice['currency_id']); $invoice_currency_code = $invoice_currency['code']; // check correct business if (!$_REQUEST['business'] && $_REQUEST['receiver_email']) { $_REQUEST['business'] = $_REQUEST['receiver_email']; } if ($_REQUEST['business'] != module_config::c('payment_method_multisafepay_email', _ERROR_EMAIL)) { send_error('Multisafepay error! Paid the wrong business name. ' . $_REQUEST['business'] . ' instead of ' . module_config::c('payment_method_multisafepay_email', _ERROR_EMAIL)); exit; } // check correct currency if ($invoice_currency_code && $_REQUEST['mc_currency'] != $invoice_currency_code) { send_error('Multisafepay error! Paid the wrong currency code. ' . $_REQUEST['mc_currency'] . ' instead of ' . $invoice_currency_code); exit; } if ($_REQUEST['payment_status'] == "Canceled_Reversal" || $_REQUEST['payment_status'] == "Refunded") { // funky refund!! oh noes!! // TODO: store this in the database as a negative payment... should be easy. // populate $_REQUEST vars then do something like $payment_history_id = update_insert("payment_history_id","new","payment_history"); send_error("Multisafepay Error! The payment {$payment_id} has been refunded or reversed! BAD BAD! You have to follup up customer for money manually now."); } else { if ($_REQUEST['payment_status'] == "Completed") { // payment is completed! yeye getting closer... switch ($_REQUEST['txn_type']) { case "web_accept": // running in multisafepay sandbox or not? //$sandbox = (self::is_sandbox())?"sandbox.":''; // quick check we're not getting a fake payment request. $url = 'https://www.' . (self::is_sandbox() ? 'sandbox.' : '') . 'multisafepay.com/cgi-bin/webscr'; $result = self::fsockPost($url, $_POST); //send_error('multisafepay sock post: '.$url."\n\n".var_export($result,true)); if (eregi("VERIFIED", $result)) { // finally have everything. // mark the payment as completed. update_insert("invoice_payment_id", $payment_id, "invoice_payment", array('date_paid' => date('Y-m-d'), 'amount' => $_REQUEST['mc_gross'], 'method' => 'Multisafepay (IPN)')); module_invoice::save_invoice($invoice_id, array()); echo "Successful Payment!"; } else { send_error("Multisafepay IPN Error (multisafepay rejected the payment!) " . var_export($result, true)); } break; case "subscr_signup": default: // TODO: support different payment methods later? like a monthly hosting fee.. send_error("Multisafepay IPN Error (we dont currently support this payment method: " . $_REQUEST['txn_type'] . ")"); break; } } else { send_error("Multisafepay info: This payment is not yet completed, this usually means it's an e-cheque, follow it up in a few days if you dont hear anything. This also means you may have to login to multisafepay and 'Accept' the payment. So check there first."); } } } else { send_error("Multisafepay IPN Error (no payment found in database!)"); } } else { send_error("Multisafepay IPN Error (error with user that was found in database..)"); } } else { send_error("Multisafepay IPN Error (no user found in database #1)"); } } else { send_error("Multisafepay IPN Error (no user id found)"); } exit; }
public function external_hook($hook) { switch ($hook) { case 'pay': // result is retured via ajax and displayed on the page. $invoice_id = isset($_REQUEST['invoice_id']) ? $_REQUEST['invoice_id'] : false; $invoice_payment_id = isset($_REQUEST['invoice_payment_id']) ? $_REQUEST['invoice_payment_id'] : false; if ($invoice_id && $invoice_payment_id) { $invoice_payment_data = module_invoice::get_invoice_payment($invoice_payment_id); $invoice_data = module_invoice::get_invoice($invoice_id); if ($invoice_payment_data && $invoice_data && $invoice_id == $invoice_data['invoice_id'] && $invoice_payment_data['invoice_id'] == $invoice_data['invoice_id']) { $currency = module_config::get_currency($invoice_payment_data['currency_id']); $currency_code = $currency['code']; $description = _l('Payment for invoice %s', $invoice_data['name']); require_once 'includes/plugin_paymethod_authorize/anet_php_1.1.8/AuthorizeNet.php'; $transaction = new AuthorizeNetAIM(module_config::c('payment_method_authorize_api_login_id', ''), module_config::c('payment_method_authorize_transaction_key', '')); $transaction->setSandbox(module_config::c('payment_method_authorize_sandbox', 0)); $transaction->VERIFY_PEER = module_config::c('payment_method_authorize_ssl_verify', 1); $transaction->amount = $invoice_payment_data['amount']; // USD ONLY foreach (array("address", "allow_partial_auth", "amount", "auth_code", "authentication_indicator", "bank_aba_code", "bank_acct_name", "bank_acct_num", "bank_acct_type", "bank_check_number", "bank_name", "card_code", "card_num", "cardholder_authentication_value", "city", "company", "country", "cust_id", "customer_ip", "delim_char", "delim_data", "description", "duplicate_window", "duty", "echeck_type", "email", "email_customer", "encap_char", "exp_date", "fax", "first_name", "footer_email_receipt", "freight", "header_email_receipt", "invoice_num", "last_name", "line_item", "login", "method", "phone", "po_num", "recurring_billing", "relay_response", "ship_to_address", "ship_to_city", "ship_to_company", "ship_to_country", "ship_to_first_name", "ship_to_last_name", "ship_to_state", "ship_to_zip", "split_tender_id", "state", "tax", "tax_exempt", "test_request", "tran_key", "trans_id", "type", "version", "zip") as $possible_value) { if (isset($_POST[$possible_value])) { $transaction->setField($possible_value, $_POST[$possible_value]); } } $transaction->setField('card_num', isset($_POST['number']) ? $_POST['number'] : ''); $transaction->setField('exp_date', $_POST['month'] . '/' . $_POST['year']); $transaction->setField('card_code', $_POST['cvv']); //$transaction->card_num = isset($_POST['number']) ? $_POST['number'] : ''; //$transaction->exp_date = $_POST['month'].'/'.$_POST['year']; //$transaction->card_code = $_POST['cvv']; $response = $transaction->authorizeAndCapture(); if ($response->approved) { // echo "<h1>Success! The test credit card has been charged!</h1>"; // echo "Transaction ID: " . $response->transaction_id; update_insert("invoice_payment_id", $invoice_payment_id, "invoice_payment", array('date_paid' => date('Y-m-d'))); module_paymethod_stripe::add_payment_data($invoice_payment_id, 'log', "Successfully paid: " . var_export($response, true)); module_invoice::save_invoice($invoice_id, array()); // success! // redirect to receipt page. redirect_browser(module_invoice::link_receipt($invoice_payment_id)); } else { echo isset($response->error_message) ? $response->error_message : (isset($response->response_reason_text) ? $response->response_reason_text : var_export($response, true)); } exit; } } echo 'Error paying via Authorize'; exit; } }