├── .gitattributes ├── ios ├── libipay88sdk.a ├── RNIpay88Sdk.xcworkspace │ └── contents.xcworkspacedata ├── IPay88.h ├── RNIpay88Sdk.h ├── IpayPayment.h ├── Ipay.h ├── IPay88.m ├── RNIpay88Sdk.m └── RNIpay88Sdk.xcodeproj │ └── project.pbxproj ├── android ├── libs │ └── ipay88_androidv7.jar ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── ipay88 │ │ ├── IPay88Package.java │ │ └── IPay88Module.java ├── build.gradle ├── gradlew.bat └── gradlew ├── .gitignore ├── package.json ├── ipay88-sdk.podspec ├── .github └── workflows │ └── npmpublish.yml ├── index.js └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text -------------------------------------------------------------------------------- /ios/libipay88sdk.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myussufz/react-native-ipay88-sdk/HEAD/ios/libipay88sdk.a -------------------------------------------------------------------------------- /android/libs/ipay88_androidv7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myussufz/react-native-ipay88-sdk/HEAD/android/libs/ipay88_androidv7.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myussufz/react-native-ipay88-sdk/HEAD/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /ios/RNIpay88Sdk.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | 3 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Mar 24 01:20:26 MYT 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip 7 | -------------------------------------------------------------------------------- /ios/IPay88.h: -------------------------------------------------------------------------------- 1 | // 2 | // IPay88.h 3 | // 4 | // Created by yussuf on 2/28/18. 5 | // Copyright © 2018 Facebook. All rights reserved. 6 | // 7 | 8 | #import "Ipay.h" 9 | #import "IpayPayment.h" 10 | #import "React/RCTBridge.h" 11 | #import 12 | 13 | @interface IPay88 : RCTEventEmitter 14 | 15 | @property RCTEventEmitter *Event; 16 | 17 | @end 18 | 19 | 20 | -------------------------------------------------------------------------------- /ios/RNIpay88Sdk.h: -------------------------------------------------------------------------------- 1 | // 2 | // IPay88.h 3 | // 4 | // Created by yussuf on 2/28/18. 5 | // Copyright © 2018 Facebook. All rights reserved. 6 | // 7 | 8 | #import "Ipay.h" 9 | #import "IpayPayment.h" 10 | #import "React/RCTBridge.h" 11 | #import 12 | 13 | @interface IPay88 : RCTEventEmitter 14 | 15 | @property RCTEventEmitter *Event; 16 | 17 | @end 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # OSX 3 | # 4 | .DS_Store 5 | 6 | # node.js 7 | # 8 | node_modules/ 9 | npm-debug.log 10 | yarn-error.log 11 | 12 | 13 | # Xcode 14 | # 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | project.xcworkspace 32 | 33 | 34 | # Android/IntelliJ 35 | # 36 | build/ 37 | .idea 38 | .gradle 39 | local.properties 40 | *.iml 41 | 42 | # BUCK 43 | buck-out/ 44 | \.buckd/ 45 | *.keystore 46 | 47 | *.project 48 | *.settings 49 | *.classpath -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ipay88-sdk", 3 | "version": "1.0.5", 4 | "description": "", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/myussufz/react-native-ipay88-sdk.git" 8 | }, 9 | "main": "index.js", 10 | "scripts": { 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [ 14 | "react-native", 15 | "ipay88", 16 | "sdk" 17 | ], 18 | "author": "Mohamed Yussuf", 19 | "license": "MIT", 20 | "peerDependencies": { 21 | "react": "^16.8.1", 22 | "react-native": ">=0.60.0-rc.0 <1.0.x" 23 | }, 24 | "devDependencies": { 25 | "react": "^16.9.0", 26 | "react-native": "^0.61.5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ipay88-sdk.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "ipay88-sdk" 3 | s.version = "1.0.2" 4 | s.summary = "ipay88-sdk" 5 | s.description = <<-DESC 6 | RNIpay88Sdk 7 | DESC 8 | s.homepage = "https://github.com/myussufz/react-native-ipay88-sdk" 9 | s.license = "MIT" 10 | s.author = { "author" => "author@domain.cn" } 11 | s.platform = :ios, "7.0" 12 | s.source = { :git => "https://github.com/author/RNIpay88Sdk.git", :tag => "master" } 13 | 14 | s.source_files = "ios/iPay.h", "ios/IpayPayment.h", "ios/RNIpay88Sdk.h", "ios/RNIpay88Sdk.m" 15 | s.vendored_libraries = "ios/**/*.a" 16 | 17 | s.requires_arc = true 18 | 19 | s.dependency "React" 20 | end 21 | -------------------------------------------------------------------------------- /.github/workflows/npmpublish.yml: -------------------------------------------------------------------------------- 1 | name: npm-publish 2 | on: 3 | push: 4 | branches: 5 | - master # Change this to your default branch 6 | jobs: 7 | npm-publish: 8 | name: npm-publish 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout repository 12 | uses: actions/checkout@master 13 | - name: Set up Node.js 14 | uses: actions/setup-node@master 15 | with: 16 | node-version: 12.16.1 17 | - name: Publish if version has been updated 18 | uses: pascalgn/npm-publish-action@51fdb4531e99aac1873764ef7271af448dc42ab4 19 | with: # All of theses inputs are optional 20 | tag_name: "v%s" 21 | tag_message: "v%s" 22 | commit_pattern: "^Release (\\S+)" 23 | env: # More info about the environment variables in the README 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Leave this as is, it's automatically generated 25 | NPM_AUTH_TOKEN: ${{ secrets.npm_token }} # You need to set this in your repo settings 26 | -------------------------------------------------------------------------------- /android/src/main/java/com/ipay88/IPay88Package.java: -------------------------------------------------------------------------------- 1 | package com.ipay88; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.JavaScriptModule; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.Arrays; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class IPay88Package implements ReactPackage { 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactContext) { 16 | return Arrays.asList(new IPay88Module(reactContext)); 17 | } 18 | 19 | // Deprecated from RN 0.47 20 | public List> createJSModules() { 21 | return Collections.emptyList(); 22 | } 23 | 24 | @Override 25 | public List createViewManagers(ReactApplicationContext reactContext) { 26 | return Collections.emptyList(); 27 | } 28 | } -------------------------------------------------------------------------------- /ios/IpayPayment.h: -------------------------------------------------------------------------------- 1 | // 2 | // IpayPayment.h 3 | // ipay88sdk 4 | // 5 | 6 | @interface IpayPayment : NSObject { 7 | NSString *merchantKey; 8 | NSString *merchantCode; 9 | NSString *paymentId; 10 | NSString *refNo; 11 | NSString *amount; 12 | NSString *currency; 13 | NSString *prodDesc; 14 | NSString *userName; 15 | NSString *userEmail; 16 | NSString *userContact; 17 | NSString *remark; 18 | NSString *lang; 19 | NSString *country; 20 | NSString *backendPostURL; 21 | } 22 | 23 | @property (nonatomic, retain) NSString *merchantKey; 24 | @property (nonatomic, retain) NSString *merchantCode; 25 | @property (nonatomic, retain) NSString *paymentId; 26 | @property (nonatomic, retain) NSString *refNo; 27 | @property (nonatomic, retain) NSString *amount; 28 | @property (nonatomic, retain) NSString *currency; 29 | @property (nonatomic, retain) NSString *prodDesc; 30 | @property (nonatomic, retain) NSString *userName; 31 | @property (nonatomic, retain) NSString *userEmail; 32 | @property (nonatomic, retain) NSString *userContact; 33 | @property (nonatomic, retain) NSString *remark; 34 | @property (nonatomic, retain) NSString *lang; 35 | @property (nonatomic, retain) NSString *country; 36 | @property (nonatomic, retain) NSString *backendPostURL; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ios/Ipay.h: -------------------------------------------------------------------------------- 1 | // 2 | // Ipay.h 3 | // ipay88sdk 4 | // 5 | 6 | #import 7 | #import 8 | #import "IpayPayment.h" 9 | 10 | @protocol PaymentResultDelegate 11 | 12 | - (void)paymentSuccess:(NSString *)refNo withTransId:(NSString *)transId withAmount:(NSString *)amount withRemark:(NSString *)remark withAuthCode:(NSString *)authCode; 13 | - (void)paymentFailed:(NSString *)refNo withTransId:(NSString *)transId withAmount:(NSString *)amount withRemark:(NSString *)remark withErrDesc:(NSString *)errDesc; 14 | - (void)paymentCancelled:(NSString *)refNo withTransId:(NSString *)transId withAmount:(NSString *)amount withRemark:(NSString *)remark withErrDesc:(NSString *)errDesc; 15 | - (void)requerySuccess:(NSString *)refNo withMerchantCode:(NSString *)merchantCode withAmount:(NSString *)amount withResult:(NSString *)result; 16 | - (void)requeryFailed:(NSString *)refNo withMerchantCode:(NSString *)merchantCode withAmount:(NSString *)amount withErrDesc:(NSString *)errDesc; 17 | @end 18 | 19 | @interface Ipay : UIViewController { 20 | __weak id delegate; 21 | } 22 | @property (nonatomic,weak) id delegate; 23 | - (UIView *)checkout:(IpayPayment *)payment; 24 | - (void)requery:(IpayPayment *)payment; 25 | 26 | @end -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | def DEFAULT_COMPILE_SDK_VERSION = 28 2 | def DEFAULT_BUILD_TOOLS_VERSION = '28.0.3' 3 | def DEFAULT_MIN_SDK_VERSION = 24 4 | def DEFAULT_TARGET_SDK_VERSION = 28 5 | 6 | def safeExtGet(prop, fallback) { 7 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 8 | } 9 | 10 | buildscript { 11 | repositories { 12 | google() 13 | jcenter() 14 | } 15 | 16 | dependencies { 17 | classpath 'com.android.tools.build:gradle:3.4.1' 18 | } 19 | } 20 | 21 | apply plugin: 'com.android.library' 22 | 23 | android { 24 | compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION) 25 | buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION) 26 | defaultConfig { 27 | minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION) 28 | targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION) 29 | versionCode 1 30 | versionName "1.0" 31 | } 32 | 33 | lintOptions { 34 | abortOnError false 35 | } 36 | 37 | compileOptions { 38 | sourceCompatibility JavaVersion.VERSION_1_8 39 | targetCompatibility JavaVersion.VERSION_1_8 40 | } 41 | } 42 | 43 | repositories { 44 | mavenLocal() 45 | maven { 46 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 47 | url "$rootDir/../node_modules/react-native/android" 48 | } 49 | maven { 50 | // Android JSC is installed from npm 51 | url "$rootDir/../node_modules/jsc-android/dist" 52 | } 53 | google() 54 | jcenter() 55 | } 56 | 57 | dependencies { 58 | implementation 'com.facebook.react:react-native:+' 59 | implementation files('libs/ipay88_androidv7.jar') 60 | } 61 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { NativeModules, DeviceEventEmitter, Platform, NativeEventEmitter } from 'react-native'; 3 | import { PropTypes } from 'prop-types'; 4 | 5 | const { IPay88 } = NativeModules; 6 | const iosEvent = new NativeEventEmitter(IPay88); 7 | 8 | const isAndroid = Platform.OS === 'android'; 9 | 10 | let successSubscription; 11 | let failedSubscription; 12 | let cancelSubscription; 13 | 14 | export default class IPay extends Component { 15 | static propTypes = { 16 | successNotify: PropTypes.func.isRequired, 17 | failedNotify: PropTypes.func.isRequired, 18 | cancelNotify: PropTypes.func.isRequired, 19 | }; 20 | 21 | componentWillMount() { 22 | if (isAndroid) { 23 | // Android 24 | successSubscription = DeviceEventEmitter.addListener('ipay88:success', (data) => this.onSuccess(data)); 25 | failedSubscription = DeviceEventEmitter.addListener('ipay88:failed', (data) => this.onFailed(data)); 26 | cancelSubscription = DeviceEventEmitter.addListener('ipay88:canceled', (data) => this.onCanceled(data)); 27 | } else { 28 | // ios 29 | successSubscription = iosEvent.addListener('ipay88:success', (data) => this.onSuccess(data)); 30 | failedSubscription = iosEvent.addListener('ipay88:failed', (data) => this.onFailed(data)); 31 | cancelSubscription = iosEvent.addListener('ipay88:canceled', (data) => this.onCanceled(data)); 32 | } 33 | } 34 | 35 | componentDidMount() { 36 | successSubscription.remove(); 37 | failedSubscription.remove(); 38 | cancelSubscription.remove(); 39 | } 40 | 41 | onSuccess = (data) => { 42 | this.props.successNotify(data); 43 | }; 44 | 45 | onCanceled = (data) => { 46 | this.props.cancelNotify(data); 47 | }; 48 | 49 | onFailed = (data) => { 50 | this.props.failedNotify(data); 51 | }; 52 | 53 | render() { 54 | return null; 55 | } 56 | } 57 | 58 | const Pay = (data) => { 59 | const { 60 | merchantKey = '', 61 | merchantCode = '', 62 | referenceNo = '', 63 | amount = '', 64 | currency = '', 65 | productDescription = '', 66 | userName = '', 67 | userEmail = '', 68 | userContact = '', 69 | country = '', 70 | backendUrl = '', 71 | } = data; 72 | 73 | const errors = {}; 74 | // if (paymentId === '') {errors.paymentId = '`paymentId` is required'; // optional 75 | if (merchantKey === '') errors.merchantKey = '`merchantKey` is required'; 76 | if (merchantCode === '') errors.merchantCode = '`merchantCode` is required`'; 77 | if (referenceNo === '') errors.referenceNo = '`referenceNo` is required'; 78 | if (amount === '') errors.amount = '`amount` is required'; 79 | if (currency === '') errors.currency = '`currency` is required'; 80 | if (productDescription === '') errors.productDescription = '`productDescription` is required'; 81 | if (userName === '') errors.userName = '`userName` is required'; 82 | if (userEmail === '') errors.userEmail = '`userEmail` is required'; 83 | if (userContact === '') errors.userContact = '`userContact` is required'; 84 | // if (remark === '') errors.remark = '`remark` is required'; // optional 85 | // if (utfLang === '') errors.utfLang = '`utfLang` is required'; // optional 86 | if (country === '') errors.country = '`country` is required'; 87 | if (backendUrl === '') errors.backendUrl = '`backendUrl` is required'; 88 | 89 | if (Object.keys(errors).length > 0) { 90 | return errors; 91 | } 92 | 93 | return IPay88.pay(data); 94 | }; 95 | 96 | export { Pay }; 97 | -------------------------------------------------------------------------------- /ios/IPay88.m: -------------------------------------------------------------------------------- 1 | // 2 | // IPay88.m 3 | // 4 | // Created by yussuf on 2/28/18. 5 | // Copyright © 2018 Facebook. All rights reserved. 6 | // 7 | 8 | #import "IPay88.h" 9 | #import 10 | #import 11 | #import 12 | 13 | @interface IPay88 () 14 | 15 | @property UIView *paymentView; 16 | @property Ipay *paymentsdk; 17 | @property IpayPayment *payment; 18 | 19 | @end 20 | 21 | @implementation IPay88 22 | 23 | RCT_EXPORT_MODULE(); 24 | - (NSArray *)supportedEvents 25 | { 26 | return @[@"ipay88:success", @"ipay88:failed", @"ipay88:canceled"]; 27 | } 28 | 29 | RCT_EXPORT_METHOD(pay:(NSDictionary *)data) 30 | { 31 | dispatch_async(dispatch_get_main_queue(), ^{ 32 | // RCTLogInfo(@"%@", data); 33 | 34 | // Precreate payment 35 | self.paymentsdk = [[Ipay alloc] init]; 36 | self.payment = [[IpayPayment alloc] init]; 37 | [self.payment setPaymentId:data[@"paymentId"]]; 38 | [self.payment setMerchantKey:data[@"merchantKey"]]; 39 | [self.payment setMerchantCode:data[@"merchantCode"]]; 40 | [self.payment setRefNo:data[@"referenceNo"]]; 41 | [self.payment setAmount:data[@"amount"]]; 42 | [self.payment setCurrency:data[@"currency"]]; 43 | [self.payment setProdDesc:data[@"productDescription"]]; 44 | [self.payment setUserName:data[@"userName"]]; 45 | [self.payment setUserEmail:data[@"userEmail"]]; 46 | [self.payment setUserContact:data[@"userContact"]]; 47 | [self.payment setRemark:data[@"remark"]]; 48 | [self.payment setLang:data[@"utfLang"]]; 49 | [self.payment setCountry:data[@"country"]]; 50 | [self.payment setBackendPostURL:data[@"backendUrl"]]; 51 | 52 | self.paymentsdk.delegate = self; 53 | self.paymentView = [self.paymentsdk checkout:self.payment]; 54 | 55 | UIViewController *ctrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; 56 | [ctrl.view addSubview:self.paymentView]; 57 | }); 58 | } 59 | 60 | 61 | - (void)paymentCancelled:(NSString *)refNo withTransId:(NSString *)transId withAmount:(NSString *)amount withRemark:(NSString *)remark withErrDesc:(NSString *)errDesc { 62 | // Remove the ipay88 webview 63 | [self.paymentView removeFromSuperview]; 64 | 65 | NSDictionary *params = 66 | @{ 67 | @"transactionId": transId, 68 | @"referenceNo": refNo, 69 | @"amount": amount, 70 | @"remark": remark, 71 | @"error": errDesc, 72 | }; 73 | 74 | [self sendEventWithName:@"ipay88:canceled" body:params]; 75 | 76 | RCTLogInfo(@"Payment cancel"); 77 | } 78 | 79 | 80 | - (void)paymentFailed:(NSString *)refNo withTransId:(NSString *)transId withAmount:(NSString *)amount withRemark:(NSString *)remark withErrDesc:(NSString *)errDesc { 81 | // Remove the ipay88 webview 82 | [self.paymentView removeFromSuperview]; 83 | 84 | NSDictionary *params = 85 | @{ 86 | @"transactionId": transId, 87 | @"referenceNo": refNo, 88 | @"amount": amount, 89 | @"remark": remark, 90 | @"error": errDesc, 91 | }; 92 | 93 | [self sendEventWithName:@"ipay88:failed" body:params]; 94 | 95 | RCTLogInfo(@"Payment failed"); 96 | } 97 | 98 | - (void)paymentSuccess:(NSString *)refNo withTransId:(NSString *)transId withAmount:(NSString *)amount withRemark:(NSString *)remark withAuthCode:(NSString *)authCode { 99 | // Remove the ipay88 webview 100 | [self.paymentView removeFromSuperview]; 101 | 102 | NSDictionary *params = 103 | @{ 104 | @"authorizationCode": authCode, 105 | @"transactionId": transId, 106 | @"referenceNo": refNo, 107 | @"amount": amount, 108 | @"remark": remark, 109 | }; 110 | 111 | [self sendEventWithName:@"ipay88:success" body:params]; 112 | 113 | RCTLogInfo(@"Payment success"); 114 | } 115 | 116 | - (void)requerySuccess:(NSString *)refNo withMerchantCode:(NSString *)merchantCode withAmount:(NSString *)amount withResult:(NSString *)result { 117 | RCTLogInfo(@"Requery success"); 118 | } 119 | 120 | - (void)requeryFailed:(NSString *)refNo withMerchantCode:(NSString *)merchantCode withAmount:(NSString *)amount withErrDesc:(NSString *)errDesc { 121 | RCTLogInfo(@"Requery failed"); 122 | } 123 | 124 | 125 | @end 126 | 127 | 128 | -------------------------------------------------------------------------------- /ios/RNIpay88Sdk.m: -------------------------------------------------------------------------------- 1 | // 2 | // IPay88.m 3 | // 4 | // Created by yussuf on 2/28/18. 5 | // Copyright © 2018 Facebook. All rights reserved. 6 | // 7 | 8 | #import "IPay88.h" 9 | #import 10 | #import 11 | #import 12 | 13 | @interface IPay88 () 14 | 15 | @property UIView *paymentView; 16 | @property Ipay *paymentsdk; 17 | @property IpayPayment *payment; 18 | 19 | @end 20 | 21 | @implementation IPay88 22 | 23 | RCT_EXPORT_MODULE(); 24 | - (NSArray *)supportedEvents 25 | { 26 | return @[@"ipay88:success", @"ipay88:failed", @"ipay88:canceled"]; 27 | } 28 | 29 | RCT_EXPORT_METHOD(pay:(NSDictionary *)data) 30 | { 31 | dispatch_async(dispatch_get_main_queue(), ^{ 32 | // RCTLogInfo(@"%@", data); 33 | 34 | // Precreate payment 35 | self.paymentsdk = [[Ipay alloc] init]; 36 | self.payment = [[IpayPayment alloc] init]; 37 | [self.payment setPaymentId:data[@"paymentId"]]; 38 | [self.payment setMerchantKey:data[@"merchantKey"]]; 39 | [self.payment setMerchantCode:data[@"merchantCode"]]; 40 | [self.payment setRefNo:data[@"referenceNo"]]; 41 | [self.payment setAmount:data[@"amount"]]; 42 | [self.payment setCurrency:data[@"currency"]]; 43 | [self.payment setProdDesc:data[@"productDescription"]]; 44 | [self.payment setUserName:data[@"userName"]]; 45 | [self.payment setUserEmail:data[@"userEmail"]]; 46 | [self.payment setUserContact:data[@"userContact"]]; 47 | [self.payment setRemark:data[@"remark"]]; 48 | [self.payment setLang:data[@"utfLang"]]; 49 | [self.payment setCountry:data[@"country"]]; 50 | [self.payment setBackendPostURL:data[@"backendUrl"]]; 51 | 52 | self.paymentsdk.delegate = self; 53 | self.paymentView = [self.paymentsdk checkout:self.payment]; 54 | 55 | UIViewController *ctrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; 56 | [ctrl.view addSubview:self.paymentView]; 57 | }); 58 | } 59 | 60 | 61 | - (void)paymentCancelled:(NSString *)refNo withTransId:(NSString *)transId withAmount:(NSString *)amount withRemark:(NSString *)remark withErrDesc:(NSString *)errDesc { 62 | // Remove the ipay88 webview 63 | [self.paymentView removeFromSuperview]; 64 | 65 | NSDictionary *params = 66 | @{ 67 | @"transactionID": transId, 68 | @"referenceNo": refNo, 69 | @"amount": amount, 70 | @"remark": remark, 71 | @"error": errDesc, 72 | }; 73 | 74 | [self sendEventWithName:@"ipay88:canceled" body:params]; 75 | 76 | RCTLogInfo(@"Payment cancel"); 77 | } 78 | 79 | 80 | - (void)paymentFailed:(NSString *)refNo withTransId:(NSString *)transId withAmount:(NSString *)amount withRemark:(NSString *)remark withErrDesc:(NSString *)errDesc { 81 | // Remove the ipay88 webview 82 | [self.paymentView removeFromSuperview]; 83 | 84 | NSDictionary *params = 85 | @{ 86 | @"transactionID": transId, 87 | @"referenceNo": refNo, 88 | @"amount": amount, 89 | @"remark": remark, 90 | @"error": errDesc, 91 | }; 92 | 93 | [self sendEventWithName:@"ipay88:failed" body:params]; 94 | 95 | RCTLogInfo(@"Payment failed"); 96 | } 97 | 98 | - (void)paymentSuccess:(NSString *)refNo withTransId:(NSString *)transId withAmount:(NSString *)amount withRemark:(NSString *)remark withAuthCode:(NSString *)authCode { 99 | // Remove the ipay88 webview 100 | [self.paymentView removeFromSuperview]; 101 | 102 | NSDictionary *params = 103 | @{ 104 | @"authorizationCode": authCode, 105 | @"transactionID": transId, 106 | @"referenceNo": refNo, 107 | @"amount": amount, 108 | @"remark": remark, 109 | }; 110 | 111 | [self sendEventWithName:@"ipay88:success" body:params]; 112 | 113 | RCTLogInfo(@"Payment success"); 114 | } 115 | 116 | - (void)requerySuccess:(NSString *)refNo withMerchantCode:(NSString *)merchantCode withAmount:(NSString *)amount withResult:(NSString *)result { 117 | RCTLogInfo(@"Requery success"); 118 | } 119 | 120 | - (void)requeryFailed:(NSString *)refNo withMerchantCode:(NSString *)merchantCode withAmount:(NSString *)amount withErrDesc:(NSString *)errDesc { 121 | RCTLogInfo(@"Requery failed"); 122 | } 123 | 124 | 125 | @end 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /android/src/main/java/com/ipay88/IPay88Module.java: -------------------------------------------------------------------------------- 1 | package com.ipay88; 2 | 3 | 4 | import android.content.Intent; 5 | 6 | import androidx.annotation.Nullable; 7 | 8 | import com.facebook.react.bridge.Arguments; 9 | import com.facebook.react.bridge.ReactApplicationContext; 10 | import com.facebook.react.bridge.ReactContext; 11 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 12 | import com.facebook.react.bridge.ReactMethod; 13 | import com.facebook.react.bridge.ReadableMap; 14 | import com.facebook.react.bridge.WritableMap; 15 | import com.facebook.react.modules.core.DeviceEventManagerModule; 16 | import com.ipay.Ipay; 17 | import com.ipay.IpayPayment; 18 | import com.ipay.IpayResultDelegate; 19 | 20 | import java.io.Serializable; 21 | 22 | /** 23 | * Created by yussuf on 2/28/18. 24 | * Forked by Yik Kok on 31/3/2020 25 | */ 26 | 27 | public class IPay88Module extends ReactContextBaseJavaModule { 28 | private static ReactApplicationContext context; 29 | 30 | public IPay88Module(ReactApplicationContext reactContext) { 31 | super(reactContext); 32 | } 33 | 34 | @Override 35 | public String getName() { 36 | return "IPay88"; 37 | } 38 | 39 | @ReactMethod 40 | public void pay(ReadableMap data) { 41 | context = getReactApplicationContext(); 42 | 43 | // Precreate payment 44 | IpayPayment payment = new IpayPayment(); 45 | payment.setMerchantKey (data.getString("merchantKey")); 46 | payment.setMerchantCode (data.getString("merchantCode")); 47 | payment.setPaymentId (data.getString("paymentId")); 48 | payment.setCurrency (data.getString("currency")); 49 | payment.setRefNo (data.getString("referenceNo")); 50 | payment.setAmount (data.getString("amount")); 51 | payment.setProdDesc (data.getString("productDescription")); 52 | payment.setUserName (data.getString("userName")); 53 | payment.setUserEmail (data.getString("userEmail")); 54 | payment.setUserContact (data.getString("userContact")); 55 | payment.setRemark (data.getString("remark")); 56 | payment.setLang (data.getString("utfLang")); 57 | payment.setCountry (data.getString("country")); 58 | payment.setBackendPostURL (data.getString("backendUrl")); 59 | 60 | Intent checkoutIntent = Ipay.getInstance().checkout(payment, getReactApplicationContext(), new ResultDelegate()); 61 | checkoutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 62 | context.startActivity(checkoutIntent); 63 | } 64 | 65 | static public class ResultDelegate implements IpayResultDelegate, Serializable { 66 | public void onPaymentSucceeded (String transId, String refNo, String amount, String remarks, String authCode) 67 | { 68 | WritableMap params = Arguments.createMap(); 69 | params.putString("transactionId", transId); 70 | params.putString("referenceNo", refNo); 71 | params.putString("amount", amount); 72 | params.putString("remark", remarks); 73 | params.putString("authorizationCode", authCode); 74 | sendEvent(context, "ipay88:success", params); 75 | } 76 | 77 | public void onPaymentFailed (String transId, String refNo, String amount, String remarks, String err) 78 | { 79 | WritableMap params = Arguments.createMap(); 80 | params.putString("transactionId", transId); 81 | params.putString("referenceNo", refNo); 82 | params.putString("amount", amount); 83 | params.putString("remark", remarks); 84 | params.putString("error", err); 85 | sendEvent(context, "ipay88:failed", params); 86 | } 87 | 88 | public void onPaymentCanceled (String transId, String refNo, String amount, String remarks, String errDesc) 89 | { 90 | WritableMap params = Arguments.createMap(); 91 | params.putString("transactionId", transId); 92 | params.putString("referenceNo", refNo); 93 | params.putString("amount", amount); 94 | params.putString("remark", remarks); 95 | params.putString("error", errDesc); 96 | sendEvent(context, "ipay88:canceled", params); 97 | } 98 | 99 | public void onRequeryResult (String merchantCode, String refNo, String amount, String result) 100 | { 101 | // No need to implement 102 | } 103 | } 104 | 105 | static void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) { 106 | reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params); 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native ipay88-sdk 2 | 3 | ## Getting started 4 | 5 | `$ npm install ipay88-sdk --save` 6 | 7 | ### Mostly automatic installation 8 | 9 | `$ react-native link ipay88-sdk` 10 | 11 | ### Manual installation 12 | 13 | #### iOS 14 | 15 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]` 16 | 2. Go to `node_modules` ➜ `ipay88-sdk` and add `RNIpay88Sdk.xcodeproj` 17 | 3. In XCode, in the project navigator, select your project. Add `libRNIpay88Sdk.a` to your project's `Build Phases` ➜ `Link Binary With Libraries` 18 | 4. Run your project (`Cmd+R`)< 19 | 20 | #### Android 21 | 22 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java` 23 | 24 | * Add `import com.ipay88.IPay88Package;` to the imports at the top of the file 25 | * Add `new IPay88Package()` to the list returned by the `getPackages()` method 26 | 27 | 2. Append the following lines to `android/settings.gradle`: 28 | ``` 29 | include ':ipay88-sdk' 30 | project(':ipay88-sdk').projectDir = new File(rootProject.projectDir, '../node_modules/ipay88-sdk/android') 31 | ``` 32 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`: 33 | ``` 34 | compile project(':ipay88-sdk') 35 | ``` 36 | 37 | ## Usage 38 | 39 | ```javascript 40 | import React, { Component } from "react"; 41 | import { 42 | Platform, 43 | StyleSheet, 44 | Button, 45 | Text, 46 | View, 47 | Alert, 48 | ToastAndroid 49 | } from "react-native"; 50 | import IPay88, { Pay } from "ipay88-sdk"; 51 | 52 | export default class App extends Component { 53 | successNotify = data => { 54 | if (Platform.OS === "ios") { 55 | const { 56 | transactionId, 57 | referenceNo, 58 | amount, 59 | remark, 60 | authorizationCode 61 | } = data; 62 | 63 | Alert.alert("Message", `Payment authcode is ${authorizationCode}`, { 64 | cancelable: true 65 | }); 66 | } else { 67 | ToastAndroid.show( 68 | `Message: Payment authcode is ${authorizationCode}`, 69 | ToastAndroid.LONG 70 | ); 71 | } 72 | }; 73 | 74 | cancelNotify = data => { 75 | const { transactionId, referenceNo, amount, remark, error } = data; 76 | 77 | if (Platform.OS === "ios") { 78 | Alert.alert("Message", `${error}`, { cancelable: true }); 79 | } else { 80 | ToastAndroid.show(`Message: ${error}`, ToastAndroid.LONG); 81 | } 82 | }; 83 | 84 | failedNotify = data => { 85 | const { transactionId, referenceNo, amount, remark, error } = data; 86 | 87 | if (Platform.OS === "ios") { 88 | Alert.alert("Message", `${error}`, { cancelable: true }); 89 | } else { 90 | ToastAndroid.show(`Message: ${error}`, ToastAndroid.LONG); 91 | } 92 | }; 93 | 94 | pay = () => { 95 | try { 96 | const data = {}; 97 | data.paymentId = "2"; // refer to ipay88 docs 98 | data.merchantKey = "{{ merchantKey }}"; 99 | data.merchantCode = "{{ merchantCode }}"; 100 | data.referenceNo = "1234565"; 101 | data.amount = "1.00"; 102 | data.currency = "MYR"; 103 | data.productDescription = "Payment"; 104 | data.userName = "test"; 105 | data.userEmail = "test@gmail.com"; 106 | data.userContact = "0123456789"; 107 | data.remark = "me"; 108 | data.utfLang = "UTF-8"; 109 | data.country = "MY"; 110 | data.backendUrl = "http://sample.com"; 111 | const errs = Pay(data); 112 | if (Object.keys(errs).length > 0) { 113 | console.log(errs); 114 | } 115 | } catch (e) { 116 | console.log(e); 117 | } 118 | }; 119 | 120 | render() { 121 | return ( 122 | 129 | 134 |