首页 > 解决方案 > 使用 haskell 服务客户端:如何将记录类型编码为 FormUrlEncoded 的正文

问题描述

我正在尝试将 Lucsanszky 的 Haskell Binance API 包装器更新为最新的仆人,并且似乎发生了一些变化。它位于https://github.com/adrianmay/haskell-binance

代码想将一些参数作为查询字符串放入请求正文中,但是当它失败时,我看到正文为空:

FailureResponse (Request {
  requestPath = (BaseUrl {
    baseUrlScheme = Https, baseUrlHost = "api.binance.com", 
    baseUrlPort = 443, 
    baseUrlPath = ""}
    , "/api/v3/order/test"), 
  requestQueryString = fromList [("signature",Just "7ffc3cc465737fb4349f06907fc200ffc5e4cc877c69188ef0827a23d5dd9077")], 
  requestBody = Just ((),application/x-www-form-urlencoded), 
  requestAccept = fromList [application/json;charset=utf-8,application/json], 
  requestHeaders = fromList [("X-MBX-APIKEY","...")]), 
  requestHttpVersion = HTTP/1.1, 
  requestMethod = "POST"} 
(Response {
  responseStatusCode = Status {statusCode = 400, statusMessage = "Bad Request"}, 
  responseHeaders = fromList [("Content-Typ...

但我知道我试图编码的类型可以将自己变成一个查询字符串:

data TradeParams = TradeParams                            
    { _symbol           :: !Text                          
    , _side             :: !Side                          
    , _type             :: !OrderType                     
    , _timeInForce      :: Maybe Text                     
    , _quantity         :: Maybe Double                   
    , _quoteOrderQty    :: Maybe Double                   
    , _price            :: Maybe Double                   
    , _newClientOrderId :: Maybe Text                     
    , _stopPrice        :: Maybe Double                   
    , _icebergQty       :: Maybe Double                   
    , _newOrderRespType :: Maybe Response                 
    , _recvWindow       :: Maybe Integer                  
    , _timestamp        :: !Integer                       
    } deriving (Eq, Show, Generic)                        
                                                          
instance ToForm TradeParams where                         
    toForm = genericToForm opts                           
      where                                               
        opts = FormOptions {fieldLabelModifier = drop 1}  

instance FromForm TradeParams                             
aTradeParams :: Integer -> H.TradeParams                    
aTradeParams t = H.TradeParams                              
                { H._symbol = "ADAGBP"                      
                , H._side = H.BUY                           
                , H._type = H.MARKET                        
                , H._quantity = Nothing                     
                , H._quoteOrderQty = Just 1                 
                , H._timestamp = t                          
                , H._timeInForce = Nothing                  
                , H._price = Nothing
                , H._newClientOrderId = Nothing             
                , H._stopPrice = Nothing                    
                , H._icebergQty = Nothing                   
                , H._newOrderRespType = Nothing             
                , H._recvWindow = Nothing                   
                }                                           
                                                            
                                                    
hspec $ do                                                                                                                
  describe "All tests" $ do                                                                                               
    it "To and from form" $                                                                                               
       P.urlEncodeAsForm (aTradeParams 1) `shouldBe` "symbol=ADAGBP&quoteOrderQty=1.0&type=MARKET&side=BUY&timestamp=1"   

我认为这些是相关的代码位:

type BinanceAccountApi                   
     = "api" :> "v3" :>                  
        (    BinanceAccountApiTime       
        :<|> BinanceAccountApiAllOrders  
        :<|> BinanceAccountApiTestOrder
        )                                

type BinanceAccountApiTestOrder =              
  Header "X-MBX-APIKEY" Text :>                
  "order" :>                                   
  "test" :>                                    
  ReqBody '[FormUrlEncoded] TradeParams :>     
  QueryParam "signature" Text :>               
  Post '[ JSON] Object                         

testOrder' ::                                                        
       Maybe Text                                                    
    -> TradeParams                                                   
    -> Maybe Text                                                    
    -> ClientM Object                                                
getServerTime' :<|> allOrders' :<|> testOrder' = client binanceProxy 

testOrder ::                                                    
       TradeParams                                              
    -> BinanceUserApi (Either ClientError Object)               
testOrder params = do                                           
    url <- asks url                                             
    man <- asks managr                                          
    pub <- asks publicKey                                       
    let msg = urlEncodeAsForm params                            
    sig <- sign $ toStrict msg                                  
    liftIO $                                                    
        runClientM                                              
            (testOrder'                                         
                 (Just pub)                                     
                 params -- I proved this was populated with a trace                    
                 (Just ((pack . show) sig))) $                  
        ClientEnv man url Nothing defaultMakeClientRequest      

标签: haskellbinanceservant

解决方案


推荐阅读