Spamworldpro Mini Shell
Spamworldpro


Server : Apache
System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64
User : corals ( 1002)
PHP Version : 7.4.33
Disable Function : exec,passthru,shell_exec,system
Directory :  /home/corals/old/lib/internal/Customweb/Payment/Authorization/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //home/corals/old/lib/internal/Customweb/Payment/Authorization/DefaultTransaction.php
<?php
/**
  * You are allowed to use this API in your web application.
 *
 * Copyright (C) 2018 by customweb GmbH
 *
 * This program is licenced under the customweb software licence. With the
 * purchase or the installation of the software in your application you
 * accept the licence agreement. The allowed usage is outlined in the
 * customweb software licence which can be found under
 * http://www.sellxed.com/en/software-license-agreement
 *
 * Any modification or distribution is strictly forbidden. The license
 * grants you the installation in one application. For multiuse you will need
 * to purchase further licences at http://www.sellxed.com/shop.
 *
 * See the customweb software licence agreement for more details.
 *
 */


/**
 * This is a default implemenation of a transaction. In most cases this class
 * should be usable by the implementors.
 *
 * @author Thomas Hunziker
 *
 */
class Customweb_Payment_Authorization_DefaultTransaction implements Customweb_Payment_Authorization_ITransaction {

	/**
	 * @var Customweb_Payment_Authorization_ITransactionContext
	 */
	private $transactionContext;

	private $transactionId;

	private $paymentId;

	private $authorizationAmount;

	private $currencyCode;

	private $historyItems = array();

	private $alias = null;

	private $aliasForDisplay = null;

	private $authorizationMethod = null;

	/**
	 * @var boolean
	 */
	private $authorized = false;

	/**
	 * @var boolean
	 */
	private $authorizationFailed = false;

	/**
	 * @var boolean
	 */
	private $authorizationUncertain = false;

	/**
	 * @var boolean
	 */
	private $captured = false;

	/**
	 * @var boolean
	 */
	private $cancelled = false;

	/**
	 * List of parameters sent by the payment service provider for the
	 * authorization confirmation.
	 *
	 * @var array
	 */
	private $parameters = array();

	private $capturedAmount = 0;

	private $refundedAmount = 0;

	private $captureClosed = false;

	private $refundClosed = false;

	private $refunds = array();

	private $captures = array();

	private $cancels = array();

	private $errorMessages = array();

	/**
	 * @var DateTime
	 */
	private $createdOn = null;

	/**
	 * @var boolean
	 */
	private $paid = false;
	
	/**
	 * @var Customweb_Date_DateTime
	 */
	private $updateExecutionDate = null;
	
	/**
	 * @var string
	 */
	private $securityToken = null;
	
	/**
	 * @var boolean
	 */
	private $liveTransaction = true;
	
	private $versionNumber;
	
	/**
	 * This flag indicates that the transaction was marked as paid than it was marked 
	 * as uncertain. Hence we set the transaction as unpaid, but we remember this flag and 
	 * when the transaction is set as certain, we swich the paid flag again.
	 * 
	 * @var boolean
	 */
	private $markedAsPaidBeforeUncertain = null;

	const STATE_3D_SECURE_NOT_APPLICABLE = '3d-secure-not-applicable';
	const STATE_3D_SECURE_FAILED = '3d-secure-failed';
	const STATE_3D_SECURE_SUCCESS = '3d-secure-success';

	private $state3DSecure = self::STATE_3D_SECURE_NOT_APPLICABLE;
	
	private $externalTransactionId;
	
	private $customerRefusingToPay = false;
	private $uncertainTransactionFinallyDeclined = false;
	

	public function __construct(Customweb_Payment_Authorization_ITransactionContext $transactionContext) {
		$this->transactionContext = $transactionContext;
		$this->transactionId = $transactionContext->getTransactionId();
		$this->authorizationAmount = $transactionContext->getOrderContext()->getOrderAmountInDecimals();
		$this->currencyCode = $transactionContext->getOrderContext()->getCurrencyCode();
		$this->createdOn = new Customweb_Date_DateTime();
		$this->externalTransactionId = $this->generateExternalId();
		$this->securityToken = Customweb_Core_Util_Rand::getRandomString(64);
		
		$skus = array();
		foreach($this->getTransactionContext()->getOrderContext()->getInvoiceItems() as	$item) {
			if (isset($skus[$item->getSku()])) {
				throw new Exception("Could not start transaction because there are multiple line items with the same SKU.");
			}
			$skus[$item->getSku()] = $item->getSku();
		}
	}
	
	/**
	 * This method generates the external transaction id according to the transaction context.
	 * 
	 * @return string
	 */
	protected final function generateExternalId() {
		$orderId = $this->getTransactionContext()->getOrderId();
		$transactionId = $this->getTransactionContext()->getTransactionId();
		
		if (!empty($orderId) && $this->transactionContext->isOrderIdUnique()) {
			return $orderId;
		}
		else if (!empty($orderId)) {
			return $orderId . '_' . $transactionId;
		}
		else {
			return $transactionId;
		}
	}
	
	public function getExternalTransactionId() {
		if ($this->externalTransactionId === null) {
			$this->externalTransactionId = $this->generateExternalId();
		}
		
		return $this->externalTransactionId;
	}


	/**
	 * The date at which the transaction was created on.
	 * 
	 * @return DateTime
	 */
	public function getCreatedOn() {
		return $this->createdOn;
	}
	
	/**
	 * @return Customweb_Payment_Authorization_ITransactionContext
	 */
	public function getTransactionContext() {
		return $this->transactionContext;
	}

	public function getTransactionId() {
		return $this->transactionId;
	}

	public function getPaymentId() {
		return $this->paymentId;
	}

	/**
	 * This method sets the paymentID.
	 *
	 * @param String $paymentId
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setPaymentId($paymentId) {
		$this->paymentId = $paymentId;
		return $this;
	}

	public function getAuthorizationMethod() {
		return $this->authorizationMethod;
	}

	/**
	 * This method sets the authorization method.
	 *
	 * @param string $method Method name
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setAuthorizationMethod($method) {
		$this->authorizationMethod = $method;
		return $this;
	}

	public function getAuthorizationAmount() {
		return $this->authorizationAmount;
	}

	public function getCurrencyCode() {
		return $this->currencyCode;
	}

	/**
	 * @return Customweb_Payment_Authorization_IPaymentMethod
	 */
	public function getPaymentMethod() {
		return $this->transactionContext->getOrderContext()->getPaymentMethod();
	}

