@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Make payment method management somewhat more reasonable in Phortune

Summary: Ref T2787. Shows somewhat-useful information, allows payment methods to be disabled and renamed.

Test Plan: Created, renamed, disabled payment methods.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T2787

Differential Revision: https://secure.phabricator.com/D10203

+450 -278
+4 -4
src/__phutil_library_map__.php
··· 2479 2479 'PhortuneNoPaymentProviderException' => 'applications/phortune/exception/PhortuneNoPaymentProviderException.php', 2480 2480 'PhortuneNotImplementedException' => 'applications/phortune/exception/PhortuneNotImplementedException.php', 2481 2481 'PhortunePaymentMethod' => 'applications/phortune/storage/PhortunePaymentMethod.php', 2482 + 'PhortunePaymentMethodCreateController' => 'applications/phortune/controller/PhortunePaymentMethodCreateController.php', 2483 + 'PhortunePaymentMethodDisableController' => 'applications/phortune/controller/PhortunePaymentMethodDisableController.php', 2482 2484 'PhortunePaymentMethodEditController' => 'applications/phortune/controller/PhortunePaymentMethodEditController.php', 2483 - 'PhortunePaymentMethodListController' => 'applications/phortune/controller/PhortunePaymentMethodListController.php', 2484 2485 'PhortunePaymentMethodQuery' => 'applications/phortune/query/PhortunePaymentMethodQuery.php', 2485 - 'PhortunePaymentMethodViewController' => 'applications/phortune/controller/PhortunePaymentMethodViewController.php', 2486 2486 'PhortunePaymentProvider' => 'applications/phortune/provider/PhortunePaymentProvider.php', 2487 2487 'PhortunePaymentProviderTestCase' => 'applications/phortune/provider/__tests__/PhortunePaymentProviderTestCase.php', 2488 2488 'PhortunePaypalPaymentProvider' => 'applications/phortune/provider/PhortunePaypalPaymentProvider.php', ··· 5386 5386 'PhortuneDAO', 5387 5387 'PhabricatorPolicyInterface', 5388 5388 ), 5389 + 'PhortunePaymentMethodCreateController' => 'PhortuneController', 5390 + 'PhortunePaymentMethodDisableController' => 'PhortuneController', 5389 5391 'PhortunePaymentMethodEditController' => 'PhortuneController', 5390 - 'PhortunePaymentMethodListController' => 'PhabricatorController', 5391 5392 'PhortunePaymentMethodQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 5392 - 'PhortunePaymentMethodViewController' => 'PhabricatorController', 5393 5393 'PhortunePaymentProviderTestCase' => 'PhabricatorTestCase', 5394 5394 'PhortunePaypalPaymentProvider' => 'PhortunePaymentProvider', 5395 5395 'PhortuneProduct' => array(
+6 -2
src/applications/phortune/application/PhabricatorPhortuneApplication.php
··· 36 36 '' => 'PhortuneLandingController', 37 37 '(?P<accountID>\d+)/' => array( 38 38 '' => 'PhortuneAccountViewController', 39 - 'paymentmethod/' => array( 40 - 'edit/' => 'PhortunePaymentMethodEditController', 39 + 'card/' => array( 40 + 'new/' => 'PhortunePaymentMethodCreateController', 41 41 ), 42 42 'buy/(?P<productID>\d+)/' => 'PhortuneProductPurchaseController', 43 + ), 44 + 'card/(?P<id>\d+)/' => array( 45 + 'edit/' => 'PhortunePaymentMethodEditController', 46 + 'disable/' => 'PhortunePaymentMethodDisableController', 43 47 ), 44 48 'cart/(?P<id>\d+)/' => array( 45 49 '' => 'PhortuneCartViewController',
+35 -12
src/applications/phortune/controller/PhortuneAccountViewController.php
··· 79 79 80 80 private function buildPaymentMethodsSection(PhortuneAccount $account) { 81 81 $request = $this->getRequest(); 82 - $user = $request->getUser(); 82 + $viewer = $request->getUser(); 83 + 84 + $can_edit = PhabricatorPolicyFilter::hasCapability( 85 + $viewer, 86 + $account, 87 + PhabricatorPolicyCapability::CAN_EDIT); 83 88 84 89 $id = $account->getID(); 85 90 ··· 88 93 ->addActionLink( 89 94 id(new PHUIButtonView()) 90 95 ->setTag('a') 91 - ->setHref($this->getApplicationURI($id.'/paymentmethod/edit/')) 96 + ->setHref($this->getApplicationURI($id.'/card/new/')) 92 97 ->setText(pht('Add Payment Method')) 93 98 ->setIcon(id(new PHUIIconView())->setIconFont('fa-plus'))); 94 99 95 100 $list = id(new PHUIObjectItemListView()) 96 - ->setUser($user) 101 + ->setUser($viewer) 97 102 ->setNoDataString( 98 103 pht('No payment methods associated with this account.')); 99 104 100 105 $methods = id(new PhortunePaymentMethodQuery()) 101 - ->setViewer($user) 106 + ->setViewer($viewer) 102 107 ->withAccountPHIDs(array($account->getPHID())) 103 - ->withStatus(PhortunePaymentMethodQuery::STATUS_OPEN) 104 108 ->execute(); 105 109 106 110 if ($methods) { ··· 108 112 } 109 113 110 114 foreach ($methods as $method) { 115 + $id = $method->getID(); 116 + 111 117 $item = new PHUIObjectItemView(); 112 - $item->setHeader($method->getBrand().' / '.$method->getLastFourDigits()); 118 + $item->setHeader($method->getFullDisplayName()); 113 119 114 120 switch ($method->getStatus()) { 115 121 case PhortunePaymentMethod::STATUS_ACTIVE: 116 - $item->addAttribute(pht('Active')); 117 122 $item->setBarColor('green'); 123 + 124 + $disable_uri = $this->getApplicationURI('card/'.$id.'/disable/'); 125 + $item->addAction( 126 + id(new PHUIListItemView()) 127 + ->setIcon('fa-times') 128 + ->setHref($disable_uri) 129 + ->setDisabled(!$can_edit) 130 + ->setWorkflow(true)); 131 + break; 132 + case PhortunePaymentMethod::STATUS_DISABLED: 133 + $item->setDisabled(true); 118 134 break; 119 135 } 120 136 121 - $item->addAttribute( 122 - pht( 123 - 'Added %s by %s', 124 - phabricator_datetime($method->getDateCreated(), $user), 125 - $this->getHandle($method->getAuthorPHID())->renderLink())); 137 + $provider = $method->buildPaymentProvider(); 138 + $item->addAttribute($provider->getPaymentMethodProviderDescription()); 139 + $item->setImageURI($provider->getPaymentMethodIcon()); 140 + 141 + $edit_uri = $this->getApplicationURI('card/'.$id.'/edit/'); 142 + 143 + $item->addAction( 144 + id(new PHUIListItemView()) 145 + ->setIcon('fa-pencil') 146 + ->setHref($edit_uri) 147 + ->setDisabled(!$can_edit) 148 + ->setWorkflow(!$can_edit)); 126 149 127 150 $list->addItem($item); 128 151 }
+3 -2
src/applications/phortune/controller/PhortuneCartCheckoutController.php
··· 28 28 $methods = id(new PhortunePaymentMethodQuery()) 29 29 ->setViewer($viewer) 30 30 ->withAccountPHIDs(array($account->getPHID())) 31 - ->withStatus(PhortunePaymentMethodQuery::STATUS_OPEN) 31 + ->withStatuses(array(PhortunePaymentMethod::STATUS_ACTIVE)) 32 32 ->execute(); 33 33 34 34 $e_method = null; ··· 57 57 ->setAccountPHID($account->getPHID()) 58 58 ->setCartPHID($cart->getPHID()) 59 59 ->setAuthorPHID($viewer->getPHID()) 60 + ->setPaymentProviderKey($provider->getProviderKey()) 60 61 ->setPaymentMethodPHID($method->getPHID()) 61 62 ->setAmountInCents($cart->getTotalPriceInCents()) 62 63 ->setStatus(PhortuneCharge::STATUS_PENDING); ··· 105 106 $method_control->setError($e_method); 106 107 107 108 $payment_method_uri = $this->getApplicationURI( 108 - $account->getID().'/paymentmethod/edit/'); 109 + $account->getID().'/card/new/'); 109 110 110 111 $form = id(new AphrontFormView()) 111 112 ->setUser($viewer)
+233
src/applications/phortune/controller/PhortunePaymentMethodCreateController.php
··· 1 + <?php 2 + 3 + final class PhortunePaymentMethodCreateController 4 + extends PhortuneController { 5 + 6 + private $accountID; 7 + 8 + public function willProcessRequest(array $data) { 9 + $this->accountID = $data['accountID']; 10 + } 11 + 12 + public function processRequest() { 13 + $request = $this->getRequest(); 14 + $user = $request->getUser(); 15 + 16 + $account = id(new PhortuneAccountQuery()) 17 + ->setViewer($user) 18 + ->withIDs(array($this->accountID)) 19 + ->executeOne(); 20 + if (!$account) { 21 + return new Aphront404Response(); 22 + } 23 + 24 + $cancel_uri = $this->getApplicationURI($account->getID().'/'); 25 + $account_uri = $this->getApplicationURI($account->getID().'/'); 26 + 27 + $providers = PhortunePaymentProvider::getProvidersForAddPaymentMethod(); 28 + if (!$providers) { 29 + throw new Exception( 30 + 'There are no payment providers enabled that can add payment '. 31 + 'methods.'); 32 + } 33 + 34 + $provider_key = $request->getStr('providerKey'); 35 + if (empty($providers[$provider_key])) { 36 + $choices = array(); 37 + foreach ($providers as $provider) { 38 + $choices[] = $this->renderSelectProvider($provider); 39 + } 40 + 41 + $content = phutil_tag( 42 + 'div', 43 + array( 44 + 'class' => 'phortune-payment-method-list', 45 + ), 46 + $choices); 47 + 48 + return $this->newDialog() 49 + ->setRenderDialogAsDiv(true) 50 + ->setTitle(pht('Add Payment Method')) 51 + ->appendParagraph(pht('Choose a payment method to add:')) 52 + ->appendChild($content) 53 + ->addCancelButton($account_uri); 54 + } 55 + 56 + $provider = $providers[$provider_key]; 57 + 58 + $errors = array(); 59 + if ($request->isFormPost() && $request->getBool('isProviderForm')) { 60 + $method = id(new PhortunePaymentMethod()) 61 + ->setAccountPHID($account->getPHID()) 62 + ->setAuthorPHID($user->getPHID()) 63 + ->setStatus(PhortunePaymentMethod::STATUS_ACTIVE) 64 + ->setProviderType($provider->getProviderType()) 65 + ->setProviderDomain($provider->getProviderDomain()); 66 + 67 + if (!$errors) { 68 + $errors = $this->processClientErrors( 69 + $provider, 70 + $request->getStr('errors')); 71 + } 72 + 73 + if (!$errors) { 74 + $client_token_raw = $request->getStr('token'); 75 + $client_token = json_decode($client_token_raw, true); 76 + if (!is_array($client_token)) { 77 + $errors[] = pht( 78 + 'There was an error decoding token information submitted by the '. 79 + 'client. Expected a JSON-encoded token dictionary, received: %s.', 80 + nonempty($client_token_raw, pht('nothing'))); 81 + } else { 82 + if (!$provider->validateCreatePaymentMethodToken($client_token)) { 83 + $errors[] = pht( 84 + 'There was an error with the payment token submitted by the '. 85 + 'client. Expected a valid dictionary, received: %s.', 86 + $client_token_raw); 87 + } 88 + } 89 + if (!$errors) { 90 + $errors = $provider->createPaymentMethodFromRequest( 91 + $request, 92 + $method, 93 + $client_token); 94 + } 95 + } 96 + 97 + if (!$errors) { 98 + $method->save(); 99 + 100 + $save_uri = new PhutilURI($account_uri); 101 + $save_uri->setFragment('payment'); 102 + return id(new AphrontRedirectResponse())->setURI($save_uri); 103 + } else { 104 + $dialog = id(new AphrontDialogView()) 105 + ->setUser($user) 106 + ->setTitle(pht('Error Adding Payment Method')) 107 + ->appendChild(id(new AphrontErrorView())->setErrors($errors)) 108 + ->addCancelButton($request->getRequestURI()); 109 + 110 + return id(new AphrontDialogResponse())->setDialog($dialog); 111 + } 112 + } 113 + 114 + $form = $provider->renderCreatePaymentMethodForm($request, $errors); 115 + 116 + $form 117 + ->setUser($user) 118 + ->setAction($request->getRequestURI()) 119 + ->setWorkflow(true) 120 + ->addHiddenInput('providerKey', $provider_key) 121 + ->addHiddenInput('isProviderForm', true) 122 + ->appendChild( 123 + id(new AphrontFormSubmitControl()) 124 + ->setValue(pht('Add Payment Method')) 125 + ->addCancelButton($account_uri)); 126 + 127 + $box = id(new PHUIObjectBoxView()) 128 + ->setHeaderText($provider->getPaymentMethodDescription()) 129 + ->setForm($form); 130 + 131 + $crumbs = $this->buildApplicationCrumbs(); 132 + $crumbs->addTextCrumb(pht('Add Payment Method')); 133 + 134 + return $this->buildApplicationPage( 135 + array( 136 + $crumbs, 137 + $box, 138 + ), 139 + array( 140 + 'title' => $provider->getPaymentMethodDescription(), 141 + )); 142 + } 143 + 144 + private function renderSelectProvider( 145 + PhortunePaymentProvider $provider) { 146 + 147 + $request = $this->getRequest(); 148 + $user = $request->getUser(); 149 + 150 + $description = $provider->getPaymentMethodDescription(); 151 + $icon_uri = $provider->getPaymentMethodIcon(); 152 + $details = $provider->getPaymentMethodProviderDescription(); 153 + 154 + $this->requireResource('phortune-css'); 155 + 156 + $icon = id(new PHUIIconView()) 157 + ->setImage($icon_uri) 158 + ->addClass('phortune-payment-icon'); 159 + 160 + $button = id(new PHUIButtonView()) 161 + ->setSize(PHUIButtonView::BIG) 162 + ->setColor(PHUIButtonView::GREY) 163 + ->setIcon($icon) 164 + ->setText($description) 165 + ->setSubtext($details); 166 + 167 + $form = id(new AphrontFormView()) 168 + ->setUser($user) 169 + ->addHiddenInput('providerKey', $provider->getProviderKey()) 170 + ->appendChild($button); 171 + 172 + return $form; 173 + } 174 + 175 + private function processClientErrors( 176 + PhortunePaymentProvider $provider, 177 + $client_errors_raw) { 178 + 179 + $errors = array(); 180 + 181 + $client_errors = json_decode($client_errors_raw, true); 182 + if (!is_array($client_errors)) { 183 + $errors[] = pht( 184 + 'There was an error decoding error information submitted by the '. 185 + 'client. Expected a JSON-encoded list of error codes, received: %s.', 186 + nonempty($client_errors_raw, pht('nothing'))); 187 + } 188 + 189 + foreach (array_unique($client_errors) as $key => $client_error) { 190 + $client_errors[$key] = $provider->translateCreatePaymentMethodErrorCode( 191 + $client_error); 192 + } 193 + 194 + foreach (array_unique($client_errors) as $client_error) { 195 + switch ($client_error) { 196 + case PhortuneErrCode::ERR_CC_INVALID_NUMBER: 197 + $message = pht( 198 + 'The card number you entered is not a valid card number. Check '. 199 + 'that you entered it correctly.'); 200 + break; 201 + case PhortuneErrCode::ERR_CC_INVALID_CVC: 202 + $message = pht( 203 + 'The CVC code you entered is not a valid CVC code. Check that '. 204 + 'you entered it correctly. The CVC code is a 3-digit or 4-digit '. 205 + 'numeric code which usually appears on the back of the card.'); 206 + break; 207 + case PhortuneErrCode::ERR_CC_INVALID_EXPIRY: 208 + $message = pht( 209 + 'The card expiration date is not a valid expiration date. Check '. 210 + 'that you entered it correctly. You can not add an expired card '. 211 + 'as a payment method.'); 212 + break; 213 + default: 214 + $message = $provider->getCreatePaymentMethodErrorMessage( 215 + $client_error); 216 + if (!$message) { 217 + $message = pht( 218 + "There was an unexpected error ('%s') processing payment ". 219 + "information.", 220 + $client_error); 221 + 222 + phlog($message); 223 + } 224 + break; 225 + } 226 + 227 + $errors[$client_error] = $message; 228 + } 229 + 230 + return $errors; 231 + } 232 + 233 + }
+64
src/applications/phortune/controller/PhortunePaymentMethodDisableController.php
··· 1 + <?php 2 + 3 + final class PhortunePaymentMethodDisableController 4 + extends PhortuneController { 5 + 6 + private $methodID; 7 + 8 + public function willProcessRequest(array $data) { 9 + $this->methodID = $data['id']; 10 + } 11 + 12 + public function processRequest() { 13 + $request = $this->getRequest(); 14 + $viewer = $request->getUser(); 15 + 16 + $method = id(new PhortunePaymentMethodQuery()) 17 + ->setViewer($viewer) 18 + ->withIDs(array($this->methodID)) 19 + ->requireCapabilities( 20 + array( 21 + PhabricatorPolicyCapability::CAN_VIEW, 22 + PhabricatorPolicyCapability::CAN_EDIT, 23 + )) 24 + ->executeOne(); 25 + if (!$method) { 26 + return new Aphront404Response(); 27 + } 28 + 29 + if ($method->getStatus() == PhortunePaymentMethod::STATUS_DISABLED) { 30 + return new Aphront400Response(); 31 + } 32 + 33 + $account = $method->getAccount(); 34 + $account_uri = $this->getApplicationURI($account->getID().'/'); 35 + 36 + if ($request->isFormPost()) { 37 + 38 + // TODO: ApplicationTransactions! 39 + $method 40 + ->setStatus(PhortunePaymentMethod::STATUS_DISABLED) 41 + ->save(); 42 + 43 + return id(new AphrontRedirectResponse())->setURI($account_uri); 44 + } 45 + 46 + return $this->newDialog() 47 + ->setTitle(pht('Disable Payment Method?')) 48 + ->setShortTitle(pht('Disable Payment Method')) 49 + ->appendParagraph( 50 + pht( 51 + 'Disable the payment method "%s"?', 52 + phutil_tag( 53 + 'strong', 54 + array(), 55 + $method->getFullDisplayName()))) 56 + ->appendParagraph( 57 + pht( 58 + 'You will no longer be able to make payments using this payment '. 59 + 'method. Disabled payment methods can not be reactivated.')) 60 + ->addCancelButton($account_uri) 61 + ->addSubmitButton(pht('Disable Payment Method')); 62 + } 63 + 64 + }
+43 -191
src/applications/phortune/controller/PhortunePaymentMethodEditController.php
··· 3 3 final class PhortunePaymentMethodEditController 4 4 extends PhortuneController { 5 5 6 - private $accountID; 6 + private $methodID; 7 7 8 8 public function willProcessRequest(array $data) { 9 - $this->accountID = $data['accountID']; 9 + $this->methodID = $data['id']; 10 10 } 11 11 12 12 public function processRequest() { 13 13 $request = $this->getRequest(); 14 - $user = $request->getUser(); 14 + $viewer = $request->getUser(); 15 15 16 - $account = id(new PhortuneAccountQuery()) 17 - ->setViewer($user) 18 - ->withIDs(array($this->accountID)) 16 + $method = id(new PhortunePaymentMethodQuery()) 17 + ->setViewer($viewer) 18 + ->withIDs(array($this->methodID)) 19 + ->requireCapabilities( 20 + array( 21 + PhabricatorPolicyCapability::CAN_VIEW, 22 + PhabricatorPolicyCapability::CAN_EDIT, 23 + )) 19 24 ->executeOne(); 20 - if (!$account) { 25 + if (!$method) { 21 26 return new Aphront404Response(); 22 27 } 23 28 24 - $cancel_uri = $this->getApplicationURI($account->getID().'/'); 29 + $account = $method->getAccount(); 25 30 $account_uri = $this->getApplicationURI($account->getID().'/'); 26 31 27 - $providers = PhortunePaymentProvider::getProvidersForAddPaymentMethod(); 28 - if (!$providers) { 29 - throw new Exception( 30 - 'There are no payment providers enabled that can add payment '. 31 - 'methods.'); 32 - } 32 + if ($request->isFormPost()) { 33 33 34 - $provider_key = $request->getStr('providerKey'); 35 - if (empty($providers[$provider_key])) { 36 - $choices = array(); 37 - foreach ($providers as $provider) { 38 - $choices[] = $this->renderSelectProvider($provider); 39 - } 34 + $name = $request->getStr('name'); 40 35 41 - $content = phutil_tag( 42 - 'div', 43 - array( 44 - 'class' => 'phortune-payment-method-list', 45 - ), 46 - $choices); 36 + // TODO: Use ApplicationTransactions 47 37 48 - return $this->newDialog() 49 - ->setRenderDialogAsDiv(true) 50 - ->setTitle(pht('Add Payment Method')) 51 - ->appendParagraph(pht('Choose a payment method to add:')) 52 - ->appendChild($content) 53 - ->addCancelButton($account_uri); 54 - } 38 + $method->setName($name); 39 + $method->save(); 55 40 56 - $provider = $providers[$provider_key]; 57 - 58 - $errors = array(); 59 - if ($request->isFormPost() && $request->getBool('isProviderForm')) { 60 - $method = id(new PhortunePaymentMethod()) 61 - ->setAccountPHID($account->getPHID()) 62 - ->setAuthorPHID($user->getPHID()) 63 - ->setStatus(PhortunePaymentMethod::STATUS_ACTIVE) 64 - ->setProviderType($provider->getProviderType()) 65 - ->setProviderDomain($provider->getProviderDomain()); 66 - 67 - if (!$errors) { 68 - $errors = $this->processClientErrors( 69 - $provider, 70 - $request->getStr('errors')); 71 - } 72 - 73 - if (!$errors) { 74 - $client_token_raw = $request->getStr('token'); 75 - $client_token = json_decode($client_token_raw, true); 76 - if (!is_array($client_token)) { 77 - $errors[] = pht( 78 - 'There was an error decoding token information submitted by the '. 79 - 'client. Expected a JSON-encoded token dictionary, received: %s.', 80 - nonempty($client_token_raw, pht('nothing'))); 81 - } else { 82 - if (!$provider->validateCreatePaymentMethodToken($client_token)) { 83 - $errors[] = pht( 84 - 'There was an error with the payment token submitted by the '. 85 - 'client. Expected a valid dictionary, received: %s.', 86 - $client_token_raw); 87 - } 88 - } 89 - if (!$errors) { 90 - $errors = $provider->createPaymentMethodFromRequest( 91 - $request, 92 - $method, 93 - $client_token); 94 - } 95 - } 96 - 97 - if (!$errors) { 98 - $method->save(); 99 - 100 - $save_uri = new PhutilURI($account_uri); 101 - $save_uri->setFragment('payment'); 102 - return id(new AphrontRedirectResponse())->setURI($save_uri); 103 - } else { 104 - $dialog = id(new AphrontDialogView()) 105 - ->setUser($user) 106 - ->setTitle(pht('Error Adding Payment Method')) 107 - ->appendChild(id(new AphrontErrorView())->setErrors($errors)) 108 - ->addCancelButton($request->getRequestURI()); 109 - 110 - return id(new AphrontDialogResponse())->setDialog($dialog); 111 - } 41 + return id(new AphrontRedirectResponse())->setURI($account_uri); 112 42 } 113 43 114 - $form = $provider->renderCreatePaymentMethodForm($request, $errors); 44 + $provider = $method->buildPaymentProvider(); 115 45 116 - $form 117 - ->setUser($user) 118 - ->setAction($request->getRequestURI()) 119 - ->setWorkflow(true) 120 - ->addHiddenInput('providerKey', $provider_key) 121 - ->addHiddenInput('isProviderForm', true) 46 + $form = id(new AphrontFormView()) 47 + ->setUser($viewer) 48 + ->appendChild( 49 + id(new AphrontFormTextControl()) 50 + ->setLabel(pht('Name')) 51 + ->setName('name') 52 + ->setValue($method->getName())) 53 + ->appendChild( 54 + id(new AphrontFormStaticControl()) 55 + ->setLabel(pht('Details')) 56 + ->setValue($method->getSummary())) 57 + ->appendChild( 58 + id(new AphrontFormStaticControl()) 59 + ->setLabel(pht('Expires')) 60 + ->setValue($method->getDisplayExpires())) 122 61 ->appendChild( 123 62 id(new AphrontFormSubmitControl()) 124 - ->setValue(pht('Add Payment Method')) 125 - ->addCancelButton($account_uri)); 63 + ->addCancelButton($account_uri) 64 + ->setValue(pht('Save Changes'))); 126 65 127 66 $box = id(new PHUIObjectBoxView()) 128 - ->setHeaderText($provider->getPaymentMethodDescription()) 129 - ->setForm($form); 67 + ->setHeaderText(pht('Edit Payment Method')) 68 + ->appendChild($form); 130 69 131 70 $crumbs = $this->buildApplicationCrumbs(); 132 - $crumbs->addTextCrumb(pht('Add Payment Method')); 71 + $crumbs->addTextCrumb($account->getName(), $account_uri); 72 + $crumbs->addTextCrumb($method->getDisplayName()); 73 + $crumbs->addTextCrumb(pht('Edit')); 133 74 134 75 return $this->buildApplicationPage( 135 76 array( ··· 137 78 $box, 138 79 ), 139 80 array( 140 - 'title' => $provider->getPaymentMethodDescription(), 81 + 'title' => pht('Edit Payment Method'), 141 82 )); 142 - } 143 - 144 - private function renderSelectProvider( 145 - PhortunePaymentProvider $provider) { 146 - 147 - $request = $this->getRequest(); 148 - $user = $request->getUser(); 149 - 150 - $description = $provider->getPaymentMethodDescription(); 151 - $icon_uri = $provider->getPaymentMethodIcon(); 152 - $details = $provider->getPaymentMethodProviderDescription(); 153 - 154 - $this->requireResource('phortune-css'); 155 - 156 - $icon = id(new PHUIIconView()) 157 - ->setImage($icon_uri) 158 - ->addClass('phortune-payment-icon'); 159 - 160 - $button = id(new PHUIButtonView()) 161 - ->setSize(PHUIButtonView::BIG) 162 - ->setColor(PHUIButtonView::GREY) 163 - ->setIcon($icon) 164 - ->setText($description) 165 - ->setSubtext($details); 166 - 167 - $form = id(new AphrontFormView()) 168 - ->setUser($user) 169 - ->addHiddenInput('providerKey', $provider->getProviderKey()) 170 - ->appendChild($button); 171 - 172 - return $form; 173 - } 174 - 175 - private function processClientErrors( 176 - PhortunePaymentProvider $provider, 177 - $client_errors_raw) { 178 - 179 - $errors = array(); 180 - 181 - $client_errors = json_decode($client_errors_raw, true); 182 - if (!is_array($client_errors)) { 183 - $errors[] = pht( 184 - 'There was an error decoding error information submitted by the '. 185 - 'client. Expected a JSON-encoded list of error codes, received: %s.', 186 - nonempty($client_errors_raw, pht('nothing'))); 187 - } 188 - 189 - foreach (array_unique($client_errors) as $key => $client_error) { 190 - $client_errors[$key] = $provider->translateCreatePaymentMethodErrorCode( 191 - $client_error); 192 - } 193 - 194 - foreach (array_unique($client_errors) as $client_error) { 195 - switch ($client_error) { 196 - case PhortuneErrCode::ERR_CC_INVALID_NUMBER: 197 - $message = pht( 198 - 'The card number you entered is not a valid card number. Check '. 199 - 'that you entered it correctly.'); 200 - break; 201 - case PhortuneErrCode::ERR_CC_INVALID_CVC: 202 - $message = pht( 203 - 'The CVC code you entered is not a valid CVC code. Check that '. 204 - 'you entered it correctly. The CVC code is a 3-digit or 4-digit '. 205 - 'numeric code which usually appears on the back of the card.'); 206 - break; 207 - case PhortuneErrCode::ERR_CC_INVALID_EXPIRY: 208 - $message = pht( 209 - 'The card expiration date is not a valid expiration date. Check '. 210 - 'that you entered it correctly. You can not add an expired card '. 211 - 'as a payment method.'); 212 - break; 213 - default: 214 - $message = $provider->getCreatePaymentMethodErrorMessage( 215 - $client_error); 216 - if (!$message) { 217 - $message = pht( 218 - "There was an unexpected error ('%s') processing payment ". 219 - "information.", 220 - $client_error); 221 - 222 - phlog($message); 223 - } 224 - break; 225 - } 226 - 227 - $errors[$client_error] = $message; 228 - } 229 - 230 - return $errors; 231 83 } 232 84 233 85 }
-21
src/applications/phortune/controller/PhortunePaymentMethodListController.php
··· 1 - <?php 2 - 3 - final class PhortunePaymentMethodListController extends PhabricatorController { 4 - 5 - public function processRequest() { 6 - $request = $this->getRequest(); 7 - $user = $request->getUser(); 8 - 9 - $title = pht('Payment Methods'); 10 - $crumbs = $this->buildApplicationCrumbs(); 11 - 12 - return $this->buildApplicationPage( 13 - array( 14 - $crumbs, 15 - ), 16 - array( 17 - 'title' => $title, 18 - )); 19 - } 20 - 21 - }
-19
src/applications/phortune/controller/PhortunePaymentMethodViewController.php
··· 1 - <?php 2 - 3 - final class PhortunePaymentMethodViewController extends PhabricatorController { 4 - 5 - public function processRequest() { 6 - 7 - $title = '...'; 8 - $crumbs = $this->buildApplicationCrumbs(); 9 - 10 - return $this->buildApplicationPage( 11 - array( 12 - $crumbs, 13 - ), 14 - array( 15 - 'title' => $title, 16 - )); 17 - } 18 - 19 - }
+4
src/applications/phortune/provider/PhortuneBalancedPaymentProvider.php
··· 27 27 return pht('Processed by Balanced'); 28 28 } 29 29 30 + public function getDefaultPaymentMethodDisplayName( 31 + PhortunePaymentMethod $method) { 32 + return pht('Credit/Debit Card'); 33 + } 30 34 31 35 public function canHandlePaymentMethod(PhortunePaymentMethod $method) { 32 36 $type = $method->getMetadataValue('type');
+5
src/applications/phortune/provider/PhortunePaymentProvider.php
··· 169 169 throw new PhortuneNotImplementedException($this); 170 170 } 171 171 172 + public function getDefaultPaymentMethodDisplayName( 173 + PhortunePaymentMethod $method) { 174 + throw new PhortuneNotImplementedException($this); 175 + } 176 + 172 177 173 178 /* -( One-Time Payments )-------------------------------------------------- */ 174 179
+4
src/applications/phortune/provider/PhortuneStripePaymentProvider.php
··· 27 27 return pht('Processed by Stripe'); 28 28 } 29 29 30 + public function getDefaultPaymentMethodDisplayName( 31 + PhortunePaymentMethod $method) { 32 + return pht('Credit/Debit Card'); 33 + } 30 34 31 35 public function canHandlePaymentMethod(PhortunePaymentMethod $method) { 32 36 $type = $method->getMetadataValue('type');
+12 -2
src/applications/phortune/provider/PhortuneTestPaymentProvider.php
··· 26 26 return pht('Infinite Free Money'); 27 27 } 28 28 29 + public function getDefaultPaymentMethodDisplayName( 30 + PhortunePaymentMethod $method) { 31 + return pht('Vast Wealth'); 32 + } 33 + 29 34 public function canHandlePaymentMethod(PhortunePaymentMethod $method) { 30 35 $type = $method->getMetadataValue('type'); 31 - return ($type === 'test.cash' || $type === 'test.multiple'); 36 + return ($type === 'test.wealth' || $type == 'test.multiple'); 32 37 } 33 38 34 39 protected function executeCharge( ··· 69 74 $method 70 75 ->setExpires('2050', '01') 71 76 ->setBrand('FreeMoney') 72 - ->setLastFourDigits('9999'); 77 + ->setLastFourDigits('9999') 78 + ->setMetadata( 79 + array( 80 + 'type' => 'test.wealth', 81 + )); 73 82 83 + return array(); 74 84 } 75 85 76 86
+11 -23
src/applications/phortune/query/PhortunePaymentMethodQuery.php
··· 6 6 private $ids; 7 7 private $phids; 8 8 private $accountPHIDs; 9 - 10 - const STATUS_ANY = 'status-any'; 11 - const STATUS_OPEN = 'status-open'; 12 - private $status = self::STATUS_ANY; 9 + private $statuses; 13 10 14 11 public function withIDs(array $ids) { 15 12 $this->ids = $ids; ··· 26 23 return $this; 27 24 } 28 25 29 - public function withStatus($status) { 30 - $this->status = $status; 26 + public function withStatuses(array $statuses) { 27 + $this->statuses = $statuses; 31 28 return $this; 32 29 } 33 30 ··· 77 74 private function buildWhereClause(AphrontDatabaseConnection $conn) { 78 75 $where = array(); 79 76 80 - if ($this->ids) { 77 + if ($this->ids !== null) { 81 78 $where[] = qsprintf( 82 79 $conn, 83 80 'id IN (%Ld)', 84 81 $this->ids); 85 82 } 86 83 87 - if ($this->phids) { 84 + if ($this->phids !== null) { 88 85 $where[] = qsprintf( 89 86 $conn, 90 87 'phid IN (%Ls)', 91 88 $this->phids); 92 89 } 93 90 94 - if ($this->accountPHIDs) { 91 + if ($this->accountPHIDs !== null) { 95 92 $where[] = qsprintf( 96 93 $conn, 97 94 'accountPHID IN (%Ls)', 98 95 $this->accountPHIDs); 99 96 } 100 97 101 - switch ($this->status) { 102 - case self::STATUS_ANY; 103 - break; 104 - case self::STATUS_OPEN: 105 - $where[] = qsprintf( 106 - $conn, 107 - 'status in (%Ls)', 108 - array( 109 - PhortunePaymentMethod::STATUS_ACTIVE, 110 - PhortunePaymentMethod::STATUS_FAILED, 111 - )); 112 - break; 113 - default: 114 - throw new Exception("Unknown status '{$this->status}'!"); 98 + if ($this->statuses !== null) { 99 + $where[] = qsprintf( 100 + $conn, 101 + 'status IN (%Ls)', 102 + $this->statuses); 115 103 } 116 104 117 105 $where[] = $this->buildPagingClause($conn);
+26 -2
src/applications/phortune/storage/PhortunePaymentMethod.php
··· 8 8 implements PhabricatorPolicyInterface { 9 9 10 10 const STATUS_ACTIVE = 'payment:active'; 11 - const STATUS_FAILED = 'payment:failed'; 12 - const STATUS_REMOVED = 'payment:removed'; 11 + const STATUS_DISABLED = 'payment:disabled'; 13 12 14 13 protected $name = ''; 15 14 protected $status; ··· 82 81 return head($accept); 83 82 } 84 83 84 + 85 + public function getDisplayName() { 86 + if (strlen($this->name)) { 87 + return $this->name; 88 + } 89 + 90 + $provider = $this->buildPaymentProvider(); 91 + return $provider->getDefaultPaymentMethodDisplayName($this); 92 + } 93 + 94 + public function getFullDisplayName() { 95 + return pht('%s (%s)', $this->getDisplayName(), $this->getSummary()); 96 + } 97 + 98 + public function getSummary() { 99 + return pht('%s %s', $this->getBrand(), $this->getLastFourDigits()); 100 + } 101 + 85 102 public function setExpires($year, $month) { 86 103 $this->expires = $year.'-'.$month; 87 104 return $this; 105 + } 106 + 107 + public function getDisplayExpires() { 108 + list($year, $month) = explode('-', $this->getExpires()); 109 + $month = sprintf('%02d', $month); 110 + $year = substr($year, -2); 111 + return $month.'/'.$year; 88 112 } 89 113 90 114