Установите сертификаты TLS на приложение iOS веб-сервера - PullRequest
0 голосов
/ 21 декабря 2018

Я пытаюсь интегрировать платеж Swish в одно из разрабатываемых мной приложений.Чтобы иметь возможность подключиться к swish api, мне нужно «настроить сертификаты TLS из Swish Certificate Management и установить его на« моем »веб-сервере» в соответствии с документацией. Вот полная техническая документация https://developer.getswish.se/merchants-api-manual/4-merchant-setup-process/.

Проблема, которую я не понимаю, заключается в том, что я не использую веб-сервер и не могу установить эти сертификаты там.

Мое приложение просто предлагает некоторые услуги для клиента и после нажатия кнопки оплаты.Кнопка должна открыть приложение Swish, чтобы вкратце завершить транзакцию.

Я попытался сделать пост-запрос, чтобы получить маркер запроса, с помощью которого я могу открыть приложение Swish, загруженное с данными платежа.Я уверен, что проблемы заключаются в сертификатах, но не удалось найти хороший источник, объясняющий, как их импортировать (интегрировать).

let strURL = "https://mss.cpc.getswish.net/swish-cpcapi/api/v1/paymentrequests/"

guard let postURL = URL(строка: strURL) else {print ("Can't create url") return}

    var request = URLRequest(url: postURL)

    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue("application/json", forHTTPHeaderField: "Accept")

    let data: [String: Any] = [
        "callbackUrl": "https://example.com/api/swishcb/paymentrequests",
        "payeeAlias": "123xxxxxxx", // The Swish number of the payee. It needs to match with Merchant Swish number.
        "amount": "100",
        "currency": "SEK",
        "message": "Test request to get the token"
    ]

    do {
        let jsonParams = try JSONSerialization.data(withJSONObject: data, options: [])
        request.httpBody = jsonParams
    } catch {
        print("Error serializing the parameters of the post request")
        return
    }

    // response will contain a Token, unique for each payment request

    let config = URLSessionConfiguration.default
    config.timeoutIntervalForResource = 120
    config.timeoutIntervalForRequest = 120
    let session = URLSession(configuration: config) 

    session.dataTask(with: request) { (data, response, error) in
        print("Data \(data)")
        print("Response \(response)")
        if error != nil {
            print("Error post request \(error?.localizedDescription)")
        }
    }.resume()

Ошибка, которую я получил: Ошибка пост-запроса Необязательно ("Произошла ошибка SSL и безопасное соединение ссервер не может быть сделан. ")

018-12-21 12: 24: 55.549759 + 0200 tolk-24-7 [7230: 111102] [BoringSSL] boringssl_context_alert_callback_handler (3718) [C6.1: 2][0x7fce4a77bf00] Уровень предупреждения: неустранимый, описание: сбой рукопожатия 2018-12-21 12: 24: 55.550047 + 0200 tolk-24-7 [7230: 111102] [BoringSSL] boringssl_session_errorlog (224) [C6.1: 2] [0x7fce4a77bf00] [boringssl_session_handshake_incomplete] SSL_ERROR_SSL (1): операция не выполнена в библиотеке 2018-12-21 12: 24: 55.550332 + 0200 tolk-24-7 [7230: 111102] [BoringSSL] boringssl_session_handshake_error_print (205) [C6] [1][0x7fce4a77bf00] 140523985879704: ошибка: 10000410: подпрограммы SSL: ОТКРЫТОSSL_internal: SSLV3_ALERT_HANDSHAKE_FAILURE: /BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.220.4/ssl/tls_record.cc: 586: номер предупреждения SSL 40 2018-12-21 12: 24 + 55,550200 tolk-24-7 [7230: 111102] [BoringSSL] boringssl_context_get_error_code (3539) [C6.1: 2] [0x7fce4a77bf00] SSL_AD_HANDSHAKE_FAILURE 2018-12-21 12: 24: 55.552299 + 0200 tolk-24-7: 72 толк-24-7: 72 Толк-24-7] TIC TCP Conn Failed [6: 0x600002dd6c40]: 3: -9824 Err (-9824) 2018-12-21 12: 24: 55.555924 + 0200 tolk-24-7 [7230: 111102] Ошибка загрузки NSURLSession / NSURLConnection HTTP (kCFStreamErrorDomainSSL, -9824) 2018-12-21 12: 24: 55.556052 + 0200 tolk-24-7 [7230: 111102] Задача <7888D080-D175-4DBF-8F66-4183F0D653E6>. <1> Ошибка загрузки HTTP (код ошибки: -1200 [3: -9824]) 2018-12-21 12: 24: 55.556234 + 0200 tolk-24-7 [7230: 111613] Задание <7888D080-D175-4DBF-8F66-4183F0D653E6>. <1> завершено с ошибкой -код: -1200