	public function isAuthorizationFailed() {
		return $this->authorizationFailed;
	}

	public function isAuthorizationUncertain() {
		return $this->authorizationUncertain;
	}

	public function getHistoryItems() {
		return $this->historyItems;
	}

	public function getErrorMessages(){
		return $this->errorMessages;
	}

	/**
	 * Add a message to the list of error messages.
	 *
	 * @param Customweb_Payment_Authorization_IErrorMessage $message
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 * @deprecated Use instead addErrorMessage()
	 */
	public function addErrorMessages($message){
		return $this->addErrorMessage($message);
	}

	/**
	 * Add a message to the list of error messages.
	 *
	 * @param Customweb_Payment_Authorization_IErrorMessage $message
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function addErrorMessage($message){

		if ($message instanceof Customweb_Payment_Authorization_IErrorMessage) {
			$this->errorMessages[] = $message;
		}
		else {
			$this->errorMessages[] = new Customweb_Payment_Authorization_ErrorMessage($message);
		}

		return $this;
	}

	/**
	 *
	 * @param Customweb_Payment_Authorization_ITransactionHistoryItem $item
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function addHistoryItem(Customweb_Payment_Authorization_ITransactionHistoryItem $item) {
		$this->historyItems[] = $item;
		return $this;
	}

	/**
	 * (non-PHPdoc)
	 * @see Customweb_Payment_Authorization_ITransaction::isAuthorized()
	 */
	public function isAuthorized() {
		return $this->authorized;
	}

	/**
	 *
	 * @param Customweb_I18n_LocalizableString | Customweb_Payment_Authorization_ErrorMessage $reason
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setAuthorizationFailed($reason) {
		if (is_string($reason)) {
			$reason = new Customweb_I18n_LocalizableString($reason);
		}
		if ($this->isAuthorized()) {
			throw new Exception(Customweb_I18n_Translation::__("A authorized transaction cannot be marked as failed."));
		}

		if ($this->isCancelled()) {
			throw new Exception(Customweb_I18n_Translation::__("A cancelled transaction cannot  be marked as failed."));
		}

		if ($this->isCaptured()) {
			throw new Exception(Customweb_I18n_Translation::__("A captured transaction cannot  be marked as failed."));
		}
		if ($reason instanceof Customweb_Payment_Authorization_IErrorMessage) {
			$this->addErrorMessage($reason);
		}
		else {
			$this->addErrorMessage(new Customweb_Payment_Authorization_ErrorMessage($reason));
		}

		$this->createHistoryItem(
				$reason,
				Customweb_Payment_Authorization_ITransactionHistoryItem::ACTION_AUTHORIZATION
		);
		$this->authorizationFailed = true;

		return $this;
	}

	/**
	 * This method sets an authorization to uncertain. A uncertain payment is one
	 * that may be successful, but it is not absolutly for sure.
	 *
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setAuthorizationUncertain($authorizationUncertain = true) {
		$this->authorizationUncertain = $authorizationUncertain;
		if ($authorizationUncertain && $this->isPaid()) {
			$this->setPaid(false);
			$this->markedAsPaidBeforeUncertain = true;
		}
		else if ($authorizationUncertain === false && $this->markedAsPaidBeforeUncertain) {
			$this->setPaid(true);
		}
		return $this;
	}

	/**
	 * This methdo runs a authorize action, but without change the state.
	 *
	 * @param string $additionalInformation
	 * @param boolean $paid
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function authorizeDry($additionalInformation = '', $paid = true) {
		if ($this->isAuthorizationFailed()) {
			throw new Exception(Customweb_I18n_Translation::__("A failed authorization cannot be authorized."));
		}

		if ($this->isAuthorized()) {
			throw new Exception(Customweb_I18n_Translation::__("A authorized transaction cannot be authorized again."));
		}

		if ($this->isCancelled()) {
			throw new Exception(Customweb_I18n_Translation::__("A cancelled transaction cannot be authorized."));
		}

		if ($this->isCaptured()) {
			throw new Exception(Customweb_I18n_Translation::__("A captured transaction cannot be authorized."));
		}
		return $this;
	}

	/**
	 * This method authorize this transaction.
	 *
	 * @param string $additionalInformation [optional] A message which gives more information about the authorization.
	 * @param boolean $paid
	 * @throws Exception In case some constraints are not fulfield.
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function authorize($additionalInformation = '', $paid = true) {
		$this->authorizeDry($additionalInformation, $paid);

		$historyMessage = Customweb_I18n_Translation::__(
			"The amount of !amount is authorized.",
			array('!amount' => Customweb_Util_Currency::formatAmount($this->getAuthorizationAmount(), $this->getCurrencyCode()))
		);
		if (!empty($additionalInformation)) {
			$historyMessage .= ' (' . $additionalInformation . ')';
		}

		$this->createHistoryItem(
				$historyMessage,
				Customweb_Payment_Authorization_ITransactionHistoryItem::ACTION_AUTHORIZATION
		);

		if ($paid) {
			$this->setPaid();
		}

		$this->authorized = true;
		return $this;
	}

	public function isCaptured() {
		return $this->captured;
	}

	/**
	 * This method sets the transaction as captured. The whole authorized amount is set as
	 * captured.
	 *
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_ITransactionCapture
	 */
	public function capture($additionalMessage = '') {
		return $this->partialCaptureByLineItems($this->getUncapturedLineItems(), true, $additionalMessage);
	}

	/**
	 * This method sets the state to capture, but wihtout changing the inner state of the transaction. The whole
	 * authorized amount is set as captured.
	 *
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_ITransactionCapture
	 */
	public function captureDry($additionalMessage = '') {
		return $this->partialCaptureByLineItemsDry($this->getUncapturedLineItems(), true, $additionalMessage);
	}

