skipcash-reactnative 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,361 @@
1
+ package com.skipcashreactnative;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import android.net.Uri;
5
+ import android.util.Log;
6
+ import android.content.Context;
7
+ import android.content.Intent;
8
+
9
+
10
+ import org.json.JSONException;
11
+ import org.json.JSONObject;
12
+
13
+ import android.util.Log;
14
+
15
+ import okhttp3.OkHttpClient;
16
+ import okhttp3.RequestBody;
17
+ import okhttp3.OkHttpClient;
18
+ import okhttp3.OkHttpClient;
19
+ import okhttp3.Response;
20
+ import okhttp3.Request;
21
+ import okhttp3.MediaType;
22
+
23
+ import java.io.IOException;
24
+
25
+ import java.util.concurrent.ExecutorService;
26
+ import java.util.concurrent.Executors;
27
+ import java.util.concurrent.Future;
28
+
29
+ import com.facebook.react.modules.core.DeviceEventManagerModule;
30
+ import com.facebook.react.bridge.ReactApplicationContext;
31
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
32
+ import com.facebook.react.bridge.ReactMethod;
33
+ import com.facebook.react.bridge.Promise;
34
+
35
+ public class SkipcashReactnativeModule extends ReactContextBaseJavaModule {
36
+
37
+ private static final String NAME = "SkipcashReactnative";
38
+
39
+ private final ExecutorService executor = Executors.newSingleThreadExecutor();
40
+ private Context context;
41
+
42
+ private ReactApplicationContext reactAppContext;
43
+ private static ReactApplicationContext reactAppContextStatic;
44
+
45
+ public SkipcashReactnativeModule(ReactApplicationContext reactContext) {
46
+ super(reactContext);
47
+ this.context = reactContext.getApplicationContext();
48
+ this.reactAppContext = reactContext;
49
+ this.reactAppContextStatic = reactContext;
50
+ }
51
+
52
+ @Override
53
+ public String getName() {
54
+ return NAME;
55
+ }
56
+
57
+ public class GetPayUrlParams {
58
+ String paymentData;
59
+ String createPaymentEndpoint;
60
+ String returnURL;
61
+ String authroizationHeader;
62
+
63
+
64
+ public GetPayUrlParams(String paymentData, String createPaymentEndpoint, String returnURL, String authroizationHeader) {
65
+ this.paymentData = paymentData;
66
+ this.createPaymentEndpoint = createPaymentEndpoint;
67
+ this.returnURL = returnURL;
68
+ this.authroizationHeader = authroizationHeader;
69
+ }
70
+ }
71
+
72
+ private class GetPayUrlTask implements Runnable {
73
+
74
+ private String authroizationHeader;
75
+ private String createPaymentEndpoint;
76
+ private String returnURL;
77
+ private String paymentData;
78
+
79
+ // background task | runs network request to grap a new pay url from server endpoint
80
+ GetPayUrlTask(GetPayUrlParams params) {
81
+ this.authroizationHeader = params.authroizationHeader;
82
+ this.createPaymentEndpoint = params.createPaymentEndpoint;
83
+ this.returnURL = params.returnURL;
84
+ this.paymentData = params.paymentData;
85
+ }
86
+
87
+ @Override
88
+ public void run() {
89
+ try {
90
+ JSONObject paymentDataObject = new JSONObject(paymentData);
91
+ JSONObject requiredPaymentData = new JSONObject();
92
+
93
+ requiredPaymentData.put("Amount", paymentDataObject.get("amount"));
94
+ requiredPaymentData.put("FirstName", paymentDataObject.get("firstName"));
95
+ requiredPaymentData.put("LastName", paymentDataObject.get("lastName"));
96
+ requiredPaymentData.put("Phone", paymentDataObject.get("phone"));
97
+ requiredPaymentData.put("Email", paymentDataObject.get("email"));
98
+ requiredPaymentData.put("ReturnUrl", returnURL);
99
+ requiredPaymentData.put("TransactionId", paymentDataObject.get("transactionId"));
100
+ requiredPaymentData.put("WebhookUrl", paymentDataObject.get("webhookUrl"));
101
+ requiredPaymentData.put("Custom1", paymentDataObject.get("custom1"));
102
+ requiredPaymentData.put("Custom2", paymentDataObject.get("custom2"));
103
+ requiredPaymentData.put("Custom3", paymentDataObject.get("custom3"));
104
+ requiredPaymentData.put("Custom4", paymentDataObject.get("custom4"));
105
+ requiredPaymentData.put("Custom5", paymentDataObject.get("custom5"));
106
+ requiredPaymentData.put("Custom6", paymentDataObject.get("custom6"));
107
+ requiredPaymentData.put("Custom7", paymentDataObject.get("custom7"));
108
+ requiredPaymentData.put("Custom8", paymentDataObject.get("custom8"));
109
+ requiredPaymentData.put("Custom9", paymentDataObject.get("custom9"));
110
+ requiredPaymentData.put("Custom10", paymentDataObject.get("custom10"));
111
+ requiredPaymentData.put("Description", paymentDataObject.get("description"));
112
+ requiredPaymentData.put("Subject", paymentDataObject.get("subject"));
113
+
114
+
115
+ OkHttpClient client = new OkHttpClient();
116
+ Request request;
117
+
118
+ RequestBody paymentBody = RequestBody.create(requiredPaymentData.toString(), MediaType.get("application/json; charset=utf-8"));
119
+
120
+ if (authroizationHeader.length() > 0) {
121
+ request = new Request.Builder()
122
+ .url(createPaymentEndpoint)
123
+ .post(paymentBody)
124
+ .addHeader("Authorization", authroizationHeader)
125
+ .build();
126
+ } else {
127
+ request = new Request.Builder()
128
+ .url(createPaymentEndpoint)
129
+ .post(paymentBody)
130
+ .build();
131
+ }
132
+
133
+ try {
134
+ Response response = client.newCall(request).execute();
135
+ String result = response.body().string();
136
+ handleResponse(result);
137
+ } catch (IOException e) {
138
+ e.printStackTrace();
139
+ Log.d("showPaymentModal", "" + e.getMessage());
140
+ handleResponse(e.getMessage());
141
+ }
142
+ } catch (JSONException e) {
143
+ e.printStackTrace();
144
+ Log.d("showPaymentModal", "" + e.getMessage());
145
+
146
+ handleResponse(e.getMessage());
147
+ }
148
+
149
+ }
150
+
151
+ private void handleResponse(final String result) {
152
+ new android.os.Handler(context.getMainLooper()).post(() -> {
153
+
154
+ try {
155
+ int returnCode = 0;
156
+
157
+ JSONObject paymentResponseDetails = new JSONObject();
158
+ JSONObject resultObj;
159
+ String resultObjString = "";
160
+
161
+ try{
162
+ paymentResponseDetails = new JSONObject(result);
163
+ resultObjString = paymentResponseDetails.getString("resultObj");
164
+
165
+ resultObj = new JSONObject(resultObjString);
166
+ returnCode = paymentResponseDetails.getInt("returnCode");
167
+
168
+ if (returnCode == 200) {
169
+
170
+ JSONObject paymentDataObject = new JSONObject(paymentData);
171
+
172
+ Intent intent = new Intent(context, ModalActivity.class);
173
+
174
+ /*
175
+ (transactionId) passed to webview modal to return it back alongside
176
+ the payment response if the payment was canceled by the user (by pressing back button)
177
+ */
178
+ if (paymentDataObject.get("transactionId").toString().length() > 0){
179
+ String transaction_id = (String) paymentDataObject.get("transactionId");
180
+ intent.putExtra("transactionId", transaction_id);
181
+ }else{
182
+ intent.putExtra("transactionId", "");
183
+ }
184
+
185
+ intent.putExtra("returnURL", returnURL);
186
+ intent.putExtra("url", resultObj.getString("payUrl"));
187
+ intent.putExtra("headerBackgroundColour", paymentDataObject.get("headerBackgroundColour").toString());
188
+ intent.putExtra("headerTitle", paymentDataObject.get("paymentModalTitle").toString());
189
+ intent.putExtra("headerTitleColour", paymentDataObject.get("headerTitleColour").toString());
190
+ intent.putExtra("cancelColour", paymentDataObject.get("cancelColour").toString());
191
+
192
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
193
+
194
+ context.startActivity(intent);
195
+
196
+ } else {
197
+ Log.d("showPaymentModal", " new PayUrl request failed! " + returnCode);
198
+ JSONObject returnURLObject = new JSONObject();
199
+ JSONObject paymentDataObject = new JSONObject(paymentData);
200
+
201
+ returnURLObject.put("id", "");
202
+ returnURLObject.put("statusId", "4");
203
+ returnURLObject.put("status", "new payment request failed!");
204
+ returnURLObject.put("transId", (String) paymentDataObject.get("transactionId"));
205
+ returnURLObject.put("custom1", (String) paymentDataObject.get("custom1"));
206
+
207
+ if (reactAppContext.hasActiveCatalystInstance()) {
208
+ reactAppContext
209
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
210
+ .emit("responseScPaymentData", returnURLObject.toString());
211
+ }
212
+ return;
213
+ }
214
+
215
+ }catch (JSONException e){
216
+ Log.e("showPaymentModal", "resultObj is not a valid JSON object: " + e.getMessage());
217
+ JSONObject returnURLObject = new JSONObject();
218
+ JSONObject paymentDataObject = new JSONObject(paymentData);
219
+
220
+ try{
221
+ paymentResponseDetails = new JSONObject(result);
222
+ } catch (JSONException eee){
223
+ try {
224
+
225
+ returnURLObject.put("id", "");
226
+ returnURLObject.put("statusId", "4");
227
+ returnURLObject.put("status", "failed to request new payment!");
228
+ returnURLObject.put("transId", (String) paymentDataObject.get("transactionId"));
229
+ returnURLObject.put("custom1", (String) paymentDataObject.get("custom1"));
230
+
231
+ if (reactAppContext.hasActiveCatalystInstance()) {
232
+ reactAppContext
233
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
234
+ .emit("responseScPaymentData", returnURLObject.toString());
235
+ }
236
+
237
+ return;
238
+ } catch (JSONException err){
239
+ Log.e("showPaymentModal", e.getMessage());
240
+ }
241
+ }
242
+
243
+ try {
244
+
245
+ returnURLObject.put("id", "");
246
+ returnURLObject.put("statusId", "4");
247
+ returnURLObject.put("status", paymentResponseDetails.getString("errorMessage"));
248
+ returnURLObject.put("transId", (String) paymentDataObject.get("transactionId"));
249
+ returnURLObject.put("custom1", (String) paymentDataObject.get("custom1"));
250
+
251
+ if (reactAppContext.hasActiveCatalystInstance()) {
252
+ reactAppContext
253
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
254
+ .emit("responseScPaymentData", returnURLObject.toString());
255
+ }
256
+ return;
257
+ } catch (JSONException err){
258
+ Log.e("showPaymentModal", e.getMessage());
259
+ }
260
+ }
261
+ } catch (Exception e) {
262
+ e.printStackTrace();
263
+ JSONObject returnURLObject = new JSONObject();
264
+ JSONObject paymentDataObject = null;
265
+ try {
266
+ paymentDataObject = new JSONObject(paymentData);
267
+ returnURLObject.put("id", "");
268
+ returnURLObject.put("statusId", "4");
269
+ returnURLObject.put("status", "new payment request failed!");
270
+ returnURLObject.put("transId", (String) paymentDataObject.get("transactionId"));
271
+ returnURLObject.put("custom1", (String) paymentDataObject.get("custom1"));
272
+
273
+ if (reactAppContext.hasActiveCatalystInstance()) {
274
+ reactAppContext
275
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
276
+ .emit("responseScPaymentData", returnURLObject.toString());
277
+ }
278
+ return;
279
+ } catch (JSONException ex) {
280
+ }
281
+ }
282
+ });
283
+ }
284
+ }
285
+
286
+ // gets a new payment url from server endpoint by running background task
287
+
288
+
289
+ private void getPayURL(String paymentData, String createPaymentEndpoint, String returnURL, String authroizationHeader){
290
+
291
+ GetPayUrlParams params = new GetPayUrlParams(
292
+ paymentData,
293
+ createPaymentEndpoint,
294
+ returnURL,
295
+ authroizationHeader
296
+ );
297
+
298
+ executor.execute(new GetPayUrlTask(params));
299
+ }
300
+
301
+
302
+ // handle onclose from the webview modal without proceeding with the payment
303
+
304
+ public static void handleOnWebViewClose(String transactionId){
305
+ JSONObject returnURLObject = new JSONObject();
306
+
307
+ try {
308
+ returnURLObject.put("id", "");
309
+ returnURLObject.put("statusId", "4");
310
+ returnURLObject.put("status", "Failed");
311
+ returnURLObject.put("transId", transactionId); // you must generate it (unique)
312
+ returnURLObject.put("custom1", "");
313
+ if (reactAppContextStatic.hasActiveCatalystInstance()) {
314
+ reactAppContextStatic
315
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
316
+ .emit("responseScPaymentData", returnURLObject.toString());
317
+ }
318
+ } catch (JSONException e) {
319
+ e.printStackTrace();
320
+ }
321
+ }
322
+
323
+
324
+ // handle the data received from the modal which holds the webview
325
+ public static void handleNativeWebViewData(String id, String statusId, String status, String transId, String custom1) {
326
+ JSONObject returnURLObject = new JSONObject();
327
+
328
+ try {
329
+
330
+ Log.d("showPaymentModal", id + " | " + statusId);
331
+ returnURLObject.put("id", id);
332
+ returnURLObject.put("statusId", statusId);
333
+ returnURLObject.put("status", status);
334
+ returnURLObject.put("transId", transId);
335
+ returnURLObject.put("custom1", custom1);
336
+
337
+ if (reactAppContextStatic.hasActiveCatalystInstance()) {
338
+ reactAppContextStatic
339
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
340
+ .emit("responseScPaymentData", returnURLObject.toString());
341
+ }
342
+ } catch (JSONException e) {
343
+ e.printStackTrace();
344
+ }
345
+ }
346
+
347
+ @ReactMethod
348
+ public void initiatePaymentModel(String paymentData){
349
+ String createPaymentEndpoint, returnURL, authorizationHeader;
350
+ try{
351
+ JSONObject data = new JSONObject(paymentData);
352
+ paymentData = data.getString("paymentData");
353
+ createPaymentEndpoint = data.getString("createPaymentEndpoint");
354
+ returnURL = data.getString("returnURL");
355
+ authorizationHeader = data.getString("authorizationHeader");
356
+ getPayURL(paymentData, createPaymentEndpoint, returnURL, authorizationHeader);
357
+ }catch (JSONException e) {
358
+ Log.d("showPaymentModal", e.getMessage());
359
+ }
360
+ }
361
+ }
@@ -0,0 +1,18 @@
1
+ package com.skipcashreactnative
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+
9
+ class SkipcashReactnativePackage : ReactPackage {
10
+
11
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
12
+ return listOf(SkipcashReactnativeModule(reactContext))
13
+ }
14
+
15
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
16
+ return emptyList()
17
+ }
18
+ }
@@ -0,0 +1,59 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+ android:layout_width="match_parent"
4
+ android:layout_height="match_parent"
5
+ android:orientation="vertical"
6
+ android:padding="0dp"
7
+ android:background="@android:color/white">
8
+
9
+ <!-- Header Layout -->
10
+ <RelativeLayout
11
+ android:id="@+id/header"
12
+ android:layout_width="match_parent"
13
+ android:layout_height="56dp"
14
+ android:background="@android:color/white"
15
+ android:padding="8dp">
16
+
17
+ <!-- Back Button -->
18
+ <TextView
19
+ android:id="@+id/cancel_payment_btn"
20
+ android:layout_width="wrap_content"
21
+ android:layout_height="wrap_content"
22
+ android:layout_alignParentStart="true"
23
+ android:layout_centerVertical="true"
24
+ android:text="Cancel"
25
+ android:textColor="@android:color/black"
26
+ android:textSize="14sp"
27
+ android:padding="8dp"
28
+ android:textStyle="bold"
29
+ android:clickable="true"
30
+ android:focusable="true" />
31
+
32
+ <!-- Title Text -->
33
+ <TextView
34
+ android:id="@+id/header_title"
35
+ android:layout_width="wrap_content"
36
+ android:layout_height="wrap_content"
37
+ android:layout_centerInParent="true"
38
+ android:text="Title"
39
+ android:textColor="@android:color/black"
40
+ android:textSize="18sp"
41
+ android:textStyle="bold" />
42
+ </RelativeLayout>
43
+
44
+ <!-- WebView -->
45
+ <WebView
46
+ android:id="@+id/webView"
47
+ android:layout_width="match_parent"
48
+ android:layout_height="match_parent"
49
+ android:layout_below="@id/header" />
50
+
51
+ <ProgressBar
52
+ android:id="@+id/loadingWebview"
53
+ android:layout_width="wrap_content"
54
+ android:layout_height="wrap_content"
55
+ android:layout_centerInParent="true"
56
+ android:indeterminate="true"
57
+ android:visibility="gone" />
58
+
59
+ </RelativeLayout>
@@ -0,0 +1,45 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="pCT-GY-hiB">
3
+ <device id="retina6_12" orientation="portrait" appearance="light"/>
4
+ <dependencies>
5
+ <deployment identifier="iOS"/>
6
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
7
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
8
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
9
+ </dependencies>
10
+ <scenes>
11
+ <!--SetupVC-->
12
+ <scene sceneID="s0d-6b-0kx">
13
+ <objects>
14
+ <viewController storyboardIdentifier="SetupVC" useStoryboardIdentifierAsRestorationIdentifier="YES" id="Y6W-OH-hqX" customClass="SetupVC" customModule="SkipCashSDK" customModuleProvider="target" sceneMemberID="viewController">
15
+ <view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
16
+ <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
17
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
18
+ <viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
19
+ </view>
20
+ <navigationItem key="navigationItem" id="jRA-Ju-Ip0"/>
21
+ </viewController>
22
+ <placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
23
+ </objects>
24
+ <point key="canvasLocation" x="947.32824427480909" y="3.5211267605633805"/>
25
+ </scene>
26
+ <!--Navigation Controller-->
27
+ <scene sceneID="5h7-UF-lBd">
28
+ <objects>
29
+ <navigationController automaticallyAdjustsScrollViewInsets="NO" id="pCT-GY-hiB" sceneMemberID="viewController">
30
+ <toolbarItems/>
31
+ <navigationBar key="navigationBar" contentMode="scaleToFill" id="1YA-it-F3R">
32
+ <rect key="frame" x="0.0" y="59" width="393" height="44"/>
33
+ <autoresizingMask key="autoresizingMask"/>
34
+ </navigationBar>
35
+ <nil name="viewControllers"/>
36
+ <connections>
37
+ <segue destination="Y6W-OH-hqX" kind="relationship" relationship="rootViewController" id="AWB-Sa-GV8"/>
38
+ </connections>
39
+ </navigationController>
40
+ <placeholder placeholderIdentifier="IBFirstResponder" id="dYS-jC-6PH" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
41
+ </objects>
42
+ <point key="canvasLocation" x="20.610687022900763" y="3.5211267605633805"/>
43
+ </scene>
44
+ </scenes>
45
+ </document>
@@ -0,0 +1,2 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTViewManager.h>
@@ -0,0 +1,18 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface RCT_EXTERN_MODULE(SkipcashReactnative, NSObject)
4
+
5
+ RCT_EXTERN_METHOD(isWalletHasCards:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
6
+
7
+ RCT_EXTERN_METHOD(setupNewCard)
8
+
9
+ RCT_EXTERN_METHOD( initiateApplePay: (NSString*)jsonString)
10
+
11
+ RCT_EXTERN_METHOD( initiatePaymentModel: (NSString*)jsonString)
12
+
13
+ + (BOOL)requiresMainQueueSetup
14
+ {
15
+ return NO;
16
+ }
17
+
18
+ @end