/**
 * Process a transaction and record it against the contact.
 *
 * @param  array   $params           (reference ) input parameters
 *
 * @return array (reference )        contribution of created or updated record (or a civicrm error)
 * @static void
 * @access public
 *
 */
function civicrm_api3_contribution_transact($params)
{
    // Set some params specific to payment processing
    $params['payment_processor_mode'] = empty($params['is_test']) ? 'live' : 'test';
    $params['amount'] = $params['total_amount'];
    if (!isset($params['net_amount'])) {
        $params['net_amount'] = $params['amount'];
    }
    if (!isset($params['invoiceID']) && isset($params['invoice_id'])) {
        $params['invoiceID'] = $params['invoice_id'];
    }
    $paymentProcessor = CRM_Financial_BAO_PaymentProcessor::getPayment($params['payment_processor'], $params['payment_processor_mode']);
    if (civicrm_error($paymentProcessor)) {
        return $paymentProcessor;
    }
    $payment = CRM_Core_Payment::singleton($params['payment_processor_mode'], $paymentProcessor);
    if (civicrm_error($payment)) {
        return $payment;
    }
    $transaction = $payment->doDirectPayment($params);
    if (civicrm_error($transaction)) {
        return $transaction;
    }
    // but actually, $payment->doDirectPayment() doesn't return a
    // CRM_Core_Error by itself
    if (is_object($transaction) && get_class($transaction) == 'CRM_Core_Error') {
        $errs = $transaction->getErrors();
        if (!empty($errs)) {
            $last_error = array_shift($errs);
            return CRM_Core_Error::createApiError($last_error['message']);
        }
    }
    $params['payment_instrument_id'] = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType', $paymentProcessor['payment_processor_type_id'], 'payment_type') == 1 ? 'Credit Card' : 'Debit Card';
    return civicrm_api('contribution', 'create', $params);
}
/**
 * Process a transaction and record it against the contact.
 *
 * @param  array   $params           (reference ) input parameters
 *
 * @return array (reference )        contribution of created or updated record (or a civicrm error)
 * @static void
 * @access public
 *
 */
function civicrm_contribute_transact($params)
{
    civicrm_initialize();
    if (empty($params)) {
        return civicrm_create_error(ts('No input parameters present'));
    }
    if (!is_array($params)) {
        return civicrm_create_error(ts('Input parameters is not an array'));
    }
    $values = array();
    require_once 'CRM/Contribute/BAO/Contribution.php';
    $error = _civicrm_contribute_format_params($params, $values);
    if (civicrm_error($error)) {
        return $error;
    }
    $required = array('amount');
    foreach ($required as $key) {
        if (!isset($params[$key])) {
            return civicrm_create_error("Missing parameter {$key}: civicrm_contribute_transact() requires a parameter '{$key}'.");
        }
    }
    // allow people to omit some values for convenience
    $defaults = array('payment_processor_mode' => 'live');
    $params = array_merge($defaults, $params);
    // clean up / adjust some values which
    if (!isset($params['total_amount'])) {
        $params['total_amount'] = $params['amount'];
    }
    if (!isset($params['net_amount'])) {
        $params['net_amount'] = $params['amount'];
    }
    if (!isset($params['receive_date'])) {
        $params['receive_date'] = date('Y-m-d');
    }
    if (!isset($params['invoiceID']) && isset($params['invoice_id'])) {
        $params['invoiceID'] = $params['invoice_id'];
    }
    require_once 'CRM/Core/BAO/PaymentProcessor.php';
    $paymentProcessor = CRM_Core_BAO_PaymentProcessor::getPayment($params['payment_processor_id'], $params['payment_processor_mode']);
    if (civicrm_error($paymentProcessor)) {
        return $paymentProcessor;
    }
    require_once 'CRM/Core/Payment.php';
    $payment = CRM_Core_Payment::singleton($params['payment_processor_mode'], $paymentProcessor);
    if (civicrm_error($payment)) {
        return $payment;
    }
    $transaction = $payment->doDirectPayment($params);
    if (civicrm_error($transaction)) {
        return $transaction;
    }
    // but actually, $payment->doDirectPayment() doesn't return a
    // CRM_Core_Error by itself
    if (get_class($transaction) == 'CRM_Core_Error') {
        $errs = $transaction->getErrors();
        if (!empty($errs)) {
            $last_error = array_shift($errs);
            return CRM_Core_Error::createApiError($last_error['message']);
        }
    }
    $contribution = civicrm_contribution_add($params);
    return $contribution;
}