	/**
	 * This method executes a partial capture, without changing the transaction state.
	 *
	 * @param double $amount The amount that should be captured.
	 * @param boolean $close Close the transaction or not.
	 * @param string $additionalMessage
	 * @throws Exception If something is not allowed to do.
	 */
	public function partialCaptureDry($amount, $close = false, $additionalMessage = '') {
		$items = $amount;
		if (!is_array($items)) {
			$items = Customweb_Util_Invoice::getItemsByReductionAmount($this->getUncapturedLineItems(), $amount, $this->getCurrencyCode());
		}
		return $this->partialCaptureByLineItemsDry($items, $close, $additionalMessage);
	}

	public function partialCaptureByLineItemsDry($items, $close = false, $additionalMessage = '') {

		$amount = Customweb_Util_Invoice::getTotalAmountIncludingTax($items);
		if (!$this->isAuthorized()) {
			throw new Exception(Customweb_I18n_Translation::__("Only authorized transaction can be captured."));
		}

		if ($this->captureClosed) {
			throw new Exception(Customweb_I18n_Translation::__("This transaction is already closed for further captures."));
		}

		if ($this->isCancelled()) {
			throw new Exception(Customweb_I18n_Translation::__("A cancelled transaction cannot be captured."));
		}

		if (Customweb_Util_Currency::roundAmount(($this->getCapturedAmount() + $amount), $this->getCurrencyCode()) > Customweb_Util_Currency::roundAmount($this->getAuthorizationAmount(), $this->getCurrencyCode())) {
			throw new Exception(Customweb_I18n_Translation::__(
				"The capture amount (!captureAmount) cannot be greater than the authorized amount (!authorizedAmount).",
				array(
					'!captureAmount' => $amount,
					'!authorizedAmount' => $this->getAuthorizationAmount(),
				)
			));
		}
		
		// Check that the amounts of the single items are not higher as the original ones.
		$originalItems = $this->getTransactionContext()->getOrderContext()->getInvoiceItems();
		$originalItemMap = array();
		foreach ($originalItems as $item) {
			$originalItemMap[$item->getSku()] = $item;
		}
		
		foreach ($items as $item) {
			if ($item instanceof Customweb_Payment_Authorization_IInvoiceItem) {
				if (!isset($originalItemMap[$item->getSku()])) {
					throw new Exception(Customweb_I18n_Translation::__(
						"The capture item with SKU '@sku' is not present in the original order.",
						array(
							'@sku' => $item->getSku(),
						)
					));
				}
				if (Customweb_Util_Currency::compareAmount($item->getAmountIncludingTax(), $originalItemMap[$item->getSku()]->getAmountIncludingTax(), $this->getCurrencyCode()) > 0) {
					throw new Exception(Customweb_I18n_Translation::__(
							"The capture item with SKU '@sku' has a higher amount (@amountItem) as the original item (@amountOriginal).",
							array(
								'@sku' => $item->getSku(),
								'@amountItem' => Customweb_Util_Currency::formatAmount($item->getAmountIncludingTax(), $this->getCurrencyCode()),
								'@amountOriginal' => Customweb_Util_Currency::formatAmount($originalItemMap[$item->getSku()]->getAmountIncludingTax(), $this->getCurrencyCode()),
							)
					));
				}
			}
		}
		
		return $this;
	}

	/**
	 * @param Customweb_Payment_Authorization_IInvoiceItem[] $items
	 * @param string $close
	 * @param string $additionalMessage
	 * @return Customweb_Payment_Authorization_DefaultTransactionCapture
	 */
	public function partialCaptureByLineItems($items, $close = false, $additionalMessage = '') {

		$this->partialCaptureByLineItemsDry($items, $close, $additionalMessage);
		$amount = Customweb_Util_Invoice::getTotalAmountIncludingTax($items);
		$historyMessage = Customweb_I18n_Translation::__(
			"The amount of !amount is captured.",
			array('!amount' => Customweb_Util_Currency::formatAmount($amount, $this->getCurrencyCode()))
		);
		if (!empty($additionalMessage)) {
			$historyMessage .= ' (' . $additionalMessage . ')';
		}

		$captureItem = $this->createCaptureItem($amount);
		$captureItem->setCaptureItems($items);
		$this->createHistoryItem(
			$historyMessage,
			Customweb_Payment_Authorization_ITransactionHistoryItem::ACTION_CAPTURING
		);

		$this->captured = true;
		if (Customweb_Util_Currency::compareAmount($this->getCapturedAmount(), $this->getAuthorizationAmount(), $this->getCurrencyCode()) >= 0) {
			$close = true;
		}
		$this->captureClosed = $close;

		return $captureItem;
	}

	/**
	 * This method marks this transaction as partial captured.
	 *
	 * @param double $amount The amount that should be captured.
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_ITransactionCapture
	 */
	public function partialCapture($amount, $close = false, $additionalMessage = '') {
		$items = $amount;
		if (!is_array($items)) {
			$items = Customweb_Util_Invoice::getItemsByReductionAmount($this->getUncapturedLineItems(), $amount, $this->getCurrencyCode());
		}
		return $this->partialCaptureByLineItems($items, $close, $additionalMessage);
	}

	/**
	 * This method returns a list of line items with the residual amount to capture.
	 *
	 * @return Customweb_Payment_Authorization_ITransactionCapture[]
	 */
	public function getUncapturedLineItems() {

		$resultinItems = $this->getTransactionContext()->getOrderContext()->getInvoiceItems();
		foreach ($this->getCaptures() as $capture) {
			$items = $capture->getCaptureItems();
			if ($items === null) {
				$items = Customweb_Util_Invoice::getItemsByReductionAmount($resultinItems, $capture->getAmount(), $this->getCurrencyCode());
			}
			$resultinItems = Customweb_Util_Invoice::getResultingLineItemsByDeltaItems($resultinItems, $items);
		}

		return $resultinItems;
	}
	
