# MD for: https://www.mercadopago.com.br/developers/pt/docs/apple-pay/attached-model-integration/mobile-integration.md \# Mercado Pago integration for mobile applications This model lets you offer Apple Pay in your mobile application without managing payment certificates or decrypting tokens on your server. You can integrate \*\*via SDK\*\*, using the Mercado Pago native SDK for iOS in your app to display the Apple Pay button, or \*\*via API\*\*, implementing the flow in your \_backend\_ and sending from the app the data that Apple returns. In both cases, Mercado Pago handles validation with Apple and returns a token ready to create the payment. sequenceDiagram participant C as Buyer participant A as App (iOS) participant Apple as Apple participant MP as Mercado Pago A->>A: Check availability (Apple Pay + cards) C->>A: Tap Apple Pay button A->>Apple: Payment request (Touch ID/Face ID) Apple-->>A: Apple payment token A->>MP: Create token (SDK or API) MP-->>A: Mercado Pago token A->>A: Send token to backend A->>MP: Create payment (token + data) MP-->>A: Payment response :::::TabsComponent ::::TabComponent{title="Via SDK"} In this integration you use the Mercado Pago native SDK for iOS in your app. The SDK converts the Apple token into a Mercado Pago card token; your \_backend\_ receives that token and creates the payment. Follow the steps below to integrate. :::AccordionComponent{title="Initialize the SDK" pill="1"} Having obtained and configured the \[required Apple Developer certificates\](https://www.mercadopago.com.br/developers/en/docs/apple-pay/obtain-apple-developer-certificates), use the Mercado Pago native SDK to integrate payment methods in iOS applications. Below we show how to install and initialize the SDK. ### Install the SDK Follow the step-by-step to install the SDK in your Swift project. 1\. In Swift Package Manager, click \*\*File > Add Package Dependencies\*\*. 2\. Paste the repository URL: \`https://github.com/mercadopago/sdk-ios\`. 3\. Select the desired SDK version. 4\. Click \*\*Add Package\*\* to complete the installation. ### Add dependencies Import the SDK dependencies in your project by running the following code: \`\`\` import CoreMethods \`\`\` ### Initialize the SDK After installing the SDK and adding the dependencies to your project, initialize the SDK at the start of the application lifecycle. This ensures that all essential configuration is defined before any payment operation. > WARNING > > The SDK must be initialized only once when opening the application. To ensure correct operation, make a call to \`initialize()\` before using any other SDK functionality. To initialize the Mercado Pago library, you need to use your :toolTipComponent\[credentials\]{link="/developers/en/docs/credentials" linkText="Credentials" content="Unique access keys we use to identify an integration in your account, linked to your application. For more information, see the link below."}, linked to the :toolTipComponent\[application\]{link="/developers/en/docs/application-details" linkText="Application details" content="Entity registered in Mercado Pago that acts as an identifier to manage your integrations. For more information, see the link below."} you created. At this stage, you must use your :toolTipComponent\[test Public Key\]{content="Public key of the application created in Mercado Pago, used in the frontend. You can access it in \*Your integrations > Application details > Test > Test credentials\*."}. !\[How to access credentials through Your Integrations\](https://www.mercadopago.com.br/images/snippets/credentials-prod-panel-pt.jpg) > NOTE > > If you are developing for someone else, you can access the credentials of applications you do not manage. See \[Share credentials\](https://www.mercadopago.com.br/developers/en/docs/checkout-api-payments/resources/credentials#bookmark\_compartilhar\_credenciais) for more information. * [swiftui ](#editor%5F2) * [uikit ](#editor%5F1) uikit swiftui ``` import UIKit import CoreMethods @main class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let configuration = MercadoPagoSDK.Configuration( publicKey: "YOUR-PUBLIC-KEY", country: // Enter the country of your public key ) MercadoPagoSDK.shared.initialize(configuration) return true } } ``` Copiar ``` import SwiftUI import CoreMethods @main struct YourApp: App { init() { let configuration = MercadoPagoSDK.Configuration( publicKey: "", country: "", locale: "en-US" ) MercadoPagoSDK.shared.initialize(configuration) } var body: some Scene { WindowGroup { ContentView() } } } ``` Copiar The initialization parameters are listed in the table below. | Parameter | Type | Description | Required | | --- | --- | --- | --- | | \`public\_key\` | String | :toolTipComponent\[test Public Key\]{content="Public key of the application created in Mercado Pago, used in the frontend. You can access it in \*Your integrations > Application details > Test > Test credentials\*."}: used in the frontend to access information. | Required | | \`locale\` | String | \_Locale\_ identifier (language and country). By default, the system \_locale\_ is used. | Optional | | \`country\` | \[Country\](https://mercadopago.github.io/sdk-ios/0.1.0/documentation/coremethods/mercadopagosdk/country) | \`Enum\` that identifies the country in which \_Core Methods\_ will be processed. Use the country code corresponding to your :toolTipComponent\[test Public Key\]{content="Public key of the application created in Mercado Pago. You can access it in \*Your integrations > Application details > Test > Test credentials\*."}. See the \[documentation\](https://mercadopago.github.io/sdk-ios/0.1.0/documentation/coremethods/mercadopagosdk/country/) to verify the code for your country. | Required | ::: :::AccordionComponent{title="Configure Apple Pay in the project" pill="2"} To enable Apple Pay in your app, configure the required capabilities in :toolTipComponent\[Xcode\]{content="Apple's integrated development environment (IDE) for creating applications for iOS, iPadOS, macOS, watchOS and tvOS."}: 1\. In Xcode, select the project file in the Project Navigator and the app's main Target. 2\. Go to the \*\*Signing & Capabilities\*\* tab and click \*\*+ Capability\*\*. 3\. In the search box, type "Apple Pay" and add the capability. 4\. In the \*\*Apple Pay\*\* section, select the Merchant ID you created in the Apple Developer Portal. If it does not appear, refresh the list using the circular arrow icon. !\[link-merchant-id-en\](https://www.mercadopago.com.br/images/apple-pay/xcode-apple-pay-config.png) ::: :::AccordionComponent{title="Check availability and display the button" pill="3"} Before displaying the Apple Pay button, you need to check that the user's device is compatible and has at least one card configured in the \*\*Wallet\*\* app. To do this, run the following code. * [swift ](#editor%5F3) swift ``` import MPApplePay import PassKit import UIKit class YourCheckoutViewController: UIViewController { let applePayButton: PKPaymentButton = PKPaymentButton(paymentButtonType: .plain, paymentButtonStyle: .black) let mpApplePay: MPApplePay = .init() override func viewDidLoad() { super.viewDidLoad() applePayButton.isHidden = !MPApplePay.canMakePayments() applePayButton.addTarget(self, action: #selector(handleApplePayButton), for: .touchUpInside) } } ``` Copiar \*\*Button customization\*\* You can change the button type and style in the \`PKPaymentButton(paymentButtonType:paymentButtonStyle:)\` initializer. For more appearance and Apple Pay interface options, see the \[official Apple documentation\](https://developer.apple.com/documentation/passkit/apple\_pay). ::: :::AccordionComponent{title="Create the payment request" pill="4"} In the method that runs when the user taps the Apple Pay button, create the payment request with the transaction data, configure the summary items, and present the :toolTipComponent\[Apple Pay sheet\]{content="Modal screen that Apple shows the buyer with the payment summary, selected card, and authorization request with Touch ID or Face ID."}. See the elements to complete in the table below. * [swift ](#editor%5F4) swift ``` @objc func handleApplePayButton() { let request = MPApplePay.paymentRequest( withMerchantIdentifier: "merchant.your-identifier", currency: "BRL" ) let item = PKPaymentSummaryItem( label: "Product name", amount: NSDecimalNumber(value: 10), type: .final ) let totalItem = PKPaymentSummaryItem( label: "YOUR STORE", amount: NSDecimalNumber(value: 10), type: .final ) request.paymentSummaryItems = [item, totalItem] let paymentController = PKPaymentAuthorizationController(paymentRequest: request) paymentController.delegate = self paymentController.present() } ``` Copiar | Element | Type | Description | Required | | --- | --- | --- | --- | | \`withMerchantIdentifier\` | String | Merchant ID you configured in the Apple Developer Portal. It must match the one in your app. | Required | | \`currency\` | String | Transaction currency code, for example \`BRL\` or \`ARS\`. | Required | | \`PKPaymentSummaryItem\` | Object | Each summary item the buyer sees: \`label\` (product or merchant name), \`amount\` (amount) and \`type\` (e.g. \`.final\`). | Required | | \`paymentSummaryItems\` | Array | List of summary items. The last one must be the purchase total; its \`label\` is usually your store name. | Required | | \`PKPaymentAuthorizationController\` | Object | Apple controller that displays the payment sheet. It is created with the request, the delegate is set to receive the result, and it is presented with \`present()\`. | Required | ::: :::AccordionComponent{title="Process the payment" pill="5"} Implement the \`PKPaymentAuthorizationControllerDelegate\` method to receive the Apple \_token\_, convert it to a \`card token\` with the SDK, and send it to your \_backend\_. * [swift ](#editor%5F5) swift ``` extension YourCheckoutViewController: PKPaymentAuthorizationControllerDelegate { func paymentAuthorizationController( _ controller: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void ) { Task { do { let response = try await mpApplePay.createToken( payment.token ) // send the token to your backend to process the payment await sendYourBackend(response.token) completion( PKPaymentAuthorizationResult( status: .success, errors: nil ) ) } catch { completion( PKPaymentAuthorizationResult( status: .failure, errors: [error] ) ) } } } func paymentAuthorizationControllerDidFinish( _ controller: PKPaymentAuthorizationController ) { controller.dismiss() } } ``` Copiar | Element | Type | Description | Required | | --- | --- | --- | --- | | \`paymentAuthorizationController(\_:didAuthorizePayment:handler:)\` | Method | Delegate method that Apple calls when the buyer authorizes the payment. You receive \`controller\`, \`payment\` (with the Apple token) and \`completion\` to report the result. | Required | | \`payment.token\` | Object | Payment token that Apple provides in \`payment\`. It is sent to \`mpApplePay.createToken(payment.token)\`. | Required | | \`mpApplePay.createToken(payment.token)\` | Method | Converts the Apple token into a Mercado Pago card token. Returns an object with \`response.token\`. | Required | | \`response.token\` | String | Mercado Pago card token. Send it to your \_backend\_ with \`sendToBackend(response.token)\` to create the payment. | Required | | \`completion(PKPaymentAuthorizationResult(status:errors:))\` | Callback | Completion parameter that Apple gives you in the delegate: it is the callback you must call with \`.success\` and \`errors: nil\` on success, or with \`.failure\` and \`errors: \[error\]\` on error. This allows Apple to close the sheet with the correct status. | Required | | \`paymentAuthorizationControllerDidFinish(\_:)\` | Method | Method that Apple calls when the sheet is closed. Dismisses the controller with \`controller.dismiss()\`. | Required | ::: :::AccordionComponent{title="Test the integration" pill="6"} You can simulate different payment outcomes in development by passing the \`status\` parameter when creating the token: * [swift ](#editor%5F6) swift ``` let response = try await mpApplePay.createToken( payment.token, status: "APRO" ) ``` Copiar | \`status\` value | Payment scenario | | --- | --- | | \`APRO\` | Payment approved | | \`OTHE\` | Rejected due to general error | | \`CONT\` | Pending payment | | \`CALL\` | Rejected with validation to authorize | | \`FUND\` | Rejected due to insufficient funds | | \`SECU\` | Rejected due to invalid security code | | \`EXPI\` | Rejected due to expiration date | | \`FORM\` | Rejected due to form error | | \`CARD\` | Rejected due to missing \`card\_number\` | | \`INST\` | Rejected due to invalid installments | | \`DUPL\` | Rejected due to duplicate payment | | \`LOCK\` | Rejected due to disabled card | | \`CTNA\` | Rejected due to card type not allowed | | \`ATTE\` | Rejected due to PIN attempts exceeded | | \`BLAC\` | Rejected due to blacklist | | \`UNSU\` | Not supported | | \`TEST\` | Used to apply amount rule | ::: :::: ::::TabComponent{title="Via API"} In the API integration you implement the Apple Pay flow from your \_backend\_ using Mercado Pago APIs. The app displays Apple Pay with Apple's native APIs and, when the buyer authorizes the payment, sends the data returned by Apple to your \_backend\_; the \_backend\_ validates the session with Mercado Pago, obtains the token and creates the payment. Follow the steps below. :::AccordionComponent{title="Validate the session for the tokenization flow" pill="1"} Having obtained and configured the \[required Apple Developer certificates\](https://www.mercadopago.com.br/developers/en/docs/apple-pay/obtain-apple-developer-certificates), send a \*\*POST\*\* with your :toolTipComponent\[test Public Key\]{content="Public key used in the frontend to access information and encrypt data. You can access it through \*Your integrations > Integration data > Tests > Test credentials\*."} to the endpoint :TagComponent{tag="API" text="/applepay/v1/session" href="https://api.mercadopago.com/applepay/v1/session"} with the request headers and body shown in the example. \`\`\`curl curl --location 'https://api.mercadopago.com/applepay/v1/session' \\ --header 'X-Product-ID: YOUR\_PRODUCT\_ID' \\ --header 'Content-Type: application/json' \\ --header 'X-Public-key: YOUR\_PUBLIC\_KEY' \\ --data '{ "id": "CERTIFICATE\_ID\_MERCHANT", "merchantIdentifier": "merchant.your-identifier", "domainName": "your-domain.com", "displayName": "My store", "initiative": "web", "initiativeContext": "your-domain.com", "validationURL": "https://apple-pay-gateway.apple.com/paymentservices/startSession" }' \`\`\` | Element | Type | Description | Required | | --- | --- | --- | --- | | \`X-Product-ID\` | Header | Product identifier. | Required | | \`X-Public-key\` | Header | Header with your :toolTipComponent\[test Public Key\]{content="Public key of the application created in Mercado Pago. You can access it in \*Your integrations > Application details > Test > Test credentials\*."}. | Required | | \`id\` | String | Certificate ID of the \*merchant\* type certificate obtained in the previous steps. | Required | | \`merchantIdentifier\` | String | Merchant ID configured in Apple. | Required | | \`domainName\` | String | Domain associated with your app or merchant where Apple Pay is used. | Required | | \`displayName\` | String | Name the user sees in the payment flow. | Required | | \`initiative\` | String | Fixed value \`web\`. | Required | | \`initiativeContext\` | String | Must match \`domainName\`. | Required | | \`validationURL\` | String | URL that Apple sends to the app when starting the flow; send it here unmodified. | Required | The API returns an object that includes \`merchantSessionIdentifier\` and other data that your app will use to complete the flow with Apple. ::: :::AccordionComponent{title="Payment tokenization" pill="2"} When the buyer authorizes the payment in the app, Apple returns the payment data. The app sends that data to your \_backend\_; from the \_backend\_, send a \*\*POST\*\* with your :toolTipComponent\[test Public Key\]{content="Public key used in the frontend to access information and encrypt data. You can access it through \*Your integrations > Integration data > Tests > Test credentials\*."} to the endpoint :TagComponent{tag="API" text="/platforms/pci/applepay/v1/tokenize" href="https://api.mercadopago.com/platforms/pci/applepay/v1/tokenize"} to obtain a card token from Mercado Pago. Use the request headers and body from the example below. \`\`\`curl curl --location 'https://api.mercadopago.com/platforms/pci/applepay/v1/tokenize' \\ --header 'X-Product-ID: YOUR\_PRODUCT\_ID' \\ --header 'Content-Type: application/json' \\ --header 'X-Public-key: YOUR\_PUBLIC\_KEY' \\ --data '{ "payment\_method": { "type": "applepay", "payment\_data": "APPLE\_PAYMENT\_DATA\_IN\_BASE64" }, "transaction\_identifier": "APPLE\_TRANSACTION\_IDENTIFIER", "device": { "meli": { "session\_id": "DEVICE\_SESSION\_ID" } } }' \`\`\` | Element | Type | Description | Required | | --- | --- | --- | --- | | \`X-Product-ID\` | Header | Product identifier. | Required | | \`X-Public-key\` | Header | Header with your :toolTipComponent\[test Public Key\]{content="Public key of the application created in Mercado Pago, used in the frontend. You can access it in \*Your integrations > Application details > Test > Test credentials\*."}. | Required | | \`payment\_method.type\` | String | Fixed value \`applepay\`. | Required | | \`payment\_method.payment\_data\` | String | Payment data that Apple sends to the app, in \_Base64\_ format. When the user authorizes the payment on an Apple device, the browser triggers the \`onpaymentauthorized\` event and, from that point on, within \`payment.token.paymentData\` there will be a \`JavaScript\` object containing the card data encrypted by Apple. The returned object must be converted to a \`JSON\` string and then encoded in \_Base64\_. | Required | | \`transaction\_identifier\` | String | Transaction identifier that Apple sends to the app. It is a unique hexadecimal string generated by Apple for each transaction. | Required | | \`device.meli.session\_id\` | String | Device session identifier. It must be initialized on the page before clicking the Apple Pay button. The value is available in the global variable \`window.MP\_DEVICE\_SESSION\_ID\` and comes from Mercado Pago’s device fingerprint SDK (Armor). | Optional | The API returns an object with \`id\` (card token) and \`bin\`. Use that \`id\` as \`token\` when creating the payment. ::: :::AccordionComponent{title="Create the payment" pill="3"} Create the payment by sending a \*\*POST\*\* with your :toolTipComponent\[test Access Token\]{content="Private key of the application created in Mercado Pago, that must be used in the backend. You can access it through \*Your integrations > Integration data > Tests > Test credentials\*."} to :TagComponent{tag="API" text="/v1/payments" href="/developers/en/reference/payments/\_payments/post"} with your :toolTipComponent\[test Access Token\]{content="Private key of the application created in Mercado Pago, used in the backend. You can access it in \*Your integrations > Application details > Test > Test credentials\*."} and the values described in the table below. \`\`\`curl curl --location 'https://api.mercadopago.com/v1/payments' \\ --header 'Content-Type: application/json' \\ --header 'Authorization: Bearer YOUR\_ACCESS\_TOKEN' \\ --header 'X-Idempotency-Key: SOME\_UNIQUE\_VALUE' \\ --data '{ "token": "ID\_RETURNED\_BY\_TOKENIZATION", "payment\_method\_id": "visa", "transaction\_amount": 100, "installments": 1, "description": "Payment description", "payer": { "email": "buyer@email.com", "identification": { "type": "CPF", "number": "12345678909" } } }' \`\`\` | Element | Type | Description | Required | | --- | --- | --- | --- | | \`Authorization\` | Header | Header with your :toolTipComponent\[test Access Token\]{content="Private key of the application created in Mercado Pago, used in the backend. You can access it in \*Your integrations > Application details > Test > Test credentials\*."}. | Required | | \`X-Idempotency-Key\` | Header | Unique value per request (for example, UUID v4) to avoid duplicate payments. | Required | | \`token\` | String | \`id\` value returned by tokenization in the previous step. | Required | | \`payment\_method\_id\` | String | Payment method identifier: \`visa\` or \`master\`. | Required | | \`transaction\_amount\` | Number | Transaction amount. | Required | | \`installments\` | Integer | Number of installments. | Required | | \`payer\` | Object | Buyer data (email, identification, etc.). | Required | | \`payer.email\` | String | Buyer email. | Required | | \`payer.identification\` | Object | Buyer identification data. | Required | | \`payer.identification.type\` | String | Document type (for example, \`CPF\`). | Required | | \`payer.identification.number\` | String | Buyer document number. | Required | | \`description\` | String | Payment description. | Required | | \`issuer\_id\` | String | Card issuer ID. Optional. | Optional | See the \[API Reference\](https://www.mercadopago.com.br/developers/en/reference/payments/\_payments/post) for all available fields. ::: :::: ::::: > NOTE > > If you encounter an error in your Apple Pay integration, see \[Frequent errors\](https://www.mercadopago.com.br/developers/en/docs/apple-pay/additional-content/frequent-errors).