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

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