'Approved', 2 => 'Declined', 3 => 'Error', 4 => 'Held for Review', ); public function __construct($userId = null) { parent::__construct(self::NAME, $userId); } /** * * check if the gateway is enabled * * @return bool */ public function enabled() { if (!empty($this->_data[self::MERCHANT_ID]) && !empty($this->_data[self::TRANSACTION_KEY])) { return true; } return false; } /** * * get setup form elements * * @return array */ public function getElements() { $translate = $this->getTranslate(); return array( array( 'form_id' => 'AuthorizeNet', 'id' => self::MERCHANT_ID, 'element' => 'text', 'label' => $this->_('Authorize.net Merchant ID'), 'description' => $this->_('Enter your merchant ID'), 'attributes' => array( 'class' => 'form-control input-medium', ), ), array( 'form_id' => 'AuthorizeNet', 'id' => self::TRANSACTION_KEY, 'element' => 'text', 'label' => $this->_('Authorize.net Transaction Key'), 'description' => $this->_('Enter your assigned transaction key'), 'attributes' => array( 'class' => 'form-control input-medium', ), ), array( 'form_id' => 'AuthorizeNet', 'id' => self::MD5_HASH, 'element' => 'text', 'label' => $this->_('Authorize.net MD5 Hash'), 'description' => $this->_('(recommended) enter your set md5 hash value if you wish for the ipn requests to be encrypted
' . 'Authorize.net Relay Response URL:
') . $this->getIpnUrl(), 'attributes' => array( 'class' => 'form-control input-medium', ), ), array( 'form_id' => 'AuthorizeNet', 'id' => self::SANDBOX_MODE, 'element' => 'checkbox', 'label' => $this->_('Sandbox Mode'), 'description' => $this->_('Check the above checkbox to activate the sandbox mode.'), 'multiOptions' => array( 1 => null, ), ), ); } public function formElements() { $timestamp = time(); return array( array( 'id' => 'x_version', 'value' => '3.1', 'element' => 'hidden', ), array( 'id' => self::MERCHANT_ID, 'value' => $this->_data[self::MERCHANT_ID], 'element' => 'hidden', ), array( 'id' => 'x_type', 'value' => 'AUTH_CAPTURE', 'element' => 'hidden', ), array( 'id' => 'x_method', 'value' => 'CC', 'element' => 'hidden', ), array( 'id' => 'x_amount', 'value' => $this->getAmount(), 'element' => 'hidden', ), array( 'id' => 'x_show_form', 'value' => 'PAYMENT_FORM', 'element' => 'hidden', ), array( 'id' => 'x_relay_response', 'value' => 'TRUE', 'element' => 'hidden', ), array( 'id' => 'x_test_request', 'value' => ($this->_isSandboxMode()) ? 'TRUE' : 'false', 'element' => 'hidden', ), array( 'id' => 'x_description', 'value' => $this->_shortenString($this->getName(), 255), 'element' => 'hidden', ), array( 'id' => 'x_invoice_num', 'value' => $this->getTransactionId(), 'element' => 'hidden', ), array( 'id' => 'x_currency_code', 'value' => $this->getCurrency(), 'element' => 'hidden', ), array( 'id' => 'x_fp_hash', 'value' => $this->_createHash($timestamp), 'element' => 'hidden', ), array( 'id' => 'x_fp_sequence', 'value' => $this->getTransactionId(), 'element' => 'hidden', ), array( 'id' => 'x_fp_timestamp', 'value' => $timestamp, 'element' => 'hidden', ), array( 'id' => 'x_cancel_url', 'value' => $this->getFailureUrl(), 'element' => 'hidden', ), ); } /** * * get the form post url (live or sandbox) * * @return string */ public function getPostUrl() { return ($this->_isSandboxMode()) ? self::SANDBOX_POST_URL : self::POST_URL; } /** * * process ipn * * @param \Cube\Controller\Request\AbstractRequest $request * * @return bool */ public function processIpn(AbstractRequest $request) { $response = false; if ($request->isPost()) { $paymentStatus = $request->getParam('x_response_code'); $this->setTransactionId($request->getParam('x_invoice_num')) ->setAmount($request->getParam('x_amount')) ->setCurrency($request->getParam('x_currency_code')) ->setGatewayPaymentStatus($this->_ipnCodes[$paymentStatus]) ->setGatewayTransactionCode($request->getParam('x_trans_id')); if (!$this->_validateMd5Sig($request)) { $this->setGatewayPaymentStatus('Invalid MD5 Hash'); } else if ($paymentStatus == 1) { $response = true; } } return $response; } /** * * method that checks if the amount and currency submitted through an ipn is the * coincides with the row in the transactions table * * @param float $amount * @param string $currency * * @return bool */ public function checkIpnAmount($amount, $currency) { if ($this->_amount == $amount && in_array($currency, array('USD', 'CAD', 'GBP'))) { return true; } return false; } /** * * generates the required x_fp_hash variable, based on merchant id, transaction id (x_fp_sequence), timestamp and payment amount * and hashed using the merchant's transaction key * * @param int $timestamp * * @return string */ private function _createHash($timestamp) { return $this->_hmac($this->_data[self::TRANSACTION_KEY], $this->_data[self::MERCHANT_ID] . '^' . $this->getTransactionId() . '^' . $timestamp . '^' . $this->getAmount() . '^' . $this->getCurrency()); } /** * * RFC 2104 HMAC implementation for php. * Creates an md5 HMAC. * Eliminates the need to install mhash to compute a HMAC * Hacked by Lance Rushing * * @param string $key * @param string $data * * @return string */ private function _hmac($key, $data) { $b = 64; // byte length for md5 if (strlen($key) > $b) { $key = pack("H*", md5($key)); } $key = str_pad($key, $b, chr(0x00)); $iPad = str_pad('', $b, chr(0x36)); $oPad = str_pad('', $b, chr(0x5c)); $kIPad = $key ^ $iPad; $kOPad = $key ^ $oPad; return md5($kOPad . pack("H*", md5($kIPad . $data))); } /** * * validate ipn md5 hash * * @param AbstractRequest $request * * @return bool */ private function _validateMd5Sig(AbstractRequest $request) { if (empty($this->_data[self::MD5_HASH])) { return true; } $string = $this->_data[self::MD5_HASH] . $this->_data[self::MERCHANT_ID] . $request->getParam('x_trans_id') . $request->getParam('x_amount'); if (strcasecmp(md5($string), $request->getParam(self::MD5_HASH)) === 0) { return true; } return false; } /** * * check if sandbox mode is enabled * * @return bool */ protected function _isSandboxMode() { $sandbox = (isset($this->_data[self::SANDBOX_MODE])) ? $this->_data[self::SANDBOX_MODE] : false; return (bool)$sandbox; } }