Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch to add newer network types and payment capabilities #42

Open
rakeshta opened this issue Sep 17, 2024 · 1 comment
Open

Patch to add newer network types and payment capabilities #42

rakeshta opened this issue Sep 17, 2024 · 1 comment

Comments

@rakeshta
Copy link

rakeshta commented Sep 17, 2024

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch [email protected] for the project I'm working on.

I've added support for all of the latest network types and payment capabilities supported by Apple Pay.

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..d4cde67 100644
--- a/node_modules/react-native-apay/index.d.ts
+++ b/node_modules/react-native-apay/index.d.ts
@@ -1,26 +1,68 @@
-export type APayAllowedCardNetworkType = "amex" | "mastercard"| "visa" | "privatelabel" | "chinaunionpay" | "interac" | "jcb" | "suica" | "cartebancaires" | "idcredit" | "quicpay" | "maestro"
+export type APayAllowedCardNetworkType =
+  | 'amex'
+  | 'bancontact'
+  | 'barcode'
+  | 'cartesbancaires'
+  | 'chinaunionpay'
+  | 'dankort'
+  | 'discover'
+  | 'eftpos'
+  | 'electron'
+  | 'elo'
+  | 'girocard'
+  | 'idcredit'
+  | 'interac'
+  | 'jcb'
+  | 'mada'
+  | 'maestro'
+  | 'mastercard'
+  | 'mir'
+  | 'nanaco'
+  | 'postfinance'
+  | 'privatelabel'
+  | 'quicpay'
+  | 'suica'
+  | 'visa'
+  | 'vpay'
+  | 'waon';
 
