react-native-bootpay-api 4.1.4 → 4.1.5

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.
@@ -1,130 +0,0 @@
1
-
2
-
3
- import base64 from 'react-native-base64'
4
- import DeviceInfo from 'react-native-device-info';
5
-
6
- // import CryptoJS from 'crypto-js';
7
- import { NativeModules } from 'react-native'
8
- var Aes = NativeModules.Aes
9
-
10
-
11
- const userTrace = async (applicationId, userId, phone, email, gender, birth, area) => {
12
- try {
13
- const payload = {
14
- "id": userId,
15
- "ver": DeviceInfo.getVersion(),
16
- "application_id": applicationId,
17
- "phone": phone,
18
- "email": email,
19
- "gender": gender,
20
- "birth": birth,
21
- "area": area
22
- };
23
-
24
- var key = getRandomKey(32);
25
- var iv = getRandomKey(16);
26
-
27
- try {
28
- const data = await Aes.encrypt(JSON.stringify(payload), stringToHex(key), stringToHex(iv)).then(cipher => cipher);
29
-
30
- const response = await fetch(
31
- 'https://analytics.bootpay.co.kr/login',
32
- {
33
- method: 'POST',
34
- headers: {
35
- Accept: 'application/json',
36
- 'Content-Type': 'application/json'
37
- },
38
- body: JSON.stringify({
39
- data: data,
40
- session_key: await getSessionKey(key, iv)
41
- })
42
- }
43
- );
44
- const json = await response.json();
45
- return json;
46
- } catch (e) {
47
- console.log(e);
48
- }
49
- } catch (error) {
50
- console.error(error);
51
- }
52
- }
53
-
54
- const pageTrace = async (applicationId, url, pageType, items) => {
55
- try {
56
- const payload = {
57
- "application_id": applicationId,
58
- "url": url,
59
- "page_type": pageType,
60
- "items": items,
61
- "referer": ''
62
- };
63
-
64
- var key = getRandomKey(32);
65
- var iv = getRandomKey(16);
66
-
67
- try {
68
- const data = await Aes.encrypt(JSON.stringify(payload), stringToHex(key), stringToHex(iv)).then(cipher => cipher);
69
-
70
- const response = await fetch(
71
- 'https://analytics.bootpay.co.kr/call',
72
- {
73
- method: 'POST',
74
- headers: {
75
- Accept: 'application/json',
76
- 'Content-Type': 'application/json'
77
- },
78
- body: JSON.stringify({
79
- data: data,
80
- session_key: await getSessionKey(key, iv)
81
- })
82
- }
83
- );
84
- const json = await response.json();
85
- return json;
86
- } catch (e) {
87
- console.log(e);
88
- }
89
- } catch (error) {
90
- console.error(error);
91
- }
92
- }
93
-
94
- const stringToHex = (str) => {
95
- var hex = ''
96
- for (var i = 0, l = str.length; i < l; i++) {
97
- hex += str.charCodeAt(i).toString(16)
98
- }
99
- return hex
100
- }
101
-
102
- const getRandomKey = (length) => {
103
- var text = '';
104
- var keys = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ';
105
-
106
- for (var i = 0; i < length; i++)
107
- text += keys.charAt(Math.floor(Math.random() * keys.length));
108
-
109
- return text;
110
- }
111
-
112
-
113
- const getSessionKey = async (key, iv) => {
114
- const keyValue = base64.encode(key);
115
- const ivValue = base64.encode(iv);
116
-
117
- return `${keyValue}##${ivValue}`;
118
- }
119
-
120
- const strEncode = async (str, key, iv) => {
121
- return await Aes.encrypt(str, key, iv).then(cipher => {
122
- Aes.hmac256(cipher, key).then(hash => {
123
- console.log('HMAC', hash)
124
- return hash;
125
- })
126
- })
127
-
128
- }
129
-
130
- export { userTrace, pageTrace }
@@ -1,440 +0,0 @@
1
-
2
-
3
- import React, { Component, useRef, useEffect } from 'react';
4
- import { SafeAreaView, Modal, Platform, TouchableOpacity, Image, StyleSheet, BackHandler} from 'react-native';
5
- import WebView from 'react-native-webview-bootpay';
6
- import {debounce} from 'lodash';
7
- import UserInfo from './UserInfo'
8
-
9
- export class BootpayWebView extends Component {
10
-
11
-
12
- webView = useRef<WebView>(null);
13
-
14
- _VERSION = "4.1.2";
15
- _DEBUG = false;
16
- _payload = {};
17
-
18
-
19
- state = {
20
- visibility: false,
21
- script: '',
22
- firstLoad: false
23
- }
24
-
25
- async componentWillUnmount() {
26
- this.setState(
27
- {
28
- visibility: false,
29
- firstLoad: false,
30
- showCloseButton: false
31
- }
32
- )
33
- UserInfo.setBootpayLastTime(Date.now());
34
- }
35
-
36
- componentDidMount() {
37
- this.closeDismiss = debounce(this.closeDismiss, 30);
38
- }
39
-
40
-
41
- render() {
42
- return <Modal
43
- animationType={'slide'}
44
- transparent={false}
45
- onRequestClose={()=> {
46
- this.closeDismiss();
47
- // console.log(1234);
48
- // this.dismiss();
49
- }}
50
- visible={this.state.visibility}>
51
- <SafeAreaView style={{ flex: 1 }}>
52
- {
53
- this.state.showCloseButton &&
54
- <TouchableOpacity
55
- onPress={() => {
56
- var cancelData = {
57
- action: 'BootpayCancel',
58
- message: '사용자에 의해 취소되었습니다'
59
- }
60
- var closeData = {
61
- action: 'BootpayClose',
62
- message: '결제창이 닫혔습니다'
63
- }
64
-
65
- if(this.props.onCancel != undefined) this.props.onCancel(cancelData);
66
- if(this.props.onClose != undefined) this.props.onClose();
67
-
68
- this.setState({visibility: false})
69
- } }>
70
- <Image
71
- style={[styles.overlay]}
72
- source={require('../images/close.png')} />
73
- </TouchableOpacity>
74
- }
75
- <WebView
76
- ref={(wv) => this.webView = wv}
77
- useWebKit={true}
78
- originWhitelist={['*']}
79
- source={{
80
- uri: 'https://webview.bootpay.co.kr/4.0.6/'
81
- }}
82
- injectedJavaScript={this.state.script}
83
- javaScriptEnabled={true}
84
- javaScriptCanOpenWindowsAutomatically={true}
85
- // scalesPageToFit={true}
86
- onMessage={this.onMessage}
87
- onShouldStartLoadWithRequest={this.onShouldStartLoadWithRequest}
88
- />
89
- </SafeAreaView>
90
-
91
- </Modal>
92
- }
93
-
94
- requestPayment = async (payload, items, user, extra) => {
95
- this.bootpayRequest(payload, items, user, extra, "requestPayment");
96
- }
97
-
98
- requestSubscription = async (payload, items, user, extra) => {
99
- this.bootpayRequest(payload, items, user, extra, "requestSubscription");
100
- }
101
-
102
- requestAuthentication = async (payload, items, user, extra) => {
103
- this.bootpayRequest(payload, items, user, extra, "requestAuthentication");
104
- }
105
-
106
- bootpayRequest = async (payload, items, user, extra, requestMethod) => {
107
-
108
- payload.application_id = Platform.OS == 'ios' ? this.props.ios_application_id : this.props.android_application_id;
109
- payload.items = items;
110
- payload.user = user;
111
- payload.extra = {
112
- card_quota: extra.card_quota ?? "",
113
- seller_name: extra.seller_name ?? "",
114
- delivery_day: extra.delivery_day ?? 1, //배송일자
115
- locale: extra.locale ?? "ko",
116
- offer_period: extra.offer_period ?? "" , //결제창 제공기간에 해당하는 string 값, 지원하는 PG만 적용됨
117
- disp_cash_result: extra.disp_cash_result ?? true, // 현금영수증 보일지 말지.. 가상계좌 KCP 옵션
118
- deposit_expiration: extra.deposit_expiration ?? "", //가상계좌 입금 만료일자 설정, yyyy-MM-dd
119
- app_scheme: extra.app_scheme ?? "", //ios의 경우 카드사 앱 호출 후 되돌아오기 위한 앱 스키마명
120
- use_card_point: extra.use_card_point ?? true, //카드 포인트 사용 여부 (토스만 가능)
121
- direct_card: extra.direct_card ?? "", //해당 카드로 바로 결제창 (토스만 가능)
122
- use_order_id: extra.use_order_id ?? false, //가맹점 order_id로 PG로 전송
123
- international_card_only: extra.international_card_only ?? false, //해외 결제카드 선택 여부 (토스만 가능)
124
- // phone_carrier: 'SKT', // ['SKT', 'KT', 'LGT'] 중 택 1
125
- direct_app_card: extra.direct_app_card ?? false, //카드사앱으로 direct 호출
126
- direct_samsungpay: extra.direct_samsungpay ?? false, //삼성페이 바로 띄우기
127
- test_deposit: extra.test_deposit ?? false, //가상계좌 모의 입금
128
- enable_error_webhook: extra.enable_error_webhook ?? false, //결제 오류시 Feedback URL로 webhook
129
- separately_confirmed: extra.separately_confirmed ?? true, // confirm 이벤트를 호출할지 말지, false일 경우 자동승인
130
- confirm_only_rest_api: extra.confirm_only_rest_api ?? false, // REST API로만 승인 처리
131
- open_type: extra.open_type ?? 'redirect', // [그대로 지정] 페이지 오픈 type [iframe, popup, redirect] 중 택 1, 앱에서는 redriect가 default
132
- use_bootpay_inapp_sdk: extra.use_bootpay_inapp_sdk ?? true, // [그대로 지정] native app에서는 redirect를 완성도있게 지원하기 위한 옵션
133
- redirect_url: extra.redirect_url ?? 'https://api.bootpay.co.kr/v2', // [그대로 지정] open_type이 redirect일 경우 페이지 이동할 URL ( 오류 및 결제 완료 모두 수신 가능 )
134
- display_success_result: extra.display_success_result ?? false, // 결제 완료되면 부트페이가 제공하는 완료창으로 보여주기 ( open_type이 iframe, popup 일때만 가능 )
135
- display_error_result: extra.display_error_result ?? true, // 결제가 실패하면 부트페이가 제공하는 실패창으로 보여주기 ( open_type이 iframe, popup 일때만 가능 )
136
- show_close_button: extra.show_close_button ?? false, // x 닫기 버튼 삽입 (닫기버튼이 없는 PG사를 위한 옵션)
137
- use_welcomepayment: extra.use_welcomepayment ?? false, // 웰컴에서 스마트로 재판모듈 사용시 true
138
- };
139
-
140
-
141
- this._payload = payload;
142
-
143
-
144
- //visibility가 true가 되면 webview onLoaded가 실행됨
145
- this.setState(
146
- {
147
- visibility: true,
148
- script: `
149
- ${await this.getMountJavascript()}
150
- ${this.generateScript(payload, requestMethod)}
151
- `,
152
- firstLoad: false,
153
- showCloseButton: extra.show_close_button || false
154
- }
155
- )
156
-
157
- UserInfo.updateInfo();
158
- }
159
-
160
- // debounceClose = () => {
161
- // // deboun
162
- // console.log('debounceClose');
163
- // _.debounce(this.closeDismiss, 30);
164
- // }
165
-
166
- closeDismiss = () => {
167
- if(this.props.onClose != undefined) this.props.onClose();
168
- this.dismiss();
169
- }
170
-
171
-
172
- dismiss = () => {
173
- this.setState(
174
- ({ visibility }) => ({
175
- visibility: false
176
- })
177
- )
178
- // this.removePaymentWindow();
179
- }
180
-
181
-
182
- getMountJavascript = async () => {
183
- return `
184
- ${this.getSDKVersion()}
185
- ${this.getEnvironmentMode()}
186
- ${this.getBootpayPlatform()}
187
- ${this.close()}
188
- ${await this.getAnalyticsData()}
189
- `;
190
- }
191
-
192
-
193
- generateScript= (payload, requestMethod) => {
194
- const script = "Bootpay." + requestMethod +
195
- `(${JSON.stringify(payload)})` +
196
- ".then( function (res) {" +
197
- this.confirm() +
198
- this.issued() +
199
- this.done() +
200
- "}, function (res) {" +
201
- this.error() +
202
- this.cancel() +
203
- "}); void(0);";
204
-
205
- return script;
206
-
207
- // return this.generateScript;
208
- }
209
-
210
- onMessage = ({ nativeEvent }) => {
211
- console.log(`onMessage: ${nativeEvent}, ${JSON.stringify(nativeEvent)}`);
212
-
213
- if (nativeEvent == undefined) return;
214
-
215
- const res = JSON.parse(JSON.stringify(nativeEvent));
216
-
217
-
218
- if(res.data == 'close') {
219
- this.closeDismiss();
220
- // if(this.props.onClose == undefined) return;
221
- // var json = {
222
- // action: 'BootpayClose',
223
- // message: '결제창이 닫혔습니다'
224
- // }
225
- // this.props.onClose();
226
- // this.dismiss();
227
- return;
228
- }
229
-
230
-
231
- const data = JSON.parse(res.data);
232
- // console.log(`redirect: ${JSON.stringify(data)}`);
233
-
234
- redirect = false;
235
- show_success = false;
236
- show_error = false;
237
- if(this._payload != undefined && this._payload.extra != undefined) {
238
- if(this._payload.extra.open_type == 'redirect') {
239
- redirect = true;
240
- }
241
- if(this._payload.extra.display_error_result == true) {
242
- show_error = true;
243
- }
244
- if(this._payload.extra.display_success_result == 'redirect') {
245
- show_success = true;
246
- }
247
-
248
- }
249
-
250
- if(redirect == true) {
251
- switch (data.event) {
252
- case 'cancel':
253
- if(this.props.onCancel != undefined) this.props.onCancel(data);
254
- this.closeDismiss();
255
- break;
256
- case 'error':
257
- if(this.props.onError != undefined) this.props.onError(data);
258
- if(show_error == false) {
259
- this.closeDismiss();
260
- }
261
- break;
262
- case 'issued':
263
- if(this.props.onIssued != undefined) this.props.onIssued(data);
264
- if(show_success == false) {
265
- this.closeDismiss();
266
- }
267
- break;
268
- case 'confirm':
269
- if(this.props.onConfirm != undefined) this.props.onConfirm(data);
270
- break;
271
- case 'done':
272
- if(this.props.onDone != undefined) this.props.onDone(data);
273
- if(show_success == false) {
274
- this.closeDismiss();
275
- }
276
- break;
277
- case 'close':
278
- this.closeDismiss();
279
- break;
280
- }
281
- } else {
282
- switch (data.event) {
283
- case 'cancel':
284
- if(this.props.onCancel != undefined) this.props.onCancel(data);
285
- break;
286
- case 'error':
287
- if(this.props.onError != undefined) this.props.onError(data);
288
- break;
289
- case 'issued':
290
- if(this.props.onIssued != undefined) this.props.onIssued(data);
291
- break;
292
- case 'confirm':
293
- if(this.props.onConfirm != undefined) this.props.onConfirm(data);
294
- break;
295
- case 'done':
296
- if(this.props.onDone != undefined) this.props.onDone(data);
297
- break;
298
- case 'close':
299
- this.closeDismiss();
300
- break;
301
- }
302
- }
303
- }
304
-
305
- onShouldStartLoadWithRequest = (url) => {
306
- return true;
307
- }
308
-
309
- getSDKVersion = () => {
310
- if(Platform.OS == 'ios') {
311
- return "Bootpay.setVersion('" + this._VERSION + "', 'ios_react_native')";
312
- // return "Bootpay.setDevice('IOS');";
313
- } else if(Platform.OS == 'android'){
314
- return "Bootpay.setVersion('" + this._VERSION + "', 'android_react_native')";
315
- // return "Bootpay.setDevice('ANDROID');";
316
- }
317
- }
318
-
319
- getEnvironmentMode = () => {
320
- if(this._DEBUG) {
321
- return "Bootpay.setEnvironmentMode('development');";
322
-
323
- }
324
- return "";
325
- }
326
-
327
- getBootpayPlatform = () => {
328
- if(Platform.OS == 'ios') {
329
- return "Bootpay.setDevice('IOS');";
330
- } else if(Platform.OS == 'android'){
331
- return "Bootpay.setDevice('ANDROID');";
332
- }
333
- }
334
-
335
- // setPayScript = () => {
336
- // const fullScript = this.generateScript(this.state.script);
337
- // this.injectJavaScript(fullScript);
338
- // if(this.state.showCloseButton == true) {
339
- // if(this.webView == null || this.webView == undefined) return;
340
- // this.webView.showCloseButton();
341
- // }
342
- // }
343
-
344
- transactionConfirm = () => {
345
- const script = "Bootpay.confirm()"
346
- +
347
- ".then( function (res) {" +
348
- this.confirm() +
349
- this.issued() +
350
- this.done() +
351
- "}, function (res) {" +
352
- this.error() +
353
- this.cancel() +
354
- "})";
355
-
356
- this.callJavaScript(script);
357
- }
358
-
359
- removePaymentWindow = () => {
360
- this.dismiss();
361
- // this.callJavaScript(`
362
- // Bootpay.removePaymentWindow();
363
- // `);
364
- }
365
-
366
- callJavaScript = (script) => {
367
- if(this.webView == null || this.webView == undefined || this.webView == false) return;
368
-
369
- // console.log('callJavascript: ' + script);
370
-
371
- this.webView.injectJavaScript(`
372
- setTimeout(function() { ${script} }, 30);
373
- `);
374
-
375
- // this.webView.injectJavaScript(`
376
- // javascript:(function(){${script} })()
377
- // `);
378
-
379
-
380
- // this.webView.evalu
381
- }
382
-
383
- getAnalyticsData = async () => {
384
- const uuid = await UserInfo.getBootpayUUID();
385
- // const bootpaySK = await UserInfo.getBootpaySK();
386
- const bootLastTime = await UserInfo.getBootpayLastTime();
387
-
388
-
389
- const elaspedTime = Date.now() - bootLastTime;
390
- return `window.Bootpay.$analytics.setAnalyticsData({uuid:'${uuid}', time:${elaspedTime}});`;
391
- // this.callJavaScript(`window.BootPay.setAnalyticsData({uuid:'${uuid}',sk:'${bootpaySK}',sk_time:${bootLastTime},time:${elaspedTime}});`);
392
- }
393
-
394
- confirm = () => {
395
- return "if (res.event === 'confirm') { window.BootpayRNWebView.postMessage( JSON.stringify(res) ); }";
396
- }
397
-
398
- done = () => {
399
- return "else if (res.event === 'done') { window.BootpayRNWebView.postMessage( JSON.stringify(res) ); }";
400
- }
401
-
402
- issued = () => {
403
- return "else if (res.event === 'issued') { window.BootpayRNWebView.postMessage( JSON.stringify(res) ); }";
404
- }
405
-
406
- error = () => {
407
- return "if (res.event === 'error') { window.BootpayRNWebView.postMessage( JSON.stringify(res) ); }";
408
- }
409
-
410
- cancel = () => {
411
- return "else if (res.event === 'cancel') { window.BootpayRNWebView.postMessage( JSON.stringify(res) ); }";
412
- }
413
-
414
- close = () => {
415
- return "document.addEventListener('bootpayclose', function (e) { window.BootpayRNWebView.postMessage('close'); });";
416
- }
417
- }
418
-
419
-
420
- var styles = StyleSheet.create({
421
- container: {
422
- flex: 1,
423
- justifyContent: 'center',
424
- alignItems: 'center',
425
- backgroundColor: '#F5FCFF',
426
- },
427
- welcome: {
428
- fontSize: 20,
429
- textAlign: 'center',
430
- margin: 10,
431
- },
432
- // Flex to fill, position absolute,
433
- // Fixed left/top, and the width set to the window width
434
- overlay: {
435
- width: 25,
436
- height: 25,
437
- right: 5,
438
- alignSelf: 'flex-end'
439
- }
440
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"UserInfo.d.ts","sourceRoot":"","sources":["UserInfo.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlC,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,SAAS;IAC3C,MAAM,CAAC,cAAc,QAAS,MAAM,cAAc,GAAG,sBAYpD;IAED,MAAM,CAAC,cAAc,QAAS,MAAM,OAAO,GAAG,sBAW7C;IAED,MAAM,CAAC,cAAc,yBAGpB;IAED,MAAM,CAAC,YAAY,yBAElB;IAED,MAAM,CAAC,YAAY,QAAS,MAAM,sBAEjC;IAED,MAAM,CAAC,YAAY,SAAU,MAAM,QAAQ,MAAM,sBAEhD;IAED,MAAM,CAAC,kBAAkB,yBAExB;IAED,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM;IAIrC,MAAM,CAAC,gBAAgB;IAIvB,MAAM,CAAC,gBAAgB,QAAS,MAAM,sBAErC;IAED,MAAM,CAAC,UAAU,sBAWhB;CACJ"}
package/src/UserInfo.js DELETED
@@ -1,67 +0,0 @@
1
- import { Component } from 'react';
2
- import DeviceInfo from 'react-native-device-info';
3
- import SInfo from 'react-native-sensitive-info';
4
- export default class UserInfo extends Component {
5
- static getBootpayInfo = (key, defaultVal) => {
6
- return new Promise((resolve, reject) => {
7
- SInfo.getItem(key, {
8
- sharedPreferencesName: 'bootpaySharedPrefs',
9
- keychainService: 'bootpayKeychain'
10
- }).then((res) => {
11
- res == undefined ? resolve(defaultVal) : resolve(res);
12
- resolve(res);
13
- }).catch((error) => {
14
- reject(error);
15
- });
16
- });
17
- };
18
- static setBootpayInfo = (key, val) => {
19
- return new Promise((resolve, reject) => {
20
- SInfo.setItem(String(key), String(val), {
21
- sharedPreferencesName: 'bootpaySharedPrefs',
22
- keychainService: 'bootpayKeychain'
23
- }).then((res) => {
24
- resolve(res);
25
- }).catch((error) => {
26
- reject(error);
27
- });
28
- });
29
- };
30
- static getBootpayUUID = () => {
31
- let uuid = DeviceInfo.getUniqueId();
32
- return UserInfo.setBootpayInfo('uuid', uuid);
33
- };
34
- static getBootpaySK = () => {
35
- return UserInfo.getBootpayInfo('bootpay_sk', '');
36
- };
37
- static setBootpaySK = (val) => {
38
- return UserInfo.setBootpayInfo('bootpay_sk', val);
39
- };
40
- static newBootpaySK = (uuid, time) => {
41
- return UserInfo.setBootpaySK(`${uuid}_${time}`);
42
- };
43
- static getBootpayLastTime = async () => {
44
- return await UserInfo.getBootpayInfo('bootpay_last_time', 0);
45
- };
46
- static setBootpayLastTime(val) {
47
- return UserInfo.setBootpayInfo('bootpay_last_time', val);
48
- }
49
- static getBootpayUserId() {
50
- return UserInfo.getBootpayInfo('bootpay_user_id', '');
51
- }
52
- static setBootpayUserId = (val) => {
53
- return UserInfo.setBootpayInfo('bootpay_user_id', val);
54
- };
55
- static updateInfo = async () => {
56
- const uuid = await UserInfo.getBootpayUUID();
57
- const bootpaySK = await UserInfo.getBootpaySK();
58
- const lastTime = await UserInfo.getBootpayLastTime();
59
- let current = Date.now();
60
- if (bootpaySK == '')
61
- await UserInfo.newBootpaySK(uuid, current);
62
- const isExpired = current - lastTime > 30 * 60 * 1000;
63
- if (isExpired)
64
- await UserInfo.newBootpaySK(uuid, current);
65
- await UserInfo.setBootpayLastTime(current);
66
- };
67
- }