开发者

CURLE_RECV_ERROR with PayPal API

I've developed an application that connects to the PayPal API with libcurl, which I use through the OCurl bindings for OCaml from a process running on a Debian server. The code always works when inside the Paypal sandbox (endpoint https://api-3t.sandbox.paypal.开发者_StackOverflowcom/nvp) but never works when connecting to the actual Paypal servers (endpoint https://api-3t.paypal.com/nvp).

Libcurl always returns CURLE_RECV_ERROR. The general consensus is that this error happens when there is a network problem, so I have investigated that.

I ran the exact same request with the command-line curl tool from the exact same server, using the exact same process uid/gid, and it consistently works. Tracking the transfers with tcpdump does not reveal any significant difference in the structure of transactions made by the working command-line curl and the non-working application, so it all appears as if the HTTP request is successfully performed in both cases. Then again, it's HTTPS, so I cannot be certain.

Here is the OCaml code that performs the request:

let c = new Curl.handle in
let buffer = Buffer.create 1763 in

c # set_url "https://api-3t.paypal.com/nvp" ;
c # set_post true ;
c # set_postfields "SOMEDATA" ;
c # set_postfieldsize (String.length "SOMEDATA") ;
c # set_writefunction (fun x -> Buffer.add_string buffer x ; String.length x) ;
c # perform ;
c # cleanup ;

Buffer.contents buffer

Here is the equivalent curl command line:

curl -X POST https://api-3t.paypal.com/nvp -d SOMEDATA

EDIT: By increasing the libcurl verbosity, I determined that the underlying error is this:

GnuTLS recv error (-9): A TLS packet with unexpected length was received.

What could be the cause of this error? How can I investigate to find out?

EDIT 2: It appears that the difference between command-line and library use is that the command-line version is linked to OpenSSL and the library is linked to GnuTLS.

How do I link both to OpenSSL?


First, the key to further debugging those issues is to use curl's debugging facilities, namely the VERBOSE setting (and also, possibly, the DEBUGFUNCTION setting for printing the data your way).

c # set_verbose true ;

This identified the error as being a problem with GnuTLS that is also discussed here, and which is solved by setting SSLVERSION to 3 to force the use of SSLv3.

c # set_sslversion 3 ;


I always call curl#set_postfieldsize to the length of the data passed to curl#set_postfields. My code would be, then:

let make_get url =
  let curl = new Curl.handle in
  curl#set_writefunction String.length; (* ignore result *)
  curl#set_tcpnodelay true;
  curl#set_verbose false;
  curl#set_post false;
  curl#set_url url;
  curl

let make_post url =
  let curl = make_get url in
  curl#set_post true;
  curl#set_httpheader [
  "Content-Type: text/xml; charset=\"UTF-8\"";
  "SOAPAction: \"\"";
  ];
  curl#set_postfields xml;
  curl#set_postfieldsize (String.length xml);
  curl

I hope this helps.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