protected function _get_data_for_context($context, EE_Registration $registration, $id) { //use the registration to get the transaction. $transaction = $registration->transaction(); //bail early if no transaction if (!$transaction instanceof EE_Transaction) { throw new EE_Error(__('The given registration does not have an associated transaction. Something is wrong.', 'event_espresso')); } $payment = !empty($id) ? EEM_Payment::instance()->get_one(array(array('PAY_ID' => $id, 'TXN_ID' => $transaction->ID()))) : 0; return array($transaction, $payment); }
/** * @since 4.6.0 */ public function test_get_payments_between_dates() { $timezone = new DateTimeZone('America/Toronto'); //set $now in the timezone being tested. $now = new DateTime('now', $timezone); $this->_setup_payments($now, $timezone); //test defaults $this->assertEquals(2, count(EEM_Payment::instance()->get_payments_made_between_dates())); //test including a date from past date for start date. $this->assertEquals(4, count(EEM_Payment::instance()->get_payments_made_between_dates($now->sub(new DateInterval('P2D'))->format('d/m/Y'), '', 'd/m/Y', 'America/Toronto'))); //test including a date from past date for end date. $this->assertEquals(4, count(EEM_Payment::instance()->get_payments_made_between_dates('', $now->format('d/m/Y'), 'd/m/Y', 'America/Toronto'))); //test including a date from upcoming date for start date $this->assertEquals(3, count(EEM_Payment::instance()->get_payments_made_between_dates($now->add(new DateInterval('P4D'))->format('d/m/Y'), '', 'd/m/Y', 'America/Toronto'))); //test including a date from upcoming date for end date $this->assertEquals(3, count(EEM_Payment::instance()->get_payments_made_between_dates('', $now->format('d/m/Y'), 'd/m/Y', 'America/Toronto'))); //test exception $this->setExpectedException('EE_Error'); EEM_Payment::instance()->get_payments_made_between_dates('trigger_exception'); }
public function test_just_approved() { $p1 = EE_Payment::new_instance(); $this->assertFalse($p1->just_approved()); $p1->set_status(EEM_Payment::status_id_approved); $this->assertTrue($p1->just_approved()); $id = $p1->save(); $this->assertTrue($p1->just_approved()); EEM_Payment::reset(); //now try with a payment that began as approved //note that we've reset EEM_payment so this is just like //it had been created on a previous request $p2 = EEM_Payment::instance()->get_one_by_ID($id); $this->assertFalse($p2->just_approved()); $p2->set_status(EEM_Payment::status_id_pending); $p2->save(); EEM_Payment::reset(); //again, pretend this next part is a subsequent request $p3 = EEM_Payment::instance()->get_one_by_ID($id); $this->assertFalse($p3->just_approved()); $p3->set_status(EEM_Payment::status_id_approved); $this->assertTrue($p3->just_approved()); }
/** * * @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; } }
/** * delete_payment * delete a payment or refund made towards a transaction * * @access public * @return void */ public function delete_payment() { $json_response_data = array('return_data' => FALSE); $PAY_ID = isset($this->_req_data['delete_txn_admin_payment'], $this->_req_data['delete_txn_admin_payment']['PAY_ID']) ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) : 0; if ($PAY_ID) { $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) ? $this->_req_data['delete_txn_reg_status_change'] : false; $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID); if ($payment instanceof EE_Payment) { $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment); /** @type EE_Transaction_Payments $transaction_payments */ $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); if ($transaction_payments->delete_payment_and_update_transaction($payment)) { EE_Error::add_success(__('The Payment was successfully deleted.', 'event_espresso')); $json_response_data['return_data'] = array('PAY_ID' => $PAY_ID, 'amount' => $payment->amount(), 'total_paid' => $payment->transaction()->paid(), 'txn_status' => $payment->transaction()->status_ID(), 'pay_status' => $payment->STS_ID(), 'delete_txn_reg_status_change' => $delete_txn_reg_status_change); //if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows. if (!empty($REG_IDs)) { EE_Registry::instance()->load_helper('Template'); $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs)))); foreach ($registrations as $registration) { $json_response_data['return_data']['registrations'][$registration->ID()] = array('owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()), 'paid' => $registration->pretty_paid()); } } if ($delete_txn_reg_status_change) { $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change; //MAKE sure we also add the delete_txn_req_status_change to the //$_REQUEST global because that's how messages will be looking //for it. $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change; $this->_process_registration_status_change($payment->transaction()); } } } else { EE_Error::add_error(__('Valid Payment data could not be retrieved from the database.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); } } else { $msg = __('A valid Payment ID was not received, therefore payment form data could not be loaded.', 'event_espresso'); EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); } $notices = EE_Error::get_notices(FALSE, FALSE, FALSE); echo json_encode(array_merge($json_response_data, $notices)); die; }
/** * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage * can be sent into this method and converted back into the format used for instantiating with this data handler. * * @param array $data * * @return array */ public static function convert_data_from_persistent_storage($data) { $prepped_data = array(0 => isset($data['Transaction']) ? EEM_Transaction::instance()->get_one_by_ID($data['Transaction']) : null, 1 => isset($data['Payment']) ? EEM_Payment::instance()->get_one_by_ID($data['Payment']) : null, 2 => isset($data['filter']) ? $data['filter'] : null); return $prepped_data; }
/** * recalculate_total_payments_for_transaction * * @access public * @param EE_Transaction $transaction * @param string $payment_status One of EEM_Payment's statuses, like 'PAP' (Approved). * By default, searches for approved payments * @return float|false float on success, false on fail * @throws \EE_Error */ public function recalculate_total_payments_for_transaction(EE_Transaction $transaction, $payment_status = EEM_Payment::status_id_approved) { // verify transaction if (!$transaction instanceof EE_Transaction) { EE_Error::add_error(__('Please provide a valid EE_Transaction object.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); return false; } // ensure Payment model is loaded EE_Registry::instance()->load_model('Payment'); // calls EEM_Base::sum() return EEM_Payment::instance()->sum(array(array('TXN_ID' => $transaction->ID(), 'STS_ID' => $payment_status)), 'PAY_amount'); }
/** * @group 7151 */ function test_fresh_entity_map_with() { $p = $this->new_model_obj_with_dependencies('Payment', array('PAY_amount' => 25)); $p->save(); $this->assertEquals($p, EEM_Payment::instance()->get_from_entity_map($p->ID())); //now purposefully make a naughty payment which isn't in the entity map $p2 = clone $p; $this->assertFalse($p2->in_entity_map()); //make the two EE_Payments diverge $p2->set('PAY_amount', 99); $t = EE_Transaction::new_instance(); $p2->cache('Transaction', $t); $this->assertEquals(25, $p->get('PAY_amount')); $this->assertEquals(99, $p2->get('PAY_amount')); $this->assertNotEquals($p->get_all_from_cache('Transaction'), $p2->get_all_from_cache('Transaction')); //now update the payment in the entity map with the other EEM_Payment::instance()->refresh_entity_map_with($p->ID(), $p2); $this->assertEquals(99, $p->get('PAY_amount')); //make sure p hasn't changed into p2. that's not what we wanted to do... $this->assertFalse($p2 === $p); //We wanted to just UPDATE p with p2's values $this->assertEquals($p, EEM_Payment::instance()->get_from_entity_map($p->ID())); //and make sure p's cache was updated to be the same as p2's $this->assertEquals($p2->get_all_from_cache('Transaction'), $p->get_all_from_cache('Transaction')); }
/** * test_build_payment_json_response_for_payment * @since 4.8 * @group 8620 */ public function test_build_payment_json_response_for_payment() { $this->_admin_page = new Transactions_Admin_Page_Mock(); $this->_setup_standard_transaction_and_payment(40.0, 4, 15.0); // need to make sure relation is set between payment and payment method $this->_payment->_add_relation_to($this->_payment_method(), 'Payment_Method'); $registrations = $this->_get_x_number_of_registrations_from_transaction($this->_transaction, 1); $this->_apply_payment_to_registrations($registrations); $json_response_data = $this->_admin_page->build_payment_json_response($this->_payment); $pay_status = EEM_Payment::instance()->status_array(true); $this->assertEquals(15.0, $json_response_data['amount']); // total paid is still zero, because we haven't actually updated the TXN with the payment info $this->assertEquals(0, $json_response_data['total_paid']); $this->assertEquals(EEM_Transaction::incomplete_status_code, $json_response_data['txn_status']); $this->assertEquals(EEM_Payment::status_id_approved, $json_response_data['pay_status']); $this->assertEquals(EEM_Payment::status_id_approved, $json_response_data['STS_ID']); $this->assertEquals($pay_status[EEM_Payment::status_id_approved], $json_response_data['status']); $this->assertEquals($this->_payment->ID(), $json_response_data['PAY_ID']); $this->assertEquals($this->_payment->timestamp('Y-m-d', 'h:i a'), $json_response_data['date']); $this->assertEquals(strtoupper($this->_payment->source()), $json_response_data['method']); $this->assertEquals($this->_payment_method()->ID(), $json_response_data['PM_ID']); $this->assertEquals($this->_payment_method()->admin_name(), $json_response_data['gateway']); $this->assertEquals($this->_payment->gateway_response(), $json_response_data['gateway_response']); $this->assertEquals($this->_payment->txn_id_chq_nmbr(), $json_response_data['txn_id_chq_nmbr']); $this->assertEquals($this->_payment->po_number(), $json_response_data['po_number']); $this->assertEquals($this->_payment->extra_accntng(), $json_response_data['extra_accntng']); $this->assertEquals($this->_payment->extra_accntng(), $json_response_data['extra_accntng']); // will validate $json_response_data[ 'registrations' ] in test_registration_payment_data_array() }
/** * delete a payment or refund made towards a transaction * @access public * @return void */ public function delete_payment() { $return_data = array(); if (isset($this->_req_data['delete_txn_admin_payment'])) { $pymt = $this->_req_data['delete_txn_admin_payment']; if ($payment = EEM_Payment::instance()->get_one_by_ID($pymt['PAY_ID'])) { if ($transaction = EEM_Payment::instance()->delete_by_ID($payment->ID())) { $return_data = array('amount' => $payment->amount(), 'total_paid' => $transaction->paid(), 'txn_status' => $transaction->status_ID(), 'pay_status' => $payment->STS_ID(), 'PAY_ID' => $pymt['PAY_ID'], 'delete_txn_reg_status_change' => $this->_req_data['delete_txn_reg_status_change']); } } if (isset($this->_req_data['delete_txn_reg_status_change'])) { $this->_req_data['txn_reg_status_change'] = $this->_req_data['delete_txn_reg_status_change']; $_REQUEST['txn_reg_status_change'] = $this->_req_data['delete_txn_reg_status_change']; $this->_process_registration_status_change($transaction); } } else { $msg = __('An error occurred. The payment form data could not be loaded.', 'event_espresso'); EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); $return_data = FALSE; } $notices = EE_Error::get_notices(FALSE, FALSE, FALSE); echo json_encode(array('return_data' => $return_data, 'success' => $notices['success'], 'errors' => $notices['errors'])); die; }
protected function __construct(EEM_Gateways &$model) { do_action('AHEE_log', __FILE__, __FUNCTION__, ''); //echo '<h4>$this->_gateway_name : ' . $this->_gateway_name . ' <br /><span style="font-size:10px;font-weight:normal;">' . __FILE__ . '<br />line no: ' . __LINE__ . '</span></h4>'; if (!defined('GATEWAYS_ADMIN_URL')) { define('GATEWAYS_ADMIN_URL', admin_url('admin.php?page=espresso_payment_settings')); } $this->_EEM_Gateways = $model; require_once EE_MODELS . 'EEM_Transaction.model.php'; require_once EE_CLASSES . 'EE_Transaction.class.php'; $this->_TXN = EEM_Transaction::instance(); require_once EE_MODELS . 'EEM_Payment.model.php'; require_once EE_CLASSES . 'EE_Payment.class.php'; $this->_PAY = EEM_Payment::instance(); require_once EE_MODELS . 'EEM_Registration.model.php'; require_once EE_CLASSES . 'EE_Registration.class.php'; $this->_REG = EEM_Registration::instance(); if (!$this->_btn_img) { $this->_btn_img = EE_GATEWAYS_URL . $this->_gateway_name . DS . 'lib' . DS . $this->_button_base; } $this->_set_default_properties(); $this->_handle_payment_settings(); if (is_admin() && !empty($_GET['page']) && $_GET['page'] == 'espresso_payment_settings') { $this->_gateways_admin(); } else { $this->_gateways_frontend(); } //load formatter helper and form fields helper EE_Registry::instance()->load_helper('Formatter'); EE_Registry::instance()->load_helper('Form_Fields'); }
/** * update_transaction_with_payment * * loops through the self::$_abandoned_transactions array * and attempts to finalize any TXNs that have not been completed * but have had their sessions expired, most likely due to a user not * returning from an off-site payment gateway * * @throws \EE_Error */ public static function update_transaction_with_payment() { do_action('AHEE_log', __CLASS__, __FUNCTION__); // are there any TXNs that need cleaning up ? if (!empty(self::$_update_transactions_with_payment)) { /** @type EE_Payment_Processor $payment_processor */ $payment_processor = EE_Registry::instance()->load_core('Payment_Processor'); // set revisit flag for payment processor $payment_processor->set_revisit(false); // load EEM_Transaction EE_Registry::instance()->load_model('Transaction'); foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) { // reschedule the cron if we can't hit the db right now if (!EE_Maintenance_Mode::instance()->models_can_query()) { // reset cron job for updating the TXN EE_Cron_Tasks::schedule_update_transaction_with_payment(time() + EE_Cron_Tasks::reschedule_timeout, $TXN_ID, $PAY_ID); continue; } $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID); // verify transaction if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) { // now try to update the TXN with any payments $payment_processor->update_txn_based_on_payment($transaction, $payment, true, true); } unset(self::$_update_transactions_with_payment[$TXN_ID]); } } }
/** * delete_payment * delete a payment or refund made towards a transaction * * @access public * @return void */ public function delete_payment() { $json_response_data = array('return_data' => FALSE); $PAY_ID = isset($this->_req_data['delete_txn_admin_payment'], $this->_req_data['delete_txn_admin_payment']['PAY_ID']) ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) : 0; if ($PAY_ID) { $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) ? $this->_req_data['delete_txn_reg_status_change'] : false; $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID); if ($payment instanceof EE_Payment) { /** @type EE_Transaction_Payments $transaction_payments */ $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); if ($transaction_payments->delete_payment_and_update_transaction($payment)) { EE_Error::add_success(__('The Payment was successfully deleted.', 'event_espresso')); $json_response_data['return_data'] = array('PAY_ID' => $PAY_ID, 'amount' => $payment->amount(), 'total_paid' => $payment->transaction()->paid(), 'txn_status' => $payment->transaction()->status_ID(), 'pay_status' => $payment->STS_ID(), 'delete_txn_reg_status_change' => $delete_txn_reg_status_change); if ($delete_txn_reg_status_change) { $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change; //MAKE sure we also add the delete_txn_req_status_change to the //$_REQUEST global because that's how messages will be looking //for it. $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change; $this->_process_registration_status_change($payment->transaction()); } } } else { EE_Error::add_error(__('Valid Payment data could not be retrieved from the database.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); } } else { $msg = __('A valid Payment ID was not received, therefore payment form data could not be loaded.', 'event_espresso'); EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); } $notices = EE_Error::get_notices(FALSE, FALSE, FALSE); echo json_encode(array_merge($json_response_data, $notices)); die; }
/** * return the payment object for a given payment ID * * @since 4.3.0 * * @param int $PMT_ID the payment id for the payment to attempt to retrieve * * @return mixed null|EE_Payment */ public function get_object_by_id($PMT_ID) { return EEM_Payment::instance()->get_one_by_ID($PMT_ID); }
public function test_process_payment__offsite__declined_then_approved() { /** @type EE_Payment_Method $pm */ $pm = $this->new_model_obj_with_dependencies('Payment_Method', array('PMD_type' => 'Mock_Offsite')); $transaction = $this->_new_typical_transaction(); global $wp_actions; EE_Registry::instance()->load_helper('Array'); $successful_payment_actions = EEH_Array::is_set($wp_actions, 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', 0); /** @type EE_Payment_Processor $payment_processor */ $payment_processor = EE_Registry::instance()->load_core('Payment_Processor'); $payment = $payment_processor->process_payment($pm, $transaction, NULL, NULL, 'success', 'CART', TRUE, TRUE); $this->assertInstanceOf('EE_Payment', $payment); //verify it's already been saved $this->assertNotEquals(0, $payment->ID()); //assert that the payment still has its default status $this->assertEquals(EEM_Payment::instance()->field_settings_for('STS_ID')->get_default_value(), $payment->status()); $this->assertEquals(EEM_Payment::instance()->field_settings_for('STS_ID')->get_default_value(), $this->_get_payment_status_in_db($payment)); //assert that the we haven't notified of successful payment JUST yet... $this->assertEquals($successful_payment_actions, EEH_Array::is_set($wp_actions, 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', 0)); //PENDING IPN $payment = $payment_processor->process_ipn(array('status' => EEM_Payment::status_id_pending, 'gateway_txn_id' => $payment->txn_id_chq_nmbr()), $transaction, $pm); $this->assertEquals(EEM_Payment::status_id_pending, $payment->status()); $this->assertEquals(EEM_Payment::status_id_pending, $this->_get_payment_status_in_db($payment)); //and the payment-approved action should have NOT been triggered $this->assertEquals($successful_payment_actions, EEH_Array::is_set($wp_actions, 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', 0)); //APPROVED IPN $payment = $payment_processor->process_ipn(array('status' => EEM_Payment::status_id_approved, 'gateway_txn_id' => $payment->txn_id_chq_nmbr()), $transaction, $pm); //payment should be what the gateway set it to be, which was approved $this->assertEquals(EEM_Payment::status_id_approved, $payment->status()); $this->assertEquals(EEM_Payment::status_id_approved, $this->_get_payment_status_in_db($payment)); //and the payment-approved action should have been triggered $this->assertEquals($successful_payment_actions + 1, EEH_Array::is_set($wp_actions, 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', 0)); //DUPLICATE SUCCESS IPN //for this, we need to reset payment model so we fetch a NEW payment object, instead of reusing the old //and because the payment method caches a payment method type which caches a gateway which caches the payment model, //we also need to reset the payment method EEM_Payment::reset(); $pm = EEM_Payment_Method::reset()->get_one_by_ID($pm->ID()); $payment = $payment_processor->process_ipn(array('status' => EEM_Payment::status_id_approved, 'gateway_txn_id' => $payment->txn_id_chq_nmbr()), $transaction, $pm); //payment should be what the gateway set it to be, which was failed $this->assertEquals(EEM_Payment::status_id_approved, $payment->status()); //and the payment-approved action should have NOT been triggered this time because it's a duplicate $this->assertEquals($successful_payment_actions + 1, EEH_Array::is_set($wp_actions, 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', 0)); }
/** * Export a custom CSV of registration info including: A bunch of the reg fields, the time of the event, the price name, * and the questions associated with the registrations * @param int $event_id */ function report_registrations_for_event($event_id = NULL) { $reg_fields_to_include = array('TXN_ID', 'ATT_ID', 'REG_ID', 'REG_date', 'REG_code', 'REG_count', 'REG_final_price'); $att_fields_to_include = array('ATT_fname', 'ATT_lname', 'ATT_email', 'ATT_address', 'ATT_address2', 'ATT_city', 'STA_ID', 'CNT_ISO', 'ATT_zip', 'ATT_phone'); $registrations_csv_ready_array = array(); $reg_model = EE_Registry::instance()->load_model('Registration'); $query_params = apply_filters('FHEE__EE_Export__report_registration_for_event', array(array('OR' => array('Transaction.STS_ID' => array('NOT IN', array(EEM_Transaction::failed_status_code, EEM_Transaction::abandoned_status_code)), 'STS_ID' => EEM_Registration::status_id_approved), 'Ticket.TKT_deleted' => array('IN', array(true, false))), 'order_by' => array('Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'), 'force_join' => array('Transaction', 'Ticket', 'Attendee'), 'caps' => EEM_Base::caps_read_admin), $event_id); if ($event_id) { $query_params[0]['EVT_ID'] = $event_id; } else { $query_params['force_join'][] = 'Event'; } $registration_rows = $reg_model->get_all_wpdb_results($query_params); //get all questions which relate to someone in this group $registration_ids = array(); foreach ($registration_rows as $reg_row) { $registration_ids[] = intval($reg_row['Registration.REG_ID']); } // EEM_Question::instance()->show_next_x_db_queries(); $questions_for_these_regs_rows = EEM_Question::instance()->get_all_wpdb_results(array(array('Answer.REG_ID' => array('IN', $registration_ids)))); foreach ($registration_rows as $reg_row) { if (is_array($reg_row)) { $reg_csv_array = array(); if (!$event_id) { //get the event's name and Id $reg_csv_array[__('Event', 'event_espresso')] = sprintf(__('%1$s (%2$s)', 'event_espresso'), $this->_prepare_value_from_db_for_display(EEM_Event::instance(), 'EVT_name', $reg_row['Event_CPT.post_title']), $reg_row['Event_CPT.ID']); } $is_primary_reg = $reg_row['Registration.REG_count'] == '1' ? true : false; /*@var $reg_row EE_Registration */ foreach ($reg_fields_to_include as $field_name) { $field = $reg_model->field_settings_for($field_name); if ($field_name == 'REG_final_price') { $value = $this->_prepare_value_from_db_for_display($reg_model, $field_name, $reg_row['Registration.REG_final_price'], 'localized_float'); } elseif ($field_name == 'REG_count') { $value = sprintf(__('%s of %s', 'event_espresso'), $this->_prepare_value_from_db_for_display($reg_model, 'REG_count', $reg_row['Registration.REG_count']), $this->_prepare_value_from_db_for_display($reg_model, 'REG_group_size', $reg_row['Registration.REG_group_size'])); } elseif ($field_name == 'REG_date') { $value = $this->_prepare_value_from_db_for_display($reg_model, $field_name, $reg_row['Registration.REG_date'], 'no_html'); } else { $value = $this->_prepare_value_from_db_for_display($reg_model, $field_name, $reg_row[$field->get_qualified_column()]); } $reg_csv_array[$this->_get_column_name_for_field($field)] = $value; if ($field_name == 'REG_final_price') { //add a column named Currency after the final price $reg_csv_array[__("Currency", "event_espresso")] = EE_Config::instance()->currency->code; } } //get pretty status $stati = EEM_Status::instance()->localized_status(array($reg_row['Registration.STS_ID'] => __('unknown', 'event_espresso'), $reg_row['TransactionTable.STS_ID'] => __('unknown', 'event_espresso')), FALSE, 'sentence'); $reg_csv_array[__("Registration Status", 'event_espresso')] = $stati[$reg_row['Registration.STS_ID']]; //get pretty trnasaction status $reg_csv_array[__("Transaction Status", 'event_espresso')] = $stati[$reg_row['TransactionTable.STS_ID']]; $reg_csv_array[__('Transaction Amount Due', 'event_espresso')] = $is_primary_reg ? $this->_prepare_value_from_db_for_display(EEM_Transaction::instance(), 'TXN_total', $reg_row['TransactionTable.TXN_total'], 'localized_float') : '0.00'; $reg_csv_array[__('Amount Paid', 'event_espresso')] = $is_primary_reg ? $this->_prepare_value_from_db_for_display(EEM_Transaction::instance(), 'TXN_paid', $reg_row['TransactionTable.TXN_paid'], 'localized_float') : '0.00'; $payment_methods = array(); $gateway_txn_ids_etc = array(); $payment_times = array(); if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) { $payments_info = EEM_Payment::instance()->get_all_wpdb_results(array(array('TXN_ID' => $reg_row['TransactionTable.TXN_ID'], 'STS_ID' => EEM_Payment::status_id_approved), 'force_join' => array('Payment_Method')), ARRAY_A, 'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time'); foreach ($payments_info as $payment_method_and_gateway_txn_id) { $payment_methods[] = isset($payment_method_and_gateway_txn_id['name']) ? $payment_method_and_gateway_txn_id['name'] : __('Unknown', 'event_espresso'); $gateway_txn_ids_etc[] = isset($payment_method_and_gateway_txn_id['gateway_txn_id']) ? $payment_method_and_gateway_txn_id['gateway_txn_id'] : ''; $payment_times[] = isset($payment_method_and_gateway_txn_id['payment_time']) ? $payment_method_and_gateway_txn_id['payment_time'] : ''; } } $reg_csv_array[__('Payment Date(s)', 'event_espresso')] = implode(',', $payment_times); $reg_csv_array[__('Payment Method(s)', 'event_espresso')] = implode(",", $payment_methods); $reg_csv_array[__('Gateway Transaction ID(s)', 'event_espresso')] = implode(',', $gateway_txn_ids_etc); //get whether or not the user has checked in $reg_csv_array[__("Check-Ins", "event_espresso")] = $reg_model->count_related($reg_row['Registration.REG_ID'], 'Checkin'); //get ticket of registration and its price $ticket_model = EE_Registry::instance()->load_model('Ticket'); if ($reg_row['Ticket.TKT_ID']) { $ticket_name = $this->_prepare_value_from_db_for_display($ticket_model, 'TKT_name', $reg_row['Ticket.TKT_name']); $datetimes_strings = array(); foreach (EEM_Datetime::instance()->get_all_wpdb_results(array(array('Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']), 'order_by' => array('DTT_EVT_start' => 'ASC'), 'default_where_conditions' => 'none')) as $datetime) { $datetimes_strings[] = $this->_prepare_value_from_db_for_display(EEM_Datetime::instance(), 'DTT_EVT_start', $datetime['Datetime.DTT_EVT_start']); } } else { $ticket_name = __('Unknown', 'event_espresso'); $datetimes_strings = array(__('Unknown', 'event_espresso')); } $reg_csv_array[$ticket_model->field_settings_for('TKT_name')->get_nicename()] = $ticket_name; $reg_csv_array[__("Datetimes of Ticket", "event_espresso")] = implode(", ", $datetimes_strings); //get datetime(s) of registration //add attendee columns foreach ($att_fields_to_include as $att_field_name) { $field_obj = EEM_Attendee::instance()->field_settings_for($att_field_name); if ($reg_row['Attendee_CPT.ID']) { if ($att_field_name == 'STA_ID') { $value = EEM_State::instance()->get_var(array(array('STA_ID' => $reg_row['Attendee_Meta.STA_ID'])), 'STA_name'); } elseif ($att_field_name == 'CNT_ISO') { $value = EEM_Country::instance()->get_var(array(array('CNT_ISO' => $reg_row['Attendee_Meta.CNT_ISO'])), 'CNT_name'); } else { $value = $this->_prepare_value_from_db_for_display(EEM_Attendee::instance(), $att_field_name, $reg_row[$field_obj->get_qualified_column()]); } } else { $value = ''; } $reg_csv_array[$this->_get_column_name_for_field($field_obj)] = $value; } //make sure each registration has the same questions in the same order foreach ($questions_for_these_regs_rows as $question_row) { if (!isset($reg_csv_array[$question_row['Question.QST_admin_label']])) { $reg_csv_array[$question_row['Question.QST_admin_label']] = null; } } //now fill out the questions THEY answered foreach (EEM_Answer::instance()->get_all_wpdb_results(array(array('REG_ID' => $reg_row['Registration.REG_ID']), 'force_join' => array('Question'))) as $answer_row) { /* @var $answer EE_Answer */ if ($answer_row['Question.QST_ID']) { $question_label = $this->_prepare_value_from_db_for_display(EEM_Question::instance(), 'QST_admin_label', $answer_row['Question.QST_admin_label']); } else { $question_label = sprintf(__('Question $s', 'event_espresso'), $answer_row['Answer.QST_ID']); } if (isset($answer_row['Question.QST_type']) && $answer_row['Question.QST_type'] == EEM_Question::QST_type_state) { $reg_csv_array[$question_label] = EEM_State::instance()->get_state_name_by_ID($answer_row['Answer.ANS_value']); } else { $reg_csv_array[$question_label] = $this->_prepare_value_from_db_for_display(EEM_Answer::instance(), 'ANS_value', $answer_row['Answer.ANS_value']); } } $registrations_csv_ready_array[] = apply_filters('FHEE__EE_Export__report_registrations__reg_csv_array', $reg_csv_array, $reg_row); } } //if we couldn't export anything, we want to at least show the column headers if (empty($registrations_csv_ready_array)) { $reg_csv_array = array(); $model_and_fields_to_include = array('Registration' => $reg_fields_to_include, 'Attendee' => $att_fields_to_include); foreach ($model_and_fields_to_include as $model_name => $field_list) { $model = EE_Registry::instance()->load_model($model_name); foreach ($field_list as $field_name) { $field = $model->field_settings_for($field_name); $reg_csv_array[$this->_get_column_name_for_field($field)] = null; //$registration->get($field->get_name()); } } $registrations_csv_ready_array[] = $reg_csv_array; } if ($event_id) { $event_slug = EEM_Event::instance()->get_var(array(array('EVT_ID' => $event_id)), 'EVT_slug'); if (!$event_slug) { $event_slug = __('unknown', 'event_espresso'); } } else { $event_slug = __('all', 'event_espresso'); } $filename = sprintf("registrations-for-%s", $event_slug); $handle = $this->EE_CSV->begin_sending_csv($filename); $this->EE_CSV->write_data_array_to_csv($handle, $registrations_csv_ready_array); $this->EE_CSV->end_sending_csv($handle); }
/** * delete_payment * delete a payment or refund made towards a transaction * * @access public * @return void */ public function delete_payment() { $json_response_data = array('return_data' => FALSE); $PAY_ID = isset($this->_req_data['delete_txn_admin_payment'], $this->_req_data['delete_txn_admin_payment']['PAY_ID']) ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) : 0; if ($PAY_ID) { $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) ? $this->_req_data['delete_txn_reg_status_change'] : false; $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID); if ($payment instanceof EE_Payment) { $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment); /** @type EE_Transaction_Payments $transaction_payments */ $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); if ($transaction_payments->delete_payment_and_update_transaction($payment)) { $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs, $delete_txn_reg_status_change); if ($delete_txn_reg_status_change) { $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change; //MAKE sure we also add the delete_txn_req_status_change to the //$_REQUEST global because that's how messages will be looking for it. $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change; $this->_maybe_send_notifications(); $this->_process_registration_status_change($payment->transaction(), $REG_IDs); } } } else { EE_Error::add_error(__('Valid Payment data could not be retrieved from the database.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); } } else { EE_Error::add_error(__('A valid Payment ID was not received, therefore payment form data could not be loaded.', 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); } $notices = EE_Error::get_notices(false, false, false); $this->_template_args = array('data' => $json_response_data, 'success' => $notices['success'], 'error' => $notices['errors'], 'attention' => $notices['attention']); $this->_return_json(); }