public function refundAction()
 {
     $this->getDi()->authAdmin->getUser()->checkPermission('grid_payment', 'insert');
     do {
         $this->invoice_payment_id = $this->getInt('invoice_payment_id');
         if (!$this->invoice_payment_id) {
             $res = array('success' => false, 'text' => ___("Not payment# submitted"));
             continue;
         }
         $p = $this->getDi()->invoicePaymentTable->load($this->invoice_payment_id);
         /* @var $p InvoicePayment */
         if (!$p) {
             $res = array('success' => false, 'text' => ___("No payment found"));
             continue;
         }
         if ($this->user_id != $p->user_id) {
             $res = array('success' => false, 'text' => ___("Payment belongs to another customer"));
             continue;
         }
         if ($p->isFullRefunded()) {
             $res = array('success' => false, 'text' => ___("Payment is already refunded"));
             continue;
         }
         $amount = sprintf('%.2f', $this->_request->get('amount'));
         if ($p->amount < $amount) {
             $res = array('success' => false, 'text' => ___("Refund amount cannot exceed payment amount"));
             continue;
         }
         if ($this->_request->getInt('manual')) {
             $el = new Am_Form_Element_Date();
             $dattm = $el->convertReadableToSQL($this->_request->get('dattm'));
             if (!$dattm) {
                 $dattm = sqlDate('now');
             }
             $dattm .= ' 00:00:00';
             if ($dattm < $p->dattm) {
                 $res = array('success' => false, 'text' => ___("Refund date cannot be before payment date"));
                 continue;
             }
             switch ($type = $this->_request->getFiltered('type')) {
                 case 'refund':
                 case 'chargeback':
                     $pl = $this->getDi()->plugins_payment->loadEnabled()->get($p->paysys_id);
                     if (!$pl) {
                         $res = array('success' => false, 'text' => ___("Could not load payment plugin [%s]", $pl));
                         continue 2;
                     }
                     $invoice = $p->getInvoice();
                     $transaction = new Am_Paysystem_Transaction_Manual($pl);
                     $transaction->setAmount($amount);
                     $transaction->setReceiptId($p->receipt_id . '-manual-' . $type);
                     $transaction->setTime(new DateTime($dattm));
                     if ($type == 'refund') {
                         $invoice->addRefund($transaction, $p->receipt_id);
                     } else {
                         $invoice->addChargeback($transaction, $p->receipt_id);
                     }
                     break;
                 case 'correction':
                     $this->getDi()->accessTable->deleteBy(array('invoice_payment_id' => $this->invoice_payment_id));
                     $invoice = $p->getInvoice();
                     $p->delete();
                     $invoice->updateStatus();
                     break;
                 default:
                     $res = array('success' => false, 'text' => ___("Incorrect refund [type] passed: %s", $type));
                     continue 2;
             }
             $res = array('success' => true, 'text' => ___("Payment has been successfully refunded"));
         } else {
             // automatic
             /// ok, now we have validated $p here
             $pl = $this->getDi()->plugins_payment->loadEnabled()->get($p->paysys_id);
             if (!$pl) {
                 $res = array('success' => false, 'text' => ___("Could not load payment plugin [%s]", $pl));
                 continue;
             }
             /* @var $pl Am_Paysystem_Abstract */
             $result = new Am_Paysystem_Result();
             $pl->processRefund($p, $result, $amount);
             if ($result->isSuccess()) {
                 if ($transaction = $result->getTransaction()) {
                     $p->getInvoice()->addRefund($result->getTransaction(), $p->receipt_id, $amount);
                 }
                 $res = array('success' => true, 'text' => ___("Payment has been successfully refunded"));
             } elseif ($result->isAction()) {
                 $action = $result->getAction();
                 if ($action instanceof Am_Paysystem_Action_Redirect) {
                     $res = array('success' => 'redirect', 'url' => $result->getUrl());
                 } else {
                     // todo handle other actions if necessary
                     throw new Am_Exception_NotImplemented("Could not handle refund action " . get_class($action));
                 }
             } elseif ($result->isFailure()) {
                 $res = array('success' => false, 'text' => join(";", $result->getErrorMessages()));
             }
         }
     } while (false);
     $this->_response->setHeader("Content-Type", "application/json", true);
     echo $this->getJson($res);
 }