I am using SWIFT to build API communication without using libraries such as Alamofire.
Introduction to virtual currency system trading starting with Swift
With this site as a reference, the entire API structure was advanced to the point where no build errors occurred.
There are the following errors and I can't find a solution.
Error detailsBuild Succeeded->Run launches the simulator and triggers sending requests
When the button is clicked, the following is output to the debug console.
The response from the communication destination is displayed as a string.
Optional ("{\" error \ ": {\" message \ ": \" Authorization Required \ ", \" name \ ": \" HTTPError \ "}}")
Recognizing that it is an error that requires authentication, creating breakpoints in the debug console
Looking at the contents of the request, the flow to create authentication in the program is working firmly, the request URL is
Looks like it ’s done.
The following is the value of urlRequest created at the break console and confirmed by the debug console.
Access: https://testnet.bitmex.com/api/
Printing description of urlRequest:
▿ https:/(access destination) .com/api/v1/order? OrderType = Limit&symbol = XBTUSD&orderQty = 1&price = 590
▿ url: Optional<URL>
▿ some: https:/(access destination) .com/api/v1/order? OrderType = Limit&symbol = XBTUSD&orderQty = 1&price = 590
-_url: https:/(access destination) .com/api/v1/order? orderType = Limit&symbol = XBTUSD&orderQty = 1&price = 590
-cachePolicy: 0
-timeoutInterval: 60.0
-mainDocumentURL: nil
-networkServiceType: __C.NSURLRequestNetworkServiceType
-allowsCellularAccess: true
Method httpMethod: Optional<String>
-some: "POST"
HTTP allHTTPHeaderFields: Optional<Dictionary<String, String >>
▿ some: 4 elements
▿ 0: 2 elements
-key: "Content-Type"
-value: "application/json"
▿ 1: 2 elements
-key: "ACCESS-SIGN"
-value: "b2dce06bcb67b6db3418b5018b45cf9f4442986ed05b76fc91bfb4303788332f"
▿ 2: 2 elements
-key: "ACCESS-TIMESTAMP"
-value: "1575546"
▿ 3: 2 elements
-key: "ACCESS-KEY"
-value: "Access key is output"
-httpBody: nil
-httpBodyStream: nil
-httpShouldHandleCookies: true
-httpShouldUsePipelining: false
Authentication code
Program execution flow
- User action (button press)
- Session class call
- Execute buildURLRequest method (extension Requestable in RequestAPI)
- Start creation of authentication header if isAuthorizedRequest is true in buildURLRequest (confirmed to be true in console)
- Create HMAC SHA256 authentication hash with makeAccessSignWith
- Return to buildURLRequest, pack everything and complete as urlRequest
- Return to Session class and execute with task.resume () using URLSession
enum Result<T, E: Error>{
case success (T)
case failure (E)
}
enum ResponseError: Error {
case unexpectedResponse
}
// Protocol definition
protocol Requestable {
(Omitted)
}
extension Requestable {
func buildURLRequest ()->URLRequest {
let url = Self.baseURL.appendingPathComponent (Self.path)
var urlRequest = URLRequest (url: url)
var header: [String: String] = Self.headerField
urlRequest.httpMethod = Self.httpMethod
if Self.isAuthorizedRequest {
header ["ACCESS-KEY"] = "You have entered an access key"
let now = (Date (). timeIntervalSince1970/1000) + 60
let timeStamp = String (Int (now.rounded ())
header ["ACCESS-TIMESTAMP"] = timeStamp
header ["ACCESS-SIGN"] = makeAccessSignWith (accessKey: "You have entered your access key",
timeStamp: timeStamp,
method: Self.httpMethod,
path: Self.path,
queryParams: Self.queryParameters,
body: Self.httpBody)
header ["Content-Type"] = "application/json"
}
header.forEach {key, value in
urlRequest.addValue (value, forHTTPHeaderField: key)
}
if let body = Self.httpBody {
urlRequest.httpBody = body
}
guard var urlComponents = URLComponents (url: url, resolvingAgainstBaseURL: true) else {
return urlRequest
}
urlComponents.query = Self.queryParameters
.map {"\ ($0.key) = \ ($0.value)"}
.joined (separator: "&")
urlRequest.url = urlComponents.url
return urlRequest
}
}
final class Session {
static let shared = Session ()
private init () {}
func send<T: Requestable>(_ request: T, closure: @escaping (Result<T.Response, ResponseError>)->Void) {
let urlRequest = request.buildURLRequest ()
let task = URLSession.shared.dataTask (with: urlRequest) {(data, rawResponse, error) in
// If an error is occurred.if error! = nil {
closure (.failure (.unexpectedResponse))
return
}
// If the data is empty.
guard let data = data else {
closure (.failure (.unexpectedResponse))
return
}
// Decode the value.
do {
let decoder = JSONDecoder ()
let result = try decoder.decode (T.Response.self, from: data)
closure (.success (result))
} catch {
let errorResult = String (data: data, encoding: .utf8) // Convert to String for debugging
print (errorResult as Any)
}
}
task.resume ()
}
}
private func makeAccessSignWith (accessKey: String, timeStamp: String, method: String, path: String, queryParams: [String: Any],
body: Data?)->String? {
let key = "Entering secret key"
var bytes: [UInt8] = []
bytes + = timeStamp.bytes
bytes + = method.bytes
bytes + = path.bytes
func makeSign (queryParams: [String: Any])->String {
let requestBody = "?" + queryParams
.map {"\ ($0.key) = \ ($0.value)"}
.joined (separator: "&")
return requestBody
}
if! queryParams.isEmpty {
let str = makeSign (queryParams: ViewController.PostNewOrderRequest.queryParameters)
let data: Data? = str.data (using: .utf8)
let hexStr: String = data! .map {String (format: "% .2hhx", $0)}. joined ()
var bytes = [UInt8] ()
for char in hexStr.utf8 {
bytes + = [char]
}
}
if body? .isEmpty == false {
if let bodyParameter = body,
let bodyString = String (data: bodyParameter, encoding: .utf8) {
bytes + = bodyString.utf8
}
}
let signedString = try! HMAC (key: key, variant: .sha256) .authenticate (bytes)
return signedString.toHexString ()
}
-
Answer # 1
Related articles
- google api - i want to resolve google authentication error 403: access_denied
- ios - what is the difference between guest authentication and anonymous authentication?
- ios - rejected with sign in with apple error
- typescript - i want to run the sample code of denoland/x/abc without error
- ios - swift import gpuimage error
- ios - error occurs when only value in dictionary is stored in array
- an error occurs in javascript authentication after authentication by python + selenium submit
- ios - how to implement sms authentication
- ruby - i'm getting an error with the google authentication implementation of characters
- ios - xcode error "uilocalnotification" is abolished
- ios - use of unresolved identifier'firebaseapp' error persists
- ios - outlet cooperation error [swift]
- python 3x - python3 proxy authentication error
- ios - weakpassword of the error handle does not work
- how can i add a page that can be accessed without authentication with laravel?
- ios - i identified the error with exception breakpoint, but i don't know the inappropriate part [exc_bad_access]
- ios - [unity] i want to resolve the build error of unity cloud build
- ios - self error in do-catch [i want to call urlsession from another class ]
- ios - unexpectedly found nil error when selecteduser is nil
- mysql - error! the server quit without updating i want to resolve the pid file
- ios - when the button is pressed, the api data is not switched and displayed [swift]
- ios : swift metal HDR video color rendering
- ios - unexpectedly found nil error when selecteduser is nil
- ios - i want to make uiimageview rounded
- ios - after pushing, the file disappeared [github]
- ios - i want to set the title on the screen with tabbar under navigationcontroller in swift5
- ios - the size of the placeholder image does not fit the imageview
- ios - i want to use http communication with alamofire [get image]
- ios - how to convert an image to data in userdefaults or document and save/load it
- ios - where is the file to write gitignore?
Thank you very much.
From this document, it seems that [permanent API key] is required: Bitmex REST API
And according to Authenticating with an API Key, you need to send the following header:
The sample code provided by masayoshi555 seems to have a slightly different header.
Please confirm.