如何使用Clojure和clj-oauth与正文签署POST请求?

时间:2016-08-10 20:14:07

标签: oauth clojure quickbooks-online

我正在尝试与使用OAuth 1的quickbooks在线REST API进行通信:

我可以像这样构造任意GET请求:

(require '[oauth.client :as oauth])
(require '[cheshire.core :refer :all])
(require '[clj-http.client :as client])

(def OAuth-Consumer-Key     "qyprdtoUhI8AjLxEQ9tucTJkSiklKn")
(def OAuth-Consumer-Secret  "*********************")

(def OAuth-Access-Token         "qyprdaXOWBph7MUnkqzRVruovEMlvgUH52Gup8kfinSgbnJL")
(def OAuth-Access-Token-Secret  "********************************" )


(def consumer (oauth/make-consumer OAuth-Consumer-Key
                                   OAuth-Consumer-Secret
                                   ""
                                   ""
                                   ""
                                   :hmac-sha1))


(def get-url "https://sandbox-quickbooks.api.intuit.com/v3/company/123145835981692/account/4")

(def get-user-params {})

(def get-credentials (oauth/credentials consumer
                                    OAuth-Access-Token
                                    OAuth-Access-Token-Secret
                                    :GET
                                    get-url
                                    get-user-params))

(client/get get-url {:query-params (merge get-credentials get-user-params) })

但是我无法构造POST请求。如果我将正文放在user-params中,那么认证似乎有效,但API拒绝接受请求,但如果我不这样做,它首先不会进行身份验证。

(def post-body "<Customer xmlns=\"http://schema.intuit.com/finance/v3\" domain=\"QBO\" sparse=\"false\">\n<CompanyName>Best Company</CompanyName>\n<DisplayName>Sir Jonhn Doe</DisplayName>\n<BillAddr>\n<Line1>123 Main Street</Line1>\n<City>Mountain View</City>\n<Country>USA</Country>\n<CountrySubDivisionCode>CA</CountrySubDivisionCode>\n<PostalCode>94042</PostalCode>\n</BillAddr>\n</Customer>")

(def post-user-params {:content-type "application/xml" :body post-body})

(def post-credentials (oauth/credentials consumer
                     OAuth-Access-Token
                     OAuth-Access-Token-Secret 
                     :POST
                     "https://sandbox-quickbooks.api.intuit.com/v3/company/123145835981692/customer"
                     post-user-params))


(client/post "https://sandbox-quickbooks.api.intuit.com/v3/company/123145835981692/customer"
             {:query-params (merge post-user-params post-credentials)
              :body post-body})

这个手工构造的版本工作正常。 (使用Chrome的Postman扩展程序完成)。

(client/post "https://sandbox-quickbooks.api.intuit.com/v3/company/123145835981692/customer"
                   {:headers {:authorization "OAuth oauth_consumer_key=\"qyprdtoUhI8AjLxEQ9tucTJkSiklKn\",oauth_token=\"qyprdaXOWBph7MUnkqzRVruovEMlvgUH52Gup8kfinSgbnJL\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1470828646\",oauth_nonce=\"WXZu67\",oauth_version=\"1.0\",oauth_signature=\"a66RFI8clxNIhv8M1YzzijDgE1A%3D\""
                              :content-type "application/xml",
                              :cache-control "no-cache",
                              :postman-token "0effd852-8271-7f66-f43d-6710443c5107"}
                    :body post-body})

任何人都可以看到我应该做些什么来正确签署请求吗?

1 个答案:

答案 0 :(得分:1)

最终我发现这个咒语有效。看来你实际上并不需要签署身体。而关键的变化是将内容类型移动到post请求中并从签名位移出。

我不知道这里发生了什么!

(def post-url "https://sandbox-quickbooks.api.intuit.com/v3/company/123145835981692/customer")

(def post-body (str "<Customer xmlns=\"http://schema.intuit.com/finance/v3\" domain=\"QBO\" sparse=\"false\">\n"
                    "<CompanyName>Company</CompanyName>\n"
                    "<DisplayName>Sir Jeaweaaan Doe</DisplayName>\n"
                    "<BillAddr>\n"
                    "<Line1>123 Main Street</Line1>\n"
                    "<City>Mountain View</City>\n"
                    "<Country>USA</Country>\n"
                    "<CountrySubDivisionCode>CA</CountrySubDivisionCode>\n"
                    "<PostalCode>94042</PostalCode>\n"
                    "</BillAddr>\n"
                    "</Customer>"))

(def post-user-params {
                       :cache-control "no-cache"
                       })

(def post-credentials (oauth/credentials consumer
                     OAuth-Access-Token
                     OAuth-Access-Token-Secret 
                     :POST
                     post-url
                     post-user-params))


(que? (client/post post-url
                   {:query-params (merge post-user-params post-credentials)
                    :content-type "application/xml"
                    :body post-body
              }))