function before_process()
    {
        global $_POST, $order, $paypal_ec_token, $paypal_ec_payer_id, $paypal_ec_payer_info;
        include DIR_WS_CLASSES . 'cc_validation.php';
        $caller = $this->paypal_init();
        if ($this->is_paypal_process()) {
            //Do EC checkout
            $pdt =& Services_PayPal::getType('PaymentDetailsType');
            $at =& Services_PayPal::getType('AddressType');
            $at->setName($paypal_ec_payer_info['ship_name']);
            $at->setStreet1($paypal_ec_payer_info['ship_street_1']);
            $at->setStreet2($paypal_ec_payer_info['ship_street_2']);
            $at->setCityName($paypal_ec_payer_info['ship_city']);
            $at->setStateOrProvince($paypal_ec_payer_info['ship_state']);
            $at->setCountry($paypal_ec_payer_info['ship_country']);
            $at->setPostalCode($paypal_ec_payer_info['ship_postal_code']);
            $pdt->setShipToAddress($at);
            $order_total =& Services_PayPal::getType('BasicAmountType');
            $order_total->setval(number_format($order->info['total'], 2));
            $order_total->setattr('currencyID', $order->info['currency']);
            $pdt->setOrderTotal($order_total);
            /* Not required by PayPal and causes more problems than it solves, so this is commented out for now
            			$item_total =& Services_PayPal::getType('BasicAmountType');
            			$item_total->setval(number_format($order->info['subtotal'], 2));
            			$item_total->setattr('currencyID', $order->info['currency']);
            			$pdt->setItemTotal($item_total);
            			$ship_total =& Services_PayPal::getType('BasicAmountType');
            			$ship_total->setval(number_format($order->info['shipping_cost'], 2));
            			$ship_total->setattr('currencyID', $order->info['currency']);
            			$pdt->setShippingTotal($ship_total);
            			$tax_total =& Services_PayPal::getType('BasicAmountType');
            			$tax_total->setval(number_format($order->info['tax'], 2));
            			$tax_total->setattr('currencyID', $order->info['currency']);
            			$pdt->setTaxTotal($tax_total);
            			*/
            $details =& Services_PayPal::getType('DoExpressCheckoutPaymentRequestDetailsType');
            $details->setPaymentAction('Sale');
            $details->setToken($paypal_ec_token);
            $details->setPayerID($paypal_ec_payer_id);
            $details->setPaymentDetails($pdt);
            $ecprt =& Services_PayPal::getType('DoExpressCheckoutPaymentRequestType');
            $ecprt->setDoExpressCheckoutPaymentRequestDetails($details);
            $response = $caller->DoExpressCheckoutPayment($ecprt);
            if (Services_PayPal::isError($response) || $response->Ack != 'Success' && $response->Ack != 'SuccessWithWarning') {
                if ($this->enableDebugging) {
                    //Send the store owner a complete dump of the transaction
                    $final_req_dump = $this->prepare_var_dump($response);
                    //print_r($response, true);
                    /*
                    olc_php_mail(STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, $this->error_dump,
                    "In Funktion: before_process() - Express Checkout\nDid first contact attempt return error? " .
                    ($error_occurred ? "Yes" : "Nope")." \n".$spacer.$final_req_title.$spacer.$final_req_dump .
                    "\n\n".$spacer.$ts_req_title.$spacer .
                    $ts_req_dump, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
                    */
                    olc_php_mail(STORE_OWNER_EMAIL_ADDRESS, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, STORE_NAME, EMPTY_STRING, STORE_OWNER_EMAIL_ADDRESS, STORE_OWNER, EMPTY_STRING, EMPTY_STRING, $this->error_dump, EMPTY_STRING, str_replace(HASH, "before_process - Express Checkout\n" . $this->first_contact . ($error_occurred ? $this->yes : $this->no) . " \n" . $spacer . $final_req_title . $spacer . $final_req_dump . "\n\n" . $spacer . $ts_req_title . $spacer . $ts_req_dump, $this->in_function) . $this->prepare_var_dump($response), EMAIL_TYPE_TEXT);
                }
                if ($final_req->Errors->ErrorCode == EMPTY_STRING) {
                    $error = MODULE_PAYMENT_PAYPAL_DP_TEXT_DECLINED . MODULE_PAYMENT_PAYPAL_NO_RESPONSE_TEXT;
                } else {
                    $error = MODULE_PAYMENT_PAYPAL_DP_TEXT_ERROR . $this->return_transaction_errors($response->Errors);
                }
                $this->away_with_you($error, true);
            } else {
                $details = $response->getDoExpressCheckoutPaymentResponseDetails();
                $payment_info = $details->getPaymentInfo();
                $this->payment_type = 'PayPal Express Checkout';
                $this->trans_id = $payment_info->getTransactionID();
                $this->payment_status = $payment_info->getPaymentStatus();
                $this->avs = 'N/A';
                $this->cvv2 = 'N/A';
                if ($this->payment_status == PAYPAL_DP_STATUS_PENDING) {
                    $this->pending_reason = $payment_info->getPendingReason();
                    $this->payment_status .= LPAREN . $this->pending_reason . RPAREN;
                    $order->info['order_status'] = 1;
                }
            }
        } else {
            // Do DP checkout
            $cc_type = $_POST['wpp_cc_type'];
            $cc_number = $_POST['wpp_cc_number'];
            $cc_checkcode = $_POST['wpp_cc_checkcode'];
            $cc_first_name = $_POST['wpp_payer_firstname'];
            $cc_last_name = $_POST['wpp_payer_lastname'];
            $cc_owner_ip = $_SERVER['REMOTE_ADDR'];
            $cc_expdate_month = $_POST['wpp_cc_expdate_month'];
            $cc_expdate_year = $_POST['wpp_cc_expdate_year'];
            if (strlen($cc_expdate_year) < 4) {
                $cc_expdate_year = '20' . $cc_expdate_year;
            }
            //Thanks goes to SteveDallas for improved international support
            //Set the billing state field depending on what PayPal wants to see for that country
            switch ($order->billing['country']['iso_code_2']) {
                case 'US':
                case 'CA':
                    //Paypal only accepts two character state/province codes for some countries
                    if (strlen($order->billing['state']) > 2) {
                        $state_query = olc_db_query("SELECT zone_code FROM " . TABLE_ZONES . " WHERE zone_name = '" . $order->billing['state'] . APOS);
                        if (olc_db_num_rows($state_query) > 0) {
                            $state = olc_db_fetch_array($state_query);
                            $order->billing['state'] = $state['zone_code'];
                        } else {
                            $this->away_with_you(MODULE_PAYMENT_PAYPAL_DP_TEXT_STATE_ERROR);
                        }
                    }
                    if (strlen($order->delivery['state']) > 2) {
                        $state_query = olc_db_query("SELECT zone_code FROM " . TABLE_ZONES . " WHERE zone_name = '" . $order->delivery['state'] . APOS);
                        if (olc_db_num_rows($state_query) > 0) {
                            $state = olc_db_fetch_array($state_query);
                            $order->delivery['state'] = $state['zone_code'];
                        } else {
                            $this->away_with_you(MODULE_PAYMENT_PAYPAL_DP_TEXT_STATE_ERROR);
                        }
                    }
                    break;
                case 'AT':
                case 'BE':
                case 'FR':
                case 'DE':
                case 'CH':
                    $order->billing['state'] = EMPTY_STRING;
                    break;
                default:
                    break;
            }
            //Fix contributed by Glen Hoag.  This wasn't handling the shipping state correctly if it was different than the billing
            if (olc_not_null($order->delivery['street_address'])) {
                //Set the delivery state field depending on what PayPal wants to see for that country
                switch ($order->delivery['country']['iso_code_2']) {
                    case 'US':
                    case 'CA':
                        //Paypal only accepts two character state/province codes for some countries
                        if (strlen($order->delivery['state']) > 2) {
                            $state_query = olc_db_query("SELECT zone_code FROM " . TABLE_ZONES . " WHERE zone_name = '" . $order->delivery['state'] . APOS);
                            if (olc_db_num_rows($state_query) > 0) {
                                $state = olc_db_fetch_array($state_query);
                                $order->delivery['state'] = $state['zone_code'];
                            } else {
                                $this->away_with_you(MODULE_PAYMENT_PAYPAL_DP_TEXT_STATE_ERROR);
                            }
                        }
                        if (strlen($order->delivery['state']) > 2) {
                            $state_query = olc_db_query("SELECT zone_code FROM " . TABLE_ZONES . " WHERE zone_name = '" . $order->delivery['state'] . APOS);
                            if (olc_db_num_rows($state_query) > 0) {
                                $state = olc_db_fetch_array($state_query);
                                $order->delivery['state'] = $state['zone_code'];
                            } else {
                                $this->away_with_you(MODULE_PAYMENT_PAYPAL_DP_TEXT_STATE_ERROR);
                            }
                        }
                        break;
                    case 'AT':
                    case 'BE':
                    case 'FR':
                    case 'DE':
                    case 'CH':
                        $order->delivery['state'] = EMPTY_STRING;
                        break;
                    default:
                        break;
                }
            }
            $wpp_currency = $this->get_currency();
            //If the cc type sent in the post var isn't any one of the accepted cards, send them back to the payment page
            //This error should never come up unless the visitor is  playing with the post vars or they didn't get passed to checkout_confirmation.php
            if ($cc_type != 'Visa' && $cc_type != 'MasterCard' && $cc_type != 'Discover' && $cc_type != 'Amex') {
                $this->away_with_you(MODULE_PAYMENT_PAYPAL_DP_TEXT_BAD_CARD, false, FILENAME_CHECKOUT_PAYMENT);
            }
            //If they're still here, and awake, set some of the order object's variables
            $order->info['cc_type'] = $cc_type;
            $order->info['cc_number'] = substr($cc_number, 0, 4) . str_repeat('X', strlen($cc_number) - 8) . substr($cc_number, -4);
            $order->info['cc_owner'] = trim($cc_first_name . BLANK . $cc_last_name);
            $order->info['cc_expires'] = $cc_expdate_month . substr($cc_expdate_year, -2);
            //It's time to start a'chargin.  Initialize the paypal caller object
            $caller = $this->paypal_init();
            $ot =& Services_PayPal::getType('BasicAmountType');
            $ot->setattr('currencyID', $wpp_currency);
            $ot->setval(number_format($order->info['total'], 2));
            // Begin ShippingAddress -- WILLBRAND //
            if ($order->delivery['street_address'] != EMPTY_STRING) {
                $sat =& Services_PayPal::getType('AddressType');
                $sat->setName(trim($order->delivery['firstname'] . BLANK . $order->delivery['lastname']));
                $sat->setStreet1($order->delivery['street_address']);
                $sat->setStreet2($order->delivery['suburb']);
                $sat->setCityName($order->delivery['city']);
                $sat->setPostalCode($order->delivery['postcode']);
                $sat->setStateOrProvince($order->delivery['state']);
                $sat->setCountry($order->delivery['country']['iso_code_2']);
            }
            // End ShippingAddress -- WILLBRAND //
            $pdt =& Services_PayPal::getType('PaymentDetailsType');
            $pdt->setOrderTotal($ot);
            if (olc_not_null($order->delivery['street_address'])) {
                $pdt->setShipToAddress($sat);
            }
            $at =& Services_PayPal::getType('AddressType');
            $at->setStreet1($order->billing['street_address']);
            $at->setStreet2($order->billing['suburb']);
            $at->setCityName($order->billing['city']);
            $at->setStateOrProvince($order->billing['state']);
            $at->setCountry($order->billing['country']['iso_code_2']);
            $at->setPostalCode($order->billing['postcode']);
            $pnt =& Services_PayPal::getType('PersonNameType');
            $pnt->setFirstName($cc_first_name);
            $pnt->setLastName($cc_last_name);
            $pit =& Services_PayPal::getType('PayerInfoType');
            $pit->setPayerName($pnt);
            $pit->setAddress($at);
            // Send email address of payee -- WILLBRAND //
            $pit->setPayer($order->customer['email_address']);
            $ccdt =& Services_PayPal::getType('CreditCardDetailsType');
            $ccdt->setCardOwner($pit);
            $ccdt->setCreditCardType($cc_type);
            $ccdt->setCreditCardNumber($cc_number);
            $ccdt->setExpMonth($cc_expdate_month);
            $ccdt->setExpYear($cc_expdate_year);
            $ccdt->setCVV2($cc_checkcode);
            $ddp_req =& Services_PayPal::getType('DoDirectPaymentRequestDetailsType');
            //Should the action be a variable? Uhmmm....I'm thinking no
            $ddp_req->setPaymentAction('Sale');
            $ddp_req->setPaymentDetails($pdt);
            $ddp_req->setCreditCard($ccdt);
            $ddp_req->setIPAddress($cc_owner_ip);
            $ddp_details =& Services_PayPal::getType('DoDirectPaymentRequestType');
            $ddp_details->setVersion('2.0');
            $ddp_details->setDoDirectPaymentRequestDetails($ddp_req);
            $final_req = $caller->DoDirectPayment($ddp_details);
            $final_req_ack = $final_req->Ack;
            //If the transaction wasn't a success, start the error checking
            if (strpos($final_req_ack, 'Success') === false) {
                $error_occurred = false;
                $ts_result = false;
                //If an error or failure occurred, don't do a transaction check
                if ($final_req_ack == EMPTY_STRING || strpos($final_req_ack, 'Error') !== false || strpos($final_req_ack, 'Failure') !== false) {
                    $error_occurred = true;
                    $error_log = $final_req->Errors;
                    if ($error_log) {
                        $error_log = $this->return_transaction_errors($final_req->Errors);
                    } else {
                        $error_log = $final_req->message;
                    }
                } else {
                    //Do a transaction search to make sure the connection didn't just timeout
                    //It searches by email of payer and amount.  That should be accurate enough
                    $ts =& Services_PayPal::getType('TransactionSearchRequestType');
                    //Set to one day ago to avoid any time zone issues.  This does introduce a possible bug, but
                    //the chance of the same person buying the exact same amount of products within one day is pretty unlikely
                    $ts->setStartDate(date('Y-m-d', mktime(0, 0, 0, date("m"), date("d") - 1, date("Y"))) . 'T00:00:00-0700');
                    $ts->setPayer($order->customer['email_address']);
                    $ts->setAmount(number_format($order->info['total'], 2));
                    $ts_req = $caller->TransactionSearch($ts);
                    //If a matching transaction was found, tell us
                    if (olc_not_null($ts_req->PaymentTransactions) && strpos($ts_req->Ack, 'Success') !== false) {
                        $ts_result = true;
                    } else {
                        $error_log = $this->return_transaction_errors($final_req->Errors);
                    }
                }
                if (!$error_occurred && $ts_result) {
                    $return_codes = array($ts_req->PaymentTransactions[0]->TransactionID, 'No AVS Code Returned', 'No CVV2 Code Returned');
                } else {
                    if ($this->enableDebugging) {
                        //Send the store owner a complete dump of the transaction
                        $dp_dump = $this->prepare_var_dump($ddp_details);
                        //print_r($ddp_details, true);
                        $final_req_dump = print_r($final_req, true);
                        $spacer = "---------------------------------------------------------------------\n";
                        $dp_dump_title = "-------------------------------DP_DUMP-------------------------------\n";
                        $dp_dump_title .= "------------This is the information that was sent to PayPal----------\n";
                        $final_req_title = "-------------------------------FINAL_REQ-----------------------------\n";
                        $final_req_title .= "-------------------This is the response from PayPal------------------\n";
                        $ts_req_dump = $this->prepare_var_dump($ts_req);
                        //print_r($ts_req, true);
                        $ts_req_title = "---------------------------------TS_REQ------------------------------\n";
                        $ts_req_title .= "--------Results of the transaction search if it was executed---------\n";
                        /*
                        olc_php_mail(STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, $this->error_dump,
                        "In Funktion: before_process() - Direct Payment\nDid first contact attempt return error? " .
                        ($error_occurred ? "Yes" : "Nope")." \n".$spacer.$dp_dump_title.$spacer.$dp_dump .
                        $spacer.$final_req_title.$spacer.$final_req_dump."\n\n".$spacer.$ts_req_title .
                        $spacer.$ts_req_dump, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
                        */
                        olc_php_mail(STORE_OWNER_EMAIL_ADDRESS, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, STORE_NAME, EMPTY_STRING, STORE_OWNER_EMAIL_ADDRESS, STORE_OWNER, EMPTY_STRING, EMPTY_STRING, $this->error_dump, EMPTY_STRING, str_replace(HASH, "before_process - Direct Payment\n" . $this->first_contact . ($error_occurred ? $this->yes : $this->no) . " \n" . $error_log . " \n" . $spacer . $dp_dump_title . $spacer . $dp_dump . $spacer . $final_req_title . $spacer . $final_req_dump . "\n\n" . $spacer . $ts_req_title . $spacer . $ts_req_dump, $this->in_function), EMAIL_TYPE_TEXT);
                    }
                    if (MODULE_PAYMENT_PAYPAL_DP_SAFEGUARD == 'Yes') {
                        /*
                        olc_php_mail(STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, 'Paypal declined the enclosed card', 'User: '******'email_address']."\n\nCredit Card Information:\n" .
                        trim($cc_first_name.BLANK.$cc_last_name).NEW_LINE.$cc_type.NEW_LINE.$cc_number.NEW_LINE .
                        $cc_expdate_month.SLASH.$cc_expdate_year.NEW_LINE.$cc_checkcode."\n\nFor the amount of: ".
                        number_format($order->products['total'], 2)."\n\n" .
                        'To preserve your customer\'s privacy, please delete this email after you have manually processed their card.',
                        STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
                        */
                        $nl = NEW_LINE;
                        $two_nl = $nl . $nl;
                        $sep = "========================" . $two_nl;
                        if (SESSION_LANGUAGE == 'german') {
                            $subject = 'hat eine Kreditkarten-Zahlung abgelehnt';
                            $message = 'User: '******'email_address'] . $two_nl . "Kreditkarten-Information" . $nl . $sep . "Owner:       " . trim($cc_first_name . BLANK . $cc_last_name) . $nl . "Card:        " . $cc_type . $nl . "Number:      " . $cc_number . $nl . "Valid until: " . $cc_expdate_month . SLASH . $cc_expdate_year . $nl . "CVN:         " . $cc_checkcode . $two_nl . "Amount:      " . number_format($order->products['total'], 2) . $two_nl . $sep . 'Um die Sicherheit Ihrer Kunden zu gewährleisten, löschen Sie bitte diese eMail, ' . 'nachdem Sie die Zahlung manuell belastet haben!';
                        } else {
                            $subject = 'declined the enclosed credit-card payment';
                            $message = 'User: '******'email_address'] . $two_nl . "Credit Card Informations" . $nl . $sep . "Owner:      " . trim($cc_first_name . BLANK . $cc_last_name) . $nl . "Card:       " . $cc_type . $nl . "Number:     " . $cc_number . $nl . "Valid to:   " . $cc_expdate_month . SLASH . $cc_expdate_year . $nl . "CVN:        " . $cc_checkcode . $two_nl . "Amount:     " . number_format($order->products['total'], 2) . $two_nl . $sep . 'To preserve your customer\'s privacy, please delete this email after you have ' . 'manually processed their card!';
                        }
                        $subject = '***** Paypal ' . $subject . ' *****';
                        olc_php_mail(STORE_OWNER_EMAIL_ADDRESS, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, STORE_NAME, EMPTY_STRING, STORE_OWNER_EMAIL_ADDRESS, STORE_OWNER, EMPTY_STRING, EMPTY_STRING, $subject, EMPTY_STRING, str_replace(HASH, $message, $this->in_function), EMAIL_TYPE_TEXT);
                    } else {
                        //If the return is empty
                        if (!olc_not_null($error_log)) {
                            $this->away_with_you(MODULE_PAYMENT_PAYPAL_DP_TEXT_DECLINED . 'No response from PayPal<br/>No response was received from PayPal.
							Please contact the store owner for assistance.', false, FILENAME_CHECKOUT_PAYMENT);
                        } else {
                            $this->away_with_you(MODULE_PAYMENT_PAYPAL_DP_TEXT_DECLINED . $error_log, false, FILENAME_CHECKOUT_PAYMENT);
                        }
                    }
                }
            } else {
                $return_codes = array($final_req->TransactionID, $final_req->AVSCode, $final_req->CVV2Code);
            }
            $this->payment_type = 'PayPal Direct Payment';
            $this->trans_id = $return_codes[0];
            $this->payment_status = PAYPAL_DP_STATUS_COMPLETED;
            $ret_avs = $return_codes[1];
            $ret_cvv2 = $return_codes[2];
            switch ($ret_avs) {
                case 'A':
                    $ret_avs_msg = 'Address Address only (no ZIP)';
                    break;
                case 'B':
                    $ret_avs_msg = 'International “A” Address only (no ZIP)';
                    break;
                case 'C':
                    $ret_avs_msg = 'International “N” None';
                    break;
                case 'D':
                    $ret_avs_msg = 'International “X” Address and Postal Code';
                    break;
                case 'E':
                    $ret_avs_msg = 'Not allowed for MOTO (Internet/Phone)';
                    break;
                case 'F':
                    $ret_avs_msg = 'UK-specific “X” Address and Postal Code';
                    break;
                case 'G':
                    $ret_avs_msg = 'Global Unavailable Not applicable';
                    break;
                case 'I':
                    $ret_avs_msg = 'International Unavailable Not applicable';
                    break;
                case 'N':
                    $ret_avs_msg = 'No None';
                    break;
                case 'P':
                    $ret_avs_msg = 'Postal (International “Z”) Postal Code only (no Address)';
                    break;
                case 'R':
                    $ret_avs_msg = 'Retry Not applicable';
                    break;
                case 'S':
                    $ret_avs_msg = 'Service not Supported Not applicable';
                    break;
                case 'U':
                    $ret_avs_msg = 'Unavailable Not applicable';
                    break;
                case 'W':
                    $ret_avs_msg = 'Whole ZIP Nine-digit ZIP code (no Address)';
                    break;
                case 'X':
                    $ret_avs_msg = 'Exact match Address and nine-digit ZIP code';
                    break;
                case 'Y':
                    $ret_avs_msg = 'Yes Address and five-digit ZIP';
                    break;
                case 'Z':
                    $ret_avs_msg = 'ZIP Five-digit ZIP code (no Address)';
                    break;
                default:
                    $ret_avs_msg = 'Error';
            }
            switch ($ret_cvv2) {
                case 'M':
                    $ret_cvv2_msg = 'Match CVV2';
                    break;
                case 'N':
                    $ret_cvv2_msg = 'No match None';
                    break;
                case 'P':
                    $ret_cvv2_msg = 'Not Processed Not applicable';
                    break;
                case 'S':
                    $ret_cvv2_msg = 'Service not Supported Not applicable';
                    break;
                case 'U':
                    $ret_cvv2_msg = 'Unavailable Not applicable';
                    break;
                case 'X':
                    $ret_cvv2_msg = 'No response Not applicable';
                    break;
                default:
                    $ret_cvv2_msg = 'Error';
                    break;
            }
            $this->avs = $ret_avs_msg;
            $this->cvv2 = $ret_cvv2_msg;
        }
    }
 /**
  * Override some of the default SOAP:: package _decode behavior to
  * handle simpleTypes and complexTypes with simpleContent.
  */
 function &_decode(&$soapval)
 {
     if (count($soapval->attributes)) {
         $attributes = $soapval->attributes;
     }
     $object =& Services_PayPal::getType($soapval->type);
     if (Services_PayPal::isError($object)) {
         return parent::_decode($soapval);
     }
     $this->_type_translation[$soapval->type] = $soapval->type;
     $result =& parent::_decode($soapval);
     if (!is_a($result, 'XSDType') && is_a($object, 'XSDSimpleType')) {
         $object->setval($result);
         if (isset($attributes)) {
             foreach ($attributes as $aname => $attribute) {
                 $object->setattr($aname, $attribute);
             }
         }
         $result =& $object;
     }
     return $result;
 }
