public function willRefundCharge(PhabricatorUser $actor, PhortunePaymentProvider $provider, PhortuneCharge $charge, PhortuneCurrency $amount) { if (!$amount->isPositive()) { throw new Exception(pht('Trying to refund non-positive amount of money!')); } if ($amount->isGreaterThan($charge->getAmountRefundableAsCurrency())) { throw new Exception(pht('Trying to refund more money than remaining on charge!')); } if ($charge->getRefundedChargePHID()) { throw new Exception(pht('Trying to refund a refund!')); } if ($charge->getStatus() !== PhortuneCharge::STATUS_CHARGED && $charge->getStatus() !== PhortuneCharge::STATUS_HOLD) { throw new Exception(pht('Trying to refund an uncharged charge!')); } $refund_charge = PhortuneCharge::initializeNewCharge()->setAccountPHID($this->getAccount()->getPHID())->setCartPHID($this->getPHID())->setAuthorPHID($actor->getPHID())->setMerchantPHID($this->getMerchant()->getPHID())->setProviderPHID($provider->getProviderConfig()->getPHID())->setPaymentMethodPHID($charge->getPaymentMethodPHID())->setRefundedChargePHID($charge->getPHID())->setAmountAsCurrency($amount->negate()); $charge->openTransaction(); $charge->beginReadLocking(); $copy = clone $charge; $copy->reload(); if ($copy->getRefundingPHID() !== null) { throw new Exception(pht('Trying to refund a charge which is already refunding!')); } $refund_charge->save(); $charge->setRefundingPHID($refund_charge->getPHID()); $charge->save(); $charge->endReadLocking(); $charge->saveTransaction(); return $refund_charge; }