PageRenderTime 61ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/application/libraries/merchant.php

https://bitbucket.org/fusioninvoice_it/fusioninvoice
PHP | 893 lines | 564 code | 130 blank | 199 comment | 74 complexity | 8b5e0c0611244f3539e776af18196928 MD5 | raw file
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /*
  3. * CI-Merchant Library
  4. *
  5. * Copyright (c) 2011-2012 Adrian Macneil
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. // Support legacy drivers which extend the CI_Driver class
  24. // All drivers should be updated to extend Merchant_driver instead
  25. // This will be removed in a future version!
  26. if ( ! class_exists('CI_Driver')) get_instance()->load->library('driver');
  27. define('MERCHANT_CONFIG_PATH', realpath(dirname(__FILE__).'/../config'));
  28. define('MERCHANT_DRIVER_PATH', realpath(dirname(__FILE__).'/merchant'));
  29. define('MERCHANT_VENDOR_PATH', realpath(dirname(__FILE__).'/../vendor'));
  30. /**
  31. * Merchant Class
  32. *
  33. * Payment processing for CodeIgniter
  34. */
  35. class Merchant
  36. {
  37. public static $CURRENCIES_WITHOUT_DECIMALS = array('JPY');
  38. public static $NUMERIC_CURRENCY_CODES = array(
  39. 'AUD' => '036',
  40. 'CAD' => '124',
  41. 'EUR' => '978',
  42. 'GBP' => '826',
  43. 'NZD' => '554',
  44. 'USD' => '840',
  45. );
  46. private $_driver;
  47. public function __construct($driver = NULL)
  48. {
  49. if ( ! empty($driver))
  50. {
  51. $this->load($driver);
  52. }
  53. }
  54. public function __call($function, $arguments)
  55. {
  56. if ( ! empty($this->_driver))
  57. {
  58. return call_user_func_array(array($this->_driver, $function), $arguments);
  59. }
  60. }
  61. /**
  62. * Load the specified driver
  63. */
  64. public function load($driver)
  65. {
  66. $this->_driver = $this->_create_instance($driver);
  67. return $this->_driver !== FALSE;
  68. }
  69. /**
  70. * Returns the name of the currently loaded driver
  71. */
  72. public function active_driver()
  73. {
  74. $class_name = get_class($this->_driver);
  75. if ($class_name === FALSE) return FALSE;
  76. return str_replace('Merchant_', '', $class_name);
  77. }
  78. /**
  79. * Load and create a new instance of a driver.
  80. * $driver can be specified either as a class name (Merchant_paypal) or a short name (paypal)
  81. */
  82. private function _create_instance($driver)
  83. {
  84. if (stripos($driver, 'merchant_') === 0)
  85. {
  86. $driver_class = ucfirst(strtolower($driver));
  87. }
  88. else
  89. {
  90. $driver_class = 'Merchant_'.strtolower($driver);
  91. }
  92. if ( ! class_exists($driver_class))
  93. {
  94. // attempt to load driver file
  95. $driver_path = MERCHANT_DRIVER_PATH.'/'.strtolower($driver_class).'.php';
  96. if ( ! file_exists($driver_path)) return FALSE;
  97. require_once($driver_path);
  98. // did the driver file implement the class?
  99. if ( ! class_exists($driver_class)) return FALSE;
  100. }
  101. // ensure class is not abstract
  102. $reflection_class = new ReflectionClass($driver_class);
  103. if ($reflection_class->isAbstract()) return FALSE;
  104. return new $driver_class();
  105. }
  106. public function valid_drivers()
  107. {
  108. static $valid_drivers = array();
  109. if (empty($valid_drivers))
  110. {
  111. foreach (scandir(MERCHANT_DRIVER_PATH) as $file_name)
  112. {
  113. $driver_path = MERCHANT_DRIVER_PATH.'/'.$file_name;
  114. if (stripos($file_name, 'merchant_') === 0 AND is_file($driver_path))
  115. {
  116. require_once($driver_path);
  117. // does the file implement an appropriately named class?
  118. $driver_class = ucfirst(str_replace('.php', '', $file_name));
  119. if ( ! class_exists($driver_class)) continue;
  120. // ensure class is not abstract
  121. $reflection_class = new ReflectionClass($driver_class);
  122. if ($reflection_class->isAbstract()) continue;
  123. $valid_drivers[] = str_replace('Merchant_', '', $driver_class);
  124. }
  125. }
  126. }
  127. return $valid_drivers;
  128. }
  129. public function authorize($params)
  130. {
  131. return $this->_do_authorize_or_purchase('authorize', $params);
  132. }
  133. public function authorize_return($params)
  134. {
  135. return $this->_do_authorize_or_purchase('authorize_return', $params);
  136. }
  137. public function capture($params)
  138. {
  139. return $this->_do_capture_or_refund('capture', $params);
  140. }
  141. public function purchase($params)
  142. {
  143. return $this->_do_authorize_or_purchase('purchase', $params);
  144. }
  145. public function purchase_return($params)
  146. {
  147. return $this->_do_authorize_or_purchase('purchase_return', $params);
  148. }
  149. public function refund($params)
  150. {
  151. return $this->_do_capture_or_refund('refund', $params);
  152. }
  153. private function _do_authorize_or_purchase($method, $params)
  154. {
  155. $this->_normalize_card_params($params);
  156. $this->_normalize_currency_params($params);
  157. try
  158. {
  159. // load driver params
  160. $this->_driver->set_params($params);
  161. // all payments require amount and currency
  162. $this->_driver->require_params('amount', 'currency');
  163. // support drivers using deprecated required_fields array
  164. if (($method == 'authorize' OR $method == 'purchase') AND
  165. ! empty($this->_driver->required_fields))
  166. {
  167. $this->_driver->require_params($this->_driver->required_fields);
  168. }
  169. // validate card_no
  170. $this->_driver->validate_card();
  171. // begin the actual processing
  172. return $this->_driver->$method();
  173. }
  174. catch (Merchant_exception $e)
  175. {
  176. return new Merchant_response(Merchant_response::FAILED, $e->getMessage());
  177. }
  178. }
  179. private function _do_capture_or_refund($method, $params)
  180. {
  181. $this->_normalize_currency_params($params);
  182. try
  183. {
  184. // load driver params
  185. $this->_driver->set_params($params);
  186. // begin the actual processing
  187. return $this->_driver->$method();
  188. }
  189. catch (Merchant_exception $e)
  190. {
  191. return new Merchant_response(Merchant_response::FAILED, $e->getMessage());
  192. }
  193. }
  194. private function _normalize_card_params(&$params)
  195. {
  196. // normalize months to 2 digits and years to 4
  197. if ( ! empty($params['exp_month'])) $params['exp_month'] = sprintf('%02d', (int)$params['exp_month']);
  198. if ( ! empty($params['exp_year'])) $params['exp_year'] = sprintf('%04d', (int)$params['exp_year']);
  199. if ( ! empty($params['start_month'])) $params['start_month'] = sprintf('%02d', (int)$params['start_month']);
  200. if ( ! empty($params['start_year'])) $params['start_year'] = sprintf('%04d', (int)$params['start_year']);
  201. // normalize card_type to lowercase
  202. if (isset($params['card_type'])) $params['card_type'] = strtolower($params['card_type']);
  203. // support deprecated card_name parameter
  204. if (isset($params['card_name']))
  205. {
  206. $params['name'] = $params['card_name'];
  207. }
  208. if (isset($params['name']))
  209. {
  210. $params['card_name'] = $params['name'];
  211. // split first/last names
  212. if (empty($params['first_name']) AND empty($params['last_name']))
  213. {
  214. $names = explode(' ', (string)$params['name'], 2);
  215. $params['first_name'] = $names[0];
  216. $params['last_name'] = isset($names[1]) ? $names[1] : '';
  217. }
  218. }
  219. // support deprecated address parameter
  220. if (isset($params['address']))
  221. {
  222. $params['address1'] = $params['address'];
  223. }
  224. elseif (isset($params['address1']))
  225. {
  226. $params['address'] = $params['address1'];
  227. }
  228. }
  229. private function _normalize_currency_params(&$params)
  230. {
  231. // support deprecated currency_code parameter
  232. if (isset($params['currency_code']))
  233. {
  234. $params['currency'] = $params['currency_code'];
  235. }
  236. if (isset($params['currency']))
  237. {
  238. // currency should always be uppercase
  239. $params['currency'] = strtoupper($params['currency']);
  240. $params['currency_code'] = $params['currency'];
  241. }
  242. }
  243. /**
  244. * Deprecated. Please use Merchant_driver::get_request() or
  245. * Merchant_driver::post_request() instead.
  246. */
  247. public static function curl_helper($url, $post_data = NULL, $username = NULL, $password = NULL)
  248. {
  249. // errors are now thrown as Merchant_exception()
  250. $response = array('error' => NULL);
  251. if (is_null($post_data))
  252. {
  253. $response['data'] = get_instance()->merchant->get_request($url, $username, $password);
  254. }
  255. else
  256. {
  257. $response['data'] = get_instance()->merchant->post_request($url, $post_data, $username, $password);
  258. }
  259. return $response;
  260. }
  261. /**
  262. * Redirect the user's browser to a URL.
  263. *
  264. * @param string $url
  265. */
  266. public static function redirect($url)
  267. {
  268. get_instance()->load->helper('url');
  269. redirect($url);
  270. }
  271. /**
  272. * Redirect the user's browser to a URL using a POST request.
  273. *
  274. * @param string $url
  275. * @param array $data
  276. * @param string $message
  277. */
  278. public static function post_redirect($url, $data, $message = NULL)
  279. {
  280. if (empty($message))
  281. {
  282. $message = lang('merchant_payment_redirect');
  283. }
  284. ?><!DOCTYPE html>
  285. <html>
  286. <head><title>Redirecting...</title></head>
  287. <body onload="document.forms[0].submit();">
  288. <form name="payment" action="<?php echo htmlspecialchars($url); ?>" method="post">
  289. <p><?php echo htmlspecialchars($message); ?></p>
  290. <p>
  291. <?php foreach ($data as $key => $value): ?>
  292. <input type="hidden" name="<?php echo htmlspecialchars($key); ?>" value="<?php echo htmlspecialchars($value); ?>" />
  293. <?php endforeach ?>
  294. <input type="submit" value="Continue" />
  295. </p>
  296. </form>
  297. </body>
  298. </html>
  299. <?php
  300. exit();
  301. }
  302. }
  303. abstract class Merchant_driver
  304. {
  305. protected $CI;
  306. /**
  307. * Settings related to the payment gateway.
  308. * Accessing this array directly is deprecated.
  309. *
  310. * @var array
  311. */
  312. protected $settings = array();
  313. /**
  314. * Parameters related to the current payment.
  315. *
  316. * @var array
  317. */
  318. private $_params = array();
  319. public function __construct()
  320. {
  321. $this->CI =& get_instance();
  322. // initialize default settings
  323. foreach ($this->default_settings() as $key => $default)
  324. {
  325. if (is_array($default))
  326. {
  327. $this->settings[$key] = isset($default['default']) ? $default['default'] : NULL;
  328. }
  329. else
  330. {
  331. $this->settings[$key] = $default;
  332. }
  333. }
  334. }
  335. /**
  336. * Default settings. This should be overridden by the driver.
  337. */
  338. public abstract function default_settings();
  339. /**
  340. * Initialize the driver settings
  341. */
  342. public function initialize($settings)
  343. {
  344. foreach ($this->default_settings() as $key => $default)
  345. {
  346. if (isset($settings[$key]))
  347. {
  348. // boolean settings must remain booleans
  349. $this->settings[$key] = is_bool($default) ? (bool)$settings[$key] : $settings[$key];
  350. }
  351. }
  352. }
  353. /**
  354. * All driver settings
  355. *
  356. * @return array
  357. */
  358. public function settings()
  359. {
  360. return $this->settings;
  361. }
  362. /**
  363. * Setting
  364. *
  365. * @return mixed
  366. */
  367. public function setting($key)
  368. {
  369. return isset($this->settings[$key]) ? $this->settings[$key] : FALSE;
  370. }
  371. public function can_authorize()
  372. {
  373. $method = new ReflectionMethod($this, 'authorize');
  374. return $method->getDeclaringClass()->name !== __CLASS__;
  375. }
  376. public function can_capture()
  377. {
  378. $method = new ReflectionMethod($this, 'capture');
  379. return $method->getDeclaringClass()->name !== __CLASS__;
  380. }
  381. public function can_refund()
  382. {
  383. $method = new ReflectionMethod($this, 'refund');
  384. return $method->getDeclaringClass()->name !== __CLASS__;
  385. }
  386. public function can_return()
  387. {
  388. $method = new ReflectionMethod($this, 'purchase_return');
  389. if ($method->getDeclaringClass()->name !== __CLASS__) return TRUE;
  390. // try calling deprecated process_return() method instead
  391. if (method_exists($this, 'process_return')) return TRUE;
  392. if (method_exists($this, '_process_return')) return TRUE;
  393. return FALSE;
  394. }
  395. public function authorize()
  396. {
  397. throw new BadMethodCallException(lang('merchant_invalid_method'));
  398. }
  399. public function authorize_return()
  400. {
  401. throw new BadMethodCallException(lang('merchant_invalid_method'));
  402. }
  403. public function capture()
  404. {
  405. throw new BadMethodCallException(lang('merchant_invalid_method'));
  406. }
  407. public function purchase()
  408. {
  409. // try calling deprecated process() method instead
  410. if (method_exists($this, 'process'))
  411. {
  412. return $this->process($this->_params);
  413. }
  414. if (method_exists($this, '_process'))
  415. {
  416. return $this->_process($this->_params);
  417. }
  418. throw new BadMethodCallException(lang('merchant_invalid_method'));
  419. }
  420. public function purchase_return()
  421. {
  422. // try calling deprecated process_return() method instead
  423. if (method_exists($this, 'process_return'))
  424. {
  425. return $this->process_return($this->_params);
  426. }
  427. if (method_exists($this, '_process_return'))
  428. {
  429. return $this->_process_return($this->_params);
  430. }
  431. throw new BadMethodCallException(lang('merchant_invalid_method'));
  432. }
  433. public function refund()
  434. {
  435. throw new BadMethodCallException(lang('merchant_invalid_method'));
  436. }
  437. public function param($name)
  438. {
  439. return isset($this->_params[$name]) ? $this->_params[$name] : FALSE;
  440. }
  441. public function set_params($params)
  442. {
  443. $this->_params = array_merge($this->_params, $params);
  444. }
  445. public function require_params()
  446. {
  447. $args = func_get_args();
  448. if (empty($args)) return;
  449. // also accept an array instead of multiple parameters
  450. if (count($args) == 1 AND is_array($args[0])) $args = $args[0];
  451. foreach ($args as $name)
  452. {
  453. if (empty($this->_params[$name]))
  454. {
  455. throw new Merchant_exception(str_replace('%s', lang("merchant_$name"), lang('merchant_required')));
  456. }
  457. }
  458. }
  459. public function validate_card()
  460. {
  461. // skip validation if card_no is empty
  462. if (empty($this->_params['card_no'])) return;
  463. if ( ! $this->secure_request())
  464. {
  465. throw new Merchant_exception(lang('merchant_insecure_connection'));
  466. }
  467. // strip any non-digits from card_no
  468. $this->_params['card_no'] = preg_replace('/\D/', '', $this->_params['card_no']);
  469. if ($this->validate_luhn($this->_params['card_no']) == FALSE)
  470. {
  471. throw new Merchant_exception(lang('merchant_invalid_card_no'));
  472. }
  473. if ($this->param('exp_month') AND $this->param('exp_year') AND
  474. $this->validate_expiry($this->param('exp_month'), $this->param('exp_year')) == FALSE)
  475. {
  476. throw new Merchant_exception(lang('merchant_card_expired'));
  477. }
  478. }
  479. /**
  480. * Luhn algorithm number checker - (c) 2005-2008 shaman - www.planzero.org
  481. * This code has been released into the public domain, however please
  482. * give credit to the original author where possible.
  483. *
  484. * @return boolean TRUE if the number is valid
  485. */
  486. protected function validate_luhn($number)
  487. {
  488. // Set the string length and parity
  489. $number_length = strlen($number);
  490. $parity = $number_length % 2;
  491. // Loop through each digit and do the maths
  492. $total = 0;
  493. for ($i = 0; $i < $number_length; $i++)
  494. {
  495. $digit = $number[$i];
  496. // Multiply alternate digits by two
  497. if ($i % 2 == $parity)
  498. {
  499. $digit *= 2;
  500. // If the sum is two digits, add them together (in effect)
  501. if ($digit > 9)
  502. {
  503. $digit -= 9;
  504. }
  505. }
  506. // Total up the digits
  507. $total += $digit;
  508. }
  509. // If the total mod 10 equals 0, the number is valid
  510. return ($total % 10 == 0) ? TRUE : FALSE;
  511. }
  512. /**
  513. * Check whether an expiry date has already passed
  514. *
  515. * @return bool TRUE if the expiry date is valid
  516. */
  517. protected function validate_expiry($month, $year)
  518. {
  519. // subtract 12 hours from current GMT time to avoid potential timezone issues
  520. // in this rare case we will leave it up to the payment gateway to decide
  521. $date = getdate(gmmktime() - 43200); // 12*60*60
  522. if ($year < $date['year'])
  523. {
  524. return FALSE;
  525. }
  526. if ($year == $date['year'] AND $month < $date['mon'])
  527. {
  528. return FALSE;
  529. }
  530. return TRUE;
  531. }
  532. /**
  533. * Returns TRUE if the current request was made using HTTPS
  534. */
  535. protected function secure_request()
  536. {
  537. if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) AND $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
  538. {
  539. return TRUE;
  540. }
  541. if (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) == 'off')
  542. {
  543. return FALSE;
  544. }
  545. return TRUE;
  546. }
  547. protected function amount_dollars()
  548. {
  549. if (in_array($this->param('currency'), Merchant::$CURRENCIES_WITHOUT_DECIMALS))
  550. {
  551. return round($this->param('amount'));
  552. }
  553. return sprintf('%01.2f', $this->param('amount'));
  554. }
  555. protected function amount_cents()
  556. {
  557. if (in_array($this->param('currency'), Merchant::$CURRENCIES_WITHOUT_DECIMALS))
  558. {
  559. return round($this->param('amount'));
  560. }
  561. return round($this->param('amount') * 100);
  562. }
  563. protected function currency()
  564. {
  565. return $this->param('currency');
  566. }
  567. protected function currency_numeric()
  568. {
  569. $code = $this->param('currency');
  570. return isset(Merchant::$NUMERIC_CURRENCY_CODES[$code]) ? Merchant::$NUMERIC_CURRENCY_CODES[$code] : 0;
  571. }
  572. /**
  573. * Make a standard HTTP GET request.
  574. * This method is only public to support the deprecated Merchant::curl_helper() method,
  575. * and will be marked as protected in a future version.
  576. *
  577. * @param string $url The URL to request
  578. * @param string $username
  579. * @param string $password
  580. * @param array $extra_headers
  581. */
  582. public function get_request($url, $username = NULL, $password = NULL, $extra_headers = NULL)
  583. {
  584. $ch = curl_init($url);
  585. return $this->_do_curl_request($ch, $username, $password, $extra_headers);
  586. }
  587. /**
  588. * Make a standard HTTP POST request.
  589. * This method is only public to support the deprecated Merchant::curl_helper() method,
  590. * and will be marked as protected in a future version.
  591. *
  592. * @param string $url The URL to request
  593. * @param mixed $data An optional string or array of form data which will be appended to the URL
  594. * @param string $username
  595. * @param string $password
  596. * @param array $extra_headers
  597. */
  598. public function post_request($url, $data = NULL, $username = NULL, $password = NULL, $extra_headers = NULL)
  599. {
  600. $ch = curl_init($url);
  601. if (is_array($data))
  602. {
  603. $data = http_build_query($data);
  604. }
  605. curl_setopt($ch, CURLOPT_POST, TRUE);
  606. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  607. return $this->_do_curl_request($ch, $username, $password, $extra_headers);
  608. }
  609. private function _do_curl_request($ch, $username, $password, $extra_headers)
  610. {
  611. curl_setopt($ch, CURLOPT_HEADER, FALSE);
  612. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  613. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
  614. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
  615. curl_setopt($ch, CURLOPT_CAINFO, MERCHANT_CONFIG_PATH.'/cacert.pem');
  616. if ($username !== NULL)
  617. {
  618. curl_setopt($ch, CURLOPT_USERPWD, $username.':'.$password);
  619. }
  620. if ( ! empty($extra_headers))
  621. {
  622. curl_setopt($ch, CURLOPT_HTTPHEADER, $extra_headers);
  623. }
  624. $response = curl_exec($ch);
  625. $error = curl_error($ch);
  626. if ( ! empty($error))
  627. {
  628. throw new Merchant_exception($error);
  629. }
  630. curl_close($ch);
  631. return $response;
  632. }
  633. /**
  634. * Redirect the user's browser to a URL.
  635. */
  636. protected function redirect($url)
  637. {
  638. return Merchant::redirect($url);
  639. }
  640. /**
  641. * Redirect the user's browser to a URL using a POST request.
  642. */
  643. protected function post_redirect($url, $data, $message = NULL)
  644. {
  645. return Merchant::post_redirect($url, $data, $message);
  646. }
  647. }
  648. class Merchant_exception extends Exception {}
  649. class Merchant_response
  650. {
  651. const AUTHORIZED = 'authorized';
  652. const COMPLETE = 'complete';
  653. const FAILED = 'failed';
  654. const REDIRECT = 'redirect';
  655. const REFUNDED = 'refunded';
  656. protected $_status;
  657. protected $_message;
  658. protected $_reference;
  659. protected $_data;
  660. protected $_redirect_url;
  661. protected $_redirect_method = 'GET';
  662. protected $_redirect_message;
  663. protected $_redirect_data;
  664. public function __construct($status, $message = NULL, $reference = NULL)
  665. {
  666. // support deprecated 'declined' status
  667. if ($status == 'declined') $status = self::FAILED;
  668. // always require a valid status
  669. if ( ! in_array($status, array(self::AUTHORIZED, self::COMPLETE, self::FAILED, self::REDIRECT, self::REFUNDED)))
  670. {
  671. throw new InvalidArgumentException(lang('merchant_invalid_status'));
  672. }
  673. $this->_status = $status;
  674. $this->_message = $message;
  675. $this->_reference = $reference;
  676. }
  677. /**
  678. * The response status.
  679. * One of self::AUTHORIZED, self::COMPLETE, self::FAILED, self::REDIRECT, or self::REFUNDED
  680. */
  681. public function status()
  682. {
  683. return $this->_status;
  684. }
  685. /**
  686. * Whether the request was successful.
  687. */
  688. public function success()
  689. {
  690. return $this->_status !== self::FAILED;
  691. }
  692. /**
  693. * A plain text message returned by the payment gateway.
  694. */
  695. public function message()
  696. {
  697. return $this->_message;
  698. }
  699. /**
  700. * A transaction reference generated by the payment gateway.
  701. */
  702. public function reference()
  703. {
  704. return $this->_reference;
  705. }
  706. /**
  707. * The raw response data returned by the payment gateway.
  708. */
  709. public function data()
  710. {
  711. return $this->_data;
  712. }
  713. /**
  714. * Does this response require a redirect?
  715. */
  716. public function is_redirect()
  717. {
  718. return $this->_status === self::REDIRECT;
  719. }
  720. /**
  721. * If this response requires a redirect, the URL which must be redirected to.
  722. */
  723. public function redirect_url()
  724. {
  725. return $this->_redirect_url;
  726. }
  727. /**
  728. * The HTTP redirect method required (either "GET" or "POST").
  729. */
  730. public function redirect_method()
  731. {
  732. return $this->_redirect_method;
  733. }
  734. /**
  735. * A message to display while redirecting using the POST method.
  736. */
  737. public function redirect_message()
  738. {
  739. return $this->_redirect_message;
  740. }
  741. /**
  742. * If this response requires a POST redirect, the HTTP form data which must be submitted.
  743. */
  744. public function redirect_data()
  745. {
  746. return $this->_redirect_data;
  747. }
  748. /**
  749. * Perform the required redirect. If no redirect is required, returns FALSE.
  750. */
  751. public function redirect()
  752. {
  753. if ($this->is_redirect() == FALSE) return FALSE;
  754. if ('POST' == strtoupper($this->redirect_method()))
  755. {
  756. return Merchant::post_redirect($this->redirect_url(), $this->redirect_data(), $this->redirect_message());
  757. }
  758. return Merchant::redirect($this->redirect_url());
  759. }
  760. }
  761. /* End of file ./libraries/merchant/merchant.php */