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:
parent
7d3b54ba53
commit
b170d1c15f
10 changed files with 119 additions and 57 deletions
|
@ -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',
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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'))
|
||||||
|
|
|
@ -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/');
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 |
Loading…
Reference in a new issue