	/**
	 * Returns a list of items, which are currently captured.
	 * 
	 * @return Customweb_Payment_Authorization_ITransactionCapture[]
	 */
	public function getCapturedLineItems() {
		$resultinItems = array();
		
		foreach ($this->getCaptures() as $capture) {
			$items = $capture->getCaptureItems();
			if ($items === null) {
				$lineItems = Customweb_Util_Invoice::getResultingLineItemsByDeltaItems($this->getTransactionContext()->getOrderContext()->getInvoiceItems(), $resultinItems);
				$items = Customweb_Util_Invoice::getItemsByReductionAmount($lineItems, $capture->getAmount(), $this->getCurrencyCode());
			}
			$resultinItems = Customweb_Util_Invoice::addLineItems($resultinItems, $items);
		}
		
		return $resultinItems;
	}

	public function getCapturedAmount() {
		return $this->capturedAmount;
	}

	public function isCancelled() {
		return $this->cancelled;
	}

	/**
	 * This method cancels the transaction without changing the inner state. This method can be used
	 * to check the constraints for this action.
	 *
	 * @param string $additionalMessage
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_ITransactionCapture
	 */
	public function cancelDry($additionalMessage = '') {
		if ($this->isCaptured()) {
			throw new Exception(Customweb_I18n_Translation::__("A captured transaction cannot be cancelled."));
		}

		if (!$this->isAuthorized()) {
			throw new Exception(Customweb_I18n_Translation::__("Only authorized transaction can be cancelled."));
		}

		if ($this->isCancelled()) {
			throw new Exception(Customweb_I18n_Translation::__("A cancelled transaction cannot be cancelled again."));
		}
		return $this;
	}

	/**
	 *
	 * @param boolean $close
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_ITransactionCancel
	 */
	public function cancel($additionalMessage = '') {
		$this->cancelDry($additionalMessage);

		$historyMessage = Customweb_I18n_Translation::__("The whole transaction is cancelled.");
		if (!empty($additionalMessage)) {
			$historyMessage .= ' (' . $additionalMessage . ')';
		}
		$cancelItem = $this->createCancelItem();

		$this->createHistoryItem(
			$historyMessage,
			Customweb_Payment_Authorization_ITransactionHistoryItem::ACTION_CANCELLATION
		);

		$this->cancelled = true;
		return $cancelItem;
	}

	public function getAuthorizationParameters() {
		return $this->parameters;
	}

	public function setAuthorizationParameters(array $parameters) {
		$this->parameters = $parameters;
		return $this;
	}

	public function getRefundedTotalAmount() {
		return $this->refundedAmount;
	}

	/**
	 * This method creates a new refund and creates a new history item, but without changing the state. This method
	 * can be used to check if a given refund, will be accepted by this transaction.
	 *
	 * @param double $amount
	 * @param boolean $close
	 * @param string $additionalMessage
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function refundDry($amount, $close = false, $additionalMessage = '') {
		$items = $amount;
		if (!is_array($items)) {
			$items = Customweb_Util_Invoice::getItemsByReductionAmount($this->getNonRefundedLineItems(), $amount, $this->getCurrencyCode());
		}
		return $this->refundByLineItemsDry($items, $close, $additionalMessage);
	}

	public function refundByLineItemsDry(array $items, $close = false, $additionalMessage = '') {

		$amount = Customweb_Util_Invoice::getTotalAmountIncludingTax($items);
		if (!$this->isAuthorized()) {
			throw new Exception(Customweb_I18n_Translation::__("Only authorized transaction can be refunded."));
		}

		if ($this->refundClosed) {
			throw new Exception(Customweb_I18n_Translation::__("This transaction is already closed for further refunds."));
		}

		if ($this->isCancelled()) {
			throw new Exception(Customweb_I18n_Translation::__("A cancelled transaction cannot be refunded."));
		}

		if (!$this->isCaptured()) {
			throw new Exception(Customweb_I18n_Translation::__("Only captured transaction can be refunded."));
		}

		$newTotalRefundedAmount = $amount + $this->getRefundedTotalAmount();
		if (Customweb_Util_Currency::roundAmount($newTotalRefundedAmount, $this->getCurrencyCode()) > Customweb_Util_Currency::roundAmount($this->getCapturedAmount(), $this->getCurrencyCode())) {
			throw new Exception(Customweb_I18n_Translation::__(
					"The total refund amount (!totalRefundedAmount) cannot be greater than the captured amount (!capturedAmount).",
					array(
							'!totalRefundedAmount' => $newTotalRefundedAmount,
							'!capturedAmount' => $this->getCapturedAmount(),
					)
			));
		}
		

		// Check that the amounts of the single items are not higher as the original ones.
		$originalItems = $this->getCapturedLineItems();
		$originalItemMap = array();
		foreach ($originalItems as $item) {
			$originalItemMap[$item->getSku()] = $item;
		}
		
		foreach ($items as $item) {
			if ($item instanceof Customweb_Payment_Authorization_IInvoiceItem) {
				if (!isset($originalItemMap[$item->getSku()])) {
					throw new Exception(Customweb_I18n_Translation::__(
							"The refund item with SKU '@sku' is not present in the original order.",
							array(
								'@sku' => $item->getSku(),
							)
					));
				}
				if (Customweb_Util_Currency::compareAmount($item->getAmountIncludingTax(), $originalItemMap[$item->getSku()]->getAmountIncludingTax(), $this->getCurrencyCode()) > 0) {
					throw new Exception(Customweb_I18n_Translation::__(
							"The refund item with SKU '@sku' has a higher amount (@amountItem) as the original item (@amountOriginal).",
							array(
								'@sku' => $item->getSku(),
								'@amountItem' => Customweb_Util_Currency::formatAmount($item->getAmountIncludingTax(), $this->getCurrencyCode()),
								'@amountOriginal' => Customweb_Util_Currency::formatAmount($originalItemMap[$item->getSku()]->getAmountIncludingTax(), $this->getCurrencyCode()),
							)
					));
				}
			}
		}
		
		return $this;
	}

	/**
	 * This method creates a new refund and creates a new history item.
	 *
	 * @param double $amount The amount to refund
	 * @param boolean $close Close the transaction for further refunds
	 * @return Customweb_Payment_Authorization_ITransactionRefund
	 */

	public function refund($amount, $close = false, $additionalMessage = '') {
		$items = $amount;
		if (!is_array($items)) {
			$items = Customweb_Util_Invoice::getItemsByReductionAmount($this->getNonRefundedLineItems(), $amount, $this->getCurrencyCode());
		}
		return $this->refundByLineItems($items, $close, $additionalMessage);
	}


	public function refundByLineItems($items, $close = false, $additionalMessage = '') {

		$this->refundByLineItemsDry($items, $close, $additionalMessage);
		$amount = Customweb_Util_Invoice::getTotalAmountIncludingTax($items);

		$historyMessage = Customweb_I18n_Translation::__(
			"A refund was added over !amount.",
			array('!amount' => Customweb_Util_Currency::formatAmount($amount, $this->getCurrencyCode()))
		);
		if (!empty($additionalMessage)) {
			$historyMessage .= ' (' . $additionalMessage . ')';
		}

		$refundItem = $this->createRefundItem($amount);
		$refundItem->setRefundItems($items);
		$this->createHistoryItem(
			$historyMessage,
			Customweb_Payment_Authorization_ITransactionHistoryItem::ACTION_REFUND
		);

		if (Customweb_Util_Currency::compareAmount($this->getRefundedTotalAmount(), $this->getCapturedAmount(), $this->getCurrencyCode()) >= 0) {
			$close = true;
		}
		$this->refundClosed = $close;

		return $refundItem;
	}


	/**
	 * This method returns a list of line items with the residual amount to refund.
	 *
	 * @return Customweb_Payment_Authorization_IInvoiceItem[]
	 */
	public function getNonRefundedLineItems() {
		$resultingItems = $this->getCapturedLineItems();

		foreach ($this->getRefunds() as $refund){
			$items = $refund->getRefundItems();
			if($items === null){
				$items = Customweb_Util_Invoice::getItemsByReductionAmount($resultingItems, $refund->getAmount(), $this->getCurrencyCode());
			}
			$resultingItems = Customweb_Util_Invoice::substractLineItems($resultingItems, $items);
		}
		return $resultingItems;
	}

	/**
	 * This method adds a refund object to the list of refunds. To add a refund
	 * the method self::refund() should be used.
	 *
	 * @param Customweb_Payment_Authorization_ITransactionRefund $refund
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function addRefund(Customweb_Payment_Authorization_ITransactionRefund $refund) {
		$this->refunds[] = $refund;
		return $this;
	}

	/**
	 * This method adds a capture object to the list of refunds. To add a capture
	 * the method self::setPartialCapture() should be used.
	 *
	 * @param Customweb_Payment_Authorization_ITransactionCapture $refund
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function addCapture(Customweb_Payment_Authorization_ITransactionCapture $capture) {
		$this->captures[] = $capture;
		return $this;
	}

	/**
	 * This method adds a cancel object to the list of cancels. To add a cancel
	 * the method self::cancel() should be used.
	 *
	 * @param Customweb_Payment_Authorization_ITransactionCancel $cancel
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function addCancel(Customweb_Payment_Authorization_ITransactionCancel $cancel) {
		$this->cancels[] = $cancel;
		return $this;
	}

	public function getRefunds() {
		return $this->refunds;
	}

	public function getCaptures() {
		return $this->captures;
	}

	public function getCancels() {
		return $this->cancels;
	}

	public function isPartialRefundPossible() {
		if ($this->refundClosed) {
			return false;
		}

		if (!$this->isCaptured()) {
			return false;
		}
		
		// We can not allow to refund, until the transaction is closed for further captures,
		// because otherwise we can not determine which items can be refunded. Some of them may
		// be refunded later, but then we may close the transaction for further refunds arleady. In
		// this case we were then in a fussy state.
		if (!$this->captureClosed) {
			return false;
		}

		if ($this->getRefundedTotalAmount() >= $this->getCapturedAmount()) {
			return false;
		}
		else {
			return true;
		}
	}

	public function isRefundPossible() {
		return $this->isPartialRefundPossible();
	}

	public function isRefundClosable() {
		return !$this->refundClosed;
	}

	public function getRefundableAmount() {
		return max($this->getCapturedAmount() - $this->getRefundedTotalAmount(), 0);
	}

	public function isPartialCapturePossible() {
		if ($this->captureClosed) {
			return false;
		}

		if ($this->isCancelled()) {
			return false;
		}

		if (!$this->isAuthorized()) {
			return false;
		}

		if ($this->getCapturedAmount() >= $this->getAuthorizationAmount()) {
			return false;
		}
		else {
			return true;
		}
	}

	public function isCapturePossible() {
		return $this->isPartialCapturePossible();
	}

	public function isCaptureClosable() {
		return !$this->captureClosed;
	}

	/**
	 * @return boolean
	 * @deprecated
	 */
	public function isUpdatable(){
		if ($this->getUpdateExecutionDate() === null) {
			return false;
		}
		
		return true;
	}

	/**
	 * @param string $updatable
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 * @deprecated
	 */
	public function setUpdatable($updatable = true){
		
		// Since we can not use the flag anymore and we need a concrete date
		// we set it 1 hour in the future.
		$date = new Customweb_Date_DateTime();
		$date->setTimestamp(time() + 3600);
		$this->setUpdateExecutionDate($date);
		
		return $this;
	}

	public function getCapturableAmount() {
		return max($this->getAuthorizationAmount() - $this->getCapturedAmount(), 0);
	}

	public function isCancelPossible() {
		if (!$this->isAuthorized()) {
			return false;
		}

		if ($this->isCancelled()) {
			return false;
		}

		if ($this->isCaptured()) {
			return false;
		}

		return true;
	}

	/**
	 * This method creates a new history item. The item is automatically added
	 * to the list of history items and then returned.
	 *
	 * @param Customweb_I18n_LocalizableString $message The history message.
	 * @param string $action The action performed.
	 * @return Customweb_Payment_Authorization_ITransactionHistoryItem
	 */
	protected function createHistoryItem($message, $action) {
		$item = $this->buildNewHistoryObject($message, $action);
		$this->addHistoryItem($item);
		return $item;
	}

	protected function buildNewHistoryObject($message, $action) {
		return new Customweb_Payment_Authorization_DefaultTransactionHistoryItem($message, $action);
	}

