title: Manage Paypal IPN with Google Apps Script
body: <p>To manage IPN there is 4 steps  :</p>
  
  <ol>
  <li>Receive by post request info of payment by Paypal  </li>
  <li>Return HTTP 200 response</li>
  <li>Return complete unaltered message to paypal</li>
  <li>Receive Verified or Invalid from Paypal after 3</li>
  </ol>
  
  <p>To do that there is an example <a href="https://sites.google.com/site/scriptsexamples/home/announcements/ivestartedalittleexperiment#TOC-Annex" rel="nofollow noreferrer">here</a>.
  I made some customization of Romain script for my own need but philosophy is the same and I know with Romain we have the same issue with IPN (I'm in contact with him).</p>
  
  <p>The issue is : We can't validate the IPN Process. The HTTP response code is at status 405.</p>
  
  <p>What I have found is in the romain script we do step 3 before step 2. So I made a change and now the script return an empty answer :</p>
  
  <pre><code>return ContentService.createTextOutput('');
  </code></pre>
  
  <p>Before sending back the complete unaltered paypal message, I setup a trigger who send message to paypal after 30s :</p>
  
  <pre><code>var params = {
      method: "post"
    }
    var req = messge from paypal;
    var resp = UrlFetchApp.fetch("https://www.paypal.com/cgi-bin/webscr?"+req,params);
  </code></pre>
  
  <p>This code is not the same as Romain but I well received the "VERIFIED" answer from Paypal.</p>
  
  <p>So now I think issue is the HTTP 200 response send back to paypal, step 2.
  What I made is, check the data in content, header and response code by sending my own post request to the apps script. Here the result :</p>
  
  <blockquote>
    <p>[15-03-25 22:50:29:753 CET] code : 200</p>
    
    <p>[15-03-25 22:50:29:754 CET] content : </p>
    
    <p>[15-03-25 22:50:29:756 CET] hearder : ({'X-XSS-Protection':"1;
    mode=block", Expires:"Fri, 01 Jan 1990 00:00:00 GMT",
    'Alternate-Protocol':"443:quic,p=0.5",
    'Set-Cookie':"NID=67=hlLDTKuNN7fjl66UwT9e2_BV0xw_dd67lZ9R337Zm2K8RYNAMzF0FjnEt0uhE0cxCzymgsH-1ehuGOgZ7pHynjWRkM1Y6n0PxXp8RAdyPKgfr-Y4cUrBqoDZdUib9zWo;Domain=.googleusercontent.com;Path=/;Expires=Thu,
    24-Sep-2015 21:50:29 GMT;HttpOnly", Server:"GSE",
    'Cache-Control':"no-cache, no-store, max-age=0, must-revalidate",
    Pragma:"no-cache", 'X-Content-Type-Options':"nosniff",
    'X-Frame-Options':"SAMEORIGIN", 'Transfer-Encoding':"chunked",
    Date:"Wed, 25 Mar 2015 21:50:29 GMT",
    'Access-Control-Allow-Origin':"*", P3P:"CP=\"This is not a P3P policy!
    See
    <a href="http://www.google.com/support/accounts/bin/answer.py?hl=en&amp;answer=151657" rel="nofollow noreferrer">http://www.google.com/support/accounts/bin/answer.py?hl=en&amp;answer=151657</a>
    for more info.\"", 'Content-Type':"text/plain; charset=utf-8"})</p>
  </blockquote>
  
  <p>I have found this message on stackoverflow about http response status 405 and a test to do : (<a href="https://stackoverflow.com/questions/1162022/ipn-delivery-failed-http-error-code-405-method-not-allowed">IPN delivery failed. HTTP error code 405: Method Not Allowed</a>).</p>
  
  <p>The header send back with appscript after a dopost() request does not seems to be well formated. I'm not sure about that but now I don't have other idea. </p>
  
  <p>If someone have an idea ?
  I thought may be send a custom answer with specific header at the end of the <code>doPost()</code> with apps script but don't know how to do that ?</p>