My favorites | Sign in
Project Home Downloads Source
Checkout   Browse   Changes    
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "IPNServer.h"

NAMESPACE_UPP

// constructor - defaults to port 8787 and connection timeout of 5 minutes (300 sec.)
IPNServer::IPNServer(int port) : ScgiServer(port)
{
}

void IPNServer::OnAccepted()
{
Cout() << "Accepted connection from client " << FormatIP(clientIP) << "\n";
}

void IPNServer::OnRequest()
{
// we handle just POST requests, GET not allowed
if(HasPostData())
{
// create context for ssl connection
SSLContext context;
if(!context.Create(const_cast<SSL_METHOD *>(SSLv3_client_method())))
{
Cerr() << "Error creating SSL context.";
return;
}

// re-send back data to paypal site, in order to check
// if data was from them
Socket answerSocket;
if(!SSLClientSocket(answerSocket, context, payServer, payPort))
{
Cout() << "Error creating connection to PayPal\n";
return;
}
String req = "cmd=_notify-validate";
for(int i = 0; i < post.GetCount(); i++)
req << "&" << ToLower(post.GetKey(i)) << "=" << UrlEncode(post[i]);

String header;
header <<
"POST /cgi-bin/webscr HTTP/1.0\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: " << req.GetCount() << "\r\n\r\n"
;
answerSocket.Write(header + req);

// wait for PayPal server answer
req = "";
while(answerSocket.IsOpen() && !answerSocket.IsEof() && !answerSocket.IsError())
req << answerSocket.Read();
answerSocket.Close();

// 'VERIFIED' or 'INVALID' answer are on last line of received HTTP packet;
// the rest is just HTTP headers and can be discarded
// in detail, the LAST part of req string must be "VERIFIED"
if(req.Right(8) == "VERIFIED")
{
VectorMap<String, String> data;
for(int i = 0; i < post.GetCount(); i++)
data.Add(ToUpper(post.GetKey(i)), post[i]);
onVerified(data);
}
else
onInvalid();
}
else
Cout() << "No POST data on PayPal request\n";

// this one avoids "500 server error".... don't know why
// but paypal do check the http response along with reply packet
// on direct http access it'll show just a blank page
clientSock.Write("Content-Type: text/plain\r\n\r\n");
}

void IPNServer::OnClosed()
{
Cout() << "Connection with " << FormatIP(clientIP) << " closed\n";
}

// runs the server
void IPNServer::Run(void)
{
// runs the SCGI server
ScgiServer::Run();
}

END_UPP_NAMESPACE

Change log

r4597 by micio on Feb 14, 2012   Diff
Bazaar/IPNServer : capitalize keys before
calling VERIFIED handler
Go to: 
Project members, sign in to write a code review

Older revisions

r4584 by micio on Feb 13, 2012   Diff
Bazaar/IPNServer : an SCGI-based
server for PayPal Instant Payement
Notification
All revisions of this file

File info

Size: 2316 bytes, 88 lines
Powered by Google Project Hosting