Page MenuHomePhabricator

D10666.id25621.diff
No OneTemporary

D10666.id25621.diff

diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php
--- a/src/applications/base/controller/PhabricatorController.php
+++ b/src/applications/base/controller/PhabricatorController.php
@@ -518,7 +518,7 @@
*
* @return AphrontDialogView New dialog.
*/
- protected function newDialog() {
+ public function newDialog() {
$submit_uri = new PhutilURI($this->getRequest()->getRequestURI());
$submit_uri = $submit_uri->getPath();
diff --git a/src/applications/phortune/controller/PhortuneCartCheckoutController.php b/src/applications/phortune/controller/PhortuneCartCheckoutController.php
--- a/src/applications/phortune/controller/PhortuneCartCheckoutController.php
+++ b/src/applications/phortune/controller/PhortuneCartCheckoutController.php
@@ -111,7 +111,20 @@
$provider = $method->buildPaymentProvider();
$charge = $cart->willApplyCharge($viewer, $provider, $method);
- $provider->applyCharge($method, $charge);
+
+ try {
+ $provider->applyCharge($method, $charge);
+ } catch (Exception $ex) {
+ $cart->didFailCharge($charge);
+ return $this->newDialog()
+ ->setTitle(pht('Charge Failed'))
+ ->appendParagraph(
+ pht(
+ 'Unable to make payment: %s',
+ $ex->getMessage()))
+ ->addCancelButton($cart->getCheckoutURI(), pht('Continue'));
+ }
+
$cart->didApplyCharge($charge);
$done_uri = $cart->getDoneURI();
diff --git a/src/applications/phortune/provider/PhortunePayPalPaymentProvider.php b/src/applications/phortune/provider/PhortunePayPalPaymentProvider.php
--- a/src/applications/phortune/provider/PhortunePayPalPaymentProvider.php
+++ b/src/applications/phortune/provider/PhortunePayPalPaymentProvider.php
@@ -339,9 +339,27 @@
// difficult for now and we can't reasonably just fail these charges.
var_dump($result);
-
die();
- break;
+
+ $success = false; // TODO: <----
+
+ // TODO: Clean this up once that mess up there ^^^^^ gets cleaned up.
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ if ($success) {
+ $cart->didApplyCharge($charge);
+ $response = id(new AphrontRedirectResponse())->setURI(
+ $cart->getDoneURI());
+ } else {
+ $cart->didFailCharge($charge);
+
+ $response = $controller
+ ->newDialog()
+ ->setTitle(pht('Charge Failed'))
+ ->addCancelButton($cart->getCheckoutURI(), pht('Continue'));
+ }
+ unset($unguarded);
+
+ return $response;
case 'cancel':
var_dump($_REQUEST);
break;
diff --git a/src/applications/phortune/provider/PhortuneWePayPaymentProvider.php b/src/applications/phortune/provider/PhortuneWePayPaymentProvider.php
--- a/src/applications/phortune/provider/PhortuneWePayPaymentProvider.php
+++ b/src/applications/phortune/provider/PhortuneWePayPaymentProvider.php
@@ -145,7 +145,7 @@
}
public function getPaymentMethodDescription() {
- return pht('Credit Card or Bank Account');
+ return pht('Credit or Debit Card');
}
public function getPaymentMethodIcon() {
@@ -286,10 +286,10 @@
$params = array(
'account_id' => $this->getWePayAccountID(),
- 'short_description' => 'Services', // TODO
+ 'short_description' => $cart->getName(),
'type' => 'SERVICE',
'amount' => $price->formatBareValue(),
- 'long_description' => 'Services', // TODO
+ 'long_description' => $cart->getName(),
'reference_id' => $cart->getPHID(),
'app_fee' => 0,
'fee_payer' => 'Payee',
@@ -305,7 +305,10 @@
'shipping_fee' => 0,
'charge_tax' => 0,
'mode' => 'regular',
- 'funding_sources' => 'bank,cc',
+
+ // TODO: We could accept bank accounts but the hold/capture rules
+ // are not quite clear. Just accept credit cards for now.
+ 'funding_sources' => 'cc',
);
$charge = $cart->willApplyCharge($viewer, $this);
@@ -322,6 +325,11 @@
->setIsExternal(true)
->setURI($uri);
case 'charge':
+ if ($cart->getStatus() !== PhortuneCart::STATUS_PURCHASING) {
+ return id(new AphrontRedirectResponse())
+ ->setURI($cart->getCheckoutURI());
+ }
+
$checkout_id = $request->getInt('checkout_id');
$params = array(
'checkout_id' => $checkout_id,
@@ -333,24 +341,41 @@
pht('Checkout reference ID does not match cart PHID!'));
}
- switch ($checkout->state) {
- case 'authorized':
- case 'reserved':
- case 'captured':
- break;
- default:
- throw new Exception(
- pht(
- 'Checkout is in bad state "%s"!',
- $result->state));
- }
-
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
- $cart->didApplyCharge($charge);
+ switch ($checkout->state) {
+ case 'authorized':
+ case 'reserved':
+ case 'captured':
+ // TODO: Are these all really "done" states, and not "hold"
+ // states? Cards and bank accounts both come back as "authorized"
+ // on the staging environment. Figure out what happens in
+ // production?
+
+ $cart->didApplyCharge($charge);
+
+ $response = id(new AphrontRedirectResponse())->setURI(
+ $cart->getDoneURI());
+ break;
+ default:
+ // It's not clear if we can ever get here on the web workflow,
+ // WePay doesn't seem to return back to us after a failure (the
+ // workflow dead-ends instead).
+
+ $cart->didFailCharge($charge);
+
+ $response = $controller
+ ->newDialog()
+ ->setTitle(pht('Charge Failed'))
+ ->appendParagraph(
+ pht(
+ 'Unable to make payment (checkout state is "%s").',
+ $checkout->state))
+ ->addCancelButton($cart->getCheckoutURI(), pht('Continue'));
+ break;
+ }
unset($unguarded);
- return id(new AphrontRedirectResponse())
- ->setURI($cart->getDoneURI());
+ return $response;
case 'cancel':
// TODO: I don't know how it's possible to cancel out of a WePay
// charge workflow.
diff --git a/src/applications/phortune/storage/PhortuneCart.php b/src/applications/phortune/storage/PhortuneCart.php
--- a/src/applications/phortune/storage/PhortuneCart.php
+++ b/src/applications/phortune/storage/PhortuneCart.php
@@ -146,6 +146,37 @@
return $this;
}
+ public function didFailCharge(PhortuneCharge $charge) {
+ $charge->setStatus(PhortuneCharge::STATUS_FAILED);
+
+ $this->openTransaction();
+ $this->beginReadLocking();
+
+ $copy = clone $this;
+ $copy->reload();
+
+ if ($copy->getStatus() !== self::STATUS_PURCHASING) {
+ throw new Exception(
+ pht(
+ 'Cart has wrong status ("%s") to call didFailCharge(), '.
+ 'expected "%s".',
+ $copy->getStatus(),
+ self::STATUS_PURCHASING));
+ }
+
+ $charge->save();
+
+ // Move the cart back into STATUS_READY so the user can try
+ // making the purchase again.
+ $this->setStatus(self::STATUS_READY)->save();
+
+ $this->endReadLocking();
+ $this->saveTransaction();
+
+ return $this;
+ }
+
+
public function willRefundCharge(
PhabricatorUser $actor,
PhortunePaymentProvider $provider,

File Metadata

Mime Type
text/plain
Expires
Sun, Oct 27, 11:38 AM (3 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6749759
Default Alt Text
D10666.id25621.diff (7 KB)

Event Timeline