Skip to main content
Available in🇮🇳 India
Use Razorpay Apple Pay to add Apple Pay to your React Native app. Razorpay handles payment processing while you build your own UI around the Apple Pay button.
SDK VersionThe Apple Pay feature is available in react-native-customui version 2.3.0 and later. Apple Pay runs on iOS only.

Prerequisites

iOS OnlyApple Pay is available on iOS only. On Android, canMakePayment() resolves false, so hide the Apple Pay button there. Never call open() with app.apple_pay on Android.

One-Time Setup (Before Code)

Complete this setup once before writing any integration code.
  1. Create Apple Pay Merchant ID: In the Apple Developer Portal, go to Identifiers → + → Merchant IDs. Use the format merchant.com.yourcompany.app and register.
  2. Share Merchant ID with Razorpay: Send your Merchant ID to your Razorpay point of contact. The team will share a CSR file with you.
  3. Generate Certificate on Apple: In the Apple Developer Portal, open your Merchant ID → Create Certificate under Apple Pay Payment Processing. Upload the .csr, then download the apple_pay.cer.
Watch Out!Certificates expire after 25 months. Set a reminder to renew before expiry.
  1. Share Certificate with Razorpay: Send the apple_pay.cer file back to your Razorpay point of contact for configuration.
  1. Open ios/YourApp.xcworkspace in Xcode.
  2. Select your app target → Signing & Capabilities.
  3. Click + Capability → Apple Pay.
  4. Tick the Merchant ID created above.
This generates a .entitlements file. Sample output:
Entitlements
The merchant identifier in this entitlement must be the same one you pass as app.apple_pay.merchant_identifier at runtime.

Integration Steps

Step 1: Install the SDK

Install the package from npm:
Terminal

Step 2: Add the Apple Pay Plugin Pod

The Apple Pay plugin is opt-in. Add it to your ios/Podfile, inside your app target:
Podfile
Then install the pods:
Terminal
Existing apps that already have the pod should run pod update razorpay-applepay-pod.
Declaring the plugin as a hard dependency would force the Apple Pay pod on every app using react-native-customui, so you add it explicitly only when you need Apple Pay.The SDK resolves the plugin at runtime. If the pod is absent, your app still builds and Apple Pay degrades cleanly: canMakePayment returns false and open() rejects with DEVICE_NOT_SUPPORTED.

Step 3: Initialise Once

JavaScript
Eligibility uses the key and SDK instance this creates. Calling canMakePayment() before it resolves false and logs a console warning; it does not reject. Do not await this call, as the promise returned by initRazorpay never settles.

Step 4: Check if the Customer Can Pay

Call this before showing your Apple Pay button. It checks whether the user can pay via Apple Pay with your merchant account.
JavaScript
canMakePayment returns a boolean. It is merchant-aware, not a device probe: it fetches the card networks enabled for your Razorpay account and resolves true only when Apple Pay is live for your account and the customer’s Wallet holds a card on an accepted network. It returns false on Android, and when initRazorpay has not been called. Hide the Apple Pay button when it is false.

Step 5: Create an Order on Your Server

Create a Razorpay order via the Orders API on your backend and send the order_id to your app.
Request
The response returns an order_id such as order_CuEzONfnOI86Ab. Pass this to your app. To carry your own order reference through an Apple Pay payment, set receipt and notes on the order (as shown above). See Attaching Your Own Order Reference.
Watch Out!Never embed your API secret in the mobile app. Orders must be created by your own backend. A decompiled app bundle exposes any secret it contains, and with it your merchant account.

Step 6: Load the Payment Button

Apple’s Human Interface Guidelines require the use of PKPaymentButton (or a visually compliant variant). Custom buttons will lead to App Store rejection. React Native has no built-in Apple Pay button. Expose PKPaymentButton to JavaScript with a small native view module (an RCTViewManager subclass that returns a PKPaymentButton), or use a community package that does the same. Whichever you use, it must render Apple’s PKPaymentButton and call your payment handler on tap. Button constraints:
  • Use PKPaymentButton, not a generic button with an Apple Pay icon.
  • Do not place text or icons inside it.
  • Respect Apple’s minimum height requirement.
  • Use the automatic style on iOS 14+ for automatic light and dark mode adaptation.
  • Disable the button while a payment is in flight (see Step 7).
