/** * * @param EE_Transaction $transaction * @param float $amount * @param EE_Billing_Info_Form $billing_info * @param string $return_url * @param string $fail_url * @param string $method * @param bool $by_admin * @return EE_Payment * @throws EE_Error */ function process_payment(EE_Transaction $transaction, $amount = null, $billing_info = null, $return_url = null, $fail_url = '', $method = 'CART', $by_admin = false) { // @todo: add surcharge for the payment method, if any if ($this->_gateway) { //there is a gateway, so we're going to make a payment object //but wait! do they already have a payment in progress that we thought was failed? $duplicate_properties = array('STS_ID' => EEM_Payment::status_id_failed, 'TXN_ID' => $transaction->ID(), 'PMD_ID' => $this->_pm_instance->ID(), 'PAY_source' => $method, 'PAY_amount' => $amount !== null ? $amount : $transaction->remaining(), 'PAY_gateway_response' => null); $payment = EEM_Payment::instance()->get_one(array($duplicate_properties)); //if we didn't already have a payment in progress for the same thing, //then we actually want to make a new payment if (!$payment instanceof EE_Payment) { $payment = EE_Payment::new_instance(array_merge($duplicate_properties, array('PAY_timestamp' => time(), 'PAY_txn_id_chq_nmbr' => null, 'PAY_po_number' => null, 'PAY_extra_accntng' => null, 'PAY_details' => null))); } //make sure the payment has been saved to show we started it, and so it has an ID should the gateway try to log it $payment->save(); $billing_values = $this->_get_billing_values_from_form($billing_info); // Offsite Gateway if ($this->_gateway instanceof EE_Offsite_Gateway) { $payment = $this->_gateway->set_redirection_info($payment, $billing_values, $return_url, EE_Config::instance()->core->txn_page_url(array('e_reg_url_link' => $transaction->primary_registration()->reg_url_link(), 'ee_payment_method' => $this->_pm_instance->slug())), $fail_url); $payment->save(); // Onsite Gateway } elseif ($this->_gateway instanceof EE_Onsite_Gateway) { $payment = $this->_gateway->do_direct_payment($payment, $billing_values); $payment->save(); } else { throw new EE_Error(sprintf(__('Gateway for payment method type "%s" is "%s", not a subclass of either EE_Offsite_Gateway or EE_Onsite_Gateway, or null (to indicate NO gateway)', 'event_espresso'), get_class($this), gettype($this->_gateway))); } } else { // no gateway provided // there is no payment. Must be an offline gateway // create a payment object anyways, but dont save it $payment = EE_Payment::new_instance(array('STS_ID' => EEM_Payment::status_id_pending, 'TXN_ID' => $transaction->ID(), 'PMD_ID' => $transaction->payment_method_ID(), 'PAY_amount' => 0.0, 'PAY_timestamp' => time())); } // if there is billing info, clean it and save it now if ($billing_info instanceof EE_Billing_Attendee_Info_Form) { $this->_save_billing_info_to_attendee($billing_info, $transaction); } return $payment; }
/** * Process the IPN. Firstly, we'll hope we put the standard args into the IPN URL so * we can easily find what registration the IPN is for and what payment method. * However, if not, we'll give all payment methods a chance to claim it and process it. * If a payment is found for the IPN info, it is saved. * * @param array $_req_data eg $_REQUEST * @param EE_Transaction|int $transaction optional (or a transactions id) * @param EE_Payment_Method $payment_method (or a slug or id of one) * @param boolean $update_txn whether or not to call * EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment() * @param bool $separate_IPN_request whether the IPN uses a separate request ( true like PayPal ) * or is processed manually ( false like Mijireh ) * @throws EE_Error * @throws Exception * @return EE_Payment */ public function process_ipn($_req_data, $transaction = null, $payment_method = null, $update_txn = true, $separate_IPN_request = true) { EE_Registry::instance()->load_model('Change_Log'); $_req_data = $this->_remove_unusable_characters_from_array((array) $_req_data); EE_Processor_Base::set_IPN($separate_IPN_request); $obj_for_log = null; if ($transaction instanceof EE_Transaction) { $obj_for_log = $transaction; if ($payment_method instanceof EE_Payment_Method) { $obj_for_log = EEM_Payment::instance()->get_one(array(array('TXN_ID' => $transaction->ID(), 'PMD_ID' => $payment_method->ID()), 'order_by' => array('PAY_timestamp' => 'desc'))); } } else { if ($payment_method instanceof EE_Payment) { $obj_for_log = $payment_method; } } $log = EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data received' => $_req_data), $obj_for_log); try { /** * @var EE_Payment $payment */ $payment = NULL; if ($transaction && $payment_method) { /** @type EE_Transaction $transaction */ $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction); /** @type EE_Payment_Method $payment_method */ $payment_method = EEM_Payment_Method::instance()->ensure_is_obj($payment_method); if ($payment_method->type_obj() instanceof EE_PMT_Base) { $payment = $payment_method->type_obj()->handle_ipn($_req_data, $transaction); $log->set_object($payment); } else { // not a payment EE_Error::add_error(sprintf(__('A valid payment method could not be determined due to a technical issue.%sPlease refresh your browser and try again or contact %s for assistance.', 'event_espresso'), '<br/>', EE_Registry::instance()->CFG->organization->get_pretty('email')), __FILE__, __FUNCTION__, __LINE__); } } else { //that's actually pretty ok. The IPN just wasn't able //to identify which transaction or payment method this was for // give all active payment methods a chance to claim it $active_payment_methods = EEM_Payment_Method::instance()->get_all_active(); foreach ($active_payment_methods as $active_payment_method) { try { $payment = $active_payment_method->type_obj()->handle_unclaimed_ipn($_req_data); $payment_method = $active_payment_method; EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment); break; } catch (EE_Error $e) { //that's fine- it apparently couldn't handle the IPN } } } // EEM_Payment_Log::instance()->log("got to 7",$transaction,$payment_method); if ($payment instanceof EE_Payment) { $payment->save(); // update the TXN $this->update_txn_based_on_payment($transaction, $payment, $update_txn, $separate_IPN_request); } else { //we couldn't find the payment for this IPN... let's try and log at least SOMETHING if ($payment_method) { EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $payment_method); } elseif ($transaction) { EEM_Change_Log::instance()->log(EEM_Change_Log::type_gateway, array('IPN data' => $_req_data), $transaction); } } return $payment; } catch (EE_Error $e) { do_action('AHEE__log', __FILE__, __FUNCTION__, sprintf(__('Error occurred while receiving IPN. Transaction: %1$s, req data: %2$s. The error was "%3$s"', 'event_espresso'), print_r($transaction, TRUE), print_r($_req_data, TRUE), $e->getMessage())); throw $e; } }
/** * Sets the initial payment method properties (including extra meta) * * @param EE_Payment_Method $payment_method * @return EE_Payment_Method * @throws \EE_Error */ public function initialize_payment_method($payment_method) { $pm_type_obj = $payment_method->type_obj(); $payment_method->set_description($pm_type_obj->default_description()); if (!$payment_method->button_url()) { $payment_method->set_button_url($pm_type_obj->default_button_url()); } //now add setup its default extra meta properties $extra_metas = $pm_type_obj->settings_form()->extra_meta_inputs(); if (!empty($extra_metas)) { //verify the payment method has an ID before adding extra meta if (!$payment_method->ID()) { $payment_method->save(); } foreach ($extra_metas as $meta_name => $input) { $payment_method->update_extra_meta($meta_name, $input->raw_value()); } } return $payment_method; }