Payment_Process
[ class tree: Payment_Process ] [ index: Payment_Process ] [ all elements ]

Source for file Transfirst.php

Documentation is available at Transfirst.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at                              |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Ian Eure <ieure@php.net>                                    |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Transfirst.php,v 1.3 2005/07/14 20:54:00 ieure Exp $
  20.  
  21. require_once('Payment/Process/Common.php');
  22. require_once('Net/Curl.php');
  23.  
  24. // Transfirst transaction types
  25. // Request authorization only - no funds are transferred.
  26. define('PAYMENT_PROCESS_ACTION_TRANSFIRST_AUTH'30);
  27. // Transfer funds from a previous authorization.
  28. define('PAYMENT_PROCESS_ACTION_TRANSFIRST_SETTLE'40);
  29. // Authorize & transfer funds
  30. define('PAYMENT_PROCESS_ACTION_TRANSFIRST_AUTHSETTLE'32);
  31. // Debit the indicated amount to a previously-charged card.
  32. define('PAYMENT_PROCESS_ACTION_TRANSFIRST_CREDIT'20);
  33. // Cancel authorization
  34. define('PAYMENT_PROCESS_ACTION_TRANSFIRST_VOID'61);
  35.  
  36. define('PAYMENT_PROCESS_RESULT_TRANSFIRST_APPROVAL'00);
  37. define('PAYMENT_PROCESS_RESULT_TRANSFIRST_DECLINE'05);
  38. define('PAYMENT_PROCESS_RESULT_TRANSFIRST_INVALIDAMOUNT'13);
  39. define('PAYMENT_PROCESS_RESULT_TRANSFIRST_INVALIDCARDNO'14);
  40. define('PAYMENT_PROCESS_RESULT_TRANSFIRST_REENTER'19);
  41.  
  42. // Map actions
  43. $GLOBALS['_Payment_Process_Transfirst'= array(
  44. );
  45.  
  46. /**
  47.  * Payment_Process_Transfirst
  48.  *
  49.  * This is a processor for TransFirst's merchant payment gateway, formerly known
  50.  * as DPILink. (http://www.transfirst.com/)
  51.  *
  52.  * *** WARNING ***
  53.  * This is BETA code. While I have tested it and it appears to work for me, I
  54.  * strongly recommend that you do additional testing before using it in
  55.  * production systems.
  56.  *
  57.  * @package Payment_Process
  58.  * @author Ian Eure <ieure@php.net>
  59.  * @version @version@
  60.  */
  61. class Payment_Process_Transfirst extends Payment_Process_Common {
  62.     /**
  63.      * Front-end -> back-end field map.
  64.      *
  65.      * This array contains the mapping from front-end fields (defined in
  66.      * the Payment_Process class) to the field names Transfirst requires.
  67.      *
  68.      * @see _prepare()
  69.      * @access private
  70.      */
  71.     var $_fieldMap = array(
  72.         // Required
  73.         'login'             => "DPIAccountNum",
  74.         'password'          => "password",
  75.         'action'            => "transactionCode",
  76.         'invoiceNumber'     => "orderNum",
  77.         'customerId'        => "customerNum",
  78.         'amount'            => "transactionAmount",
  79.         'transactionSource' => "ECommerce",
  80.         // Credit Card Type
  81.         'cardNumber'        => "cardAccountNum",
  82.         'expDate'           => "expirationDate",
  83.         'zip'               => "cardHolderZip",
  84.         // Common Type
  85. //         'name'              => "cardHolderName",
  86.         'address'           => "cardHolderAddress",
  87.         'city'              => "cardHolderCity",
  88.         'state'             => "cardHolderState",
  89.         'phone'             => "cardHolderPhone",
  90.         'email'             => "cardHolderEmail"
  91.     );
  92.  
  93.     /**
  94.      * Default options for this processor.
  95.      *
  96.      * @see Payment_Process::setOptions()
  97.      * @access private
  98.      */
  99.     var $_defaultOptions = array(
  100.         'authorizeUri' => "https://epaysecure.transfirst.com/eLink/authpd.asp"
  101.     );
  102.  
  103.     /**
  104.      * Has the transaction been processed?
  105.      *
  106.      * @type boolean
  107.      * @access private
  108.      */
  109.     var $_processed = false;
  110.  
  111.     /**
  112.      * The response body sent back from the gateway.
  113.      *
  114.      * @access private
  115.      */
  116.     var $_responseBody '';
  117.  
  118.     /**
  119.      * Constructor.
  120.      *
  121.      * @param  array  $options  Class options to set.
  122.      * @see Payment_Process::setOptions()
  123.      * @return void 
  124.      */
  125.     function __construct($options = false)
  126.     {
  127.         parent::__construct($options);
  128.         $this->_driver 'Transfirst';
  129.         $this->_makeRequired('login''password''action''invoiceNumber''customerId''amount''cardNumber''expDate');
  130.     }
  131.  
  132.     function Payment_Process_Transfirst($options = false)
  133.     {
  134.         $this->__construct($options);
  135.     }
  136.  
  137.     /**
  138.      * Prepare the data.
  139.      *
  140.      * This function handles the 'testTransaction' option, which is specific to
  141.      * this processor.
  142.      */
  143.     function _prepare()
  144.     {
  145.         if ($this->_options['testTransaction']{
  146.             $this->_data['testTransaction'$this->_options['testTransaction'];
  147.         }
  148.         $this->_handleCardHolderName();
  149.         return parent::_prepare();
  150.     }
  151.  
  152.     /**
  153.      * Process the transaction.
  154.      *
  155.      * @return mixed Payment_Process_Result on success, PEAR_Error on failure
  156.      */
  157.     function &process()
  158.     {
  159.         // Sanity check
  160.         if(PEAR::isError($res $this->validate())) {
  161.             return($res);
  162.         }
  163.  
  164.         // Prepare the data
  165.         $this->_prepare();
  166.  
  167.         // Don't die partway through
  168.         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  169.  
  170.         $req &new Net_Curl($this->_options['authorizeUri']);
  171.         if (PEAR::isError($req)) {
  172.             PEAR::popErrorHandling();
  173.             return $req;
  174.         }
  175.         $req->type = 'POST';
  176.         $req->fields = $this->_prepareQueryString();
  177.         $req->userAgent = 'PEAR Payment_Process_Transfirst 0.1';
  178.         $res &$req->execute();
  179.         $req->close();
  180.         if (PEAR::isError($res)) {
  181.             PEAR::popErrorHandling();
  182.             return $res;
  183.         }
  184.  
  185.         $this->_processed = true;
  186.  
  187.         // Restore error handling
  188.         PEAR::popErrorHandling();
  189.  
  190.         $response trim($res);
  191.         print "Response: {$response}\n";
  192.         $result &Payment_Process_Result::factory('Transfirst'$response);
  193.         $result->_request = &$this;
  194.         $this->_result &$result;
  195.  
  196.         return $result;
  197.  
  198.         /*
  199.          * HTTP_Request doesn't do SSL until PHP 4.3.0, but it
  200.          * might be useful later...
  201.         $req = &new HTTP_Request($this->_authUri);
  202.         $this->_setPostData();
  203.         $req->sendRequest();
  204.         */
  205.     }
  206.  
  207.     /**
  208.      * Get (completed) transaction status.
  209.      *
  210.      * @return string Two-digit status returned from gateway.
  211.      */
  212.     function getStatus()
  213.     {
  214.         if (!$this->_processed{
  215.             return PEAR::raiseError('The transaction has not been processed yet.'PAYMENT_PROCESS_ERROR_INCOMPLETE);
  216.         }
  217.         return $this->_result->code;
  218.     }
  219.  
  220.     /**
  221.      * Get transaction sequence.
  222.      *
  223.      * 'Sequence' is what Transfirst calls their transaction ID/approval code. This
  224.      * function returns that code from a processed transaction.
  225.      *
  226.      * @return mixed  Sequence ID, or PEAR_Error if the transaction hasn't been
  227.      *                 processed.
  228.      */
  229.     function getSequence()
  230.     {
  231.         if (!$this->_processed{
  232.             return PEAR::raiseError('The transaction has not been processed yet.'PAYMENT_PROCESS_ERROR_INCOMPLETE);
  233.         }
  234.         return $this->_result->_sequenceNumber;
  235.     }
  236.  
  237.     /**
  238.      * Prepare the POST query string.
  239.      *
  240.      * @access private
  241.      * @return string The query string
  242.      */
  243.     function _prepareQueryString()
  244.     {
  245.         foreach($this->_data as $var => $value{
  246.             if (strlen($value))
  247.                 $tmp[urlencode($var).'='.urlencode($value);
  248.         }
  249.         return @implode('&'$tmp);
  250.     }
  251.  
  252.     /*
  253.     function _setPostData(&$req)
  254.     {
  255.         foreach($this->_data as $var => $value) {
  256.             $req->addPostData($var, $value);
  257.         }
  258.     }
  259.     */
  260.  
  261.     /**
  262.      * Handle transaction source.
  263.      *
  264.      * @access private
  265.      */
  266.     function _handleTransactionSource()
  267.     {
  268.         $specific $this->_fieldMap['transactionSource'];
  269.         if ($this->transactionSource == PAYMENT_PROCESS_SOURCE_ONLINE{
  270.             $this->_data[$specific'Y';
  271.         else {
  272.             $this->_data[$specific'N';
  273.         }
  274.     }
  275.  
  276.     /**
  277.      * Handle card expiration date.
  278.      *
  279.      * The gateway wants the date in the format MMYY, with no other chars.
  280.      *
  281.      * @access private
  282.      */
  283.     function _handleExpDate()
  284.     {
  285.         $specific $this->_fieldMap['expDate'];
  286.         if (isset($this->_data[$specific])) {
  287.             $this->_data[$specificstr_replace('/'''$this->_data[$specific]);
  288.         else {
  289.             $this->_data[$specificstr_replace('/'''$this->expDate);
  290.         }
  291.     }
  292.  
  293.     /**
  294.      * Map firstName & lastName
  295.      *
  296.      * P_P now has split firstName/lastName fields, instead of 'name.' This
  297.      * handles concatenating them into the Transfirst cardHolderName field.
  298.      *
  299.      * @return  void 
  300.      */
  301.     function _handleCardHolderName()
  302.     {
  303.         $this->_data['cardHolderName'$this->firstName ' ' $this->lastName;
  304.     }
  305.  
  306.     /**
  307.      * Validate the merchant account login.
  308.      *
  309.      * The Transfirst docs specify that the login is exactly eight digits.
  310.      *
  311.      * @access private
  312.      * @return boolean true if valid, false otherwise
  313.      */
  314.     function _validateLogin()
  315.     {
  316.         return Validate::string($this->loginarray(
  317.             'format' => VALIDATE_NUM,
  318.             'max_length' => 8,
  319.             'min_length' => 8
  320.         ));
  321.     }
  322.  
  323.     /**
  324.      * Validate the merchant account password.
  325.      *
  326.      * The Transfirst docs specify that the password is a string between 6 and 10
  327.      * characters in length.
  328.      *
  329.      * @access private
  330.      * @return boolean true if valid, false otherwise
  331.      */
  332.     function _validatePassword()
  333.     {
  334.         return Validate::string($this->passwordarray(
  335.             'format' => VALIDATE_ALPHA . VALIDATE_NUM,
  336.             'min_length' => 6,
  337.             'max_length' => 10
  338.         ));
  339.     }
  340.  
  341.     /**
  342.      * Validate the invoice number.
  343.      *
  344.      * Invoice number must be a 5-character long alphanumeric string.
  345.      *
  346.      * @return boolean true on success, false otherwise
  347.      */
  348.     function _validateInvoiceNumber()
  349.     {
  350.         return Validate::string($this->invoiceNumberarray(
  351.             'format' => VALIDATE_NUM . VALIDATE_ALPHA,
  352.             'min_length' => 5,
  353.             'max_length' => 5
  354.         ));
  355.     }
  356.  
  357.     /**
  358.      * Validate the invoice number.
  359.      *
  360.      * Invoice no. must be a 15-character long alphanumeric string.
  361.      *
  362.      * @return boolean true on success, false otherwise
  363.      */
  364.     function _validateCustomerId()
  365.     {
  366.         return Validate::string($this->customerIdarray(
  367.             'format' => VALIDATE_NUM . VALIDATE_ALPHA,
  368.             'min_length' => 15,
  369.             'max_length' => 15
  370.         ));
  371.     }
  372.  
  373.     /**
  374.      * Validate the zip code.
  375.      *
  376.      * Zip is only required if AVS is enabled.
  377.      *
  378.      * @return boolean true on success, false otherwise.
  379.      */
  380.     function _validateZip()
  381.     {
  382.         if(strlen($this->zip|| $this->performAvs{
  383.             return parent::_validateZip();
  384.         }
  385.         return true;
  386.     }
  387. }
  388.  
  389.  
  390.     /**
  391.      * Transfirst status codes.
  392.      *
  393.      * This array holds every possible status returned by the Transfirst gateway.
  394.      *
  395.      * See the Transfirst documentation for more details on each response.
  396.      *
  397.      * @see getStatusText()
  398.      * @access private
  399.      */
  400.     var $_statusCodeMessages = array(
  401.         '00' => "Approved",
  402.         '01' => "Refer to issuer",
  403.         '02' => "Refer to issuer - Special condition",
  404.         '03' => "Invalid merchant ID",
  405.         '04' => "Pick up card",
  406.         '05' => "Declined",
  407.         '06' => "General error",
  408.         '07' => "Pick up card - Special condition",
  409.         '13' => "Invalid amount",
  410.         '14' => "Invalid card number",
  411.         '15' => "No such issuer",
  412.         '19' => "Re-enter transaction",
  413.         '21' => "Unable to back out transaction",
  414.         '28' => "File is temporarily unavailable",
  415.         '39' => "No credit account",
  416.         '41' => "Pick up card - Lost",
  417.         '43' => "Pick up card - Stolen",
  418.         '51' => "Insufficient funds",
  419.         '54' => "Expired card",
  420.         '57' => "Transaction not permitted - Card",
  421.         '61' => "Amount exceeds withdrawal limit",
  422.         '62' => "Invalid service code, restricted",
  423.         '65' => "Activity limit exceeded",
  424.         '76' => "Unable to locate, no match",
  425.         '77' => "Inconsistent data, rev. or repeat",
  426.         '78' => "No account",
  427.         '80' => "Invalid date",
  428.         '85' => "Card OK",
  429.         '91' => "Issuer or switch is unavailable",
  430.         '93' => "Violation, cannot complete",
  431.         '96' => "System malfunction",
  432.         '98' => "No matching transaction to void",
  433.         '99' => "System timeout",
  434.         'L0' => "General System Error - Contact Transfirst Account Exec.",
  435.         'L1' => "Invalid or missing account number",
  436.         'L2' => "Invalid or missing password",
  437.         'L3' => "Expiration Date is not formatted correctly",
  438.         'L4' => "Reference number not found",
  439.         'L6' => "Order number is required but missing",
  440.         'L7' => "Wrong transaction code",
  441.         'L8' => "Network timeout",
  442.         'L14' => "Invalid card number",
  443.         'S5' => "Already settled",
  444.         'S6' => "Not authorized",
  445.         'S7' => "Declined",
  446.         'V6' => "Invalid transaction type",
  447.         'V7' => "Declined",
  448.         'V8' => "Already voided",
  449.         'V9' => "Already posted"
  450.     );
  451.  
  452.     var $_avsCodeMap = array(
  453.         'A' => "Address match",
  454.         'E' => "Ineligible",
  455.         'N' => "No match",
  456.         'R' => "Retry",
  457.         'S' => "Service unavailable",
  458.         'U' => "Address information unavailable",
  459.         'W' => "9-digit zip match",
  460.         'X' => "Address and 9-digit zip match",
  461.         'Y' => "Address and 5-digit zip match",
  462.         'Z' => "5-digit zip match"
  463.     );
  464.  
  465.     /**
  466.      * Status code map
  467.      *
  468.      * This contains a map from the Processor-specific result codes to the generic
  469.      * P_P codes. Anything not defined here is treated as a DECLINED result by
  470.      * validate()
  471.      *
  472.      * @type array
  473.      * @access private
  474.      */
  475.     var $_statusCodeMap = array(
  476.         '00' => PAYMENT_PROCESS_RESULT_APPROVED,
  477.         '05' => PAYMENT_PROCESS_RESULT_DECLINED,
  478.         'V7' => PAYMENT_PROCESS_RESULT_DECLINED
  479.     );
  480.  
  481.     var $_aciCodes = array(
  482.         'A' => "CPS Qualified",
  483.         'E' => "CPS Qualified  -  Card Acceptor Data was submitted in the authorization  request.",
  484.         'M' => "Reserved - The card was not present and no AVS request for International transactions",
  485.         'N' => "Not CPS Qualified",
  486.         'V' => "CPS Qualified ? Included an address verification request in the authorization request."
  487.     );
  488.  
  489.     var $_authSourceCodes = array(
  490.         ' ' => "Terminal doesn't support",
  491.         '0' => "Exception File",
  492.         '1' => "Stand in Processing, time-out response",
  493.         '2' => "Loss Control System (LCS) response provided",
  494.         '3' => "STIP, response provided, issuer suppress inquiry mode",
  495.         '4' => "STIP, response provided, issuer is down",
  496.         '5' => "Response provided by issuer",
  497.         '9' => "Automated referral service (ARS) stand-in"
  498.     );
  499.  
  500.     var $_fieldMap = array(
  501.         0  => '_null',                    // TF Internal Message Format
  502.         1  => '_acctNo',                  // TF Account number
  503.         2  => '_transactionCode',         // The transaction code from the request message passed by the original request.
  504.         3  => 'transactionId',            // Assigned by TF used to uniquely identify transaction.
  505.         4  => '_mailOrder',               // Mail Order Identifier
  506.         5  => '_ccAcctNo',                // The credit card account number passed by the original request.
  507.         6  => '_ccExpDate',               // The Expiration Date passed by the original request. The field is formatted YYMM (Year, Month)
  508.         7  => '_authAmount',              // An eight-digit value, which denotes the dollar amount passed to TF, without a decimal. ( DDDDDDCC )
  509.         8  => '_authDate',                // A six-digit value, which denotes the date the authorization, was attempted.  The field is formatted YYMMDD. (Year, Month, Date)
  510.         9  => '_authTime',                // A six-digit value, which denotes the time the authorization, was attempted.  The field is formatted HHMMSS.  (Hour, Minute, Second)
  511.         10 => 'messageCode',              // A two-digit value, which indicates the result of the authorization request.  Used to determine if the card was authorized, declined or timed out.
  512.         11 => 'customerId',               // The Customer Number passed by the original request
  513.         12 => 'invoiceNumber',            // The Order Number passed by the original request.
  514.         13 => '_urn',                     // A number that uniquely identifies an individual transaction.  Assigned by TF and can be used when referencing a specific transaction.
  515.         14 => '_authResponse',            // A number provided by the issuing bank indicating the authorization is valid and funds have been reserved for transfer to the merchants account at a later time.
  516.         15 => '_authSource',              // A code that defines the source where an authorization was captured.
  517.         16 => '_authCharacteristic',      // A code that defines the qualification level for the authorized transaction.
  518.         17 => 'approvalCode',             // Assigned by Visa or MasterCard, used to uniquely identify and link together all related information and used to authorize and clear a transaction.
  519.         18 => '_validationCode',          // Assigned by V.I.P. System that is used to determine the accuracy of the authorization data.
  520.         19 => '_sicCatCode',              // A merchants industry classification.  Example - Mail Order/Phone Order Merchants (Direct Market) = 5969.
  521.         20 => '_currencyCode',            // 840 indicate US Currency to date this is the only valid value.
  522.         21 => 'avsCode',                  // A value that indicates the level of Address Verification that was validated.
  523.         22 => '_merchantStoreNo',         // Identifies the specific terminal used at a location  1-4 Merchant store #, 5-8 specific terminal at store.
  524.         23 => 'cvvCode'                   // A two-digit value, indicating the result of the card verification based on the CVV2 code provided by the cardholder.
  525.     );
  526.  
  527.     /**
  528.      * Constructor.
  529.      *
  530.      * @param  string  $rawResponse  The raw response from the gateway
  531.      * @return mixed boolean true on success, PEAR_Error on failure
  532.      */
  533.     function Payment_Process_Result_Transfirst($rawResponse)
  534.     {
  535.         $res $this->_validateResponse($rawResponse);
  536.         if (!$res || PEAR::isError($res)) {
  537.             if (!$res{
  538.                 $res = PEAR::raiseError("Unable to validate response body");
  539.             }
  540.             return $res;
  541.         }
  542.  
  543.         $this->_rawResponse = $rawResponse;
  544.         $res $this->_parseResponse();
  545.     }
  546.  
  547.     function getAuthSource()
  548.     {
  549.         return @$this->_authSourceCodes[$this->_authSource];
  550.     }
  551.  
  552.     function getAuthCharacteristic()
  553.     {
  554.         return @$this->_aciCodes[$this->_authChar];
  555.     }
  556.  
  557.     function getCode()
  558.     {
  559.         return $this->_statusCodeMap[$this->messageCode];
  560.     }
  561.  
  562.     /**
  563.      * Parse Transfirst (DPILink) R1 response string.
  564.      *
  565.      * This function parses the response the gateway sends back, which is in
  566.      * pipe-delimited format.
  567.      *
  568.      * @return void 
  569.      */
  570.     function _parseResponse()
  571.     {
  572.         $this->_mapFields(explode('|'$this->_rawResponse));
  573.     }
  574.  
  575.     /**
  576.      * Validate a R1 response.
  577.      *
  578.      * @return boolean 
  579.      */
  580.     function _validateResponse($resp)
  581.     {
  582.         if (strlen($resp> 160)
  583.             return false;
  584.  
  585.         // FIXME - add more tests
  586.  
  587.         return true;
  588.     }
  589. }
  590.  
  591. ?>

Documentation generated on Mon, 11 Mar 2019 14:16:04 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.