[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class PhortuneCartCancelController 4 extends PhortuneCartController { 5 6 private $id; 7 private $action; 8 9 public function willProcessRequest(array $data) { 10 $this->id = $data['id']; 11 $this->action = $data['action']; 12 } 13 14 public function processRequest() { 15 $request = $this->getRequest(); 16 $viewer = $request->getUser(); 17 18 $cart = id(new PhortuneCartQuery()) 19 ->setViewer($viewer) 20 ->withIDs(array($this->id)) 21 ->needPurchases(true) 22 ->executeOne(); 23 if (!$cart) { 24 return new Aphront404Response(); 25 } 26 27 switch ($this->action) { 28 case 'cancel': 29 // You must be able to edit the account to cancel an order. 30 PhabricatorPolicyFilter::requireCapability( 31 $viewer, 32 $cart->getAccount(), 33 PhabricatorPolicyCapability::CAN_EDIT); 34 $is_refund = false; 35 break; 36 case 'refund': 37 // You must be able to control the merchant to refund an order. 38 PhabricatorPolicyFilter::requireCapability( 39 $viewer, 40 $cart->getMerchant(), 41 PhabricatorPolicyCapability::CAN_EDIT); 42 $is_refund = true; 43 break; 44 default: 45 return new Aphront404Response(); 46 } 47 48 $cancel_uri = $cart->getDetailURI(); 49 $merchant = $cart->getMerchant(); 50 51 try { 52 if ($is_refund) { 53 $title = pht('Unable to Refund Order'); 54 $cart->assertCanRefundOrder(); 55 } else { 56 $title = pht('Unable to Cancel Order'); 57 $cart->assertCanCancelOrder(); 58 } 59 } catch (Exception $ex) { 60 return $this->newDialog() 61 ->setTitle($title) 62 ->appendChild($ex->getMessage()) 63 ->addCancelButton($cancel_uri); 64 } 65 66 $charges = id(new PhortuneChargeQuery()) 67 ->setViewer($viewer) 68 ->withCartPHIDs(array($cart->getPHID())) 69 ->withStatuses( 70 array( 71 PhortuneCharge::STATUS_HOLD, 72 PhortuneCharge::STATUS_CHARGED, 73 )) 74 ->execute(); 75 76 $amounts = mpull($charges, 'getAmountAsCurrency'); 77 $maximum = PhortuneCurrency::newFromList($amounts); 78 $v_refund = $maximum->formatForDisplay(); 79 80 $errors = array(); 81 $e_refund = true; 82 if ($request->isFormPost()) { 83 if ($is_refund) { 84 try { 85 $refund = PhortuneCurrency::newFromUserInput( 86 $viewer, 87 $request->getStr('refund')); 88 $refund->assertInRange('0.00 USD', $maximum->formatForDisplay()); 89 } catch (Exception $ex) { 90 $errors[] = $ex->getMessage(); 91 $e_refund = pht('Invalid'); 92 } 93 } else { 94 $refund = $maximum; 95 } 96 97 if (!$errors) { 98 $charges = msort($charges, 'getID'); 99 $charges = array_reverse($charges); 100 101 if ($charges) { 102 $providers = id(new PhortunePaymentProviderConfigQuery()) 103 ->setViewer($viewer) 104 ->withPHIDs(mpull($charges, 'getProviderPHID')) 105 ->execute(); 106 $providers = mpull($providers, null, 'getPHID'); 107 } else { 108 $providers = array(); 109 } 110 111 foreach ($charges as $charge) { 112 $refundable = $charge->getAmountRefundableAsCurrency(); 113 if (!$refundable->isPositive()) { 114 // This charge is a refund, or has already been fully refunded. 115 continue; 116 } 117 118 if ($refund->isGreaterThan($refundable)) { 119 $refund_amount = $refundable; 120 } else { 121 $refund_amount = $refund; 122 } 123 124 $provider_config = idx($providers, $charge->getProviderPHID()); 125 if (!$provider_config) { 126 throw new Exception(pht('Unable to load provider for charge!')); 127 } 128 129 $provider = $provider_config->buildProvider(); 130 131 $refund_charge = $cart->willRefundCharge( 132 $viewer, 133 $provider, 134 $charge, 135 $refund_amount); 136 137 $refunded = false; 138 try { 139 $provider->refundCharge($charge, $refund_charge); 140 $refunded = true; 141 } catch (Exception $ex) { 142 phlog($ex); 143 $cart->didFailRefund($charge, $refund_charge); 144 } 145 146 if ($refunded) { 147 $cart->didRefundCharge($charge, $refund_charge); 148 $refund = $refund->subtract($refund_amount); 149 } 150 151 if (!$refund->isPositive()) { 152 break; 153 } 154 } 155 156 if ($refund->isPositive()) { 157 throw new Exception(pht('Unable to refund some charges!')); 158 } 159 160 // TODO: If every HOLD and CHARGING transaction has been fully refunded 161 // and we're in a HOLD, REVIEW, PURCHASING or CHARGED cart state we 162 // probably need to kick the cart back to READY here (or maybe kill 163 // it if it was in REVIEW)? 164 165 return id(new AphrontRedirectResponse())->setURI($cancel_uri); 166 } 167 } 168 169 if ($is_refund) { 170 $title = pht('Refund Order?'); 171 $body = pht( 172 'Really refund this order?'); 173 $button = pht('Refund Order'); 174 $cancel_text = pht('Cancel'); 175 176 $form = id(new AphrontFormView()) 177 ->setUser($viewer) 178 ->appendChild( 179 id(new AphrontFormTextControl()) 180 ->setName('refund') 181 ->setLabel(pht('Amount')) 182 ->setError($e_refund) 183 ->setValue($v_refund)); 184 185 $form = $form->buildLayoutView(); 186 187 } else { 188 $title = pht('Cancel Order?'); 189 $body = pht( 190 'Really cancel this order? Any payment will be refunded.'); 191 $button = pht('Cancel Order'); 192 193 // Don't give the user a "Cancel" button in response to a "Cancel?" 194 // prompt, as it's confusing. 195 $cancel_text = pht('Do Not Cancel Order'); 196 197 $form = null; 198 } 199 200 return $this->newDialog() 201 ->setTitle($title) 202 ->setErrors($errors) 203 ->appendChild($body) 204 ->appendChild($form) 205 ->addSubmitButton($button) 206 ->addCancelButton($cancel_uri, $cancel_text); 207 } 208 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |