sorokin0andrey / react-native-apay

React Native bridge for Apple Pay
55 stars 30 forks source link

Expose `merchantCapabilities` to JavaScript #41

Open rakeshta opened 4 months ago

rakeshta commented 4 months ago

Hi! 👋

Firstly, thanks for your work on this project! 🙂

We had a need in our project to restrict Apple Pay to allow only Debit Cards. So I made a patch to the package to expose the "merchantCapabilities" property to JavaScript / TypeScript.

This patch was generated using patch-package on react-native-apay@1.3.1 for the project I'm working on.

Here is the diff:

diff --git a/node_modules/react-native-apay/index.d.ts b/node_modules/react-native-apay/index.d.ts
index a49977e..d33e575 100644
--- a/node_modules/react-native-apay/index.d.ts
+++ b/node_modules/react-native-apay/index.d.ts
@@ -1,5 +1,9 @@
 export type APayAllowedCardNetworkType = "amex" | "mastercard"| "visa" | "privatelabel" | "chinaunionpay" | "interac" | "jcb" | "suica" | "cartebancaires" | "idcredit" | "quicpay" | "maestro"

+/** Capabilities for processing payment
+ *  @see {@link https://developer.apple.com/documentation/passkit_apple_pay_and_wallet/pkmerchantcapability} */
+export type APayMerchantCapability = 'InstantFundsOut' | '3DS' | 'EMV' | 'Credit' | 'Debit';
+
 export type APayPaymentStatusType = number

 export interface APayPaymentSummaryItemType {
@@ -9,6 +13,18 @@ export interface APayPaymentSummaryItemType {

 export interface APayRequestDataType {
   merchantIdentifier: string
+  /**
+   * The `3DS` and `EMV` values of {@link APayMerchantCapability} specify the supported cryptographic payment protocols. At least
+   * one of these two values is required.
+   *
+   * Check with your payment processors about the cryptographic payment protocols they support. As a general rule,
+   * if you want to support China UnionPay cards, you use `EMV`. To support cards from other networks—like
+   * American Express, Visa, or Mastercard—use `3DS`.
+   *
+   * To filter the types of cards to make available for the transaction, pass the `Credit` and `Debit` values.
+   * If neither is passed, all card types will be available.
+   */
+  merchantCapabilities: APayMerchantCapability[];
   supportedNetworks: APayAllowedCardNetworkType[]
   countryCode: string
   currencyCode: string
diff --git a/node_modules/react-native-apay/ios/RNApplePay.m b/node_modules/react-native-apay/ios/RNApplePay.m
index c6cba6c..cc27110 100644
--- a/node_modules/react-native-apay/ios/RNApplePay.m
+++ b/node_modules/react-native-apay/ios/RNApplePay.m
@@ -27,7 +27,7 @@ - (NSDictionary *)constantsToExport

 RCT_EXPORT_METHOD(requestPayment:(NSDictionary *)props promiseWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
     PKPaymentRequest *paymentRequest = [[PKPaymentRequest alloc] init];
-    paymentRequest.merchantCapabilities = PKMerchantCapability3DS;
+    paymentRequest.merchantCapabilities = [self getMerchantCapabilities:props];
     paymentRequest.merchantIdentifier = props[@"merchantIdentifier"];
     paymentRequest.countryCode = props[@"countryCode"];
     paymentRequest.currencyCode = props[@"currencyCode"];
@@ -103,6 +103,32 @@ - (NSArray *_Nonnull)getSupportedNetworks:(NSDictionary *_Nonnull)props
     return supportedNetworks;
 }

+- (PKMerchantCapability)getMerchantCapabilities:(NSDictionary *_Nonnull)props {
+    NSArray<NSString *> *merchantCapabilities = props[@"merchantCapabilities"];
+    
+    PKMerchantCapability mask = 0;
+    
+    if (@available(iOS 17.0, *)) {
+        if ([merchantCapabilities containsObject:@"InstantFundsOut"]) {
+            mask |= PKMerchantCapabilityInstantFundsOut;
+        }
+    }
+    if ([merchantCapabilities containsObject:@"3DS"]) {
+        mask |= PKMerchantCapability3DS;
+    }
+    if ([merchantCapabilities containsObject:@"EMV"]) {
+        mask |= PKMerchantCapabilityEMV;
+    }
+    if ([merchantCapabilities containsObject:@"Credit"]) {
+        mask |= PKMerchantCapabilityCredit;
+    }
+    if ([merchantCapabilities containsObject:@"Debit"]) {
+        mask |= PKMerchantCapabilityDebit;
+    }
+
+    return  mask;
+}
+
 - (NSArray<PKPaymentSummaryItem *> *_Nonnull)getPaymentSummaryItems:(NSDictionary *_Nonnull)props
 {
     NSMutableArray <PKPaymentSummaryItem *> * paymentSummaryItems = [NSMutableArray array];

This issue body was partially generated by patch-package.