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.Apple Developer Portal Steps
Apple Developer Portal Steps
- Create Apple Pay Merchant ID: In the Apple Developer Portal, go to Identifiers → + → Merchant IDs. Use the format
merchant.com.yourcompany.appand register. - Share Merchant ID with Razorpay: Send your Merchant ID to your Razorpay point of contact. The team will share a CSR file with you.
- 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 theapple_pay.cer.
- Share Certificate with Razorpay: Send the
apple_pay.cerfile back to your Razorpay point of contact for configuration.
Xcode Steps
Xcode Steps
- Open
ios/YourApp.xcworkspacein Xcode. - Select your app target → Signing & Capabilities.
- Click + Capability → Apple Pay.
- Tick the Merchant ID created above.
.entitlements file. Sample output:Entitlements
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 yourios/Podfile, inside your app target:
Podfile
Terminal
pod update razorpay-applepay-pod.
Why is the plugin opt-in?
Why is the plugin opt-in?
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
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 theorder_id to your app.
Request
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.
Order Parameters
Order Parameters
Step 6: Load the Payment Button
Apple’s Human Interface Guidelines require the use ofPKPaymentButton (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
automaticstyle 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 existingRazorpay.open(options) API with an Apple Pay payload.
JavaScript
Payment Parameters
Payment Parameters
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
Response
Response
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 successfulopen() is not a fulfilled order. Send razorpay_payment_id, razorpay_order_id and razorpay_signature to your backend for HMAC verification.
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, passnotes 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
Error Codes
Apple Pay uses the sameRazorpay.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
Can I test Apple Pay on the iOS Simulator or in Razorpay test mode?
Can I test Apple Pay on the iOS Simulator or in Razorpay test mode?
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.I show payment methods in a list where each expands on selection. How does Apple Pay fit?
I show payment methods in a list where each expands on selection. How does Apple Pay fit?
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.The Apple Pay sheet appears but the transaction always fails. What should I check?
The Apple Pay sheet appears but the transaction always fails. What should I check?
- Merchant ID alignment: Does the Merchant ID you passed in
app.apple_pay.merchant_identifiermatch the one in your.entitlementsand 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?
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 returns false but the device has cards in Wallet. Why?
canMakePayment returns false but the device has cards in Wallet. Why?
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.