Test on a Real DeviceRun on a physical iOS device. Transactions cannot complete on the simulator. Tap your Apple Pay button, authenticate with Face ID or Touch ID, then confirm the payment record appears in the Razorpay Dashboard.

Step 7: Trigger the Payment on User Tap

This call must be made in response to a user gesture (such as a button tap). Do not call it on mount or from a timer. Use the existing Razorpay.open(options) API with an Apple Pay payload.
JavaScript
Guard Against Double TapsApple Pay will not present a second payment sheet while one is pending. If open() is called twice, both calls fail with SHEET_PRESENTATION_FAILED. Set a busy flag at the start of the tap handler, before any async work such as creating the order, and clear it only after the promise settles.

Step 8: Handle the Payment Result

open() returns a promise. It resolves with the payment payload on success and rejects with an error object on failure or cancellation.
JavaScript
Success response (promise resolves with):
Response
Failure response (promise rejects with): Customer cancels:
Response
Payment declined after it was created:
Response
err.error.code is always present. err.error.description is not: errors raised on the device carry only the code, and their message is in the top-level err.description. Read err.error.description first and fall back to err.description. metadata.payment_id is present only on PAYMENT_FAILED when a payment was created before the failure.

Step 9: Verify Payment Signature on Your Server

Always verify the signature on your server before fulfilling the order. A successful open() is not a fulfilled order. Send razorpay_payment_id, razorpay_order_id and razorpay_signature to your backend for HMAC verification.
Watch Out!Never fulfil an order based solely on the client-side result. Always verify the payment signature server-side.
See the signature verification guide for Node.js and other language samples.

Attaching Your Own Order Reference

To map payments back to your own order ID, pass notes in the Razorpay.open() options (requires razorpay-applepay-pod 1.0.1+). As an optional alternative, set the reference on the order instead. Set it at order creation (Step 5):
Order
Then read it back:

Error Codes

Apple Pay uses the same Razorpay.open() promise, the same success and error events and the same error envelope as any other payment method in this SDK. If your app already handles card payments, your existing .then() and .catch() handle Apple Pay with no changes. On failure, read the error code as a string from err.error.code in the rejected promise. The top-level err.code is a legacy number shared with other payment methods. For Apple Pay it is 0 for every failure, including cancellation, so check err.error.code === 'PAYMENT_CANCELLED' to detect a cancel.

Currency and Card Networks

American Express is accepted for INR payments only. For any other currency the SDK removes American Express from the payment sheet automatically. You do not need to do anything.

Complete Working Example

JavaScript

Frequently Asked Questions

No. The Simulator has no Secure Element, so the Apple Pay token it produces is empty and the payment fails. Razorpay test mode does not process Apple Pay tokens. Test on a physical iOS device with a real card in Wallet, using your rzp_live_* key.
The SDK separates detection from payment. Use canMakePayment to decide whether to include the Apple Pay row at all. When the user selects that row, show the Apple Pay button. When they tap it, call Razorpay.open(options) with the Apple Pay payload.
  • Merchant ID alignment: Does the Merchant ID you passed in app.apple_pay.merchant_identifier match the one in your .entitlements and the one you shared with Razorpay?
  • Certificate uploaded: Has your Razorpay point of contact confirmed that the certificate for that Merchant ID is configured?
  • Network match: Are you testing with a card whose network is enabled for your Razorpay account?
  • Backend support: Is Apple Pay enabled for your account in the Razorpay Dashboard?
  • Real device: Are you running on a physical device, not the Simulator?
If all of these are correct, take err.error.metadata.payment_id (when present) from the rejected promise and look up that payment in the Razorpay Dashboard or through the Payments API for the decline reason.
canMakePayment checks your merchant account as well as the device. It returns false when Apple Pay is not enabled for your Razorpay account, when none of the cards in Wallet are on a network enabled for your account, when the razorpay-applepay-pod is not installed, when initRazorpay has not been called, or on Android.