/** * Creates a new "refund" in Realex's systems. * * Sends a 'receipt-out' request to Realex which creates a new payment at Realex. * * This also logs the transaction into the \Entities\RealexTransaction table, * and returns that object which can be queried for the request and transaction * state. * * If $this->_fake_transactions is true then it skips the Realex request and returns with * success after performing all normal database operations as if the request was sent. * @see $_fake_transactions * * @param \Entities\RealexCard $card * @param int|float $amount the amount to be withdrawn from the card, in the biggest unit of the currency, * e.g. in euro or dollar and not in cent, then conversion is made inside the method * @return CreditcardTransaction The resultant CreditcardTransaction object * @throws OSS_PaymentProcessor_Exception */ public function paymentOut($card, $amount) { $rqTimeStamp = $this->getTimeStamp(); // we're about to perform payment which means that the cerdit card should exist if (!$card instanceof Creditcard) { $this->_log("PROG ERROR - expecting instance of Creditcard", OSS_Log::ERR); throw new OSS_PaymentProcessor_Exception('System Failure - our technical staff have been notified'); } $rtrans = new \Entities\RealexTransaction(); $rtrans->setRequestType('payment-out'); $rtrans->setPayer($card->getPayer()); $rtrans->getcard($card); $rtrans->setAmount($amount); $rtrans->setAccount($this->_account); $rtrans->setState(\Entities\RealexTransaction::STATE_INIT); $rtrans->setRequest(""); $rtrans->setCreated(new \DateTime()); $rtrans->setUpdated(new \DateTime()); $rtrans->setIsFake(0); $this->getD2EM()->persist($rtrans); $this->getD2EM()->flush(); $this->_log("[RTRANS: {$rtrans->getId()}] Realex::paymentOut() - transaction set to STATE_INIT"); // we're about to perform payment which means that the cerdit card paygate state should be insync if ($card->etState() != \Entities\RealexCard::STATE_INSYNC) { $rtrans->setResult(999); throw new OSS_PaymentProcessor_Realex_Receipt_Exception($rtrans, OSS_PaymentProcessor_Exception::ERR_INCONSISTANT_PAYGATE_STATE); } $amount = (int) ($amount * 100); $rqOrderId = self::createOrderId($rtrans); $payerRef = $card->getPayer()->getPayerref(); $cardRef = $card->getCardref(); $rqHash = OSS_PaymentProcessor_Realex_Hash::payment($rqTimeStamp, $this->getMerchantId(), $rqOrderId, $amount, 'EUR', $payerRef, $this->getMerchantSecret()); $refundHash = OSS_PaymentProcessor_Realex_Hash::refund($this->getRefundPassword(), $this->getMerchantSecret()); $reqXML = "<request type='payment-out' timestamp='{$rqTimeStamp}'>\n <merchantid>" . $this->getMerchantId() . "</merchantid>\n <account>{$this->_account}</account>\n <orderid>{$rqOrderId}</orderid>\n <amount currency='EUR'>{$amount}</amount>\n <payerref>{$payerRef}</payerref>\n <paymentmethod>{$cardRef}</paymentmethod>\n <sha1hash>{$rqHash}</sha1hash>\n <refundhash>{$refundHash}</refundhash>\n </request>"; $rtrans->setRequest($amount); $rtrans->setState(\Entities\RealexTransaction::STATE_PRESEND); $rtrans->setUpdated(new \DateTime()); $this->getD2EM()->flush(); $this->_log("[RTRANS: {$rtrans->getId()}] Realex::paymentOut() - transaction set to STATE_PRESEND\n\n{$reqXML}\n\n"); if ($this->_fake_transactions) { $this->_log("[RTRANS: {$rtrans->getId()}] Realex::paymentOut() - faking transaction"); return $this->_completeFakeTransation($rtrans); } $this->_sendRequest($rtrans, $reqXML); // can throw OSS_PaymentProcessor_Realex_Receipt_Exception() return $rtrans; }