/**
  *
  * @param EEI_Payment $payment
  * @param array $billing_info
  * @return \EE_Payment|\EEI_Payment
  */
 public function do_direct_payment($payment, $billing_info = null)
 {
     require_once dirname(__FILE__) . '/lib/ChasePaymentech.php';
     $this->_default_error = __('An error occurred while processing your transaction. Please try again or contact us to complete your order.', 'event-espresso');
     $card_num = preg_replace('/[^0-9]+/', '', $billing_info['credit_card']);
     $cvv = preg_replace('/[^0-9]+/', '', $billing_info['cvv']);
     $payment_id = uniqid();
     $payment->set_txn_id_chq_nmbr($payment_id);
     $fields = array('AccountNum' => $card_num, 'Exp' => $billing_info['exp_month'] . $billing_info['exp_year'], 'CurrencyCode' => $payment->currency_code() === 'USD' ? '840' : '124', 'CurrencyExponent' => 2, 'CardSecValInd' => null, 'CardSecVal' => $cvv, 'Amount' => number_format($payment->amount(), 2, '', ''), 'AVSzip' => substr($billing_info['zip'], 0, 10), 'AVSaddress1' => substr($billing_info['address'], 0, 30), 'AVSaddress2' => $billing_info['address2'] ? substr($billing_info['address2'], 0, 30) : null, 'AVScity' => substr($billing_info['city'], 0, 20), 'AVSstate' => substr($billing_info['state'], 0, 2), 'AVScountryCode' => in_array($billing_info['country'], array('US', 'CA', 'GB', 'UK')) ? $billing_info['country'] : ' ', 'AVSphoneNum' => substr(preg_replace('/\\D/', '', $billing_info['phone']), 0, 14), 'AVSname' => substr($billing_info['first_name'] . ' ' . $billing_info['last_name'], 0, 30), 'OrderID' => $payment_id);
     /*
      * Visa & Discover require that the CardSecValInd be set
      *
      */
     $card_type = ChasePaymentech_Request::getCreditCardBrand($card_num);
     if (in_array($card_type, array('Visa', 'Discover'))) {
         $fields['CardSecValInd'] = is_numeric($cvv) ? 1 : 9;
     }
     $this->_log_clean_request_fields($fields, $payment);
     $sale = new ChasePaymentech_NewOrder($this->_connection_username, $this->_connection_password, $this->_merchant_id, array('bin' => $this->_bin, 'terminal_id' => $this->_terminal_id));
     if ($this->_validate_ssl_locally && file_exists(dirname(__FILE__) . '/lib/cacert.pem')) {
         $sale->setCurlOption(CURLOPT_CAINFO, dirname(__FILE__) . '/lib/cacert.pem');
     }
     if ($this->_disable_ssl_validation) {
         $sale->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
         $sale->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
     }
     $sale->setTestMode($this->_debug_mode);
     // $sale->setLogFile($this->log_file);
     // $sale->setLogRequests($this->log_requests, $force = true);
     $sale->setFields($fields);
     $response = $sale->authorizeAndCapture();
     $this->log(array('approved' => (string) $response->approved, 'declined' => (string) $response->declined, 'error' => (string) $response->error, 'ProcStatus' => (string) $response->ProcStatus instanceof SimpleXMLElement ? $response->ProcStatus->asXML() : '', 'RespCode' => (string) $response->RespCode, 'ApprovalStatus' => (string) $response->ApprovalStatus, 'response' => (string) htmlentities($response->response)), $payment);
     $payment->set_details(wp_json_encode($response));
     if (!isset($response->RespCode) || trim($response->RespCode) != '00') {
         $payment->set_status($this->_pay_model->declined_status());
         if ($this->_show_default_error !== true) {
             $error_message = $response->StatusMsg && !empty($response->StatusMsg) ? (string) $response->StatusMsg : $this->_default_error;
             $payment->set_gateway_response((string) $error_message);
         } else {
             $payment->set_gateway_response((string) $this->_default_error);
         }
     } else {
         $payment->set_status($this->_pay_model->approved_status());
         $payment->set_gateway_response(__('Payment Accepted', 'event_espresso'));
     }
     return $payment;
 }
 /**
  * Determines whether or not we can easily itemize the transaction using only
  * items and taxes (ie, no promotions or surcharges or cancellations needed)
  * @param EEI_Payment $payment
  * @return boolean
  */
 protected function _can_easily_itemize_transaction_for(EEI_Payment $payment)
 {
     return $this->_money->compare_floats($this->_sum_items_and_taxes($payment->transaction()), $payment->transaction()->total()) && $this->_money->compare_floats($payment->amount(), $payment->transaction()->total());
 }
 /**
  * @param EEI_Payment $payment      to process
  * @param array       $billing_info but should be empty for this gateway
  * @param string      $return_url   URL to send the user to after payment on the payment provider's website
  * @param string      $notify_url   URL to send the instant payment notification
  * @param string      $cancel_url   URL to send the user to after a cancelled payment attempt on teh payment provider's website
  * @return EEI_Payment
  */
 public function set_redirection_info($payment, $billing_info = array(), $return_url = NULL, $notify_url = NULL, $cancel_url = NULL)
 {
     $redirect_args = array();
     $transaction = $payment->transaction();
     $primary_registrant = $transaction->primary_registration();
     $item_num = 1;
     /** @type EE_Line_Item $total_line_item */
     $total_line_item = $transaction->total_line_item();
     $total_discounts_to_cart_total = $transaction->paid();
     //only itemize the order if we're paying for the rest of the order's amount
     if ($payment->amount() == $transaction->total()) {
         $payment->update_extra_meta(EEG_Paypal_Standard::itemized_payment_option_name, true);
         //this payment is for the remaining transaction amount,
         //keep track of exactly how much the itemized order amount equals
         $itemized_sum = 0;
         $shipping_previously_added = 0;
         //so let's show all the line items
         foreach ($total_line_item->get_items() as $line_item) {
             if ($line_item instanceof EE_Line_Item) {
                 //it's some kind of discount
                 if ($line_item->total() < 0) {
                     $total_discounts_to_cart_total += abs($line_item->total());
                     $itemized_sum += $line_item->total();
                     continue;
                 }
                 //dont include shipping again.
                 if (strpos($line_item->code(), 'paypal_shipping_') === 0) {
                     $shipping_previously_added = $line_item->total();
                     continue;
                 }
                 $redirect_args['item_name_' . $item_num] = substr(sprintf(_x('%1$s for %2$s', 'Ticket for Event', 'event_espresso'), $line_item->name(), $line_item->ticket_event_name()), 0, 127);
                 $redirect_args['amount_' . $item_num] = $line_item->unit_price();
                 $redirect_args['quantity_' . $item_num] = $line_item->quantity();
                 //if we're not letting PayPal calculate shipping, tell them its 0
                 if (!$this->_paypal_shipping) {
                     $redirect_args['shipping_' . $item_num] = '0';
                     $redirect_args['shipping2_' . $item_num] = '0';
                 }
                 $item_num++;
                 $itemized_sum += $line_item->total();
             }
         }
         $taxes_li = $this->_line_item->get_taxes_subtotal($total_line_item);
         //ideally itemized sum equals the transaction total. but if not (which is weird)
         //and the itemized sum is LESS than the transaction total
         //add another line item
         //if the itemized sum is MORE than the transaction total,
         //add the difference it to the discounts
         $itemized_sum_diff_from_txn_total = round($transaction->total() - $itemized_sum - $taxes_li->total() - $shipping_previously_added, 2);
         if ($itemized_sum_diff_from_txn_total < 0) {
             //itemized sum is too big
             $total_discounts_to_cart_total += abs($itemized_sum_diff_from_txn_total);
         } elseif ($itemized_sum_diff_from_txn_total > 0) {
             $redirect_args['item_name_' . $item_num] = substr(__('Other charges', 'event_espresso'), 0, 127);
             $redirect_args['amount_' . $item_num] = $this->format_currency($itemized_sum_diff_from_txn_total);
             $redirect_args['quantity_' . $item_num] = 1;
             $item_num++;
         }
         if ($total_discounts_to_cart_total > 0) {
             $redirect_args['discount_amount_cart'] = $this->format_currency($total_discounts_to_cart_total);
         }
         //add our taxes to the order if we're NOT using PayPal's
         if (!$this->_paypal_taxes) {
             $redirect_args['tax_cart'] = $total_line_item->get_total_tax();
         }
     } else {
         $payment->update_extra_meta(EEG_Paypal_Standard::itemized_payment_option_name, false);
         //partial payment that's not for the remaining amount, so we can't send an itemized list
         $redirect_args['item_name_' . $item_num] = substr(sprintf(__('Payment of %1$s for %2$s', "event_espresso"), $payment->amount(), $primary_registrant->reg_code()), 0, 127);
         $redirect_args['amount_' . $item_num] = $payment->amount();
         $redirect_args['shipping_' . $item_num] = '0';
         $redirect_args['shipping2_' . $item_num] = '0';
         $redirect_args['tax_cart'] = '0';
         $item_num++;
     }
     if ($this->_debug_mode) {
         $redirect_args['item_name_' . $item_num] = 'DEBUG INFO (this item only added in sandbox mode';
         $redirect_args['amount_' . $item_num] = 0;
         $redirect_args['on0_' . $item_num] = 'NOTIFY URL';
         $redirect_args['os0_' . $item_num] = $notify_url;
         $redirect_args['on1_' . $item_num] = 'RETURN URL';
         $redirect_args['os1_' . $item_num] = $return_url;
         //			$redirect_args['option_index_' . $item_num] = 1; // <-- dunno if this is needed ?
         $redirect_args['shipping_' . $item_num] = '0';
         $redirect_args['shipping2_' . $item_num] = '0';
     }
     $redirect_args['business'] = $this->_paypal_id;
     $redirect_args['return'] = $return_url;
     $redirect_args['cancel_return'] = $cancel_url;
     $redirect_args['notify_url'] = $notify_url;
     $redirect_args['cmd'] = '_cart';
     $redirect_args['upload'] = 1;
     $redirect_args['currency_code'] = $payment->currency_code();
     $redirect_args['rm'] = 2;
     //makes the user return with method=POST
     if ($this->_image_url) {
         $redirect_args['image_url'] = $this->_image_url;
     }
     $redirect_args['no_shipping'] = $this->_shipping_details;
     $redirect_args['bn'] = 'EventEspresso_SP';
     //EE will blow up if you change this
     $redirect_args = apply_filters("FHEE__EEG_Paypal_Standard__set_redirection_info__arguments", $redirect_args, $this);
     $payment->set_redirect_url($this->_gateway_url);
     $payment->set_redirect_args($redirect_args);
     //                echo "redirect info";
     //                var_dump( $redirect_args );
     //                die;
     return $payment;
 }
 /**
  *
  * @param EEI_Payment $payment
  * @param type $billing_info
  * @param type $return_url
  * @param type $cancel_url
  */
 public function set_redirection_info($payment, $billing_info = array(), $return_url = NULL, $notify_url = NULL, $cancel_url = NULL)
 {
     global $auto_made_thing_seed;
     if (empty($auto_made_thing_seed)) {
         $auto_made_thing_seed = rand(1, 1000000);
     }
     $payment->set_txn_id_chq_nmbr($auto_made_thing_seed++);
     $payment->set_redirect_url(EE_NEW_PAYMENT_METHOD_URL . DS . 'payment_methods' . DS . 'New_Payment_Method_Offsite' . DS . 'pretend_offsite_page.php');
     $payment->set_redirect_args(array('amount' => $payment->amount(), 'gateway_txn_id' => $payment->txn_id_chq_nmbr(), 'return_url' => $return_url, 'uses_separate_IPN_request' => $this->uses_separate_IPN_request(), 'ipn_url' => $notify_url));
     return $payment;
 }