	/**
	 * This method creates a refund item. The item is automatically added
	 * to the list of refunds and then returned.
	 *
	 * @param double $amount The refund amount.
	 * @return Customweb_Payment_Authorization_ITransactionRefund
	 */
	protected function createRefundItem($amount, $status = NULL, $refundId = NULL) {
		if ($refundId === NULL) {
			$number = count($this->getRefunds());
			$refundId = $this->getTransactionId() . '_r_' . ($number+1);
		}
		$item = $this->buildNewRefundObject($refundId, $amount, $status);
		$this->refundedAmount += $item->getAmount();
		$this->addRefund($item);
		return $item;
	}

	protected function buildNewRefundObject($refundId, $amount, $status = NULL) {
		return new Customweb_Payment_Authorization_DefaultTransactionRefund($refundId, $amount, $status);
	}


	/**
	 * This method creates a cancel item. The item is automatically added
	 * to the list of cancels and then returned.
	 *
	 * @return Customweb_Payment_Authorization_ITransactionCancel
	 */
	protected function createCancelItem($status = NULL, $cancelId = NULL) {
		if ($cancelId === NULL) {
			$number = count($this->getCancels());
			$cancelId = $this->getTransactionId() . '_a_' . ($number+1);
		}
		$item = $this->buildNewCancelObject($cancelId, $status);
		$this->addCancel($item);
		return $item;
	}

	protected function buildNewCancelObject($cancelId, $status = NULL) {
		return new Customweb_Payment_Authorization_DefaultTransactionCancel($cancelId, $status);
	}


	/**
	 * This method creates a capture item. The item is automatically added
	 * to the list of captures and then returned.
	 *
	 * @param double $amount The refund amount.
	 * @return Customweb_Payment_Authorization_ITransactionCapture
	 */
	protected function createCaptureItem($amount, $status = NULL, $captureId = NULL) {
		if ($captureId === NULL) {
			$number = count($this->getCaptures());
			$captureId = $this->getTransactionId() . '_c_' . ($number+1);
		}
		$item = $this->buildNewCaptureObject($captureId, $amount, $status);
		$this->capturedAmount += $item->getAmount();
		$this->addCapture($item);
		return $item;
	}

	protected function buildNewCaptureObject($captureId, $amount, $status = NULL) {
		return new Customweb_Payment_Authorization_DefaultTransactionCapture($captureId, $amount, $status);
	}

	public function getAlias() {
		return $this->alias;
	}

	/**
	 * Sets the alias (overwrites existing alias wihtout check).
	 *
	 * @param string $alias
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setAlias($alias) {
		$this->alias = $alias;
		return $this;
	}

	public function getAliasForDisplay() {
		return $this->aliasForDisplay;
	}

	/**
	 * Sets the alias for display (overwrites existing alias wihtout check).
	 *
	 * @param string $aliasForDisplay
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setAliasForDisplay($aliasForDisplay) {
		$this->aliasForDisplay = $aliasForDisplay;
		return $this;
	}

	/**
	 * Returns the state of 3D secure for the transaction.
	 *
	 * @return string STATE_3D_SECURE_NOT_APPLICABLE | STATE_3D_SECURE_FAILED | STATE_3D_SECURE_SUCCESS
	 */
	public function getState3DSecure(){
		return $this->state3DSecure;
	}

	/**
	 * Sets the state of 3D secure for the transaction.
	 *
	 * @param string $state STATE_3D_SECURE_NOT_APPLICABLE | STATE_3D_SECURE_FAILED | STATE_3D_SECURE_SUCCESS
	 */
	public function setState3DSecure($state){
		$this->state3DSecure = $state;
	}

	/**
	 * @see Customweb_Payment_Authorization_ITransaction::getPaymentCustomerContext()
	 */
	public function getPaymentCustomerContext() {
		return $this->getTransactionContext()->getPaymentCustomerContext();
	}

	/**
	 * (non-PHPdoc)
	 * @see Customweb_Payment_Authorization_ITransaction::isPaid()
	 */
	public function isPaid() {
		return $this->paid;
	}

	/**
	 * By invoking this method the transaction is marked as paid. The effect of
	 * this method is not invertable.
	 *
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setPaid($paid = true) {
		$this->paid = $paid;
		return $this;
	}

	/**
	 * (non-PHPdoc)
	 * @see Customweb_Payment_Authorization_ITransaction::getTransactionInformation()
	 */
	public function getTransactionLabels() {
		return array_merge(
			$this->getBasicLabels(),
			$this->getStateLabels(),
			$this->getAliasLabels(),
			$this->getTransactionSpecificLabels(),
			$this->getState3DSecureLabel()
		);
	}

	/**
	 * This method returns a list of labels which reflects some basic informations about
	 * the transactions. Such as the amount and currency.
	 */
	protected function getBasicLabels() {
		$labels = array();
		$labels['authorization_amount'] = array(
			'label' => Customweb_I18n_Translation::__('Authorization Amount'),
			'value' => $this->getAuthorizationAmount()
		);

		$labels['currency'] = array(
			'label' => Customweb_I18n_Translation::__('Currency'),
			'value' => $this->getCurrencyCode()
		);

		$labels['payment_method'] = array(
			'label' => Customweb_I18n_Translation::__('Payment Method'),
			'value' => $this->getPaymentMethod()->getPaymentMethodDisplayName()
		);

		$paymentId = $this->getPaymentId();
		if (!empty($paymentId)) {
			$labels['payment_id'] = array(
				'label' => Customweb_I18n_Translation::__('Payment ID'),
				'value' => $paymentId
			);
		}

		if ($this->getCapturedAmount() > 0) {
			$labels['captured_amount'] = array(
				'label' => Customweb_I18n_Translation::__('Captured Amount'),
				'value' => $this->getCapturedAmount()
			);
		}

		if ($this->getRefundedTotalAmount() > 0) {
			$labels['refunded_amount'] = array(
				'label' => Customweb_I18n_Translation::__('Refunded Amount'),
				'value' => $this->getRefundedTotalAmount()
			);
		}

		if (!$this->isLiveTransaction()) {
			$labels['test_transaction'] = array(
				'label' => Customweb_I18n_Translation::__('Test Transaction'),
				'value' => Customweb_I18n_Translation::__('Yes'),
				'description' => Customweb_I18n_Translation::__('The transaction is only executed in the test system. The goods should not be delivered.'),
			);
		}
		
		$updateExecutionDate = $this->getUpdateExecutionDate();
		if ($updateExecutionDate !== null && $updateExecutionDate instanceof DateTime) {
			$labels['update_execution_date'] = array(
				'label' => Customweb_I18n_Translation::__('Next Update Execution Date'),
				'value' => $updateExecutionDate->format('c'),
				'description' => Customweb_I18n_Translation::__('The next update execution date indicates when the next cron is run to update the transaction state.'),
			);
		}

		return $labels;
	}

