You are here

protected function AuthorizeNet::_uc_authorizenet_charge in Ubercart 8.4

Handles authorizations and captures through AIM at Authorize.Net.

File

payment/uc_authorizenet/src/Plugin/Ubercart/PaymentMethod/AuthorizeNet.php, line 272

Class

AuthorizeNet
Defines the Authorize.net payment method.

Namespace

Drupal\uc_authorizenet\Plugin\Ubercart\PaymentMethod

Code

protected function _uc_authorizenet_charge(OrderInterface $order, $amount, $txn_type, $reference) {
  global $user;

  // Build a description of the order for logging in Auth.Net.
  $description = [];
  foreach ((array) $order->products as $product) {
    $description[] = $product->qty . 'x ' . $product->model;
  }
  $billing_address = $order
    ->getAddress('billing');
  $billing_street = $billing_address
    ->getStreet1();
  if ($billing_address
    ->getStreet2()) {
    $billing_street .= ', ' . $billing_address
      ->getStreet2();
  }
  $delivery_address = $order
    ->getAddress('delivery');
  $delivery_street = $delivery_address
    ->getStreet1();
  if ($delivery_address
    ->getStreet2()) {
    $delivery_street .= ', ' . $delivery_address
      ->getStreet2();
  }

  // Build the POST data for the transaction.
  $submit_data = [
    // Merchant information.
    'x_login' => $this->configuration['login_id'],
    'x_tran_key' => $this->configuration['transaction_key'],
    // Transaction information.
    'x_version' => '3.1',
    'x_type' => $this
      ->transactionTypeMap($txn_type),
    // 'x_method' => $order->getPaymentMethodId() == 'credit' ? 'CC' : 'ECHECK',
    'x_method' => 'CC',
    // 'x_recurring_billing' => 'FALSE',
    'x_amount' => uc_currency_format($amount, FALSE, FALSE, '.'),
    'x_card_num' => $order->payment_details['cc_number'],
    'x_exp_date' => $order->payment_details['cc_exp_month'] . '/' . $order->payment_details['cc_exp_year'],
    'x_card_code' => $order->payment_details['cc_cvv'],
    // 'x_trans_id' => '',
    // 'x_auth_code' => '',
    'x_test_request' => $this->configuration['aim']['txn_mode'] == 'live_test' ? 'TRUE' : 'FALSE',
    'x_duplicate_window' => $this->configuration['duplicate_window'],
    // Order information.
    'x_invoice_num' => $order
      ->id(),
    'x_description' => substr(implode(', ', $description), 0, 255),
    // Customer information.
    'x_first_name' => substr($billing_address
      ->getFirstName(), 0, 50),
    'x_last_name' => substr($billing_address
      ->getLastName(), 0, 50),
    'x_company' => substr($billing_address
      ->getCompany(), 0, 50),
    'x_address' => substr($billing_street, 0, 60),
    'x_city' => substr($billing_address
      ->getCity(), 0, 40),
    'x_state' => substr($billing_address
      ->getZone(), 0, 40),
    'x_zip' => substr($billing_address
      ->getPostalCode(), 0, 20),
    'x_country' => $billing_address
      ->getCountry(),
    'x_phone' => substr($billing_address
      ->getPhone(), 0, 25),
    // 'x_fax' => substr('', 0, 25),
    'x_email' => substr($order
      ->getEmail(), 0, 255),
    'x_cust_id' => $order
      ->getOwnerId(),
    'x_customer_ip' => substr(Drupal::request()
      ->getClientIp(), 0, 15),
    // Shipping information.
    'x_ship_to_first_name' => substr($delivery_address
      ->getFirstName(), 0, 50),
    'x_ship_to_last_name' => substr($delivery_address
      ->getLastName(), 0, 50),
    'x_ship_to_company' => substr($delivery_address
      ->getCompany(), 0, 50),
    'x_ship_to_address' => substr($delivery_street, 0, 60),
    'x_ship_to_city' => substr($delivery_address
      ->getCity(), 0, 40),
    'x_ship_to_state' => substr($delivery_address
      ->getZone(), 0, 40),
    'x_ship_to_zip' => substr($delivery_address
      ->getPostalCode(), 0, 20),
    'x_ship_to_country' => $delivery_address
      ->getCountry(),
    // Extra information.
    'x_delim_data' => 'TRUE',
    'x_delim_char' => '|',
    'x_encap_char' => '"',
    'x_relay_response' => 'FALSE',
    'x_email_customer' => $this->configuration['aim']['email_customer'] ? 'TRUE' : 'FALSE',
  ];
  if ($txn_type == UC_CREDIT_PRIOR_AUTH_CAPTURE) {
    $submit_data['x_trans_id'] = $data['auth_id'];
  }

  // Allow other modules to alter the transaction.
  \Drupal::moduleHandler()
    ->alter('uc_authorizenet_transaction', $submit_data);

  // Determine the correct URL based on the transaction mode.
  if ($this->configuration['aim']['txn_mode'] == 'developer_test') {
    $post_url = $this->configuration['test_gateway_url'];
  }
  else {
    $post_url = $this->configuration['live_gateway_url'];
  }
  $result = \Drupal::httpClient()
    ->setSslVerification(TRUE, TRUE, 2)
    ->setConfig([
    'curl.options' => [
      CURLOPT_FOLLOWLOCATION => FALSE,
    ],
  ])
    ->post($post_url, NULL, $submit_data)
    ->send();

  // Log any errors to the watchdog.
  if ($result
    ->isError()) {
    \Drupal::logger('uc_authorizenet')
      ->error('@error', [
      '@error' => $result
        ->getReasonPhrase(),
    ]);
    return [
      'success' => FALSE,
    ];
  }
  $response = explode('|', $result
    ->getBody(TRUE));
  if ($this->configuration['aim']['response_debug']) {
    \Drupal::logger('uc_authorizenet')
      ->notice('Debug response: @data', [
      '@data' => '<pre>' . print_r($response, TRUE) . '</pre>',
    ]);
  }

  // Trim off the encapsulating character from the results.
  for ($i = 0; $i < count($response); $i++) {
    $response[$i] = substr($response[$i], 1, strlen($response[$i]) - 2);
  }

  /*
   * Response key index:
   * 0 = Response Code
   * 2 = Response Reason Code
   * 3 = Response Reason Text
   * 4 = Authorization Code
   * 5 = Address Verification Service (AVS) Response
   * 6 = Transaction ID; needed for CREDIT, PRIOR_AUTH_CAPTURE, and VOID transactions.
   * 9 = Amount
   * 11 = Transaction Type
   * 32 = Tax Amount Charged
   * 37 = Transaction Response MD5 Hash
   * 38 = Card Code (CVV) Response
   */

  // If we didn't get an approval response code...
  if ($response[0] != '1') {

    // Fail the charge with the reason text in the decline message.
    $result = [
      'success' => FALSE,
      'message' => $this
        ->t('Credit card payment declined: @message', [
        '@message' => $response[3],
      ]),
      'uid' => $user
        ->id(),
    ];
  }
  else {

    // Build a message for display and comments in the payments table.
    $message = $this
      ->t('Type: @type<br />ID: @id', [
      '@type' => $this
        ->transactionType($response[11]),
      '@id' => $response[6],
    ]);
    $result = [
      'success' => TRUE,
      'comment' => $message,
      'message' => $message,
      'data' => [
        'module' => 'uc_authorizenet',
        'txn_type' => $response[11],
        'txn_id' => $response[6],
        'txn_authcode' => $response[4],
      ],
      'uid' => $user
        ->id(),
    ];

    // If this was an authorization only transaction...
    if ($txn_type == UC_CREDIT_AUTH_ONLY) {

      // Log the authorization to the order.
      uc_credit_log_authorization($order
        ->id(), $response[6], $amount);
    }
    elseif ($txn_type == UC_CREDIT_PRIOR_AUTH_CAPTURE) {
      uc_credit_log_prior_auth_capture($order
        ->id(), $data['auth_id']);
    }

    // Create a transaction reference if specified in the payment gateway
    // settings and this is an appropriate transaction type.
    if ($this->configuration['cim']['cim_profile'] && in_array($txn_type, [
      UC_CREDIT_AUTH_ONLY,
      UC_CREDIT_AUTH_CAPTURE,
    ])) {

      // Ignore returned message for now; it will appear in the comments.
      _uc_authorizenet_cim_profile_create($order);
    }
  }

  // Don't log this as a payment money wasn't actually captured.
  if (in_array($txn_type, [
    UC_CREDIT_AUTH_ONLY,
  ])) {
    $result['log_payment'] = FALSE;
  }

  // Build an admin order comment.
  $comment = $this
    ->t('<b>@type</b><br /><b>@status:</b> @message<br />Amount: @amount<br />AVS response: @avs', [
    '@type' => $this
      ->transactionType($response[11]),
    '@status' => $result['success'] ? $this
      ->t('ACCEPTED') : $this
      ->t('REJECTED'),
    '@message' => $response[3],
    '@amount' => uc_currency_format($response[9]),
    '@avs' => $this
      ->avsCodeMessage($response[5]),
  ]);

  // Add the CVV response if enabled.
  if ($this->configuration['uc_credit_cvv_enabled']) {
    $comment .= '<br />' . $this
      ->t('CVV match: @cvv', [
      '@cvv' => $this
        ->cvvmatchMessage($response[38]),
    ]);
  }

  // Save the comment to the order.
  uc_order_comment_save($order
    ->id(), $user
    ->id(), $comment, 'admin');
  return $result;
}