diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c5f3f6b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive" +} \ No newline at end of file diff --git a/README.md b/README.md index 3619fbf..42da31f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # react-native-paytabs -![Version](https://img.shields.io/badge/React%20Native%20Paytabs-v2.3.11-green) +![Version](https://img.shields.io/badge/React%20Native%20Paytabs-v2.4.0-green) React native paytabs library is a wrapper for the native PayTabs Android and iOS SDKs, It helps you integrate with PayTabs seamlessly. @@ -12,7 +12,7 @@ Library Support: # Installation ```sh -$ npm install @paytabs/react-native-paytabs@2.3.11 --save --force +$ npm install @paytabs/react-native-paytabs@2.4.0 --save --force ``` ### Expo @@ -48,7 +48,7 @@ expo install @paytabs/react-native-paytabs Import `@paytabs/react-native-paytabs` ```javascript -import {RNPaymentSDKLibrary, PaymentSDKConfiguration, PaymentSDKBillingDetails, PaymentSDKTheme, PaymentSDKConstants} from '@paytabs/react-native-paytabs'; +import {RNPaymentSDKLibrary, PaymentSDKConfiguration, PaymentSDKBillingDetails, PaymentSDKTheme, PaymentSDKConstants, PaymentSDKSavedCardInfo} from '@paytabs/react-native-paytabs'; ``` ### Pay with Card @@ -104,7 +104,8 @@ Options to show billing and shipping ifno ``` -3. Start payment by calling `startCardPayment` method and handle the transaction details +# 1- Pay with card +Start payment by calling `startCardPayment` method and handle the transaction details ```javascript @@ -120,6 +121,74 @@ RNPaymentSDKLibrary.startCardPayment(JSON.stringify(configuration)).then( result }); ``` +card + + +# 2- Pay with Token +Start payment by calling `startTokenizedCardPayment` method and handle the transaction details + +```javascript + +RNPaymentSDKLibrary.startTokenizedCardPayment(JSON.stringify(configuration), +"Token", +"TransactionReference" +).then( result => { + if(result["PaymentDetails"] != null) { // Handle transaction details + let paymentDetails = result["PaymentDetails"] + console.log(paymentDetails) + } else if(result["Event"] == "CancelPayment") { // Handle events + console.log("Cancel Payment Event") + } + }, function(error) { // Handle error + console.log(error) + }); + +``` + +# 3- Pay with 3DS Secured Token +Start payment by calling `start3DSecureTokenizedCardPayment` method and handle the transaction details + +```javascript +let cardInfo = new PaymentSDKSavedCardInfo("Card mask", "cardType") +RNPaymentSDKLibrary.start3DSecureTokenizedCardPayment( + JSON.stringify(configuration), + JSON.stringify(cardInfo), + "Token" + ).then( result => { + if(result["PaymentDetails"] != null) { // Handle transaction details + let paymentDetails = result["PaymentDetails"] + console.log(paymentDetails) + } else if(result["Event"] == "CancelPayment") { // Handle events + console.log("Cancel Payment Event") + } + }, function(error) { // Handle error + console.log(error) + }); + +``` +rec 3ds + + +# 4- Pay with saved card +Start payment by calling `startPaymentWithSavedCards` method and handle the transaction details + +```javascript + +RNPaymentSDKLibrary.startPaymentWithSavedCards(JSON.stringify(configuration), +support3DsBool).then( result => { + if(result["PaymentDetails"] != null) { // Handle transaction details + let paymentDetails = result["PaymentDetails"] + console.log(paymentDetails) + } else if(result["Event"] == "CancelPayment") { // Handle events + console.log("Cancel Payment Event") + } + }, function(error) { // Handle error + console.log(error) + }); + +``` +rec 3ds + ### Pay with Apple Pay diff --git a/android/build.gradle b/android/build.gradle index d8367d0..26c65af 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -164,6 +164,6 @@ repositories { dependencies { implementation 'com.facebook.react:react-native:+' - implementation 'com.paytabs:payment-sdk:6.2.12' + implementation 'com.paytabs:payment-sdk:6.3.2' } \ No newline at end of file diff --git a/android/src/main/java/com/paymentsdk/RNPaymentManagerModule.java b/android/src/main/java/com/paymentsdk/RNPaymentManagerModule.java index 2c9a227..6efa256 100644 --- a/android/src/main/java/com/paymentsdk/RNPaymentManagerModule.java +++ b/android/src/main/java/com/paymentsdk/RNPaymentManagerModule.java @@ -33,6 +33,7 @@ import com.payment.paymentsdk.integrationmodels.PaymentSdkTransactionDetails; import com.payment.paymentsdk.integrationmodels.PaymentSdkTransactionType; import com.payment.paymentsdk.sharedclasses.interfaces.CallbackPaymentInterface; +import com.payment.paymentsdk.save_cards.entities.PaymentSDKSavedCardInfo; import org.jetbrains.annotations.NotNull; import org.json.JSONArray; @@ -87,7 +88,88 @@ public void startCardPayment(final String arguments,final Promise promise) { promise.reject("Error", e.getMessage(), new Throwable(e.getMessage())); } } + + + + @ReactMethod + public void startTokenizedCardPayment( + final String arguments, + final String token, + final String transactionRef, + final Promise promise) { + this.promise = promise; + try { + final JSONObject paymentDetails = new JSONObject(arguments); + final PaymentSdkConfigBuilder configBuilder = createConfiguration(paymentDetails); + if (!paymentDetails.isNull("theme")) { + if (!paymentDetails.optJSONObject("theme").isNull("merchantLogo")) { + String iconUri = paymentDetails.optJSONObject("theme").optJSONObject("merchantLogo").optString("uri"); + Log.d("LogoURL", iconUri); + configBuilder.setMerchantIcon(iconUri); + } + } + + startTokenizedPayment(paymentDetails, token, transactionRef, configBuilder); + + } catch (Exception e) { + promise.reject("Error", e.getMessage(), new Throwable(e.getMessage())); + } + } + + @ReactMethod + public void start3DSecureTokenizedCardPayment( + final String arguments, + final String savedCardInfo, + final String token, + final Promise promise) { + this.promise = promise; + try { + final JSONObject paymentDetails = new JSONObject(arguments); + final PaymentSdkConfigBuilder configBuilder = createConfiguration(paymentDetails); + + final JSONObject savedCardObject = new JSONObject(savedCardInfo); + final PaymentSDKSavedCardInfo paymentSDKSavedCardInfo = createSavedCardInfo(savedCardObject); + if (!paymentDetails.isNull("theme")) { + if (!paymentDetails.optJSONObject("theme").isNull("merchantLogo")) { + String iconUri = paymentDetails.optJSONObject("theme").optJSONObject("merchantLogo").optString("uri"); + Log.d("LogoURL", iconUri); + configBuilder.setMerchantIcon(iconUri); + } + } + + start3DsPayment(paymentDetails, paymentSDKSavedCardInfo, token, configBuilder); + + } catch (Exception e) { + promise.reject("Error", e.getMessage(), new Throwable(e.getMessage())); + } + } + + + @ReactMethod + public void startPaymentWithSavedCards( + final String arguments, + final Boolean support3DS, + final Promise promise) { + this.promise = promise; + try { + final JSONObject paymentDetails = new JSONObject(arguments); + final PaymentSdkConfigBuilder configBuilder = createConfiguration(paymentDetails); + if (!paymentDetails.isNull("theme")) { + if (!paymentDetails.optJSONObject("theme").isNull("merchantLogo")) { + String iconUri = paymentDetails.optJSONObject("theme").optJSONObject("merchantLogo").optString("uri"); + Log.d("LogoURL", iconUri); + configBuilder.setMerchantIcon(iconUri); + } + } + + startSavedCardPayment(paymentDetails, support3DS, configBuilder); + + } catch (Exception e) { + promise.reject("Error", e.getMessage(), new Throwable(e.getMessage())); + } + } + public static String optString(JSONObject json, String key) { if (json.isNull(key)) return ""; @@ -95,12 +177,56 @@ public static String optString(JSONObject json, String key) { return json.optString(key, null); } - private void startPayment(JSONObject paymentDetails, PaymentSdkConfigBuilder configBuilder) { + private void startPayment(JSONObject paymentDetails, PaymentSdkConfigBuilder configBuilder) { + String samsungToken = paymentDetails.optString("samsungToken"); + if (samsungToken != null && samsungToken.length() > 0) + PaymentSdkActivity.startSamsungPayment(reactContext.getCurrentActivity(), configBuilder.build(), samsungToken, this); + else + PaymentSdkActivity.startCardPayment(reactContext.getCurrentActivity(), configBuilder.build(), this); + } + + + + private void startTokenizedPayment( + JSONObject paymentDetails, + final String token, + final String transactionRef, + PaymentSdkConfigBuilder configBuilder) { String samsungToken = paymentDetails.optString("samsungToken"); - if (samsungToken != null && samsungToken.length() > 0) - PaymentSdkActivity.startSamsungPayment(reactContext.getCurrentActivity(), configBuilder.build(), samsungToken, this); - else - PaymentSdkActivity.startCardPayment(reactContext.getCurrentActivity(), configBuilder.build(), this); + PaymentSdkActivity.startTokenizedCardPayment( + reactContext.getCurrentActivity(), + configBuilder.build(), + token, + transactionRef, + this); + } + + + private void start3DsPayment( + JSONObject paymentDetails, + final PaymentSDKSavedCardInfo savedCardInfo, + final String token, + PaymentSdkConfigBuilder configBuilder) { + String samsungToken = paymentDetails.optString("samsungToken"); + PaymentSdkActivity.start3DSecureTokenizedCardPayment( + reactContext.getCurrentActivity(), + configBuilder.build(), + savedCardInfo, + token, + this); + } + + + private void startSavedCardPayment( + JSONObject paymentDetails, + final Boolean support3DS, + PaymentSdkConfigBuilder configBuilder) { + String samsungToken = paymentDetails.optString("samsungToken"); + PaymentSdkActivity.startPaymentWithSavedCards( + reactContext.getCurrentActivity(), + configBuilder.build(), + support3DS, + this); } @ReactMethod @@ -181,6 +307,16 @@ private PaymentSdkConfigBuilder createConfiguration(JSONObject paymentDetails) { return configData; } + private PaymentSDKSavedCardInfo createSavedCardInfo(JSONObject jsonCardInfo) { + String maskedCard = jsonCardInfo.optString("maskedCard"); + String cardType = jsonCardInfo.optString("cardType"); + + + PaymentSDKSavedCardInfo cardInfo = new PaymentSDKSavedCardInfo( + maskedCard, cardType); + return cardInfo; + } + private void getDrawableFromUri(final String path, final RetrieveDrawableListener listener) { try { new AsyncTask() { diff --git a/example/App.js b/example/App.js index d66a8ef..54dbc0a 100644 --- a/example/App.js +++ b/example/App.js @@ -16,6 +16,7 @@ import { PaymentSDKBillingDetails, PaymentSDKTheme, PaymentSDKConstants, + PaymentSDKSavedCardInfo, } from '@paytabs/react-native-paytabs'; const instructions = Platform.select({ @@ -82,6 +83,126 @@ export default class App extends Component { }); } + onPressTokenizedPayment() { + let configuration = new PaymentSDKConfiguration(); + configuration.profileID = 'profileID' + configuration.serverKey = 'serverKey' + configuration.clientKey = 'clientKey' + configuration.cartID = "545454" + configuration.currency = "EGP" + configuration.cartDescription = "Flowers" + configuration.merchantCountryCode = "eg" + configuration.merchantName = "Flowers Store" + configuration.amount = 20 + configuration.screenTitle = "Pay with Card" + + let billingDetails = new PaymentSDKBillingDetails(name= "Jone Smith", + email= "email@domain.com", + phone= "97311111111", + addressLine= "Flat 1,Building 123, Road 2345", + city= "Dubai", + state= "Dubai", + countryCode= "EG", + zip= "1234") + configuration.billingDetails = billingDetails + let theme = new PaymentSDKTheme() + + RNPaymentSDKLibrary.startTokenizedCardPayment( + JSON.stringify(configuration), + "Token", + "TransactionReference" + ).then( result => { + if(result["PaymentDetails"] != null) { + let paymentDetails = result["PaymentDetails"] + console.log(paymentDetails) + } else if(result["Event"] == "CancelPayment") { + console.log("Cancel Payment Event") + } + }, function(error) { + console.log(error) + }); + } + onPress3DsPayment() { + let configuration = new PaymentSDKConfiguration(); + configuration.profileID = 'profileID' + configuration.serverKey = 'serverKey' + configuration.clientKey = 'clientKey' + configuration.cartID = "545454" + configuration.currency = "EGP" + configuration.cartDescription = "Flowers" + configuration.merchantCountryCode = "eg" + configuration.merchantName = "Flowers Store" + configuration.amount = 20 + configuration.screenTitle = "Pay with Card" + + let billingDetails = new PaymentSDKBillingDetails(name= "Jone Smith", + email= "email@domain.com", + phone= "97311111111", + addressLine= "Flat 1,Building 123, Road 2345", + city= "Dubai", + state= "Dubai", + countryCode= "EG", + zip= "1234") + configuration.billingDetails = billingDetails + let theme = new PaymentSDKTheme() + let cardInfo = new PaymentSDKSavedCardInfo("4111 11## #### 1111", "visa") + RNPaymentSDKLibrary.start3DSecureTokenizedCardPayment( + JSON.stringify(configuration), + JSON.stringify(cardInfo), + "Token" + ).then( result => { + if(result["PaymentDetails"] != null) { + let paymentDetails = result["PaymentDetails"] + console.log(paymentDetails) + } else if(result["Event"] == "CancelPayment") { + console.log("Cancel Payment Event") + } + }, function(error) { + console.log(error) + }); + } + + onPressSavedCardPayment() { + let configuration = new PaymentSDKConfiguration(); + configuration.profileID = 'profileID' + configuration.serverKey = 'serverKey' + configuration.clientKey = 'clientKey' + configuration.cartID = "545454" + configuration.currency = "EGP" + configuration.cartDescription = "Flowers" + configuration.merchantCountryCode = "eg" + configuration.merchantName = "Flowers Store" + configuration.amount = 20 + configuration.screenTitle = "Pay with Card" + configuration.tokeniseType = "merchantMandatory" + + let billingDetails = new PaymentSDKBillingDetails(name= "Jone Smith", + email= "email@domain.com", + phone= "97311111111", + addressLine= "Flat 1,Building 123, Road 2345", + city= "Dubai", + state= "Dubai", + countryCode= "EG", + zip= "1234") + configuration.billingDetails = billingDetails + let theme = new PaymentSDKTheme() + + RNPaymentSDKLibrary.startPaymentWithSavedCards( + JSON.stringify(configuration), + false, + ).then( result => { + if(result["PaymentDetails"] != null) { + let paymentDetails = result["PaymentDetails"] + console.log(paymentDetails) + } else if(result["Event"] == "CancelPayment") { + console.log("Cancel Payment Event") + } + }, function(error) { + console.log(error) + }); + } + + onPressApplePay() { let configuration = new PaymentSDKConfiguration(); configuration.profileID = '*profile id*' @@ -163,6 +284,12 @@ export default class App extends Component { {this.state.message}