PLEASE NOTE: With the code/info below, this problem can be reproduced in 2-3 minutes.
BACKGROUND: Firstly I haven't found a plugin to help with the Paypal Advanced Interface (their mid-level solution between "Standard" and "Pro"), but if if I don't need to roll my own HTTPBuilder and other interface code I'm definitely for that.
Now, I'm able to narrow down the HTTPBuilder problem to making the curl command work from the DOS prompt using the correct URL; I just can't get it to work with groovy's HTTPBuilder.
So, what works that one can easily try is:
c:\groovy\ex>curl https://pilot-payflowpro.paypal.com
curl: (52) Empty reply from server
But still a reply. Or the real URL to get a SECURETOKEN back from Paypal is more like:
c:\groovy\ex>curl https://pilot-payflowpro.paypal.com -kd "PARTNER=PayPal&VENDOR=ROAdvanced&USER=ROAdvanced&PWD=joespizza1&TRXTYPE=S&MODE=TEST&AMT=40&CREATESECURETOKEN=Y&SECURETOKENID=12528208de1413abc3d60c86233"
RESULT=0&SECURETOKEN=15XTWEZtFlkeNqtWCBZHSTgcs&SECURETOKENID=12528208de1413abc3d60c86233&RESPMSG=Approved
OR you'll get a result like the following, but either result is good, since Paypal is sending a response in both cases!
RESULT=7&SECURETOKENID=12528208de1413abc3d60c86233&RESPMSG=Field format error: Secure Token Id already been used
Ok, my code is as follows. Please note my code errors out with an immediate failure even though (I think) I'm using a delay:
Class: org.apache.http.NoHttpResponseException
Message: The target server failed to respond
This happens around the
http.request(GET, ContentType.ANY) {
Please note even with setting the delays on HTTPBuilder, this failure happens IMMEDIATELY. I'll put the whole code/stack trace in at the end. Also note if one takes out adding the SSL security as described in this post, the result is the same error, i.e. the server failed to respond.
So the code is:
package apps
import grails.converters.*
import org.codehaus.groovy.grails.web.json.*; // package containing JSONObject, JSONArray,...
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
import javax.net.ssl.X509TrustManager
import javax.net.ssl.SSLContext
import java.security.cert.X509Certificate
import javax.net.ssl.TrustManager
import java.security.SecureRandom
import org.apache.http.conn.ssl.SSLSocketFactory
import org.apache.http.conn.scheme.Scheme
import org.apache.http.conn.scheme.SchemeRegistry
import org.apache.http.conn.ssl.X509HostnameVerifier
class PaypalController {
def index() {
def paypalUrl = "https://pilot-payflowpro.paypal.com?PARTNER=PayPal&VENDOR=ROAdvanced&USER=ROAdvanced&PWD=joespizza1&TRXTYPE=S&MODE=TEST&AMT=40&CREATESECURETOKEN=Y&SECURETOKENID=12528208de1413abc3d60c86cdr87"
//def paypalUrl = "https://pilot-payflowpro.paypal.com"
println "Making new http Builder with paypalURL ..."
def http = new HTTPBuilder(paypalUrl)
println "Now setting timeouts ..."
http.getClient().getParams().setParameter("http.connection.timeout", new Integer(12000))
http.getClient().getParams().setParameter("http.socket.timeout", new Integer(30000))
//=== SSL UNSECURE CERTIFICATE ===
println "Don't know if needed, but since timeouts don't work to get a response, setting up SSL bypass"
def sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, [new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {null }
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
public void checkServerTrusted(X509Certificate[] certs, String authType) { }
}] as TrustManager[], new SecureRandom())
//SSLSocketFactory sf = new org.apache.http.conn.ssl.SSLSocketFactory(sslContext, org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
SSLSocketFactory sf = new org.apache.http.conn.ssl.SSLSocketFactory(sslContext)
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
def httpsScheme = new Scheme("https", sf, 443)
http.client.connectionManager.schemeRegistry.register(httpsScheme)
println "Now doing the get"
// perform a GET request, expecting JSON response data
try {
http.request(GET, ContentType.ANY) {
println "Issued the get waiting for the response"
// Sleeping doesn't help
//Thread.sleep(2000)
// println "Done sleeping, looking to process success"
response.success = { resp, any ->
println "in success code"
println "My response handler got response: ${resp.statusLine}"
println "Response length: ${resp.headers.'Content-Length'}"
assert resp.status == 200
def result = any.results;
render(view: "index", model: [message: "Request sent", result: result]);
}
println "past the success code"
}//end of request
} catch (groovyx.net.http.HttpResponseException ex) {
println "Had response exception ...."
ex.printStackTrace()
return null
} catch (java.net.ConnectException ex) {
println "Had connection exception ...."
ex.printStackTrace()
return null
}
finally {
http.shutdown()
}
}//end of method
def fail() {}
def success() {}
}
------------------- Running this code I get (with no delays anywhere) -------------------------
Making new http Builder with paypalURL ...
Now setting timeouts ...
Don't know if needed, but since timeouts don't work to get a response, setting up SSL bypass
Now doing the get
Issued the get waiting for the response
past the success code
| Error 2013-07-19 13:27:32,301 [http-bio-8080-exec-10] ERROR errors.GrailsExceptionResolver - NoHttpResponseException occurred when processing request: [GET] /apps/paypal/index
The target server failed to respond. Stacktrace follows:
Message: The target server failed to respond
Line | Method
->> 101 | parseHead in org.apache.http.impl.conn.DefaultResponseParser
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 210 | parse in org.apache.http.impl.io.AbstractMessageParser
| 271 | receiveResponseHeader in org.apache.http.impl.AbstractHttpClientConnection
| 233 | receiveResponseHeader in org.apache.http.impl.conn.DefaultClientConnection
| 209 | receiveResponseHeader in org.apache.http.impl.conn.AbstractClientConnAdapter
| 292 | doReceiveResponse in org.apache.http.protocol.HttpRequestExecutor
| 126 | execute . . . . . . . in ''
| 483 | execute in org.apache.http.impl.client.DefaultRequestDirector
| 641 | execute . . . . . . . in org.apache.http.impl.client.AbstractHttpClient
| 576 | execute in ''
| 477 | doRequest . . . . . . in groovyx.net.http.HTTPBuilder
| 441 | doRequest in ''
| 390 | request . . . . . . . in ''
| 56 | index in apps.PaypalController$$EOC4TiIi
| 195 | doFilter . . . . . . in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 886 | runTask . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker
| 908 | run in ''
^ 619 | run . . . . . . . . . in java.lang.Thread
----------------- I had to add the following to BuildConfig.groovy to get this to this work ----
...
dependencies {
// specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes e.g.
compile('org.codehaus.groovy.modules.http-builder:http-builder:0.5.2') {
excludes "commons-logging", "xml-apis", "groovy"
}
Code hopefully matching Groovy HTTPBuilder documentation:
NOTE THIS PRODUCES THE SAME ERROR AT THE SAME LINE, I.E.:
org.apache.http.NoHttpResponseException, Message: The target server failed to respond
at the line: http.request(POST) {
class PaypalController {
def index() {
def paypalUrl = "https://pilot-payflowpro.paypal.com?PARTNER=PayPal&VENDOR=ROAdvanced&USER=ROAdvanced&PWD=joespizza1&TRXTYPE=S&MODE=TEST&AMT=40&CREATESECURETOKEN=Y&SECURETOKENID=12528208de1413abc3d60c86cdr87"
println "Making new http Builder with paypalURL ..."
def http = new HTTPBuilder(paypalUrl)
println "Now doing the post as a request per example"
// perform a GET request, expecting JSON response data
try {
http.request(POST) {
body = [ status : 'update!' , source : 'httpbuilder' ]
requestContentType = ContentType.URLENC
println "Issued the post waiting for the response"
response.success = { resp ->
println "in success code"
println "My response handler got response: ${resp.statusLine}"
println "Response length: ${resp.headers.'Content-Length'}"
assert resp.status == 200
//def result = any.results;
render(view: "index", model: [message: "Request sent", result: result]);
}
println "past the success code"
}//end of request
} catch (groovyx.net.http.HttpResponseException ex) {
println "Had response exception ...."
ex.printStackTrace()
return null
} catch (java.net.ConnectException ex) {
println "Had connection exception ...."
ex.printStackTrace()
return null
}
finally {
http.shutdown()
}
}//end of method
def fail() {}
def success() {}
}
found your problem: curl -d
is not a GET but a POST request. If you leave out the -d in your curl request, you'll run in to the same problem as with your groovy...
Try this groovy code:
def url = new URL("https://pilot-payflowpro.paypal.com")
def body= "PARTNER=PayPal&VENDOR=ROAdvanced&USER=ROAdvanced&PWD=..."
def connection = url.openConnection()
connection.setRequestMethod("POST")
connection.doOutput = true
def writer = new OutputStreamWriter(connection.outputStream)
writer.write(body)
writer.flush()
writer.close()
connection.connect()
def response = connection.content.text