OSB enhancements to date

This commit is contained in:
Deon George
2010-11-30 09:41:08 +11:00
parent 8715a2059b
commit ec6a542bc3
478 changed files with 23423 additions and 9309 deletions

View File

@@ -2,8 +2,7 @@
$auth_methods = Array
(
Array ('module' => 'checkout', 'method' => 'preview'),
Array ('module' => 'checkout', 'method' => 'adddiscount'),
Array ('module' => 'checkout', 'method' => 'checkoutoption'),
Array ('module' => 'checkout', 'method' => 'checkoutnow')
);
?>
?>

View File

@@ -71,6 +71,10 @@ class base_checkout_plugin
}
}
public function getName() {
return $this->name;
}
/**
* Get country name,
*

View File

@@ -29,11 +29,6 @@
* @subpackage Module:Checkout
*/
class checkout extends OSB_module {
var $account_id;
var $session_id;
var $affiliate_id;
var $campaign_id;
var $admin_view=false;
var $admin_checkout=false;
var $admin_checkout_option=false;
@@ -50,16 +45,6 @@ class checkout extends OSB_module {
return true;
}
/**
* Add Discount Code to Sess
*/
function adddiscount($VAR)
{
include_once(PATH_MODULES.'discount/discount.inc.php');
$dsc=new discount();
$dsc->add_cart_discount($VAR);
}
/**
* Admin Create the Invoice Record
*/
@@ -130,20 +115,30 @@ class checkout extends OSB_module {
* @param int $account_id
* @param float $total
* @param array $product_arr Array of product_ids being purchased
* @param int $country_id
* @param bool $any_new
* @param bool $any_trial
* @param bool $any_recurring
* @return array
* @uses account
*/
function get_checkout_options($account_id,$total=0,$product_arr=false,$country_id=1,$any_new=false,$any_trial=false,$any_recurring=false) {
$options=false;
if($any_trial) $options .= " AND allow_trial=1 ";
if($any_recurring) $options .= " AND allow_recurring=1 ";
if($any_new) $options .= " AND allow_new=1 ";
if(!$options) return false;
$db=&DB();
$chopt = $db->Execute(sqlSelect($db,"checkout","*","active=1 $options"));
function get_checkout_options($account_id,$total=0,$product_arr=false,$any_new=false,$any_trial=false,$any_recurring=false) {
$options = '';
if ($any_trial)
$options .= ' AND allow_trial=1';
if ($any_recurring)
$options .= ' AND allow_recurring=1';
if ($any_new)
$options .= ' AND allow_new=1';
if (! $options)
return false;
include_once(PATH_MODULES.'account/account.inc.php');
$ao = new account($account_id);
$country_id = $ao->getRecordAttr('country_id');
$db = &DB();
$chopt = $db->Execute(sqlSelect($db,'checkout','*',sprintf('active=1 %s',$options)));
if($chopt && $chopt->RecordCount()) {
while( !$chopt->EOF ) {
$show = true;
@@ -240,57 +235,72 @@ class checkout extends OSB_module {
/**
* Preview / Confirm prior to checkout
*
* @uses account
* @uses cart
*/
public function preview($VAR) {
public function preview($VAR,$object,$returnInvoice=false) {
if (! SESS_LOGGED)
return false;
$db = &DB();
if (empty($this->session_id))
$this->session_id = SESS;
if (empty($this->account_id))
$this->account_id = SESS_ACCOUNT;
# Load the cart
include_once(PATH_MODULES.'/cart/cart.inc.php');
$cartObj = new cart;
$co = new cart();
$cartObj->account_id = $this->account_id;
$cartObj->session_id = $this->session_id;
$result = $cartObj->get_contents();
if (! $result || $result->RecordCount() == 0)
if (! $results = $co->sGetContents())
return false;
# Load invoice object
include_once(PATH_MODULES.'invoice/invoice.inc.php');
$invoice = new invoice;
$invoice = new invoice();
$invoice->initNew(0);
$invoice->account_id = $this->account_id;
$invoice->setRecordAttr('account_id',$this->account_id);
# Get the account details:
$account = $db->Execute(sqlSelect($db,'account','*',array('id'=>$this->account_id)));
$invoice->country_id = $account->fields['country_id'];
$invoice->state = $account->fields['state'];
# Put the cart items into an invoice
foreach ($results as $result) {
$invoice->aaddItem(array(
'charge_id'=>null,
'domain_name'=>$result['domain_name'],
'domain_term'=>$result['domain_term'],
'domain_type'=>$result['domain_type'],
'domain_tld'=>$result['domain_tld'],
'host_type'=>$result['host_type'],
'item_type'=>0,
'service_id'=>null,
'cart_id'=>$result['id'],
'product_id'=>$result['product_id'],
'quantity'=>isset($result['quantity']) ? $result['quantity'] : 1,
'recurr_schedule'=>$result['recurr_schedule'],
'product_attr'=>$result['product_attr'],
'product_attr_cart'=>$result['product_attr'],
'type'=>in_array($result['host_type'],array('register')) ? 'domain' : null
));
}
# Put cart contents into invoice format
$smart = $cartObj->put_contents_invoice($result,$invoice);
# Get available checkout options
$product_arr = array();
foreach ($invoice->invoice_item as $item)
if (! empty($item['product_id']))
array_push($product_arr,$item['product_id']);
$checkout_options = $this->get_checkout_options($this->account_id,$invoice->total_amt,$product_arr,$invoice->country_id,$invoice->any_new,$invoice->any_trial,$invoice->any_recurring);
$checkout_c = count($checkout_options);
# If we are being called by checkout, then we use the preview code to build our invoice.
if ($returnInvoice)
return $invoice;
global $smarty;
$smarty->assign('results',count($invoice->invoice_item));
$smarty->assign('cart',$smart);
$smarty->assign('sub_total',($invoice->total_amt+$invoice->discount_amt)-$invoice->tax_amt);
$smarty->assign('total',$invoice->total_amt);
$smarty->assign('discount',$invoice->group_discounts());
$smarty->assign('tax',$invoice->group_taxes());
$smarty->assign('results',$invoice->sCountItems());
$smarty->assign('cart',$invoice->getItems());
$smarty->assign('sub_total',$invoice->sSubTotal());
$smarty->assign('discounttotal',$invoice->sTotalDiscount(true));
$smarty->assign('discount',$invoice->getDiscountDetails(true));
$smarty->assign('taxtotal',$invoice->sTotalTax(true));
$smarty->assign('tax',$invoice->getTaxDetails());
$smarty->assign('total',$invoice->sTotal(true));
# Get our checkout options
$checkout_options = $this->get_checkout_options($this->account_id,$invoice->sTotal(),$invoice->getProductItems(),
(is_null($invoice->getRecordAttr('id'))),
in_array(2,$invoice->getProductItemTypes()),(! is_null($invoice->getRecordAttr('id'))));
$checkout_c = count($checkout_options);
$smarty->assign('checkout',$checkout_options);
$smarty->assign('checkout_c',$checkout_c);
$checkout_c--;
@@ -299,10 +309,12 @@ class checkout extends OSB_module {
/**
* Create the Invoice Record and send user to checkout
*
* @uses account
* @uses currency
*/
public function checkoutnow($VAR) {
global $C_translate,$C_list,$smarty;
$db = &DB();
# Validate user is logged in:
if (! SESS_LOGGED) {
@@ -312,6 +324,8 @@ class checkout extends OSB_module {
return false;
}
$db = &DB();
# Check for admin
if (! $this->admin_checkout && ! empty($VAR['account_id'])) {
global $C_auth;
@@ -325,34 +339,28 @@ class checkout extends OSB_module {
}
}
if (empty($this->session_id))
$this->session_id = SESS;
if (empty($this->account_id))
$this->account_id = SESS_ACCOUNT;
$invoice = $this->preview($VAR,null,true);
include_once(PATH_MODULES.'/cart/cart.inc.php');
$cartObj = new cart;
# Set some defaults
$invoice->setRecordAttr('actual_billed_amt',0);
$invoice->setRecordAttr('billed_amt',0);
$invoice->setRecordAttr('billing_status',0);
$invoice->setRecordAttr('due_date',time());
$invoice->setRecordAttr('grace_period',0);
$invoice->setRecordAttr('notice_count',0);
$invoice->setRecordAttr('notice_max',0);
$invoice->setRecordAttr('notice_next_date',null);
$invoice->setRecordAttr('print_status',0);
$invoice->setRecordAttr('process_status',0);
$invoice->setRecordAttr('status',1);
$invoice->setRecordAttr('suspend_billing',0);
$invoice->setRecordAttr('reseller_id',0);
$invoice->setRecordAttr('type',0);
$cartObj->account_id = $this->account_id;
$cartObj->session_id = $this->session_id;
$result = $cartObj->get_contents();
if (! $result || $result->RecordCount() == 0)
return false;
# Load invoice object
include_once(PATH_MODULES.'invoice/invoice.inc.php');
$invoice = new invoice;
$invoice->initNew(0);
$invoice->account_id = $this->account_id;
# Get the account details:
$account = $db->Execute(sqlSelect($db,'account','*',array('id'=>$this->account_id)));
$invoice->country_id = $account->fields['country_id'];
$invoice->state = $account->fields['state'];
# Put cart contents into invoice format
$cartObj->put_contents_invoice($result,$invoice);
# (Re)Calculate our discounts and taxes
$invoice->setRecordAttr('discount_amt',$invoice->sTotalDiscount(true));
$invoice->setRecordAttr('tax_amt',$invoice->sTotalTax(true));
$invoice->setRecordAttr('total_amt',$invoice->sTotal(true));
// Validate and init a checkout plugin
$checkout = false;
@@ -362,24 +370,22 @@ class checkout extends OSB_module {
$PLG = new checkout_admin;
$checkout = true;
$invoice->checkout_plugin_id = false;
$invoice->setRecordAttr('checkout_plugin_id',false);
} else {
// Get available checkout options and check against the one provided
$invoice->checkout_plugin_id = $VAR['option'];
$product_arr = array();
foreach ($invoice->invoice_item as $item)
if (! empty($item['product_id']))
array_push($product_arr,$item['product_id']);
# Get available checkout options and check against the one provided
$invoice->setRecordAttr('checkout_plugin_id',$VAR['option']);
$checkout_options = $this->get_checkout_options($this->account_id,$invoice->total_amt,$product_arr,$invoice->country_id,$invoice->any_new,$invoice->any_trial,$invoice->any_recurring);
$checkout_options = $this->get_checkout_options($this->account_id,$invoice->sTotal(),$invoice->getProductItems(),
(is_null($invoice->getRecordAttr('id'))),
in_array(2,$invoice->getProductItemTypes()),in_array(1,$invoice->getProductItemTypes()));
if ($checkout_options) {
foreach ($checkout_options as $a) {
if ($a['fields']['id'] == $invoice->checkout_plugin_id) {
if ($a['fields']['id'] == $invoice->getRecordAttr('checkout_plugin_id')) {
# Load the selected checkout plugin and run pre-validation
$checkout_plugin = $a['fields']['checkout_plugin'];
include_once(sprintf('%scheckout/%s.php',PATH_PLUGINS,$checkout_plugin));
eval ('$PLG = new plg_chout_'.$checkout_plugin.'("'.$invoice->checkout_plugin_id.'");');
eval (sprintf('$PLG = new plg_chout_%s("%s");',$checkout_plugin,$invoice->getRecordAttr('checkout_plugin_id')));
$plugin_validate = $PLG->validate($VAR,$this);
if ($plugin_validate != true) {
@@ -394,17 +400,19 @@ class checkout extends OSB_module {
}
}
# If we werent able to checkout, then return here
if (! $checkout) {
echo '<script language=Javascript> alert("Unable to checkout with the selected method, please select another."); </script> ';
echo '<script type="text/javascript">alert("Unable to checkout with the selected method, please select another.");</script>';
return false;
}
// validate credit card on file details
global $VAR;
if (! empty($VAR['account_billing_id']) && @$VAR['new_card']==2) {
$invoice->account_billing_id=$VAR['account_billing_id'];
$invoice->setRecordAttr('account_billing_id',$VAR['account_billing_id']);
/* validate credit card on file details */
if(!$PLG->setBillingFromDB($this->account_id, $invoice->account_billing_id, $invoice->checkout_plugin_id)) {
if(!$PLG->setBillingFromDB($this->account_id,$VAR['account_billing_id'],$invoice->checkout_plugin_id)) {
global $C_debug;
$C_debug->alert("Sorry, we cannot use that billing record for this purchase.");
return false;
@@ -442,86 +450,102 @@ class checkout extends OSB_module {
}
}
# Load account object
include_once(PATH_MODULES.'account/account.inc.php');
$ao = new account($this->account_id);
# Affiliate
if(empty($this->affiliate_id)) {
if(!empty($account->fields['affiliate_id']))
$invoice->affiliate_id = $account->fields['affiliate_id'];
else
$invoice->affiliate_id = SESS_AFFILIATE;
}
if (is_null($invoice->getRecordAttr('affiliate_id')))
$invoice->setRecordAttr('affiliate_id',
(! is_null($ao->getRecordAttr('affiliate_id'))) ? $ao->getRecordAttr('affiliate_id') : SESS_AFFILIATE);
# Campaign
if(empty($this->campaign_id)) {
if(!empty($account->fields['campaign_id']))
$invoice->campaign_id = $account->fields['campaign_id'];
else
$invoice->campaign_id = SESS_CAMPAIGN;
}
if (is_null($invoice->getRecordAttr('campaign_id')))
$invoice->setRecordAttr('campaign_id',
(! is_null($ao->getRecordAttr('campaign_id'))) ? $ao->getRecordAttr('campaign_id') : SESS_CAMPAIGN);
$invoice->record_id = sqlGenID($db,"invoice");
$invoice->actual_billed_currency_id = SESS_CURRENCY;
$invoice->billed_currency_id = DEFAULT_CURRENCY;
$invoice->setRecordAttr('actual_billed_currency_id',SESS_CURRENCY);
$invoice->setRecordAttr('billed_currency_id',DEFAULT_CURRENCY);
$invoice->checkout_type = $PLG->type;
$invoice->setRecordAttr('id',sqlGenID($db,'invoice'));
// initial invoice status
if( $invoice->total_amt == 0 || $PLG->type == 'gateway') {
$invoice->billing_status = 1;
$invoice->actual_billed_amt = $C_list->format_currency_decimal($invoice->total_amt, SESS_CURRENCY);
$invoice->billed_amt = $invoice->total_amt;
# Initial invoice status
if ($invoice->sTotal() == 0 || $PLG->type == 'gateway') {
$invoice->setRecordAttr('billing_status',1);
$invoice->actual_billed_amt = $C_list->format_currency_decimal($invoice->sTotal(),SESS_CURRENCY);
$invoice->billed_amt = $invoice->sTotal();
}
// Currency conversion:
# Currency conversion
if (SESS_CURRENCY != DEFAULT_CURRENCY) {
$bill_amt = $C_list->format_currency_decimal ($invoice->total_amt, SESS_CURRENCY);
$recur_amt = $C_list->format_currency_decimal ($invoice->recur_amt, SESS_CURRENCY);
$bill_amt = $C_list->format_currency_decimal($invoice->sTotal(),SESS_CURRENCY);
$recur_amt = is_null($invoice->sRecurAmt()) ? null : $C_list->format_currency_decimal($invoice->sRecurAmt(),SESS_CURRENCY);
} else {
$bill_amt = round($invoice->total_amt,2);
$recur_amt = round($invoice->recur_amt,2);
$bill_amt = round($invoice->sTotal(),2);
$recur_amt = is_null($invoice->sRecurAmt()) ? null : round($invoice->sRecurAmt(),2);
}
// Get currency ISO (three_digit) for checkout plugin
$currrs = $db->Execute(sqlSelect($db,"currency","three_digit","id=".SESS_CURRENCY));
if($currrs && $currrs->RecordCount()) $currency_iso = $currrs->fields['three_digit'];
# Get currency ISO (three_digit) for checkout plugin
include_once(PATH_MODULES.'currency/currency.inc.php');
$cuo = new currency();
$currencies = $cuo->sql_GetRecords(array('where'=>array('id'=>SESS_CURRENCY)));
if ($currencies)
$currency_iso = $currencies[0]['three_digit'];
else
$currency_iso = $C_list->currency_iso(SESS_CURRENCY);
# Run the plugin bill_checkout() method:
$invoice->setRecordAttr('checkout_plugin_data',
$PLG->bill_checkout($bill_amt,$invoice->getRecordAttr('id'),$currency_iso,$ao->getRecord(),$recur_amt,$invoice->recur_arr));
if ($invoice->getRecordAttr('checkout_plugin_data') === false || $invoice->getRecordAttr('checkout_plugin_data') == '' ) {
if (! empty($PLG->redirect))
echo $PLG->redirect;
// Run the plugin bill_checkout() method:
$currency_iso = $C_list->currency_iso(SESS_CURRENCY);
$invoice->checkout_plugin_data = $PLG->bill_checkout($bill_amt, $invoice->record_id, $currency_iso, $account->fields, $recur_amt, $invoice->recur_arr);
if($invoice->checkout_plugin_data === false || $invoice->checkout_plugin_data == '' ) {
if(!empty($PLG->redirect)) echo $PLG->redirect;
return false;
} elseif ($PLG->type == "gateway" || empty($PLG->redirect)) {
$VAR['id'] = $invoice->record_id;
if(!$this->admin_checkout) $VAR['_page'] = "invoice:thankyou";
$invoice->checkout_plugin_data=false;
} elseif(!$this->admin_checkout) {
echo "<html><head></head><body><center>
Please wait while we redirect you to the secure payment site....
{$PLG->redirect}</center></body></html>";
} elseif ($PLG->type == 'gateway' || empty($PLG->redirect)) {
$VAR['id'] = $invoice->getRecordAttr('id');
if (! $this->admin_checkout)
$VAR['_page'] = 'invoice:thankyou';
$invoice->setRecordAttr('checkout_plugin_data',false);
} elseif (! $this->admin_checkout) {
echo "<html><head></head><body><center>Please wait while we redirect you to the secure payment site.... {$PLG->redirect}</center></body></html>";
}
// Call the Plugin method for storing the checkout data:
$invoice->account_billing_id = $PLG->store_billing($VAR, $invoice->account_id);
# Call the Plugin method for storing the checkout data:
$invoice->setRecordAttr('account_billing_id',$PLG->store_billing($VAR,$invoice->account_id));
// clear user discounts
$fields=Array('discounts'=>"");
$db->Execute(sqlUpdate($db,"session",$fields,"id = ::".SESS."::"));
# Clear user discounts
$db->Execute(sqlUpdate($db,'session',array('discounts'=>null),array('id'=>SESS)));
// admin options
$email=true;
if($this->admin_checkout) {
if(empty($VAR['send_email']) || $VAR['send_email']=='false') $email=false; else $email=true;
if(!empty($VAR['due_date'])) $invoice->due_date=$this->getInputDate($VAR['due_date']);
if(!empty($VAR['grace_period'])) $invoice->grace_period=$VAR['grace_period'];
if(!empty($VAR['notice_max'])) $invoice->notice_max=$VAR['notice_max'];
# admin options
$email = true;
if ($this->admin_checkout) {
if (empty($VAR['send_email']) || $VAR['send_email']=='false')
$email=false;
else
$email=true;
if (! empty($VAR['due_date']))
$invoice->due_date=$this->getInputDate($VAR['due_date']);
if (! empty($VAR['grace_period']))
$invoice->grace_period=$VAR['grace_period'];
if (! empty($VAR['notice_max']))
$invoice->notice_max=$VAR['notice_max'];
}
if ($invoice->commitNew($taxObj,$discountObj,$email)) {
if ($invoice->sql_SaveRecord(true)) {
# Delete all cart items
$db->Execute(sqlDelete($db,'cart',sprintf('(session_id=::%s:: OR account_id=%s)',SESS,$invoice->account_id)));
$db->Execute(sqlDelete($db,'cart',sprintf('(session_id=::%s:: OR account_id=%s)',SESS,$invoice->getRecordAttr('account_id'))));
# Admin redirect
if ($this->admin_checkout)
printf('<script language="javascript">parent.location.href=\'%sadmin.php?_page=invoice:view&id=%s\';</script>',URL,$invoice->record_id);
printf('<script language="javascript">parent.location.href=\'%sadmin.php?_page=invoice:view&id=%s\';</script>',URL,$invoice->getRecordAttr('id'));
}
return false;
@@ -564,7 +588,7 @@ class checkout extends OSB_module {
if($amt > 0)
{
// get total due for this invoice:
$rs=sqlSelect($db, "invoice","SUM(total_amt-billed_amt) as total","id=$id");
$rs=sqlSelect($db, "invoice","SUM(total_amt-billed_amt-IFNULL(credit_amt,0)) as total","id=$id");
if($rs && $rs->RecordCount()) {
$thisamt = $rs->fields["total"];
@@ -582,235 +606,248 @@ class checkout extends OSB_module {
}
/**
* Postback for Redirect Pay
* Postback Payment Processing
* This function will handle the postback processing from a payment processor
*
* @param array $arr Incoming payment information
* @uses invoice
* @uses invoice_item
*/
function postback($arr)
{
global $C_debug;
public function postback($arr) {
global $C_debug,$C_list;
if(empty($arr['invoice_id'])) return false;
if(empty($arr['transaction_id'])) return false;
if(empty($arr['amount'])) return false;
# Minimum incoming values to continue
if (empty($arr['invoice_id']))
return false;
if (empty($arr['transaction_id']))
return false;
if (empty($arr['amount']))
return false;
if(eregi("MULTI-", $arr['invoice_id'])) {
$this->postback_multiple($arr);
return;
}
# Does this postback pay multiple invoices?
if (preg_match('/^MULTI-/',$arr['invoice_id']))
return $this->postback_multiple($arr);
# Get the latest invoice info:
$db = &DB();
$sql1 ="";
if(!empty($arr['subscription_id']))
$sql1 = "checkout_plugin_data = ".$db->qstr( trim($arr['subscription_id']) )." OR ";
include_once(PATH_MODULES.'invoice/invoice.inc.php');
$io = new invoice();
$q = "SELECT * FROM ".AGILE_DB_PREFIX."invoice WHERE
(
$sql1
parent_id = ".$db->qstr(@$arr['invoice_id'])."
OR
id = ".$db->qstr(@$arr['invoice_id'])."
)
AND
billing_status != 1
AND
site_id = ".$db->qstr(DEFAULT_SITE)."
ORDER BY date_orig
LIMIT 0,1";
$invoice = $db->Execute($q);
# Get the latest invoice information
$invoices = $io->sql_GetRecords(array(
'where'=>sprintf('(parent_id=%s OR id=%s%s)',$arr['invoice_id'],$arr['invoice_id'],
(! empty($arr['subscription_id']) && trim($arr['subscription_id'])) ? sprintf(' OR checkout_plugin_data=%s',trim($arr['subscription_id'])) : ''),
'limit'=>'0,1'));
if ($invoice === false || $invoice->RecordCount()==0)
$C_debug->error('checkout.inc.php','postback', $q . " | " . @$db->ErrorMsg());
if (! count($invoices)) {
$C_debug->error(__FILE__,__METHOD__,sprintf('No invoice records, unable to process payment for: %s',$arr['invoice_id']));
if($invoice->RecordCount() == 0)
return false;
$invoice_id = $invoice->fields['id'];
# Validate the currency
$billed_currency_id = $invoice->fields['billed_currency_id'];
$total_amt = $invoice->fields['total_amt'];
$billed_amt = $invoice->fields['billed_amt'];
$actual_billed_amt = $invoice->fields['actual_billed_amt'];
$currency_iso = @$arr['currency'];
if(empty($currency_iso) || !$currency_iso)
{
# same as billed_currency_id
$this->billed_amt = $arr['amount'] + $billed_amt;
$this->actual_billed_amt = $arr['amount'] + $billed_amt;
$this->actual_billed_currency_id = $billed_currency_id;
}
else
{
# Get the actual billed currency id currency info:
$q = "SELECT * FROM ".AGILE_DB_PREFIX."currency WHERE
three_digit = ".$db->qstr($currency_iso)." AND
site_id = ".$db->qstr(DEFAULT_SITE);
$result = $db->Execute($q);
if ($result === false)
$C_debug->error('checkout.inc.php','postback', $q . " | " . @$db->ErrorMsg());
$actual_billed_currency_id = $result->fields['id'];
if(is_string($result->fields["convert_array"]))
$convert = unserialize($result->fields["convert_array"]);
else
$convert = false;
$this->format_currency[$actual_billed_currency_id] = Array (
'symbol' => $result->fields["symbol"],
'convert' => $convert,
'iso' => $result->fields["three_digit"]);
if($result->RecordCount() == 0 || $actual_billed_currency_id == $billed_currency_id)
{
# same as billed_currency_id
$this->billed_amt = $arr['amount'] + $billed_amt;
$this->actual_billed_amt = $arr['amount'] + $billed_amt;
$this->actual_billed_currency_id = $actual_billed_currency_id;
}
else
{
# Get the billed currency id currency info:
$q = "SELECT * FROM ".AGILE_DB_PREFIX."currency WHERE
id = ".$db->qstr($billed_currency_id)." AND
site_id = ".$db->qstr(DEFAULT_SITE);
$result = $db->Execute($q);
if ($result === false)
$C_debug->error('checkout.inc.php','postback', $q . " | " . @$db->ErrorMsg());
$this->format_currency[$billed_currency_id] = Array (
'symbol' => $result->fields["symbol"],
'convert' => unserialize($result->fields["convert_array"]),
'iso' => $result->fields["three_digit"]);
# Convert the invoice amount to the actual billed currency amount
$due_amount = $invoice->fields['total_amt'] - $invoice->fields['billed_amt'];
$conversion = $this->format_currency[$billed_currency_id]["convert"][$actual_billed_currency_id]["rate"];
$this->billed_amt = $billed_amt + ($arr['amount'] /= $conversion);
$this->actual_billed_amt = $actual_billed_amt + $arr['amount'];
$this->actual_billed_currency_id = $actual_billed_currency_id;
}
return false;
}
# Get our invoice object, that this payment is for.
$invoice = array_pop($invoices);
# If we are not passed a currency, we can only assume it is the same as that used to bill the invoice.
if (! isset($arr['currency']) || ! trim($arr['currency'])) {
$this->billed_amt = $arr['amount']+$invoice['billed_amt'];
$this->actual_billed_amt = $arr['amount']+$invoice['billed_amt'];
$this->actual_billed_currency_id = $invoice['billed_currency_id'];
# Check for any subscription_id
if(!empty($arr['subscription_id'])) {
$this->subscription_id = trim($arr['subscription_id']);
} else {
$this->subscription_id = trim($invoice->fields['checkout_plugin_data']);
}
# Get the actual billed currency id currency info
$rs = $db->Execute(sqlSelect('currency','*',array('where'=>array('three_digit'=>$arr['currency']))));
# Check for the checkout_id
if(!empty($arr['checkout_id'])) {
$this->checkout_id = $arr['checkout_id'];
} else {
$this->checkout_id = $invoice->fields['checkout_plugin_id'];
}
if (! $rs)
$C_debug->error(__FILE__,__METHOD__,$db->ErrorMsg());
# Check for the billing status:
if($this->billed_amt >= $invoice->fields['total_amt']) {
$this->billing_status = '1';
} else {
$this->billing_status = '0';
}
# No currency information, assume the currency of the invoice
elseif (! $rs->RecordCount()) {
$C_debug->error(__FILE__,__METHOD__,sprintf('No currency: %s?',$arr['currency']));
# Check if this transaction_id has already been processed:
$q = "SELECT id FROM ".AGILE_DB_PREFIX."invoice_memo WHERE
invoice_id = ".$db->qstr($invoice_id)." AND
type = ".$db->qstr('postback')." AND
memo = ".$db->qstr($arr['transaction_id'])." AND
site_id = ".$db->qstr(DEFAULT_SITE);
$memo = $db->Execute($q);
if ($memo === false)
$C_debug->error('checkout.inc.php','postback', $q . " | " . @$db->ErrorMsg());
if ($memo->RecordCount() > 0) {
# duplicate post:
$C_debug->error('Duplicate Postback','checkout.inc.php :: postback()', "Duplicate postback for invoice {$arr['invoice_id']} & transaction id {$arr['transaction_id']}");
} else {
# Create the invoice memo:
$memo_id = $db->GenID(AGILE_DB_PREFIX . 'invoice_memo_id');
$q = "INSERT INTO
".AGILE_DB_PREFIX."invoice_memo
SET
id = ".$db->qstr($memo_id).",
site_id = ".$db->qstr(DEFAULT_SITE).",
date_orig = ".$db->qstr(time()).",
invoice_id = ".$db->qstr($invoice_id).",
account_id = ".$db->qstr(0).",
type = ".$db->qstr('postback').",
memo = ".$db->qstr($arr['transaction_id']) ;
$memosql = $db->Execute($q);
if ($memosql === false)
$C_debug->error('checkout.inc.php','postback', $q . " | " . @$db->ErrorMsg());
# Update the invoice billing info:
$q = "UPDATE
".AGILE_DB_PREFIX."invoice
SET
date_last = ".$db->qstr(time()).",
billing_status = ".$db->qstr($this->billing_status).",
checkout_plugin_id = ".$db->qstr($this->checkout_id).",
checkout_plugin_data = ".$db->qstr($this->subscription_id).",
billed_amt = ".$db->qstr($this->billed_amt).",
actual_billed_amt = ".$db->qstr($this->actual_billed_amt).",
actual_billed_currency_id = ".$db->qstr($this->actual_billed_currency_id)."
WHERE
id = ".$db->qstr($invoice_id)." AND
site_id = ".$db->qstr(DEFAULT_SITE);
$memosql = $db->Execute($q);
if ($memosql === false)
$C_debug->error('checkout.inc.php','postback', $q . " | " . @$db->ErrorMsg());
# Update the invoice approval status
$VAR['id'] = $invoice_id;
include_once(PATH_MODULES.'invoice/invoice.inc.php');
$inv = new invoice;
if(!$arr['status'])
{
# void
$inv->voidInvoice($VAR);
# create a record of the viod in an invoice memo:
$memo_id = $db->GenID(AGILE_DB_PREFIX . 'invoice_memo_id');
$q = "INSERT INTO
".AGILE_DB_PREFIX."invoice_memo
SET
id = ".$db->qstr($memo_id).",
site_id = ".$db->qstr(DEFAULT_SITE).",
date_orig = ".$db->qstr(time()).",
invoice_id = ".$db->qstr($invoice_id).",
account_id = ".$db->qstr(0).",
type = ".$db->qstr('void').",
memo = ".$db->qstr("Voided due to postback: ".$arr['transaction_id']) ;
$rsql = $db->Execute($q);
if ($rsql === false)
$C_debug->error('checkout.inc.php','postback', $q . " | " . @$db->ErrorMsg());
$this->billed_amt = $arr['amount']+$invoice['billed_amt'];
$this->actual_billed_amt = $arr['amount']+$invoice['billed_amt'];
$this->actual_billed_currency_id = $invoice['billed_currency_id'];
} else {
$this->actual_billed_currency_id = $rs->fields['id'];
# approve
$inv->autoApproveInvoice($invoice_id);
if (is_string($rs->fields['convert_array']))
$convert = unserialize($rs->fields['convert_array']);
else
$convert = false;
$this->format_currency[$this->actual_billed_currency_id] = array(
'symbol'=>$rs->fields['symbol'],
'convert'=>$convert,
'iso'=>$rs->fields['three_digit']);
# Get the billed currency id currency info:
$rs = $db->Execute(sqlSelect('currency','*',array('where'=>array('id'=>$invoice['billed_currency_id']))));
if (! $rs)
$C_debug->error(__FILE__,__METHOD__,$db->ErrorMsg());
$this->format_currency[$invoice['billed_currency_id']] = array(
'symbol'=>$rs->fields['symbol'],
'convert'=>unserialize($rs->fields['convert_array']),
'iso'=>$rs->fields['three_digit']);
# Convert the invoice amount to the actual billed currency amount
$conversion = $this->format_currency[$invoice['billed_currency_id']]['convert'][$this->actual_billed_currency_id]['rate'];
$this->billed_amt = $invoice['billed_amt']+($arr['amount']/$conversion);
$this->actual_billed_amt = $invoice['actual_billed_amt']+$arr['amount'];
}
}
# Check for any subscription_id
if (! empty($arr['subscription_id']))
$this->subscription_id = trim($arr['subscription_id']);
else
$this->subscription_id = trim($invoice['checkout_plugin_data']);
$this->checkout_id = $this->getRecordAttr('id');
# Check for the billing status:
if ($this->billed_amt >= $invoice['total_amt'])
$this->billing_status = '1';
else
$this->billing_status = '0';
# Check if this transaction_id has already been processed:
$rs = $db->Execute(
sqlSelect('invoice_memo','id',
array('where'=>array('invoice_id'=>$invoice['id'],'type'=>'postback','memo'=>sprintf('%s-%s',$this->getRecordAttr('id'),$arr['transaction_id'])))));
if (! $rs)
$C_debug->error(__FILE__,__METHOD__,$db->ErrorMsg());
# Transaction ID already exists
elseif ($rs->RecordCount()) {
# Duplicate post:
$C_debug->error(__FILE__,__METHOD__,
sprintf('Duplicate postback for invoice %s & transaction id %s-%s',$arr['invoice_id'],$this->getRecordAttr('id'),$arr['transaction_id']));
# Record new transaction ID
} else {
# Create the invoice memo
# @todo should get the account_id
$rs = $db->Execute(
sqlInsert($db,'invoice_memo',
array('date_orig'=>time(),'invoice_id'=>$invoice['id'],'account_id'=>null,
'type'=>'postback','memo'=>sprintf('%s-%s',$this->getRecordAttr('id'),$arr['transaction_id']))));
if (! $rs)
$C_debug->error(__FILE__,__METHOD__,$db->ErrorMsg());
$io = new invoice($invoice['id']);
# Update the invoice approval status
if (! isset($arr['status']) || ! $arr['status']) {
$rs = $db->Execute(
sqlInsert($db,'invoice_memo',
array('date_orig'=>time(),'invoice_id'=>$invoice['id'],
'account_id'=>null,'type'=>'void','memo'=>sprintf('%s: %s-%s',_('Voided due to postback'),$this->getRecordAttr('id'),$arr['transaction_id']))));
if (! $rs)
$C_debug->error(__FILE__,__METHOD__,$db->ErrorMsg());
# Void
$io->voidInvoice(array('id'=>$invoice['id']));
} else {
# Check the items, see if there is a payment fee to add to the invoice
if (isset($arr['items']) && is_array($arr['items'])) {
include_once(PATH_MODULES.'invoice_item/invoice_item.inc.php');
foreach ($arr['items'] as $k => $v) {
if (isset($v['item_number']) && $v['item_number'] == 'PAYFEE') {
$ito = new invoice_item();
$ito->setRecordAttr('invoice_id',$invoice['id']);
$ito->setRecordAttr('account_id',0);
$ito->setRecordAttr('service_id',null);
$ito->setRecordAttr('charge_id',null);
$ito->setRecordAttr('product_name',sprintf('Payment Fee: %s',$this->getRecordAttr('name')));
$ito->setRecordAttr('product_id',null);
$ito->setRecordAttr('product_attr',null);
$ito->setRecordAttr('product_attr_cart',null);
$ito->setRecordAttr('sku','PAYFEE');
$ito->setRecordAttr('quantity',1);
$ito->setRecordAttr('item_type',0);
$ito->setRecordAttr('price_setup',0);
$ito->setRecordAttr('domain_name',null);
$ito->setRecordAttr('domain_tld',null);
$ito->setRecordAttr('domain_type',null);
$ito->setRecordAttr('domain_term',null);
$ito->setRecordAttr('price_type',null);
$ito->setRecordAttr('recurring_schedule',null);
$ito->setRecordAttr('date_start',null);
$ito->setRecordAttr('date_stop',null);
$ito->setRecordAttr('price_base',$v['mc_gross_']);
# @todo need to retro work out the tax amount.
$ito->setRecordAttr('tax_amt',0);
$item = $ito->sql_SaveRecord();
$io->setRecordAttr('total_amt',$io->getRecordAttr('total_amt')+$ito->getRecordAttr('total_amt'));
$io->setRecordAttr('tax_amt',$io->getRecordAttr('tax_amt')+$ito->getRecordAttr('tax_amt'));
}
}
}
$io->setRecordAttr('billing_status',$this->billing_status);
$io->setRecordAttr('checkout_plugin_id',$this->getRecordAttr('id'));
$io->setRecordAttr('checkout_plugin_data',$this->subscription_id);
$io->setRecordAttr('billed_amt',$this->billed_amt);
$io->setRecordAttr('actual_billed_amt',$this->actual_billed_amt);
$io->setRecordAttr('actual_billed_currency_id',$this->actual_billed_currency_id);
$rs = $io->sql_SaveRecord();
# If the payment module is installed, record the payment item.
if ($C_list->is_installed('payment')) {
include_once(PATH_MODULES.'payment/payment.inc.php');
include_once(PATH_MODULES.'payment_item/payment_item.inc.php');
$po = new payment();
$po->setRecordAttr('account_id',$io->getRecordAttr('account_id'));
$po->setRecordAttr('date_payment',time());
$po->setRecordAttr('checkout_plugin_id',$this->getRecordAttr('id'));
$po->setRecordAttr('total_amt',$arr['amount']);
$po->setRecordAttr('fees_amt',(isset($arr['fee']) ? $arr['fee'] : 0));
$po->setRecordAttr('notes',print_r($_POST,true));
$po->setRecordAttr('source_id',$io->getRecordAttr('account_id'));
$pid = $po->sql_SaveRecord(true);
$po->sql_LoadRecord($pid);
# Mark this payment pending
# @todo Make this a global configuration option to auto mark payments as pending, so they can be reviewed.
$po->setRecordAttr('pending_status',1);
$po->sql_SaveRecord();
$pio = new payment_item();
$pio->setRecordAttr('payment_id',$pid);
$pio->setRecordAttr('invoice_id',$io->getRecordAttr('id'));
$pio->setRecordAttr('alloc_amt',$arr['amount']);
$pio->sql_SaveRecord();
}
# Approve
$io->autoApproveInvoice($invoice['id']);
# User invoice payment confirmation
include_once(PATH_MODULES.'email_template/email_template.inc.php');
$email = new email_template;
$email->send('invoice_paid_user', $invoice->fields['account_id'], $invoice_id, DEFAULT_CURRENCY, '');
$email->send('invoice_paid_user',$invoice['account_id'],$invoice['id'],DEFAULT_CURRENCY,'');
# Admin alert of payment processed
$email = new email_template;
$email->send('admin->invoice_paid_admin', $invoice->fields['account_id'], $invoice_id, DEFAULT_CURRENCY, '');
$email->send('admin->invoice_paid_admin',$invoice['account_id'],$invoice['id'],DEFAULT_CURRENCY,'');
}
}
return true;
}

View File

@@ -141,11 +141,11 @@
<!-- Methods for this class, and the fields they have access to, if applicable -->
<method>
<add>id,site_id,name,description,active,checkout_plugin,plugin_data,allow_recurring,allow_new,allow_trial,total_minimum,total_maximum,max_decline_attempts,manual_approval_all,manual_approval_recur,manual_approval_country,manual_approval_group,manual_approval_amount,manual_approval_currency,default_when_currency,default_when_country,default_when_group,default_when_amount,allowed_currencies,email_template,excluded_products,required_groups,graphic_url</add>
<update>id,site_id,name,description,active,checkout_plugin,plugin_data,allow_recurring,allow_new,allow_trial,total_minimum,total_maximum,max_decline_attempts,manual_approval_all,manual_approval_recur,manual_approval_country,manual_approval_group,manual_approval_amount,manual_approval_currency,default_when_currency,default_when_country,default_when_group,default_when_amount,allowed_currencies,email_template,excluded_products,required_groups,graphic_url</update>
<delete>id,site_id,name,description,active,checkout_plugin,plugin_data,allow_recurring,allow_new,allow_trial,total_minimum,total_maximum,max_decline_attempts,manual_approval_all,manual_approval_recur,manual_approval_country,manual_approval_group,manual_approval_amount,manual_approval_currency,default_when_currency,default_when_country,default_when_group,default_when_amount,allowed_currencies,excluded_products,required_groups</delete>
<view>id,site_id,name,description,active,checkout_plugin,plugin_data,allow_recurring,allow_new,allow_trial,total_minimum,total_maximum,max_decline_attempts,manual_approval_all,manual_approval_recur,manual_approval_country,manual_approval_group,manual_approval_amount,manual_approval_currency,default_when_currency,default_when_country,default_when_group,default_when_amount,allowed_currencies,email_template,excluded_products,required_groups,graphic_url</view>
<search>id,site_id,name,description,active,checkout_plugin,plugin_data,allow_recurring,allow_new,allow_trial,total_minimum,total_maximum,max_decline_attempts,manual_approval_all,manual_approval_recur,manual_approval_country,manual_approval_group,manual_approval_amount,manual_approval_currency,default_when_currency,default_when_country,default_when_group,default_when_amount,allowed_currencies,email_template,excluded_products,required_groups</search>
<add>name,description,active,checkout_plugin,allow_recurring,allow_new,allow_trial,total_minimum,total_maximum,max_decline_attempts,manual_approval_all,manual_approval_recur,manual_approval_amount,default_when_amount,allowed_currencies,email_template,required_groups,graphic_url</add>
<delete>id</delete>
<search>id,name,description,active,checkout_plugin,plugin_data,allow_recurring,allow_new,allow_trial,total_minimum,total_maximum,max_decline_attempts,manual_approval_all,manual_approval_recur,manual_approval_country,manual_approval_group,manual_approval_amount,manual_approval_currency,default_when_currency,default_when_country,default_when_group,default_when_amount,allowed_currencies,email_template,excluded_products,required_groups</search>
<update>id,name,description,active,checkout_plugin,plugin_data,allow_recurring,allow_new,allow_trial,total_minimum,total_maximum,max_decline_attempts,manual_approval_all,manual_approval_recur,manual_approval_country,manual_approval_group,manual_approval_amount,manual_approval_currency,default_when_currency,default_when_country,default_when_group,default_when_amount,allowed_currencies,email_template,excluded_products,required_groups,graphic_url</update>
<view>id,name,description,active,checkout_plugin,plugin_data,allow_recurring,allow_new,allow_trial,total_minimum,total_maximum,max_decline_attempts,manual_approval_all,manual_approval_recur,manual_approval_country,manual_approval_group,manual_approval_amount,manual_approval_currency,default_when_currency,default_when_country,default_when_group,default_when_amount,allowed_currencies,email_template,excluded_products,required_groups,graphic_url</view>
</method>
<!-- Method triggers -->

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,150 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class provides checkout capabilities.
*
* @package OSB
* @subpackage Checkout
* @category Controllers
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class Controller_Checkout extends Controller_TemplateDefault {
protected $auth_required = TRUE;
protected $noauth_redirect = 'login/register';
/**
* This is the main call to export, providing a list of items to export and
* setting up the page to call the export plugin when submitted.
*/
public function action_index() {
if ($_POST)
return $this->checkout();
// @todo - this should be a global config item
$mediapath = Route::get('default/media');
$block = new block;
// @todo Items in the cart dont have account_id if they were put in the cart when the user was not logged in
// If the cart is empty, we'll return here.
if (! Cart::instance()->contents()->count_all())
$block->add(array(
'title'=>_('Empty Cart'),
'body'=>_('The cart is empty')
));
else {
Style::add(array(
'type'=>'file',
'data'=>'css/checkout_cartlist.css',
));
// Show a list of items in the cart
$output = '<table class="checkout_cartlist" border="0">';
foreach (Cart::instance()->contents()->find_all() as $item) {
$ppa = $item->product->get_price_array();
$pdata = Period::details($item->recurr_schedule,$item->product->price_recurr_weekday,time(),TRUE);
$output .= View::factory('cart/checkout_list')
->set('price_firstinvoice',$item->quantity*$ppa[$item->recurr_schedule]['price_base']*$pdata['prorata'])
->set('price_setup',$item->quantity*$ppa[$item->recurr_schedule]['price_setup'])
->set('service_start',$pdata['date'])
->set('service_end',$pdata['end'])
->set('price_recurring',$item->quantity*$ppa[$item->recurr_schedule]['price_base'])
->set('item',$item)
->set('mediapath',$mediapath);
}
$output .= '</table>';
$block->add(array(
'title'=>_('Your Items'),
'body'=>$output,
));
$po = ORM::factory('checkout')
->payment_options_cart();
// @todo Country value should come from somewhere?
$block->add(array(
'title'=>_('Order Total'),
'body'=>View::factory('cart/checkout_total')
->set('cart',Cart::instance())
->set('country',61),
));
$output = Form::open();
$output .= '<table class="payment_options_box" border="0">';
foreach ($po as $payment) {
$output .= View::factory('checkout/payment_option')
->set('payment',$payment);
}
// @todo Add Javascript to stop submission if something not selected
$output .= '<tr><td>&nbsp;</td></tr>';
$output .= '<tr>';
$output .= sprintf('<td>%s</td>',Form::submit('submit',_('Submit Order')));
$output .= '</tr>';
$output .= '</table>';
$output .= Form::close();
$block->add(array(
'title'=>_('Available Payment Methods'),
'body'=>$output,
));
}
$this->template->content = $block;
// Suppress our right hand tab
$this->template->right = ' ';
}
/**
* Process checkout
*/
private function checkout() {
$invoice = ORM::factory('invoice');
// Add our individual items to the invoice
foreach (Cart::instance()->contents()->find_all() as $item) {
$invoice_item = $invoice->add_item();
$invoice_item->product_id = $item->product_id;
$invoice_item->product_attr = $item->product_attr;
$invoice_item->product_attr_cart = $item->product_attr;
$invoice_item->quantity = $item->quantity;
$invoice_item->recurring_schedule = $item->recurr_schedule;
$ppa = $item->product->get_price_array();
$period = Period::details($item->recurr_schedule,$item->product->price_recurr_weekday,time(),TRUE);
// @todo rounding should be a global config
$invoice_item->price_base = round($item->quantity*$ppa[$item->recurr_schedule]['price_base']*$period['prorata'],2);
$invoice_item->price_setup = round($item->quantity*$ppa[$item->recurr_schedule]['price_setup'],2);
}
$invoice->account_id = Auth::instance()->get_user()->id;
$invoice->type = 2; // INVOICED VIA CHECKOUT
$invoice->status = 1; // INVOICE IS NOT CANCELLED
$invoice->due_date = time(); // DATE INVOICE MUST BE PAID
$invoice->billed_currency_id = 6; // @todo This should come from the site config or the currency selected
/*
$invoice->process_status = NULL; // TO BE PROCESSED
$invoice->billing_status = NULL; // UNPAID
$invoice->refund_status = NULL; // NOT REFUNDED
$invoice->print_status = NULL; // NOT YET PRINTED
$invoice->discount_amt = NULL; // @todo CALCULATE DISCOUNTS
$invoice->checkout_plugin_id = NULL; // @todo Update the selected checkout plugin
$invoice->checkout_plugin_data = NULL; // @todo Data required for the checkout plugin
*/
if ($invoice->check())
$invoice->save();
else
throw new Kohana_Exception('Problem saving invoice - Failed check()');
}
}
?>

View File

@@ -0,0 +1,67 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class provides checkout capabilities.
*
* @package OSB
* @subpackage Checkout
* @category Models
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class Model_Checkout extends ORMOSB {
protected $_has_many = array(
'payment' => array()
);
/**
* Give a cart, this will present the available checkout options
*
* Trial Products are NEW products
* Cart items are NEW products
* Invoice items are RE-OCCURING items (ie: carts are not re-occuring)
*
*/
public function payment_options_cart() {
$cart = Cart::instance();
$available_payments = array();
if ($cart->has_trial())
$this->and_where('allow_trial','=',TRUE);
$this->and_where('allow_new','=',TRUE);
foreach ($this->where('active','=',TRUE)->find_all() as $item) {
// Check that the cart total meets the minimum requirement
if ($item->total_minimum AND $cart->total() < $item->total_minimum)
continue;
// Check the cart total meets the maximum requirement
if (($item->total_maximum AND $cart->total() > $item->total_maximum) OR ($item->total_maximum == '0' AND $cart->total()))
continue;
// Check that the payment option is available to this client based on groups
// @todo Enable this test
// Check that the payment option is not prohibited by an SKU item
// @todo Enable this test
// Check if this payment method is a default payment method
// @todo Enable this test
// By Amount
// By Currency
// By Group
// By Country
// This payment option is valid
array_push($available_payments,$item);
// Sort the checkout options
// @todo Is this required?
}
return $available_payments;
}
}
?>

View File

@@ -0,0 +1,3 @@
<tr>
<td class="icon"><label for="payment_<?php echo $payment->id; ?>"><?php echo FORM::radio('payment',$payment->id,0,array('id'=>'payment_'.$payment->id)); ?> <?php echo HTML::image($payment->graphic_url,array('alt'=>'')); ?> <?php echo $payment->name; ?></label></td>
</tr>