1 Ответ

0 голосов
/ 13 мая 2019

Я чувствую ваше разочарование, я не работал с Swish API как таковым, но похоже, что URLSession не может выполнить запрос сертификата клиента.На этом этапе происходит сбой рукопожатия.

Существует возможность добавить URLSessionDelegate в URLSession для обработки проблем аутентификации, таких как ServerTrust и ClientCertificate.Они обсуждают это здесь: Swift 3 UrlSession с аутентификацией клиента по сертификату

Если вы можете создать p12 / pfx с сертификатом клиента и секретным ключом, вы можете использовать SecPKCS12Import дляимпортируйте его и используйте для доверия URLCredential в NSURLAuthenticationMethodClientCertificate, полученном в URLSessionDelegate.Вот реализация, которую я написал:

func urlSession(
        _ session: URLSession,
        didReceive challenge: URLAuthenticationChallenge,
        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
    {

        let authenticationMethod = challenge.protectionSpace.authenticationMethod
        if authenticationMethod == NSURLAuthenticationMethodServerTrust {
            //Handle server trust if necessary
        } else if authenticationMethod == NSURLAuthenticationMethodClientCertificate {
            if let clientCredential = try? getClientUrlCredential() {
                completionHandler(.useCredential, clientCredential)
            } else {
                completionHandler(.cancelAuthenticationChallenge, nil)
            }
        }
    }

getClientUrlCredential function:

private func getClientUrlCredential() throws -> URLCredential {

        let p12Data = getP12Data() //Get the data from the bundle if it's bundled in the app
        let p12Key = getP12Key() //you need the key set for creating the p12/pfx

        let certOptions: NSDictionary = [
            kSecImportExportPassphrase as NSString : p12Key as NSString
        ]

        // import certificate to read its entries
        var items: CFArray?
        let status = SecPKCS12Import(p12Data, certOptions, &items)

        if status == errSecSuccess,
            let items = items,
            let dict = (items as Array).first as? [String: AnyObject],
            let certChain = dict[kSecImportItemCertChain as String] as? [SecTrust] {

            // Check if SecIdentityGetTypeID is present
            guard let cfIdentity = dict[kSecImportItemIdentity as String] as CFTypeRef?,
                CFGetTypeID(cfIdentity) == SecIdentityGetTypeID() else {
                    throw URLSessionPinningDelegateError.localClientCertificateError
            }

            let identity = dict[kSecImportItemIdentity as String] as! SecIdentity
            return URLCredential(
                identity: identity,
                certificates: certChain,
                persistence: .forSession
            )
        }

        //Failed to read local certificate, throw error
        throw URLSessionPinningDelegateError.localClientCertificateError
    }

Имея действительный клиентский сертификат, вы должны иметь возможность выполнить привет клиента и настроить TLS на сервере, посколькуКажется, сейчас вы терпите неудачу.Предупреждение SSL по номеру 40, которое вы получаете от BoringSSL, подсказывает мне, по крайней мере.

Надеюсь, что это, по крайней мере, направит вас в правильном направлении, и будет рад поддержать вас в случае необходимости.

...