如何在 iOS 中使用 Braintree 实现支付应用

Posted

技术标签:

【中文标题】如何在 iOS 中使用 Braintree 实现支付应用【英文标题】:How to implement a payment app with Braintree in iOS 【发布时间】:2017-04-21 18:19:16 【问题描述】:

我的问题是:我创建了一个应该接受信用卡/借记卡的应用程序。我在 ios 中使用 Braintree 4 SDK 和 swift 使用可可豆荚。我可以很好地呈现下降,但它的作用是只要求一个 cc 号码然后消失,为什么?因为我使用快速入门指南中的代码,它应该这样做。但它没有说明何时调用 nonce 函数或显示金额或任何内容! SDK 3 是一个视图控制器,我可以在其中放置委托,除了记忆卡片之外,几乎所有东西都可以工作。所以我的问题是我应该在哪里调用 iOS 中的 nonce 函数?应该在哪里显示总数?以及如何向服务器 BT 付款?

该页面确实缺少所有内容的实际信息!帮助。

我的代码:

// 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)
    

我应该在哪里称呼它?:

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

    

编辑

在虚拟卡之后它就关闭了。

【问题讨论】:

我在通过 cocoapod 安装 Braintree 时遇到此错误。 "找不到BraintreeDropIn 的规范" @Pedro.Alonson 您是否找到了一种向用户显示产品数量并进行购买的方法? @VJVJ 不,我现在使用 Openpay 必须更改框架 【参考方案1】:

全面披露:我在 Braintree 工作。如果您还有任何问题,请随时联系support。

您可以通过showDropIn() 中的result 对象访问付款方式nonce。这也是您可以拨打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)

在您成功调用postNonceToServer() 后,您可以在您的服务器上使用receive the payment method nonce 和create a transaction。

【讨论】:

并显示总数? @Shea 我在通过 cocoapod 安装 Braintree 时遇到此错误。 "无法找到 BraintreeDropIn 的规范 为什么 Paypal 没有显示在我的 Braintree drop in 中?为什么在我的大脑树中输入邮政编码? @KhanShaheb 包括braintree paypal pod,你会没事的。 pod 'Braintree/PayPal'【参考方案2】:

Braintree 由 PayPal 提供

Step 1.braintree 支付网关的大部分工作是由您支持的开发人员设置,braintree 是从两端以及后端和前端部署的。

Step 3.

如果您的应用,请安装以下 pod pod 'BraintreeDropIn' pod 'Braintree/PayPal' Step 3. After Setup braintree 从后端询问您的后端开发人员获取交易令牌的网址。

Step 4. 通过 BTDropInRequest 将此令牌传递给 BTDropInController(他们提供插入式支付 UI),在调用此方法后,我们将获得一个字符串名称 nonce,然后将此带有金额的 nonce 发送到下一个流程。

Step 5.这个API会给你交易的状态以响应它是否成功

【讨论】:

以上是关于如何在 iOS 中使用 Braintree 实现支付应用的主要内容,如果未能解决你的问题,请参考以下文章

Braintree 点对点 iOS

在 iOS 应用中使用 Braintree 支付 api

如何使用现有的 customerId 处理 Braintree 付款

使用Braintree进行iOS订阅

如何使用 Braintree 在客户端显示客户的付款方式?

Braintree for iOS 应用程序与 paypal 集成