[bknr-cvs] hans changed trunk/projects/quickhoney/src/

BKNR Commits bknr at bknr.net
Sat Jul 26 22:06:02 UTC 2008


Revision: 3648
Author: hans
URL: http://bknr.net/trac/changeset/3648

Add beginnings of a Paypal payment module

U   trunk/projects/quickhoney/src/packages.lisp
A   trunk/projects/quickhoney/src/paypal.lisp
U   trunk/projects/quickhoney/src/quickhoney.asd

Modified: trunk/projects/quickhoney/src/packages.lisp
===================================================================
--- trunk/projects/quickhoney/src/packages.lisp	2008-07-26 12:19:43 UTC (rev 3647)
+++ trunk/projects/quickhoney/src/packages.lisp	2008-07-26 22:06:02 UTC (rev 3648)
@@ -52,3 +52,6 @@
 	:quickhoney.config)
   (:shadowing-import-from :cl-interpol #:quote-meta-chars)
   (:export #:client-selectbox))
+
+(defpackage :paypal
+  (:use :cl))
\ No newline at end of file

Added: trunk/projects/quickhoney/src/paypal.lisp
===================================================================
--- trunk/projects/quickhoney/src/paypal.lisp	                        (rev 0)
+++ trunk/projects/quickhoney/src/paypal.lisp	2008-07-26 22:06:02 UTC (rev 3648)
@@ -0,0 +1,77 @@
+(in-package :paypal)
+
+(defparameter *paypal-url* "https://api-3t.sandbox.paypal.com/nvp"
+  "NVP URL of the Paypal server")
+(defparameter *paypal-user* "sdk-three_api1.sdk.com"
+  "Username to use to authenticate at the Paypal server")
+(defparameter *paypal-password* "QFZCWN5HZM8VBG7Q"
+  "Password to use to authenticate at the Paypal server")
+(defparameter *paypal-signature* "A-IzJhZZjhg29XQ2qnhapuwxIDzyAZQ92FRP5dqBzVesOkzbdUONzmOU"
+  "Signature to use to authenticate at the Paypal server")
+
+(define-condition request-error (error)
+  ((response :initarg :response)))
+
+(define-condition http-request-error (error)
+  ((http-status :initarg :http-status)
+   (response-string :initarg :response-string)))
+
+(defun decode-response (response)
+  "Decode a paypal response string, which is URL encoded and follow
+  list encoding rules.  Returns the parameters as a plist."
+  (let ((hash (make-hash-table)))
+    (dolist (entry (cl-ppcre:split "&" response))
+      (destructuring-bind (parameter-string value) (cl-ppcre:split "=" entry :limit 2)
+        (multiple-value-bind (match registers) (cl-ppcre:scan-to-strings "^L_(.*?)([0-9]+)$" parameter-string)
+          (if match
+              (let* ((parameter (intern (aref registers 0) :keyword))
+                     (index (parse-integer (aref registers 1)))
+                     (previous-value (gethash parameter hash)))
+                (unless (= (length previous-value) index)
+                  (error "unexpected list value ~A in Paypal response ~S" parameter-string response))
+                (setf (gethash parameter hash) (append previous-value (list (hunchentoot:url-decode value)))))
+              (setf (gethash (intern parameter-string :keyword) hash) (hunchentoot:url-decode value))))))
+    (loop for key being the hash-keys of hash
+         collect key
+         collect (gethash key hash))))
+
+(defun request (method &rest args &key &allow-other-keys)
+  "Perform a request to the Paypal NVP API.  METHOD is the method to
+  use, additional keyword arguments are passed as parameters to the
+  API.  Returns "
+  (multiple-value-bind (response-string http-status)
+      (drakma:http-request *paypal-url*
+                           :method :post
+                           :parameters (append (list (cons "METHOD" method)
+                                                     (cons "VERSION" "52.0")
+                                                     (cons "USER" *paypal-user*)
+                                                     (cons "PWD" *paypal-password*)
+                                                     (cons "SIGNATURE" *paypal-signature*))
+                                               (loop for (param value) on args by #'cddr
+                                                  collect (cons (symbol-name param)
+                                                                (if (stringp value) value (princ-to-string value))))))
+    (unless (= 200 http-status)
+      (error 'http-request-error :http-status http-status :response-string response-string))
+    (let ((response (decode-response response-string)))
+      (unless (string-equal "Success" (getf response :ack))
+        (error 'request-error :response response))
+      response)))
+
+(defun test-express-checkout ()
+  (let* ((amt "50.00")
+         (currencycode "EUR")
+         (returnurl "http://test.createrainforest.org/return-paypal")
+         (cancelurl "http://test.createrainforest.org/cancel-paypal")
+         (token (getf (request "SetExpressCheckout"
+                              :amt amt
+                              :currencycode currencycode
+                              :returnurl returnurl
+                              :cancelurl cancelurl
+                              :paymentaction "Sale")
+                     :token)))
+    (format *trace-output* "url: https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=~A~
+                                 &AMT=~A&CURRENCYCODE=~A&RETURNURL=~A&CANCELURL=~A"
+            (hunchentoot:url-encode token)
+            amt currencycode
+            (hunchentoot:url-encode returnurl)
+            (hunchentoot:url-encode cancelurl))))
\ No newline at end of file

Modified: trunk/projects/quickhoney/src/quickhoney.asd
===================================================================
--- trunk/projects/quickhoney/src/quickhoney.asd	2008-07-26 12:19:43 UTC (rev 3647)
+++ trunk/projects/quickhoney/src/quickhoney.asd	2008-07-26 22:06:02 UTC (rev 3648)
@@ -20,6 +20,7 @@
 	       :cl-ppcre
 	       :cxml
 	       :cl-mime
+               :drakma
 	       :bknr.web
 	       :bknr.datastore
 	       :bknr.modules




More information about the Bknr-cvs mailing list