7

Using Swift 3 I'm implementing Apple Pay in my app and trying to send PKPaymentToken which I receive in paymentAuthorizationViewController to bank's API to process payment but without success. The data which I send is always rejected.

Bank support suggests me to send the whole payment.token instead of payment.token.PaymentData but I don't how can I do that cause payment.token is the instance of PKPaymentToken and as I know cannot be converted to string or encoded to base64.

What is the correct way to send the token?

   func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, completion: @escaping ((PKPaymentAuthorizationStatus) -> Void)) {
        self.processPayment(payment: payment, completion: completion)
    }

    func processPayment(payment: PKPayment, completion: @escaping ((PKPaymentAuthorizationStatus) -> Void)) {

        print("Payment token: \(payment.token)")

        let paymentData=String(data: payment.token.paymentData.base64EncodedData(), encoding: .utf8)

        var request = URLRequest(url: URL(string: "https://bankapi.com/method")!)
        request.httpMethod = "POST"
        let postString = "orderid=\(orderid)&token=\(String(describing: paymentData))&amount=\(price)"
        print("POST: \(postString)")
        request.httpBody = postString.data(using: .utf8)

        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {                                                 // check for fundamental networking error
                print("error=\(String(describing: error))")
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
            }

            let responseString = String(data: data, encoding: .utf8)
            print("responseString = \(String(describing: responseString))")
            //@TODO check response is failure or success
            //completion(PKPaymentAuthorizationStatus.failure)
        }
        task.resume()
    }

upd. bank service provided me an example in Objective C. I now try to reproduce it in Swift.

moogeek
  • 397
  • 4
  • 14
  • 34

1 Answers1

11

Ok there is now clear for me.

let paymentDataDictionary: [AnyHashable: Any]? = try? JSONSerialization.jsonObject(with: payment.token.paymentData, options: .mutableContainers) as! [AnyHashable : Any]
var paymentType: String = "debit"

var paymentMethodDictionary: [AnyHashable: Any] = ["network": "", "type": paymentType, "displayName": ""]

if #available(iOS 9.0, *) {
    paymentMethodDictionary = ["network": payment.token.paymentMethod.network ?? "", "type": paymentType, "displayName": payment.token.paymentMethod.displayName ?? ""]

    switch payment.token.paymentMethod.type {
        case .debit:
            paymentType = "debit"
        case .credit:
            paymentType = "credit"
        case .store:
            paymentType = "store"
        case .prepaid:
            paymentType = "prepaid"
        default:
            paymentType = "unknown"
        }
}

let cryptogramDictionary: [AnyHashable: Any] = ["paymentData": paymentDataDictionary ?? "", "transactionIdentifier": payment.token.transactionIdentifier, "paymentMethod": paymentMethodDictionary]
let cardCryptogramPacketDictionary: [AnyHashable: Any] = cryptogramDictionary
let cardCryptogramPacketData: Data? = try? JSONSerialization.data(withJSONObject: cardCryptogramPacketDictionary, options: [])

// in cardCryptogramPacketString we now have all necessary data which demand most of bank gateways to process the payment

let cardCryptogramPacketString = String(describing: cardCryptogramPacketData)
Dan Bovey
  • 195
  • 2
  • 11
moogeek
  • 397
  • 4
  • 14
  • 34