	protected function getAliasLabels() {
		$labels = array();

		if ($this->getAliasForDisplay() !== null) {
			$labels['alias_for_display'] = array(
				'label' => Customweb_I18n_Translation::__('Alias'),
				'value' => $this->getAliasForDisplay(),
			);
		}

		return $labels;
	}

	/**
	 * This method is intended for overriding by a subclass. It provides
	 * the opportunity for the subclass to provide own labels.
	 *
	 * @return array(
	 * 	  array(
	 * 	     'label' => 'Translated label',
	 *       'value' => 'Value to display',
	 *    )
	 * )
	 */
	protected function getTransactionSpecificLabels() {
		return array();
	}

	/**
	 * This method returns a list of labes which refelcts the current
	 * state of this transaction.
	 *
	 */
	protected function getStateLabels() {
		$labels = array();

		if ($this->isAuthorizationFailed()) {
			$labels['failed_authorization'] = array(
				'label' => Customweb_I18n_Translation::__('Authorization Failed'),
				'value' => Customweb_I18n_Translation::__('Yes')
			);
		}
		else if ($this->isAuthorized()) {
			$labels['authorized'] = array(
				'label' => Customweb_I18n_Translation::__('Transaction Authorized'),
				'value' => Customweb_I18n_Translation::__('Yes')
			);

			$labels['uncertain'] = array(
				'label' => Customweb_I18n_Translation::__('Transaction Uncertain'),
				'description' => Customweb_I18n_Translation::__('A transaction may be uncertain, when the payment is not guaranteed. For example in case the credit card does not participate in the 3D procedure.'),
			);
			if ($this->isAuthorizationUncertain()) {
				$labels['uncertain']['value'] = Customweb_I18n_Translation::__('Yes');
			}
			else {
				$labels['uncertain']['value'] = Customweb_I18n_Translation::__('No');
			}

			if ($this->isCancelled()) {
				$labels['cancelled'] = array(
					'label' => Customweb_I18n_Translation::__('Transaction Cancelled'),
					'value' => Customweb_I18n_Translation::__('Yes')
				);
			}

			if ($this->isCaptured()) {
				$labels['captured'] = array(
					'label' => Customweb_I18n_Translation::__('Transaction Captured'),
					'value' => Customweb_I18n_Translation::__('Yes')
				);
			}

			if ($this->isPaid()) {
				$labels['paid'] = array(
						'label' => Customweb_I18n_Translation::__('Transaction Paid'),
						'value' => Customweb_I18n_Translation::__('Yes')
				);
			}
		}

		return $labels;
	}

	/**
	 * This method returns labels that reflect the state of the 3d secure process,
	 * if available.
	 *
	 * @return array
	 */
	protected function getState3DSecureLabel(){
		$labels = array();
		if($this->getState3DSecure() == self::STATE_3D_SECURE_FAILED){
			$labels['3DSecure'] = array(
					'label' => Customweb_I18n_Translation::__('3D Secure'),
					'value' => Customweb_I18n_Translation::__('Failed')
			);
		}
		elseif($this->getState3DSecure() == self::STATE_3D_SECURE_SUCCESS){
			$labels['3DSecure'] = array(
					'label' => Customweb_I18n_Translation::__('3D Secure'),
					'value' => Customweb_I18n_Translation::__('Successful')
			);
		}
		return $labels;
	}
	
	/**
	 * @return NULL|string
	 * @deprecated
	 */
	public function getOrderStatus() {
		$key = $this->getOrderStatusSettingKey();
		if ($key === null) {
			return null;
		}
		return $this->getPaymentMethod()->getPaymentMethodConfigurationValue($key);
	}

	public function getOrderStatusSettingKey() {
		
		// No dedicated order status needed.
		if ($this->isAuthorizationFailed() || !$this->isAuthorized()) {
			return null;
		}
		
		$method = $this->getPaymentMethod();
		$statusKey = 'status_authorized';
		if ($this->isCaptured()) {
			if ($method->existsPaymentMethodConfigurationValue('status_captured')) {
				$capturedState = $method->getPaymentMethodConfigurationValue('status_captured');
				// 'none' check is backward compatibility
				if ($capturedState != 'no_status_change' && $capturedState != 'none') {
					$statusKey = 'status_captured';
				}
			}
		}

		if ($this->isAuthorizationUncertain()) {
			if ($method->existsPaymentMethodConfigurationValue('status_uncertain')) {
				$statusKey = 'status_uncertain';
			}
		}
		
		if($this->isUncertainTransactionFinallyDeclined()) {
			if ($method->existsPaymentMethodConfigurationValue('status_finallydeclined')) {
				$declinedStatus = $method->getPaymentMethodConfigurationValue('status_finallydeclined');
				if ($declinedStatus != 'no_status_change' && $declinedStatus != 'none') {
					$statusKey = 'status_finallydeclined';
				}
			}
		}

		if ($this->isCancelled()) {
			if ($method->existsPaymentMethodConfigurationValue('status_cancelled')) {
				$cancelledStatus = $method->getPaymentMethodConfigurationValue('status_cancelled');
				if ($cancelledStatus != 'no_status_change' && $cancelledStatus != 'none') {
					$statusKey = 'status_cancelled';
				}
			}
		}
		
		if($this->isCustomerRefusingToPay()) {
			if ($method->existsPaymentMethodConfigurationValue('status_refusetopay')) {
				$refusedStatus = $method->getPaymentMethodConfigurationValue('status_refusetopay');
				if ($refusedStatus != 'no_status_change' && $refusedStatus != 'none') {
					$statusKey = 'status_refusetopay';
				}
			}
		}
		
		return $this->getCustomOrderStatusSettingKey($statusKey);
	}

