v7‰PNG
IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ±üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0AºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT
db.xml 0000644 00000001515 15210160104 0005643 0 ustar 00
library/CcRebill.php 0000644 00000002112 15210160104 0010362 0 ustar 00 'Started',
self::NO_CC => 'No Credit Card saved',
self::ERROR => 'Error',
self::SUCCESS => 'OK',
self::EXCEPTION => 'Exception!',
);
return $arr[$status];
}
function setStatus($status, $message)
{
$this->updateQuick(array(
'status' => (int)$status,
'status_msg' => $message,
'status_tm' => $this->getDi()->sqlDateTime,
));
return $this;
}
}
class CcRebillTable extends Am_Table
{
protected $_table = '?_cc_rebill';
protected $_key = 'cc_rebill_id';
public function insert(array $values, $returnInserted = false)
{
if (empty($values['tm_added']))
$values['tm_added'] = $this->getDi()->sqlDateTime;
return parent::insert($values, $returnInserted);
}
} library/EcheckRecord.php 0000644 00000004403 15210160104 0011231 0 ustar 00 maskBan($arr['echeck_ban']);
}
$arr['echeck_aba'] = preg_replace('/\D+/', '', $arr['echeck_aba']);
foreach ($this->_encryptedFields as $f)
if (array_key_exists($f, $arr))
$arr[$f] = $this->_table->encrypt($arr[$f]);
return $arr;
}
public function fromRow(array $arr)
{
// fields to decrypt
foreach ($this->_encryptedFields as $f)
if (array_key_exists($f, $arr))
$arr[$f] = $this->_table->decrypt($arr[$f]);
return parent::fromRow($arr);
}
/**
* Delete existing record for this user_id, then insert this one
* @return EcRecord provides fluent interface
*/
function replace()
{
if (empty($this->user_id) || $this->user_id <= 0)
throw new Am_Exception_InternalError("this->user_id is empty in " . __METHOD__);
$this->_table->deleteByUserId($this->user_id);
return $this->insert();
}
}
class EcheckRecordTable extends Am_Table
{
protected $_crypt;
protected $_key = 'echeck_id';
protected $_table = '?_echeck';
protected $_recordClass = 'EcheckRecord';
function encrypt($s){
return $this->_getCrypt()->encrypt($s);
}
function decrypt($s){
return $this->_getCrypt()->decrypt($s);
}
function _getCrypt(){
if (empty($this->_crypt))
$this->_crypt = Am_Di::getInstance ()->crypt;
return $this->_crypt;
}
function setCrypt(Am_Crypt $crypt)
{
$this->_crypt = $crypt;
}
}
library/Am/Paysystem/Nmi.php 0000644 00000013473 15210160104 0011775 0 ustar 00 addText('user')
->setLabel("Your username\n" .
'Username assigned to merchant account')
->addRule('required');
$form->addPassword('pass')
->setLabel("Your password\n" .
'Password for the specified username')
->addRule('required');
$form->addAdvCheckbox('testMode')
->setLabel("Test Mode\n" .
'Test account data will be used');
}
public function isConfigured()
{
return $this->getConfig('user') && $this->getConfig('pass');
}
public function loadCreditCard(Invoice $invoice)
{
if($cc = parent::loadCreditCard($invoice))
return $cc;
return $this->getDi()->CcRecordTable->createRecord(); // return fake record for rebill
}
public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result)
{
$user = $invoice->getUser();
if ($doFirst) // not recurring sale
{
if (!(float)$invoice->first_total) // first - free
{
$trAuth = new Am_Paysystem_Networkmerchants_Transaction_Authorization($this, $invoice, $cc);
$trAuth->run($result);
$transactionId = $trAuth->getUniqId();
$customerVaultId = $trAuth->getCustomerVaultId();
if (!$transactionId || !$customerVaultId)
{
return $result->setFailed(array("NMI Plugin: Bad auth response."));
}
$trVoid = new Am_Paysystem_Networkmerchants_Transaction_Void($this, $invoice, $transactionId, $customerVaultId);
$trVoid->run($result);
$trFree = new Am_Paysystem_Transaction_Free($this);
$trFree->setInvoice($invoice);
$trFree->process();
$result->setSuccess($trFree);
} else
{
$trAuth = new Am_Paysystem_Networkmerchants_Transaction_Authorization($this, $invoice, $cc, $invoice->first_total);
$trAuth->run($result);
$transactionId = $trAuth->getUniqId();
$customerVaultId = $trAuth->getCustomerVaultId();
if (!$transactionId || !$customerVaultId)
{
return $result->setFailed(array("NMI Plugin: Bad auth response."));
}
$trSale = new Am_Paysystem_Networkmerchants_Transaction_Capture($this, $invoice, $doFirst, $transactionId);
$trSale->run($result);
}
$user->data()->set($this->getCustomerVaultVariable(), $customerVaultId)->update();
} else
{
$customerVaultId = $user->data()->get($this->getCustomerVaultVariable());
if (!$customerVaultId)
{
return $result->setFailed(array("No saved reference transaction for customer"));
}
$trSale = new Am_Paysystem_Networkmerchants_Transaction_Sale($this, $invoice, $doFirst, $customerVaultId);
$trSale->run($result);
}
}
public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result)
{
$user = $this->getDi()->userTable->load($cc->user_id);
$customerVaultId = $user->data()->get($this->getCustomerVaultVariable());
if ($this->invoice)
{ // to link log records with current invoice
$invoice = $this->invoice;
} else { // updating credit card info?
$invoice = $this->getDi()->invoiceRecord;
$invoice->invoice_id = 0;
$invoice->user_id = $user->pk();
}
// compare stored cc for that user may be we don't need to refresh?
if ($customerVaultId && ($cc->cc_number != '0000000000000000'))
{
$storedCc = $this->getDi()->ccRecordTable->findFirstByUserId($user->pk());
if ($storedCc && (($storedCc->cc != $cc->maskCc($cc->cc_number)) || ($storedCc->cc_expire != $cc->cc_expire)))
{
$user->data()->set($this->getCustomerVaultVariable(), null)->update();
$customerVaultId = null;
}
}
if (!$customerVaultId)
{
$trAdd = new Am_Paysystem_Networkmerchants_Transaction_AddCustomer ($this, $invoice, $cc);
$trAdd->run($result);
$customerVaultId = $trAdd->getCustomerVaultId();
if (!$customerVaultId)
{
return $result->setFailed(array("PSWW Plugin: Bad add response."));
}
$user->data()->set($this->getCustomerVaultVariable(), $customerVaultId)->update();
}
///
$cc->cc = $cc->maskCc(@$cc->cc_number);
$cc->cc_number = '0000000000000000';
if ($cc->pk())
$cc->update();
else
$cc->replace();
$result->setSuccess();
}
public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount)
{
$customerVaultId = $this->getDi()->userTable->load($payment->user_id)->data()->get($this->getCustomerVaultVariable());
$tr = new Am_Paysystem_Networkmerchants_Transaction_Refund($this, $payment->getInvoice(), $payment->receipt_id, $amount, $customerVaultId);
$tr->run($result);
}
}
library/Am/Paysystem/Echeck.php 0000644 00000052561 15210160104 0012435 0 ustar 00 getPluginUrl(self::ACTION_ECHECK) );
$action->id = $invoice->getSecureId($this->getId());
$result->setAction($action);
}
public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs){}
public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
switch ($request->getActionName())
{
case self::ACTION_IPN:
return parent::directAction($request, $response, $invokeArgs);
case self::ACTION_UPDATE:
return $this->updateAction($request, $response, $invokeArgs);
case self::ACTION_CANCEL:
return $this->doCancelAction($request, $response, $invokeArgs);
case self::ACTION_ECHECK:
default:
return $this->echeckAction($request, $response, $invokeArgs);
}
}
protected function echeckActionValidateSetInvoice(Am_Mvc_Request $request, array $invokeArgs)
{
$invoiceId = $request->getFiltered('id');
if (!$invoiceId)
throw new Am_Exception_InputError("invoice_id is empty - seems you have followed wrong url, please return back to continue");
$invoice = $this->getDi()->invoiceTable->findBySecureId($invoiceId, $this->getId());
if (!$invoice)
throw new Am_Exception_InputError('You have used wrong link for payment page, please return back and try again');
if ($invoice->isCompleted())
throw new Am_Exception_InputError(sprintf(___('Payment is already processed, please go to %sMembership page%s'), "",""));
if ($invoice->paysys_id != $this->getId())
throw new Am_Exception_InputError("You have used wrong link for payment page, please return back and try again");
if ($invoice->tm_added < sqlTime('-30 days'))
throw new Am_Exception_InputError("Invoice expired - you cannot open invoice after 30 days elapsed");
$this->invoice = $invoice; // set for reference
}
/**
* Show echeck info input page, validate it if submitted
*/
public function echeckAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
$this->echeckActionValidateSetInvoice($request, $invokeArgs);
$p = $this->createController($request, $response, $invokeArgs);
$p->setPlugin($this);
$p->setInvoice($this->invoice);
$p->run();
}
/**
* Process echeck update request
* @param Am_Mvc_Request $request
* @param Am_Mvc_Response $response
* @param array $invokeArgs
*/
public function updateAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
$this->getDi()->auth->requireLogin($this->getDi()->url('member',null,false));
$p = $this->createController($request, $response, $invokeArgs);
$p->setPlugin($this);
$p->run();
}
/**
* Process "cancel recurring" request
* @param Am_Mvc_Request $request
* @param Am_Mvc_Response $response
* @param array $invokeArgs
*/
public function doCancelAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
$id = $request->getFiltered('id');
$invoice = $this->getDi()->invoiceTable->findBySecureId($id, 'STOP' . $this->getId());
if (!$invoice)
throw new Am_Exception_InputError("No invoice found [$id]");
if ($invoice->user_id != $this->getDi()->auth->getUserId())
throw new Am_Exception_InternalError("User tried to access foreign invoice: [$id]");
if (method_exists($this, 'cancelInvoice'))
$this->cancelInvoice($invoice);
$invoice->setCancelled();
$response->setRedirect($this->getDi()->url('member/payment-history',null,false));
}
/**
* To be overriden in children classes
* @param Am_Mvc_Request $request
* @param Am_Mvc_Response $response
* @param array $invokeArgs
* @return Am_Mvc_Controller_Echeck
*/
protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
return new Am_Mvc_Controller_Echeck($request, $response, $invokeArgs);
}
/**
* Method must return array of self::ECHECK_xxx constants to control which
* additional fields will be displayed in the form
* @return array
*/
public function getFormOptions()
{
$ret = array(self::ECHECK_ADDRESS, self::ECHECK_COUNTRY, self::ECHECK_STATE, self::ECHECK_CITY, self::ECHECK_STREET, self::ECHECK_ZIP);
return $ret;
}
/**
* You can do form customization necessary for the plugin
* here
*/
public function onFormInit(Am_Form_Echeck $form)
{
}
/**
* You can do custom form validation here. If errors found,
* call $form->getElementById('xx-0')->setError('xxx') and
* return false
* @return bool
*/
public function onFormValidate(Am_Form_Echeck $form)
{
return true;
}
public function doBill(Invoice $invoice, $doFirst, EcheckRecord $echeck = null)
{
$this->invoice = $invoice;
$this->echeck = $echeck;
$result = new Am_Paysystem_Result();
$this->_doBill($invoice, $doFirst, $echeck, $result);
return $result;
}
abstract public function _doBill(Invoice $invoice, $doFirst, EcheckRecord $echeck, Am_Paysystem_Result $result);
/**
* Function can be overrided to change behaviour
*/
public function storeEcheck(EcheckRecord $echeck, Am_Paysystem_Result $result)
{
if ($this->storesCcInfo())
{
$echeck->replace();
$result->setSuccess();
}
return $this;
}
/**
* Method defined for overriding in child classes where EC info is not stored locally
* @return EcRecord
* @param Invoice $invoice
* @throws Am_Exception
*/
public function loadEcheck(Invoice $invoice)
{
if ($this->storesCcInfo())
return $this->getDi()->echeckRecordTable->findFirstByUserId($invoice->user_id);
}
public function prorateInvoice(Invoice $invoice, EcheckRecord $echeck, Am_Paysystem_Result $result, $date)
{
/** @todo use "reattempt" config **/
$reattempt = array_filter($this->getConfig('reattempt', array()));
sort($reattempt);
if (!$reattempt) {
$invoice->setStatus(Invoice::RECURRING_FAILED);
$invoice->updateQuick('rebill_date', null);
return;
}
$first_failure = $invoice->data()->get(self::FIRST_REBILL_FAILURE);
if (!$first_failure)
{
$invoice->data()->set(self::FIRST_REBILL_FAILURE, $date)->update();
$first_failure = $date;
}
$days_diff = (strtotime($date) - strtotime($first_failure)) / (24*3600);
foreach ($reattempt as $day)
if ($day > $days_diff) break; // we have found next rebill date to jump
if ($day <= $days_diff){
// Several rebilling attempts failed already.
// change status to RECURRING_FAILED;
$invoice->setStatus(Invoice::RECURRING_FAILED);
$invoice->updateQuick('rebill_date', null);
return;
}
$invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($first_failure." +$day days")));
$tr = new Am_Paysystem_Transaction_Manual($this);
if ($invoice->getAccessExpire() < $invoice->rebill_date)
$invoice->extendAccessPeriod($invoice->rebill_date);
}
public function onRebillFailure(Invoice $invoice, EcheckRecord $echeck, Am_Paysystem_Result $result, $date)
{
$this->prorateInvoice($invoice, $echeck, $result, $date);
if($this->getDi()->config->get('cc.rebill_failed'))
$this->sendRebillFailedToUser($invoice, $result->getLastError(), $invoice->rebill_date);
}
function sendRebillFailedToUser(Invoice $invoice, $failedReason, $nextRebill)
{
try
{
if($et = Am_Mail_Template::load('cc.rebill_failed'))
{
$et->setError($failedReason);
$et->setUser($invoice->getUser());
$et->setInvoice($invoice);
$et->setProrate(
($nextRebill > $this->getDi()->sqlDate) ?
sprintf(___('Our system will try to charge your card again on %s'), amDate($nextRebill)) : ""
);
$et->setMailPeriodic(Am_Mail::USER_REQUESTED);
$et->send($invoice->getUser());
}
}catch(Exception $e)
{
// No mail exceptions when rebilling;
$this->getDi()->errorLogTable->logException($e);
}
}
function sendRebillSuccessToUser(Invoice $invoice)
{
try
{
if($et = Am_Mail_Template::load('cc.rebill_success'))
{
$et->setUser($invoice->getUser());
$et->setInvoice($invoice);
$et->setAmount($invoice->second_total);
$et->setRebill_date($invoice->rebill_date ? amDate($invoice->rebill_date) : ___('NEVER'));
$et->setMailPeriodic(Am_Mail::USER_REQUESTED);
$et->send($invoice->getUser());
}
}
catch(Exception $e)
{
// No mail exceptions when rebilling;
$this->getDi()->errorLogTable->logException($e);
}
}
public function onRebillSuccess(Invoice $invoice, EcheckRecord $echeck, Am_Paysystem_Result $result, $date)
{
if ($invoice->data()->get(self::FIRST_REBILL_FAILURE))
{
$invoice->addToRebillDate(false, $invoice->data()->get(self::FIRST_REBILL_FAILURE));
$invoice->data()->set(self::FIRST_REBILL_FAILURE, null)->update();
}
if($this->getDi()->config->get('cc.rebill_success'))
$this->sendRebillSuccessToUser($invoice);
}
// called from Bootstrap_Cc
public function ccRebill($date = null)
{
/**
* If plugin can't rebill payments itself, leave it alone.
*/
if($this->getRecurringType() != self::REPORTS_CRONREBILL) return;
$rebillTable = $this->getDi()->ccRebillTable;
$processedCount = 0;
foreach ($this->getDi()->invoiceTable->findForRebill($date, $this->getId()) as $invoice)
{
// Invoice must have status RECURRING_ACTIVE in order to be rebilled;
if($invoice->status != Invoice::RECURRING_ACTIVE)
continue;
// If we already have all payments for this invoice unset rebill_date and update invoice status;
if($invoice->getPaymentsCount() >= $invoice->getExpectedPaymentsCount())
{
$invoice->recalculateRebillDate();
$invoice->updateStatus();
continue;
}
/* @var $invoice Invoice */
try {
$rebill = $rebillTable->createRecord(array(
'paysys_id' => $this->getId(),
'invoice_id' => $invoice->invoice_id,
'rebill_date' => $date,
'status' => CcRebill::STARTED,
'status_msg' => "Not Processed",
));
//only one attempt to rebill per day
try {
$rebill->insert();
} catch (Am_Exception_Db_NotUnique $e) {
continue;
}
$echeck = $this->getDi()->echeckRecordTable->createRecord();
if ($this->storesCcInfo())
{
$echeck = $this->loadEcheck($invoice);
if (!$echeck)
{
$rebill->setStatus(CcRebill::NO_CC, "No credit card/echeck saved, cannot rebill");
continue;
}
}
$result = $this->doBill($invoice, false, $echeck);
if (!$result->isSuccess())
$this->onRebillFailure($invoice, $echeck, $result, $date);
else
$this->onRebillSuccess($invoice, $echeck, $result, $date);
$rebill->setStatus($result->isSuccess() ? CcRebill::SUCCESS : CcRebill::ERROR,
current($result->getErrorMessages()));
$processedCount++;
} catch (Exception $e) {
if (stripos(get_class($e), 'PHPUnit_')===0) throw $e;
$rebill->setStatus(CcRebill::EXCEPTION,
"Exception " . get_class($e) . " : " . $e->getMessage());
// if there was an exception in billing (say internal error),
// we set rebill_date to tomorrow
$invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($invoice->rebill_date . ' +1 day')));
$this->getDi()->errorLogTable->logException($e);
$this->logError("Exception on rebilling", $e, $invoice);
unset($this->invoice);
}
}
// Send message only if rebill executed by cron;
if($this->getDi()->config->get('cc.admin_rebill_stats')
&& (is_null($date) || $date == $this->getDi()->sqlDate)
&& $processedCount)
$this->sendStatisticsEmail();
}
protected function getStatisticsRow(Array $r)
{
if($r['status']!= CcRebill::SUCCESS)
{
$failed = "Reason: ".$r['status_msg'];
if($r['rebill_date']>$this->getDi()->sqlDate)
$failed .= "\t Next Rebill Date: ".$r['rebill_date'];
}else
$failed = '';
$row = sprintf("%s, %s, %s %s, \nInvoice: %s\tAmount: %s\t%s\n%s\n\n",
$r['email'], $r['login'], $r['name_f'], $r['name_l'],
$r['public_id'], $r['second_total'], $failed,
$this->getDi()->url(array('admin-user-payments/index/user_id/%s#invoice-%s', $r['user_id'], $r['invoice_id']))
);
return $row;
}
protected function sendStatisticsEmail()
{
$date = $this->getDi()->sqlDate;
$success = $failed = "";
$success_count = $failed_count = $success_amount = $failed_amount = 0;
if ($et = Am_Mail_Template::load('cc.admin_rebill_stats'))
{
foreach($this->getDi()->db->selectPage($total, "
SELECT r.*, i.second_total, i.user_id, i.invoice_id, i.public_id, i.rebill_date, u.name_f, u.name_l, u.email, u.login
FROM ?_cc_rebill r LEFT JOIN ?_invoice i USING(invoice_id) LEFT JOIN ?_user u ON(i.user_id = u.user_id)
WHERE status_tm>? and status_tm<=? and r.paysys_id=?
", $date, $this->getDi()->sqlDateTime, $this->getId()) as $r)
{
if($r['status'] == CcRebill::SUCCESS)
{
$success_count++; $success_amount+=$r['second_total'];
$success .= $this->getStatisticsRow($r);
}else{
$failed_count++; $failed_amount += $r['second_total'];
$failed .= $this->getStatisticsRow($r);;
}
}
if($success || $failed)
{
$currency = $this->getDi()->config->get('currency');
$et->setShort_stats(sprintf(___('Success: %d (%0.2f %s) Failed: %d (%0.2f %s)'),
$success_count, $success_amount, $currency, $failed_count, $failed_amount, $currency));
$et->setRebills_success(!empty($success) ? $success : ___('No items in this section'));
$et->setRebills_failed(!empty($failed) ? $failed : ___('No items in this section'));
$et->setPlugin($this->getId());
$et->setMailPeriodic(Am_Mail::ADMIN_REQUESTED);
$et->sendAdmin();
}
}
}
protected function _afterInitSetupForm(Am_Form_Setup $form)
{
// insert title, description fields
$form->setTitle(ucfirst(toCamelCase($this->getId())));
$el = $form->addMagicSelect('reattempt', array('multiple'=>'multiple'));
$options = array();
for ($i=1;$i<60;$i++) $options[$i] = ___("on %d-th day", $i);
$el->loadOptions($options);
$el->setLabel(___("Retry On Failure\n".
"if the recurring billing has failed,\n".
"aMember can repeat it after several days,\n".
"and extend customer subscription for that period\n".
"enter number of days to repeat billing attempt"));
if($this->storesCcInfo() && !$this->_pciDssNotRequired)
{
$text = "
WARNING! Every application processing e-check information, must be certified\n" .
"as PA-DSS compliant, and every website processing credit cards must\n" .
"be certified as PCI-DSS compliant.
";
$text.= "aMember Pro is not yet certified as PA-DSS compliant. We will start certification process\n".
"once we get 4.2.0 branch released and stable. This plugins is provided solely for TESTING purproses\n".
"Use it for anything else but testing at your own risk.
";
$form->addProlog(<<
$text
CUT
);
}
$keyFile = defined('AM_KEYFILE') ? AM_KEYFILE : AM_APPLICATION_PATH . '/configs/key.php';
if (!is_readable($keyFile))
{
$random = $this->getDi()->security->randomString(78);
$text = "To use credit card plugins, you need to create a key file that contains unique\n";
$text .= "encryption key for your website. It is necessary even if the plugin does not\n";
$text .= "store sensitive information.
";
$text .= "In a text editor, create file with the following content (one-line, no spaces before opening <?php):\n";
$text .= "
<?php return '$random';
\n";
$text .= "
save the file as key.php, and upload to amember/application/configs/ folder.\n";
$text .= "This warning will disappear once you do it correctly.";
$text .= "KEEP A BACKUP COPY OF THE key.php FILE (!)
";
$form->addProlog(<<
$text
CUT
);
}
return parent::_afterInitSetupForm($form);
}
/**
* If plugin require special actions to cancel invoice, cancelInvoice will be called
* after Invoice will actually be cancelled by CreditCard Controller.
* do nothing by default;
* @throws Am_Exception_InputError if failure;
* @param Invoice $invoice
*/
function cancelInvoice(Invoice $invoice)
{
return true;
}
public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result)
{
$invoice->setCancelled(true);
}
public function getUpdateEcheckLink($user)
{
if ($this->storesCcInfo() &&
$this->getDi()->echeckRecordTable->findFirstByUserId($user->user_id))
{
return $this->getPluginUrl('update');
}
}
} library/Am/Paysystem/Transaction/Echeck.php 0000644 00000006045 15210160104 0014716 0 ustar 00 setInvoice($invoice);
$this->request = $request;
$this->doFirst = $doFirst;
}
public function run(Am_Paysystem_Result $result)
{
$this->result = $result;
$log = $this->getInvoiceLog();
$log->add($this->request);
$this->response = $this->request->send();
$log->add($this->response);
$this->validateResponseStatus($this->result);
if ($this->result->isFailure())
return;
try {
$this->parseResponse();
// validate function must set success status
$this->validate();
if ($this->result->isSuccess())
$this->processValidated();
} catch (Exception $e) {
if ($e instanceof PHPUnit_Framework_Error)
throw $e;
if ($e instanceof PHPUnit_Framework_Asser )
throw $e;
if (!$result->isFailure())
$result->setFailed(___("Payment failed"));
$log->add($e);
}
}
/**
* Must operate $this->result to set error status or call
* $result->setSuccess if all ok
*/
public function validate()
{
}
/**
* Parse response and return it, it will be placed to @link $this->vars
* @return mixed
*/
abstract public function parseResponse();
public function validateResponseStatus(Am_Paysystem_Result $result)
{
if ($this->response->getStatus() != 200)
{
$result->setFailed(array("Received invalid response from payment server: " . $this->response->getStatus()));
}
}
/** @return InvoiceLog */
function getInvoiceLog()
{
if (!$this->log)
{
$this->log = $this->plugin->getDi()->invoiceLogRecord;
if ($this->invoice)
{
$this->log->invoice_id = $this->invoice->invoice_id;
$this->log->user_id = $this->invoice->user_id;
}
$this->log->paysys_id = $this->getPlugin()->getId();
$this->log->remote_addr = $_SERVER['REMOTE_ADDR'];
foreach ($this->plugin->getConfig() as $k => $v)
if (is_scalar($v) && (strlen($v) > 4))
$this->log->mask($v);
}
return $this->log;
}
} library/Am/Paysystem/Transaction/CreditCard.php 0000644 00000006032 15210160104 0015534 0 ustar 00 setInvoice($invoice);
$this->request = $request;
$this->doFirst = $doFirst;
}
public function run(Am_Paysystem_Result $result)
{
$this->result = $result;
$log = $this->getInvoiceLog();
$log->add($this->request);
$this->response = $this->request->send();
$log->add($this->response);
$this->validateResponseStatus($this->result);
if ($this->result->isFailure())
return;
try {
$this->parseResponse();
// validate function must set success status
$this->validate();
if ($this->result->isSuccess())
$this->processValidated();
} catch (Exception $e) {
if ($e instanceof PHPUnit_Framework_Error)
throw $e;
if ($e instanceof PHPUnit_Framework_Asser )
throw $e;
if (!$result->isFailure())
$result->setFailed(___("Payment failed"));
$log->add($e);
}
}
/**
* Must operate $this->result to set error status or call
* $result->setSuccess if all ok
*/
public function validate()
{
}
/**
* Parse response and return it, it will be placed to @link $this->vars
* @return mixed
*/
abstract public function parseResponse();
public function validateResponseStatus(Am_Paysystem_Result $result)
{
//nop, it is not necessary to validate it here. In most cases REST API
//can return different status with detailed
//error messages instead of our common one
}
/** @return InvoiceLog */
function getInvoiceLog()
{
if (!$this->log)
{
$this->log = $this->plugin->getDi()->invoiceLogRecord;
if ($this->invoice)
{
$this->log->invoice_id = $this->invoice->invoice_id;
$this->log->user_id = $this->invoice->user_id;
}
$this->log->paysys_id = $this->getPlugin()->getId();
$this->log->remote_addr = $_SERVER['REMOTE_ADDR'];
foreach ($this->plugin->getConfig() as $k => $v)
if (is_scalar($v) && (strlen($v) > 4))
$this->log->mask($v);
}
return $this->log;
}
} library/Am/Paysystem/Transaction/Maxmind/Minfraud.php 0000644 00000007027 15210160104 0016677 0 ustar 00 body = $this->response->getBody();
$this->vars = array();
$list = explode(';', $this->body);
foreach ($list as $l)
{
list($key, $value) = explode('=', $l);
$this->vars[$key] = $value;
}
}
public function isEmpty()
{
if (!@array_key_exists('countryMatch', (array) $this->vars))
return false;
return empty($this->body);
}
public function validate()
{
$this->riskscore = $this->vars['riskScore'];
$payment_records_edit_log = array();
if ($this->vars['carderEmail'] == 'Yes')
$payment_records_edit_log[] = 'Email is in database of high risk e-mails';
if ($this->vars['countryMatch'] == 'No' && !$this->plugin->getConfig('maxmind_allow_country_not_matched'))
$payment_records_edit_log[] = 'Country of IP address not matches billing address country';
if ($this->vars['highRiskCountry'] == 'Yes' && !$this->plugin->getConfig('maxmind_allow_high_risk_country'))
$payment_records_edit_log[] = 'IP address or billing address country is in high risk countries list';
if ($this->vars['anonymousProxy'] == 'Yes' && !$this->plugin->getConfig('maxmind_allow_anonymous_proxy'))
$payment_records_edit_log[] = 'Anonymous proxy are not allowed';
if ($this->vars['freeMail'] == 'Yes' && !$this->plugin->getConfig('maxmind_allow_free_mail'))
$payment_records_edit_log[] = 'E-mail from free e-mail provider are not allowed';
if ($this->vars['queriesRemaining'] > 0 && $this->vars['queriesRemaining'] < 10)
Am_Di::getInstance()->errorLogTable->log("MaxMind queriesRemaining: " . $this->vars['queriesRemaining']);
$ccfd_warnings = array(
'IP_NOT_FOUND',
'COUNTRY_NOT_FOUND',
'CITY_NOT_FOUND',
'CITY_REQUIRED',
'POSTAL_CODE_REQUIRED',
'POSTAL_CODE_NOT_FOUND'
);
$ccfd_fatal_errors = array(
'INVALID_LICENSE_KEY',
'MAX_REQUESTS_PER_LICENSE',
'IP_REQUIRED',
'LICENSE_REQUIRED',
'COUNTRY_REQUIRED',
'MAX_REQUESTS_REACHED'
);
if (count($payment_records_edit_log))
$this->riskscore = 99;
if ($this->vars['err'] || count($payment_records_edit_log))
{
if (in_array($this->vars['err'], $ccfd_warnings))
Am_Di::getInstance()->errorLogTable->log("MaxMind warning: " . $this->vars['err'] . " maxmindID: " . $this->vars['maxmindID']);
if (in_array($this->vars['err'], $ccfd_fatal_errors))
{
$payment_records_edit_log[] = $this->vars['err'];
}
if (count($payment_records_edit_log))
{
$this->getInvoiceLog()->add($payment_records_edit_log);
return $this->result->setFailed(___('Payment failed'));
}
}
if($this->riskscore > $this->getPlugin()->getConfig('maxmind_risk_score'))
return $this->result->setFailed(___('Payment failed'));
$this->result->setSuccess($this);
}
public function getRiskScore()
{
return $this->riskscore;
}
public function processValidated()
{
//do nothing
}
}
library/Am/Paysystem/Transaction/Maxmind/Number.php 0000644 00000002104 15210160104 0016351 0 ustar 00 body = $this->response->getBody();
$this->vars = array();
$list = explode(';', $this->body);
foreach ($list as $l)
{
list($key, $value) = explode('=', $l);
$this->vars[$key] = $value;
}
}
public function isEmpty()
{
if (!array_key_exists('phoneType', $this->vars))
return false;
return empty($this->body);
}
public function validate()
{
if ($this->vars['err'])
return $this->result->setFailed(___('Payment failed'));
if(!in_array($this->vars['phoneType'], $this->getPlugin()->getConfig('maxmind_tni_phone_types')))
return $this->result->setFailed(___('Payment failed'));
$this->result->setSuccess($this);
}
public function processValidated()
{
//do nothing
}
}
library/Am/Paysystem/Transaction/Maxmind/Phone.php 0000644 00000001620 15210160104 0016174 0 ustar 00 body = $this->response->getBody();
$this->vars = array();
$list = explode(';', $this->body);
foreach ($list as $l)
{
list($key, $value) = explode('=', $l);
$this->vars[$key] = $value;
}
}
public function isEmpty()
{
if (!array_key_exists('refid', $this->vars))
return false;
return empty($this->body);
}
public function validate()
{
if ($this->vars['err'])
return $this->result->setFailed(___('Payment failed'));
$this->result->setSuccess($this);
}
public function processValidated()
{
//do nothing
}
}
library/Am/Paysystem/CreditCard.php 0000644 00000105403 15210160104 0013251 0 ustar 00 getPluginUrl(self::ACTION_CC) );
$action->id = $invoice->getSecureId($this->getId());
$result->setAction($action);
}
public function createTransaction(/*Am_Mvc_Request */$request, /*Am_Mvc_Response */$response, array $invokeArgs){}
public function directAction(/*Am_Mvc_Request */$request, /*Am_Mvc_Response */$response, $invokeArgs)
{
switch ($request->getActionName())
{
case self::ACTION_IPN:
return parent::directAction($request, $response, $invokeArgs);
case self::ACTION_UPDATE:
return $this->updateAction($request, $response, $invokeArgs);
case self::ACTION_CANCEL:
return $this->doCancelAction($request, $response, $invokeArgs);
case self::ACTION_CANCEL_PAYMENT:
return $this->cancelPaymentAction($request, $response, $invokeArgs);
case self::ACTION_THANKS:
return $this->thanksAction($request, $response, $invokeArgs);
case self::ACTION_CC:
default:
return $this->ccAction($request, $response, $invokeArgs);
}
}
protected function ccActionValidateSetInvoice(Am_Mvc_Request $request, array $invokeArgs)
{
$invoiceId = $request->getFiltered('id');
if (!$invoiceId)
throw new Am_Exception_InputError("invoice_id is empty - seems you have followed wrong url, please return back to continue");
$invoice = $this->getDi()->invoiceTable->findBySecureId($invoiceId, $this->getId());
if (!$invoice)
throw new Am_Exception_InputError('You have used wrong link for payment page, please return back and try again');
if ($invoice->isCompleted())
throw new Am_Exception_InputError(sprintf(___('Payment is already processed, please go to %sMembership page%s'), "",""));
if ($invoice->paysys_id != $this->getId())
throw new Am_Exception_InputError("You have used wrong link for payment page, please return back and try again");
if ($invoice->tm_added < sqlTime('-30 days'))
throw new Am_Exception_InputError("Invoice expired - you cannot open invoice after 30 days elapsed");
$this->invoice = $invoice; // set for reference
}
/**
* Show credit card info input page, validate it if submitted
*/
public function ccAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
$this->ccActionValidateSetInvoice($request, $invokeArgs);
$p = $this->createController($request, $response, $invokeArgs);
$p->setPlugin($this);
$p->setInvoice($this->invoice);
$p->run();
}
/**
* Process credit card update request
* @param Am_Mvc_Request $request
* @param Am_Mvc_Response $response
* @param array $invokeArgs
*/
public function updateAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
$this->getDi()->auth->requireLogin($this->getDi()->url('member',null,false));
$p = $this->createController($request, $response, $invokeArgs);
$p->setPlugin($this);
$p->run();
}
/**
* Process "cancel recurring" request
* @param Am_Mvc_Request $request
* @param Am_Mvc_Response $response
* @param array $invokeArgs
*/
public function doCancelAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
$id = $request->getFiltered('id');
$invoice = $this->getDi()->invoiceTable->findBySecureId($id, 'STOP'.$this->getId());
if (!$invoice)
throw new Am_Exception_InputError("No invoice found [$id]");
if ($invoice->user_id != $this->getDi()->auth->getUserId())
throw new Am_Exception_InternalError("User tried to access foreign invoice: [$id]");
if (method_exists($this, 'cancelInvoice'))
$this->cancelInvoice($invoice);
$invoice->setCancelled();
$response->setRedirect($this->getDi()->surl('member/payment-history', false));
}
public function cancelPaymentAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
$id = $request->getFiltered('id');
if (!$id && isset($_GET['id'])) $id = filterId($_GET['id']);
$invoice = $this->getDi()->invoiceTable->findFirstByPublicId($id);
if (!$invoice)
throw new Am_Exception_InputError("No invoice found [$id]");
if ($invoice->user_id != $this->getDi()->auth->getUserId())
throw new Am_Exception_InternalError("User tried to access foreign invoice: [$id]");
$this->invoice = $invoice;
// find invoice and redirect to default "cancel" page
$response->setRedirect($this->getCancelUrl());
}
/**
* To be overriden in children classes
* @param Am_Mvc_Request $request
* @param Am_Mvc_Response $response
* @param array $invokeArgs
* @return \Am_Mvc_Controller_CreditCard
*/
protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs)
{
return new Am_Mvc_Controller_CreditCard($request, $response, $invokeArgs);
}
/**
* Method must return array of self::CC_xxx constants to control which
* additional fields will be displayed in the form
* @return array
*/
public function getFormOptions(){
$ret = array(self::CC_CODE, self::CC_ADDRESS, self::CC_COUNTRY, self::CC_STATE, self::CC_CITY, self::CC_STREET, self::CC_ZIP);
if ($this->getCreditCardTypeOptions()) $ret[] = self::CC_TYPE_OPTIONS;
return $ret;
}
/**
*
*/
public function getCreditCardTypeOptions(){
return array();
}
/**
* You can do form customization necessary for the plugin
* here
*/
public function onFormInit(Am_Form_CreditCard $form)
{
}
/**
* You can do custom form validation here. If errors found,
* call $form->getElementById('xx-0')->setError('xxx') and
* return false
* @return bool
*/
public function onFormValidate(Am_Form_CreditCard $form)
{
return true;
}
/**
* Filter and validate cc#
* @return null|string null if ok, error message if error
*/
public function validateCreditCardNumber($cc){
require_once 'ccvs.php';
$validator = new CreditCardValidationSolution;
if (!$validator->validateCreditCard($cc))
return $validator->CCVSError;
/** @todo translate error messages from ccvs.php */
return null;
}
public function doBill(Invoice $invoice, $doFirst, CcRecord $cc = null)
{
$this->invoice = $invoice;
$this->cc = $cc;
$result = new Am_Paysystem_Result();
$this->_doBill($invoice, $doFirst, $cc, $result);
return $result;
}
public function doMaxmindCheck(Invoice $invoice, CcRecord $cc)
{
$result = new Am_Paysystem_Result();
$user = $invoice->getUser();
$server = array(
'minfraud.maxmind.com',
'minfraud-us-east.maxmind.com',
'minfraud-us-west.maxmind.com'
);
$i = 0;
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
{
$client_ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
$forwarded_ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
else
{
if (isset($_SERVER["HTTP_CLIENT_IP"]))
$client_ip = $_SERVER["HTTP_CLIENT_IP"];
else
$client_ip = $_SERVER["REMOTE_ADDR"];
$forwarded_ip = '';
}
$ps = new stdclass;
$ps->license_key = $this->getConfig('maxmind_license_key');
$ps->bin = substr($cc->cc_number, 0, 6);
$ps->i = $client_ip;
$ps->forwardedIP = $forwarded_ip;
$ps->city = $cc->cc_city;
$ps->region = $cc->cc_state;
$ps->country = $cc->cc_country;
$ps->postal = $cc->cc_zip;
list($acc, $domain) = @explode('@', $user->email, 2);
$ps->domain = $domain;
$ps->emailMD5 = md5(strtolower($user->email));
$ps->usernameMD5 = md5($user->login);
$ps->custPhone = $cc->cc_phone;
$ps->requested_type = $this->getConfig('maxmind_requested_type');
$ps->shipAddr = $cc->cc_street;
$ps->shipCity = $cc->cc_city;
$ps->shipRegion = $cc->cc_city;
$ps->shipPostal = $cc->cc_city;
$ps->shipCountry = $cc->cc_city;
$ps->txnID = $invoice->public_id;
$ps->sessionID = md5(session_id());
$ps->user_agent = $_SERVER['HTTP_USER_AGENT'];
$request = $this->createHttpRequest();
$request->addPostParameter((array) $ps);
$request->setMethod(Am_HttpRequest::METHOD_POST);
do
{
//minfraud verification
$request->setUrl('https://' . $server[$i] . '/app/ccv2r');
$transaction = new Am_Paysystem_Transaction_Maxmind_Minfraud($this, $invoice, $request, true);
$transaction->run($result);
$i++;
}
while ($i < count($server) && $transaction->isEmpty());
$risk_score = $transaction->getRiskScore();
if ($this->getConfig('maxmind_use_telephone_verification') &&
$risk_score >= $this->getConfig('maxmind_risk_score') &&
$risk_score <= 10 &&
!empty($cc->cc_phone))
{
//number identification
if($this->getConfig('maxmind_use_number_identification'))
{
$result_number = new Am_Paysystem_Result();
$i = 0;
$ps = new stdclass;
$ps->l = $this->getConfig('maxmind_license_key');
$ps->phone = preg_replace("/[^\d]+/i", "", $cc->cc_phone);
$request_number = $this->createHttpRequest();
$request_number->addPostParameter((array) $ps);
$request_number->setMethod(Am_HttpRequest::METHOD_POST);
do
{
$request_number->setUrl('https://' . $server[$i] . '/app/phone_id_http');
$transaction = new Am_Paysystem_Transaction_Maxmind_Number($this, $invoice, $request_number, true);
$transaction->run($result_number);
$i++;
}
while ($i < count($server) && $transaction->isEmpty());
if($result_number->isFailure())
return $result_number;
}
//phone verification
/*if($this->getConfig('maxmind_use_telephone_verification'))
{
$result_phone= new Am_Paysystem_Result();
$i = 0;
$ps = new stdclass;
$ps->l = $this->getConfig('maxmind_license_key');
$ps->phone = preg_replace("/[^\d]+/i", "", $cc->cc_phone);
$request_phone = $this->createHttpRequest();
$request_phone->addPostParameter((array) $ps);
$request_phone->setMethod(Am_HttpRequest::METHOD_POST);
do
{
$request_phone->setUrl('https://' . $server[$i] . '/app/telephone_http');
$transaction = new Am_Paysystem_Transaction_Maxmind_Phone($this, $invoice, $request_phone, true);
$transaction->run($result_phone);
$i++;
}
while ($i < count($server) && $transaction->isEmpty());
if($result_phone->isFailure())
return $result_phone;
}*/
}
return $result;
}
abstract public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result);
/**
* Function can be overrided to change behaviour
*/
public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result)
{
if ($this->storesCcInfo())
{
$cc->replace();
$result->setSuccess();
}
return $this;
}
/**
* Method defined for overriding in child classes where CC info is not stored locally
* @return CcRecord
* @param Invoice $invoice
* @throws Am_Exception
*/
public function loadCreditCard(Invoice $invoice)
{
if ($this->storesCcInfo())
return $this->getDi()->ccRecordTable->findFirstByUserId($invoice->user_id);
}
public function prorateInvoice(Invoice $invoice, CcRecord $cc, Am_Paysystem_Result $result, $date)
{
/** @todo use "reattempt" config **/
$reattempt = array_filter($this->getConfig('reattempt', array()));
sort($reattempt);
if (!$reattempt) {
$invoice->setStatus(Invoice::RECURRING_FAILED);
$invoice->updateQuick('rebill_date', null);
return;
}
$first_failure = $invoice->data()->get(self::FIRST_REBILL_FAILURE);
if (!$first_failure)
{
$invoice->data()->set(self::FIRST_REBILL_FAILURE, $date)->update();
$first_failure = $date;
}
$days_diff = (strtotime($date) - strtotime($first_failure)) / (24*3600);
foreach ($reattempt as $day)
if ($day > $days_diff) break; // we have found next rebill date to jump
if ($day <= $days_diff){
// Several rebilling attempts failed already.
// change status to RECURRING_FAILED;
$invoice->setStatus(Invoice::RECURRING_FAILED);
$invoice->updateQuick('rebill_date', null);
return;
}
$invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($first_failure." +$day days")));
$tr = new Am_Paysystem_Transaction_Manual($this);
if ($invoice->getAccessExpire() < $invoice->rebill_date)
$invoice->extendAccessPeriod($invoice->rebill_date);
}
public function onRebillFailure(Invoice $invoice, CcRecord $cc, Am_Paysystem_Result $result, $date)
{
$this->prorateInvoice($invoice, $cc, $result, $date);
if($this->getDi()->config->get('cc.rebill_failed'))
$this->sendRebillFailedToUser($invoice, $result->getLastError(), $invoice->rebill_date);
}
function sendRebillFailedToUser(Invoice $invoice, $failedReason, $nextRebill)
{
try
{
if($et = Am_Mail_Template::load('cc.rebill_failed'))
{
$et->setError($failedReason);
$et->setUser($invoice->getUser());
$et->setInvoice($invoice);
$et->setProrate(
($nextRebill > $this->getDi()->sqlDate) ?
sprintf(___('Our system will try to charge your card again on %s'), amDate($nextRebill)) : ""
);
$et->setMailPeriodic(Am_Mail::USER_REQUESTED);
$et->send($invoice->getUser());
}
}catch(Exception $e)
{
// No mail exceptions when rebilling;
$this->getDi()->errorLogTable->logException($e);
}
}
function sendRebillSuccessToUser(Invoice $invoice)
{
try
{
if($et = Am_Mail_Template::load('cc.rebill_success'))
{
$et->setUser($invoice->getUser());
$et->setInvoice($invoice);
$et->setAmount($invoice->second_total);
$et->setRebill_date($invoice->rebill_date ? amDate($invoice->rebill_date) : ___('NEVER'));
$et->setMailPeriodic(Am_Mail::USER_REQUESTED);
$et->send($invoice->getUser());
}
}
catch(Exception $e)
{
// No mail exceptions when rebilling;
$this->getDi()->errorLogTable->logException($e);
}
}
public function onRebillSuccess(Invoice $invoice, CcRecord $cc, Am_Paysystem_Result $result, $date)
{
if ($invoice->data()->get(self::FIRST_REBILL_FAILURE))
{
$invoice->addToRebillDate(false, $invoice->data()->get(self::FIRST_REBILL_FAILURE));
$invoice->data()->set(self::FIRST_REBILL_FAILURE, null)->update();
}
if($this->getDi()->config->get('cc.rebill_success'))
$this->sendRebillSuccessToUser($invoice);
}
public function ccRebill($date = null)
{
/**
* If plugin can't rebill payments itself, leave it alone.
*/
if($this->getRecurringType() != self::REPORTS_CRONREBILL) return;
$rebillTable = $this->getDi()->ccRebillTable;
$processedCount = 0;
foreach ($this->getDi()->invoiceTable->findForRebill($date, $this->getId()) as $invoice)
{
// Invoice must have status RECURRING_ACTIVE in order to be rebilled;
if($invoice->status != Invoice::RECURRING_ACTIVE)
continue;
// If we already have all payments for this invoice unset rebill_date and update invoice status;
if($invoice->getPaymentsCount() >= $invoice->getExpectedPaymentsCount())
{
$invoice->recalculateRebillDate();
$invoice->updateStatus();
continue;
}
/* @var $invoice Invoice */
try {
$rebill = $rebillTable->createRecord(array(
'paysys_id' => $this->getId(),
'invoice_id' => $invoice->invoice_id,
'rebill_date' => $date,
'status' => CcRebill::STARTED,
'status_msg' => "Not Processed",
));
//only one attempt to rebill per day
try {
$rebill->insert();
} catch (Am_Exception_Db_NotUnique $e) {
continue;
}
$cc = $this->getDi()->CcRecordRecord;
if ($this->storesCcInfo())
{
$cc = $this->loadCreditCard($invoice);
if (!$cc)
{
$rebill->setStatus(CcRebill::NO_CC, "No credit card saved, cannot rebill");
continue;
}
}
$result = $this->doBill($invoice, false, $cc);
if (!$result->isSuccess())
$this->onRebillFailure($invoice, $cc, $result, $date);
else
$this->onRebillSuccess($invoice, $cc, $result, $date);
$rebill->setStatus($result->isSuccess() ? CcRebill::SUCCESS : CcRebill::ERROR,
current($result->getErrorMessages()));
$processedCount++;
} catch (Exception $e) {
if (stripos(get_class($e), 'PHPUnit_')===0) throw $e;
$rebill->setStatus(CcRebill::EXCEPTION,
"Exception " . get_class($e) . " : " . $e->getMessage());
// if there was an exception in billing (say internal error),
// we set rebill_date to tomorrow
$invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($invoice->rebill_date . ' +1 day')));
$this->getDi()->errorLogTable->logException($e);
$this->logError("Exception on rebilling", $e, $invoice);
unset($this->invoice);
}
}
// Send message only if rebill executed by cron;
if($this->getDi()->config->get('cc.admin_rebill_stats')
&& (is_null($date) || $date == $this->getDi()->sqlDate)
&& $processedCount)
$this->sendStatisticsEmail();
}
protected function getStatisticsRow(Array $r)
{
if($r['status']!= CcRebill::SUCCESS)
{
$failed = "Reason: ".$r['status_msg'];
if($r['rebill_date']>$this->getDi()->sqlDate)
$failed .= "\t Next Rebill Date: ".$r['rebill_date'];
}else
$failed = '';
$row = sprintf("%s, %s, %s %s, \nInvoice: %s\tAmount: %s\t%s\n%s\n\n",
$r['email'], $r['login'], $r['name_f'], $r['name_l'],
$r['public_id'], $r['second_total'], $failed,
$this->getDi()->url(array('admin-user-payments/index/user_id/%s#invoice-%s', $r['user_id'], $r['invoice_id']))
);
return $row;
}
protected function sendStatisticsEmail()
{
$date = $this->getDi()->sqlDate;
$success = $failed = "";
$success_count = $failed_count = $success_amount = $failed_amount = 0;
if ($et = Am_Mail_Template::load('cc.admin_rebill_stats'))
{
foreach($this->getDi()->db->selectPage($total, "
SELECT r.*, i.second_total, i.user_id, i.invoice_id, i.public_id, i.rebill_date, u.name_f, u.name_l, u.email, u.login
FROM ?_cc_rebill r LEFT JOIN ?_invoice i USING(invoice_id) LEFT JOIN ?_user u ON(i.user_id = u.user_id)
WHERE status_tm>? and status_tm<=? and r.paysys_id=?
", $date, $this->getDi()->sqlDateTime, $this->getId()) as $r)
{
if($r['status'] == CcRebill::SUCCESS)
{
$success_count++; $success_amount+=$r['second_total'];
$success .= $this->getStatisticsRow($r);
}else{
$failed_count++; $failed_amount += $r['second_total'];
$failed .= $this->getStatisticsRow($r);;
}
}
if($success || $failed)
{
$currency = $this->getDi()->config->get('currency');
$et->setShort_stats(sprintf(___('Success: %d (%0.2f %s) Failed: %d (%0.2f %s)'),
$success_count, $success_amount, $currency, $failed_count, $failed_amount, $currency));
$et->setRebills_success(!empty($success) ? $success : ___('No items in this section'));
$et->setRebills_failed(!empty($failed) ? $failed : ___('No items in this section'));
$et->setPlugin($this->getId());
$et->setMailPeriodic(Am_Mail::ADMIN_REQUESTED);
$et->sendAdmin();
}
}
}
protected function _afterInitSetupForm(Am_Form_Setup $form)
{
// insert title, description fields
$form->setTitle(ucfirst(toCamelCase($this->getId())));
$el = $form->addMagicSelect('reattempt', array('multiple'=>'multiple'));
$options = array();
for ($i=1;$i<60;$i++) $options[$i] = ___("on %d-th day", $i);
$el->loadOptions($options);
$el->setLabel(___("Retry On Failure\n".
"if the recurring billing has failed,\n".
"aMember can repeat it after several days,\n".
"and extend customer subscription for that period\n".
"enter number of days to repeat billing attempt"));
if($this->canUseMaxmind())
{
$form->addFieldset()->setLabel(___('MaxMind Credit Card Fraud Detection'));
$form->addAdvCheckbox('use_maxmind')->setLabel(___('Use MaxMind Credit Card Fraud Detection'));
$form->addText('maxmind_license_key')->setLabel(
___("Maxmind License Key\n" .
"%sObtain a Free or Premium license key%s", '', ''));
$form->addSelect('maxmind_requested_type')->setLabel(
___("Requested Type\n" .
"To be used if you have multiple plans in one account\n" .
"and wish to select type of query you wish to make.\n" .
"By default the service uses the highest level available"))
->loadOptions(array(
"" => 'Default',
"free" => 'Free',
"city" => 'City (standard paid service)',
"premium" => 'Premium (premium paid service)'));
$form->addText('maxmind_risk_score')->setLabel(
___("Risk Score\n" .
"Overall %sRisk Score%s (decimal from 0 to 10)\n" .
"For orders that return a fraud score of 2.5 and above,\n" .
" it is recommended to hold for review,\n" .
" or require the validation with the Telephone Verification service\n", '', ''));
$form->setDefault('maxmind_risk_score', '2.5');
/*$form->addAdvCheckbox('maxmind_use_telephone_verification')->setLabel(
___("Telephone Verification\n" .
"Enable %sTelephone Verification%s service"
, '', ''));*/
$form->addAdvCheckbox('maxmind_use_number_identification')->setLabel(
___("Number Identification\n" .
"Enable %sTelephone Number Identification (TNI)%s service", '', ''));
$form->addMagicSelect('maxmind_tni_phone_types')->setLabel(
___("Allowed Phone Types\n" .
"The TNI service is able to categorize customer inputted US and Canadian\n" .
"phone numbers into %seight different phone types%s\n" .
"such as fixed land line, mobile, VoIP, and invalid phone numbers", '', ''))
->loadOptions(array(
'0' => 'Undetermined (Medium Risk Level)',
'1' => 'Fixed Line (Low Risk Level)',
'2' => 'Mobile (Low-Medium Risk Level)',
'3' => 'PrePaid Mobile (Medium-High Risk Level)',
'4' => 'Toll-Free (High Risk Level)',
'5' => 'Non-Fixed VoIP (High Risk Level)',
'8' => 'Invalid Number (High Risk Level)',
'9' => 'Restricted Number (High Risk Level)'));
$form->addAdvCheckbox('maxmind_allow_country_not_matched')->setLabel(
___("Allow payment if country not matched\n" .
"Whether country of IP address matches billing address country\n" .
"(mismatch = higher risk)"));
$form->addAdvCheckbox('maxmind_allow_high_risk_country')->setLabel(
___("Allow payment if high risk countries\n" .
"Whether IP address or billing address country is in\n" .
"Egypt, Ghana, Indonesia, Lebanon, Macedonia, Morocco, Nigeria,\n" .
"Pakistan, Romania, Serbia and Montenegro, Ukraine, or Vietnam"));
$form->addAdvCheckbox('maxmind_allow_anonymous_proxy')->setLabel(
___("Allow payment if anonymous proxy\n" .
"Whether IP address is %sAnonymous Proxy%s\n" .
"(anonymous proxy = very high risk)", '', ''));
$form->addAdvCheckbox('maxmind_allow_free_mail')->setLabel(
___("Allow payment if free e-mail\n" .
"Whether e-mail is from free e-mail provider\n" .
"(free e-mail = higher risk)"));
$form->addElement('script')->setScript(<<storesCcInfo() && !$this->_pciDssNotRequired)
{
$text = "WARNING! Every application processing credit card information, must be certified\n" .
"as PA-DSS compliant, and every website processing credit cards must\n" .
"be certified as PCI-DSS compliant.
";
$text.= "aMember Pro is not yet certified as PA-DSS compliant. ".
"This plugins is provided solely for TESTING purproses\n".
"Use it for anything else but testing at your own risk.
";
$form->addProlog(<<
$text
CUT
);
}
$keyFile = defined('AM_KEYFILE') ? AM_KEYFILE : AM_APPLICATION_PATH . '/configs/key.php';
if (!is_readable($keyFile))
{
$random = $this->getDi()->security->randomString(78);
$text = "To use credit card plugins, you need to create a key file that contains unique\n";
$text .= "encryption key for your website. It is necessary even if the plugin does not\n";
$text .= "store sensitive information.
";
$text .= "In a text editor, create file with the following content (one-line, no spaces before opening <?php):\n";
$text .= "
<?php return '$random';
\n";
$text .= "
save the file as key.php, and upload to amember/application/configs/ folder.\n";
$text .= "This warning will disappear once you do it correctly.";
$text .= "KEEP A BACKUP COPY OF THE key.php FILE (!)
";
$form->addProlog(<<
$text
CUT
);
}
return parent::_afterInitSetupForm($form);
}
/**
* If plugin require special actions to cancel invoice, cancelInvoice will be called
* after Invoice will actually be cancelled by CreditCard Controller.
* do nothing by default;
* @throws Am_Exception_InputError if failure;
* @param Invoice $invoice
*/
function cancelInvoice(Invoice $invoice){
return true;
}
public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result)
{
$result->setSuccess();
$invoice->setCancelled(true);
}
public function getUpdateCcLink($user)
{
if ($this->storesCcInfo() &&
$this->getDi()->ccRecordTable->findFirstByUserId($user->user_id))
{
return $this->getPluginUrl('update');
}
}
public function onDaily()
{
$this->sendCcExpireMessage();
}
public function sendCcExpireMessage()
{
// Send Message only if plugin is allowed to store CC info.
if(!$this->storesCcInfo()) return;
if(!$this->getDi()->config->get('cc.card_expire')) return;
$oRebillDate = $this->getDi()->dateTime;
$oRebillDate->modify(sprintf("+%d days", $this->getDi()->config->get('cc.card_expire_days', 5)));
foreach($this->getDi()->db->selectPage($total, "
SELECT i.invoice_id, c.cc_expire
FROM ?_invoice i LEFT JOIN ?_cc c using(user_id)
WHERE i.status = ? and i.rebill_date = ? and CONCAT(SUBSTR(c.cc_expire, 3,2), SUBSTR(c.cc_expire, 1,2)) < ?
and i.paysys_id = ?
", Invoice::RECURRING_ACTIVE, $oRebillDate->format('Y-m-d'), $oRebillDate->format('ym'), $this->getId()) as $r)
{
$invoice = $this->getDi()->invoiceTable->load($r['invoice_id']);
if($et = Am_Mail_Template::load('cc.card_expire'))
{
$et->setUser($invoice->getUser());
$et->setInvoice($invoice);
$et->setExpires(substr_replace($r['cc_expire'], '/', 2, 0));
$et->setMailPeriodic(Am_Mail::USER_REQUESTED);
$et->send($invoice->getUser());
}
}
}
public function canUseMaxmind()
{
return false;
}
}
library/Am/Paysystem/Networkmerchants/Transaction/Refund.php 0000644 00000001527 15210160104 0020315 0 ustar 00 amount = $amount;
parent::__construct($plugin, $invoice, true);
$this->request->addPostParameter('transactionid', $transactionId);
$this->request->addPostParameter('customer_vault_id', $customerVaultId);
}
public function getAmount()
{
return $this->amount;
}
public function addRequestParams()
{
parent::addRequestParams();
$this->request->addPostParameter('type', 'refund');
$this->request->addPostParameter('amount', $this->getAmount());
}
public function processValidated(){} // no process payment
}
library/Am/Paysystem/Networkmerchants/Transaction/AddCustomer.php 0000644 00000001040 15210160104 0021272 0 ustar 00 setCcRecord($cc);
}
protected function addRequestParams()
{
parent::addRequestParams();
$this->request->addPostParameter('customer_vault', 'add_customer');
}
public function processValidated(){} // no process payment
}
library/Am/Paysystem/Networkmerchants/Transaction/Capture.php 0000644 00000001121 15210160104 0020463 0 ustar 00 request->addPostParameter('transactionid', $transactionid);
}
protected function addRequestParams()
{
parent::addRequestParams();
$this->request->addPostParameter('amount', $this->getAmount());
$this->request->addPostParameter('type', 'capture');
}
}
library/Am/Paysystem/Networkmerchants/Transaction/Sale.php 0000644 00000001123 15210160104 0017746 0 ustar 00 request->addPostParameter('customer_vault_id', $customerVaultId);
}
protected function addRequestParams()
{
parent::addRequestParams();
$this->request->addPostParameter('amount', $this->getAmount());
$this->request->addPostParameter('type', 'sale');
}
}
library/Am/Paysystem/Networkmerchants/Transaction/Void.php 0000644 00000001321 15210160104 0017763 0 ustar 00 request->addPostParameter('transactionid', $transactionId);
$this->request->addPostParameter('customer_vault_id', $customerVaultId);
}
protected function addRequestParams()
{
parent::addRequestParams();
$this->request->addPostParameter('type', 'void');
$this->request->addPostParameter('amount', 1.00);
}
public function processValidated(){} // no process payment
}
library/Am/Paysystem/Networkmerchants/Transaction/Authorization.php 0000644 00000001322 15210160104 0021723 0 ustar 00 amount = $amount;
parent::__construct($plugin, $invoice, true);
$this->setCcRecord($cc);
}
protected function addRequestParams()
{
parent::addRequestParams();
$this->request->addPostParameter('type', 'auth');
$this->request->addPostParameter('amount', $this->amount);
$this->request->addPostParameter('customer_vault', 'add_customer');
}
public function processValidated(){} // no process payment
}
library/Am/Paysystem/Networkmerchants/Transaction.php 0000644 00000005600 15210160104 0017066 0 ustar 00 getGatewayURL(), Am_HttpRequest::METHOD_POST);
parent::__construct($plugin, $invoice, $request, $doFirst);
$this->addRequestParams();
}
private function getUser()
{
return (!$this->plugin->getConfig('testMode')) ? $this->plugin->getConfig('user') : 'demo';
}
private function getPass()
{
return (!$this->plugin->getConfig('testMode')) ? $this->plugin->getConfig('pass') : 'password';
}
public function getAmount()
{
return $this->doFirst ? $this->invoice->first_total : $this->invoice->second_total;
}
protected function addRequestParams()
{
$this->request->addPostParameter('username', $this->getUser());
$this->request->addPostParameter('password', $this->getPass());
}
public function getUniqId()
{
return $this->parsedResponse->transactionid;
}
public function parseResponse()
{
parse_str($this->response->getBody(), $this->parsedResponse);
$this->parsedResponse = (object)$this->parsedResponse;
}
public function validate()
{
switch ($this->parsedResponse->response)
{
case 1:
break;
case 2:
$err = "Transaction Declined.";
break;
case 3:
$err = "Error in transaction data or system error.";
break;
default:
$err = "Unknown error num: " . $this->parsedResponse->response . ".";
break;
}
if (!empty($err))
{
return $this->result->setFailed(array($err, $this->parsedResponse->responsetext));
}
$this->result->setSuccess($this);
}
protected function setCcRecord(CcRecord $cc)
{
$this->request->addPostParameter('ccnumber', $cc->cc_number);
$this->request->addPostParameter('ccexp', $cc->cc_expire);
$this->request->addPostParameter('cvv', $cc->getCvv());
$this->request->addPostParameter('firstname', $cc->cc_name_f);
$this->request->addPostParameter('lastname', $cc->cc_name_l);
$this->request->addPostParameter('address1', $cc->cc_street);
$this->request->addPostParameter('city', $cc->cc_city);
$this->request->addPostParameter('state', $cc->cc_state);
$this->request->addPostParameter('zip', $cc->cc_zip);
$this->request->addPostParameter('country', $cc->cc_country);
$this->request->addPostParameter('phone', $cc->cc_phone);
}
public function getCustomerVaultId()
{
return $this->parsedResponse->customer_vault_id;
}
}
library/Am/Form/Echeck.php 0000644 00000022613 15210160104 0011335 0 ustar 00 plugin = $plugin;
$this->formType = $formType;
$this->payButtons = array(
self::PAYFORM => ___('Subscribe And Pay'),
self::ADMIN_UPDATE => ___('Update eCheck Info'),
self::USER_UPDATE => ___('Update eCheck Info'),
self::ADMIN_INSERT => ___('Update eCheck Info'),
);
parent::__construct('ec');
}
public function init()
{
parent::init();
$name = $this->addGroup()
->setLabel(___("Your Name\n" .
'your first and last name'));
$name->setSeparator(' ');
$name->addRule('required', ___('Please enter your name'));
$name->addText('echeck_name_f', array('size' => 15))
->addRule('required', ___('Please enter first name'))
->addRule('regex', ___('Please enter first name'), '|^[a-zA-Z_\' -]+$|');
$name->addText('echeck_name_l', array('size' => 15))
->addRule('required', ___('Please enter your last name'))
->addRule('regex', ___('Please enter your last name'), '|^[a-zA-Z_\' -]+$|');
if ($this->formType == self::ADMIN_UPDATE)
{
$group = $this->addGroup()->setLabel(___("Bank Account Number\n" .
'Up to 20 digits'));
$group->addStatic()->setContent('');
$group->addStatic('echeck');
$group->addText('echeck_ban', array('autocomplete' => 'off', 'maxlength' => 20, 'style' => 'display:none'))
->addRule('regex', ___('Invalid Bank Account Number'), '/^[a-zA-Z0-9]{1,20}$/');
$group->addScript("")->setScript(<<addStatic()->setContent('
');
} else
{
$this->addText('echeck_ban', array('autocomplete' => 'off', 'maxlength' => 20))
->setLabel(___("Your Bank Account Number\n" .
'Up to 20 digits'))
->addRule('required', ___('Please enter Account Number'))
->addRule('regex', ___('Invalid Account Number'), '/^[a-zA-Z0-9]{1,20}$/');
}
$this->addText('echeck_aba', array('autocomplete' => 'off', 'maxlength' => 9))
->setLabel(___("ABA Routing Number\n" .
'9 digits'))
->addRule('required', ___('Please enter Routing Number'))
->addRule('regex', ___('Invalid Routing Number'), '/^[a-zA-Z0-9]{1,9}$/');
$options = $this->plugin->getFormOptions();
if (in_array(Am_Paysystem_Echeck::ECHECK_COMPANY, $options))
{
$this->addText(Am_Paysystem_Echeck::ECHECK_COMPANY)
->setLabel(___("Company Name\n" .
'the company name associated with the billing address for ' .
'the transaction'));
}
if (in_array(Am_Paysystem_Echeck::ECHECK_TYPE_OPTIONS, $options))
{
$type = $this->addSelect(Am_Paysystem_Echeck::ECHECK_TYPE_OPTIONS)
->setLabel(___("Bank Account Type\n" .
'please select one'))
->loadOptions(array_merge(array(''=>'-- ' . ___('Please choose') . ' --'),
$this->plugin->getEcheckTypeOptions()));
$type->addRule('required', ___('Please choose a Bank Account Type'));
}
if (in_array(Am_Paysystem_Echeck::ECHECK_BANK_NAME, $options))
{
$this->addText(Am_Paysystem_Echeck::ECHECK_BANK_NAME, array('autocomplete' => 'off', 'maxlength' => 50))
->setLabel(___('Bank Name'))
->addRule('required', ___('Please enter Bank Name'));
}
if (in_array(Am_Paysystem_Echeck::ECHECK_ACCOUNT_NAME, $options))
{
$this->addText(Am_Paysystem_Echeck::ECHECK_ACCOUNT_NAME, array('autocomplete' => 'off', 'maxlength' => 50))
->setLabel(___("Bank Account Name\n" .
'name associated with the bank account'))
->addRule('required', ___('Please enter Bank Account Name'));
}
if (in_array(Am_Paysystem_Echeck::ECHECK_ADDRESS, $options))
{
$fieldSet = $this->addFieldset(___('Address Info'))
->setLabel(___("Address Info\n" .
'(must match your credit card statement delivery address)'));
if (in_array(Am_Paysystem_Echeck::ECHECK_STREET, $options))
{
$street = $fieldSet->addText('echeck_street')->setLabel(___('Street Address'))
->addRule('required', ___('Please enter Street Address'));
}
if (in_array(Am_Paysystem_Echeck::ECHECK_STREET2, $options))
{
$street2 = $fieldSet->addText('echeck_street2')->setLabel(___('Street Address (Second Line)'))
->addRule('required', ___('Please enter Street Address'));
}
if (in_array(Am_Paysystem_Echeck::ECHECK_CITY, $options))
{
$city = $fieldSet->addText('echeck_city')->setLabel(___('City'))
->addRule('required', ___('Please enter City'));
}
if (in_array(Am_Paysystem_Echeck::ECHECK_ZIP, $options))
{
$zip = $fieldSet->addText('echeck_zip')->setLabel(___('ZIP'))
->addRule('required', ___('Please enter ZIP code'));
}
if (in_array(Am_Paysystem_Echeck::ECHECK_COUNTRY, $options))
{
$country = $fieldSet->addSelect('echeck_country')->setLabel(___('Country'))
->setId('f_cc_country')
->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true));
$country->addRule('required', ___('Please enter Country'));
}
if (in_array(Am_Paysystem_Echeck::ECHECK_STATE, $options))
{
$group = $fieldSet->addGroup()->setLabel(___('State'));
$group->addRule('required', ___('Please enter State'));
/** @todo load correct states */
$stateSelect = $group->addSelect('echeck_state')
->setId('f_cc_state')
->loadOptions($stateOptions = Am_Di::getInstance()->stateTable->getOptions(@$_REQUEST['echeck_country'], true));
$stateText = $group->addText('echeck_state')->setId('t_cc_state');
$disableObj = $stateOptions ? $stateText : $stateSelect;
$disableObj->setAttribute('disabled', 'disabled')->setAttribute('style', 'display: none');
}
if (in_array(Am_Paysystem_Echeck::ECHECK_PHONE, $options))
{
$phone = $fieldSet->addText('echeck_phone', array('size'=>14))->setLabel(___('Phone'))
->addRule('required', ___('Please enter phone number'))
->addRule('regex', ___('Please enter phone number'), '|^[\d() +-]+$|');
}
}
$buttons = $this->addGroup();
$buttons->addSubmit('_echeck_', array('value' =>
' '
. $this->payButtons[$this->formType]
. ' '));
if ($this->formType == self::USER_UPDATE)
{
$buttons->addInputButton('_echeck_', array('value' =>
' '
. ___("Back")
. ' ',
'onclick' => 'goBackToMember()'));
$this->addScript("")->setScript("function goBackToMember(){ window.location = amUrl('/member'); }");
}
$this->plugin->onFormInit($this);
}
/**
* Return array of default values based on $user record
* @param User $user
*/
public function getDefaultValues(User $user)
{
return array(
'echeck_name_f' => $user->name_f,
'echeck_name_l' => $user->name_l,
'echeck_street' => $user->street,
'echeck_street2' => $user->street2,
'echeck_city' => $user->city,
'echeck_state' => $user->state,
'echeck_country' => $user->country,
'echeck_zip' => $user->zip,
'echeck_phone' => $user->phone,
);
}
public function validate()
{
return parent::validate() && $this->plugin->onFormValidate($this);
}
public function getValue()
{
$ret = parent::getValue();
array_walk_recursive($ret, function(&$v, $k) {$v=trim($v);});
if (!empty($ret['echeck_ban']))
$ret['echeck_ban'] = preg_replace('/\D/', '', $ret['echeck_ban']);
return $ret;
}
public function toEcheckRecord(EcheckRecord $echeck)
{
$values = $this->getValue();
unset($values['a']);
unset($values['id']);
unset($values['action']);
$echeck->setForInsert($values);
}
}
library/Am/Form/CreditCard.php 0000644 00000033134 15210160104 0012157 0 ustar 00 setSeparator(' ');
$require = !$data['dont_require'];
$years = @$data['years'];
if (!$years) $years = 10;
$m = $this->addSelect('m')->loadOptions($this->getMonthOptions());
if ($require)
$m->addRule('required', ___('Invalid Expiration Date - Month'));
$y = $this->addSelect('y')->loadOptions($this->getYearOptions($years));
if ($require)
$y->addRule('required', ___('Invalid Expiration Date - Year'));
}
public function getMonthOptions()
{
$locale = Am_Di::getInstance()->locale;
$months = $locale->getMonthNames('wide', false);
foreach ($months as $k=>$v) $months[$k] = sprintf('(%02d) %s', $k, $v);
$months[''] = '';
ksort($months);
return $months;
}
public function getYearOptions($add){
$years = range(date('Y'), date('Y')+$add);
array_unshift($years, '');
return array_combine($years, $years);
}
public function setValue($value)
{
if (is_string($value) && preg_match('/^\d{4}$/', $value))
{
$value = array(
'm' => (int)substr($value, 0, 2),
'y' => '20' . substr($value, 2, 2),
);
}
return parent::setValue($value);
}
protected function updateValue()
{
$name = $this->getName();
foreach ($this->getDataSources() as $ds) {
if (null !== ($value = $ds->getValue($name))) {
$this->setValue($value);
return;
}
}
return parent::updateValue();
}
}
class Am_Form_CreditCard extends Am_Form
{
const PAYFORM = 'payform';
const USER_UPDATE = 'user-update';
const ADMIN_UPDATE = 'admin-update';
const ADMIN_INSERT = 'admin-insert';
protected $payButtons = array();
/** @var Am_Paysystem_CreditCard */
protected $plugin;
protected $formType = self::PAYFORM;
public function __construct(Am_Paysystem_CreditCard $plugin, $formType = self::PAYFORM) {
$this->plugin = $plugin;
$this->formType = $formType;
$this->payButtons = array(
self::PAYFORM => ___('Subscribe And Pay'),
self::ADMIN_UPDATE => ___('Update Credit Card Info'),
self::USER_UPDATE => ___('Update Credit Card Info'),
self::ADMIN_INSERT => ___('Update Credit Card Info'),
);
parent::__construct('cc');
}
public function init() {
parent::init();
$name = $this->addGroup()
->setLabel(___("Cardholder Name\n" .
'cardholder first and last name, exactly as on the card'));
$name->setSeparator(' ');
$name->addRule('required', ___('Please enter credit card holder name'));
$name_f = $name->addText('cc_name_f', array('size'=>15));
$name_f->addRule('required', ___('Please enter credit card holder first name'))->addRule('regex', ___('Please enter credit card holder first name'), '/^[^=:<>{}()"]+$/D');
$name_l = $name->addText('cc_name_l', array('size'=>15));
$name_l->addRule('required', ___('Please enter credit card holder last name'))->addRule('regex', ___('Please enter credit card holder last name'), '/^[^=:<>{}()"]+$/D');
$options = $this->plugin->getFormOptions();
if (in_array(Am_Paysystem_CreditCard::CC_COMPANY, $options))
$company = $this->addText('cc_company')
->setLabel(___("Company Name\n" .
'the company name associated with the billing address for the transaction'));
if (in_array(Am_Paysystem_CreditCard::CC_TYPE_OPTIONS, $options)) {
$type = $this->addSelect('cc_type')
->setLabel(___("Credit Card Type\n" .
'please select one'))
->loadOptions(array_merge(array(''=>'-- ' . ___('Please choose') . ' --'),
$this->plugin->getCreditCardTypeOptions()));
$type->addRule('required', ___('Please choose a Credit Card Type'));
}
if ($this->formType == self::ADMIN_UPDATE) {
$group = $this->addGroup()
->setLabel(___("Credit Card Number\n" .
"for example: 1111-2222-3333-4444"));
$group->addStatic()->setContent('');
$group->addStatic('cc');
$cc = $group->addText('cc_number', array('autocomplete'=>'off', 'size'=>22, 'maxlength'=>22, 'style'=>'display:none'));
$cc->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/')
->addRule('callback2', 'Invalid CC#', array($this->plugin, 'validateCreditCardNumber'));
$group->addScript("")->setScript(<<addStatic()->setContent('
');
} else {
$cc = $this->addText('cc_number', array('autocomplete'=>'off', 'size'=>22, 'maxlength'=>22))
->setLabel(___("Credit Card Number\n" .
'for example: 1111-2222-3333-4444'));
$cc->addRule('required', ___('Please enter Credit Card Number'))
->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/')
->addRule('callback2', 'Invalid CC#', array($this->plugin, 'validateCreditCardNumber'));
}
$expire = $this->addElement(new Am_Form_Element_CreditCardExpire('cc_expire'))
->setLabel(___("Card Expire\n" .
'Select card expiration date - month and year'))
->addRule('required');
if (in_array(Am_Paysystem_CreditCard::CC_CODE, $options)) {
$code = $this->addPassword('cc_code', array('autocomplete'=>'off', 'size'=>4, 'maxlength'=>4))
->setLabel(___("Credit Card Code\n" .
'The "Card Code" is a three- or four-digit security code ' .
'that is printed on the back of credit cards in the card\'s ' .
'signature panel (or on the front for American Express cards)'));
$code->addRule('required', ___('Please enter Credit Card Code'))
->addRule('regex', ___('Please enter Credit Card Code'), '/^\s*\d{3,4}\s*$/');
}
if (in_array(Am_Paysystem_CreditCard::CC_MAESTRO_SOLO_SWITCH, $options)) {
$issue = $this->addText('cc_issuenum', array('autocomplete'=>'off', 'size'=>20, 'maxlength'=>22))
->setLabel(___("Card Issue #\n" .
'is required for Maestro/Solo/Switch credit cards only'))
->addRule('regex', ___('Invalid Issue Number'), '/^\d+$/');
$this->addElement(new Am_Form_Element_CreditCardExpire('cc_startdate', null, array('dont_require'=>true, 'years'=>-10)))
->setLabel(___("Card Start Date\n" .
'is required for Maestro/Solo/Switch credit cards only'));
}
if (in_array(Am_Paysystem_CreditCard::CC_INPUT_BIN, $options)) {
$fieldSet = $this->addFieldset()->setLabel(___('Bank Identification'));
$fieldSet->addText('_cc_bin_name', array())
->setLabel(___("Bank Name\n" .
'name of the bank which issued the credit card'));
$fieldSet->addText('_cc_bin_phone', array())
->setLabel(___("Bank Phone\n" .
'customer service phone number listed on back of your credit card'));
}
if (in_array(Am_Paysystem_CreditCard::CC_ADDRESS, $options)) {
$fieldSet = $this->addFieldset(___('Billing Address'))
->setLabel(___("Billing Address\n" .
'must match your credit card statement delivery address'));
if (in_array(Am_Paysystem_CreditCard::CC_STREET, $options)) {
$street = $fieldSet->addText('cc_street', array('class'=>'el-wide'))->setLabel(___('Street Address'))
->addRule('required', ___('Please enter Street Address'));
}
if (in_array(Am_Paysystem_CreditCard::CC_STREET2, $options)) {
$street2 = $fieldSet->addText('cc_street2', array('class'=>'el-wide'))->setLabel(___('Street Address (Second Line)'))
->addRule('required', ___('Please enter Street Address'));
}
if (in_array(Am_Paysystem_CreditCard::CC_HOUSENUMBER, $options)) {
$house = $fieldSet->addText('cc_housenumber', array('size'=>15))->setLabel(___('Housenumber'))
->addRule('required', ___('Please enter housenumber'));
}
if (in_array(Am_Paysystem_CreditCard::CC_CITY, $options)) {
$city = $fieldSet->addText('cc_city')->setLabel(___('City'))
->addRule('required', ___('Please enter City'));
}
if (in_array(Am_Paysystem_CreditCard::CC_PROVINCE_OUTSIDE_OF_US, $options)) {
$province = $fieldSet->addText('cc_province', array('size'=>15))
->setLabel(___("Billing International Province\n" .
'for international provinces outside of US & Canada ' .
'include the province name here'))
->addRule('required', ___('Please choose state'));
}
if (in_array(Am_Paysystem_CreditCard::CC_ZIP, $options)) {
$zip = $fieldSet->addText('cc_zip')->setLabel(___('ZIP'))
->addRule('required', ___('Please enter ZIP code'));
}
if (in_array(Am_Paysystem_CreditCard::CC_COUNTRY, $options)) {
$country = $fieldSet->addSelect('cc_country')->setLabel(___('Country'))
->setId('f_cc_country')
->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true));
$country->addRule('required', ___('Please enter Country'));
}
if (in_array(Am_Paysystem_CreditCard::CC_STATE, $options)) {
$group = $fieldSet->addGroup()->setLabel(___('State'));
$group->addRule('required', ___('Please enter State'));
/** @todo load correct states */
$stateSelect = $group->addSelect('cc_state')
->setId('f_cc_state')
->loadOptions($stateOptions = Am_Di::getInstance()->stateTable->getOptions(@$_REQUEST['cc_country'], true));
$stateText = $group->addText('cc_state')->setId('t_cc_state');
$disableObj = $stateOptions ? $stateText : $stateSelect;
$disableObj->setAttribute('disabled', 'disabled')->setAttribute('style', 'display: none');
}
if (in_array(Am_Paysystem_CreditCard::CC_PHONE, $options)) {
$phone = $fieldSet->addText('cc_phone', array('size'=>14))->setLabel(___('Phone'))
->addRule('required', ___('Please enter phone number'))
->addRule('regex', ___('Please enter phone number'), '|^[\d() +-]+$|');
}
}
// if free trial set _TPL_CC_INFO_SUBMIT_BUT2
$buttons = $this->addGroup();
$buttons->setSeparator(' ');
$buttons->addSubmit('_cc_', array('value'=> $this->payButtons[ $this->formType ]));
if ($this->formType == self::USER_UPDATE) {
$buttons->addStatic()
->setContent(sprintf('%s', ___("Back")));
$this->addScript("")->setScript("function goBackToMember(){ window.location = amUrl('/member'); }");
}
$this->plugin->onFormInit($this);
}
/**
* Return array of default values based on $user record
* @param User $user
*/
public function getDefaultValues(User $user){
return array(
'cc_name_f' => $user->name_f,
'cc_name_l' => $user->name_l,
'cc_street' => $user->street,
'cc_street2' => $user->street2,
'cc_city' => $user->city,
'cc_state' => $user->state,
'cc_country' => $user->country,
'cc_zip' => $user->zip,
'cc_phone' => $user->phone,
);
}
public function validate() {
return parent::validate() && $this->plugin->onFormValidate($this);
}
public function getValue() {
$ret = parent::getValue();
array_walk_recursive($ret, function(&$v, $k) {$v=trim($v);});
if (!empty($ret['cc_number']))
$ret['cc_number'] = preg_replace('/\D/', '', $ret['cc_number']);
return $ret;
}
public function toCcRecord(CcRecord $cc){
$values = $this->getValue();
foreach ($values as $k=>$v)
if (is_array($v))
{
if(!empty($v['m']))
$values[$k] = sprintf('%02d%02d', $v['m'], substr($v['y'], -2));
elseif(array_key_exists('m', $v))
$values[$k] = '';
}
unset($values['_cc_bin_name']);
unset($values['_cc_bin_phone']);
unset($values['a']);
unset($values['id']);
if( !empty($values['cc_code']))
$cc->setCvv($values['cc_code']);
unset($values['cc_code']);
unset($values['action']);
$cc->setForInsert($values);
}
} library/Am/Mvc/Controller/Echeck.php 0000644 00000010322 15210160104 0013274 0 ustar 00 plugin = $plugin;
}
/**
* Process the validated form and if ok, display thanks page,
* if not ok, return false
*/
public function processEcheck()
{
$echeck = $this->getDi()->echeckRecordRecord;
$this->form->toEcheckRecord($echeck);
$echeck->user_id = $this->invoice->user_id;
$result = $this->plugin->doBill($this->invoice, true, $echeck);
if ($result->isSuccess())
{
if (($this->invoice->rebill_times > 0) && !$echeck->pk())
$this->plugin->storeEcheck($echeck, new Am_Paysystem_Result);
$this->_response->redirectLocation($this->plugin->getReturnUrl());
return true;
} elseif ($result->isAction() && ($result->getAction() instanceof Am_Paysystem_Action_Redirect))
{
$result->getAction()->process($this); // throws Am_Exception_Redirect (!)
} else
{
$this->view->error = $result->getErrorMessages();
}
}
public function setInvoice(Invoice $invoice)
{
$this->invoice = $invoice;
}
public function echeckAction()
{
// invoice must be set to this point by the plugin
if (!$this->invoice)
throw new Am_Exception_InternalError('Empty invoice - internal error!');
$this->form = $this->createForm();
if ($this->form->isSubmitted() && $this->form->validate() && $this->processEcheck())
return;
$this->view->form = $this->form;
$this->view->invoice = $this->invoice;
$this->view->display_receipt = true;
$this->view->layoutNoMenu = true;
$this->view->display('echeck/info.phtml');
}
public function createForm()
{
$form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice);
$form->setDataSources(array(
$this->_request,
new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser()))
));
$form->addHidden(Am_Mvc_Controller::ACTION_KEY)->setValue($this->_request->getActionName());
$form->addHidden('id')->setValue($this->getFiltered('id'));
return $form;
}
public function preDispatch() {
if (!$this->plugin)
throw new Am_Exception_InternalError("Payment plugin is not passed to " . __CLASS__);
}
public function createUpdateForm()
{
$form = new Am_Form_Echeck($this->plugin, Am_Form_CreditCard::USER_UPDATE);
$user = $this->getDi()->auth->getUser(true);
if (!$user)
throw new Am_Exception_InputError("You are not logged-in");
$echeck = $this->getDi()->echeckRecordTable->findFirstByUserId($user->user_id);
if (!$echeck) $echeck = $this->getDi()->echeckRecordRecord;
$arr = $echeck->toArray();
unset($arr['echeck_ban']);
$form->setDataSources(array(
$this->_request,
new HTML_QuickForm2_DataSource_Array($arr)
));
return $form;
}
public function updateAction()
{
$this->form = $this->createUpdateForm();
if ($this->form->isSubmitted() && $this->form->validate())
{
$echeck = $this->getDi()->echeckRecordRecord;
$this->form->toEcheckRecord($echeck);
$echeck->user_id = $this->getDi()->auth->getUserId();
$result = new Am_Paysystem_Result();
$this->plugin->storeEcheck($echeck, $result);
if ($result->isSuccess())
{
return $this->_response->redirectLocation($this->getDi()->url('member',null,false));
} else {
$this->form->getElementById('echeck_ban-0')->setError($result->getLastError());
}
}
$this->view->form = $this->form;
$this->view->invoice = null;
$this->view->display_receipt = false;
$this->view->display('echeck/info.phtml');
}
}
library/Am/Mvc/Controller/CreditCard.php 0000644 00000011111 15210160104 0014113 0 ustar 00 plugin = $plugin;
}
/**
* Process the validated form and if ok, display thanks page,
* if not ok, return false
*/
public function processCc()
{
$cc = $this->getDi()->ccRecordRecord;
$this->form->toCcRecord($cc);
$cc->user_id = $this->invoice->user_id;
if($this->plugin->getConfig('use_maxmind'))
{
$checkresult = $this->plugin->doMaxmindCheck($this->invoice, $cc);
if (!$checkresult->isSuccess())
{
$this->view->error = $checkresult->getErrorMessages();
return;
}
}
$result = $this->plugin->doBill($this->invoice, true, $cc);
if ($result->isSuccess()) {
if (($this->invoice->rebill_times > 0) && !$cc->pk())
$this->plugin->storeCreditCard($cc, new Am_Paysystem_Result);
$this->_response->redirectLocation($this->plugin->getReturnUrl());
return true;
} elseif ($result->isAction() && ($result->getAction() instanceof Am_Paysystem_Action_Redirect)) {
$result->getAction()->process($this); // throws Am_Exception_Redirect (!)
} else {
$this->view->error = $result->getErrorMessages();
}
}
public function setInvoice(Invoice $invoice)
{
$this->invoice = $invoice;
}
public function ccAction()
{
// invoice must be set to this point by the plugin
if (!$this->invoice)
throw new Am_Exception_InternalError('Empty invoice - internal error!');
$this->form = $this->createForm();
$this->getDi()->hook->call(Bootstrap_Cc::EVENT_CC_FORM, array('form' => $this->form));
if ($this->form->isSubmitted() && $this->form->validate()) {
if ($this->processCc()) return;
}
$this->view->form = $this->form;
$this->view->invoice = $this->invoice;
$this->view->display_receipt = true;
$this->view->layoutNoMenu = true;
$this->view->display('cc/info.phtml');
}
public function createForm()
{
$form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice);
$form->setDataSources(array(
$this->_request,
new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser()))
));
$form->addHidden(Am_Mvc_Controller::ACTION_KEY)->setValue($this->_request->getActionName());
$form->addHidden('id')->setValue($this->getFiltered('id'));
return $form;
}
public function preDispatch() {
if (!$this->plugin)
throw new Am_Exception_InternalError("Payment plugin is not passed to " . __CLASS__);
}
public function createUpdateForm()
{
$form = new Am_Form_CreditCard($this->plugin, Am_Form_CreditCard::USER_UPDATE);
$user = $this->getDi()->auth->getUser(true);
if (!$user)
throw new Am_Exception_InputError("You are not logged-in");
$cc = $this->getDi()->ccRecordTable->findFirstByUserId($user->user_id);
if (!$cc) $cc = $this->getDi()->ccRecordRecord;
$arr = $cc->toArray();
unset($arr['cc_number']);
$form->setDataSources(array(
$this->_request,
new HTML_QuickForm2_DataSource_Array($arr)
));
return $form;
}
public function updateAction()
{
$this->form = $this->createUpdateForm();
if ($this->form->isSubmitted() && $this->form->validate())
{
$cc = $this->getDi()->ccRecordRecord;
$this->form->toCcRecord($cc);
$cc->user_id = $this->getDi()->auth->getUserId();
$result = new Am_Paysystem_Result();
$this->plugin->storeCreditCard($cc, $result);
if ($result->isSuccess())
{
return $this->_response->redirectLocation($this->getDi()->url('member',array('_msg'=>___('Your card details have been updated.')),false));
} else {
$this->form->getElementById('cc_number-0')->setError($result->getLastError());
}
}
$this->view->form = $this->form;
$this->view->invoice = null;
$this->view->display_receipt = false;
$this->view->display('cc/info.phtml');
}
}
library/Am/Controller/Echeck.php 0000644 00000010232 15210160104 0012547 0 ustar 00 plugin = $plugin;
}
/**
* Process the validated form and if ok, display thanks page,
* if not ok, return false
*/
public function processEcheck()
{
$echeck = $this->getDi()->echeckRecordRecord;
$this->form->toEcheckRecord($echeck);
$echeck->user_id = $this->invoice->user_id;
$result = $this->plugin->doBill($this->invoice, true, $echeck);
if ($result->isSuccess())
{
if (($this->invoice->rebill_times > 0) && !$echeck->pk())
$this->plugin->storeEcheck($echeck, new Am_Paysystem_Result);
$this->redirectLocation($this->plugin->getReturnUrl());
return true;
} elseif ($result->isAction() && ($result->getAction() instanceof Am_Paysystem_Action_Redirect))
{
$result->getAction()->process($this); // throws Am_Exception_Redirect (!)
} else
{
$this->view->error = $result->getErrorMessages();
}
}
public function setInvoice(Invoice $invoice)
{
$this->invoice = $invoice;
}
public function echeckAction()
{
// invoice must be set to this point by the plugin
if (!$this->invoice)
throw new Am_Exception_InternalError('Empty invoice - internal error!');
$this->form = $this->createForm();
if ($this->form->isSubmitted() && $this->form->validate() && $this->processEcheck())
return;
$this->view->form = $this->form;
$this->view->invoice = $this->invoice;
$this->view->display_receipt = true;
$this->view->layoutNoMenu = true;
$this->view->display('echeck/info.phtml');
}
public function createForm()
{
$form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice);
$form->setDataSources(array(
$this->_request,
new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser()))
));
$form->addHidden(Am_Controller::ACTION_KEY)->setValue($this->_request->getActionName());
$form->addHidden('id')->setValue($this->getFiltered('id'));
return $form;
}
public function preDispatch() {
if (!$this->plugin)
throw new Am_Exception_InternalError("Payment plugin is not passed to " . __CLASS__);
}
public function createUpdateForm()
{
$form = new Am_Form_Echeck($this->plugin, Am_Form_CreditCard::USER_UPDATE);
$user = $this->getDi()->auth->getUser(true);
if (!$user)
throw new Am_Exception_InputError("You are not logged-in");
$echeck = $this->getDi()->echeckRecordTable->findFirstByUserId($user->user_id);
if (!$echeck) $echeck = $this->getDi()->echeckRecordRecord;
$arr = $echeck->toArray();
unset($arr['echeck_ban']);
$form->setDataSources(array(
$this->_request,
new HTML_QuickForm2_DataSource_Array($arr)
));
return $form;
}
public function updateAction()
{
$this->form = $this->createUpdateForm();
if ($this->form->isSubmitted() && $this->form->validate())
{
$echeck = $this->getDi()->echeckRecord;
$this->form->toEcheckRecord($echeck);
$echeck->user_id = $this->getDi()->auth->getUserId();
$result = new Am_Paysystem_Result();
$this->plugin->storeEcheck($echeck, $result);
if ($result->isSuccess())
{
return $this->redirectLocation(REL_ROOT_URL . '/member');
} else {
$this->form->getElementById('echeck_ban-0')->setError($result->getLastError());
}
}
$this->view->form = $this->form;
$this->view->invoice = null;
$this->view->display_receipt = false;
$this->view->display('echeck/info.phtml');
}
}
library/Am/Controller/CreditCard.php 0000644 00000010741 15210160104 0013376 0 ustar 00 plugin = $plugin;
}
/**
* Process the validated form and if ok, display thanks page,
* if not ok, return false
*/
public function processCc()
{
$cc = $this->getDi()->ccRecordRecord;
$this->form->toCcRecord($cc);
$cc->user_id = $this->invoice->user_id;
if($this->plugin->getConfig('use_maxmind'))
{
$checkresult = $this->plugin->doMaxmindCheck($this->invoice, $cc);
if (!$checkresult->isSuccess())
{
$this->view->error = $checkresult->getErrorMessages();
return;
}
}
$result = $this->plugin->doBill($this->invoice, true, $cc);
if ($result->isSuccess()) {
if (($this->invoice->rebill_times > 0) && !$cc->pk())
$this->plugin->storeCreditCard($cc, new Am_Paysystem_Result);
$this->redirectLocation($this->plugin->getReturnUrl());
return true;
} elseif ($result->isAction() && ($result->getAction() instanceof Am_Paysystem_Action_Redirect)) {
$result->getAction()->process($this); // throws Am_Exception_Redirect (!)
} else {
$this->view->error = $result->getErrorMessages();
}
}
public function setInvoice(Invoice $invoice)
{
$this->invoice = $invoice;
}
public function ccAction()
{
// invoice must be set to this point by the plugin
if (!$this->invoice)
throw new Am_Exception_InternalError('Empty invoice - internal error!');
$this->form = $this->createForm();
$this->getDi()->hook->call(Bootstrap_Cc::EVENT_CC_FORM, array('form' => $this->form));
if ($this->form->isSubmitted() && $this->form->validate()) {
if ($this->processCc()) return;
}
$this->view->form = $this->form;
$this->view->invoice = $this->invoice;
$this->view->display_receipt = true;
$this->view->layoutNoMenu = true;
$this->view->display('cc/info.phtml');
}
public function createForm()
{
$form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice);
$form->setDataSources(array(
$this->_request,
new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser()))
));
$form->addHidden(Am_Controller::ACTION_KEY)->setValue($this->_request->getActionName());
$form->addHidden('id')->setValue($this->getFiltered('id'));
return $form;
}
public function preDispatch() {
if (!$this->plugin)
throw new Am_Exception_InternalError("Payment plugin is not passed to " . __CLASS__);
}
public function createUpdateForm()
{
$form = new Am_Form_CreditCard($this->plugin, Am_Form_CreditCard::USER_UPDATE);
$user = $this->getDi()->auth->getUser(true);
if (!$user)
throw new Am_Exception_InputError("You are not logged-in");
$cc = $this->getDi()->ccRecordTable->findFirstByUserId($user->user_id);
if (!$cc) $cc = $this->getDi()->ccRecordRecord;
$arr = $cc->toArray();
unset($arr['cc_number']);
$form->setDataSources(array(
$this->_request,
new HTML_QuickForm2_DataSource_Array($arr)
));
return $form;
}
public function updateAction()
{
$this->form = $this->createUpdateForm();
if ($this->form->isSubmitted() && $this->form->validate())
{
$cc = $this->getDi()->ccRecordRecord;
$this->form->toCcRecord($cc);
$cc->user_id = $this->getDi()->auth->getUserId();
$result = new Am_Paysystem_Result();
$this->plugin->storeCreditCard($cc, $result);
if ($result->isSuccess())
{
return $this->redirectLocation(REL_ROOT_URL . '/member');
} else {
$this->form->getElementById('cc_number-0')->setError($result->getLastError());
}
}
$this->view->form = $this->form;
$this->view->invoice = null;
$this->view->display_receipt = false;
$this->view->display('cc/info.phtml');
}
}
library/CcRecord.php 0000644 00000006565 15210160104 0010407 0 ustar 00 _cc_code;
}
function setCvv($code)
{
$this->_cc_code = filterId($code);
}
function maskCc($number)
{
$number = preg_replace('/\D+/', '', $number);
if (strlen($number)<8)
return '****************';
return str_repeat('*', strlen($number)-4) .
substr($number, -4, 4);
}
function toRow()
{
$arr = parent::toRow();
// fields to encrypt
if (isset($arr['cc_number']))
{
$arr['cc_number'] = preg_replace('/\D+/', '', $arr['cc_number']);
if (empty($arr['cc']) || ($arr['cc_number'] != '0000000000000000'))
$arr['cc'] = $this->maskCc($arr['cc_number']);
}
foreach ($this->_encryptedFields as $f)
if (array_key_exists($f, $arr))
$arr[$f] = $this->_table->encrypt($arr[$f]);
return $arr;
}
public function fromRow(array $arr)
{
// fields to decrypt
foreach ($this->_encryptedFields as $f)
if (array_key_exists($f, $arr))
$arr[$f] = $this->_table->decrypt($arr[$f]);
return parent::fromRow($arr);
}
/**
* Delete existing record for this user_id, then insert this one
* @return CcRecord provides fluent interface
*/
function replace()
{
if (empty($this->user_id) || $this->user_id <= 0)
throw new Am_Exception_InternalError("this->user_id is empty in " . __METHOD__);
$this->_table->deleteByUserId($this->user_id);
return $this->insert();
}
function getExpire($format = "%02d%02d")
{
if ("" == $this->cc_expire) return "";
$m = substr($this->cc_expire, 0, 2);
$y = substr($this->cc_expire, 2, 2);
return sprintf($format, $m, $y);
}
}
class CcRecordTable extends Am_Table
{
protected $_crypt;
protected $_key = 'cc_id';
protected $_table = '?_cc';
protected $_recordClass = 'CcRecord';
function encrypt($s){
return $this->_getCrypt()->encrypt($s);
}
function decrypt($s){
return $this->_getCrypt()->decrypt($s);
}
function _getCrypt(){
if (empty($this->_crypt))
$this->_crypt = Am_Di::getInstance ()->crypt;
return $this->_crypt;
}
function setCrypt(Am_Crypt $crypt)
{
$this->_crypt = $crypt;
}
}
email-templates.xml 0000644 00000004564 15210160104 0010350 0 ustar 00
cc.admin_rebill_stats
2
en
text
%site_title%: %plugin% Rebill Statistics (%short_stats%)
Outlined below are the results of latest rebilling attempt on %site_title%
Here you can find statistics about SUCCESS rebills
===
%rebills_success%
Here you can find statistics about FAILED rebills
===
%rebills_failed%
cc.rebill_failed
1
en
text
%site_title%: Subscription Renewal Failed
Your subscription was not renewed automatically by membership system
due to payment failure: %error%
%prorate%
You may update your credit card info here:.
%root_url%/member
Thank you for attention!
cc.rebill_success
1
en
text
%site_title%: Subscription Renewed
Your subscription has been renewed automatically by our membership system.
Your credit card was charged %amount%
Next renewal date: %rebill_date%
You may login to membership info page at :
%root_url%/member
cc.card_expire
1
en
text
%site_title%: Credit Card Expiration
Your credit card that we have on file for recurring billing will expire
on %expires%. Next recurring billing for invoice %invoice.public_id%
is sheduled for %invoice.rebill_date|date%.
To avoid any interruption of your subscription, please visit page
%root_url%/member
and update your credit card information.