title: Paypal API Request with MVC3
body: <p>I have been having a hell of a time sorting out <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&amp;content_ID=developer/library_download_sdks" rel="nofollow">PayPal's documentation</a>, as all of it applies to ASP but not MVC (including their otherwise-handy Integration Wizard). I have seen oft-reference <a href="http://www.west-wind.com/presentations/PayPalIntegration/PayPalIntegration.asp" rel="nofollow">guide by Rick Strahl</a>, but it is also for ASP, and I have no experience with Webforms to translate into MVC.</p>
  
  <p>I am stuck on one part, and have a security concern about another.</p>
  
  <p>First: how do you actually submit the request to the paypal api? The <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&amp;content_ID=developer/e_howto_api_ECGettingStarted" rel="nofollow">documentation</a> tells you to use a form with your password in it.</p>
  
  <pre><code>&lt;form method=post action=https://api-3t.sandbox.paypal.com/nvp&gt; 
      &lt;input type=hidden name=USER value=API_username&gt; 
      &lt;input type=hidden name=PWD value=API_password&gt; 
      &lt;input type=hidden name=SIGNATURE value=API_signature&gt; 
      &lt;input type=hidden name=VERSION value=XX.0&gt; 
      &lt;input type=hidden name=PAYMENTREQUEST_0_PAYMENTACTION 
          value=Sale&gt; 
      &lt;input name=PAYMENTREQUEST_0_AMT value=19.95&gt; 
      &lt;input type=hidden name=RETURNURL 
          value=https://www.YourReturnURL.com&gt; 
      &lt;input type=hidden name=CANCELURL 
          value=https://www.YourCancelURL.com&gt; 
      &lt;input type=submit name=METHOD value=SetExpressCheckout&gt; 
  &lt;/form&gt;
  </code></pre>
  
  <p>Surely this form isn't going into the View where anyone with the sense to check your source could steal your login info? I would assume this needs to be done from the controller, but I don't know how to create do this from the controller. HttpWebRequest and WebClient look promising, but I don't know how to actually add a form to them.</p>
  
  <p>Second: even if I did make this form and api call from inside the controller where the user can't see it, anyone with access to the source code (like the web host, or other developers) would be able to see the password. This doesn't seem like good security. What's the practice here? How can this be made secure?</p>
  
  <p><strong>EDIT</strong>
  For the people who come looking, this is how I eventually submitted the initial request (condensed the code into one block for readability)</p>
  
  <pre><code>public static string GetResponse(RequestContext context, decimal price)
      {
          HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api-3t.sandbox.paypal.com/nvp");
          //HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://api-3t.sandbox.paypal.com/nvp");
  
          request.Method = "POST";
  
          UrlHelper url = new UrlHelper(context);
          string urlBase = string.Format("{0}://{1}", context.HttpContext.Request.Url.Scheme, context.HttpContext.Request.Url.Authority);
  
          string formContent =  "USER=" + System.Configuration.ConfigurationManager.AppSettings["paypalUser"] +
                  "&amp;PWD=" + System.Configuration.ConfigurationManager.AppSettings["paypalPassword"] +
                  "&amp;SIGNATURE=" + System.Configuration.ConfigurationManager.AppSettings["paypalSignature"] +
                  "&amp;VERSION=84.0" +
                  "&amp;PAYMENTREQUEST_0_PAYMENTACTION=Sale" +
                  "&amp;PAYMENTREQUEST_0_AMT=" + String.Format("{0:0.00}", price) +
                  "&amp;RETURNURL=" + urlBase + url.Action("Confirm", "Checkout") +
                  "&amp;CANCELURL=" + urlBase + url.Action("Canceled", "Checkout") +
                  "&amp;METHOD=SetExpressCheckout"; 
  
          byte[] byteArray = Encoding.UTF8.GetBytes(formContent);
          request.ContentType = "application/x-www-form-urlencoded";
          request.ContentLength = byteArray.Length;
          Stream dataStream = request.GetRequestStream();
          dataStream.Write(byteArray, 0, byteArray.Length);
          dataStream.Close();
          WebResponse response = request.GetResponse();
          dataStream = response.GetResponseStream();
          StreamReader reader = new StreamReader(dataStream);
          string responseFromServer = HttpUtility.UrlDecode(reader.ReadToEnd());
  
          reader.Close();
          dataStream.Close();
          response.Close();
  
          return responseFromServer;
      }
  </code></pre>