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));
 }