public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $cart = id(new PhortuneCartQuery())->setViewer($viewer)->withIDs(array($this->id))->needPurchases(true)->executeOne();
     if (!$cart) {
         return new Aphront404Response();
     }
     $account = $cart->getAccount();
     $account_uri = $this->getApplicationURI($account->getID() . '/');
     $methods = id(new PhortunePaymentMethodQuery())->setViewer($viewer)->withAccountPHIDs(array($account->getPHID()))->withStatuses(array(PhortunePaymentMethod::STATUS_ACTIVE))->execute();
     $e_method = null;
     $errors = array();
     if ($request->isFormPost()) {
         // Require CAN_EDIT on the cart to actually make purchases.
         PhabricatorPolicyFilter::requireCapability($viewer, $cart, PhabricatorPolicyCapability::CAN_EDIT);
         $method_id = $request->getInt('paymentMethodID');
         $method = idx($methods, $method_id);
         if (!$method) {
             $e_method = pht('Required');
             $errors[] = pht('You must choose a payment method.');
         }
         if (!$errors) {
             $provider = $method->buildPaymentProvider();
             $charge = id(new PhortuneCharge())->setAccountPHID($account->getPHID())->setCartPHID($cart->getPHID())->setAuthorPHID($viewer->getPHID())->setPaymentProviderKey($provider->getProviderKey())->setPaymentMethodPHID($method->getPHID())->setAmountInCents($cart->getTotalPriceInCents())->setStatus(PhortuneCharge::STATUS_PENDING);
             $charge->openTransaction();
             $charge->save();
             $cart->setStatus(PhortuneCart::STATUS_PURCHASING);
             $cart->save();
             $charge->saveTransaction();
             $provider->applyCharge($method, $charge);
             $cart->setStatus(PhortuneCart::STATUS_PURCHASED);
             $cart->save();
             $view_uri = $this->getApplicationURI('cart/' . $cart->getID() . '/');
             return id(new AphrontRedirectResponse())->setURI($view_uri);
         }
     }
     $cart_box = $this->buildCartContents($cart);
     $cart_box->setFormErrors($errors);
     $title = pht('Buy Stuff');
     if (!$methods) {
         $method_control = id(new AphrontFormStaticControl())->setLabel(pht('Payment Method'))->setValue(phutil_tag('em', array(), pht('No payment methods configured.')));
     } else {
         $method_control = id(new AphrontFormRadioButtonControl())->setLabel(pht('Payment Method'))->setName('paymentMethodID')->setValue($request->getInt('paymentMethodID'));
         foreach ($methods as $method) {
             $method_control->addButton($method->getID(), $method->getFullDisplayName(), $method->getDescription());
         }
     }
     $method_control->setError($e_method);
     $payment_method_uri = $this->getApplicationURI($account->getID() . '/card/new/');
     $form = id(new AphrontFormView())->setUser($viewer)->appendChild($method_control);
     $add_providers = PhortunePaymentProvider::getProvidersForAddPaymentMethod();
     if ($add_providers) {
         $new_method = phutil_tag('a', array('class' => 'button grey', 'href' => $payment_method_uri, 'sigil' => 'workflow'), pht('Add New Payment Method'));
         $form->appendChild(id(new AphrontFormMarkupControl())->setValue($new_method));
     }
     if ($methods || $add_providers) {
         $form->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Submit Payment'))->setDisabled(!$methods));
     }
     $provider_form = null;
     $pay_providers = PhortunePaymentProvider::getProvidersForOneTimePayment();
     if ($pay_providers) {
         $one_time_options = array();
         foreach ($pay_providers as $provider) {
             $one_time_options[] = $provider->renderOneTimePaymentButton($account, $cart, $viewer);
         }
         $one_time_options = phutil_tag('div', array('class' => 'phortune-payment-onetime-list'), $one_time_options);
         $provider_form = new PHUIFormLayoutView();
         $provider_form->appendChild(id(new AphrontFormMarkupControl())->setLabel('Pay With')->setValue($one_time_options));
     }
     $payment_box = id(new PHUIObjectBoxView())->setHeaderText(pht('Choose Payment Method'))->appendChild($form)->appendChild($provider_form);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb($title);
     return $this->buildApplicationPage(array($crumbs, $cart_box, $payment_box), array('title' => $title));
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $account = id(new PhortuneAccountQuery())->setViewer($user)->withIDs(array($this->accountID))->executeOne();
     if (!$account) {
         return new Aphront404Response();
     }
     $cancel_uri = $this->getApplicationURI($account->getID() . '/');
     $account_uri = $this->getApplicationURI($account->getID() . '/');
     $providers = PhortunePaymentProvider::getProvidersForAddPaymentMethod();
     if (!$providers) {
         throw new Exception('There are no payment providers enabled that can add payment ' . 'methods.');
     }
     $provider_key = $request->getStr('providerKey');
     if (empty($providers[$provider_key])) {
         $choices = array();
         foreach ($providers as $provider) {
             $choices[] = $this->renderSelectProvider($provider);
         }
         $content = phutil_tag('div', array('class' => 'phortune-payment-method-list'), $choices);
         return $this->newDialog()->setRenderDialogAsDiv(true)->setTitle(pht('Add Payment Method'))->appendParagraph(pht('Choose a payment method to add:'))->appendChild($content)->addCancelButton($account_uri);
     }
     $provider = $providers[$provider_key];
     $errors = array();
     if ($request->isFormPost() && $request->getBool('isProviderForm')) {
         $method = id(new PhortunePaymentMethod())->setAccountPHID($account->getPHID())->setAuthorPHID($user->getPHID())->setStatus(PhortunePaymentMethod::STATUS_ACTIVE)->setProviderType($provider->getProviderType())->setProviderDomain($provider->getProviderDomain());
         if (!$errors) {
             $errors = $this->processClientErrors($provider, $request->getStr('errors'));
         }
         if (!$errors) {
             $client_token_raw = $request->getStr('token');
             $client_token = json_decode($client_token_raw, true);
             if (!is_array($client_token)) {
                 $errors[] = pht('There was an error decoding token information submitted by the ' . 'client. Expected a JSON-encoded token dictionary, received: %s.', nonempty($client_token_raw, pht('nothing')));
             } else {
                 if (!$provider->validateCreatePaymentMethodToken($client_token)) {
                     $errors[] = pht('There was an error with the payment token submitted by the ' . 'client. Expected a valid dictionary, received: %s.', $client_token_raw);
                 }
             }
             if (!$errors) {
                 $errors = $provider->createPaymentMethodFromRequest($request, $method, $client_token);
             }
         }
         if (!$errors) {
             $method->save();
             $save_uri = new PhutilURI($account_uri);
             $save_uri->setFragment('payment');
             return id(new AphrontRedirectResponse())->setURI($save_uri);
         } else {
             $dialog = id(new AphrontDialogView())->setUser($user)->setTitle(pht('Error Adding Payment Method'))->appendChild(id(new AphrontErrorView())->setErrors($errors))->addCancelButton($request->getRequestURI());
             return id(new AphrontDialogResponse())->setDialog($dialog);
         }
     }
     $form = $provider->renderCreatePaymentMethodForm($request, $errors);
     $form->setUser($user)->setAction($request->getRequestURI())->setWorkflow(true)->addHiddenInput('providerKey', $provider_key)->addHiddenInput('isProviderForm', true)->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Add Payment Method'))->addCancelButton($account_uri));
     $box = id(new PHUIObjectBoxView())->setHeaderText($provider->getPaymentMethodDescription())->setForm($form);
     $crumbs = $this->buildApplicationCrumbs();
     $crumbs->addTextCrumb(pht('Add Payment Method'));
     return $this->buildApplicationPage(array($crumbs, $box), array('title' => $provider->getPaymentMethodDescription()));
 }