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

Source for file AuthorizeNet.php

Documentation is available at AuthorizeNet.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: Joe Stump <joe@joestump.net>                                |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: AuthorizeNet.php,v 1.19 2004/11/15 15:35:07 jstump Exp $
  20.  
  21. require_once 'Payment/Process.php';
  22. require_once 'Payment/Process/Common.php';
  23. require_once 'Net/Curl.php';
  24.  
  25. $GLOBALS['_Payment_Process_AuthorizeNet'= array(
  26.     PAYMENT_PROCESS_ACTION_NORMAL   => 'AUTH_CAPTURE',
  27.     PAYMENT_PROCESS_ACTION_AUTHONLY => 'AUTH_ONLY',
  28.     PAYMENT_PROCESS_ACTION_POSTAUTH => 'PRIOR_AUTH_CAPTURE'
  29. );
  30.  
  31. /**
  32.  * Payment_Process_AuthorizeNet
  33.  *
  34.  * This is a processor for Authorize.net's merchant payment gateway.
  35.  * (http://www.authorize.net/)
  36.  *
  37.  * *** WARNING ***
  38.  * This is BETA code, and has not been fully tested. It is not recommended
  39.  * that you use it in a production envorinment without further testing.
  40.  *
  41.  * @package Payment_Process
  42.  * @author Joe Stump <joe@joestump.net>
  43.  * @version @version@
  44.  */
  45.     /**
  46.      * Front-end -> back-end field map.
  47.      *
  48.      * This array contains the mapping from front-end fields (defined in
  49.      * the Payment_Process class) to the field names DPILink requires.
  50.      *
  51.      * @see _prepare()
  52.      * @access private
  53.      */
  54.     var $_fieldMap = array(
  55.         // Required
  56.         'login' => 'x_login',
  57.         'password' => 'x_password',
  58.         'action' => 'x_type',
  59.         'invoiceNumber' => 'x_invoice_num',
  60.         'customerId' => 'x_cust_id',
  61.         'amount' => 'x_amount',
  62.         'description' => 'x_description',
  63.         'name' => '',
  64.         'zip' => 'x_zip',
  65.         // Optional
  66.         'company' => 'x_company',
  67.         'address' => 'x_address',
  68.         'city' => 'x_city',
  69.         'state' => 'x_state',
  70.         'country' => 'x_country',
  71.         'phone' => 'x_phone',
  72.         'email' => 'x_email',
  73.         'ip' => 'x_customer_ip',
  74.     );
  75.  
  76.     /**
  77.     * $_typeFieldMap
  78.     *
  79.     * @author Joe Stump <joe@joestump.net>
  80.     * @access protected
  81.     */
  82.     var $_typeFieldMap = array(
  83.  
  84.            'CreditCard' => array(
  85.  
  86.                     'cardNumber' => 'x_card_num',
  87.                     'cvv' => 'x_card_code',
  88.                     'expDate' => 'x_exp_date'
  89.  
  90.            ),
  91.  
  92.            'eCheck' => array(
  93.  
  94.                     'routingCode' => 'x_bank_aba_code',
  95.                     'accountNumber' => 'x_bank_acct_num',
  96.                     'type' => 'x_bank_acct_type',
  97.                     'bankName' => 'x_bank_name',
  98.                     'name' => 'x_bank_acct_name'
  99.  
  100.            )
  101.     );
  102.  
  103.     /**
  104.      * Default options for this processor.
  105.      *
  106.      * @see Payment_Process::setOptions()
  107.      * @access private
  108.      */
  109.     var $_defaultOptions = array(
  110.          'authorizeUri' => 'https://secure.authorize.net/gateway/transact.dll',
  111.          'x_delim_data' => 'TRUE',
  112.          'x_relay' => 'FALSE',
  113.          'x_email_customer' => 'FALSE',
  114.          'x_test_request' => 'FALSE',
  115.          'x_currency_code' => 'USD',
  116.          'x_version' => '3.1'
  117.     );
  118.  
  119.     /**
  120.      * Has the transaction been processed?
  121.      *
  122.      * @type boolean
  123.      * @access private
  124.      */
  125.     var $_processed = false;
  126.  
  127.     /**
  128.      * The response body sent back from the gateway.
  129.      *
  130.      * @access private
  131.      */
  132.     var $_responseBody '';
  133.  
  134.     /**
  135.      * Constructor.
  136.      *
  137.      * @param  array  $options  Class options to set.
  138.      * @see Payment_Process::setOptions()
  139.      * @return void 
  140.      */
  141.     function Payment_Process_AuthorizeNet($options = false)
  142.     {
  143.         $this->setOptions($options);
  144.     }
  145.  
  146.     /**
  147.      * Process the transaction.
  148.      *
  149.      * @return mixed Payment_Process_Result on success, PEAR_Error on failure
  150.      */
  151.     function &process()
  152.     {
  153.         if($this->_options['debug'=== true{
  154.             echo "----------- DATA -----------\n";
  155.             print_r($this->_data);
  156.             echo "----------- DATA -----------\n";
  157.         }
  158.  
  159.         // Sanity check
  160.         $result $this->validate();
  161.         if(PEAR::isError($result)) {
  162.             return $result;
  163.         }
  164.  
  165.         // Prepare the data
  166.         $result $this->_prepare();
  167.         if (PEAR::isError($result)) {
  168.             return $result
  169.         }
  170.  
  171.         // Don't die partway through
  172.         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  173.  
  174.         if($this->_options['debug'=== true{
  175.             print_r($this->_options);
  176.         }
  177.  
  178.         $fields $this->_prepareQueryString();
  179.         $curl new Net_Curl($this->_options['authorizeUri']);
  180.         if (PEAR::isError($curl)) {
  181.             PEAR::popErrorHandling();
  182.             return $curl;
  183.         }
  184.  
  185.         $curl->type = 'PUT';
  186.         $curl->fields = $fields;
  187.         if($this->_options['debug'=== true{
  188.             echo "------------ CURL FIELDS -------------\n";
  189.             print_r($curl->fields)
  190.             echo "------------ CURL FIELDS -------------\n";
  191.         }
  192.  
  193.         $curl->userAgent = 'PEAR Payment_Process_AuthorizeNet 0.1';
  194.  
  195.         $result &$curl->execute();
  196.         if (PEAR::isError($result)) {
  197.             PEAR::popErrorHandling();
  198.             return $result;
  199.         else {
  200.             $curl->close();
  201.         }
  202.  
  203.  
  204.         $this->_responseBody trim($result);
  205.         $this->_processed = true;
  206.  
  207.         // Restore error handling
  208.         PEAR::popErrorHandling();
  209.  
  210.         $response &Payment_Process_Result::factory($this->_driver,$this->_responseBody);
  211.         if(!PEAR::isError($response))
  212.         {
  213.           $response->_request = $this;
  214.           $response->parse();
  215.         }
  216.  
  217.         return $response;
  218.  
  219.     }
  220.  
  221.     /**
  222.      * Get (completed) transaction status.
  223.      *
  224.      * @return string Two-digit status returned from gateway.
  225.      */
  226.     function getStatus()
  227.     {
  228.         return false;
  229.     }
  230.  
  231.     /**
  232.      * Prepare the POST query string.
  233.      *
  234.      * @access private
  235.      * @return string The query string
  236.      */
  237.     function _prepareQueryString()
  238.     {
  239.  
  240.         $data array_merge($this->_options,$this->_data);
  241.  
  242.         // Set payment method to eCheck if our payment type is eCheck.
  243.         // Default is Credit Card.
  244.         $data['x_method''CC';
  245.         if($this->_payment->getType(== 'eCheck')
  246.         {
  247.           $data['x_method''ECHECK';
  248.           switch($this->_payment->type)
  249.           {
  250.             case PAYMENT_PROCESS_CK_CHECKING:
  251.               $data['x_bank_acct_type''CHECKING';
  252.               break;
  253.             case PAYMENT_PROCESS_CK_SAVINGS:
  254.               $data['x_bank_acct_type''SAVINGS';
  255.               break;
  256.           }
  257.         }
  258.  
  259.         if($this->_options['debug'=== true{
  260.             echo "--------- PREPARE QS DATA -----------\n";
  261.             print_r($this->_data);
  262.             print_r($data);
  263.             echo "--------- PREPARE QS DATA -----------\n";
  264.         }
  265.         $return = array();
  266.         $sets = array();
  267.         foreach ($data as $key => $val{
  268.             if (eregi('^x_',$key&& strlen($val)) {
  269.                 $return[$key$val;
  270.                 $sets[$key.'='.urlencode($val);
  271.             }
  272.         }
  273.  
  274.         $this->_options['authorizeUri'.= '?'.implode('&',$sets);
  275.  
  276.         return $return;
  277.     }
  278.  
  279.     /**
  280.     * _handleName
  281.     *
  282.     * @author Joe Stump <joe@joestump.net>
  283.     * @access private
  284.     */
  285.     function _handleName()
  286.     {
  287.       $parts explode(' ',$this->_payment->name);
  288.       $this->_data['x_first_name'array_shift($parts);
  289.       $this->_data['x_last_name'implode(' ',$parts)
  290.     }
  291. }
  292.  
  293.  
  294.     var $_statusCodeMap = array('1' => PAYMENT_PROCESS_RESULT_APPROVED,
  295.                                 '2' => PAYMENT_PROCESS_RESULT_DECLINED,
  296.                                 '3' => PAYMENT_PROCESS_RESULT_OTHER);
  297.  
  298.     /**
  299.      * AuthorizeNet status codes
  300.      *
  301.      * This array holds many of the common response codes. There are over 200
  302.      * response codes - so check the AuthorizeNet manual if you get a status
  303.      * code that does not match (see "Response Reason Codes & Response
  304.      * Reason Text" in the AIM manual).
  305.      *
  306.      * @see getStatusText()
  307.      * @access private
  308.      */
  309.     var $_statusCodeMessages = array(
  310.           '1' => 'This transaction has been approved.',
  311.           '2' => 'This transaction has been declined.',
  312.           '3' => 'This transaction has been declined.',
  313.           '4' => 'This transaction has been declined.',
  314.           '5' => 'A valid amount is required.',
  315.           '6' => 'The credit card number is invalid.',
  316.           '7' => 'The credit card expiration date is invalid.',
  317.           '8' => 'The credit card has expired.',
  318.           '9' => 'The ABA code is invalid.',
  319.           '10' => 'The account number is invalid.',
  320.           '11' => 'A duplicate transaction has been submitted.',
  321.           '12' => 'An authorization code is required but not present.',
  322.           '13' => 'The merchant Login ID is invalid or the account is inactive.',
  323.           '14' => 'The Referrer or Relay Response URL is invalid.',
  324.           '15' => 'The transaction ID is invalid.',
  325.           '16' => 'The transaction was not found.',
  326.           '17' => 'The merchant does not accept this type of credit card.',
  327.           '18' => 'ACH transactions are not accepted by this merchant.',
  328.           '19' => 'An error occurred during processing. Please try again in 5 minutes.',
  329.           '20' => 'An error occurred during processing. Please try again in 5 minutes.',
  330.           '21' => 'An error occurred during processing. Please try again in 5 minutes.',
  331.           '22' => 'An error occurred during processing. Please try again in 5 minutes.',
  332.           '23' => 'An error occurred during processing. Please try again in 5 minutes.',
  333.           '24' => 'The Nova Bank Number or Terminal ID is incorrect. Call Merchant Service Provider.',
  334.           '25' => 'An error occurred during processing. Please try again in 5 minutes.',
  335.           '26' => 'An error occurred during processing. Please try again in 5 minutes.',
  336.           '27' => 'The transaction resulted in an AVS mismatch. The address provided does not match billing address of cardholder.',
  337.           '28' => 'The merchant does not accept this type of credit card.',
  338.           '29' => 'The PaymentTech identification numbers are incorrect. Call Merchant Service Provider.',
  339.           '30' => 'The configuration with the processor is invalid. Call Merchant Service Provider.',
  340.           '31' => 'The FDC Merchant ID or Terminal ID is incorrect. Call Merchant Service Provider.',
  341.           '32' => 'The merchant password is invalid or not present.',
  342.           '33' => 'Missing required field',
  343.           '34' => 'The VITAL identification numbers are incorrect. Call Merchant Service Provider.',
  344.           '35' => 'An error occurred during processing. Call Merchant Service Provider.',
  345.           '36' => 'The authorization was approved, but settlement failed.',
  346.           '37' => 'The credit card number is invalid.',
  347.           '38' => 'The Global Payment System identification numbers are incorrect. Call Merchant Service Provider.',
  348.           '39' => 'The supplied currency code is either invalid, not supported, not allowed for this merchant or doesn\'t have an exchange rate.',
  349.           '40' => 'This transaction must be encrypted.',
  350.           '41' => 'FraudScreen.net fraud score is higher than threshold set by merchant',
  351.           '42' => 'There is missing or invalid information in a required field.',
  352.           '43' => 'The merchant was incorrectly set up at the processor. Call your Merchant Service Provider.',
  353.           '44' => 'This transaction has been declined. Card Code filter error!',
  354.           '45' => 'This transaction has been declined. Card Code / AVS filter error!',
  355.           '46' => 'Your session has expired or does not exist. You must log in to continue working.',
  356.           '47' => 'The amount requested for settlement may not be greater than the original amount authorized.',
  357.           '48' => 'This processor does not accept partial reversals.',
  358.           '49' => 'A transaction amount greater than $99,999 will not be accepted.',
  359.           '50' => 'This transaction is awaiting settlement and cannot be refunded.',
  360.           '51' => 'The sum of all credits against this transaction is greater than the original transaction amount.',
  361.           '52' => 'The transaction was authorized, but the client could not be notified; the transaction will not be settled.',
  362.           '53' => 'The transaction type was invalid for ACH transactions.',
  363.           '54' => 'The referenced transaction does not meet the criteria for issuing a credit.',
  364.           '55' => 'The sum of credits against the referenced transaction would exceed the original debit amount.',
  365.           '56' => 'This merchant accepts ACH transactions only; no credit card transactions are accepted.',
  366.           '57' => 'An error occurred in processing. Please try again in 5 minutes.',
  367.           '58' => 'An error occurred in processing. Please try again in 5 minutes.',
  368.           '59' => 'An error occurred in processing. Please try again in 5 minutes.',
  369.           '60' => 'An error occurred in processing. Please try again in 5 minutes.',
  370.           '61' => 'An error occurred in processing. Please try again in 5 minutes.',
  371.           '62' => 'An error occurred in processing. Please try again in 5 minutes.',
  372.           '63' => 'An error occurred in processing. Please try again in 5 minutes.',
  373.           '64' => 'The referenced transaction was not approved.',
  374.           '65' => 'This transaction has been declined.',
  375.           '66' => 'The transaction did not meet gateway security guidelines.',
  376.           '67' => 'The given transaction type is not supported for this merchant.',
  377.           '68' => 'The version parameter is invalid.',
  378.           '69' => 'The transaction type is invalid. The value submitted in x_type was invalid.',
  379.           '70' => 'The transaction method is invalid.',
  380.           '71' => 'The bank account type is invalid.',
  381.           '72' => 'The authorization code is invalid.',
  382.           '73' => 'The driver\'s license date of birth is invalid.',
  383.           '74' => 'The duty amount is invalid.',
  384.           '75' => 'The freight amount is invalid.',
  385.           '76' => 'The tax amount is invalid.',
  386.           '77' => 'The SSN or tax ID is invalid.',
  387.           '78' => 'The Card Code (CVV2/CVC2/CID) is invalid.',
  388.           '79' => 'The driver\'s license number is invalid.',
  389.           '80' => 'The driver\'s license state is invalid.',
  390.           '81' => 'The merchant requested an integration method not compatible with the AIM API.',
  391.           '82' => 'The system no longer supports version 2.5; requests cannot be posted to scripts.',
  392.           '83' => 'The requested script is either invalid or no longer supported.',
  393.           '84' => 'This reason code is reserved or not applicable to this API.',
  394.           '85' => 'This reason code is reserved or not applicable to this API.',
  395.           '86' => 'This reason code is reserved or not applicable to this API.',
  396.           '87' => 'This reason code is reserved or not applicable to this API.',
  397.           '88' => 'This reason code is reserved or not applicable to this API.',
  398.           '89' => 'This reason code is reserved or not applicable to this API.',
  399.           '90' => 'This reason code is reserved or not applicable to this API.',
  400.           '91' => 'Version 2.5 is no longer supported.',
  401.           '92' => 'The gateway no longer supports the requested method of integration.',
  402.           '93' => 'A valid country is required.',
  403.           '94' => 'The shipping state or country is invalid.',
  404.           '95' => 'A valid state is required.',
  405.           '96' => 'This country is not authorized for buyers.',
  406.           '97' => 'This transaction cannot be accepted.',
  407.           '98' => 'This transaction cannot be accepted.',
  408.           '99' => 'This transaction cannot be accepted.',
  409.           '100' => 'The eCheck type is invalid.',
  410.           '101' => 'The given name on the account and/or the account type does not match the actual account.',
  411.           '102' => 'This request cannot be accepted.',
  412.           '103' => 'This transaction cannot be accepted.',
  413.           '104' => 'This transaction is currently under review.',
  414.           '105' => 'This transaction is currently under review.',
  415.           '106' => 'This transaction is currently under review.',
  416.           '107' => 'This transaction is currently under review.',
  417.           '108' => 'This transaction is currently under review.',
  418.           '109' => 'This transaction is currently under review.',
  419.           '110' => 'This transaction is currently under review.',
  420.           '111' => 'A valid billing country is required.',
  421.           '112' => 'A valid billing state/provice is required.',
  422.           '116' => 'The authentication indicator is invalid.',
  423.           '117' => 'The cardholder authentication value is invalid.',
  424.           '118' => 'The combination of authentication indicator and cardholder authentication value is invalid.',
  425.           '119' => 'Transactions having cardholder authentication values cannot be marked as recurring.',
  426.           '120' => 'An error occurred during processing. Please try again.',
  427.           '121' => 'An error occurred during processing. Please try again.',
  428.           '122' => 'An error occurred during processing. Please try again.',
  429.           '127' => 'The transaction resulted in an AVS mismatch. The address provided does not match billing address of cardholder.',
  430.           '141' => 'This transaction has been declined.',
  431.           '145' => 'This transaction has been declined.',
  432.           '152' => 'The transaction was authorized, but the client could not be notified; the transaction will not be settled.',
  433.           '165' => 'This transaction has been declined.',
  434.           '170' => 'An error occurred during processing. Please contact the merchant.',
  435.           '171' => 'An error occurred during processing. Please contact the merchant.',
  436.           '172' => 'An error occurred during processing. Please contact the merchant.',
  437.           '173' => 'An error occurred during processing. Please contact the merchant.',
  438.           '174' => 'The transaction type is invalid. Please contact the merchant.',
  439.           '175' => 'The processor does not allow voiding of credits.',
  440.           '180' => 'An error occurred during processing. Please try again.',
  441.           '181' => 'An error occurred during processing. Please try again.',
  442.           '200' => 'This transaction has been declined.',
  443.           '201' => 'This transaction has been declined.',
  444.           '202' => 'This transaction has been declined.',
  445.           '203' => 'This transaction has been declined.',
  446.           '204' => 'This transaction has been declined.',
  447.           '205' => 'This transaction has been declined.',
  448.           '206' => 'This transaction has been declined.',
  449.           '207' => 'This transaction has been declined.',
  450.           '208' => 'This transaction has been declined.',
  451.           '209' => 'This transaction has been declined.',
  452.           '210' => 'This transaction has been declined.',
  453.           '211' => 'This transaction has been declined.',
  454.           '212' => 'This transaction has been declined.',
  455.           '213' => 'This transaction has been declined.',
  456.           '214' => 'This transaction has been declined.',
  457.           '215' => 'This transaction has been declined.',
  458.           '216' => 'This transaction has been declined.',
  459.           '217' => 'This transaction has been declined.',
  460.           '218' => 'This transaction has been declined.',
  461.           '219' => 'This transaction has been declined.',
  462.           '220' => 'This transaction has been declined.',
  463.           '221' => 'This transaction has been declined.',
  464.           '222' => 'This transaction has been declined.',
  465.           '223' => 'This transaction has been declined.',
  466.           '224' => 'This transaction has been declined.'
  467.     );
  468.  
  469.     var $_avsCodeMap = array(
  470.         'A' => PAYMENT_PROCESS_AVS_MISMATCH,
  471.         'B' => PAYMENT_PROCESS_AVS_ERROR,
  472.         'E' => PAYMENT_PROCESS_AVS_ERROR,
  473.         'G' => PAYMENT_PROCESS_AVS_NOAPPLY,
  474.         'N' => PAYMENT_PROCESS_AVS_MISMATCH,
  475.         'P' => PAYMENT_PROCESS_AVS_NOAPPLY,
  476.         'R' => PAYMENT_PROCESS_AVS_ERROR,
  477.         'S' => PAYMENT_PROCESS_AVS_ERROR,
  478.         'U' => PAYMENT_PROCESS_AVS_ERROR,
  479.         'W' => PAYMENT_PROCESS_AVS_MISMATCH,
  480.         'X' => PAYMENT_PROCESS_AVS_MATCH,
  481.         'Y' => PAYMENT_PROCESS_AVS_MATCH,
  482.         'Z' => PAYMENT_PROCESS_AVS_MISMATCH
  483.     );
  484.  
  485.     var $_avsCodeMessages = array(
  486.         'A' => 'Address matches, ZIP does not',
  487.         'B' => 'Address information not provided',
  488.         'E' => 'AVS Error',
  489.         'G' => 'Non-U.S. Card Issuing Bank',
  490.         'N' => 'No match',
  491.         'P' => 'AVS not applicable',
  492.         'R' => 'Retry - System unavailable or timeout',
  493.         'S' => 'Service not supported by issuer',
  494.         'U' => 'Address information unavailable',
  495.         'W' => '9-digit zip matches, Address (street) does not',
  496.         'X' => 'Address and 9-digit zip match',
  497.         'Y' => 'Address and 5-digit zip match',
  498.         'Z' => '5-digit zip matches, Address (street) does not'
  499.     );
  500.  
  501.     var $_cvvCodeMap = array('M' => PAYMENT_PROCESS_CVV_MATCH,
  502.                              'N' => PAYMENT_PROCESS_CVV_MISMATCH,
  503.                              'P' => PAYMENT_PROCESS_CVV_ERROR,
  504.                              'S' => PAYMENT_PROCESS_CVV_ERROR,
  505.                              'U' => PAYMENT_PROCESS_CVV_ERROR
  506.     );
  507.  
  508.     var $_cvvCodeMessages = array(
  509.         'M' => 'CVV codes match',
  510.         'N' => 'CVV codes do not match',
  511.         'P' => 'CVV code was not processed',
  512.         'S' => 'CVV code should have been present',
  513.         'U' => 'Issuer unable to process request',
  514.     );
  515.  
  516.     var $_fieldMap = array('0'  => 'code',
  517.                            '2'  => 'messageCode',
  518.                            '3'  => 'message',
  519.                            '4'  => 'approvalCode',
  520.                            '5'  => 'avsCode',
  521.                            '6'  => 'transactionId',
  522.                            '7'  => 'invoiceNumber',
  523.                            '12' => 'customerId',
  524.                            '38' => 'cvvCode'
  525.     );
  526.  
  527.     function Payment_Process_Response_AuthorizeNet($rawResponse
  528.     {
  529.         $this->Payment_Process_Response($rawResponse);
  530.     }
  531.  
  532.     function parse()
  533.     {
  534.       $responseArray explode(',',$this->_rawResponse);
  535.       $this->_mapFields($responseArray);
  536.     }
  537. }
  538.  
  539. ?>

Documentation generated on Mon, 11 Mar 2019 13:58:48 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.