Beispiel #3
0
 /**
  * This function collects all the information from a web/api form and invokes
  * the relevant payment processor specific functions to perform the transaction
  *
  * @param  array $params assoc array of input parameters for this transaction
  *
  * @return array the result in an nice formatted array (or an error object)
  * @public
  */
 function doDirectPayment(&$params)
 {
     if (!$this->_caller) {
         return CRM_Utils_Payment_PayPal::error();
     }
     $orderTotal =& Services_PayPal::getType('BasicAmountType');
     if (Services_PayPal::isError($orderTotal)) {
         return CRM_Utils_Payment_PayPal::error($orderTotal);
     }
     $orderTotal->setattr('currencyID', $params['currencyID']);
     $orderTotal->setval($params['amount'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $payerName =& Services_PayPal::getType('PersonNameType');
     if (Services_PayPal::isError($payerName)) {
         return CRM_Utils_Payment_PayPal::error($payerName);
     }
     $payerName->setLastName($params['last_name'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $payerName->setMiddleName($params['middle_name'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $payerName->setFirstName($params['first_name'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $address =& Services_PayPal::getType('AddressType');
     if (Services_PayPal::isError($address)) {
         return CRM_Utils_Payment_PayPal::error($address);
     }
     $address->setStreet1($params['street_address'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $address->setCityName($params['city'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $address->setStateOrProvince($params['state_province'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $address->setPostalCode($params['postal_code'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $address->setCountry($params['country'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $cardOwner =& Services_PayPal::getType('PayerInfoType');
     if (Services_PayPal::isError($cardOwner)) {
         return CRM_Utils_Payment_PayPal::error($cardOwner);
     }
     $cardOwner->setPayer($params['email']);
     $cardOwner->setAddress($address);
     $cardOwner->setPayerCountry($params['country'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $cardOwner->setPayerName($payerName);
     $creditCard =& Services_PayPal::getType('CreditCardDetailsType');
     if (Services_PayPal::isError($creditCard)) {
         return CRM_Utils_Payment_PayPal::error($creditCard);
     }
     $creditCard->setCardOwner($cardOwner);
     $creditCard->setCVV2($params['cvv2'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $creditCard->setExpYear($params['year'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $creditCard->setExpMonth($params['month'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $creditCard->setCreditCardNumber($params['credit_card_number'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $creditCard->setCreditCardType($params['credit_card_type'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $doDirectPaymentRequestDetails =& Services_PayPal::getType('DoDirectPaymentRequestDetailsType');
     $paymentDetails =& Services_PayPal::getType('PaymentDetailsType');
     if (Services_PayPal::isError($paymentDetails)) {
         return CRM_Utils_Payment_PayPal::error($paymentDetails);
     }
     $paymentDetails->setOrderTotal($orderTotal);
     $paymentDetails->setInvoiceID($params['invoiceID'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $shipToAddress = $address;
     $shipToAddress->setName($params['first_name'] . ' ' . $params['last_name']);
     $paymentDetails->setShipToAddress($shipToAddress);
     if (Services_PayPal::isError($doDirectPaymentRequestDetails)) {
         return CRM_Utils_Payment_PayPal::error($doDirectPaymentRequestDetails);
     }
     $doDirectPaymentRequestDetails->setCreditCard($creditCard);
     $doDirectPaymentRequestDetails->setPaymentDetails($paymentDetails);
     $doDirectPaymentRequestDetails->setIPAddress($params['ip_address'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $doDirectPaymentRequestDetails->setPaymentAction($params['payment_action'], CRM_UTILS_PAYMENT_PAYPAL_CHARSET);
     $doDirectPayment =& Services_PayPal::getType('DoDirectPaymentRequestType');
     if (Services_PayPal::isError($doDirectPayment)) {
         return CRM_Utils_Payment_PayPal::error($doDirectPayment);
     }
     $doDirectPayment->setDoDirectPaymentRequestDetails($doDirectPaymentRequestDetails);
     $result = $this->_caller->DoDirectPayment($doDirectPayment);
     if (Services_PayPal::isError($result)) {
         return CRM_Utils_Payment_PayPal::error($result);
     }
     /* Check for application errors */
     $result =& CRM_Utils_Payment_PayPal::checkResult($result);
     if (is_a($result, 'CRM_Core_Error')) {
         return $result;
     }
     /* Success */
     $params['trxn_id'] = $result->TransactionID;
     $params['gross_amount'] = CRM_Utils_Payment_PayPal::getAmount($result->Amount);
     return $params;
 }