My issue is this: I have created an app that is supposed to accept Credit/Debit cards. And Im using Braintree 4 SDK in iOS with swift using a cocoa pod. I can present the drop in just fine but what it does is that just ask for a cc number and then disappears, why? Because I use the code in the quick-start guide and it's supposed to do that. But it doesn't say anything about when to call the nonce function or show the amount or anything! With SDK 3 is a view controller where I can put the delegate and almost everything works except remembering cards. So my question are where am I supposed to call the nonce function in iOS? Where does the total should be shown? And how do I make a payment to the server BT?.
The page is really lacking actual information for everything! Help.
My code:
// Mark - Braintree methods
func showDropIn(clientTokenOrTokenizationKey: String) {
let request = BTDropInRequest()
request.amount = "\(total)"
request.currencyCode = "MXN"
// request.
let dropIn = BTDropInController(authorization: clientTokenOrTokenizationKey, request: request)
{ (controller, result, error) in
if (error != nil) {
print("ERROR")
} else if (result?.isCancelled == true) {
print("CANCELLED")
} else if let result = result {
// Use the BTDropInResult properties to update your UI
// result.paymentOptionType
// result.paymentMethod
// result.paymentIcon
// result.paymentDescription
print(result)
// controller.
}
controller.dismiss(animated: true, completion: nil)
}
self.present(dropIn!, animated: true, completion: nil)
// //create paymentrequest
// let
// paymentRequest: BTPaymentRequest = BTPaymentRequest()
// paymentRequest.summaryTitle = "Lavado Automozo"
// paymentRequest.summaryDescription = "$\(totalLabel.text!) precio total de los servicios solicitados."
// paymentRequest.displayAmount = "$\(total!).00 MXN"
// paymentRequest.currencyCode = "MXN"
// paymentRequest.callToActionText = "Aceptar compra."
// paymentRequest.shouldHideCallToAction = false
// //set delegate
// let dropInViewController = BTDropInViewController(apiClient: braintreeClient!)
// dropInViewController.delegate = self
// dropInViewController.paymentRequest = paymentRequest
// //add cancel button
// dropInViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.cancel, target: self, action: #selector(ViewController.userDidCancelPayment))
//
// //present view
// let navigationController = UINavigationController(rootViewController: dropInViewController)
//
// present(navigationController, animated: true, completion: nil)
//
// let request = BTDropInRequest()
// let dropIn = BTDropInController()
// { (controller, result, error) in
// if (error != nil) {
// print("ERROR")
// } else if (result?.isCancelled == true) {
// print("CANCELLED")
// } else if let result = result {
// // Use the BTDropInResult properties to update your UI
// // result.paymentOptionType
// // result.paymentMethod
// // result.paymentIcon
// // result.paymentDescription
// }
// controller.dismiss(animated: true, completion: nil)
// }
// self.present(dropIn!, animated: true, completion: nil)
}
And Where am I supposed to call this?:
func postNonceToServer(paymentMethodNonce: String) -> Bool {
PFCloud.callFunction(inBackground: "checkout", withParameters: ["payment_method_nonce" : paymentMethodNonce, "amount" : "\(total!).00"]) {
(response, error) -> Void in
// let ratings = response as? Float
// ratings is 4.5
if error != nil {
} else {
}
print("the response \(response ?? "nil")")
print("The error: \(error?.localizedDescription)")
//self.clientToken = response as! String
// print(self.clientToken)
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "mmm. dd, YYYY HH:mm"
dateFormatter.timeZone = NSTimeZone.local
let fechaRegistro = dateFormatter.string(from: Date())
// displayError("Exito", message: "Tu pago ha sido procesado, en unos momentos atenderemos tu orden. Total es de $\(totalLabel.text!) la fecha registrada \(fechaRegistro)")
let usuarioPagado: PFObject = PFObject(className: "Ordenes")
let location: PFGeoPoint = PFGeoPoint(latitude: ubicacion.latitude, longitude: ubicacion.longitude)
usuarioPagado["Ubicacion"] = location
usuarioPagado["NumeroExterior"] = numeroExteriorTextField.text!
usuarioPagado["NumeroDeTelefono"] = telefonoTextField.text!
usuarioPagado["LavadoCarro"] = numeroCarrosTextField.text!
usuarioPagado["LavadoMiniVan"] = numeroMinivanTextField.text!
usuarioPagado["LavadoPickUp"] = numeroPickUpsTextField.text!
usuarioPagado["LavadoDeVan"] = numeroVansTextField.text!
usuarioPagado["LavadoAspiradoCarro"] = numeroAspiradoCarrosTextField.text!
usuarioPagado["LavadoAspiradoMiniVan"] = numeroAspiradoMinivanTextField.text!
usuarioPagado["LavadoAspiradoPickUp"] = numeroPickUpsTextField.text!
usuarioPagado["LavadoAspiradoDeVan"] = numeroAspiradoVansTextField.text!
usuarioPagado["Monto"] = totalLabel.text!
usuarioPagado["NumeroDeTelefono"] = telefonoTextField.text!
usuarioPagado["TipoDeCelular"] = "iPhone"
usuarioPagado["FechaDeOrden"] = fechaRegistro
//usuarioPagado["TipoDeCelular"]
//usuarioPagado["PaymentConfirmation"] = completedPayment.confirmation.description
//
// usuarioPagado.saveInBackground() {
// (success: Bool, error: Error?) -> Void in
//
// if error == nil {
//
// //done
// print("saved object")
//
// } else {
//
// //not done
// print("not saved because \(error?.localizedDescription)")
//
// }
// }
do {
let result = try usuarioPagado.save()
// displayError("Exito", message: "Tu pago ha sido procesado, en unos momentos atenderemos tu orden. Total es de $\(totalLabel.text!) la fecha registrada \(fechaRegistro)")
//
} catch let error {
print(error.localizedDescription)
self.displayError("Error", message: "Hubo un error al guardar tu informacion, ponte ne contacto con nosotros.")
return false
}
numeroCarrosTextField.text = "0"
numeroMinivanTextField.text = "0"
numeroPickUpsTextField.text = "0"
numeroVansTextField.text = "0"
numeroAspiradoCarrosTextField.text = "0"
numeroAspiradoMinivanTextField.text = "0"
numeroAspiradoPickUpsTextField.text = "0"
numeroAspiradoVansTextField.text = "0"
totalLabel.text = "00.00"
self.lavadoSwitch.isOn = false
self.lavadoYAspiradSwitch.isOn = false
self.numeroExteriorTextField.text = ""
self.telefonoTextField.text = ""
// displayError("Exito", message: "Tu pago ha sido procesado, en unos momentos atenderemos tu orden. Total es de $\(totalLabel.text!) la fecha registrada \(fechaRegistro)")
// Update URL with your server
// let paymentURL = URL(string: "https://your-server.example.com/payment-methods")!
// let request = NSMutableURLRequest(url: paymentURL)
// request.httpBody = "payment_method_nonce=\(paymentMethodNonce)".data(using: String.Encoding.utf8)
// request.httpMethod = "POST"
//
// URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
// // TODO: Handle success or failure
// }.resume()
return true
}
After the dummy card it just closes.
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
You can access the payment method nonce via the result
object within showDropIn()
. This is also where you may call postNonceToServer()
.
func showDropIn(clientTokenOrTokenizationKey: String) {
let request = BTDropInRequest()
request.amount = "\(total)"
request.currencyCode = "MXN"
let dropIn = BTDropInController(authorization: clientTokenOrTokenizationKey, request: request)
{ (controller, result, error) in
if (error != nil) {
print("ERROR")
} else if (result?.isCancelled == true) {
print("CANCELLED")
} else if let result = result {
let selectedPaymentMethod = result.paymentMethod! // retrieve the payment method.
self.postNonceToServer(paymentMethodNonce: selectedPaymentMethod.nonce) // call postNonceToServer() with the nonce from the selected payment method.
}
controller.dismiss(animated: true, completion: nil)
}
self.present(dropIn!, animated: true, completion: nil)
}
After you successfully call postNonceToServer()
you can receive the payment method nonce and create a transaction on your server.