PageRenderTime 70ms CodeModel.GetById 42ms RepoModel.GetById 0ms app.codeStats 0ms

/administrator/components/com_virtuemart/classes/payment/payflow_pro.php

https://bitbucket.org/dgough/annamaria-daneswood-25102012
PHP | 826 lines | 614 code | 106 blank | 106 comment | 49 complexity | 77ed004dbe1b63a080b51789922dda92 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. if( !defined( '_VALID_MOS' ) && !defined( '_JEXEC' ) ) die( 'Direct Access to '.basename(__FILE__).' is not allowed.' );
  3. /**
  4. * The PayFlow Pro class, containing the payment processing code
  5. * for transactions with payflowpro.verisign.com
  6. *
  7. * @version $Id: payflow_pro.php 1095 2007-12-19 20:19:16Z soeren_nb $
  8. * @package VirtueMart
  9. * @subpackage payment
  10. * @copyright Copyright (C) 2007 Soeren Eberhardt. All rights reserved.
  11. * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php
  12. * VirtueMart is free software. This version may have been modified pursuant
  13. * to the GNU General Public License, and as distributed it includes or
  14. * is derivative of works licensed under the GNU General Public License or
  15. * other free or open source software licenses.
  16. * See /administrator/components/com_virtuemart/COPYRIGHT.php for copyright notices and details.
  17. *
  18. * http://virtuemart.net
  19. */
  20. define ('PFP_CLIENT_CERTIFICATION_ID', 'bea46ef28cd8693d8b191d2d011b7fd1');
  21. class payflow_pro {
  22. var $payment_code = "PFP";
  23. var $classname = "payflow_pro";
  24. /**
  25. * Show all configuration parameters for this payment method
  26. * @returns boolean False when the Payment method has no configration
  27. */
  28. function show_configuration() {
  29. global $VM_LANG, $sess;
  30. $db =& new ps_DB;
  31. $payment_method_id = mosGetParam( $_REQUEST, 'payment_method_id', null );
  32. /** Read current Configuration ***/
  33. require_once(CLASSPATH ."payment/".$this->classname.".cfg.php");
  34. ?>
  35. <table>
  36. <tr>
  37. <td><strong><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_ENABLE_PFP_TESTMODE') ?></strong></td>
  38. <td>
  39. <select name="PFP_TEST_REQUEST" class="inputbox" >
  40. <option <?php if (PFP_TEST_REQUEST == 'TRUE') echo "selected=\"selected\""; ?> value="TRUE"><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_YES') ?></option>
  41. <option <?php if (PFP_TEST_REQUEST == 'FALSE') echo "selected=\"selected\""; ?> value="FALSE"><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_NO') ?></option>
  42. </select>
  43. </td>
  44. <td><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_ENABLE_PFP_TESTMODE_EXPLAIN') ?></td>
  45. </tr>
  46. <tr>
  47. <td><strong><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PFP_PARTNER') ?></strong></td>
  48. <td>
  49. <input type="text" name="PFP_PARTNER" class="inputbox" value="<?php echo PFP_PARTNER ?>" />
  50. </td>
  51. <td><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PFP_PARTNET_EXPLAIN') ?></td>
  52. </tr>
  53. <tr>
  54. <td><strong><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PFP_VENDOR') ?></strong></td>
  55. <td>
  56. <input type="text" name="PFP_VENDOR" class="inputbox" value="<?php echo PFP_VENDOR ?>" />
  57. </td>
  58. <td><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PFP_VENDOR_EXPLAIN') ?></td>
  59. </tr>
  60. <tr>
  61. <td><strong><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PFP_USER') ?></strong></td>
  62. <td>
  63. <input type="text" name="PFP_USER" class="inputbox" value="<?php echo PFP_USER ?>" />
  64. </td>
  65. <td><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PFP_USER_EXPLAIN') ?></td>
  66. </tr>
  67. <tr>
  68. <td><strong><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PFP_PASSWORD') ?></strong></td>
  69. <td>
  70. <a id="changekey" href="<?php $sess->purl($_SERVER['PHP_SELF']."?page=store.payment_method_keychange&pshop_mode=admin&payment_method_id=$payment_method_id") ?>" >
  71. <input onclick="document.location=document.getElementById('changekey').href" type="button" name="" value="<?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PFP_PASSWORD_SETCHANGE') ?>" class="button" /><a/>
  72. </td>
  73. <td>&nbsp;</td>
  74. </tr>
  75. <tr>
  76. <td><strong><?php echo $VM_LANG->_('PHPSHOP_PAYMENT_CVV2') ?></strong></td>
  77. <td>
  78. <select name="PFP_CHECK_CARD_CODE" class="inputbox">
  79. <option <?php if (PFP_CHECK_CARD_CODE == 'YES') echo "selected=\"selected\""; ?> value="YES">
  80. <?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_YES') ?></option>
  81. <option <?php if (PFP_CHECK_CARD_CODE == 'NO') echo "selected=\"selected\""; ?> value="NO">
  82. <?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_NO') ?></option>
  83. </select>
  84. </td>
  85. <td><?php echo $VM_LANG->_('PHPSHOP_PAYMENT_CVV2_TOOLTIP') ?></td>
  86. </tr>
  87. <tr><td colspan="3"><hr/></td></tr>
  88. <tr>
  89. <td><strong><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PAYMENT_ORDERSTATUS_SUCC') ?></strong></td>
  90. <td>
  91. <select name="PFP_VERIFIED_STATUS" class="inputbox" >
  92. <?php
  93. $q = "SELECT order_status_name,order_status_code FROM #__{vm}_order_status ORDER BY list_order";
  94. $db->query($q);
  95. $order_status_code = Array();
  96. $order_status_name = Array();
  97. while ($db->next_record()) {
  98. $order_status_code[] = $db->f("order_status_code");
  99. $order_status_name[] = $db->f("order_status_name");
  100. }
  101. for ($i = 0; $i < sizeof($order_status_code); $i++) {
  102. echo "<option value=\"" . $order_status_code[$i];
  103. if (PFP_VERIFIED_STATUS == $order_status_code[$i])
  104. echo "\" selected=\"selected\">";
  105. else
  106. echo "\">";
  107. echo $order_status_name[$i] . "</option>\n";
  108. }?>
  109. </select>
  110. </td>
  111. <td><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PAYMENT_ORDERSTATUS_SUCC_EXPLAIN') ?></td>
  112. </tr>
  113. <tr>
  114. <td><strong><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PAYMENT_ORDERSTATUS_FAIL') ?></strong></td>
  115. <td>
  116. <select name="PFP_INVALID_STATUS" class="inputbox" >
  117. <?php
  118. for ($i = 0; $i < sizeof($order_status_code); $i++) {
  119. echo "<option value=\"" . $order_status_code[$i];
  120. if (PFP_INVALID_STATUS == $order_status_code[$i])
  121. echo "\" selected=\"selected\">";
  122. else
  123. echo "\">";
  124. echo $order_status_name[$i] . "</option>\n";
  125. } ?>
  126. </select>
  127. </td>
  128. <td><?php echo $VM_LANG->_('PHPSHOP_ADMIN_CFG_PAYMENT_ORDERSTATUS_FAIL_EXPLAIN') ?></td>
  129. </tr>
  130. </table>
  131. <?php
  132. // return false if there's no configuration
  133. return true;
  134. }
  135. function has_configuration() {
  136. // return false if there's no configuration
  137. return true;
  138. }
  139. /**
  140. * Returns the "is_writeable" status of the configuration file
  141. * @param void
  142. * @returns boolean True when the configuration file is writeable, false when not
  143. */
  144. function configfile_writeable() {
  145. return is_writeable( CLASSPATH."payment/".$this->classname.".cfg.php" );
  146. }
  147. /**
  148. * Returns the "is_readable" status of the configuration file
  149. * @param void
  150. * @returns boolean True when the configuration file is writeable, false when not
  151. */
  152. function configfile_readable() {
  153. return is_readable( CLASSPATH."payment/".$this->classname.".cfg.php" );
  154. }
  155. /**
  156. * Writes the configuration file for this payment method
  157. * @param array An array of objects
  158. * @returns boolean True when writing was successful
  159. */
  160. function write_configuration( &$d ) {
  161. $my_config_array = array("PFP_TEST_REQUEST" => $d['PFP_TEST_REQUEST'],
  162. "PFP_PARTNER" => $d['PFP_PARTNER'],
  163. "PFP_VENDOR" => $d['PFP_VENDOR'],
  164. "PFP_USER" => $d['PFP_USER'],
  165. "PFP_CHECK_CARD_CODE" => $d['PFP_CHECK_CARD_CODE'],
  166. "PFP_VERIFIED_STATUS" => $d['PFP_VERIFIED_STATUS'],
  167. "PFP_INVALID_STATUS" => $d['PFP_INVALID_STATUS']
  168. );
  169. $config = "<?php\n";
  170. $config .= "if( !defined( '_VALID_MOS' ) && !defined( '_JEXEC' ) ) die( 'Direct Access to '.basename(__FILE__).' is not allowed.' ); \n\n";
  171. foreach( $my_config_array as $key => $value ) {
  172. $config .= "define ('$key', '$value');\n";
  173. }
  174. $config .= "?>";
  175. if ($fp = fopen(CLASSPATH ."payment/".$this->classname.".cfg.php", "w")) {
  176. fputs($fp, $config, strlen($config));
  177. fclose ($fp);
  178. return true;
  179. }
  180. else {
  181. return false;
  182. }
  183. }
  184. /**
  185. * process transaction with Payflow Pro
  186. * Authorizes the amount for the customer account
  187. *
  188. * @param string $order_number
  189. * @param float $order_total
  190. * @param array $d
  191. * @return boolean
  192. */
  193. function process_payment($order_number, $order_total, &$d) {
  194. global $vendor_mail, $vendor_currency, $VM_LANG, $vmLogger;
  195. $database = new ps_DB;
  196. $ps_vendor_id = $_SESSION["ps_vendor_id"];
  197. $auth = $_SESSION['auth'];
  198. $ps_checkout = new ps_checkout;
  199. // Get the Configuration File for authorize.net
  200. require_once(CLASSPATH ."payment/".$this->classname.".cfg.php");
  201. // connector class
  202. require_once(CLASSPATH ."connectionTools.class.php");
  203. // Get the Password securely from the database
  204. $database->query( "SELECT ".VM_DECRYPT_FUNCTION."(payment_passkey,'".ENCODE_KEY."') as passkey FROM #__{vm}_payment_method WHERE payment_class='".$this->classname."' AND shopper_group_id='".$auth['shopper_group_id']."'" );
  205. $transaction = $database->record[0];
  206. if( empty($transaction->passkey)) {
  207. $vmLogger->err( $VM_LANG->_('PHPSHOP_PAYMENT_ERROR',false).'. Technical Note: The required passwird is empty! The payment method settings must be reviewed.' );
  208. return false;
  209. }
  210. // Get user billing information
  211. $dbbt = new ps_DB;
  212. $qt = "SELECT * FROM #__{vm}_user_info WHERE user_id=".$auth["user_id"]." AND address_type='BT'";
  213. $dbbt->query($qt);
  214. $dbbt->next_record();
  215. $user_info_id = $dbbt->f("user_info_id");
  216. if( $user_info_id != $d["ship_to_info_id"]) {
  217. // Get user billing information
  218. $dbst =& new ps_DB;
  219. $qt = "SELECT * FROM #__{vm}_user_info WHERE user_info_id='".$d["ship_to_info_id"]."' AND address_type='ST'";
  220. $dbst->query($qt);
  221. $dbst->next_record();
  222. }
  223. else {
  224. $dbst = $dbbt;
  225. }
  226. $tempstr = $_SESSION['ccdata']['order_payment_number'] . $order_total . date('YmdGis');
  227. $request_id = md5($tempstr);
  228. //Authnet vars to send
  229. $formdata = array (
  230. 'PARTNER' => PFP_PARTNER,
  231. 'VENDOR' => PFP_VENDOR,
  232. 'USER' => PFP_USER,
  233. 'PWD' => $transaction->passkey,
  234. 'TEST' => PFP_TEST_REQUEST,
  235. // Transaction Data
  236. 'AMT' => $order_total, // amount
  237. 'TRXTYPE' => 'A', // transaction type: Delayed Capture
  238. 'TENDER' => 'C', // payment method (C = Credit Card)
  239. 'CURRENCY' => $vendor_currency,
  240. // Customer Name and Billing Address
  241. 'NAME' => strtoupper(substr($dbbt->f("first_name"), 0, 15).substr($dbbt->f("last_name"), 0, 15)),
  242. 'STREET' => substr($dbbt->f("address_1"), 0, 30),
  243. 'CITY' => substr($dbbt->f("city"), 0, 40),
  244. 'STATE' => substr($dbbt->f("state"), 0, 40),
  245. 'ZIP' => substr($dbbt->f("zip"), 0, 9 ),
  246. // Invoice Information
  247. 'CUSTREF' => substr($order_number, 0, 12),
  248. // Account Data
  249. 'ACCT' => $_SESSION['ccdata']['order_payment_number'],
  250. 'CVV2' => $_SESSION['ccdata']['credit_card_code'],
  251. 'EXPDATE' => ($_SESSION['ccdata']['order_payment_expire_month']) . substr($_SESSION['ccdata']['order_payment_expire_year'], 2 )
  252. );
  253. //build the post string
  254. $poststring = '';
  255. foreach($formdata AS $key => $val){
  256. $poststring .= urlencode($key) . "=" . urlencode($val) . "&";
  257. }
  258. // strip off trailing ampersand
  259. $poststring = substr($poststring, 0, -1);
  260. if(PFP_TEST_REQUEST=='TRUE') {
  261. $host = 'pilot-payflowpro.verisign.com';
  262. } else {
  263. $host = 'payflowpro.verisign.com';
  264. }
  265. $headers[] = "X-VPS-Timeout: 30";
  266. $headers[] = "X-VPS-VIT-OS-Name: ".PHP_OS; // Name of your OS
  267. $headers[] = "X-VPS-VIT-OS-Version: ".PHP_OS; // OS Version
  268. $headers[] = "X-VPS-VIT-Client-Type: PHP/cURL"; // What you are using
  269. $headers[] = "X-VPS-VIT-Client-Version: 0.01"; // For your info
  270. $headers[] = "X-VPS-VIT-Client-Architecture: x86"; // For your info
  271. $headers[] = "X-VPS-VIT-Client-Certification-Id: ".PFP_CLIENT_CERTIFICATION_ID; // get this from Todd @ payflowintegrator@paypal.com
  272. $headers[] = "X-VPS-VIT-Integration-Product: ".phpversion()."::cURL"; // For your info, would populate with application name
  273. $headers[] = "X-VPS-VIT-Integration-Version: 0.01"; // Application version
  274. $headers[] = "X-VPS-Request-ID: " . $request_id;
  275. $result = vmConnector::handleCommunication( "https://$host:443/transaction/", $poststring, $headers );
  276. if( !$result ) {
  277. $vmLogger->err('The transaction could not be completed.' );
  278. return false;
  279. }
  280. $result = strstr($result, 'RESULT');
  281. $valArray = explode('&', $result);
  282. foreach($valArray as $val) {
  283. $valArray2 = explode('=', $val);
  284. $pfpro[$valArray2[0]] = $valArray2[1];
  285. }
  286. $vmLogger->debug('Beginning to analyse the response from '.$host);
  287. $RESULT_CODE = mosGetParam( $pfpro, 'RESULT' );
  288. $TRANSACTION_ID = mosGetParam( $pfpro, 'PNREF' );
  289. $RESPMSG = mosGetParam( $pfpro, 'RESPMSG', '' );
  290. $CVV2MATCH = mosGetParam( $pfpro, 'CVV2MATCH', '' );
  291. $success = false;
  292. switch($RESULT_CODE) {
  293. case '0':
  294. // Approved - Success!
  295. $success = true;
  296. $d["order_payment_log"] = $VM_LANG->_('PHPSHOP_PAYMENT_TRANSACTION_SUCCESS').": ";
  297. $d["order_payment_log"] .= $RESPMSG;
  298. $vmLogger->debug( $d['order_payment_log']);
  299. break;
  300. default:
  301. $d["order_payment_log"] = payflow_pro::getResponseMsg( $RESULT_CODE );
  302. if( !empty( $d["order_payment_log"] )) {
  303. $vmLogger->err( $d["order_payment_log"] );
  304. } else {
  305. $vmLogger->err( 'An unknown Error occured while processing your Payment Request.');
  306. }
  307. break;
  308. }
  309. // Catch Transaction ID
  310. $d["order_payment_trans_id"] = $TRANSACTION_ID;
  311. return $success;
  312. }
  313. /**
  314. * Process a previous transaction with Payflow Pro and Capture the Payment
  315. *
  316. * @param array $d
  317. * @return boolean
  318. */
  319. function capture_payment( &$d ) {
  320. global $vendor_mail, $vendor_currency, $VM_LANG, $vmLogger;
  321. $database = new ps_DB();
  322. require_once(CLASSPATH ."connectionTools.class.php");
  323. if( empty($d['order_number'])) {
  324. $vmLogger->err("Error: No Order Number provided.");
  325. return false;
  326. }
  327. /*** Get the Configuration File for authorize.net ***/
  328. require_once(CLASSPATH ."payment/".$this->classname.".cfg.php");
  329. // Get the Account Password securely from the database
  330. $database->query( "SELECT ".VM_DECRYPT_FUNCTION."(payment_passkey,'".ENCODE_KEY."') as passkey FROM #__{vm}_payment_method WHERE payment_class='".$this->classname."'" );
  331. $transaction = $database->record[0];
  332. if( empty($transaction->passkey)) {
  333. $vmLogger->err($VM_LANG->_('PHPSHOP_PAYMENT_ERROR'),false);
  334. return false;
  335. }
  336. $db = new ps_DB;
  337. $q = "SELECT * FROM #__{vm}_orders, #__{vm}_order_payment WHERE ";
  338. $q .= "order_number='".$d['order_number']."' ";
  339. $q .= "AND #__{vm}_orders.order_id=#__{vm}_order_payment.order_id";
  340. $db->query( $q );
  341. if( !$db->next_record() ) {
  342. $vmLogger->err("Error: Order not found.");
  343. return false;
  344. }
  345. $expire_date = date( "my", $db->f("order_payment_expire") );
  346. $cvv2_code = $db->f("order_payment_code");
  347. // DECODE Account Number
  348. $dbaccount = new ps_DB;
  349. $q = "SELECT ".VM_DECRYPT_FUNCTION."(order_payment_number,'".ENCODE_KEY."')
  350. AS account_number from #__{vm}_order_payment WHERE order_id='".$db->f("order_id")."'";
  351. $dbaccount->query($q);
  352. $dbaccount->next_record();
  353. // Get user billing information
  354. $dbbt = new ps_DB;
  355. $qt = "SELECT * FROM #__{vm}_user_info WHERE user_id='".$db->f("user_id")."'";
  356. $dbbt->query($qt);
  357. $dbbt->next_record();
  358. $user_info_id = $dbbt->f("user_info_id");
  359. if( $user_info_id != $db->f("user_info_id")) {
  360. // Get user's alternative shipping information
  361. $dbst =& new ps_DB;
  362. $qt = "SELECT * FROM #__{vm}_user_info WHERE user_info_id='".$db->f("user_info_id")."' AND address_type='ST'";
  363. $dbst->query($qt);
  364. $dbst->next_record();
  365. }
  366. else {
  367. $dbst = $dbbt;
  368. }
  369. $tempstr = $dbaccount->f('account_number') . $db->f('order_total') . date('YmdGis');
  370. $request_id = md5($tempstr);
  371. //Authnet vars to send
  372. $formdata = array (
  373. 'PARTNER' => PFP_PARTNER,
  374. 'VENDOR' => PFP_VENDOR,
  375. 'USER' => PFP_USER,
  376. 'PWD' => $transaction->passkey,
  377. 'TEST' => PFP_TEST_REQUEST,
  378. // Transaction Data
  379. 'AMT' => $db->f('order_total'), // amount
  380. 'TRXTYPE' => 'D', // transaction type: Delayed Capture
  381. 'TENDER' => 'C', // payment method (C = Credit Card)
  382. 'CURRENCY' => $vendor_currency,
  383. // Customer Name and Billing Address
  384. 'NAME' => strtoupper(substr($dbbt->f("first_name"), 0, 15).substr($dbbt->f("last_name"), 0, 15)),
  385. 'STREET' => substr($dbbt->f("address_1"), 0, 30),
  386. 'CITY' => substr($dbbt->f("city"), 0, 40),
  387. 'STATE' => substr($dbbt->f("state"), 0, 40),
  388. 'ZIP' => substr($dbbt->f("zip"), 0, 9 ),
  389. // Invoice Information
  390. 'CUSTREF' => substr($db->f('order_number'), 0, 12),
  391. // Account Data
  392. 'ORIGID' => $db->f('order_payment_trans_id'),
  393. 'ACCT' => $dbaccount->f('account_number'),
  394. 'CVV2' => $cvv2_code,
  395. 'EXPDATE' => $expire_date
  396. );
  397. //build the post string
  398. $poststring = '';
  399. foreach($formdata AS $key => $val){
  400. $poststring .= urlencode($key) . "=" . urlencode($val) . "&";
  401. }
  402. // strip off trailing ampersand
  403. $poststring = substr($poststring, 0, -1);
  404. if(PFP_TEST_REQUEST=='TRUE') {
  405. $host = 'pilot-payflowpro.verisign.com';
  406. } else {
  407. $host = 'payflowpro.verisign.com';
  408. }
  409. $headers[] = "X-VPS-Timeout: 30";
  410. $headers[] = "X-VPS-VIT-OS-Name: ".PHP_OS; // Name of your OS
  411. $headers[] = "X-VPS-VIT-OS-Version: ".PHP_OS; // OS Version
  412. $headers[] = "X-VPS-VIT-Client-Type: PHP/cURL"; // What you are using
  413. $headers[] = "X-VPS-VIT-Client-Version: 0.01"; // For your info
  414. $headers[] = "X-VPS-VIT-Client-Architecture: x86"; // For your info
  415. $headers[] = "X-VPS-VIT-Client-Certification-Id: ".PFP_CLIENT_CERTIFICATION_ID; // get this from Todd @ payflowintegrator@paypal.com
  416. $headers[] = "X-VPS-VIT-Integration-Product: ".phpversion()."::cURL"; // For your info, would populate with application name
  417. $headers[] = "X-VPS-VIT-Integration-Version: 0.01"; // Application version
  418. $headers[] = "X-VPS-Request-ID: " . $request_id;
  419. $result = vmConnector::handleCommunication( "https://$host:443/transaction", $poststring, $headers );
  420. if( !$result ) {
  421. $vmLogger->err('The transaction could not be completed.' );
  422. return false;
  423. }
  424. $result = strstr($result, 'RESULT');
  425. $valArray = explode('&', $result);
  426. foreach($valArray as $val) {
  427. $valArray2 = explode('=', $val);
  428. $pfpro[$valArray2[0]] = $valArray2[1];
  429. }
  430. $vmLogger->debug('Beginning to analyse the response from '.$host);
  431. $RESULT_CODE = mosGetParam( $pfpro, 'RESULT' );
  432. $TRANSACTION_ID = mosGetParam( $pfpro, 'PNREF' );
  433. $RESPMSG = mosGetParam( $pfpro, 'RESPMSG', '' );
  434. $CVV2MATCH = mosGetParam( $pfpro, 'CVV2MATCH', '' );
  435. $success = false;
  436. switch($RESULT_CODE) {
  437. case '0':
  438. // Approved - Success!
  439. $success = true;
  440. $d["order_payment_log"] = $VM_LANG->_('PHPSHOP_PAYMENT_TRANSACTION_SUCCESS').": ";
  441. $d["order_payment_log"] .= $RESPMSG;
  442. $q = "UPDATE #__{vm}_order_payment SET ";
  443. $q .="order_payment_log='".$d["order_payment_log"]."',";
  444. $q .="order_payment_trans_id='".$TRANSACTION_ID."' ";
  445. $q .="WHERE order_id='".$db->f("order_id")."' ";
  446. $db->query( $q );
  447. $vmLogger->debug( $d['order_payment_log']);
  448. break;
  449. default:
  450. $d["order_payment_log"] = payflow_pro::getResponseMsg( $RESULT_CODE );
  451. if( !empty( $d["order_payment_log"] )) {
  452. $vmLogger->err( $d["order_payment_log"] );
  453. } else {
  454. $vmLogger->err( 'An unknown Error occured while capturing the Payment.');
  455. }
  456. break;
  457. }
  458. return $success;
  459. }
  460. /**
  461. * Voids a previous transaction with Payflow Pro
  462. *
  463. * @param array $d
  464. * @return boolean
  465. */
  466. function void_authorization( &$d ) {
  467. global $vendor_mail, $vendor_currency, $VM_LANG, $vmLogger;
  468. $database = new ps_DB();
  469. require_once(CLASSPATH ."connectionTools.class.php");
  470. if( empty($d['order_number'])) {
  471. $vmLogger->err("Error: No Order Number provided.");
  472. return false;
  473. }
  474. /*** Get the Configuration File for authorize.net ***/
  475. require_once(CLASSPATH ."payment/".$this->classname.".cfg.php");
  476. // Get the Account Password securely from the database
  477. $database->query( "SELECT ".VM_DECRYPT_FUNCTION."(payment_passkey,'".ENCODE_KEY."') as passkey FROM #__{vm}_payment_method WHERE payment_class='".$this->classname."'" );
  478. $transaction = $database->record[0];
  479. if( empty($transaction->passkey)) {
  480. $vmLogger->err($VM_LANG->_('PHPSHOP_PAYMENT_ERROR'),false);
  481. return false;
  482. }
  483. $db = new ps_DB;
  484. $q = "SELECT * FROM #__{vm}_orders, #__{vm}_order_payment WHERE ";
  485. $q .= "order_number='".$d['order_number']."' ";
  486. $q .= "AND #__{vm}_orders.order_id=#__{vm}_order_payment.order_id";
  487. $db->query( $q );
  488. if( !$db->next_record() ) {
  489. $vmLogger->err("Error: Order not found.");
  490. return false;
  491. }
  492. $expire_date = date( "my", $db->f("order_payment_expire") );
  493. $cvv2_code = $db->f("order_payment_code");
  494. // DECODE Account Number
  495. $dbaccount = new ps_DB;
  496. $q = "SELECT ".VM_DECRYPT_FUNCTION."(order_payment_number,'".ENCODE_KEY."')
  497. AS account_number from #__{vm}_order_payment WHERE order_id='".$db->f("order_id")."'";
  498. $dbaccount->query($q);
  499. $dbaccount->next_record();
  500. // Get user billing information
  501. $dbbt = new ps_DB;
  502. $qt = "SELECT * FROM #__{vm}_user_info WHERE user_id='".$db->f("user_id")."'";
  503. $dbbt->query($qt);
  504. $dbbt->next_record();
  505. $user_info_id = $dbbt->f("user_info_id");
  506. if( $user_info_id != $db->f("user_info_id")) {
  507. // Get user's alternative shipping information
  508. $dbst =& new ps_DB;
  509. $qt = "SELECT * FROM #__{vm}_user_info WHERE user_info_id='".$db->f("user_info_id")."' AND address_type='ST'";
  510. $dbst->query($qt);
  511. $dbst->next_record();
  512. }
  513. else {
  514. $dbst = $dbbt;
  515. }
  516. $tempstr = $dbaccount->f('account_number') . $db->f('order_total') . date('YmdGis');
  517. $request_id = md5($tempstr);
  518. //Authnet vars to send
  519. $formdata = array (
  520. 'PARTNER' => PFP_PARTNER,
  521. 'VENDOR' => PFP_VENDOR,
  522. 'USER' => PFP_USER,
  523. 'PWD' => $transaction->passkey,
  524. 'TEST' => PFP_TEST_REQUEST,
  525. // Transaction Data
  526. 'AMT' => $db->f('order_total'), // amount
  527. 'TRXTYPE' => 'V', // transaction type: Void
  528. 'TENDER' => 'C', // payment method (C = Credit Card)
  529. 'CURRENCY' => $vendor_currency,
  530. // Customer Name and Billing Address
  531. 'NAME' => strtoupper(substr($dbbt->f("first_name"), 0, 15).substr($dbbt->f("last_name"), 0, 15)),
  532. 'STREET' => substr($dbbt->f("address_1"), 0, 30),
  533. 'CITY' => substr($dbbt->f("city"), 0, 40),
  534. 'STATE' => substr($dbbt->f("state"), 0, 40),
  535. 'ZIP' => substr($dbbt->f("zip"), 0, 9 ),
  536. // Invoice Information
  537. 'CUSTREF' => substr($db->f('order_number'), 0, 12),
  538. // Account Data
  539. 'ORIGID' => $db->f('order_payment_trans_id'),
  540. 'ACCT' => $dbaccount->f('account_number'),
  541. 'CVV2' => $cvv2_code,
  542. 'EXPDATE' => $expire_date
  543. );
  544. //build the post string
  545. $poststring = '';
  546. foreach($formdata AS $key => $val){
  547. $poststring .= urlencode($key) . "=" . urlencode($val) . "&";
  548. }
  549. // strip off trailing ampersand
  550. $poststring = substr($poststring, 0, -1);
  551. if(PFP_TEST_REQUEST=='TRUE') {
  552. $host = 'pilot-payflowpro.verisign.com';
  553. } else {
  554. $host = 'payflowpro.verisign.com';
  555. }
  556. $headers[] = "X-VPS-Timeout: 30";
  557. $headers[] = "X-VPS-VIT-OS-Name: ".PHP_OS; // Name of your OS
  558. $headers[] = "X-VPS-VIT-OS-Version: ".PHP_OS; // OS Version
  559. $headers[] = "X-VPS-VIT-Client-Type: PHP/cURL"; // What you are using
  560. $headers[] = "X-VPS-VIT-Client-Version: 0.01"; // For your info
  561. $headers[] = "X-VPS-VIT-Client-Architecture: x86"; // For your info
  562. $headers[] = "X-VPS-VIT-Client-Certification-Id: ".PFP_CLIENT_CERTIFICATION_ID; // get this from Todd @ payflowintegrator@paypal.com
  563. $headers[] = "X-VPS-VIT-Integration-Product: ".phpversion()."::cURL"; // For your info, would populate with application name
  564. $headers[] = "X-VPS-VIT-Integration-Version: 0.01"; // Application version
  565. $headers[] = "X-VPS-Request-ID: " . $request_id;
  566. $result = vmConnector::handleCommunication( "https://$host:443/transaction", $poststring, $headers );
  567. if( !$result ) {
  568. $vmLogger->err('The transaction could not be completed.' );
  569. return false;
  570. }
  571. $result = strstr($result, 'RESULT');
  572. $valArray = explode('&', $result);
  573. foreach($valArray as $val) {
  574. $valArray2 = explode('=', $val);
  575. $pfpro[$valArray2[0]] = $valArray2[1];
  576. }
  577. $vmLogger->debug('Beginning to analyse the response from '.$host);
  578. $RESULT_CODE = mosGetParam( $pfpro, 'RESULT' );
  579. $TRANSACTION_ID = mosGetParam( $pfpro, 'PNREF' );
  580. $RESPMSG = mosGetParam( $pfpro, 'RESPMSG', '' );
  581. $CVV2MATCH = mosGetParam( $pfpro, 'CVV2MATCH', '' );
  582. $success = false;
  583. switch($RESULT_CODE) {
  584. case '0':
  585. // Approved - Success!
  586. $success = true;
  587. $d["order_payment_log"] = $VM_LANG->_('PHPSHOP_PAYMENT_TRANSACTION_SUCCESS').": ";
  588. $d["order_payment_log"] .= $RESPMSG;
  589. $q = "UPDATE #__{vm}_order_payment SET ";
  590. $q .="order_payment_log='".$d["order_payment_log"]."',";
  591. $q .="order_payment_trans_id='".$TRANSACTION_ID."' ";
  592. $q .="WHERE order_id='".$db->f("order_id")."' ";
  593. $db->query( $q );
  594. $vmLogger->debug( $d['order_payment_log']);
  595. break;
  596. default:
  597. $d["order_payment_log"] = payflow_pro::getResponseMsg( $RESULT_CODE );
  598. if( !empty( $d["order_payment_log"] )) {
  599. $vmLogger->err( $d["order_payment_log"] );
  600. } else {
  601. $vmLogger->err( 'An unknown Error occured while voiding the transaction.');
  602. }
  603. break;
  604. }
  605. return $success;
  606. }
  607. /**
  608. * Returns the error / mesage for the response code returned by Payflow Pro
  609. *
  610. * @param int $response_code
  611. * @return string
  612. */
  613. function getResponseMsg( $response_code ) {
  614. switch ( $response_code ) {
  615. case '1':
  616. return 'User authentication failed. Error is caused by one or more of the following: a) Login information is incorrect. Verify that USER, VENDOR, PARTNER, and PASSWORD have been entered correctly,
  617. b) Invalid Processor information entered. Contact merchant bank to verify.
  618. c) Allowed IP Address" security feature implemented. The transaction is coming from an unknown IP address. See PayPal Manager online help for details on how to use Manager to update the allowed IP addresses.
  619. c) You are using a test (not active) account to submit a transaction to the live PayPal servers. Change the URL from test-payflow.paypal.com to payflow.paypal.com.';
  620. case '2':
  621. return "Invalid tender type. Your merchant bank account does not support the following credit card type that was submitted.";
  622. case '3':
  623. return 'Invalid transaction type. Transaction type is not appropriate for this transaction. For example, you cannot credit an authorization-only transaction.';
  624. case '4':
  625. return 'Invalid amount format. Use the format: “#####.##” Do not include currency symbols or commas.';
  626. case '5':
  627. return 'Invalid merchant information. Processor does not recognize your merchant account information. Contact your bank account acquirer to resolve this problem.';
  628. case '6':
  629. return 'Invalid or unsupported currency code';
  630. case '7':
  631. return 'Field format error. Invalid information entered. See RESPMSG.';
  632. case '8':
  633. return 'Not a transaction server';
  634. case '9':
  635. return 'Too many parameters or invalid stream';
  636. case '10':
  637. return 'Too many line items';
  638. case '11':
  639. return 'Client time-out waiting for response';
  640. case '12':
  641. return 'Declined. Check the credit card number, expiration date, and transaction information to make sure they were entered correctly. If this does not resolve the problem, have the customer call their card issuing bank to resolve.';
  642. case '13':
  643. return 'Referral. Transaction cannot be approved electronically but can be approved with a verbal authorization. Contact your merchant bank to obtain an authorization and submit a manual Voice Authorization transaction.';
  644. case '14':
  645. return 'Invalid Client Certification ID. Check the HTTP header. If the tag, X-VPS-VIT-CLIENT-CERTIFICATION-ID, is missing, RESULT code 14 is returned.';
  646. case '19':
  647. return 'Original transaction ID not found. The transaction ID you entered for this transaction is not valid. See RESPMSG.';
  648. case '20':
  649. return 'Cannot find the customer reference number';
  650. case '22':
  651. return 'Invalid ABA number';
  652. case '23':
  653. return 'Invalid account number. Check credit card number and re-submit.';
  654. case '24':
  655. return 'Invalid expiration date. Check and re-submit.';
  656. case '25':
  657. return 'Invalid Host Mapping. You are trying to process a tender type such as Discover Card, but you are not set up with your merchant bank to accept this card type.';
  658. case '26':
  659. return 'Invalid vendor account';
  660. case '27':
  661. return 'Insufficient partner permissions';
  662. case '28':
  663. return 'Insufficient user permissions';
  664. case '29':
  665. return 'Invalid XML document. This could be caused by an unrecognized XML tag or a bad XML format that cannot be parsed by the system.';
  666. case '50':
  667. return 'Insufficient funds available in account';
  668. case '51':
  669. return 'Exceeds per transaction limit';
  670. case '99':
  671. return 'General error. See RESPMSG.';
  672. case '100':
  673. return 'Transaction type not supported by host';
  674. case '101':
  675. return 'Time-out value too small';
  676. case '102':
  677. return 'Processor not available';
  678. case '103':
  679. return 'Error reading response from host';
  680. case '104':
  681. return 'Timeout waiting for processor response. Try your transaction again.';
  682. case '105':
  683. return 'Credit error. Make sure you have not already credited this transaction, or that this transaction ID is for a creditable transaction. (For example, you cannot credit an authorization.)';
  684. case '106':
  685. return 'Host not available';
  686. case '107':
  687. return 'Duplicate suppression time-out';
  688. case '108':
  689. return 'Void error. See RESPMSG. Make sure the transaction ID entered has not already been voided. If not, then look at the Transaction Detail screen for this transaction to see if it has settled. (The Batch field is set to a number greater than zero if the transaction has been settled). If the transaction has already settled, your only recourse is a reversal (credit a payment or submit a payment for a credit).';
  690. case '109':
  691. return 'Time-out waiting for host response';
  692. case '111':
  693. return 'Capture error. Either an attempt to capture a transaction that is not an authorization transaction type, or an attempt to capture an authorization transaction that has already been captured.';
  694. case '112':
  695. return 'Failed AVS check. Address and ZIP code do not match. An authorization may still exist on the cardholder’s account.';
  696. case '113':
  697. return 'Merchant sale total will exceed the sales cap with current transaction. ACH transactions only.';
  698. case '114':
  699. return 'Card Security Code (CSC) Mismatch. An authorization may still exist on the cardholder’s account.';
  700. case '115':
  701. return 'System busy, try again later';
  702. case '116':
  703. return 'VPS Internal error. Failed to lock terminal number';
  704. case '117':
  705. return 'Failed merchant rule check. One or more of the following three failures occurred:
  706. An attempt was made to submit a transaction that failed to meet the security settings specified on the PayPal Manager Security Settings page. If the transaction exceeded the Maximum Amount security setting, then no values are returned for AVS or CSC.
  707. AVS validation failed. The AVS return value should appear in the RESPMSG.
  708. CSC validation failed. The CSC return value should appear in the RESPMSG.';
  709. case '118':
  710. return 'Invalid keywords found in string fields';
  711. case '122':
  712. return 'Merchant sale total will exceed the credit cap with current transaction. ACH transactions only.';
  713. case '125':
  714. return 'Fraud Protection Services Filter — Declined by filters';
  715. case '126':
  716. return 'Fraud Protection Services Filter — Flagged for review by filters';
  717. break;
  718. }
  719. }
  720. }