commit 23cab0bb8454e7aaf64e24de4f535a0591edef16
Author: Facundo Médica <facundo@inmuvi.com>
Date:   Wed Feb 21 16:27:34 2018 +0000

    test

diff --git a/MercadoPagoSDK/MercadoPagoSDK/MercadoPagoCheckoutServices.swift b/MercadoPagoSDK/MercadoPagoSDK/MercadoPagoCheckoutServices.swift
index bad101b7..51ca8888 100644
--- a/MercadoPagoSDK/MercadoPagoSDK/MercadoPagoCheckoutServices.swift
+++ b/MercadoPagoSDK/MercadoPagoSDK/MercadoPagoCheckoutServices.swift
@@ -9,123 +9,129 @@
 import Foundation
 
 extension MercadoPagoCheckout {
-
+    
     func getCheckoutPreference() {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.getCheckoutPreference(checkoutPreferenceId: self.viewModel.checkoutPreference._id, callback: { [weak self] (checkoutPreference) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.checkoutPreference = checkoutPreference
             strongSelf.viewModel.paymentData.payer = checkoutPreference.getPayer()
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.GET_PREFERENCE.rawValue), errorCallback: { [weak self] (_) -> Void in
                 self?.getCheckoutPreference()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func getDirectDiscount() {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.getDirectDiscount(amount: self.viewModel.getFinalAmount(), payerEmail: self.viewModel.checkoutPreference.payer.email, callback: { [weak self] (discount) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.paymentData.discount = discount
             strongSelf.executeNextStep()
             strongSelf.dismissLoading()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func getPaymentMethodSearch() {
         self.presentLoading()
-
+        
         self.viewModel.mercadoPagoServicesAdapter.getPaymentMethodSearch(amount: self.viewModel.getFinalAmount(), excludedPaymentTypesIds: self.viewModel.getExcludedPaymentTypesIds(), excludedPaymentMethodsIds: self.viewModel.getExcludedPaymentMethodsIds(), defaultPaymentMethod: self.viewModel.getDefaultPaymentMethodId(), payer: Payer(), site: MercadoPagoContext.getSite(), callback: { [weak self] (paymentMethodSearch) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.updateCheckoutModel(paymentMethodSearch: paymentMethodSearch)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.PAYMENT_METHOD_SEARCH.rawValue), errorCallback: { [weak self] (_) -> Void in
-
+                
                 self?.getPaymentMethodSearch()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
-    func getIssuers() {
+    
+    func getIssuers(updateCallback: (() -> Void)? = nil){ // Le agregué un callback para poder ordenar los requests (primero este, despues getpayercost, etc)
         self.presentLoading()
         guard let paymentMethod = self.viewModel.paymentData.getPaymentMethod() else {
             return
         }
         let bin = self.viewModel.cardToken?.getBin()
         self.viewModel.mercadoPagoServicesAdapter.getIssuers(paymentMethodId: paymentMethod._id, bin: bin, callback: { [weak self] (issuers) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.issuers = issuers
-
+            
             if issuers.count == 1 {
                 strongSelf.viewModel.updateCheckoutModel(issuer: issuers[0])
             }
-            strongSelf.dismissLoading()
-            strongSelf.executeNextStep()
-
+            
+            if let updateCallback = updateCallback {
+                updateCallback()
+                strongSelf.dismissLoading()
+            } else {
+                strongSelf.dismissLoading()
+                strongSelf.executeNextStep()
+            }
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.GET_ISSUERS.rawValue), errorCallback: { [weak self] (_) in
                 self?.getIssuers()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func createCardToken(cardInformation: CardInformation? = nil, securityCode: String? = nil) {
         guard let cardInfo = self.viewModel.paymentOptionSelected as? CardInformation else {
             createNewCardToken()
@@ -136,44 +142,44 @@ extension MercadoPagoCheckout {
                 return // TODO Refactor : Tenemos unos lios barbaros con CardInformation y CardInformationForm, no entiendo porque hay uno y otr
             }
             cloneCardToken(token: token, securityCode: securityCode!)
-
+            
         } else if self.viewModel.mpESCManager.hasESCEnable() {
             var savedESCCardToken: SavedESCCardToken
-
+            
             let esc = self.viewModel.mpESCManager.getESC(cardId: cardInfo.getCardId())
-
+            
             if !String.isNullOrEmpty(esc) {
                 savedESCCardToken = SavedESCCardToken(cardId: cardInfo.getCardId(), esc: esc)
             } else {
                 savedESCCardToken = SavedESCCardToken(cardId: cardInfo.getCardId(), securityCode: securityCode)
             }
             createSavedESCCardToken(savedESCCardToken: savedESCCardToken)
-
+            
         } else {
             createSavedCardToken(cardInformation: cardInfo, securityCode: securityCode!)
         }
     }
-
+    
     func createNewCardToken() {
         self.presentLoading()
-
+        
         self.viewModel.mercadoPagoServicesAdapter.createToken(cardToken: self.viewModel.cardToken!, callback: { [weak self] (token) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.updateCheckoutModel(token: token)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
             let error = MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.CREATE_TOKEN.rawValue)
-
+            
             if error.apiException?.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_IDENTIFICATION_NUMBER.rawValue) == true {
                 if let identificationViewController = strongSelf.navigationController.viewControllers.last as? IdentificationViewController {
                     identificationViewController.showErrorMessage("Revisa este dato".localized)
@@ -186,52 +192,52 @@ extension MercadoPagoCheckout {
                 strongSelf.dismissLoading()
                 strongSelf.executeNextStep()
             }
-
+            
         }
     }
-
+    
     func createSavedCardToken(cardInformation: CardInformation, securityCode: String) {
         self.presentLoading()
-
+        
         let cardInformation = self.viewModel.paymentOptionSelected as! CardInformation
         let saveCardToken = SavedCardToken(card: cardInformation, securityCode: securityCode, securityCodeRequired: true)
-
+        
         self.viewModel.mercadoPagoServicesAdapter.createToken(savedCardToken: saveCardToken, callback: { [weak self] (token) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             if token.lastFourDigits.isEmpty {
                 token.lastFourDigits = cardInformation.getCardLastForDigits()
             }
             strongSelf.viewModel.updateCheckoutModel(token: token)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.CREATE_TOKEN.rawValue), errorCallback: { [weak self] (_) in
                 self?.createSavedCardToken(cardInformation: cardInformation, securityCode: securityCode)
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func createSavedESCCardToken(savedESCCardToken: SavedESCCardToken) {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.createToken(savedESCCardToken: savedESCCardToken, callback: { [weak self] (token) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             if token.lastFourDigits.isEmpty {
                 let cardInformation = strongSelf.viewModel.paymentOptionSelected as? CardInformation
                 token.lastFourDigits = cardInformation?.getCardLastForDigits() ?? ""
@@ -239,79 +245,79 @@ extension MercadoPagoCheckout {
             strongSelf.viewModel.updateCheckoutModel(token: token)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
             let mpError = MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.CREATE_TOKEN.rawValue)
-
+            
             if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_ESC.rawValue) ||  apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_FINGERPRINT.rawValue) {
-
+                
                 strongSelf.viewModel.mpESCManager.deleteESC(cardId: savedESCCardToken.cardId)
-
+                
             } else {
                 strongSelf.viewModel.errorInputs(error: mpError, errorCallback: { [weak self] (_) in
                     self?.createSavedESCCardToken(savedESCCardToken: savedESCCardToken)
                 })
-
+                
             }
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func cloneCardToken(token: Token, securityCode: String) {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.cloneToken(tokenId: token._id, securityCode: securityCode, callback: { [weak self] (token) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.updateCheckoutModel(token: token)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.CREATE_TOKEN.rawValue), errorCallback: { [weak self] (_) in
                 self?.cloneCardToken(token: token, securityCode: securityCode)
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func getPayerCosts(updateCallback: (() -> Void)? = nil) {
         self.presentLoading()
-
+        
         guard let paymentMethod = self.viewModel.paymentData.getPaymentMethod() else {
             return
         }
-
+        
         let bin = self.viewModel.cardToken?.getBin()
-
+        
         self.viewModel.mercadoPagoServicesAdapter.getInstallments(bin: bin, amount: self.viewModel.getFinalAmount(), issuer: self.viewModel.paymentData.getIssuer(), paymentMethodId: paymentMethod._id, callback: { [weak self] (installments) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.payerCosts = installments[0].payerCosts
-
+            
             let defaultPayerCost = strongSelf.viewModel.checkoutPreference.paymentPreference?.autoSelectPayerCost(installments[0].payerCosts)
             if let defaultPC = defaultPayerCost {
                 strongSelf.viewModel.updateCheckoutModel(payerCost: defaultPC)
             }
-
+            
             if let updateCallback = updateCallback {
                 updateCallback()
                 strongSelf.dismissLoading()
@@ -319,105 +325,109 @@ extension MercadoPagoCheckout {
                 strongSelf.dismissLoading()
                 strongSelf.executeNextStep()
             }
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.GET_INSTALLMENTS.rawValue), errorCallback: { [weak self] (_) in
                 self?.getPayerCosts()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func createPayment() {
         self.presentLoading()
-
-        var paymentBody: [String:Any]
-        if MercadoPagoCheckoutViewModel.servicePreference.isUsingDeafaultPaymentSettings() {
-            let mpPayment = MercadoPagoCheckoutViewModel.createMPPayment(preferenceId: self.viewModel.checkoutPreference._id, paymentData: self.viewModel.paymentData, binaryMode: self.viewModel.binaryMode)
-            paymentBody = mpPayment.toJSON()
-        } else {
-            paymentBody = self.viewModel.paymentData.toJSON()
-        }
-
-        var createPaymentQuery: [String:String]? = [:]
-        if let paymentAdditionalInfo = MercadoPagoCheckoutViewModel.servicePreference.getPaymentAddionalInfo() as? [String:String] {
-            createPaymentQuery = paymentAdditionalInfo
-        } else {
-            createPaymentQuery = nil
-        }
-
-        self.viewModel.mercadoPagoServicesAdapter.createPayment(url: MercadoPagoCheckoutViewModel.servicePreference.getPaymentURL(), uri: MercadoPagoCheckoutViewModel.servicePreference.getPaymentURI(), paymentData: paymentBody as NSDictionary, query: createPaymentQuery, callback: { [weak self] (payment) in
-
-            guard let strongSelf = self else {
-                return
-            }
-
-            strongSelf.viewModel.updateCheckoutModel(payment: payment)
-            strongSelf.dismissLoading()
-            strongSelf.executeNextStep()
-
-        }) { [weak self] (error) in
-
-            guard let strongSelf = self else {
-                return
-            }
-
-            strongSelf.dismissLoading()
-            let mpError = MPSDKError.convertFrom(error, requestOrigin: ApiUtil.RequestOrigin.CREATE_PAYMENT.rawValue)
-
-            if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_PAYMENT_WITH_ESC.rawValue) {
-                strongSelf.viewModel.prepareForInvalidPaymentWithESC()
-            } else if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_PAYMENT_IDENTIFICATION_NUMBER.rawValue) {
-                self?.viewModel.paymentData.clearCollectedData()
-                let mpInvalidIdentificationError = MPSDKError.init(message: "Algo salió mal… ".localized, errorDetail: "El número de identificación es inválido".localized, retry: true)
-                strongSelf.viewModel.errorInputs(error: mpInvalidIdentificationError, errorCallback: { [weak self] (_) in
-                    self?.viewModel.resetInformation()
-                    self?.viewModel.resetGroupSelection()
-                    self?.executeNextStep()
-                })
-            } else {
-                strongSelf.viewModel.errorInputs(error: mpError, errorCallback: { [weak self] (_) in
-                    self?.createPayment()
-                })
-            }
-            strongSelf.executeNextStep()
-
-        }
+        self.getIssuers(updateCallback: { // Esto lo agregué porque en la llamada getPayerCosts daba error por no tener issuer
+            self.getPayerCosts(updateCallback: { // Sin esto no había forma de obtener el transactionAmount y otros datos necesarios
+                var paymentBody: [String:Any]
+                if MercadoPagoCheckoutViewModel.servicePreference.isUsingDeafaultPaymentSettings() {
+                    let mpPayment = MercadoPagoCheckoutViewModel.createMPPayment(preferenceId: self.viewModel.checkoutPreference._id, paymentData: self.viewModel.paymentData, binaryMode: self.viewModel.binaryMode)
+                    paymentBody = mpPayment.toJSON()
+                } else {
+                    paymentBody = self.viewModel.paymentData.toCustomJSON()
+                }
+                
+                // Ahora el additionalInfo se agrega en el body, tal como lo hace el SDK de Android
+                if let paymentAdditionalInfo = MercadoPagoCheckoutViewModel.servicePreference.getPaymentAddionalInfo() as? [String:String] {
+                    for (k, v) in paymentAdditionalInfo {
+                        paymentBody[k] = v
+                    }
+                }
+                
+                // query ahora es nil, ya que no paso ningún dato utilizando ese método
+                self.viewModel.mercadoPagoServicesAdapter.createPayment(url: MercadoPagoCheckoutViewModel.servicePreference.getPaymentURL(), uri: MercadoPagoCheckoutViewModel.servicePreference.getPaymentURI(), paymentData: paymentBody as NSDictionary, query: nil, callback: { [weak self] (payment) in
+                    
+                    guard let strongSelf = self else {
+                        return
+                    }
+                    
+                    strongSelf.viewModel.updateCheckoutModel(payment: payment)
+                    strongSelf.dismissLoading()
+                    strongSelf.executeNextStep()
+                    
+                }) { [weak self] (error) in
+                    
+                    guard let strongSelf = self else {
+                        return
+                    }
+                    
+                    strongSelf.dismissLoading()
+                    let mpError = MPSDKError.convertFrom(error, requestOrigin: ApiUtil.RequestOrigin.CREATE_PAYMENT.rawValue)
+                    
+                    if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_PAYMENT_WITH_ESC.rawValue) {
+                        strongSelf.viewModel.prepareForInvalidPaymentWithESC()
+                    } else if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_PAYMENT_IDENTIFICATION_NUMBER.rawValue) {
+                        self?.viewModel.paymentData.clearCollectedData()
+                        let mpInvalidIdentificationError = MPSDKError.init(message: "Algo salió mal… ".localized, errorDetail: "El número de identificación es inválido".localized, retry: true)
+                        strongSelf.viewModel.errorInputs(error: mpInvalidIdentificationError, errorCallback: { [weak self] (_) in
+                            self?.viewModel.resetInformation()
+                            self?.viewModel.resetGroupSelection()
+                            self?.executeNextStep()
+                        })
+                    } else {
+                        strongSelf.viewModel.errorInputs(error: mpError, errorCallback: { [weak self] (_) in
+                            self?.createPayment()
+                        })
+                    }
+                    strongSelf.executeNextStep()
+                    
+                }
+            })
+        })
     }
-
+    
     func getInstructions() {
         self.presentLoading()
-
+        
         guard let paymentResult = self.viewModel.paymentResult else {
             fatalError("Get Instructions - Payment Result does no exist")
         }
-
+        
         guard let paymentId = paymentResult._id else {
-           fatalError("Get Instructions - Payment Id does no exist")
+            fatalError("Get Instructions - Payment Id does no exist")
         }
-
+        
         guard let paymentTypeId = paymentResult.paymentData?.getPaymentMethod()?.paymentTypeId else {
             fatalError("Get Instructions - Payment Method Type Id does no exist")
         }
-
+        
         self.viewModel.mercadoPagoServicesAdapter.getInstructions(paymentId: paymentId, paymentTypeId: paymentTypeId, callback: { [weak self] (instructionsInfo) in
-
+            
             guard let strongSelf = self else {
                 return
             }
             strongSelf.viewModel.instructionsInfo = instructionsInfo
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
@@ -426,34 +436,34 @@ extension MercadoPagoCheckout {
                 self?.getInstructions()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func getIdentificationTypes() {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.getIdentificationTypes(callback: { [weak self] (identificationTypes) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.updateCheckoutModel(identificationTypes: identificationTypes)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.GET_IDENTIFICATION_TYPES.rawValue), errorCallback: { [weak self] (_) in
                 self?.getIdentificationTypes()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
 }
diff --git a/MercadoPagoSDK/MercadoPagoSDK/PaymentData.swift b/MercadoPagoSDK/MercadoPagoSDK/PaymentData.swift
index 3974c90a..2d636ad7 100644
--- a/MercadoPagoSDK/MercadoPagoSDK/PaymentData.swift
+++ b/MercadoPagoSDK/MercadoPagoSDK/PaymentData.swift
@@ -9,7 +9,7 @@
 import UIKit
 
 public class PaymentData: NSObject {
-
+    
     public var paymentMethod: PaymentMethod?
     public var issuer: Issuer?
     public var payerCost: PayerCost?
@@ -17,7 +17,7 @@ public class PaymentData: NSObject {
     public var payer = Payer()
     public var transactionDetails: TransactionDetails?
     public var discount: DiscountCoupon?
-
+    
     func clearCollectedData() {
         self.paymentMethod = nil
         self.issuer = nil
@@ -27,60 +27,60 @@ public class PaymentData: NSObject {
         self.transactionDetails = nil
         // No borrar el descuento
     }
-
+    
     func isComplete() -> Bool {
-
+        
         guard let paymentMethod = self.paymentMethod else {
             return false
         }
-
+        
         if paymentMethod.isEntityTypeRequired && payer.entityType == nil {
             return false
         }
-
+        
         if paymentMethod.isPayerInfoRequired && payer.identification == nil {
             return false
         }
-
+        
         if !Array.isNullOrEmpty(paymentMethod.financialInstitutions) && transactionDetails?.financialInstitution == nil {
             return false
         }
-
+        
         if paymentMethod._id == PaymentTypeId.ACCOUNT_MONEY.rawValue || !paymentMethod.isOnlinePaymentMethod {
             return true
         }
-
+        
         if paymentMethod.isCard && (token == nil || payerCost == nil) {
-
+            
             if (paymentMethod.paymentTypeId == PaymentTypeId.DEBIT_CARD.rawValue || paymentMethod.paymentTypeId == PaymentTypeId.PREPAID_CARD.rawValue ) && token != nil {
                 return true
             }
             return false
         }
-
+        
         return true
     }
-
+    
     func hasToken() -> Bool {
         return token != nil
     }
-
+    
     func hasIssuer() -> Bool {
         return issuer != nil
     }
-
+    
     func hasPayerCost() -> Bool {
         return payerCost != nil
     }
-
+    
     func hasPaymentMethod() -> Bool {
         return paymentMethod != nil
     }
-
+    
     func hasCustomerPaymentOption() -> Bool {
         return hasPaymentMethod() && (self.paymentMethod!.isAccountMoney || (hasToken() && !String.isNullOrEmpty(self.token!.cardId)))
     }
-
+    
     public func updatePaymentDataWith(paymentMethod: PaymentMethod?) {
         guard let paymentMethod = paymentMethod else {
             return
@@ -90,21 +90,21 @@ public class PaymentData: NSObject {
         cleanPayerCost()
         self.paymentMethod = paymentMethod
     }
-
+    
     public func updatePaymentDataWith(token: Token?) {
         guard let token = token else {
             return
         }
         self.token = token
     }
-
+    
     public func updatePaymentDataWith(payerCost: PayerCost?) {
         guard let payerCost = payerCost else {
             return
         }
         self.payerCost = payerCost
     }
-
+    
     public func updatePaymentDataWith(issuer: Issuer?) {
         guard let issuer = issuer else {
             return
@@ -112,75 +112,108 @@ public class PaymentData: NSObject {
         cleanPayerCost()
         self.issuer = issuer
     }
-
+    
     public func updatePaymentDataWith(payer: Payer?) {
         guard let payer = payer else {
             return
         }
         self.payer = payer
     }
-
+    
     public func cleanToken() {
         self.token = nil
     }
-
+    
     public func cleanPayerCost() {
         self.payerCost = nil
     }
-
+    
     func cleanIssuer() {
         self.issuer = nil
     }
-
+    
     func cleanPaymentMethod() {
         self.paymentMethod = nil
     }
-
-   public func getToken() -> Token? {
+    
+    public func getToken() -> Token? {
         return token
     }
-
+    
     public func getPayerCost() -> PayerCost? {
         return payerCost
     }
-
+    
     public func getIssuer() -> Issuer? {
         return issuer
     }
-
+    
     public func getPaymentMethod() -> PaymentMethod? {
         return paymentMethod
     }
-
+    
     func toJSONString() -> String {
         return JSONHandler.jsonCoding(toJSON())
     }
-
+    
     func toJSON() -> [String:Any] {
-       var obj: [String:Any] = [
+        var obj: [String:Any] = [
             "payer": payer.toJSON()
-       ]
+        ]
         if let paymentMethod = self.paymentMethod {
             obj["payment_method"] = paymentMethod.toJSON()
         }
-
+        
         if let payerCost = self.payerCost {
             obj["payer_cost"] = payerCost.toJSON()
         }
-
+        
         if let token = self.token {
             obj["card_token"] = token.toJSON()
         }
-
+        
         if let issuer = self.issuer {
             obj["issuer"] = issuer.toJSON()
         }
-
+        
         if let discount = self.discount {
             obj["discount"] = discount.toJSON()
         }
-
+        
         return obj
     }
-
+    
+    // Agrego este método para no modificar el otro
+    // Le agrego algunos tags y modifico otros para que sea "compliant" con el request que hace Android
+    func toCustomJSON() -> [String:Any] {
+        var obj: [String:Any] = [
+            "payer": payer.toJSON()
+        ]
+        if let paymentMethod = self.paymentMethod {
+            obj["payment_method"] = paymentMethod.toJSON()
+            obj["payment_method_id"] = paymentMethod._id
+        }
+        
+        if let payerCost = self.payerCost {
+            obj["transaction_amount"] = payerCost.totalAmount
+            obj["installments"] = payerCost.installments
+        }
+        
+        if let token = self.token {
+            obj["card_token"] = token._id
+        }
+        
+        if let issuer = self.issuer {
+            obj["issuer"] = issuer.toJSON()
+            obj["card_issuer_id"] = issuer._id
+        }
+        
+        if let discount = self.discount {
+            obj["discount"] = discount.toJSON()
+            obj["campaign_id"] = discount._id
+        }
+        
+        return obj
+    }
+    
 }
commit 23cab0bb8454e7aaf64e24de4f535a0591edef16
Author: Facundo Médica <facundo@inmuvi.com>
Date:   Wed Feb 21 16:27:34 2018 +0000

    test

diff --git a/MercadoPagoSDK/MercadoPagoSDK/MercadoPagoCheckoutServices.swift b/MercadoPagoSDK/MercadoPagoSDK/MercadoPagoCheckoutServices.swift
index bad101b7..51ca8888 100644
--- a/MercadoPagoSDK/MercadoPagoSDK/MercadoPagoCheckoutServices.swift
+++ b/MercadoPagoSDK/MercadoPagoSDK/MercadoPagoCheckoutServices.swift
@@ -9,123 +9,129 @@
 import Foundation
 
 extension MercadoPagoCheckout {
-
+    
     func getCheckoutPreference() {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.getCheckoutPreference(checkoutPreferenceId: self.viewModel.checkoutPreference._id, callback: { [weak self] (checkoutPreference) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.checkoutPreference = checkoutPreference
             strongSelf.viewModel.paymentData.payer = checkoutPreference.getPayer()
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.GET_PREFERENCE.rawValue), errorCallback: { [weak self] (_) -> Void in
                 self?.getCheckoutPreference()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func getDirectDiscount() {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.getDirectDiscount(amount: self.viewModel.getFinalAmount(), payerEmail: self.viewModel.checkoutPreference.payer.email, callback: { [weak self] (discount) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.paymentData.discount = discount
             strongSelf.executeNextStep()
             strongSelf.dismissLoading()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func getPaymentMethodSearch() {
         self.presentLoading()
-
+        
         self.viewModel.mercadoPagoServicesAdapter.getPaymentMethodSearch(amount: self.viewModel.getFinalAmount(), excludedPaymentTypesIds: self.viewModel.getExcludedPaymentTypesIds(), excludedPaymentMethodsIds: self.viewModel.getExcludedPaymentMethodsIds(), defaultPaymentMethod: self.viewModel.getDefaultPaymentMethodId(), payer: Payer(), site: MercadoPagoContext.getSite(), callback: { [weak self] (paymentMethodSearch) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.updateCheckoutModel(paymentMethodSearch: paymentMethodSearch)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.PAYMENT_METHOD_SEARCH.rawValue), errorCallback: { [weak self] (_) -> Void in
-
+                
                 self?.getPaymentMethodSearch()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
-    func getIssuers() {
+    
+    func getIssuers(updateCallback: (() -> Void)? = nil){ // Le agregué un callback para poder ordenar los requests (primero este, despues getpayercost, etc)
         self.presentLoading()
         guard let paymentMethod = self.viewModel.paymentData.getPaymentMethod() else {
             return
         }
         let bin = self.viewModel.cardToken?.getBin()
         self.viewModel.mercadoPagoServicesAdapter.getIssuers(paymentMethodId: paymentMethod._id, bin: bin, callback: { [weak self] (issuers) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.issuers = issuers
-
+            
             if issuers.count == 1 {
                 strongSelf.viewModel.updateCheckoutModel(issuer: issuers[0])
             }
-            strongSelf.dismissLoading()
-            strongSelf.executeNextStep()
-
+            
+            if let updateCallback = updateCallback {
+                updateCallback()
+                strongSelf.dismissLoading()
+            } else {
+                strongSelf.dismissLoading()
+                strongSelf.executeNextStep()
+            }
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.GET_ISSUERS.rawValue), errorCallback: { [weak self] (_) in
                 self?.getIssuers()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func createCardToken(cardInformation: CardInformation? = nil, securityCode: String? = nil) {
         guard let cardInfo = self.viewModel.paymentOptionSelected as? CardInformation else {
             createNewCardToken()
@@ -136,44 +142,44 @@ extension MercadoPagoCheckout {
                 return // TODO Refactor : Tenemos unos lios barbaros con CardInformation y CardInformationForm, no entiendo porque hay uno y otr
             }
             cloneCardToken(token: token, securityCode: securityCode!)
-
+            
         } else if self.viewModel.mpESCManager.hasESCEnable() {
             var savedESCCardToken: SavedESCCardToken
-
+            
             let esc = self.viewModel.mpESCManager.getESC(cardId: cardInfo.getCardId())
-
+            
             if !String.isNullOrEmpty(esc) {
                 savedESCCardToken = SavedESCCardToken(cardId: cardInfo.getCardId(), esc: esc)
             } else {
                 savedESCCardToken = SavedESCCardToken(cardId: cardInfo.getCardId(), securityCode: securityCode)
             }
             createSavedESCCardToken(savedESCCardToken: savedESCCardToken)
-
+            
         } else {
             createSavedCardToken(cardInformation: cardInfo, securityCode: securityCode!)
         }
     }
-
+    
     func createNewCardToken() {
         self.presentLoading()
-
+        
         self.viewModel.mercadoPagoServicesAdapter.createToken(cardToken: self.viewModel.cardToken!, callback: { [weak self] (token) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.updateCheckoutModel(token: token)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
             let error = MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.CREATE_TOKEN.rawValue)
-
+            
             if error.apiException?.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_IDENTIFICATION_NUMBER.rawValue) == true {
                 if let identificationViewController = strongSelf.navigationController.viewControllers.last as? IdentificationViewController {
                     identificationViewController.showErrorMessage("Revisa este dato".localized)
@@ -186,52 +192,52 @@ extension MercadoPagoCheckout {
                 strongSelf.dismissLoading()
                 strongSelf.executeNextStep()
             }
-
+            
         }
     }
-
+    
     func createSavedCardToken(cardInformation: CardInformation, securityCode: String) {
         self.presentLoading()
-
+        
         let cardInformation = self.viewModel.paymentOptionSelected as! CardInformation
         let saveCardToken = SavedCardToken(card: cardInformation, securityCode: securityCode, securityCodeRequired: true)
-
+        
         self.viewModel.mercadoPagoServicesAdapter.createToken(savedCardToken: saveCardToken, callback: { [weak self] (token) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             if token.lastFourDigits.isEmpty {
                 token.lastFourDigits = cardInformation.getCardLastForDigits()
             }
             strongSelf.viewModel.updateCheckoutModel(token: token)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.CREATE_TOKEN.rawValue), errorCallback: { [weak self] (_) in
                 self?.createSavedCardToken(cardInformation: cardInformation, securityCode: securityCode)
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func createSavedESCCardToken(savedESCCardToken: SavedESCCardToken) {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.createToken(savedESCCardToken: savedESCCardToken, callback: { [weak self] (token) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             if token.lastFourDigits.isEmpty {
                 let cardInformation = strongSelf.viewModel.paymentOptionSelected as? CardInformation
                 token.lastFourDigits = cardInformation?.getCardLastForDigits() ?? ""
@@ -239,79 +245,79 @@ extension MercadoPagoCheckout {
             strongSelf.viewModel.updateCheckoutModel(token: token)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
             let mpError = MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.CREATE_TOKEN.rawValue)
-
+            
             if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_ESC.rawValue) ||  apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_FINGERPRINT.rawValue) {
-
+                
                 strongSelf.viewModel.mpESCManager.deleteESC(cardId: savedESCCardToken.cardId)
-
+                
             } else {
                 strongSelf.viewModel.errorInputs(error: mpError, errorCallback: { [weak self] (_) in
                     self?.createSavedESCCardToken(savedESCCardToken: savedESCCardToken)
                 })
-
+                
             }
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func cloneCardToken(token: Token, securityCode: String) {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.cloneToken(tokenId: token._id, securityCode: securityCode, callback: { [weak self] (token) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.updateCheckoutModel(token: token)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.CREATE_TOKEN.rawValue), errorCallback: { [weak self] (_) in
                 self?.cloneCardToken(token: token, securityCode: securityCode)
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func getPayerCosts(updateCallback: (() -> Void)? = nil) {
         self.presentLoading()
-
+        
         guard let paymentMethod = self.viewModel.paymentData.getPaymentMethod() else {
             return
         }
-
+        
         let bin = self.viewModel.cardToken?.getBin()
-
+        
         self.viewModel.mercadoPagoServicesAdapter.getInstallments(bin: bin, amount: self.viewModel.getFinalAmount(), issuer: self.viewModel.paymentData.getIssuer(), paymentMethodId: paymentMethod._id, callback: { [weak self] (installments) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.payerCosts = installments[0].payerCosts
-
+            
             let defaultPayerCost = strongSelf.viewModel.checkoutPreference.paymentPreference?.autoSelectPayerCost(installments[0].payerCosts)
             if let defaultPC = defaultPayerCost {
                 strongSelf.viewModel.updateCheckoutModel(payerCost: defaultPC)
             }
-
+            
             if let updateCallback = updateCallback {
                 updateCallback()
                 strongSelf.dismissLoading()
@@ -319,105 +325,109 @@ extension MercadoPagoCheckout {
                 strongSelf.dismissLoading()
                 strongSelf.executeNextStep()
             }
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.GET_INSTALLMENTS.rawValue), errorCallback: { [weak self] (_) in
                 self?.getPayerCosts()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func createPayment() {
         self.presentLoading()
-
-        var paymentBody: [String:Any]
-        if MercadoPagoCheckoutViewModel.servicePreference.isUsingDeafaultPaymentSettings() {
-            let mpPayment = MercadoPagoCheckoutViewModel.createMPPayment(preferenceId: self.viewModel.checkoutPreference._id, paymentData: self.viewModel.paymentData, binaryMode: self.viewModel.binaryMode)
-            paymentBody = mpPayment.toJSON()
-        } else {
-            paymentBody = self.viewModel.paymentData.toJSON()
-        }
-
-        var createPaymentQuery: [String:String]? = [:]
-        if let paymentAdditionalInfo = MercadoPagoCheckoutViewModel.servicePreference.getPaymentAddionalInfo() as? [String:String] {
-            createPaymentQuery = paymentAdditionalInfo
-        } else {
-            createPaymentQuery = nil
-        }
-
-        self.viewModel.mercadoPagoServicesAdapter.createPayment(url: MercadoPagoCheckoutViewModel.servicePreference.getPaymentURL(), uri: MercadoPagoCheckoutViewModel.servicePreference.getPaymentURI(), paymentData: paymentBody as NSDictionary, query: createPaymentQuery, callback: { [weak self] (payment) in
-
-            guard let strongSelf = self else {
-                return
-            }
-
-            strongSelf.viewModel.updateCheckoutModel(payment: payment)
-            strongSelf.dismissLoading()
-            strongSelf.executeNextStep()
-
-        }) { [weak self] (error) in
-
-            guard let strongSelf = self else {
-                return
-            }
-
-            strongSelf.dismissLoading()
-            let mpError = MPSDKError.convertFrom(error, requestOrigin: ApiUtil.RequestOrigin.CREATE_PAYMENT.rawValue)
-
-            if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_PAYMENT_WITH_ESC.rawValue) {
-                strongSelf.viewModel.prepareForInvalidPaymentWithESC()
-            } else if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_PAYMENT_IDENTIFICATION_NUMBER.rawValue) {
-                self?.viewModel.paymentData.clearCollectedData()
-                let mpInvalidIdentificationError = MPSDKError.init(message: "Algo salió mal… ".localized, errorDetail: "El número de identificación es inválido".localized, retry: true)
-                strongSelf.viewModel.errorInputs(error: mpInvalidIdentificationError, errorCallback: { [weak self] (_) in
-                    self?.viewModel.resetInformation()
-                    self?.viewModel.resetGroupSelection()
-                    self?.executeNextStep()
-                })
-            } else {
-                strongSelf.viewModel.errorInputs(error: mpError, errorCallback: { [weak self] (_) in
-                    self?.createPayment()
-                })
-            }
-            strongSelf.executeNextStep()
-
-        }
+        self.getIssuers(updateCallback: { // Esto lo agregué porque en la llamada getPayerCosts daba error por no tener issuer
+            self.getPayerCosts(updateCallback: { // Sin esto no había forma de obtener el transactionAmount y otros datos necesarios
+                var paymentBody: [String:Any]
+                if MercadoPagoCheckoutViewModel.servicePreference.isUsingDeafaultPaymentSettings() {
+                    let mpPayment = MercadoPagoCheckoutViewModel.createMPPayment(preferenceId: self.viewModel.checkoutPreference._id, paymentData: self.viewModel.paymentData, binaryMode: self.viewModel.binaryMode)
+                    paymentBody = mpPayment.toJSON()
+                } else {
+                    paymentBody = self.viewModel.paymentData.toCustomJSON()
+                }
+                
+                // Ahora el additionalInfo se agrega en el body, tal como lo hace el SDK de Android
+                if let paymentAdditionalInfo = MercadoPagoCheckoutViewModel.servicePreference.getPaymentAddionalInfo() as? [String:String] {
+                    for (k, v) in paymentAdditionalInfo {
+                        paymentBody[k] = v
+                    }
+                }
+                
+                // query ahora es nil, ya que no paso ningún dato utilizando ese método
+                self.viewModel.mercadoPagoServicesAdapter.createPayment(url: MercadoPagoCheckoutViewModel.servicePreference.getPaymentURL(), uri: MercadoPagoCheckoutViewModel.servicePreference.getPaymentURI(), paymentData: paymentBody as NSDictionary, query: nil, callback: { [weak self] (payment) in
+                    
+                    guard let strongSelf = self else {
+                        return
+                    }
+                    
+                    strongSelf.viewModel.updateCheckoutModel(payment: payment)
+                    strongSelf.dismissLoading()
+                    strongSelf.executeNextStep()
+                    
+                }) { [weak self] (error) in
+                    
+                    guard let strongSelf = self else {
+                        return
+                    }
+                    
+                    strongSelf.dismissLoading()
+                    let mpError = MPSDKError.convertFrom(error, requestOrigin: ApiUtil.RequestOrigin.CREATE_PAYMENT.rawValue)
+                    
+                    if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_PAYMENT_WITH_ESC.rawValue) {
+                        strongSelf.viewModel.prepareForInvalidPaymentWithESC()
+                    } else if let apiException = mpError.apiException, apiException.containsCause(code: ApiUtil.ErrorCauseCodes.INVALID_PAYMENT_IDENTIFICATION_NUMBER.rawValue) {
+                        self?.viewModel.paymentData.clearCollectedData()
+                        let mpInvalidIdentificationError = MPSDKError.init(message: "Algo salió mal… ".localized, errorDetail: "El número de identificación es inválido".localized, retry: true)
+                        strongSelf.viewModel.errorInputs(error: mpInvalidIdentificationError, errorCallback: { [weak self] (_) in
+                            self?.viewModel.resetInformation()
+                            self?.viewModel.resetGroupSelection()
+                            self?.executeNextStep()
+                        })
+                    } else {
+                        strongSelf.viewModel.errorInputs(error: mpError, errorCallback: { [weak self] (_) in
+                            self?.createPayment()
+                        })
+                    }
+                    strongSelf.executeNextStep()
+                    
+                }
+            })
+        })
     }
-
+    
     func getInstructions() {
         self.presentLoading()
-
+        
         guard let paymentResult = self.viewModel.paymentResult else {
             fatalError("Get Instructions - Payment Result does no exist")
         }
-
+        
         guard let paymentId = paymentResult._id else {
-           fatalError("Get Instructions - Payment Id does no exist")
+            fatalError("Get Instructions - Payment Id does no exist")
         }
-
+        
         guard let paymentTypeId = paymentResult.paymentData?.getPaymentMethod()?.paymentTypeId else {
             fatalError("Get Instructions - Payment Method Type Id does no exist")
         }
-
+        
         self.viewModel.mercadoPagoServicesAdapter.getInstructions(paymentId: paymentId, paymentTypeId: paymentTypeId, callback: { [weak self] (instructionsInfo) in
-
+            
             guard let strongSelf = self else {
                 return
             }
             strongSelf.viewModel.instructionsInfo = instructionsInfo
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
@@ -426,34 +436,34 @@ extension MercadoPagoCheckout {
                 self?.getInstructions()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
-
+    
     func getIdentificationTypes() {
         self.presentLoading()
         self.viewModel.mercadoPagoServicesAdapter.getIdentificationTypes(callback: { [weak self] (identificationTypes) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.viewModel.updateCheckoutModel(identificationTypes: identificationTypes)
             strongSelf.dismissLoading()
             strongSelf.executeNextStep()
-
+            
         }) { [weak self] (error) in
-
+            
             guard let strongSelf = self else {
                 return
             }
-
+            
             strongSelf.dismissLoading()
             strongSelf.viewModel.errorInputs(error: MPSDKError.convertFrom(error, requestOrigin:  ApiUtil.RequestOrigin.GET_IDENTIFICATION_TYPES.rawValue), errorCallback: { [weak self] (_) in
                 self?.getIdentificationTypes()
             })
             strongSelf.executeNextStep()
-
+            
         }
     }
 }
diff --git a/MercadoPagoSDK/MercadoPagoSDK/PaymentData.swift b/MercadoPagoSDK/MercadoPagoSDK/PaymentData.swift
index 3974c90a..2d636ad7 100644
--- a/MercadoPagoSDK/MercadoPagoSDK/PaymentData.swift
+++ b/MercadoPagoSDK/MercadoPagoSDK/PaymentData.swift
@@ -9,7 +9,7 @@
 import UIKit
 
 public class PaymentData: NSObject {
-
+    
     public var paymentMethod: PaymentMethod?
     public var issuer: Issuer?
     public var payerCost: PayerCost?
@@ -17,7 +17,7 @@ public class PaymentData: NSObject {
     public var payer = Payer()
     public var transactionDetails: TransactionDetails?
     public var discount: DiscountCoupon?
-
+    
     func clearCollectedData() {
         self.paymentMethod = nil
         self.issuer = nil
@@ -27,60 +27,60 @@ public class PaymentData: NSObject {
         self.transactionDetails = nil
         // No borrar el descuento
     }
-
+    
     func isComplete() -> Bool {
-
+        
         guard let paymentMethod = self.paymentMethod else {
             return false
         }
-
+        
         if paymentMethod.isEntityTypeRequired && payer.entityType == nil {
             return false
         }
-
+        
         if paymentMethod.isPayerInfoRequired && payer.identification == nil {
             return false
         }
-
+        
         if !Array.isNullOrEmpty(paymentMethod.financialInstitutions) && transactionDetails?.financialInstitution == nil {
             return false
         }
-
+        
         if paymentMethod._id == PaymentTypeId.ACCOUNT_MONEY.rawValue || !paymentMethod.isOnlinePaymentMethod {
             return true
         }
-
+        
         if paymentMethod.isCard && (token == nil || payerCost == nil) {
-
+            
             if (paymentMethod.paymentTypeId == PaymentTypeId.DEBIT_CARD.rawValue || paymentMethod.paymentTypeId == PaymentTypeId.PREPAID_CARD.rawValue ) && token != nil {
                 return true
             }
             return false
         }
-
+        
         return true
     }
-
+    
     func hasToken() -> Bool {
         return token != nil
     }
-
+    
     func hasIssuer() -> Bool {
         return issuer != nil
     }
-
+    
     func hasPayerCost() -> Bool {
         return payerCost != nil
     }
-
+    
     func hasPaymentMethod() -> Bool {
         return paymentMethod != nil
     }
-
+    
     func hasCustomerPaymentOption() -> Bool {
         return hasPaymentMethod() && (self.paymentMethod!.isAccountMoney || (hasToken() && !String.isNullOrEmpty(self.token!.cardId)))
     }
-
+    
     public func updatePaymentDataWith(paymentMethod: PaymentMethod?) {
         guard let paymentMethod = paymentMethod else {
             return
@@ -90,21 +90,21 @@ public class PaymentData: NSObject {
         cleanPayerCost()
         self.paymentMethod = paymentMethod
     }
-
+    
     public func updatePaymentDataWith(token: Token?) {
         guard let token = token else {
             return
         }
         self.token = token
     }
-
+    
     public func updatePaymentDataWith(payerCost: PayerCost?) {
         guard let payerCost = payerCost else {
             return
         }
         self.payerCost = payerCost
     }
-
+    
     public func updatePaymentDataWith(issuer: Issuer?) {
         guard let issuer = issuer else {
             return
@@ -112,75 +112,108 @@ public class PaymentData: NSObject {
         cleanPayerCost()
         self.issuer = issuer
     }
-
+    
     public func updatePaymentDataWith(payer: Payer?) {
         guard let payer = payer else {
             return
         }
         self.payer = payer
     }
-
+    
     public func cleanToken() {
         self.token = nil
     }
-
+    
     public func cleanPayerCost() {
         self.payerCost = nil
     }
-
+    
     func cleanIssuer() {
         self.issuer = nil
     }
-
+    
     func cleanPaymentMethod() {
         self.paymentMethod = nil
     }
-
-   public func getToken() -> Token? {
+    
+    public func getToken() -> Token? {
         return token
     }
-
+    
     public func getPayerCost() -> PayerCost? {
         return payerCost
     }
-
+    
     public func getIssuer() -> Issuer? {
         return issuer
     }
-
+    
     public func getPaymentMethod() -> PaymentMethod? {
         return paymentMethod
     }
-
+    
     func toJSONString() -> String {
         return JSONHandler.jsonCoding(toJSON())
     }
-
+    
     func toJSON() -> [String:Any] {
-       var obj: [String:Any] = [
+        var obj: [String:Any] = [
             "payer": payer.toJSON()
-       ]
+        ]
         if let paymentMethod = self.paymentMethod {
             obj["payment_method"] = paymentMethod.toJSON()
         }
-
+        
         if let payerCost = self.payerCost {
             obj["payer_cost"] = payerCost.toJSON()
         }
-
+        
         if let token = self.token {
             obj["card_token"] = token.toJSON()
         }
-
+        
         if let issuer = self.issuer {
             obj["issuer"] = issuer.toJSON()
         }
-
+        
         if let discount = self.discount {
             obj["discount"] = discount.toJSON()
         }
-
+        
         return obj
     }
-
+    
+    // Agrego este método para no modificar el otro
+    // Le agrego algunos tags y modifico otros para que sea "compliant" con el request que hace Android
+    func toCustomJSON() -> [String:Any] {
+        var obj: [String:Any] = [
+            "payer": payer.toJSON()
+        ]
+        if let paymentMethod = self.paymentMethod {
+            obj["payment_method"] = paymentMethod.toJSON()
+            obj["payment_method_id"] = paymentMethod._id
+        }
+        
+        if let payerCost = self.payerCost {
+            obj["transaction_amount"] = payerCost.totalAmount
+            obj["installments"] = payerCost.installments
+        }
+        
+        if let token = self.token {
+            obj["card_token"] = token._id
+        }
+        
+        if let issuer = self.issuer {
+            obj["issuer"] = issuer.toJSON()
+            obj["card_issuer_id"] = issuer._id
+        }
+        
+        if let discount = self.discount {
+            obj["discount"] = discount.toJSON()
+            obj["campaign_id"] = discount._id
+        }
+        
+        return obj
+    }
+    
 }