-export type APayPaymentStatusType = number
+/** 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 {
-  label: string
-  amount: string
+  label: string;
+  amount: string;
 }
 
 export interface APayRequestDataType {
-  merchantIdentifier: string
-  supportedNetworks: APayAllowedCardNetworkType[]
-  countryCode: string
-  currencyCode: string
-  paymentSummaryItems: APayPaymentSummaryItemType[]
+  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;
+  paymentSummaryItems: APayPaymentSummaryItemType[];
 }
 
 declare class ApplePay {
-  static SUCCESS: APayPaymentStatusType
-  static FAILURE: APayPaymentStatusType
-  static canMakePayments: boolean
-  static requestPayment: (requestData: APayRequestDataType) => Promise<string>
-  static complete: (status: APayPaymentStatusType) => Promise<void>
+  static SUCCESS: APayPaymentStatusType;
+  static FAILURE: APayPaymentStatusType;
+  static canMakePayments: boolean;
+  static requestPayment: (requestData: APayRequestDataType) => Promise<string>;
+  static complete: (status: APayPaymentStatusType) => Promise<void>;
 }
 
-export { ApplePay }
\ No newline at end of file
+export { ApplePay };
diff --git a/node_modules/react-native-apay/ios/RNApplePay.m b/node_modules/react-native-apay/ios/RNApplePay.m
index c6cba6c..a1d1633 100644
--- a/node_modules/react-native-apay/ios/RNApplePay.m
+++ b/node_modules/react-native-apay/ios/RNApplePay.m
@@ -2,7 +2,9 @@
 #import "RNApplePay.h"
 #import <React/RCTUtils.h>
 
-@implementation RNApplePay
+@implementation RNApplePay {
+    NSDictionary *_supportedNetworksMapping;
+}
 
 - (dispatch_queue_t)methodQueue
 {
@@ -27,7 +29,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"];
@@ -55,44 +57,88 @@ - (NSDictionary *)constantsToExport
     }
 }
 
-- (NSArray *_Nonnull)getSupportedNetworks:(NSDictionary *_Nonnull)props
-{
-    NSMutableDictionary *supportedNetworksMapping = [[NSMutableDictionary alloc] init];
+- (NSDictionary *_Nonnull)supportedNetworksMapping {
+    if (_supportedNetworksMapping == nil) {
+        NSMutableDictionary *mapping = [[NSMutableDictionary alloc] init];
 
-    if (@available(iOS 8, *)) {
-        [supportedNetworksMapping setObject:PKPaymentNetworkAmex forKey:@"amex"];
-        [supportedNetworksMapping setObject:PKPaymentNetworkMasterCard forKey:@"mastercard"];
-        [supportedNetworksMapping setObject:PKPaymentNetworkVisa forKey:@"visa"];
-    }
+        if (@available(iOS 8, *)) {
+            mapping[@"amex"] = PKPaymentNetworkAmex;
+            mapping[@"mastercard"] = PKPaymentNetworkMasterCard;
+            mapping[@"visa"] = PKPaymentNetworkVisa;
+        }
 
-    if (@available(iOS 9, *)) {
-        [supportedNetworksMapping setObject:PKPaymentNetworkDiscover forKey:@"discover"];
-        [supportedNetworksMapping setObject:PKPaymentNetworkPrivateLabel forKey:@"privatelabel"];
-    }
+        if (@available(iOS 9, *)) {
+            mapping[@"discover"] = PKPaymentNetworkDiscover;
+            mapping[@"privatelabel"] = PKPaymentNetworkPrivateLabel;
+        }
 
-    if (@available(iOS 9.2, *)) {
-        [supportedNetworksMapping setObject:PKPaymentNetworkChinaUnionPay forKey:@"chinaunionpay"];
-        [supportedNetworksMapping setObject:PKPaymentNetworkInterac forKey:@"interac"];
-    }
+        if (@available(iOS 9.2, *)) {
+            mapping[@"chinaunionpay"] = PKPaymentNetworkChinaUnionPay;
+            mapping[@"interac"] = PKPaymentNetworkInterac;
+        }
 
-    if (@available(iOS 10.1, *)) {
-        [supportedNetworksMapping setObject:PKPaymentNetworkJCB forKey:@"jcb"];
-        [supportedNetworksMapping setObject:PKPaymentNetworkSuica forKey:@"suica"];
-    }
+        if (@available(iOS 10.1, *)) {
+            mapping[@"jcb"] = PKPaymentNetworkJCB;
+            mapping[@"suica"] = PKPaymentNetworkSuica;
+        }
 
-    if (@available(iOS 10.3, *)) {
-        [supportedNetworksMapping setObject:PKPaymentNetworkCarteBancaire forKey:@"cartebancaires"];
-        [supportedNetworksMapping setObject:PKPaymentNetworkIDCredit forKey:@"idcredit"];
-        [supportedNetworksMapping setObject:PKPaymentNetworkQuicPay forKey:@"quicpay"];
-    }
+        if (@available(iOS 10.3, *)) {
+            mapping[@"idcredit"] = PKPaymentNetworkIDCredit;
+            mapping[@"quicpay"] = PKPaymentNetworkQuicPay;
+        }
 
-    if (@available(iOS 11.0, *)) {
-        [supportedNetworksMapping setObject:PKPaymentNetworkCarteBancaires forKey:@"cartebancaires"];
-    }
+        if (@available(iOS 11.2, *)) {
+            // PKPaymentNetworkCarteBancaire was deprecated & replaced with PKPaymentNetworkCartesBancaires
+            mapping[@"cartebancaires"]  = PKPaymentNetworkCartesBancaires;
+            mapping[@"cartesbancaires"] = PKPaymentNetworkCartesBancaires;
+        }
+
+        if (@available(iOS 12.0, *)) {
+            mapping[@"eftpos"] = PKPaymentNetworkEftpos;
+            mapping[@"electron"] = PKPaymentNetworkElectron;
+            mapping[@"maestro"] = PKPaymentNetworkMaestro;
+            mapping[@"vpay"] = PKPaymentNetworkVPay;
+        }
+
+        if (@available(iOS 12.1.1, *)) {
+            mapping[@"elo"] = PKPaymentNetworkElo;
+            mapping[@"mada"] = PKPaymentNetworkMada;
+        }
+
+        if (@available(iOS 14.0, *)) {
+            mapping[@"barcode"] = PKPaymentNetworkBarcode;
+            mapping[@"girocard"] = PKPaymentNetworkGirocard;
+        }
+
+        if (@available(iOS 14.5, *)) {
+            mapping[@"mir"] = PKPaymentNetworkMir;
+        }
 
-    if (@available(iOS 12.0, *)) {
-        [supportedNetworksMapping setObject:PKPaymentNetworkMaestro forKey:@"maestro"];
+        if (@available(iOS 15.0, *)) {
+            mapping[@"nanaco"] = PKPaymentNetworkNanaco;
+            mapping[@"waon"] = PKPaymentNetworkWaon;
+        }
+
+        if (@available(iOS 15.1, *)) {
+            mapping[@"dankort"] = PKPaymentNetworkDankort;
+        }
+
+        if (@available(iOS 16.0, *)) {
+            mapping[@"bancontact"] = PKPaymentNetworkBancontact;
+        }
+
+        if (@available(iOS 16.4, *)) {
+            mapping[@"postfinance"] = PKPaymentNetworkPostFinance;
+        }
+
+        _supportedNetworksMapping = mapping;
     }
+    return _supportedNetworksMapping;
+}
+
+- (NSArray *_Nonnull)getSupportedNetworks:(NSDictionary *_Nonnull)props
+{
+    NSDictionary *supportedNetworksMapping = [self supportedNetworksMapping];
 
     NSArray *supportedNetworksProp = props[@"supportedNetworks"];
     NSMutableArray *supportedNetworks = [NSMutableArray array];
@@ -103,6 +149,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];
@rakeshta
Copy link
Author

Just in case, I've attached the patch generated by patch-package in this comment. I hope you can use this to update your package.
react-native-apay+1.3.1.patch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant