/** * This method performs a financial transaction against this payment object. * * @throws jmsPaymentApprovalExpiredException * @throws jmsPaymentCommunicationException * @throws jmsPaymentFinancialException * @throws jmsPaymentFunctionNotSupportedException * @throws jmsPaymentTimeoutException * @throws jmsPaymentUserActionRequiredException * @param mixed $transaction One of the FinancialTransaction::TYPE_* constants, * or an instance of FinancialTransaction * @return void */ public final function performTransaction($transaction) { if (is_string($transaction)) { $transaction = FinancialTransaction::create($transaction, $this); } if (!$transaction instanceof FinancialTransaction) { throw new InvalidArgumentException(sprintf('"%s" must inherit from FinancialTransaction.', get_class($transaction))); } // for now, only transactions which are NEW or PENDING can be executed // against this payment if ($transaction->isInFinalState() === true) { throw new LogicException('The given transaction is already in a final state.'); } // check if this payment is in a final state. If so, no transactions can be // performed against it. if ($this->isInFinalState()) { throw new LogicException('This payment is in a final state; no transactions' . ' can be performed against it.'); } // verify that the transaction belongs to this payment if ($transaction->Payment !== $this) { throw new InvalidArgumentException('The given transaction already belongs to another payment.'); } $event = $this->dispatchEvent(new jmsPaymentTransactionEvent(self::EVENT_PRE_TRANSACTION, $this, $transaction)); if ($event->isPreventDefault() === true) { $transaction->state = FinancialTransaction::STATE_CANCELED; $transaction->save(); throw new jmsPaymentFinancialException('The transaction was prevented by one of the listeners.'); } $transaction->execute(); // TODO: Consider dispatching an event for transactions which do not // complete successfully. Maybe split into EVENT_POST_SUCCESSFUL_TRANSACTION // and EVENT_POST_UNSUCCESSFUL_TRANSACTION? $this->dispatchEvent(new jmsPaymentTransactionEvent(self::EVENT_POST_TRANSACTION, $this, $transaction)); }