function do_renew() { global $_SESSION; global $_amember_id; global $config, $db, $t, $vars, $plugins, $error; $member_id = intval($_amember_id); $error = array_merge((array) $error, (array) plugin_validate_member_form($vars)); if (count($error)) { $t->assign('error', $error); return; } $vars['product_id'] = is_array($vars['product_id']) ? array_filter(array_map('intval', $vars['product_id'])) : intval($vars['product_id']); if (!$vars['product_id']) { $t->assign('error', _MEMBER_SELECT_PRODUCT); return; } if ($vars['coupon'] != '' && $config['use_coupons']) { $coupon = $db->coupon_get($vars['coupon'], $_SESSION[_amember_id]); if (is_string($coupon)) { $t->assign('error', $coupon); return; } } $pc =& new PriceCalculator(); $pc->addProducts($vars['product_id']); if ($config['use_coupons'] && $vars['coupon'] != '') { $coupon = $db->coupon_get($vars['coupon'], $_SESSION[_amember_id]); if ($coupon['coupon_id']) { $pc->setCouponDiscount($coupon['discount'], split(',', trim($coupon['product_id']))); } } $pc->setPriceFieldsByPaysys($vars['paysys_id']); $pc->setTax(get_member_tax($member_id)); $terms =& $pc->calculate(); $price = $terms->total; if ($price == 0 && !product_get_trial($vars['product_id']) && ($terms->discount > 0 && !$coupon['is_recurring'] || !$terms->discount) && in_array('free', $plugins['payment'])) { $vars['paysys_id'] = 'free'; } if ($config['product_paysystem']) { $pr = get_product(is_array($vars['product_id']) ? $vars['product_id'][0] : $vars['product_id']); $vars['paysys_id'] = $pr->config['paysys_id']; } if (!$vars['paysys_id']) { $t->assign('error', _MEMBER_SELECT_PAYMENT); return; } //check for agreement $display_agreement = 0; foreach ((array) $vars['product_id'] as $pid) { $product = $db->get_product($pid); if ($product['need_agreement']) { $display_agreement++; } } $member = $db->get_user($member_id); if ($display_agreement && !$member['data']['i_agree'] && !$vars['i_agree']) { display_agreement(serialize($vars)); // defined in the product.inc.php exit; } if ($vars['i_agree'] && !$member['data']['i_agree']) { $member['data']['i_agree']++; $db->update_user($member_id, $member); } /// do { // for easy exit using break; $paysys_id = $vars['paysys_id']; $product_id = $vars['product_id']; if (!is_array($product_id)) { $product_id = array($product_id); } foreach ((array) $vars['product_id'] as $pid) { $error = check_product_scope($pid, $_amember_id); if ($error) { break; } } if ($error = check_product_requirements($product_id, get_product_requirements_for_member($_amember_id))) { break; } // if ($terms->discount > 0) $vars['COUPON_CODE'] = $vars['coupon']; global $payment_additional_fields; $additional_values = array(); foreach ($payment_additional_fields as $f) { $fname = $f['name']; if (isset($vars[$fname])) { $additional_values[$fname] = $vars[$fname]; } } $additional_values['COUPON_DISCOUNT'] = $terms->discount; $additional_values['TAX_AMOUNT'] = $terms->tax; $taxes = $prices = array(); foreach ($terms->lines as $pid => $line) { $prices[$pid] = $line->total; if ($line->tax) { $taxes[$pid] = $line->tax; } } $additional_values['TAXES'] = $taxes; $product =& get_product($product_id[0]); $begin_date = $product->get_start($member_id); $expire_date = $product->get_expire($begin_date, null, $terms); //yyyy-mm-dd // add payment $payment_id = $db->add_waiting_payments($member_id, $product_id, $paysys_id, $price, $prices, $begin_date, $expire_date, $vars, $additional_values); $error = plugin_do_payment($paysys_id, $payment_id, $member_id, is_array($product_id) ? $product_id[0] : $product_id, $price, $begin_date, $expire_date, $vars); if ($error) { $db->delete_payment($payment_id); break; } exit; } while (0); //if we here, error was occured $t->assign('error', $error); return; }
function cc_core_rebill($plugin, $dat = '', $running_from_cron = true, $repeat_declined = false) { global $config, $db, $t; if (!$config['use_cron'] && $running_from_cron) { $db->log_error("{$plugin} rebill can be run only with external cron"); } $amDb =& amDb(); if ($dat == '') { $dat = date('Y-m-d'); } $tomorrow = date('Y-m-d', strtotime($dat) + 3600 * 24); $pl =& instantiate_plugin('payment', $plugin); if (!method_exists($pl, 'cc_bill')) { fatal_error("This plugin ({$plugin}) is not handled by cc_core!"); } // check if another rebilling process is active // last status_tm / added_tm in rebill_log is < 5 minutes ago // to avoiding starting new process while a PHP rebill script runned // less than 10 minutes ago is still running if ($running_from_cron) { if ($last_rebill_log_id = $amDb->selectCell("SELECT MAX(rebill_log_id) FROM ?_rebill_log")) { $last_tm_diff = $amDb->selectCell("SELECT UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(IFNULL(status_tm, added_tm)) \n\t\t\t\tFROM ?_rebill_log WHERE rebill_log_id=?", $last_rebill_log_id); if ($last_tm_diff < 5 * 60) { $db->log_error("[Notice] cc_core_rebill({$plugin}, {$dat}) skipped because previous rebilling process still working ({$last_tm_diff} seconds ago)"); return; } } print ".\n"; // to avoid Apache's timeout } $payments = $db->get_expired_payments($dat, $dat, $plugin); $renewed = array(); $log = "{$plugin} Rebill\n"; foreach ($payments as $p) { if ($p['data']['CANCELLED']) { continue; } $member_id = $p['member_id']; $member = $db->get_user($member_id); $product_id = $p['product_id']; if ($renewed[$member_id][$product_id]++) { continue; } $product =& get_product($product_id); if (!$product->config['is_recurring']) { continue; } if ($product->config['rebill_times'] && !cc_core_check_rebill_times($product->config['rebill_times'], $p)) { continue; } // check if we've already tried to rebill the customer today $check = $repeat_declined ? "SUM(status = 0)" : "MAX(status IS NOT NULL)"; if ($amDb->selectCell("SELECT {$check} FROM ?_rebill_log\n\t\t\tWHERE payment_id = ? AND payment_date = ? ", $p['payment_id'], $dat)) { // retry on payment processor failure? todo, real tests needed continue; } $vars = array('RENEWAL_ORIG' => "RENEWAL_ORIG: {$p['payment_id']}"); $pc =& new PriceCalculator(); $pc->setTax(get_member_tax($member_id)); $coupon_code = $p['data'][0]['COUPON_CODE']; if ($config['use_coupons'] && $coupon_code != '') { $coupon = $db->coupon_get($coupon_code, null, 1); if ($coupon['coupon_id'] && $coupon['is_recurring']) { $pc->setCouponDiscount($coupon['discount'], split(',', trim($coupon['product_id']))); $vars['COUPON_CODE'] = $coupon_code; } } $pc->addProduct($product_id); $terms =& $pc->calculate(); $additional_values = array(); $additional_values['COUPON_DISCOUNT'] = $terms->discount; $additional_values['TAX_AMOUNT'] = $terms->tax; $payment_id = $db->add_waiting_payment($member_id, $product_id, $plugin, $terms->total, $dat, $product->get_expire($dat), $vars, $additional_values); $rebill_log_id = $amDb->query("INSERT INTO ?_rebill_log \n\t\t(payment_id, added_tm, payment_date, amount, rebill_payment_id)\n\t\tVALUES\n\t\t(?d, ?, ?, ?f, ?d)", $p['payment_id'], date('Y-m-d H:i:s'), $dat, $terms->total, $payment_id); $payment = $db->get_payment($payment_id); $cc_info = $member['data']; $cc_info['cc_number'] = amember_decrypt($cc_info['cc-hidden']); $x = list($res, $err_msg, $receipt_id, $log) = $pl->cc_bill($cc_info, $member, $payment['amount'], $product->config[$payment['paysys_id'] . '_currency'], $product->config['title'], CC_CHARGE_TYPE_RECURRING, $payment['payment_id'], $payment); foreach ($log as $v) { $payment['data'][] = $v; } $db->update_payment($payment['payment_id'], $payment); $amDb->query("UPDATE ?_rebill_log \n \tSET status = ?, status_tm = ?, status_msg = ? \n \tWHERE rebill_payment_id = ?d", $res, date('Y-m-d H:i:s'), $err_msg, $payment_id); switch ($res) { case CC_RESULT_SUCCESS: $err = $db->finish_waiting_payment($payment['payment_id'], $payment['paysys_id'], $receipt_id, $payment['amount'], '', cc_core_get_payer_id($vars, $member)); if ($err) { $db->log_error($err . ": payment_id = {$payment['payment_id']} (rebilling)"); } if ($config['cc_rebill_success']) { mail_rebill_success_member($member, $payment_id, $product); } break; case CC_RESULT_INTERNAL_ERROR: case CC_RESULT_DECLINE_TEMP: if ($pl->config['reattempt'] != '') { $new_expire = cc_core_prorate_subscription($p['payment_id'], $pl->config['reattempt'], $dat); } if ($config['cc_rebill_failed']) { mail_rebill_failed_member($member, $payment_id, $product, "{$err_msg}", $new_expire); } if ($config['cc_rebill_failed_admin']) { mail_rebill_failed_admin($member, $payment_id, $product, "{$err_msg}", $new_expire); } break; case CC_RESULT_DECLINE_PERM: if ($pl->config['reattempt'] != '') { $new_expire = cc_core_prorate_subscription($p['payment_id'], $pl->config['reattempt'], $dat); } if ($config['cc_rebill_failed']) { mail_rebill_failed_member($member, $payment_id, $product, "{$err_msg}", $new_expire); } if ($config['cc_rebill_failed_admin']) { mail_rebill_failed_admin($member, $payment_id, $product, "{$err_msg}", $new_expire); } // clean_cc_info($member); break; case CC_RESULT_IGNORE: break; default: $db->log_error("Unknown return from plugin_bill: {$res}"); } } }
function build_subscription_params($products, $total_price, $u, $invoice) { global $config, $db; $a = $p = $t = array(1 => '', 2 => '', 3 => ''); $was_recurring = 0; $pc =& new PriceCalculator(); $pc->setTax(get_member_tax($u['member_id'])); $payment = $db->get_payment($invoice); $coupon_code = $payment['data'][0]['COUPON_CODE']; $coupon = array(); if ($config['use_coupons'] && $coupon_code != '') { $coupon = $db->coupon_get($coupon_code); if ($coupon['coupon_id'] > 0) { $pc->setCouponDiscount($coupon['discount'], split(',', trim($coupon['product_id']))); } else { $coupon = array(); } } $rebill_times = $products[0]['rebill_times']; foreach ($products as $pr) { $pp = $pt = array(1 => '', 2 => '', 3 => ''); if ($pr['trial1_days'] != '') { list($pp[1], $pt[1]) = $this->get_days($pr['trial1_days']); } if ($pr['expire_days'] != '') { list($pp[3], $pt[3]) = $this->get_days($pr['expire_days']); } if (!$pr['is_recurring']) { //fatal_error(_PLUG_PAY_PAYPALR_FERROR7); //$a[1] += $pa[3]; // there is at least one recurring product if we went here } else { // recurring if ($was_recurring) { // check if it was compatible if (array_diff($p, $pp) || array_diff($t, $pt)) { fatal_error(_PLUG_PAY_PAYPALR_FERROR8); } if ($pr['rebill_times'] != $rebill_times) { fatal_error(_PLUG_PAY_PAYPALR_FERROR8); } } $p[1] = $pp[1]; $p[3] = $pp[3]; $t[1] = $pt[1]; $t[3] = $pt[3]; $was_recurring++; } } // calculate first trial - add both recurring, and non-recurring products here $pc->setPriceFields(array('trial1_price', 'price')); $need_trial1 = false; foreach ($products as $pr) { if ($pr['trial1_price'] || !$pr['is_recurring'] || $coupon['coupon_id'] && !$coupon['is_recurring']) { $need_trial1 = true; } $pc->addProduct($pr['product_id']); } if ($need_trial1) { $terms[1] = $pc->calculate(); $a[1] = $terms[1]->total; if (!$p[1]) { // we added trial because of discount or non-recurring product if ($rebill_times) { $rebill_times--; } // lets decrease rebill_times then! } } // calculate regular rate $pc->emptyProducts(); $pc->setPriceFields(array('price')); foreach ($products as $pr) { if ($pr['is_recurring']) { $pc->addProduct($pr['product_id']); } if (!$coupon['is_recurring']) { $pc->setCouponDiscount(null); } } $terms[3] = $pc->calculate(); $a[3] = $terms[3]->total; if ($a[1] && !$p[1]) { // trial1 price set, but trial 1 period did not $p[1] = $p[3]; $t[1] = $t[3]; } $taxes = array(); foreach (array(1, 2, 3) as $k) { if ($terms[$k]) { $taxes[$k] = $terms[$k]->tax; } } return array($a, $p, $t, $rebill_times, $taxes); }
function do_payment($payment_id, $member_id, $product_id, $price, $begin_date, $expire_date, &$vars) { global $config; global $db; $product = $db->get_product($product_id); $vars = array('SITEID' => $this->config['siteid'], 'ORDERID' => $payment_id, 'DESCRIPTION' => $product['title'], 'RETURNURL' => $config['root_url'] . "/plugins/payment/gspay/thanks.php", 'TEST' => $this->config['testing'] ? '<INPUT TYPE="HIDDEN" NAME="TransactionMode" VALUE="test">' : ''); $vars['RECURRING_FIELDS'] = ''; //******************* $pc =& new PriceCalculator(); $pc->setTax(get_member_tax($u['member_id'])); $pc->setPriceFields(array('trial1_price')); $p = $db->get_payment($payment_id); $coupon_code = $p['data'][0]['COUPON_CODE']; if ($config['use_coupons'] && $coupon_code != '') { $coupon = $db->coupon_get($coupon_code); $pc->setCouponDiscount($coupon['discount'], split(',', trim($coupon['product_id']))); } $pc->addProduct($product_id); $terms = $pc->calculate(); $trial_amount = $terms->total; //******************* $pc =& new PriceCalculator(); $pc->setTax(get_member_tax($u['member_id'])); $pc->setPriceFields(array('price')); if ($config['use_coupons'] && $coupon_code != '') { $coupon = $db->coupon_get($coupon_code); $pc->setCouponDiscount($coupon['discount'], split(',', trim($coupon['product_id']))); } $pc->addProduct($product_id); $terms = $pc->calculate(); $amount = $terms->total; //******************* //print_r($terms);die; if ($product['trial1_days']) { $product['trial1_days'] = $this->get_days($product['trial1_days']); } $product['expire_days'] = $this->get_days($product['expire_days']); if ($product->config['is_recurring']) { if ($product['trial1_days']) { if ($product['trial1_price']) { if ($config['use_coupons'] && $coupon_code != '') { $vars['RECURRING_FIELDS'] .= "\n\t\t\t\t\t\t<input type=\"hidden\" name=\"Amount\" value=\"{$trial_amount}\">"; } else { $vars['RECURRING_FIELDS'] .= "\n\t\t\t\t\t\t<input type=\"hidden\" name=\"Amount\" value=\"{$product['trial1_price']}\">"; } } else { if ($config['use_coupons'] && $coupon_code != '' && $coupon['is_recurring']) { $vars['RECURRING_FIELDS'] .= "\n\t\t\t\t\t\t<input type=\"hidden\" name=\"Amount\" value=\"{$amount}\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"TrialDuration\" value=\"{$product['trial1_days']}\">"; } else { $vars['RECURRING_FIELDS'] .= "\n\t\t\t\t\t\t<input type=\"hidden\" name=\"Amount\" value=\"{$product['price']}\">\n\t\t\t\t\t\t<input type=\"hidden\" name=\"TrialDuration\" value=\"{$product['trial1_days']}\">"; } } if ($config['use_coupons'] && $coupon_code != '' && $coupon['is_recurring']) { $vars['RECURRING_FIELDS'] .= "\n\t\t\t\t\t<input type=\"hidden\" name=\"RebillAmount\" value=\"{$amount}\">\n\t\t\t\t\t<input type=\"hidden\" name=\"Duration\" value=\"{$product['duration']}\">\n\t\t\t\t\t"; } else { $vars['RECURRING_FIELDS'] .= "\n\t\t\t\t\t<input type=\"hidden\" name=\"RebillAmount\" value=\"{$product['price']}\">\n\t\t\t\t\t<input type=\"hidden\" name=\"Duration\" value=\"{$product['duration']}\">\n\t\t\t\t\t"; } } else { if ($config['use_coupons'] && $coupon_code != '') { if ($coupon['is_recurring']) { $vars['RECURRING_FIELDS'] .= "\n\t\t\t\t\t<input type=\"hidden\" name=\"Amount\" value=\"{$amount}\">\n\t\t\t\t\t<input type=\"hidden\" name=\"RebillAmount\" value=\"{$amount}\">\n\t\t\t\t\t<input type=\"hidden\" name=\"Duration\" value=\"{$product['duration']}\">\n\t\t\t\t\t"; } else { $vars['RECURRING_FIELDS'] .= "\n\t\t\t\t\t<input type=\"hidden\" name=\"Amount\" value=\"{$amount}\">\n\t\t\t\t\t<input type=\"hidden\" name=\"RebillAmount\" value=\"{$product['price']}\">\n\t\t\t\t\t<input type=\"hidden\" name=\"Duration\" value=\"{$product['duration']}\">\n\t\t\t\t\t"; } } else { $vars['RECURRING_FIELDS'] .= "\n\t\t\t\t<input type=\"hidden\" name=\"Amount\" value=\"{$product['price']}\">\n\t\t\t\t<input type=\"hidden\" name=\"RebillAmount\" value=\"{$product['price']}\">\n\t\t\t\t<input type=\"hidden\" name=\"Duration\" value=\"{$product['duration']}\">\n\t\t\t\t"; } } } else { if ($config['use_coupons'] && $coupon_code != '') { $vars['RECURRING_FIELDS'] .= "\n\t\t\t<input type=\"hidden\" name=\"Amount\" value=\"{$amount}\">\n\t\t\t"; } else { $vars['RECURRING_FIELDS'] .= "\n\t\t\t<input type=\"hidden\" name=\"Amount\" value=\"{$product['price']}\">\n\t\t\t"; } } $t =& new_smarty(); $t->assign('vars', $vars); $t->display(dirname(__FILE__) . '/gspay.html'); }
function calculate_tax($product_id, $member_id, $amount, $incl_tax) { global $db; $pr = $db->get_product($product_id); // Not a subject of tax; if (!$pr['use_tax']) { ajaxResponse(array('tax' => 0, "errorCode" => 0)); } $tax_value = get_member_tax($member_id); if (!$tax_value) { ajaxResponse(array('tax' => 0, 'errorCode' => 0)); } // Got tax, now apply it to price: if ($incl_tax == 1) { $tax = $amount - $amount / (1 + $tax_value / 100); } else { $tax = $amount * $tax_value / 100; } ajaxResponse(array("tax" => sprintf("%01.2f", $tax), "errorCode" => 0)); }
function getBillingTerms($payment_id, $products) { global $config, $db; $terms = array(); $cnt = 0; $payment = $db->get_payment($payment_id); $u = $db->get_user($payment[member_id]); $coupon_code = $payment['data'][0]['COUPON_CODE']; $coupon = array(); if ($config['use_coupons'] && $coupon_code != '') { $coupon = $db->coupon_get($coupon_code); } $pc =& new PriceCalculator(); $pc->setTax(get_member_tax($u['member_id'])); foreach ($products as $p) { $po = get_product($p['product_id']); $pc->emptyProducts(); $terms[$cnt]['product'] = $p; $pc->addProduct($p['product_id']); if ($coupon['coupon_id'] > 0) { $pc->setCouponDiscount($coupon['discount'], split(',', trim($coupon['product_id']))); } if ($p[is_recurring]) { // Calculate Trial first; $pc->setPriceFields(array('trial1_price', 'price')); $t = $pc->calculate(); $terms[$cnt]['initial'] = $t->total - $t->tax; $terms[$cnt]['initial_tax'] = $t->tax; // Calculate Recurring; $pc->emptyProducts(); $pc->addProduct($p['product_id']); $pc->setPriceFields(array('price')); if (!$coupon['is_recurring']) { $pc->setCouponDiscount(null); } $t = $pc->calculate(); $terms[$cnt]['recurring'] = $t->total - $t->tax; $terms[$cnt]['recurring_tax'] = $t->tax; } else { $pc->setPriceFields(array('price')); $t = $pc->calculate(); $terms[$cnt]['initial'] = $t->total - $t->tax; $terms[$cnt]['initial_tax'] = $t->tax; $terms[$cnt]['recurring'] = 0; } $terms[$cnt]['terms_description'] = $po->getSubscriptionTerms(); // We got first payment alrelady so need to create profile with delay. $terms[$cnt]['start_delay'] = $this->getStartDelay($p); $terms[$cnt]['freq'] = $this->getFreq($p); $terms[$cnt]['period'] = $this->getPeriod($p); switch ($this->getRecurringCount($p)) { case 0: $terms[$cnt]['recurring_count'] = 0; break; // case 0 : $terms[$cnt]['recurring'] =0; break; // case 0 : $terms[$cnt]['recurring'] =0; break; default: $terms[$cnt]['recurring_count'] = $this->getRecurringCount($p); } $cnt++; } return $terms; }
function rebill($dat = '') { global $config, $db, $t, $cc_core; if ($dat == '') { $dat = date('Y-m-d'); } $tomorrow = date('Y-m-d', strtotime($dat) + 3600 * 24); $plugin = 'manual_euro_bank'; $payments = $db->get_expired_payments($dat, $dat, $plugin); foreach ($payments as $p) { if ($p['data']['CANCELLED']) { continue; } $product = get_product($p['product_id']); if (!$product->config['is_recurring']) { continue; } $pc =& new PriceCalculator(); $pc->addProduct($p['product_id']); $pc->setTax(get_member_tax($p['member_id'])); $terms =& $pc->calculate(); $pp = array('member_id' => $p['member_id'], 'product_id' => $p['product_id'], 'paysys_id' => $p['paysys_id'], 'begin_date' => $dat, 'expire_date' => $product->get_expire($dat), 'amount' => calculate_price($p['product_id'], $p['member_id'], $vars, $prices)); if ($err = $db->add_payment($pp)) { trigger_error("Cannot add payment : {$err}", E_USER_WARNING); } $payment_id = $GLOBALS['_amember_added_payment_id']; $this->signup_moderator_mail($payment_id, $signup = false); } }
$db->update_user($member_id, $member); } } if ($error) { break; } $pc =& new PriceCalculator(); $pc->addProducts($vars['product_id']); if ($config['use_coupons'] && $vars['coupon'] != '') { $coupon = $db->coupon_get($vars['coupon']); if ($coupon['coupon_id']) { $pc->setCouponDiscount($coupon['discount'], split(',', trim($coupon['product_id']))); } } $pc->setPriceFieldsByPaysys($vars['paysys_id']); $pc->setTax(get_member_tax($member_id)); $terms =& $pc->calculate(); $price = $terms->total; // if ($terms->discount > 0) $vars['COUPON_CODE'] = $vars['coupon']; $additional_values = array(); foreach ($payment_additional_fields as $f) { $fname = $f['name']; if (isset($vars[$fname])) { $additional_values[$fname] = $vars[$fname]; } } $additional_values['COUPON_DISCOUNT'] = $terms->discount; $additional_values['TAX_AMOUNT'] = $terms->tax; $taxes = $prices = array(); foreach ($terms->lines as $pid => $line) {