diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml
index fb98c79..f4060b7 100644
--- a/.github/actions/setup/action.yml
+++ b/.github/actions/setup/action.yml
@@ -5,13 +5,17 @@ runs:
using: composite
steps:
- name: Setup Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
+ - name: Enable Corepack
+ run: corepack enable
+ shell: bash
+
- name: Cache dependencies
id: yarn-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: |
**/node_modules
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0c7ff3c..9b7013e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup
uses: ./.github/actions/setup
@@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup
uses: ./.github/actions/setup
@@ -42,7 +42,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup
uses: ./.github/actions/setup
@@ -56,13 +56,13 @@ jobs:
TURBO_CACHE_DIR: .turbo/android
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup
uses: ./.github/actions/setup
- name: Cache turborepo for Android
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-android-${{ hashFiles('yarn.lock') }}
@@ -79,7 +79,7 @@ jobs:
- name: Install JDK
if: env.turbo_cache_hit != 1
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
@@ -91,7 +91,7 @@ jobs:
- name: Cache Gradle
if: env.turbo_cache_hit != 1
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: |
~/.gradle/wrapper
@@ -102,23 +102,26 @@ jobs:
- name: Build example for Android
env:
- JAVA_OPTS: "-XX:MaxHeapSize=6g"
+ JAVA_OPTS: '-XX:MaxHeapSize=6g'
run: |
yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}"
build-ios:
- runs-on: macos-14
+ runs-on: macos-15
env:
TURBO_CACHE_DIR: .turbo/ios
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup
uses: ./.github/actions/setup
+ - name: Install xcbeautify
+ run: brew install xcbeautify
+
- name: Cache turborepo for iOS
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-ios-${{ hashFiles('yarn.lock') }}
@@ -133,19 +136,21 @@ jobs:
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- - name: Cache cocoapods
+ - name: Cache CocoaPods
if: env.turbo_cache_hit != 1
id: cocoapods-cache
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
- path: |
- **/ios/Pods
+ path: example/ios/Pods
key: ${{ runner.os }}-cocoapods-${{ hashFiles('example/ios/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-cocoapods-
- - name: Install cocoapods
- if: env.turbo_cache_hit != 1 && steps.cocoapods-cache.outputs.cache-hit != 'true'
+ # React Native 0.76+ requires pod install to run even when Pods are cached,
+ # because it generates ReactAppDependencyProvider.podspec in build/generated/ios/.
+ # Skipping pod install on cache hit causes "No podspec found" errors.
+ - name: Install CocoaPods
+ if: env.turbo_cache_hit != 1
run: |
cd example/ios
pod install
@@ -153,5 +158,17 @@ jobs:
NO_FLIPPER: 1
- name: Build example for iOS
+ if: env.turbo_cache_hit != 1
run: |
- yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}"
+ cd example/ios
+ xcodebuild \
+ -workspace MsdkReactNativeExample.xcworkspace \
+ -scheme MsdkReactNativeExample \
+ -configuration Debug \
+ -sdk iphonesimulator \
+ -destination "platform=iOS Simulator,name=iPhone 16,OS=latest" \
+ -derivedDataPath ~/DerivedData \
+ COMPILER_INDEX_STORE_ENABLE=NO \
+ CLANG_ENABLE_MODULE_DEBUGGING=NO \
+ build > xcodebuild.log 2>&1 || (cat xcodebuild.log | xcbeautify && exit 1)
+ cat xcodebuild.log | xcbeautify
diff --git a/.gitignore b/.gitignore
index d8b1e7a..c491960 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,6 +50,7 @@ example/vendor/
# node.js
#
node_modules/
+example/node_modules/
npm-debug.log
yarn-debug.log
yarn-error.log
diff --git a/.nvmrc b/.nvmrc
index 3f430af..9a2a0e2 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-v18
+v20
diff --git a/.yarnrc.yml b/.yarnrc.yml
new file mode 100644
index 0000000..3186f3f
--- /dev/null
+++ b/.yarnrc.yml
@@ -0,0 +1 @@
+nodeLinker: node-modules
diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa431ff..44e832e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,3 +2,4 @@
## [0.2.1] Update internal SDK libraries to android 3.8.8 and iOS 3.8.5
## [0.2.2] Update internal SDK libraries to android 3.8.9 and iOS 3.8.8. Upgrade React Native version
## [0.3.0] Update internal SDK libraries to android 3.9.1 and iOS 4.0.0. Change ios integration to SPM
+## [0.3.1] Update internal SDK libraries to android 3.10.2 and iOS 4.0.7
diff --git a/android/build.gradle b/android/build.gradle
index 6aed97e..9e9d716 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -96,7 +96,7 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.3")
- implementation "com.ecommpay:msdk-ui:3.9.1"
+ implementation "com.ecommpay:msdk-ui:3.10.2"
implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
diff --git a/example/Gemfile b/example/Gemfile
index 2a7ce35..e69022a 100644
--- a/example/Gemfile
+++ b/example/Gemfile
@@ -6,3 +6,4 @@ ruby ">= 2.6.10"
# Exclude problematic versions of cocoapods and activesupport that causes build failures.
gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1'
gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0'
+gem 'nkf'
diff --git a/example/ios/.xcode.env.local b/example/ios/.xcode.env.local
index 34d2a70..b612a49 100644
--- a/example/ios/.xcode.env.local
+++ b/example/ios/.xcode.env.local
@@ -1 +1 @@
-export NODE_BINARY=/opt/homebrew/bin/node
+export NODE_BINARY=/Users/satiryc/.nvm/versions/node/v20.20.2/bin/node
diff --git a/example/ios/MsdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved b/example/ios/MsdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved
new file mode 100644
index 0000000..043fde2
--- /dev/null
+++ b/example/ios/MsdkReactNativeExample.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -0,0 +1,15 @@
+{
+ "originHash" : "1f8a50bb7ada8d01703987854dd44acf406aa27c9323f1096103f8eeeb2b51a9",
+ "pins" : [
+ {
+ "identity" : "mobile-sdk-ios-ui",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/ITECOMMPAY/mobile-sdk-ios-ui.git",
+ "state" : {
+ "revision" : "0473d5d021ed2c126867ca47f9f65a9d9f956558",
+ "version" : "4.0.7"
+ }
+ }
+ ],
+ "version" : 3
+}
diff --git a/example/ios/MsdkReactNativeExample/Info.plist b/example/ios/MsdkReactNativeExample/Info.plist
index b771a2b..2e27ad6 100644
--- a/example/ios/MsdkReactNativeExample/Info.plist
+++ b/example/ios/MsdkReactNativeExample/Info.plist
@@ -34,7 +34,7 @@
NSLocationWhenInUseUsageDescription
RCTNewArchEnabled
-
+
UILaunchStoryboardName
LaunchScreen
UIRequiredDeviceCapabilities
diff --git a/example/ios/Podfile b/example/ios/Podfile
index 31d6379..ec0ffea 100644
--- a/example/ios/Podfile
+++ b/example/ios/Podfile
@@ -7,7 +7,7 @@ require Pod::Executable.execute_command('node', ['-p',
platform :ios, 16.6
prepare_react_native_project!
-ENV['RCT_NEW_ARCH_ENABLED'] = '1'
+ENV['RCT_NEW_ARCH_ENABLED'] = '0'
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
@@ -25,12 +25,22 @@ target 'MsdkReactNativeExample' do
)
post_install do |installer|
- # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
- # :ccache_enabled => true
)
+
+ installer.pods_project.targets.each do |target|
+ target.build_configurations.each do |config|
+ if target.name == 'fmt'
+ config.build_settings['CLANG_CXX_LANGUAGE_STANDARD'] = 'c++17'
+ else
+ config.build_settings['CLANG_CXX_LANGUAGE_STANDARD'] = 'c++20'
+ end
+
+ config.build_settings['CLANG_ENABLE_MODULE_DEBUGGING'] = 'NO'
+ end
+ end
end
end
diff --git a/example/node_modules b/example/node_modules
deleted file mode 100644
index 68a084a..0000000
--- a/example/node_modules
+++ /dev/null
@@ -1 +0,0 @@
-../node_modules
\ No newline at end of file
diff --git a/example/package.json b/example/package.json
index 7078ded..cef3b55 100644
--- a/example/package.json
+++ b/example/package.json
@@ -10,9 +10,9 @@
"build:ios": "react-native build-ios --scheme MsdkReactNativeExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\""
},
"dependencies": {
- "react": "19.1.0",
- "react-native": "^0.81.3",
- "msdk-react-native": "*"
+ "msdk-react-native": "*",
+ "react": "19.1.4",
+ "react-native": "^0.81.3"
},
"devDependencies": {
"@babel/core": "^7.20.0",
diff --git a/example/src/App.tsx b/example/src/App.tsx
index 7b7df25..9324179 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
import {
StyleSheet,
View,
@@ -7,7 +7,7 @@ import {
Button,
ScrollView,
Switch,
- useColorScheme
+ useColorScheme,
} from 'react-native';
import {
initializePayment,
@@ -18,21 +18,24 @@ import {
type EcmpAdditionalField,
type EcmpRecipientInfo,
type EcmpRecurrentData,
- getParamsForSignature
+ getParamsForSignature,
} from 'msdk-react-native';
import SignatureGenerator from '../../src/index';
-export default function App() {
+const App = (): JSX.Element => {
const colorScheme = useColorScheme();
const isDark = colorScheme === 'dark';
const [paymentResult, setPaymentResult] = useState('');
// Payment Info State
const [projectID, setProjectID] = useState('138723');
- const [paymentID, setPaymentID] = useState('sdk_sample_ui_' + Math.random().toString(36).substring(2, 9));
+ const [paymentID, setPaymentID] = useState(
+ 'sdk_sample_ui_' + Math.random().toString(36).substring(2, 9)
+ );
const [paymentAmount, setPaymentAmount] = useState('100.50');
const [paymentCurrency, setPaymentCurrency] = useState('USD');
- const [paymentDescription, setPaymentDescription] = useState('Test payment');
+ const [paymentDescription, setPaymentDescription] =
+ useState('Test payment');
const [customerID, setCustomerID] = useState('12');
const [regionCode, setRegionCode] = useState('US');
const [token, setToken] = useState('');
@@ -41,23 +44,31 @@ export default function App() {
const [secret, setSecret] = useState('secret key');
// Payment Options State
- const [actionType, setActionType] = useState(EcmpActionType.Sale);
+ // const [actionType, setActionType] = useState(
+ // EcmpActionType.Sale
+ // );
const [isDarkTheme, setIsDarkTheme] = useState(false);
- const [mockModeType, setMockModeType] = useState(EcmpMockModeType.disabled);
+ const [mockModeType, setMockModeType] = useState(
+ EcmpMockModeType.disabled
+ );
const [hideScanningCards, setHideScanningCards] = useState(true);
const [hideSavedWallets, setHideSavedWallets] = useState(false);
const [primaryBrandColor, setPrimaryBrandColor] = useState('#3498db');
- const [secondaryBrandColor, setSecondaryBrandColor] = useState('#CAB2FF');
+ const [secondaryBrandColor, setSecondaryBrandColor] =
+ useState('#CAB2FF');
const [storedCardType, setStoredCardType] = useState('');
// Screen Display Modes
- const [hideSuccessFinalPage, setHideSuccessFinalPage] = useState(false);
- const [hideDeclineFinalPage, setHideDeclineFinalPage] = useState(false);
+ const [hideSuccessFinalPage, setHideSuccessFinalPage] =
+ useState(false);
+ const [hideDeclineFinalPage, setHideDeclineFinalPage] =
+ useState(false);
// Google Pay
const [googleMerchantId, setGoogleMerchantId] = useState('');
const [googleMerchantName, setGoogleMerchantName] = useState('');
- const [googleIsTestEnvironment, setGoogleIsTestEnvironment] = useState(true);
+ const [googleIsTestEnvironment, setGoogleIsTestEnvironment] =
+ useState(true);
// Apple Pay
const [applePayMerchantID, setApplePayMerchantID] = useState('');
@@ -67,7 +78,9 @@ export default function App() {
// Additional Fields
const [additionalFieldType, setAdditionalFieldType] = useState('');
const [additionalFieldValue, setAdditionalFieldValue] = useState('');
- const [additionalFields, setAdditionalFields] = useState([]);
+ const [additionalFields, setAdditionalFields] = useState<
+ EcmpAdditionalField[]
+ >([]);
// Recipient Info
const [showRecipientInfo, setShowRecipientInfo] = useState(false);
@@ -95,10 +108,13 @@ export default function App() {
const addAdditionalField = () => {
if (additionalFieldType && additionalFieldValue) {
- setAdditionalFields([...additionalFields, {
- type: additionalFieldType,
- value: additionalFieldValue
- }]);
+ setAdditionalFields([
+ ...additionalFields,
+ {
+ type: additionalFieldType,
+ value: additionalFieldValue,
+ },
+ ]);
setAdditionalFieldType('');
setAdditionalFieldValue('');
}
@@ -111,7 +127,7 @@ export default function App() {
const handlePayment = async (paymentActionType: EcmpActionType) => {
try {
const paymentInfoWithoutSignature: EcmpPaymentInfo = {
- projectID: parseInt(projectID) || 0,
+ projectID: parseInt(projectID, 10) || 0,
paymentID: paymentID,
paymentAmount: parseFloat(paymentAmount) || 0,
paymentCurrency: paymentCurrency,
@@ -124,13 +140,17 @@ export default function App() {
hideSavedWallets: hideSavedWallets,
};
- const paramsForSignature = await getParamsForSignature(paymentInfoWithoutSignature);
-
+ const paramsForSignature = await getParamsForSignature(
+ paymentInfoWithoutSignature
+ );
- const signature = SignatureGenerator.generateSignature(paramsForSignature, secret);
+ const signature = SignatureGenerator.generateSignature(
+ paramsForSignature,
+ secret
+ );
const paymentInfo = {
- projectID: parseInt(projectID) || 0,
+ projectID: parseInt(projectID, 10) || 0,
paymentID: paymentID,
paymentAmount: parseFloat(paymentAmount) || 0,
paymentCurrency: paymentCurrency,
@@ -141,36 +161,42 @@ export default function App() {
languageCode: languageCode || undefined,
receiptData: receiptData || undefined,
hideSavedWallets: hideSavedWallets,
- signature: signature
- }
+ signature: signature,
+ };
const screenDisplayModes = [];
- if (hideSuccessFinalPage) screenDisplayModes.push(EcmpScreenDisplayMode.hideSuccessFinalPage);
- if (hideDeclineFinalPage) screenDisplayModes.push(EcmpScreenDisplayMode.hideDeclineFinalPage);
-
- const recipientInfo: EcmpRecipientInfo | undefined = showRecipientInfo ? {
- walletOwner: walletOwner || undefined,
- walletId: walletId || undefined,
- country: recipientCountry || undefined,
- pan: pan || undefined,
- cardHolder: cardHolder || undefined,
- address: address || undefined,
- city: city || undefined,
- stateCode: stateCode || undefined
- } : undefined;
-
- const recurrentData: EcmpRecurrentData | undefined = showRecurrentData ? {
- register: recurrentRegister,
- type: recurrentType || undefined,
- expiryDay: expiryDay || undefined,
- expiryMonth: expiryMonth || undefined,
- expiryYear: expiryYear || undefined,
- period: period || undefined,
- interval: parseInt(interval) || undefined,
- time: time || undefined,
- startDate: startDate || undefined,
- scheduledPaymentID: scheduledPaymentID || undefined
- } : undefined;
+ if (hideSuccessFinalPage)
+ screenDisplayModes.push(EcmpScreenDisplayMode.hideSuccessFinalPage);
+ if (hideDeclineFinalPage)
+ screenDisplayModes.push(EcmpScreenDisplayMode.hideDeclineFinalPage);
+
+ const recipientInfo: EcmpRecipientInfo | undefined = showRecipientInfo
+ ? {
+ walletOwner: walletOwner || undefined,
+ walletId: walletId || undefined,
+ country: recipientCountry || undefined,
+ pan: pan || undefined,
+ cardHolder: cardHolder || undefined,
+ address: address || undefined,
+ city: city || undefined,
+ stateCode: stateCode || undefined,
+ }
+ : undefined;
+
+ const recurrentData: EcmpRecurrentData | undefined = showRecurrentData
+ ? {
+ register: recurrentRegister,
+ type: recurrentType || undefined,
+ expiryDay: expiryDay || undefined,
+ expiryMonth: expiryMonth || undefined,
+ expiryYear: expiryYear || undefined,
+ period: period || undefined,
+ interval: parseInt(interval, 10) || undefined,
+ time: time || undefined,
+ startDate: startDate || undefined,
+ scheduledPaymentID: scheduledPaymentID || undefined,
+ }
+ : undefined;
await initializePayment(
{
@@ -178,8 +204,10 @@ export default function App() {
paymentInfo,
isDarkTheme,
mockModeType,
- screenDisplayModes: screenDisplayModes.length > 0 ? screenDisplayModes : undefined,
- additionalFields: additionalFields.length > 0 ? additionalFields : undefined,
+ screenDisplayModes:
+ screenDisplayModes.length > 0 ? screenDisplayModes : undefined,
+ additionalFields:
+ additionalFields.length > 0 ? additionalFields : undefined,
recipientInfo,
recurrentData,
hideScanningCards,
@@ -192,7 +220,7 @@ export default function App() {
primaryBrandColor: primaryBrandColor,
secondaryBrandColor: secondaryBrandColor,
hideFooterLogo: true,
- storedCardType: parseInt(storedCardType) || undefined
+ storedCardType: parseInt(storedCardType, 10) || undefined,
},
(result) => {
console.log('Payment result:', result);
@@ -217,6 +245,7 @@ export default function App() {
@@ -335,22 +364,34 @@ export default function App() {
Hide Saved Wallets
-
+
Hide Scanning Cards
-
+
Hide Success Final Page
-
+
Hide Decline Final Page
-
+
@@ -361,17 +402,23 @@ export default function App() {