diff --git a/bazaar/IPNServer/IPNServer.cpp b/bazaar/IPNServer/IPNServer.cpp new file mode 100644 index 000000000..fb09fd7cc --- /dev/null +++ b/bazaar/IPNServer/IPNServer.cpp @@ -0,0 +1,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(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 data; + for(int i = 0; i < post.GetCount(); i++) + data.Add(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 \ No newline at end of file diff --git a/bazaar/IPNServer/IPNServer.h b/bazaar/IPNServer/IPNServer.h new file mode 100644 index 000000000..4b196bc62 --- /dev/null +++ b/bazaar/IPNServer/IPNServer.h @@ -0,0 +1,45 @@ +#ifndef _IPNServer_IPNServer_h_ +#define _IPNServer_IPNServer_h_ + +#include + +NAMESPACE_UPP + +class IPNServer : public ScgiServer +{ + private: + + void OnAccepted(); + void OnRequest(); + void OnClosed(); + + String payServer; + int payPort; + + // 'VERIFIED' answer handler + Callback1 >onVerified; + + // 'INVALID' answer handler + Callback onInvalid; + +public: + + // constructor - defaults to port 8787 + IPNServer(int port = 8787); + + // setup server and port for back confirmation message + IPNServer &SetPayServer(String const &s) { payServer = s; return *this; } + IPNServer &SetPayPort(int p) { payPort = p; return *this; } + + // setting of handler + IPNServer &SetVerifiedHandler(Callback1 >handler) { onVerified = handler; return *this; } + IPNServer &SetInvalidHandler(Callback handler) { onInvalid = handler; return *this; } + + // runs the server + void Run(void); + +}; + +END_UPP_NAMESPACE + +#endif diff --git a/bazaar/IPNServer/IPNServer.upp b/bazaar/IPNServer/IPNServer.upp new file mode 100644 index 000000000..9a5ad679b --- /dev/null +++ b/bazaar/IPNServer/IPNServer.upp @@ -0,0 +1,10 @@ +description "Instant Payement Notification server for PayPal\377"; + +uses + Core, + Web/SSL; + +file + IPNServer.h, + IPNServer.cpp; + diff --git a/bazaar/IPNServer/init b/bazaar/IPNServer/init new file mode 100644 index 000000000..c89bbe622 --- /dev/null +++ b/bazaar/IPNServer/init @@ -0,0 +1,5 @@ +#ifndef _IPNServer_icpp_init_stub +#define _IPNServer_icpp_init_stub +#include "Core/init" +#include "Web/SSL/init" +#endif