	/**
	 * This method can be used to define the order status on custom constraines in sub classes.
	 * For example if an order should be marked as paid in case of an invoice.
	 *
	 * @param mixed $status The current order status
	 * @return mixed The order status to use
	 */
	protected function getCustomOrderStatusSettingKey($statusKey) {
		return $statusKey;
	}

	/**
	 * We return by default the authorization parameters. However subclasses may
	 * override this to provide more appropriated data abaout this transaction.
	 *  
	 */
	public function getTransactionData() {
		return $this->getAuthorizationParameters();
	}

	public function getAuthorizationStatus() {
		if ($this->isAuthorizationFailed()) {
			return self::AUTHORIZATION_STATUS_FAILED;
		}
		else if ($this->isAuthorized()) {
			return self::AUTHORIZATION_STATUS_SUCCESSFUL;
		}
		else {
			return self::AUTHORIZATION_STATUS_PENDING;
		}
	}
	
	
	public function getUpdateExecutionDate() {
		return $this->updateExecutionDate;
	}
	

	public function getSuccessUrl() {
		return Customweb_Util_Url::appendParameters(
				$this->getTransactionContext()->getSuccessUrl(),
				$this->getTransactionContext()->getCustomParameters()
		);
	}
	
	public function getFailedUrl() {
		return Customweb_Util_Url::appendParameters(
				$this->getTransactionContext()->getFailedUrl(),
				$this->getTransactionContext()->getCustomParameters()
		);
	}
	
	public function getNotificationUrl() {
		return Customweb_Util_Url::appendParameters(
				$this->getTransactionContext()->getNotificationUrl(),
				$this->getTransactionContext()->getCustomParameters()
		);
	}
	
	public function getPaymentInformation() {
		return null;
	}

	/**
	 * Sets the next execution date for the update of the transaction. The input 
	 * should be a DateTime.
	 * 
	 * @see getUpdateExecutionDate()
	 * 
	 * @param DateTIme $updateExecutionDate
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setUpdateExecutionDate($updateExecutionDate){
		if ($updateExecutionDate !== null) {
			if (!($updateExecutionDate instanceof Customweb_Date_DateTime)) {
				$updateExecutionDate = new Customweb_Date_DateTime($updateExecutionDate);
			}
		}
		
		$this->updateExecutionDate = $updateExecutionDate;
		return $this;
	}
	
	/**
	 * This method generates a signature for the given entity (e.g. controller) 
	 * and this transaction. The signature can be added for example to the
	 * URL provided to the customer. 
	 * 
	 * The signature can than be checked with checkSecuritySignature(). This enables
	 * to provided selective access to the transaction information.
	 * 
	 * @param string $entityToSecure
	 * @return string
	 */
	public function getSecuritySignature($entityToSecure) {
		if ($this->securityToken === null) {
			throw new Exception("The security token is not initialized");
		}
		$entityToSecure = (string)$entityToSecure;
		
		return hash_hmac('sha512', $entityToSecure . $this->getTransactionId(), $this->securityToken);
	}
	
	/**
	 * Checks whether the given signature is valid or not.
	 * 
	 * @param string $entityToSecure
	 * @param string $providedSignature
	 * @throws Exception
	 * @return boolean
	 */
	public function checkSecuritySignature($entityToSecure, $providedSignature) {
		$signature = $this->getSecuritySignature($entityToSecure);
		if ($signature !== $providedSignature) {
			throw new Exception(Customweb_I18n_Translation::__('The provided signature does not match with the one calculated.'));
		}
		
		return true;
	}
	
	public function isLiveTransaction() {
		return $this->liveTransaction;
	}
	
	/**
	 * Sets if a given transaction is processed on a live platform.
	 * 
	 * @param string $isLive
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setLiveTransaction($isLive = true) {
		$this->liveTransaction = (bool)$isLive;
		return $this;
	}
	
	
	public function isCustomerRefusingToPay(){
		return $this->customerRefusingToPay;
	}
	
	
	public function isUncertainTransactionFinallyDeclined(){
		return $this->uncertainTransactionFinallyDeclined;
	}
	
	/**
	 * Sets the flag to indicate that the customer refuses to pay this transaction.
	 * 
	 * @param boolean $active
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setCustomerRefusingToPay($active = true){
		if(!$this->isCaptured()) {
			throw new Exception(Customweb_I18n_Translation::__('Only on captured transaction the flag customer refusing to pay can be set.'));
		}
		$this->customerRefusingToPay = $active;
		return $this;
	}
	
	/**
	 * Sets the transaction to finally declined, after the transaction was in the uncertain state.
	 *  
	 * @throws Exception
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setUncertainTransactionFinallyDeclined() {
		if(!$this->isAuthorized()) {
			throw new Exception(Customweb_I18n_Translation::__('Only an authorized transaction can be marked as finally declined.'));
		}
		if(!$this->isAuthorizationUncertain()) {
			throw new Exception(Customweb_I18n_Translation::__('Only an uncertain transaction can be marked as finally declined.'));
		}
		$this->uncertainTransactionFinallyDeclined = true;
		return $this;
	}
	
	
	/**
	 * Sets the current version number. Used for optimistic locking
	 * @param int $versionNumber
	 * @return Customweb_Payment_Authorization_DefaultTransaction
	 */
	public function setVersionNumber($versionNumber) {
		$this->versionNumber = $versionNumber;
		return $this;
	}
	
	/**
	 * @see Customweb_Payment_Authorization_ITransaction::getVersionNumber()
	 */
	public function getVersionNumber(){
		return $this->versionNumber;
	}
	
	/**
	 * @see Customweb_Payment_Authorization_ITransaction::isSendConfirmationMailEnabled()
	 */
	public function isSendConfirmationMailEnabled(){
		return true;
	}
}

Spamworldpro Mini