react-native-payengine 1.0.5 → 1.0.6
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.
- package/android/.gradle/5.6.4/executionHistory/executionHistory.bin +0 -0
- package/android/.gradle/5.6.4/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/5.6.4/fileContent/fileContent.lock +0 -0
- package/android/.gradle/5.6.4/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/5.6.4/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/5.6.4/fileHashes/resourceHashesCache.bin +0 -0
- package/android/.gradle/5.6.4/javaCompile/classAnalysis.bin +0 -0
- package/android/.gradle/5.6.4/javaCompile/jarAnalysis.bin +0 -0
- package/android/.gradle/5.6.4/javaCompile/javaCompile.lock +0 -0
- package/android/.gradle/5.6.4/javaCompile/taskHistory.bin +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
- package/android/.idea/compiler.xml +1 -1
- package/android/.idea/gradle.xml +1 -0
- package/android/.idea/misc.xml +1 -1
- package/android/build.gradle +24 -9
- package/android/src/legacy/AndroidManifest.xml +4 -0
- package/android/src/main/java/com/reactnativepayengine/GooglePayModule.java +196 -0
- package/android/src/main/java/com/reactnativepayengine/PayenginePackage.java +1 -0
- package/android/src/main/java/com/reactnativepayengine/collect/VGSCollectModule.java +22 -17
- package/android/src/main/java/com/reactnativepayengine/util/PaymentsUtil.java +113 -0
- package/ios/Payengine.m +18 -1
- package/ios/Payengine.swift +85 -2
- package/ios/Payengine.xcodeproj/project.pbxproj +16 -5
- package/ios/Payengine.xcodeproj/project.xcworkspace/xcuserdata/tringuyen.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/Payengine.xcodeproj/xcuserdata/tringuyen.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +4 -4
- package/ios/Payengine.xcworkspace/xcuserdata/tringuyen.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/lib/commonjs/components/ApplePay/PayEngineApplePay.js +71 -0
- package/lib/commonjs/components/ApplePay/PayEngineApplePay.js.map +1 -0
- package/lib/commonjs/components/ApplePay/index.js +46 -0
- package/lib/commonjs/components/ApplePay/index.js.map +1 -0
- package/lib/commonjs/components/ApplePay/interfaces.js +2 -0
- package/lib/commonjs/components/ApplePay/interfaces.js.map +1 -0
- package/lib/commonjs/components/CreditCardForm/index.js +76 -0
- package/lib/commonjs/components/CreditCardForm/index.js.map +1 -0
- package/lib/commonjs/components/GooglePay/PayEngineGooglePay.js +65 -0
- package/lib/commonjs/components/GooglePay/PayEngineGooglePay.js.map +1 -0
- package/lib/commonjs/components/GooglePay/index.js +40 -0
- package/lib/commonjs/components/GooglePay/index.js.map +1 -0
- package/lib/commonjs/components/GooglePay/interfaces.js +2 -0
- package/lib/commonjs/components/GooglePay/interfaces.js.map +1 -0
- package/lib/commonjs/components/Legacy/CreditCardFormLegacy.js +323 -0
- package/lib/commonjs/components/Legacy/CreditCardFormLegacy.js.map +1 -0
- package/lib/commonjs/components/PayEngine.js.map +1 -1
- package/lib/commonjs/components/SecureFields/VGS/CollectManager.js +3 -8
- package/lib/commonjs/components/SecureFields/VGS/CollectManager.js.map +1 -1
- package/lib/commonjs/index.js +33 -4
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/interfaces/index.js +6 -0
- package/lib/commonjs/interfaces/index.js.map +1 -0
- package/lib/commonjs/utils/index.js +20 -8
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/module/components/ApplePay/PayEngineApplePay.js +58 -0
- package/lib/module/components/ApplePay/PayEngineApplePay.js.map +1 -0
- package/lib/module/components/ApplePay/index.js +35 -0
- package/lib/module/components/ApplePay/index.js.map +1 -0
- package/lib/module/components/ApplePay/interfaces.js +2 -0
- package/lib/module/components/ApplePay/interfaces.js.map +1 -0
- package/lib/module/components/CreditCardForm/index.js +60 -0
- package/lib/module/components/CreditCardForm/index.js.map +1 -0
- package/lib/module/components/GooglePay/PayEngineGooglePay.js +52 -0
- package/lib/module/components/GooglePay/PayEngineGooglePay.js.map +1 -0
- package/lib/module/components/GooglePay/index.js +29 -0
- package/lib/module/components/GooglePay/index.js.map +1 -0
- package/lib/module/components/GooglePay/interfaces.js +2 -0
- package/lib/module/components/GooglePay/interfaces.js.map +1 -0
- package/lib/module/components/Legacy/CreditCardFormLegacy.js +302 -0
- package/lib/module/components/Legacy/CreditCardFormLegacy.js.map +1 -0
- package/lib/module/components/PayEngine.js.map +1 -1
- package/lib/module/components/SecureFields/VGS/CollectManager.js +3 -8
- package/lib/module/components/SecureFields/VGS/CollectManager.js.map +1 -1
- package/lib/module/index.js +6 -5
- package/lib/module/index.js.map +1 -1
- package/lib/module/interfaces/index.js +2 -0
- package/lib/module/interfaces/index.js.map +1 -0
- package/lib/module/utils/index.js +14 -8
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/components/ApplePay/PayEngineApplePay.d.ts +12 -0
- package/lib/typescript/components/ApplePay/index.d.ts +7 -0
- package/lib/typescript/components/ApplePay/interfaces.d.ts +20 -0
- package/lib/typescript/components/CreditCardForm/index.d.ts +3 -0
- package/lib/typescript/components/GooglePay/PayEngineGooglePay.d.ts +10 -0
- package/lib/typescript/components/GooglePay/index.d.ts +7 -0
- package/lib/typescript/components/GooglePay/interfaces.d.ts +38 -0
- package/lib/typescript/components/Legacy/CreditCardFormLegacy.d.ts +4 -0
- package/lib/typescript/components/PayEngine.d.ts +1 -1
- package/lib/typescript/components/SecureFields/VGS/CollectManager.d.ts +1 -1
- package/lib/typescript/index.d.ts +6 -2
- package/lib/typescript/interfaces/index.d.ts +33 -0
- package/lib/typescript/utils/index.d.ts +5 -6
- package/package.json +6 -5
- package/react-native-payengine.podspec +2 -2
- package/src/components/ApplePay/PayEngineApplePay.ts +61 -0
- package/src/components/ApplePay/index.ts +32 -0
- package/src/components/ApplePay/interfaces.ts +25 -0
- package/src/components/CreditCardForm/index.tsx +43 -0
- package/src/components/GooglePay/PayEngineGooglePay.ts +48 -0
- package/src/components/GooglePay/index.ts +39 -0
- package/src/components/GooglePay/interfaces.ts +42 -0
- package/src/components/Legacy/CreditCardFormLegacy.tsx +292 -0
- package/src/components/LoadingIndicator.tsx +28 -0
- package/src/components/PayEngine.tsx +121 -0
- package/src/components/SecureFields/VGS/CVCField.tsx +21 -0
- package/src/components/SecureFields/VGS/CardHolderNameField.tsx +21 -0
- package/src/components/SecureFields/VGS/CardNumberField.tsx +21 -0
- package/src/components/SecureFields/VGS/CollectManager.tsx +74 -0
- package/src/components/SecureFields/VGS/ExpDateField.tsx +21 -0
- package/src/components/SecureFields/VGS/TextField.tsx +27 -0
- package/src/components/SecureFields/VGS/ZipCodeField.tsx +21 -0
- package/src/components/SecureFields/index.ts +17 -0
- package/src/index.tsx +37 -0
- package/src/interfaces/index.ts +38 -0
- package/src/utils/index.ts +107 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import GooglePay from '.';
|
|
2
|
+
import type { IPayEngineConfig, MobilePaymentConfig, PaymentRequest } from '../../interfaces';
|
|
3
|
+
import { createHttpClient } from '../../utils';
|
|
4
|
+
import type { GooglePayRequestData, IGooglePay } from './interfaces';
|
|
5
|
+
|
|
6
|
+
export class PayEngineGooglePay implements IGooglePay {
|
|
7
|
+
|
|
8
|
+
private googlePay: GooglePay;
|
|
9
|
+
private payEngineConfig: IPayEngineConfig;
|
|
10
|
+
private config?: MobilePaymentConfig;
|
|
11
|
+
|
|
12
|
+
constructor(payEngineConfig: IPayEngineConfig) {
|
|
13
|
+
this.payEngineConfig = payEngineConfig;
|
|
14
|
+
this.googlePay = new GooglePay()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public async canMakePayments(merchantId: string) {
|
|
18
|
+
const client = createHttpClient(this.payEngineConfig);
|
|
19
|
+
const { data } = await client.get(`/api/mobile-payment/config?merchant_id=${merchantId}`)
|
|
20
|
+
this.config = data.data
|
|
21
|
+
await this.googlePay.setProduction(Boolean(this.config!.google_pay.production))
|
|
22
|
+
return await this.googlePay.canMakePayments(this.config!.google_pay.cardPaymentMethod.allowedCardNetworks, this.config!.google_pay.cardPaymentMethod.allowedCardAuthMethods)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public async start(paymentConfig: PaymentRequest) {
|
|
26
|
+
if (!this.config) {
|
|
27
|
+
throw new Error('You must call `canMakePayments` first')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const payload: GooglePayRequestData = {
|
|
31
|
+
cardPaymentMethod: this.config!.google_pay.cardPaymentMethod,
|
|
32
|
+
transaction: {
|
|
33
|
+
totalPrice: String(paymentConfig.amount),
|
|
34
|
+
totalPriceStatus: 'FINAL',
|
|
35
|
+
currencyCode: paymentConfig.currencyCode ?? this.config!.currency,
|
|
36
|
+
countryCode: paymentConfig.countryCode ?? this.config!.country
|
|
37
|
+
},
|
|
38
|
+
merchantName: this.config!.google_pay.merchantName
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const result = await this.googlePay.start(payload);
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(result)
|
|
44
|
+
} catch {
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NativeModules, Platform } from 'react-native';
|
|
2
|
+
import type {
|
|
3
|
+
GooglePayAllowedCardAuthMethods,
|
|
4
|
+
GooglePayAllowedCardNetworks,
|
|
5
|
+
GooglePayRequestData,
|
|
6
|
+
IGooglePay,
|
|
7
|
+
} from './interfaces';
|
|
8
|
+
|
|
9
|
+
const { GooglePay: RNGooglePay } = NativeModules;
|
|
10
|
+
|
|
11
|
+
export default class GooglePay implements IGooglePay {
|
|
12
|
+
constructor() {
|
|
13
|
+
if (Platform.OS === 'android') {
|
|
14
|
+
if (!RNGooglePay) {
|
|
15
|
+
throw new Error('GooglePay is not defined');
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
throw new Error('Google Pay is not supported (Android only)');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public async setProduction(isProduction: boolean) {
|
|
23
|
+
return RNGooglePay.setEnvironment(isProduction ? 1 : 3);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async canMakePayments(
|
|
27
|
+
allowedCardNetworks: GooglePayAllowedCardNetworks,
|
|
28
|
+
allowedCardAuthMethods: GooglePayAllowedCardAuthMethods
|
|
29
|
+
) {
|
|
30
|
+
return await RNGooglePay.isReadyToPay(
|
|
31
|
+
allowedCardNetworks,
|
|
32
|
+
allowedCardAuthMethods
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public async start(requestData: GooglePayRequestData) {
|
|
37
|
+
return await RNGooglePay.requestPayment(requestData);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface IGooglePay {
|
|
2
|
+
canMakePayments: (...args: any) => Promise<boolean>
|
|
3
|
+
start: (...args: any) => Promise<any>
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
type NetworkType = 'AMEX' | 'DISCOVER' | 'JCB' | 'MASTERCARD' | 'VISA';
|
|
7
|
+
type MethodType = 'PAN_ONLY' | 'CRYPTOGRAM_3DS';
|
|
8
|
+
|
|
9
|
+
export type GooglePayAllowedCardNetworks = NetworkType[];
|
|
10
|
+
|
|
11
|
+
export type GooglePayAllowedCardAuthMethods = MethodType[];
|
|
12
|
+
|
|
13
|
+
export type TokenizationSpecificationType = 'PAYMENT_GATEWAY' | 'DIRECT';
|
|
14
|
+
|
|
15
|
+
export interface GooglePayRequestData {
|
|
16
|
+
production?: boolean,
|
|
17
|
+
cardPaymentMethod: {
|
|
18
|
+
tokenizationSpecification: {
|
|
19
|
+
type: TokenizationSpecificationType;
|
|
20
|
+
/** only with type: PAYMENT_GATEWAY */
|
|
21
|
+
gateway?: string;
|
|
22
|
+
/** only with type: PAYMENT_GATEWAY */
|
|
23
|
+
gatewayMerchantId?: string;
|
|
24
|
+
/** only with gateway: stripe */
|
|
25
|
+
stripe?: {
|
|
26
|
+
publishableKey: string;
|
|
27
|
+
version: string;
|
|
28
|
+
};
|
|
29
|
+
/** only with type: DIRECT */
|
|
30
|
+
publicKey?: string;
|
|
31
|
+
};
|
|
32
|
+
allowedCardNetworks: GooglePayAllowedCardNetworks;
|
|
33
|
+
allowedCardAuthMethods: GooglePayAllowedCardAuthMethods;
|
|
34
|
+
};
|
|
35
|
+
transaction: {
|
|
36
|
+
totalPrice: string;
|
|
37
|
+
totalPriceStatus: string;
|
|
38
|
+
currencyCode: string;
|
|
39
|
+
countryCode: string;
|
|
40
|
+
};
|
|
41
|
+
merchantName: string;
|
|
42
|
+
}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Text, View, StyleSheet, ActivityIndicator } from 'react-native';
|
|
3
|
+
import eventEmitter from 'events';
|
|
4
|
+
import { WebView } from 'react-native-webview';
|
|
5
|
+
import { createHttpClient, getHttpHeaders } from '../../utils/index';
|
|
6
|
+
import type { CreditCardFormMethods, CreditCardFormProps } from '../../interfaces/index';
|
|
7
|
+
import LoadingIndicator from '../LoadingIndicator';
|
|
8
|
+
|
|
9
|
+
const emitter = new eventEmitter();
|
|
10
|
+
|
|
11
|
+
class CardError extends Error {
|
|
12
|
+
public data: any = null;
|
|
13
|
+
|
|
14
|
+
constructor(data: any) {
|
|
15
|
+
super('Failed to create card')
|
|
16
|
+
this.data = data
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const CreditCardFormLegacy = React.forwardRef<CreditCardFormMethods, CreditCardFormProps>((props, ref) => {
|
|
21
|
+
const webviewRef = React.createRef<WebView>()
|
|
22
|
+
|
|
23
|
+
const [loading, setLoading] = React.useState(true)
|
|
24
|
+
const [error, setError] = React.useState("")
|
|
25
|
+
const [html, setHtml] = React.useState("")
|
|
26
|
+
const [webviewResponse, setWebviewResponse] = React.useState<any>()
|
|
27
|
+
|
|
28
|
+
React.useImperativeHandle(ref, () => ({
|
|
29
|
+
createCard: async (merchantId?: string) => {
|
|
30
|
+
setWebviewResponse(null)
|
|
31
|
+
const headers = getHttpHeaders(props.config)
|
|
32
|
+
const script = `
|
|
33
|
+
submit(${merchantId ? '"' + merchantId + '"' : 'null'}, '${headers.Authorization}');
|
|
34
|
+
`
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
console.log({ emitter })
|
|
37
|
+
emitter.once('pe.card_response', (data, isError) => {
|
|
38
|
+
if (isError) {
|
|
39
|
+
reject(new CardError(data))
|
|
40
|
+
} else {
|
|
41
|
+
resolve(data)
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
webviewRef.current?.injectJavaScript(script)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
},
|
|
48
|
+
}), [props.config, webviewRef, webviewResponse]);
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
React.useEffect(() => {
|
|
53
|
+
const configure = async () => {
|
|
54
|
+
setLoading(true)
|
|
55
|
+
try {
|
|
56
|
+
const http = createHttpClient(props.config)
|
|
57
|
+
const resp = await http.get('/api/setting/secure-fields')
|
|
58
|
+
const { vault, environment, cname, vgs_satellite_port } = resp.data.data
|
|
59
|
+
|
|
60
|
+
setHtml(createVGSCollectFormHTML(Boolean(props.showZipCode), vault, environment, cname, vgs_satellite_port))
|
|
61
|
+
} catch (e: any) {
|
|
62
|
+
console.log({ error: e })
|
|
63
|
+
setError(e.message)
|
|
64
|
+
} finally {
|
|
65
|
+
setLoading(false)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
configure()
|
|
70
|
+
}, [])
|
|
71
|
+
|
|
72
|
+
const onMessage = (payload: any) => {
|
|
73
|
+
let dataPayload;
|
|
74
|
+
try {
|
|
75
|
+
dataPayload = JSON.parse(payload.nativeEvent.data);
|
|
76
|
+
} catch (e) { }
|
|
77
|
+
|
|
78
|
+
if (dataPayload) {
|
|
79
|
+
console.log({ dataPayload })
|
|
80
|
+
switch (dataPayload.type) {
|
|
81
|
+
case 'PayEngineCardResponse':
|
|
82
|
+
emitter.emit('pe.card_response', dataPayload.data, dataPayload.isError)
|
|
83
|
+
break
|
|
84
|
+
default:
|
|
85
|
+
break
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
if (loading || !html) {
|
|
91
|
+
return <ActivityIndicator />
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<>
|
|
96
|
+
<View style={[styles.container, { height: props.showZipCode ? 270 : 215 }]}>
|
|
97
|
+
<WebView
|
|
98
|
+
ref={webviewRef}
|
|
99
|
+
originWhitelist={['*']}
|
|
100
|
+
source={{
|
|
101
|
+
html: html,
|
|
102
|
+
}}
|
|
103
|
+
scalesPageToFit={false}
|
|
104
|
+
style={{ backgroundColor: 'transparent' }}
|
|
105
|
+
bounces={false}
|
|
106
|
+
scrollEnabled={false}
|
|
107
|
+
renderLoading={LoadingIndicator}
|
|
108
|
+
startInLoadingState={true}
|
|
109
|
+
onMessage={onMessage}
|
|
110
|
+
/>
|
|
111
|
+
</View>
|
|
112
|
+
{error.length ? <Text>{error}</Text> : <></>}
|
|
113
|
+
</>
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
export default CreditCardFormLegacy;
|
|
118
|
+
|
|
119
|
+
const styles = StyleSheet.create({
|
|
120
|
+
container: {
|
|
121
|
+
width: '100%',
|
|
122
|
+
padding: 20,
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const createVGSCollectFormHTML = (showZipCode: boolean, vault: string, environment: string, cname: string, vgs_satellite_port: string) => `
|
|
127
|
+
<!DOCTYPE html>
|
|
128
|
+
<html lang="en">
|
|
129
|
+
<head>
|
|
130
|
+
<meta charset="UTF-8">
|
|
131
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
132
|
+
<title>Credit Card Form</title>
|
|
133
|
+
<script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/2.16.0/vgs-collect.js"></script>
|
|
134
|
+
|
|
135
|
+
<style>
|
|
136
|
+
html, body {
|
|
137
|
+
margin: 0;
|
|
138
|
+
padding: 0;
|
|
139
|
+
background: transparent;
|
|
140
|
+
}
|
|
141
|
+
.row {
|
|
142
|
+
display: flex;
|
|
143
|
+
gap: 10px;
|
|
144
|
+
}
|
|
145
|
+
.col {
|
|
146
|
+
flex: 1;
|
|
147
|
+
}
|
|
148
|
+
.form-group {
|
|
149
|
+
margin-bottom: 10px;
|
|
150
|
+
}
|
|
151
|
+
.form-field {
|
|
152
|
+
display: block;
|
|
153
|
+
width: 100%;
|
|
154
|
+
height: 50px;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.form-field iframe {
|
|
158
|
+
border: 0 none transparent;
|
|
159
|
+
height: 100%;
|
|
160
|
+
vertical-align: middle;
|
|
161
|
+
width: 100%;
|
|
162
|
+
}
|
|
163
|
+
</style>
|
|
164
|
+
</head>
|
|
165
|
+
<body>
|
|
166
|
+
<form id="cc-form">
|
|
167
|
+
<div class="form-group">
|
|
168
|
+
<span id="card_holder" class="form-field">
|
|
169
|
+
</span>
|
|
170
|
+
</div>
|
|
171
|
+
<div class="form-group">
|
|
172
|
+
<span id="card_number" class="form-field"></span>
|
|
173
|
+
</div>
|
|
174
|
+
<div class="row">
|
|
175
|
+
<div class="form-group">
|
|
176
|
+
<span id="card_exp" class="form-field"></span>
|
|
177
|
+
</div>
|
|
178
|
+
<div class="form-group">
|
|
179
|
+
<span id="card_cvc" class="form-field"></span>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
${showZipCode ? `<div class="form-group">
|
|
183
|
+
<span id="address_zip" class="form-field"></span>
|
|
184
|
+
</div>` : ''}
|
|
185
|
+
</form>
|
|
186
|
+
|
|
187
|
+
<script>
|
|
188
|
+
const css = {
|
|
189
|
+
color: '#000',
|
|
190
|
+
border: '#CCC 1px solid',
|
|
191
|
+
'border-radius': '5px',
|
|
192
|
+
'text-transform': 'uppercase',
|
|
193
|
+
padding: '5px 10px',
|
|
194
|
+
'box-sizing': 'border-box',
|
|
195
|
+
'font-size': '1em',
|
|
196
|
+
'caret-color': 'transparent',
|
|
197
|
+
'&:focus': {
|
|
198
|
+
'border-color': '#999',
|
|
199
|
+
},
|
|
200
|
+
'&.invalid.touched': {
|
|
201
|
+
'border-color': 'red',
|
|
202
|
+
},
|
|
203
|
+
'&.valid': {
|
|
204
|
+
'border-color': '#CCC',
|
|
205
|
+
},
|
|
206
|
+
}
|
|
207
|
+
const form = VGSCollect.create('${vault}', '${environment}', function(state) {});
|
|
208
|
+
alert('${cname}')
|
|
209
|
+
form.useCname('${cname}')
|
|
210
|
+
// form.connectSatellite(parseInt(${vgs_satellite_port}) ?? 9098)
|
|
211
|
+
form.field('#card_holder', {
|
|
212
|
+
type: 'text',
|
|
213
|
+
name: 'card_holder',
|
|
214
|
+
placeholder: 'Card holder name',
|
|
215
|
+
validations: ['required'],
|
|
216
|
+
css
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const cardElement = form.field('#card_number', {
|
|
220
|
+
type: 'card-number',
|
|
221
|
+
name: 'card_number',
|
|
222
|
+
placeholder: 'Card number',
|
|
223
|
+
validations: ['required', 'validCardNumber'],
|
|
224
|
+
showCardIcon: true,
|
|
225
|
+
css
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const cvcElement = form.field('#card_cvc', {
|
|
229
|
+
type: 'card-security-code',
|
|
230
|
+
name: 'card_cvc',
|
|
231
|
+
placeholder: 'CVC',
|
|
232
|
+
validations: ['required', 'validCardSecurityCode'],
|
|
233
|
+
showCardIcon: true,
|
|
234
|
+
css
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
cardElement.setCVCDependency(cvcElement);
|
|
238
|
+
|
|
239
|
+
form.field('#card_exp', {
|
|
240
|
+
type: 'card-expiration-date',
|
|
241
|
+
name: 'card_exp',
|
|
242
|
+
placeholder: 'Exp date',
|
|
243
|
+
validations: ['required', 'validCardExpirationDate'],
|
|
244
|
+
css
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
${showZipCode ? `
|
|
248
|
+
form.field('#address_zip', {
|
|
249
|
+
type: 'text',
|
|
250
|
+
name: 'address_zip',
|
|
251
|
+
placeholder: 'Zip code',
|
|
252
|
+
maxLength: 7,
|
|
253
|
+
validations: ['required', 'postal_code/us,ca'],
|
|
254
|
+
css
|
|
255
|
+
});
|
|
256
|
+
` : ''}
|
|
257
|
+
|
|
258
|
+
const sendNative = (data, isError) => {
|
|
259
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
260
|
+
type: 'PayEngineCardResponse',
|
|
261
|
+
data: data,
|
|
262
|
+
isError: isError
|
|
263
|
+
}))
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function submit(merchantId, authHeader) {
|
|
267
|
+
form.submit('/api/cards', {
|
|
268
|
+
method: 'POST',
|
|
269
|
+
data: {
|
|
270
|
+
brand: form.state.card_number.cardType,
|
|
271
|
+
last_4: form.state.card_number.last4,
|
|
272
|
+
bin: form.state.card_number.bin,
|
|
273
|
+
pci_vault_provider: 'vgs',
|
|
274
|
+
merchant_id: merchantId,
|
|
275
|
+
},
|
|
276
|
+
headers: {
|
|
277
|
+
Authorization: authHeader
|
|
278
|
+
}
|
|
279
|
+
}, (status, data) => {
|
|
280
|
+
if (status === 200) {
|
|
281
|
+
sendNative(data, false)
|
|
282
|
+
} else {
|
|
283
|
+
sendNative({ data, status }, true)
|
|
284
|
+
}
|
|
285
|
+
}, error => {
|
|
286
|
+
sendNative(error, true)
|
|
287
|
+
})
|
|
288
|
+
return true
|
|
289
|
+
}
|
|
290
|
+
</script>
|
|
291
|
+
</body>
|
|
292
|
+
</html>`;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { StyleSheet, ActivityIndicator, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
const LoadingIndicator = () => {
|
|
5
|
+
return (
|
|
6
|
+
<View style={styles.container}>
|
|
7
|
+
<ActivityIndicator size="small" color="#0000ff" />
|
|
8
|
+
</View>
|
|
9
|
+
);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default LoadingIndicator;
|
|
13
|
+
|
|
14
|
+
const styles = StyleSheet.create({
|
|
15
|
+
container: {
|
|
16
|
+
alignItems: 'center',
|
|
17
|
+
justifyContent: 'center',
|
|
18
|
+
position: 'absolute',
|
|
19
|
+
top: 0,
|
|
20
|
+
left: 0,
|
|
21
|
+
height: '100%',
|
|
22
|
+
width: '100%'
|
|
23
|
+
},
|
|
24
|
+
activityIndicatorStyle: {
|
|
25
|
+
// flex: 1,
|
|
26
|
+
// justifyContent: "center",
|
|
27
|
+
},
|
|
28
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Platform, StyleProp, StyleSheet, Text, View, ViewStyle } from 'react-native';
|
|
3
|
+
import { WebView } from 'react-native-webview';
|
|
4
|
+
import { getScriptURL, debuggingScript } from '../utils';
|
|
5
|
+
import LoadingIndicator from './LoadingIndicator';
|
|
6
|
+
import type { IPayEngineConfig } from '../interfaces/index';
|
|
7
|
+
|
|
8
|
+
interface IProps {
|
|
9
|
+
config: IPayEngineConfig
|
|
10
|
+
type: string
|
|
11
|
+
merchantId?: string
|
|
12
|
+
hash?: string
|
|
13
|
+
events: {
|
|
14
|
+
[key: string]: (eventData: any) => void
|
|
15
|
+
}
|
|
16
|
+
style?: StyleProp<ViewStyle>
|
|
17
|
+
[key: string]: any
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getHtmlTag = (props: IProps) => {
|
|
21
|
+
const allowedProps = Object.keys(props).filter(x => !['config', 'events', 'style'].includes(x))
|
|
22
|
+
return `<pay-engine id="component"
|
|
23
|
+
style="z-index: 100"
|
|
24
|
+
${allowedProps.map((propName: string) => `${propName}="${props[propName]}"`).join(' ')}
|
|
25
|
+
></pay-engine>`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const generateHTML = (scriptURL: string, props: IProps) => {
|
|
29
|
+
return `<!DOCTYPE html>
|
|
30
|
+
<html>
|
|
31
|
+
<head>
|
|
32
|
+
<title>PayEngine Elements</title>
|
|
33
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
34
|
+
<script src="${scriptURL}" async defer type="text/javascript"></script>
|
|
35
|
+
</head>
|
|
36
|
+
<body>
|
|
37
|
+
${getHtmlTag(props)}
|
|
38
|
+
<script>
|
|
39
|
+
setInterval(function() {
|
|
40
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
41
|
+
type: 'PayEngine-height',
|
|
42
|
+
height: document.body.scrollHeight
|
|
43
|
+
}))
|
|
44
|
+
}, 500);
|
|
45
|
+
</script>
|
|
46
|
+
</body>
|
|
47
|
+
</html>`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const PayEngine = (props: IProps) => {
|
|
51
|
+
|
|
52
|
+
const [scriptURL] = React.useState(getScriptURL(props.config))
|
|
53
|
+
const [height, setHeight] = React.useState(30)
|
|
54
|
+
|
|
55
|
+
const html = generateHTML(scriptURL, props)
|
|
56
|
+
|
|
57
|
+
const onMessage = (payload: any) => {
|
|
58
|
+
const isDebug = props.config.logLevel! > 0
|
|
59
|
+
let dataPayload;
|
|
60
|
+
try {
|
|
61
|
+
dataPayload = JSON.parse(payload.nativeEvent.data);
|
|
62
|
+
} catch (e) { }
|
|
63
|
+
|
|
64
|
+
if (dataPayload) {
|
|
65
|
+
switch (dataPayload.type) {
|
|
66
|
+
case 'Console':
|
|
67
|
+
if (isDebug) {
|
|
68
|
+
console.info(`[Console] ${JSON.stringify(dataPayload.data)}`);
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
case 'PayEngine':
|
|
72
|
+
const { type, detail } = dataPayload.event
|
|
73
|
+
if (props.events?.[type]) {
|
|
74
|
+
props.events?.[type]?.(detail)
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
case 'PayEngine-height':
|
|
78
|
+
setHeight(dataPayload.height)
|
|
79
|
+
break;
|
|
80
|
+
default:
|
|
81
|
+
if (isDebug) {
|
|
82
|
+
console.log(dataPayload)
|
|
83
|
+
}
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return <View style={[{ flex: 1, height: height }, props.style]}>
|
|
90
|
+
<View style={styles.yellowBox}>
|
|
91
|
+
<Text>Script URL: {scriptURL}</Text>
|
|
92
|
+
</View>
|
|
93
|
+
<View style={styles.yellowBox}>
|
|
94
|
+
<Text>{getHtmlTag(props)}</Text>
|
|
95
|
+
</View>
|
|
96
|
+
<WebView
|
|
97
|
+
originWhitelist={['*']}
|
|
98
|
+
source={{ html: html, baseUrl: '' }}
|
|
99
|
+
// source={{ uri: 'https://google.com' }}
|
|
100
|
+
applicationNameForUserAgent={`PayEngine-RN/${Platform.OS}`}
|
|
101
|
+
injectedJavaScript={debuggingScript}
|
|
102
|
+
renderLoading={LoadingIndicator}
|
|
103
|
+
startInLoadingState={true}
|
|
104
|
+
onMessage={onMessage}
|
|
105
|
+
/>
|
|
106
|
+
</View>
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const styles = StyleSheet.create({
|
|
110
|
+
yellowBox: {
|
|
111
|
+
marginVertical: 5,
|
|
112
|
+
marginHorizontal: 10,
|
|
113
|
+
padding: 10,
|
|
114
|
+
backgroundColor: 'yellow',
|
|
115
|
+
borderWidth: 1,
|
|
116
|
+
borderColor: 'yellow'
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
export default PayEngine
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { PureComponent } from 'react';
|
|
3
|
+
import { requireNativeComponent, StyleProp, ViewStyle } from 'react-native';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
interface CVCFieldProps {
|
|
8
|
+
placeholder?: string
|
|
9
|
+
style?: StyleProp<ViewStyle>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class CVCField extends PureComponent<CVCFieldProps> {
|
|
13
|
+
|
|
14
|
+
render() {
|
|
15
|
+
return <RTCCVCField {...this.props} />
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const RTCCVCField = requireNativeComponent('VGSCVCField');
|
|
20
|
+
|
|
21
|
+
export default CVCField;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { PureComponent } from 'react';
|
|
3
|
+
import { requireNativeComponent, StyleProp, ViewStyle } from 'react-native';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
interface CardHolderNameFieldProps {
|
|
8
|
+
placeholder?: string
|
|
9
|
+
style?: StyleProp<ViewStyle>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class CardHolderNameField extends PureComponent<CardHolderNameFieldProps> {
|
|
13
|
+
|
|
14
|
+
render() {
|
|
15
|
+
return <RTCCardHolderNameField {...this.props} />
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const RTCCardHolderNameField = requireNativeComponent('VGSCardHolderNameField');
|
|
20
|
+
|
|
21
|
+
export default CardHolderNameField;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { PureComponent } from 'react';
|
|
3
|
+
import { requireNativeComponent, StyleProp, ViewStyle } from 'react-native';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
interface CardNumberFieldProps {
|
|
8
|
+
placeholder?: string
|
|
9
|
+
style?: StyleProp<ViewStyle>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
class CardNumberField extends PureComponent<CardNumberFieldProps> {
|
|
13
|
+
|
|
14
|
+
render() {
|
|
15
|
+
return <RTCCardNumberField {...this.props} />
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const RTCCardNumberField = requireNativeComponent('VGSCardNumberField');
|
|
20
|
+
|
|
21
|
+
export default CardNumberField;
|