|
@@ -37,26 +37,50 @@
|
|
|
(cl-cookie:make-cookie
|
|
(cl-cookie:make-cookie
|
|
|
:name "credentials"
|
|
:name "credentials"
|
|
|
:value (base64:string-to-base64-string
|
|
:value (base64:string-to-base64-string
|
|
|
- (format nil "~a:~a" (agets token "user" "id") (agets token "accessToken")))
|
|
|
|
|
|
|
+ (format nil "~a:~a" (agets token "user" "id")
|
|
|
|
|
+ (agets token "accessToken")))
|
|
|
|
|
+ :domain +api-domain+)
|
|
|
|
|
+ (cl-cookie:make-cookie
|
|
|
|
|
+ :name "refresh-token"
|
|
|
|
|
+ :value (base64:string-to-base64-string
|
|
|
|
|
+ (format nil "~a:~a" (agets token "user" "id")
|
|
|
|
|
+ (agets token "refreshCode")))
|
|
|
:domain +api-domain+)))))
|
|
:domain +api-domain+)))))
|
|
|
|
|
|
|
|
|
|
+(defun need-to-refresh-token (method)
|
|
|
|
|
+ (unless (or (string-equal method "signin")
|
|
|
|
|
+ (string-equal method "token"))
|
|
|
|
|
+ (when-let (expire (agets *poller-token* "tokenExpiryDate"))
|
|
|
|
|
+ (let* ((expire-ts (local-time:unix-to-timestamp (round expire 1000)))
|
|
|
|
|
+ (expire-5-min (local-time:timestamp- expire-ts 5 :minute))
|
|
|
|
|
+ (now (local-time:now)))
|
|
|
|
|
+ (when (local-time:timestamp< expire-5-min now expire-ts)
|
|
|
|
|
+ (log:info "Refreshing token" expire-ts)
|
|
|
|
|
+ (error 'dex:http-request-unauthorized
|
|
|
|
|
+ :method :post :uri (quri:uri "expire")
|
|
|
|
|
+ :headers nil :status 422 :body nil))))))
|
|
|
|
|
+
|
|
|
(defmethod poller-request ((module (eql :revolut)) method &rest params)
|
|
(defmethod poller-request ((module (eql :revolut)) method &rest params)
|
|
|
(handler-case
|
|
(handler-case
|
|
|
(let* ((uri (if (listp method) (car method) method))
|
|
(let* ((uri (if (listp method) (car method) method))
|
|
|
(rest-method (if (listp method) (cdr method) :get))
|
|
(rest-method (if (listp method) (cdr method) :get))
|
|
|
|
|
+ (refresh (need-to-refresh-token uri))
|
|
|
(is-content (is-content rest-method))
|
|
(is-content (is-content rest-method))
|
|
|
|
|
+ (cookie-jar (make-cookie-jar *poller-token*))
|
|
|
(res
|
|
(res
|
|
|
(json-request (concatenate 'string +api-uri+ uri)
|
|
(json-request (concatenate 'string +api-uri+ uri)
|
|
|
:headers `((:x-device-id . ,+device-id+)
|
|
:headers `((:x-device-id . ,+device-id+)
|
|
|
(:x-browser-application . "WEB_CLIENT"))
|
|
(:x-browser-application . "WEB_CLIENT"))
|
|
|
:user-agent +user-agent+
|
|
:user-agent +user-agent+
|
|
|
- :cookie-jar (make-cookie-jar *poller-token*)
|
|
|
|
|
|
|
+ :cookie-jar cookie-jar
|
|
|
:method rest-method
|
|
:method rest-method
|
|
|
:json-content is-content
|
|
:json-content is-content
|
|
|
(if is-content :content :parameters)
|
|
(if is-content :content :parameters)
|
|
|
(rest-parameters params t))))
|
|
(rest-parameters params t))))
|
|
|
- res)
|
|
|
|
|
- (dex:http-request-failed (e) e)))
|
|
|
|
|
|
|
+ (values res cookie-jar))
|
|
|
|
|
+ (dex:http-request-failed (e)
|
|
|
|
|
+ (let ((*print-escape*)) (log:warn "Revolut request failed" e))
|
|
|
|
|
+ e)))
|
|
|
|
|
|
|
|
(defmethod poller-validate ((module (eql :revolut)) response)
|
|
(defmethod poller-validate ((module (eql :revolut)) response)
|
|
|
(not (typep response 'dex:http-request-unauthorized)))
|
|
(not (typep response 'dex:http-request-unauthorized)))
|
|
@@ -75,25 +99,45 @@
|
|
|
when (listp res) do (return res)
|
|
when (listp res) do (return res)
|
|
|
unless (= (dex:response-status res) 422) do (return)
|
|
unless (= (dex:response-status res) 422) do (return)
|
|
|
when (> (- (get-universal-time) start) 30) do (return)
|
|
when (> (- (get-universal-time) start) 30) do (return)
|
|
|
- do (sleep 2)))))
|
|
|
|
|
-
|
|
|
|
|
-(defun refresh-token (user-id refresh-code)
|
|
|
|
|
- (let* ((res (poller-request :revolut '("token" . :put)
|
|
|
|
|
- :|userId| user-id
|
|
|
|
|
- :|refreshCode| refresh-code)))
|
|
|
|
|
- (when (listp res) res)))
|
|
|
|
|
|
|
+ do (sleep 2)))))
|
|
|
|
|
+
|
|
|
|
|
+(defun get-cookie-value (jar name)
|
|
|
|
|
+ (when jar
|
|
|
|
|
+ (let ((cookie (find name (cl-cookie:cookie-jar-cookies jar)
|
|
|
|
|
+ :from-end t
|
|
|
|
|
+ :key 'cl-cookie:cookie-name
|
|
|
|
|
+ :test 'equal)))
|
|
|
|
|
+ (when cookie (cl-cookie:cookie-value cookie)))))
|
|
|
|
|
+
|
|
|
|
|
+(defun decode-cookie-token (value)
|
|
|
|
|
+ (when value
|
|
|
|
|
+ (let ((decoded (base64:base64-string-to-string value)))
|
|
|
|
|
+ (when (> (length decoded) 37)
|
|
|
|
|
+ (subseq decoded 37)))))
|
|
|
|
|
+
|
|
|
|
|
+(defun refresh-token ()
|
|
|
|
|
+ (multiple-value-bind (res jar)
|
|
|
|
|
+ (poller-request :revolut '("token" . :put))
|
|
|
|
|
+ ;;(let ((*print-escape*)) (log:info "Token refresh" res jar))
|
|
|
|
|
+ (when (listp res)
|
|
|
|
|
+ `(("user" . (("id" . ,(agets res "userId"))))
|
|
|
|
|
+ ("tokenExpiryDate" . ,(agets res "expireAt"))
|
|
|
|
|
+ ("accessToken" . ,(decode-cookie-token (get-cookie-value jar "credentials")))
|
|
|
|
|
+ ("refreshCode" . ,(decode-cookie-token (get-cookie-value jar "refresh-token")))))))
|
|
|
|
|
|
|
|
(defmethod poller-get-token ((module (eql :revolut)) secret)
|
|
(defmethod poller-get-token ((module (eql :revolut)) secret)
|
|
|
(let ((user-id (agets *poller-token* "user" "id"))
|
|
(let ((user-id (agets *poller-token* "user" "id"))
|
|
|
(refresh-code (agets *poller-token* "refreshCode")))
|
|
(refresh-code (agets *poller-token* "refreshCode")))
|
|
|
;; Try to refresh old token
|
|
;; Try to refresh old token
|
|
|
(when (and user-id refresh-code)
|
|
(when (and user-id refresh-code)
|
|
|
- (when-let (token (refresh-token user-id refresh-code))
|
|
|
|
|
- (return-from poller-get-token
|
|
|
|
|
- (append token `(("user" . (("id" . ,user-id))))))))
|
|
|
|
|
|
|
+ (when-let (token (refresh-token))
|
|
|
|
|
+ (log:info "Refreshed" token)
|
|
|
|
|
+ (return-from poller-get-token token)))
|
|
|
;; Signin for a new token
|
|
;; Signin for a new token
|
|
|
(destructuring-bind (phone . passcode) secret
|
|
(destructuring-bind (phone . passcode) secret
|
|
|
- (signin phone passcode))))
|
|
|
|
|
|
|
+ (let ((token (signin phone passcode)))
|
|
|
|
|
+ (log:info "Signin" token)
|
|
|
|
|
+ token))))
|
|
|
|
|
|
|
|
(defun get-user ()
|
|
(defun get-user ()
|
|
|
(poller-call :revolut "user/current"))
|
|
(poller-call :revolut "user/current"))
|