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; }