public function generatePaymentToken($order, $payment_method)
 {
     global $user;
     $config = array();
     $shippingAddressConfig = null;
     $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
     $billing_address = $order_wrapper->commerce_customer_billing->commerce_customer_address->value();
     $order_array = $order_wrapper->commerce_order_total->value();
     $product_line_items = $order->commerce_line_items[LANGUAGE_NONE];
     if (isset($order)) {
         $orderId = $order->order_id;
         $default_currency = commerce_default_currency();
         $amountCents = number_format(commerce_currency_convert($order->commerce_order_total['und'][0]['amount'], $order_array['currency_code'], $default_currency), 0, '', '');
         $scretKey = $payment_method['settings']['private_key'];
         $mode = $payment_method['settings']['mode'];
         $timeout = $payment_method['settings']['timeout'];
         $config['authorization'] = $scretKey;
         $config['mode'] = $mode;
         $config['timeout'] = $timeout;
         if ($payment_method['settings']['payment_action'] == 'authorize') {
             $config = array_merge($config, $this->_authorizeConfig());
         } else {
             $config = array_merge($config, $this->_captureConfig($payment_method));
         }
         $products = array();
         if (!empty($product_line_items)) {
             foreach ($product_line_items as $key => $item) {
                 $line_item[$key] = commerce_line_item_load($item['line_item_id']);
                 $product_id = $line_item[$key]->commerce_product['und'][0]['product_id'];
                 $product = commerce_product_load($product_id);
                 $price = commerce_product_calculate_sell_price($product);
                 $sell_price = number_format(commerce_currency_amount_to_decimal($price['amount'], $price['currency_code']), 2, '.', '');
                 $products[$key] = array('name' => commerce_line_item_title($line_item[$key]), 'sku' => $line_item[$key]->line_item_label, 'price' => $sell_price, 'quantity' => (int) $line_item[$key]->quantity);
             }
         }
         $billingAddressConfig = array('addressLine1' => $billing_address['thoroughfare'], 'addressLine2' => $billing_address['premise'], 'postcode' => $billing_address['postal_code'], 'country' => $billing_address['country'], 'city' => $billing_address['locality']);
         if (module_exists('commerce_shipping') && !empty($order_wrapper->commerce_customer_shipping->commerce_customer_address)) {
             $shipping_address = $order_wrapper->commerce_customer_shipping->commerce_customer_address->value();
             // Add the shipping address parameters to the request.
             $shippingAddressConfig = array('addressLine1' => $shipping_address['thoroughfare'], 'addressLine2' => $shipping_address['premise'], 'postcode' => $shipping_address['postal_code'], 'country' => $shipping_address['country'], 'city' => $shipping_address['locality']);
         }
         $config['postedParam'] = array_merge($config['postedParam'], array('email' => $order->mail, 'value' => $amountCents, 'trackId' => $orderId, 'currency' => $default_currency, 'description' => 'Order number::' . $orderId, 'shippingDetails' => $shippingAddressConfig, 'products' => $products, 'card' => array('billingDetails' => $billingAddressConfig)));
         $Api = CheckoutApi_Api::getApi(array('mode' => $mode));
         $paymentTokenCharge = $Api->getPaymentToken($config);
         $paymentTokenArray = array('message' => '', 'success' => '', 'eventId' => '', 'token' => '');
         if ($paymentTokenCharge->isValid()) {
             $paymentTokenArray['token'] = $paymentTokenCharge->getId();
             $paymentTokenArray['success'] = true;
         } else {
             $paymentTokenArray['message'] = $paymentTokenCharge->getExceptionState()->getErrorMessage();
             $paymentTokenArray['success'] = false;
             $paymentTokenArray['eventId'] = $paymentTokenCharge->getEventId();
         }
     }
     return $paymentTokenArray;
 }
 protected function _placeorder($config, $charge, $order, $payment_method)
 {
     //building charge
     $respondCharge = $this->_createCharge($config);
     $transaction = commerce_payment_transaction_new('commerce_checkoutpayment', $order->order_id);
     $transaction->instance_id = $payment_method['instance_id'];
     $transaction->amount = $charge['amount'];
     $transaction->currency_code = $charge['currency_code'];
     $transaction->payload[REQUEST_TIME] = $respondCharge->getCreated();
     $default_currency = commerce_default_currency();
     $amountCents = number_format(commerce_currency_convert($charge['amount'], $charge['currency_code'], $default_currency), 0, '', '');
     $toValidate = array('currency' => $default_currency, 'value' => $amountCents, 'trackId' => $order->order_id);
     $Api = CheckoutApi_Api::getApi(array('mode' => $config['mode']));
     $validateRequest = $Api::validateRequest($toValidate, $respondCharge);
     if ($respondCharge->isValid()) {
         if (preg_match('/^1[0-9]+$/', $respondCharge->getResponseCode())) {
             if ($validateRequest['status']) {
                 $transaction->message = 'Your transaction has been successfully authorized with transaction id : ' . $respondCharge->getId();
             } else {
                 $transaction->message = '';
                 foreach ($validateRequest['message'] as $errormessage) {
                     $transaction->message .= $errormessage . '. ';
                 }
                 $transaction->message .= 'Please contact your merchant.';
             }
             $transaction->status = COMMERCE_PAYMENT_STATUS_PENDING;
             commerce_payment_transaction_save($transaction);
             return true;
         }
         $transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
         drupal_set_message(t('We could not process your card. Please verify your information again or try a different card.'), 'error');
         drupal_set_message(check_plain($respondCharge->getMessage()), 'error');
         $transaction->message = $respondCharge->getRawRespond();
         commerce_payment_transaction_save($transaction);
         return false;
     } else {
         $transaction->status = COMMERCE_PAYMENT_STATUS_FAILURE;
         $transaction->message = $respondCharge->getRawRespond();
         drupal_set_message(t('We received the following error processing your card. Please verify your information again or try a different card.'), 'error');
         drupal_set_message(check_plain($respondCharge->getExceptionState()->getErrorMessage()), 'error');
         commerce_payment_transaction_save($transaction);
         return false;
     }
 }
 /**
  * Web Service: Validate request
  *
  * @param $request_state
  *   @see CommerceFirstDataGGE4Controller::resolvePaymentState()
  *   Additional properties:
  *   - 'validation_errors': An array of validation errors
  *
  * @return
  *   TRUE if the request can be performed, else FALSE with $request_state
  *   updated with an array of  'validation_errors'
  */
 public function requestValidate(&$request_state)
 {
     $request_state['validation_errors'] = array();
     $errors =& $request_state['validation_errors'];
     if (!$this->isValid()) {
         $errors[] = t('First Data web service is not configured.');
         return FALSE;
     }
     if (empty($request_state) || !is_array($request_state)) {
         $errors[] = t('Empty request.');
         return FALSE;
     }
     // Resolve state
     $this->controller->resolvePaymentState($request_state);
     // Set local vars
     $card = $request_state['card'];
     $charge = $request_state['charge'];
     // Check transaction type
     $txn_type_info = $this->controller->transactionType($request_state['txn_type']);
     if (empty($txn_type_info)) {
         $errors[] = t('Invalid transaction type requested.');
         return FALSE;
     }
     // Charge parameters are required for all txn types
     if (empty($request_state['skip_charge_validation'])) {
         // Check that charge is a valid price array
         if (empty($charge) || !isset($charge['amount']) || !isset($charge['currency_code'])) {
             $errors[] = t('No charge details provided.');
             return FALSE;
         }
         // Zero Dollar Pre-Authorizations
         if ($request_state['txn_type'] != FIRSTDATA_GGE4_CREDIT_PREAUTH_ONLY && commerce_firstdata_gge4_is_zero($charge['amount'])) {
             if (empty($txn_type_info['zero_auth_allowed'])) {
                 $requested_txn_type_info = $this->controller->transactionType($request_state['txn_type']);
                 $errors[] = t('Zero Dollar Pre-Authorizations cannot be performed on @label transactions.', array(isset($requested_txn_type_info['label']) ? $requested_txn_type_info['label'] : $request_state['txn_type']));
                 return FALSE;
             }
             // Switch type to preauth
             $request_state['txn_type'] = FIRSTDATA_GGE4_CREDIT_PREAUTH_ONLY;
             $txn_type_info = $this->controller->transactionType($request_state['txn_type']);
         }
     }
     // Set variable for easier checks
     $charge_exists = !empty($charge) && isset($charge['amount']) && isset($charge['currency_code']);
     // Set transaction type
     $txn_type_code = $request_state['txn_type'];
     // Validate per txn type
     if (!empty($txn_type_info['requires_card'])) {
         // Purchase, Pre-auth, Pre-auth only, Refund via card
         // Card data is needed for these transactions
         if (empty($card)) {
             $errors[] = t('Missing credit card data.');
             return FALSE;
         }
         // Only active cards can be processed
         if (isset($card->status) && $card->status != 1) {
             $errors[] = t('Credit card is not active.');
             return FALSE;
         }
         // Expiration date is needed for these transactions
         if (empty($card->card_exp_month) || empty($card->card_exp_year)) {
             $errors[] = t('Missing credit card expiration.');
             return FALSE;
         }
         // Load card functions
         module_load_include('inc', 'commerce_payment', 'includes/commerce_payment.credit_card');
         // Validate the expiration date.
         if (commerce_payment_validate_credit_card_exp_date($card->card_exp_month, $card->card_exp_year) !== TRUE) {
             $errors[] = t('Credit card has expired.');
             return FALSE;
         }
         // Check if empty card number or remote id
         // - cardonfile plugin validates for request basd on remote_id
         if (empty($card->card_number) && empty($card->remote_id)) {
             $errors[] = t('Missing credit card number.');
             return FALSE;
         }
         // Name on card
         if (empty($card->card_name)) {
             $has_card_name = FALSE;
             if (!empty($request_state['billing_address'])) {
                 if (!empty($request_state['billing_address']['name_line'])) {
                     $has_card_name = TRUE;
                 }
             }
             if (!$has_card_name) {
                 $errors[] = t('Missing name for the credit card.');
                 return FALSE;
             }
         }
     } elseif (!empty($txn_type_info['transaction_operation'])) {
         // Pre-auth capture, Void, Refund
         /** @todo: static transactionAccess($txn_type, $transaction, $amount = NULL) ****/
         $prev_transaction = $request_state['previous_transaction'];
         if (empty($prev_transaction)) {
             $errors[] = t('Missing previous transaction.');
             return FALSE;
         }
         if (empty($prev_transaction->data['authorization_num'])) {
             $errors[] = t('Missing previous transaction authorization number.');
             return FALSE;
         }
         if (empty($prev_transaction->data['transaction_tag'])) {
             $errors[] = t('Missing previous transaction tag.');
             return FALSE;
         }
         // Now used for all time calculations
         $now = time();
         // Check if requested transaction type is expired
         if (!empty($txn_type_info['expiration']) && !empty($prev_transaction->created)) {
             if ($now - $prev_transaction->created > $txn_type_info['expiration']) {
                 $errors[] = t('@label is not available after @expiration.', array('@label' => $txn_type_info['label'], '@expiration' => format_interval($txn_type_info['expiration'])));
                 return FALSE;
             }
         }
         // Check expiration since the last update to the transaction.
         if (!empty($txn_type_info['changed_expiration']) && !empty($prev_transaction->changed)) {
             if ($now - $prev_transaction->changed > $txn_type_info['changed_expiration']) {
                 $errors[] = t('@label is not available after @expiration.', array('@label' => $txn_type_info['label'], '@expiration' => format_interval($txn_type_info['changed_expiration'])));
                 return FALSE;
             }
         }
         // Check previous transaction with type info
         if (!empty($prev_transaction->remote_status) && ($prev_txn_type_info = $this->controller->transactionType($prev_transaction->remote_status))) {
             // Check allowed_transactions
             if (empty($prev_txn_type_info['allowed_transactions']) || !in_array($txn_type_code, $prev_txn_type_info['allowed_transactions'])) {
                 $errors[] = t('@label is not available for this transaction.', array('@label' => $txn_type_info['label']));
                 return FALSE;
             }
             // Check the amount is less than or equal to the max transaction amount allowed.
             if (!empty($txn_type_info['max_amount_factor']) && $charge_exists && empty($request_state['skip_charge_validation'])) {
                 $txn_max = $this->controller->transactionMaxAmount($txn_type_code, $prev_transaction);
                 $txn_max = array('amount' => commerce_currency_convert($txn_max['amount'], $txn_max['currency_code'], $charge['currency_code']), 'currency_code' => $charge['currency_code']);
                 if ($charge['amount'] > $txn_max['amount']) {
                     $action_word = !empty($txn_type_info['action_word']['present']) ? $txn_type_info['action_word']['present'] : $txn_type_code;
                     if ($txn_type_info['max_amount_factor'] > 1) {
                         $percent = 100 * ($txn_type_info['max_amount_factor'] - 1);
                         $errors[] = t('You cannot @action more than @max_amount, @percent% above the transaction amount.', array('@action' => $action_word, '@percent' => number_format($percent, 2), '@max_amount' => commerce_currency_format($txn_max['amount'], $prev_transaction->currency_code)));
                     } elseif ($txn_type_info['max_amount_factor'] < 1) {
                         $percent = 100 * (1 - $txn_type_info['max_amount_factor']);
                         $errors[] = t('You cannot @action more than @max_amount, @percent% below the transaction amount.', array('@action' => $action_word, '@percent' => number_format($percent, 2), '@max_amount' => commerce_currency_format($txn_max['amount'], $prev_transaction->currency_code)));
                     } else {
                         $errors[] = t('You cannot @action more than the transaction amount.', array('@action' => $action_word));
                     }
                     return FALSE;
                 }
             }
         }
         // Requested transaction type specific checks
         switch ($txn_type_code) {
             case COMMERCE_CREDIT_CREDIT:
                 // Doesn't have a success status or has an amount of 0 or less.
                 if ($prev_transaction->status != COMMERCE_PAYMENT_STATUS_SUCCESS || $prev_transaction->amount <= 0) {
                     $errors[] = t('Credit processing is not available for this transaction.');
                     return FALSE;
                 }
                 break;
         }
     }
     // Let other plugins and modules validate
     $event_errors = $this->controller->trigger('ws_request_validate', $request_state);
     if (!empty($event_errors)) {
         $errors = array_merge($errors, $event_errors);
         return FALSE;
     }
     // ALLOW if made it here
     return TRUE;
 }