public function processRequest()
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $account = id(new PhortuneAccountQuery())->setViewer($viewer)->withIDs(array($this->accountID))->executeOne();
     if (!$account) {
         return new Aphront404Response();
     }
     $account_id = $account->getID();
     $merchant = id(new PhortuneMerchantQuery())->setViewer($viewer)->withIDs(array($request->getInt('merchantID')))->executeOne();
     if (!$merchant) {
         return new Aphront404Response();
     }
     $cart_id = $request->getInt('cartID');
     $subscription_id = $request->getInt('subscriptionID');
     if ($cart_id) {
         $cancel_uri = $this->getApplicationURI("cart/{$cart_id}/checkout/");
     } else {
         if ($subscription_id) {
             $cancel_uri = $this->getApplicationURI("{$account_id}/subscription/edit/{$subscription_id}/");
         } else {
             $cancel_uri = $this->getApplicationURI($account->getID() . '/');
         }
     }
     $providers = $this->loadCreatePaymentMethodProvidersForMerchant($merchant);
     if (!$providers) {
         throw new Exception(pht('There are no payment providers enabled that can add payment ' . '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');
         if (empty($providers[$provider_id])) {
             $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($cancel_uri);
         }
     }
     $provider = $providers[$provider_id];
     $errors = array();
     if ($request->isFormPost() && $request->getBool('isProviderForm')) {
         $method = id(new PhortunePaymentMethod())->setAccountPHID($account->getPHID())->setAuthorPHID($viewer->getPHID())->setMerchantPHID($merchant->getPHID())->setProviderPHID($provider->getProviderConfig()->getPHID())->setStatus(PhortunePaymentMethod::STATUS_ACTIVE);
         if (!$errors) {
             $errors = $this->processClientErrors($provider, $request->getStr('errors'));
         }
         if (!$errors) {
             $client_token_raw = $request->getStr('token');
             $client_token = null;
             try {
                 $client_token = phutil_json_decode($client_token_raw);
             } catch (PhutilJSONParserException $ex) {
                 $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')));
             }
             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();
             // If we added this method on a cart flow, return to the cart to
             // check out.
             if ($cart_id) {
                 $next_uri = $this->getApplicationURI("cart/{$cart_id}/checkout/?paymentMethodID=" . $method->getID());
             } else {
                 if ($subscription_id) {
                     $next_uri = $cancel_uri;
                 } else {
                     $account_uri = $this->getApplicationURI($account->getID() . '/');
                     $next_uri = new PhutilURI($account_uri);
                     $next_uri->setFragment('payment');
                 }
             }
             return id(new AphrontRedirectResponse())->setURI($next_uri);
         } else {
             $dialog = id(new AphrontDialogView())->setUser($viewer)->setTitle(pht('Error Adding Payment Method'))->appendChild(id(new PHUIInfoView())->setErrors($errors))->addCancelButton($request->getRequestURI());
             return id(new AphrontDialogResponse())->setDialog($dialog);
         }
     }
     $form = $provider->renderCreatePaymentMethodForm($request, $errors);
     $form->setUser($viewer)->setAction($request->getRequestURI())->setWorkflow(true)->addHiddenInput('providerID', $provider_id)->addHiddenInput('cartID', $request->getInt('cartID'))->addHiddenInput('subscriptionID', $request->getInt('subscriptionID'))->addHiddenInput('isProviderForm', true)->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Add Payment Method'))->addCancelButton($cancel_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()));
 }
 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()));
 }