You are here

function _uc_cybersource_soap_charge in Ubercart 5

Same name and namespace in other branches
  1. 6.2 payment/uc_cybersource/uc_cybersource.module \_uc_cybersource_soap_charge()
  2. 7.3 payment/uc_cybersource/uc_cybersource.module \_uc_cybersource_soap_charge()
1 call to _uc_cybersource_soap_charge()
uc_cybersource_charge in payment/uc_cybersource/uc_cybersource.module

File

payment/uc_cybersource/uc_cybersource.module, line 418
A module used for CyberSource's Silent Order POST method of payment.

Code

function _uc_cybersource_soap_charge($order, $amount, $data, $cc_type, $country) {

  // Check for compatibility.
  if (!class_exists('SoapClient') || !class_exists('DOMDocument')) {
    drupal_set_message(t('CyberSource needs PHP to have the SOAP and DOM extensions enabled.  Please talk to your system administrator to get this configured.'));
    return array(
      'success' => FALSE,
    );
  }

  // Include the SOAP helper file.
  require_once drupal_get_path('module', 'uc_cybersource') . '/uc_cybersource.soap.inc';
  global $user;

  // Set the URL for the CyberSource SOAP Toolkit API WSDL.
  if (variable_get('uc_cybersource_server', 'test') == 'test') {
    $url = 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.38.wsdl';
  }
  else {
    $url = 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.38.wsdl';
  }

  // Variable currency... not used atm.
  $currency = variable_get('uc_cybersource_currency', 'usd');
  $billing_country = uc_get_country_data(array(
    'country_id' => $order->billing_country,
  ));
  $delivery_country = uc_get_country_data(array(
    'country_id' => $order->delivery_country,
  ));
  try {
    $soapClient = new CyberSourceSoapClient($url, array());

    // To see the functions and types that the SOAP extension can automatically
    // generate from the WSDL file, uncomment this section and check the logs.
    // $functions = $soapClient->__getFunctions();
    // watchdog('uc_cybersource', '<pre>'. print_r($functions, TRUE) .'</pre>');
    // $types = $soapClient->__getTypes();
    // watchdog('uc_cybersource', '<pre>'. print_r($types, TRUE) .'</pre>');
    $login = _uc_cybersource_soap_login_data();

    // Create the request with some meta data.
    $request = new stdClass();
    $request->merchantID = $login['merchant_id'];
    $request->merchantReferenceCode = $order->order_id;
    $request->clientLibrary = 'PHP';
    $request->clientLibraryVersion = phpversion();
    $request->clientEnvironment = php_uname();

    // Add the credit card authorization service.
    if (in_array($data['txn_type'], array(
      UC_CREDIT_AUTH_ONLY,
      UC_CREDIT_AUTH_CAPTURE,
      UC_CREDIT_REFERENCE_TXN,
    ))) {
      $ccAuthService = new stdClass();
      $ccAuthService->run = 'true';
      $request->ccAuthService = $ccAuthService;
    }

    // Add the credit card capture service.
    if (in_array($data['txn_type'], array(
      UC_CREDIT_PRIOR_AUTH_CAPTURE,
      UC_CREDIT_AUTH_CAPTURE,
      UC_CREDIT_REFERENCE_TXN,
    ))) {
      $ccCaptureService = new stdClass();
      $ccCaptureService->run = 'true';

      // Add the values for prior authorization capture.
      if ($data['txn_type'] == UC_CREDIT_PRIOR_AUTH_CAPTURE) {
        $ccCaptureService->authRequestID = $data['auth_id'];
        $ccCaptureService->authRequestToken = $order->data['cybersource'][$data['auth_id']];
      }
      $request->ccCaptureService = $ccCaptureService;

      // Add the subscription ID for a reference transaction.
      if ($data['txn_type'] == UC_CREDIT_REFERENCE_TXN) {
        $recurringSubscriptionInfo = new stdClass();
        $recurringSubscriptionInfo->subscriptionID = $data['ref_id'];
        $request->recurringSubscriptionInfo = $recurringSubscriptionInfo;
        $request->merchantReferenceCode .= ' (COF)';
      }
    }

    // If enabled, create a subscription profile for this transaction.
    if (variable_get('uc_cybersource_soap_create_profile', FALSE) && in_array($data['txn_type'], array(
      UC_CREDIT_AUTH_ONLY,
      UC_CREDIT_AUTH_CAPTURE,
    ))) {

      // Skip if a profile already exists for this order.
      if (!isset($order->data['uc_cybersource']['soap']['subscription_id'])) {
        $recurringSubscriptionInfo = new stdClass();
        $recurringSubscriptionInfo->amount = 0;
        $recurringSubscriptionInfo->frequency = 'on-demand';
        $request->recurringSubscriptionInfo = $recurringSubscriptionInfo;
        $paySubscriptionCreateService = new stdClass();
        $paySubscriptionCreateService->run = 'true';
        $request->paySubscriptionCreateService = $paySubscriptionCreateService;
      }
    }

    // Add the billing information.
    $billTo = new stdClass();
    $billTo->firstName = $order->billing_first_name;
    $billTo->lastName = $order->billing_last_name;
    $billTo->street1 = $order->billing_street1;
    if ($order->billing_street2) {
      $billTo->street2 = $order->billing_street2;
    }
    $billTo->city = $order->billing_city;
    $billTo->state = uc_get_zone_code($order->billing_zone);
    $billTo->postalCode = $order->billing_postal_code;
    $billTo->country = $billing_country[0]['country_iso_code_2'];
    if ($order->billing_phone) {
      $billTo->phoneNumber = $order->billing_phone;
    }
    $billTo->email = $order->primary_email;
    $billTo->customerID = $order->uid;
    $request->billTo = $billTo;

    // Add the credit card details if needed
    if (in_array($data['txn_type'], array(
      UC_CREDIT_AUTH_ONLY,
      UC_CREDIT_AUTH_CAPTURE,
    ))) {
      $card = new stdClass();
      $card->accountNumber = $order->payment_details['cc_number'];
      $card->expirationMonth = $order->payment_details['cc_exp_month'];
      $card->expirationYear = $order->payment_details['cc_exp_year'];
      $card->cardType = $cc_type;
      if (variable_get('uc_credit_cvv_enabled', TRUE)) {
        $card->cvNumber = $order->payment_details['cc_cvv'];
      }
      $request->card = $card;
    }

    // Add the order total information.
    $purchaseTotals = new stdClass();
    $purchaseTotals->currency = $currency;

    // Specify the total to charge if it's less than the order total.
    if ($amount < $order->order_total) {
      $purchaseTotals->grandTotalAmount = $amount;
    }
    $request->purchaseTotals = $purchaseTotals;

    // Separately add products and line item into the request items object if
    // we're charging the full order total.
    if ($amount == $order->order_total) {
      $request->item = array();
      $counter = 0;

      // Add the products to the item array.
      foreach ($order->products as $product) {
        $obj = $request->item[] = new stdClass();
        $obj->productName = $product->title;
        $obj->unitPrice = $product->price;
        $obj->quantity = $product->qty;
        $obj->productSKU = $product->model;
        $obj->productCode = 'default';
        $obj->id = $counter;
        $counter++;
      }

      // Add the line items to the item array.
      foreach ((array) $order->line_items as $line_item) {

        // Skip subtotal line items.
        if (strpos($line_item['type'], 'subtotal') === FALSE) {
          $obj = $request->item[] = new stdClass();
          $obj->productName = $line_item['title'];
          $obj->unitPrice = $line_item['amount'];
          $obj->quantity = 1;
          $obj->productSKU = $line_item['type'] . '_' . $line_item['line_item_id'];
          $obj->id = $counter;
          $counter++;
        }
      }
    }

    // Add business rules.
    $business = new stdClass();
    $business->ignoreAVSResult = variable_get('uc_cybersource_avs', 'true') == 'true' ? 'false' : 'true';
    $request->businessRules = $business;

    // Send the request to CyberSource and get the reply.
    $reply = $soapClient
      ->runTransaction($request);
  } catch (SoapFault $exception) {

    // Log and display errors if Ubercart is unable to connect via SOAP.
    watchdog('uc_cybersource', t('Unable to connect to CyberSource via SOAP.'), WATCHDOG_ERROR);
    drupal_set_message(t('We apologize for the delay, but we are unable to process your credit card at this time. Please <a href="!url">contact sales</a> to complete your order.', array(
      '!url' => url('contact'),
    )), 'error');
  }

  // Process a reply from CyberSource.
  if (isset($reply)) {
    $types = uc_credit_transaction_types();

    // Create the order and payment ledger comments.
    $o_comment = t('<b>@type:</b> @amount<br /><b>Decision: @decision</b><br /><b>Reason:</b> !reason', array(
      '@type' => $types[$data['txn_type']],
      '@amount' => uc_currency_format($amount),
      '@decision' => $reply->decision,
      '!reason' => _parse_cs_reason_code($reply->reasonCode),
    ));
    $p_comment = t('<b>@type:</b><br />@id<br />@decision, Reason: !reason', array(
      '@type' => $types[$data['txn_type']],
      '@id' => $reply->requestID,
      '@decision' => $reply->decision,
      '!reason' => $reply->reasonCode,
    ));
    if (!empty($reply->ccAuthReply->avsCode)) {
      $o_comment .= '<br />' . t('<b>AVS:</b> @avs', array(
        '@avs' => _parse_cs_avs_code($reply->ccAuthReply->avsCode),
      ));
      $p_comment .= t(', AVS: @avs', array(
        '@avs' => $reply->ccAuthReply->avsCode,
      ));
    }
    if (!empty($reply->ccAuthReply->cvCode)) {
      $o_comment .= '<br />' . t('<b>CVV:</b> @cvv', array(
        '!cvv' => _parse_cs_cvv_code($reply->ccAuthReply->cvCode),
      ));
      $p_comment .= t(', CVV: @cvv', array(
        '@cvv' => $reply->ccAuthReply->cvCode,
      ));
    }
    uc_order_comment_save($order->order_id, $user->uid, $o_comment, 'admin');

    // Store the subscription ID if one was created.
    if (isset($reply->paySubscriptionCreateReply)) {

      // If the create request was successful...
      if ($reply->paySubscriptionCreateReply->reasonCode == '100') {
        $id = $reply->paySubscriptionCreateReply->subscriptionID;

        // Save the subscription ID to the order's data array.
        $order->data = uc_credit_log_reference($order->order_id, $id, $order->payment_details['cc_number']);
        uc_order_comment_save($order->order_id, 0, t('<b>CyberSource profile created.</b><br /><b>Subscription ID:</b> @id', array(
          '@id' => $id,
        )), 'admin');
      }
      else {
        uc_order_comment_save($order->order_id, 0, t('<b>Attempt to create CyberSource profile failed.</b><br /><b>Reason:</b> @code', array(
          '@code' => $reply->paySubscriptionCreateReply->reasonCode,
        )), 'admin');
      }
    }
    if ($reply->decision == 'ACCEPT') {
      $result = array(
        'success' => TRUE,
        'comment' => $p_comment,
        'message' => $o_comment,
        'uid' => $user->uid,
      );

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

        // Log the authorization to the order.
        $order->data = uc_credit_log_authorization($order->order_id, $reply->requestID, $amount);

        // Add the request token associated with the request ID.
        $order->data['cybersource'][$reply->requestID] = $reply->requestToken;

        // Save the updated data array to the database.
        db_query("UPDATE {uc_orders} SET data = '%s' WHERE order_id = %d", serialize($order->data), $order->order_id);
      }
      elseif ($data['txn_type'] == UC_CREDIT_PRIOR_AUTH_CAPTURE) {
        uc_credit_log_prior_auth_capture($order->order_id, $data['auth_id']);
      }
    }
    else {
      $result = array(
        'success' => FALSE,
        'comment' => $p_comment,
        'message' => $o_comment,
        'uid' => $user->uid,
      );
    }
  }
  else {
    $result = array(
      'success' => FALSE,
      'message' => t('No response returned from CyberSource.'),
    );
  }

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