1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-21 13:00:56 +01:00

Make it easier to add payment methods for subscription autopay

Summary:
Fixes T7424. Ref T6308.

Currently, there's no option to just add a card directly from the autopay UI. Add a button so this works.

Also, chip away at T6308 a bit. This isn't perfect but looks a little less out of place.

Test Plan:
{F327637}

- Added a payment method, then set it as autopay.

Reviewers: chad, btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T6308, T7424

Differential Revision: https://secure.phabricator.com/D11935
This commit is contained in:
epriestley 2015-03-02 13:01:08 -08:00
parent 7d3b54ba53
commit b170d1c15f
10 changed files with 119 additions and 57 deletions

View file

@ -7,7 +7,7 @@
*/ */
return array( return array(
'names' => array( 'names' => array(
'core.pkg.css' => 'cd54f10c', 'core.pkg.css' => 'd9fa6161',
'core.pkg.js' => '23d653bb', 'core.pkg.js' => '23d653bb',
'darkconsole.pkg.js' => '8ab24e01', 'darkconsole.pkg.js' => '8ab24e01',
'differential.pkg.css' => '4c3242f8', 'differential.pkg.css' => '4c3242f8',
@ -83,7 +83,7 @@ return array(
'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee', 'rsrc/css/application/pholio/pholio-edit.css' => '3ad9d1ee',
'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '8e545e49',
'rsrc/css/application/pholio/pholio.css' => '95174bdd', 'rsrc/css/application/pholio/pholio.css' => '95174bdd',
'rsrc/css/application/phortune/phortune-credit-card-form.css' => 'b25b4beb', 'rsrc/css/application/phortune/phortune-credit-card-form.css' => '8391eb02',
'rsrc/css/application/phortune/phortune.css' => '9149f103', 'rsrc/css/application/phortune/phortune.css' => '9149f103',
'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad', 'rsrc/css/application/phrequent/phrequent.css' => 'ffc185ad',
'rsrc/css/application/phriction/phriction-document-css.css' => '0d16bc9a', 'rsrc/css/application/phriction/phriction-document-css.css' => '0d16bc9a',
@ -129,7 +129,7 @@ return array(
'rsrc/css/phui/phui-document.css' => '620b1eec', 'rsrc/css/phui/phui-document.css' => '620b1eec',
'rsrc/css/phui/phui-feed-story.css' => 'c9f3a0b5', 'rsrc/css/phui/phui-feed-story.css' => 'c9f3a0b5',
'rsrc/css/phui/phui-fontkit.css' => '4394f216', 'rsrc/css/phui/phui-fontkit.css' => '4394f216',
'rsrc/css/phui/phui-form-view.css' => '8b78a986', 'rsrc/css/phui/phui-form-view.css' => '76f0b086',
'rsrc/css/phui/phui-form.css' => 'f535f938', 'rsrc/css/phui/phui-form.css' => 'f535f938',
'rsrc/css/phui/phui-header-view.css' => '083669db', 'rsrc/css/phui/phui-header-view.css' => '083669db',
'rsrc/css/phui/phui-icon.css' => 'd35aa857', 'rsrc/css/phui/phui-icon.css' => 'd35aa857',
@ -242,7 +242,6 @@ return array(
'rsrc/image/checker_dark.png' => 'd8e65881', 'rsrc/image/checker_dark.png' => 'd8e65881',
'rsrc/image/checker_light.png' => 'a0155918', 'rsrc/image/checker_light.png' => 'a0155918',
'rsrc/image/checker_lighter.png' => 'd5da91b6', 'rsrc/image/checker_lighter.png' => 'd5da91b6',
'rsrc/image/credit_cards.png' => '72b8ede8',
'rsrc/image/darkload.gif' => '1ffd3ec6', 'rsrc/image/darkload.gif' => '1ffd3ec6',
'rsrc/image/divot.png' => '94dded62', 'rsrc/image/divot.png' => '94dded62',
'rsrc/image/examples/hero.png' => '979a86ae', 'rsrc/image/examples/hero.png' => '979a86ae',
@ -766,7 +765,7 @@ return array(
'pholio-edit-css' => '3ad9d1ee', 'pholio-edit-css' => '3ad9d1ee',
'pholio-inline-comments-css' => '8e545e49', 'pholio-inline-comments-css' => '8e545e49',
'phortune-credit-card-form' => '2290aeef', 'phortune-credit-card-form' => '2290aeef',
'phortune-credit-card-form-css' => 'b25b4beb', 'phortune-credit-card-form-css' => '8391eb02',
'phortune-css' => '9149f103', 'phortune-css' => '9149f103',
'phrequent-css' => 'ffc185ad', 'phrequent-css' => 'ffc185ad',
'phriction-document-css' => '0d16bc9a', 'phriction-document-css' => '0d16bc9a',
@ -784,7 +783,7 @@ return array(
'phui-font-icon-base-css' => '3dad2ae3', 'phui-font-icon-base-css' => '3dad2ae3',
'phui-fontkit-css' => '4394f216', 'phui-fontkit-css' => '4394f216',
'phui-form-css' => 'f535f938', 'phui-form-css' => 'f535f938',
'phui-form-view-css' => '8b78a986', 'phui-form-view-css' => '76f0b086',
'phui-header-view-css' => '083669db', 'phui-header-view-css' => '083669db',
'phui-icon-view-css' => 'd35aa857', 'phui-icon-view-css' => 'd35aa857',
'phui-image-mask-css' => '5a8b09c8', 'phui-image-mask-css' => '5a8b09c8',

View file

@ -20,6 +20,7 @@ final class PhortunePaymentMethodCreateController
if (!$account) { if (!$account) {
return new Aphront404Response(); return new Aphront404Response();
} }
$account_id = $account->getID();
$merchant = id(new PhortuneMerchantQuery()) $merchant = id(new PhortuneMerchantQuery())
->setViewer($viewer) ->setViewer($viewer)
@ -30,8 +31,12 @@ final class PhortunePaymentMethodCreateController
} }
$cart_id = $request->getInt('cartID'); $cart_id = $request->getInt('cartID');
$subscription_id = $request->getInt('subscriptionID');
if ($cart_id) { if ($cart_id) {
$cancel_uri = $this->getApplicationURI("cart/{$cart_id}/checkout/"); $cancel_uri = $this->getApplicationURI("cart/{$cart_id}/checkout/");
} else if ($subscription_id) {
$cancel_uri = $this->getApplicationURI(
"{$account_id}/subscription/edit/{$subscription_id}/");
} else { } else {
$cancel_uri = $this->getApplicationURI($account->getID().'/'); $cancel_uri = $this->getApplicationURI($account->getID().'/');
} }
@ -43,6 +48,10 @@ final class PhortunePaymentMethodCreateController
'methods.'); 'methods.');
} }
if (count($providers) == 1) {
// If there's only one provider, always choose it.
$provider_id = head_key($providers);
} else {
$provider_id = $request->getInt('providerID'); $provider_id = $request->getInt('providerID');
if (empty($providers[$provider_id])) { if (empty($providers[$provider_id])) {
$choices = array(); $choices = array();
@ -64,6 +73,7 @@ final class PhortunePaymentMethodCreateController
->appendChild($content) ->appendChild($content)
->addCancelButton($cancel_uri); ->addCancelButton($cancel_uri);
} }
}
$provider = $providers[$provider_id]; $provider = $providers[$provider_id];
@ -114,6 +124,8 @@ final class PhortunePaymentMethodCreateController
if ($cart_id) { if ($cart_id) {
$next_uri = $this->getApplicationURI( $next_uri = $this->getApplicationURI(
"cart/{$cart_id}/checkout/?paymentMethodID=".$method->getID()); "cart/{$cart_id}/checkout/?paymentMethodID=".$method->getID());
} else if ($subscription_id) {
$next_uri = $cancel_uri;
} else { } else {
$account_uri = $this->getApplicationURI($account->getID().'/'); $account_uri = $this->getApplicationURI($account->getID().'/');
$next_uri = new PhutilURI($account_uri); $next_uri = new PhutilURI($account_uri);
@ -140,6 +152,7 @@ final class PhortunePaymentMethodCreateController
->setWorkflow(true) ->setWorkflow(true)
->addHiddenInput('providerID', $provider_id) ->addHiddenInput('providerID', $provider_id)
->addHiddenInput('cartID', $request->getInt('cartID')) ->addHiddenInput('cartID', $request->getInt('cartID'))
->addHiddenInput('subscriptionID', $request->getInt('subscriptionID'))
->addHiddenInput('isProviderForm', true) ->addHiddenInput('isProviderForm', true)
->appendChild( ->appendChild(
id(new AphrontFormSubmitControl()) id(new AphrontFormSubmitControl())

View file

@ -103,6 +103,20 @@ final class PhortuneSubscriptionEditController extends PhortuneController {
$view_uri); $view_uri);
$crumbs->addTextCrumb(pht('Edit')); $crumbs->addTextCrumb(pht('Edit'));
$uri = $this->getApplicationURI($account->getID().'/card/new/');
$uri = new PhutilURI($uri);
$uri->setQueryParam('merchantID', $merchant->getID());
$uri->setQueryParam('subscriptionID', $subscription->getID());
$add_method_button = phutil_tag(
'a',
array(
'href' => $uri,
'class' => 'button grey',
),
pht('Add Payment Method...'));
$form = id(new AphrontFormView()) $form = id(new AphrontFormView())
->setUser($viewer) ->setUser($viewer)
->appendChild( ->appendChild(
@ -111,6 +125,9 @@ final class PhortuneSubscriptionEditController extends PhortuneController {
->setLabel(pht('Autopay With')) ->setLabel(pht('Autopay With'))
->setValue($current_phid) ->setValue($current_phid)
->setOptions($options)) ->setOptions($options))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue($add_method_button))
->appendChild( ->appendChild(
id(new AphrontFormSubmitControl()) id(new AphrontFormSubmitControl())
->setValue(pht('Save Changes')) ->setValue(pht('Save Changes'))

View file

@ -277,6 +277,8 @@ final class PhortuneStripePaymentProvider extends PhortunePaymentProvider {
array $errors) { array $errors) {
$ccform = id(new PhortuneCreditCardForm()) $ccform = id(new PhortuneCreditCardForm())
->setSecurityAssurance(
pht('Payments are processed securely by Stripe.'))
->setUser($request->getUser()) ->setUser($request->getUser())
->setErrors($errors) ->setErrors($errors)
->addScript('https://js.stripe.com/v2/'); ->addScript('https://js.stripe.com/v2/');

View file

@ -144,6 +144,8 @@ final class PhortuneTestPaymentProvider extends PhortunePaymentProvider {
array $errors) { array $errors) {
$ccform = id(new PhortuneCreditCardForm()) $ccform = id(new PhortuneCreditCardForm())
->setSecurityAssurance(
pht('This is a test payment provider.'))
->setUser($request->getUser()) ->setUser($request->getUser())
->setErrors($errors); ->setErrors($errors);

View file

@ -10,6 +10,16 @@ final class PhortuneCreditCardForm {
private $cardNumberError; private $cardNumberError;
private $cardCVCError; private $cardCVCError;
private $cardExpirationError; private $cardExpirationError;
private $securityAssurance;
public function setSecurityAssurance($security_assurance) {
$this->securityAssurance = $security_assurance;
return $this;
}
public function getSecurityAssurance() {
return $this->securityAssurance;
}
public function setUser(PhabricatorUser $user) { public function setUser(PhabricatorUser $user) {
$this->user = $user; $this->user = $user;
@ -57,11 +67,11 @@ final class PhortuneCreditCardForm {
$errors = $this->errors; $errors = $this->errors;
$e_number = isset($errors[PhortuneErrCode::ERR_CC_INVALID_NUMBER]) $e_number = isset($errors[PhortuneErrCode::ERR_CC_INVALID_NUMBER])
? pht('Invalid') ? pht('Invalid')
: true; : null;
$e_cvc = isset($errors[PhortuneErrCode::ERR_CC_INVALID_CVC]) $e_cvc = isset($errors[PhortuneErrCode::ERR_CC_INVALID_CVC])
? pht('Invalid') ? pht('Invalid')
: true; : null;
$e_expiry = isset($errors[PhortuneErrCode::ERR_CC_INVALID_EXPIRY]) $e_expiry = isset($errors[PhortuneErrCode::ERR_CC_INVALID_EXPIRY])
? pht('Invalid') ? pht('Invalid')
@ -69,21 +79,6 @@ final class PhortuneCreditCardForm {
$form $form
->setID($form_id) ->setID($form_id)
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel('')
->setValue(
javelin_tag(
'div',
array(
'class' => 'credit-card-logos',
'sigil' => 'has-tooltip',
'meta' => array(
'tip' => 'We support Visa, Mastercard, American Express, '.
'Discover, JCB, and Diners Club.',
'size' => 440,
),
))))
->appendChild( ->appendChild(
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())
->setLabel('Card Number') ->setLabel('Card Number')
@ -94,6 +89,7 @@ final class PhortuneCreditCardForm {
id(new AphrontFormTextControl()) id(new AphrontFormTextControl())
->setLabel('CVC') ->setLabel('CVC')
->setDisableAutocomplete(true) ->setDisableAutocomplete(true)
->addClass('aphront-form-cvc-input')
->setSigil('cvc-input') ->setSigil('cvc-input')
->setError($e_cvc)) ->setError($e_cvc))
->appendChild( ->appendChild(
@ -102,6 +98,25 @@ final class PhortuneCreditCardForm {
->setUser($this->user) ->setUser($this->user)
->setError($e_expiry)); ->setError($e_expiry));
$assurance = $this->getSecurityAssurance();
if ($assurance) {
$assurance = phutil_tag(
'div',
array(
'class' => 'phortune-security-assurance',
),
array(
id(new PHUIIconView())
->setIconFont('fa-lock grey'),
' ',
$assurance,
));
$form->appendChild(
id(new AphrontFormMarkupControl())
->setValue($assurance));
}
return $form; return $form;
} }
} }

View file

@ -14,6 +14,7 @@ abstract class AphrontFormControl extends AphrontView {
private $formPage; private $formPage;
private $required; private $required;
private $hidden; private $hidden;
private $classes;
public function setHidden($hidden) { public function setHidden($hidden) {
$this->hidden = $hidden; $this->hidden = $hidden;
@ -162,6 +163,11 @@ abstract class AphrontFormControl extends AphrontView {
return true; return true;
} }
public function addClass($class) {
$this->classes[] = $class;
return $this;
}
final public function render() { final public function render() {
if (!$this->shouldRender()) { if (!$this->shouldRender()) {
return null; return null;
@ -225,6 +231,11 @@ abstract class AphrontFormControl extends AphrontView {
$classes[] = 'aphront-form-control'; $classes[] = 'aphront-form-control';
$classes[] = 'grouped'; $classes[] = 'grouped';
$classes[] = $custom_class; $classes[] = $custom_class;
if ($this->classes) {
foreach ($this->classes as $class) {
$classes[] = $class;
}
}
$style = $this->controlStyle; $style = $this->controlStyle;
if ($this->hidden) { if ($this->hidden) {

View file

@ -2,7 +2,6 @@
* @provides phortune-credit-card-form-css * @provides phortune-credit-card-form-css
*/ */
.credit-card-logos { .phortune-security-assurance {
background: url(/rsrc/image/credit_cards.png) no-repeat 0px 2px; color: {$lightgreytext};
height: 32px;
} }

View file

@ -111,6 +111,10 @@
width: 100%; width: 100%;
} }
.aphront-form-cvc-input input {
width: 64px;
}
.aphront-form-input textarea { .aphront-form-input textarea {
display: block; display: block;
width: 100%; width: 100%;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB