@netappsng/react-native-pay 0.1.0
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/LICENSE +20 -0
- package/Netappspay.podspec +22 -0
- package/README.md +190 -0
- package/android/build.gradle +68 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/netappspay/NetappspayModule.kt +170 -0
- package/android/src/main/java/com/netappspay/NetappspayPackage.kt +31 -0
- package/ios/Netappspay-Bridging-Header.h +3 -0
- package/ios/Netappspay.h +6 -0
- package/ios/Netappspay.mm +67 -0
- package/ios/NetappspayBridge.swift +199 -0
- package/lib/module/NativeNetappspay.js +5 -0
- package/lib/module/NativeNetappspay.js.map +1 -0
- package/lib/module/index.js +95 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeNetappspay.d.ts +9 -0
- package/lib/typescript/src/NativeNetappspay.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +88 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +143 -0
- package/src/NativeNetappspay.ts +9 -0
- package/src/index.tsx +202 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
import NetAppsPaySDK
|
|
4
|
+
|
|
5
|
+
@objc public class NetappspayBridge: NSObject, PaymentSDKDelegate {
|
|
6
|
+
|
|
7
|
+
private var onSuccess: (([String: Any]) -> Void)?
|
|
8
|
+
private var onFailed: (([String: Any]) -> Void)?
|
|
9
|
+
private var onCancel: (() -> Void)?
|
|
10
|
+
private var onReady: (() -> Void)?
|
|
11
|
+
|
|
12
|
+
@objc public func present(
|
|
13
|
+
config configDict: NSDictionary,
|
|
14
|
+
onSuccess: @escaping ([String: Any]) -> Void,
|
|
15
|
+
onFailed: @escaping ([String: Any]) -> Void,
|
|
16
|
+
onCancel: @escaping () -> Void,
|
|
17
|
+
onReady: @escaping () -> Void
|
|
18
|
+
) {
|
|
19
|
+
self.onSuccess = onSuccess
|
|
20
|
+
self.onFailed = onFailed
|
|
21
|
+
self.onCancel = onCancel
|
|
22
|
+
self.onReady = onReady
|
|
23
|
+
|
|
24
|
+
guard let dict = configDict as? [String: Any] else { return }
|
|
25
|
+
|
|
26
|
+
// Required fields
|
|
27
|
+
guard let publicKey = dict["publicKey"] as? String, !publicKey.isEmpty,
|
|
28
|
+
let amountNumber = dict["amount"] as? NSNumber,
|
|
29
|
+
let currencyStr = dict["currency"] as? String, !currencyStr.isEmpty,
|
|
30
|
+
let email = dict["email"] as? String, !email.isEmpty,
|
|
31
|
+
let fullName = dict["fullName"] as? String, !fullName.isEmpty,
|
|
32
|
+
let narration = dict["narration"] as? String, !narration.isEmpty else {
|
|
33
|
+
onFailed([
|
|
34
|
+
"status": "failed",
|
|
35
|
+
"message": "Missing required config fields (publicKey, amount, currency, email, fullName, narration)"
|
|
36
|
+
])
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let amount = amountNumber.intValue
|
|
41
|
+
guard amount > 0 else {
|
|
42
|
+
onFailed(["status": "failed", "message": "amount must be greater than 0"])
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let currency: Currency = currencyStr.uppercased() == "USD" ? .USD : .NGN
|
|
47
|
+
|
|
48
|
+
// Payment channels
|
|
49
|
+
var channels: [PaymentChannel] = [.card]
|
|
50
|
+
if let channelStrings = dict["paymentChannels"] as? [String] {
|
|
51
|
+
channels = channelStrings.compactMap { mapChannel($0) }
|
|
52
|
+
if channels.isEmpty { channels = [.card] }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Default channel
|
|
56
|
+
let defaultChannel: PaymentChannel
|
|
57
|
+
if let defaultStr = dict["defaultChannel"] as? String,
|
|
58
|
+
let mapped = mapChannel(defaultStr) {
|
|
59
|
+
defaultChannel = mapped
|
|
60
|
+
} else {
|
|
61
|
+
defaultChannel = channels.first ?? .card
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Metadata
|
|
65
|
+
let metadata = dict["metadata"] as? [String: Any] ?? [:]
|
|
66
|
+
|
|
67
|
+
var config = PaymentConfig(
|
|
68
|
+
publicKey: publicKey,
|
|
69
|
+
amount: amount,
|
|
70
|
+
currency: currency,
|
|
71
|
+
email: email,
|
|
72
|
+
fullName: fullName,
|
|
73
|
+
address1: {
|
|
74
|
+
let v = dict["address1"] as? String ?? ""
|
|
75
|
+
return v.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? "Customer Address" : v
|
|
76
|
+
}(),
|
|
77
|
+
address2: dict["address2"] as? String ?? "",
|
|
78
|
+
phoneNumber: dict["phoneNumber"] as? String ?? "",
|
|
79
|
+
narration: narration,
|
|
80
|
+
paymentChannels: channels,
|
|
81
|
+
defaultChannel: defaultChannel,
|
|
82
|
+
metadata: metadata,
|
|
83
|
+
city: {
|
|
84
|
+
let v = dict["city"] as? String ?? ""
|
|
85
|
+
return v.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? "Lagos" : v
|
|
86
|
+
}()
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
// Optional fields
|
|
90
|
+
if let v = dict["transactionRef"] as? String { config.transactionRef = v }
|
|
91
|
+
if let v = dict["businessName"] as? String { config.businessName = v }
|
|
92
|
+
if let v = dict["logoURL"] as? String { config.logoURL = v }
|
|
93
|
+
if let v = dict["productName"] as? String { config.productName = v }
|
|
94
|
+
if let v = dict["cardHolderName"] as? String { config.cardHolderName = v }
|
|
95
|
+
if let v = dict["customerId"] as? String { config.customerId = v }
|
|
96
|
+
if let v = dict["postalCode"] as? String { config.postalCode = v }
|
|
97
|
+
if let v = dict["locality"] as? String { config.locality = v }
|
|
98
|
+
if let v = dict["administrativeArea"] as? String { config.administrativeArea = v }
|
|
99
|
+
if let v = dict["enableSaveCard"] as? Bool { config.enableSaveCard = v }
|
|
100
|
+
if let v = dict["showTransactionSummary"] as? Bool { config.showTransactionSummary = v }
|
|
101
|
+
if let v = dict["isTest"] as? Bool { config.isTest = v }
|
|
102
|
+
if let v = dict["debugMode"] as? Bool {
|
|
103
|
+
config.debugMode = v
|
|
104
|
+
PaymentSDK.debugMode = v
|
|
105
|
+
}
|
|
106
|
+
if let v = dict["chargeAllocation"] as? String {
|
|
107
|
+
config.chargeAllocation = v.uppercased() == "MERCHANT" ? .merchant : .customer
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
DispatchQueue.main.async {
|
|
111
|
+
guard let rootVC = self.topViewController() else {
|
|
112
|
+
onFailed([
|
|
113
|
+
"status": "failed",
|
|
114
|
+
"message": "Unable to find a view controller to present from"
|
|
115
|
+
])
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
PaymentSDK.present(from: rootVC, config: config, delegate: self)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// MARK: - PaymentSDKDelegate
|
|
123
|
+
|
|
124
|
+
public func paymentDidSucceed(with payload: PaymentSuccessPayload) {
|
|
125
|
+
onSuccess?([
|
|
126
|
+
"status": payload.status,
|
|
127
|
+
"merchantRef": payload.merchantRef,
|
|
128
|
+
"transactionRef": payload.transactionRef,
|
|
129
|
+
"amount": payload.amount,
|
|
130
|
+
"currency": payload.currency.rawValue,
|
|
131
|
+
"channel": payload.channel.rawValue,
|
|
132
|
+
"message": payload.message,
|
|
133
|
+
"timestamp": payload.timestamp
|
|
134
|
+
])
|
|
135
|
+
clearCallbacks()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
public func paymentDidFail(with payload: PaymentFailedPayload) {
|
|
139
|
+
var body: [String: Any] = [
|
|
140
|
+
"status": payload.status,
|
|
141
|
+
"amount": payload.amount,
|
|
142
|
+
"currency": payload.currency.rawValue,
|
|
143
|
+
"message": payload.message,
|
|
144
|
+
"timestamp": payload.timestamp
|
|
145
|
+
]
|
|
146
|
+
if let v = payload.merchantRef { body["merchantRef"] = v }
|
|
147
|
+
if let v = payload.transactionRef { body["transactionRef"] = v }
|
|
148
|
+
if let v = payload.channel { body["channel"] = v.rawValue }
|
|
149
|
+
if let v = payload.errorCode { body["errorCode"] = v }
|
|
150
|
+
onFailed?(body)
|
|
151
|
+
clearCallbacks()
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
public func paymentDidCancel() {
|
|
155
|
+
onCancel?()
|
|
156
|
+
clearCallbacks()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public func paymentDidBecomeReady() {
|
|
160
|
+
onReady?()
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// MARK: - Helpers
|
|
164
|
+
|
|
165
|
+
private func clearCallbacks() {
|
|
166
|
+
onSuccess = nil
|
|
167
|
+
onFailed = nil
|
|
168
|
+
onCancel = nil
|
|
169
|
+
onReady = nil
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private func mapChannel(_ str: String) -> PaymentChannel? {
|
|
173
|
+
switch str.lowercased() {
|
|
174
|
+
case "card": return .card
|
|
175
|
+
case "transfer", "bank_transfer": return .transfer
|
|
176
|
+
case "ussd", "ussd_code": return .ussd
|
|
177
|
+
case "payattitude", "ussd_push", "pay_attitude": return .payattitude
|
|
178
|
+
case "moniflow", "netapps_marketplace", "marketplace": return .moniflow
|
|
179
|
+
default: return nil
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private func topViewController() -> UIViewController? {
|
|
184
|
+
var keyWindow: UIWindow?
|
|
185
|
+
if #available(iOS 13.0, *) {
|
|
186
|
+
keyWindow = UIApplication.shared.connectedScenes
|
|
187
|
+
.compactMap { $0 as? UIWindowScene }
|
|
188
|
+
.flatMap { $0.windows }
|
|
189
|
+
.first { $0.isKeyWindow }
|
|
190
|
+
} else {
|
|
191
|
+
keyWindow = UIApplication.shared.keyWindow
|
|
192
|
+
}
|
|
193
|
+
guard var vc = keyWindow?.rootViewController else { return nil }
|
|
194
|
+
while let presented = vc.presentedViewController {
|
|
195
|
+
vc = presented
|
|
196
|
+
}
|
|
197
|
+
return vc
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeNetappspay.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAQpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,YAAY,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { NativeEventEmitter, Platform } from 'react-native';
|
|
4
|
+
import NativeNetappspay from "./NativeNetappspay.js";
|
|
5
|
+
|
|
6
|
+
// ── Types ──
|
|
7
|
+
|
|
8
|
+
// ── Event emitter ──
|
|
9
|
+
|
|
10
|
+
const emitter = new NativeEventEmitter(NativeNetappspay);
|
|
11
|
+
|
|
12
|
+
// ── Public API ──
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Present the NetAppsPay payment sheet.
|
|
16
|
+
*
|
|
17
|
+
* @param config Payment configuration
|
|
18
|
+
* @param callbacks Optional event callbacks
|
|
19
|
+
* @returns A cleanup function to remove event listeners
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* import { presentPayment } from 'react-native-netappspay';
|
|
24
|
+
*
|
|
25
|
+
* const cleanup = presentPayment(
|
|
26
|
+
* {
|
|
27
|
+
* publicKey: 'pk_live_xxx',
|
|
28
|
+
* amount: 150000,
|
|
29
|
+
* currency: 'NGN',
|
|
30
|
+
* email: 'customer@email.com',
|
|
31
|
+
* fullName: 'John Doe',
|
|
32
|
+
* narration: 'Order #1234',
|
|
33
|
+
* paymentChannels: ['card', 'transfer', 'ussd'],
|
|
34
|
+
* defaultChannel: 'card',
|
|
35
|
+
* },
|
|
36
|
+
* {
|
|
37
|
+
* onSuccess: (payload) => console.log('Paid!', payload.transactionRef),
|
|
38
|
+
* onFailed: (payload) => console.log('Failed:', payload.message),
|
|
39
|
+
* onCancel: () => console.log('Cancelled'),
|
|
40
|
+
* }
|
|
41
|
+
* );
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
function validateConfig(config) {
|
|
45
|
+
if (!config.publicKey?.trim()) return 'publicKey is required';
|
|
46
|
+
if (!config.email?.trim()) return 'email is required';
|
|
47
|
+
if (!config.fullName?.trim()) return 'fullName is required';
|
|
48
|
+
if (!config.narration?.trim()) return 'narration is required';
|
|
49
|
+
if (typeof config.amount !== 'number' || config.amount <= 0) return 'amount must be a positive number';
|
|
50
|
+
if (!config.currency) return 'currency is required';
|
|
51
|
+
if (!config.paymentChannels?.length) return 'paymentChannels must have at least one channel';
|
|
52
|
+
if (!config.defaultChannel) return 'defaultChannel is required';
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
export function presentPayment(config, callbacks) {
|
|
56
|
+
if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
|
|
57
|
+
console.warn('react-native-netappspay: only iOS and Android are supported');
|
|
58
|
+
return () => {};
|
|
59
|
+
}
|
|
60
|
+
const error = validateConfig(config);
|
|
61
|
+
if (error) {
|
|
62
|
+
callbacks?.onFailed?.({
|
|
63
|
+
status: 'failed',
|
|
64
|
+
amount: config.amount ?? 0,
|
|
65
|
+
currency: config.currency ?? '',
|
|
66
|
+
message: `Invalid config: ${error}`,
|
|
67
|
+
timestamp: new Date().toISOString()
|
|
68
|
+
});
|
|
69
|
+
return () => {};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Apply defaults for fields the API requires to be non-empty
|
|
73
|
+
const sanitizedConfig = {
|
|
74
|
+
...config,
|
|
75
|
+
address1: config.address1?.trim() || 'Customer Address',
|
|
76
|
+
city: config.city?.trim() || 'Lagos',
|
|
77
|
+
phoneNumber: config.phoneNumber?.trim() || ''
|
|
78
|
+
};
|
|
79
|
+
const subscriptions = [emitter.addListener('onPaymentSuccess', payload => {
|
|
80
|
+
callbacks?.onSuccess?.(payload);
|
|
81
|
+
}), emitter.addListener('onPaymentFailed', payload => {
|
|
82
|
+
callbacks?.onFailed?.(payload);
|
|
83
|
+
}), emitter.addListener('onPaymentCancel', () => {
|
|
84
|
+
callbacks?.onCancel?.();
|
|
85
|
+
}), emitter.addListener('onPaymentReady', () => {
|
|
86
|
+
callbacks?.onReady?.();
|
|
87
|
+
})];
|
|
88
|
+
|
|
89
|
+
// Call present after listeners are registered so no events are missed
|
|
90
|
+
setTimeout(() => NativeNetappspay.present(sanitizedConfig), 0);
|
|
91
|
+
return () => {
|
|
92
|
+
subscriptions.forEach(s => s.remove());
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","Platform","NativeNetappspay","emitter","validateConfig","config","publicKey","trim","email","fullName","narration","amount","currency","paymentChannels","length","defaultChannel","presentPayment","callbacks","OS","console","warn","error","onFailed","status","message","timestamp","Date","toISOString","sanitizedConfig","address1","city","phoneNumber","subscriptions","addListener","payload","onSuccess","onCancel","onReady","setTimeout","present","forEach","s","remove"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,kBAAkB,EAAEC,QAAQ,QAAQ,cAAc;AAC3D,OAAOC,gBAAgB,MAAM,uBAAoB;;AAEjD;;AAoGA;;AAEA,MAAMC,OAAO,GAAG,IAAIH,kBAAkB,CAACE,gBAAuB,CAAC;;AAE/D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASE,cAAcA,CAACC,MAAqB,EAAiB;EAC5D,IAAI,CAACA,MAAM,CAACC,SAAS,EAAEC,IAAI,CAAC,CAAC,EAAE,OAAO,uBAAuB;EAC7D,IAAI,CAACF,MAAM,CAACG,KAAK,EAAED,IAAI,CAAC,CAAC,EAAE,OAAO,mBAAmB;EACrD,IAAI,CAACF,MAAM,CAACI,QAAQ,EAAEF,IAAI,CAAC,CAAC,EAAE,OAAO,sBAAsB;EAC3D,IAAI,CAACF,MAAM,CAACK,SAAS,EAAEH,IAAI,CAAC,CAAC,EAAE,OAAO,uBAAuB;EAC7D,IAAI,OAAOF,MAAM,CAACM,MAAM,KAAK,QAAQ,IAAIN,MAAM,CAACM,MAAM,IAAI,CAAC,EAAE,OAAO,kCAAkC;EACtG,IAAI,CAACN,MAAM,CAACO,QAAQ,EAAE,OAAO,sBAAsB;EACnD,IAAI,CAACP,MAAM,CAACQ,eAAe,EAAEC,MAAM,EAAE,OAAO,gDAAgD;EAC5F,IAAI,CAACT,MAAM,CAACU,cAAc,EAAE,OAAO,4BAA4B;EAC/D,OAAO,IAAI;AACb;AAEA,OAAO,SAASC,cAAcA,CAC5BX,MAAqB,EACrBY,SAA4B,EAChB;EACZ,IAAIhB,QAAQ,CAACiB,EAAE,KAAK,KAAK,IAAIjB,QAAQ,CAACiB,EAAE,KAAK,SAAS,EAAE;IACtDC,OAAO,CAACC,IAAI,CAAC,6DAA6D,CAAC;IAC3E,OAAO,MAAM,CAAC,CAAC;EACjB;EAEA,MAAMC,KAAK,GAAGjB,cAAc,CAACC,MAAM,CAAC;EACpC,IAAIgB,KAAK,EAAE;IACTJ,SAAS,EAAEK,QAAQ,GAAG;MACpBC,MAAM,EAAE,QAAQ;MAChBZ,MAAM,EAAEN,MAAM,CAACM,MAAM,IAAI,CAAC;MAC1BC,QAAQ,EAAEP,MAAM,CAACO,QAAQ,IAAI,EAAE;MAC/BY,OAAO,EAAE,mBAAmBH,KAAK,EAAE;MACnCI,SAAS,EAAE,IAAIC,IAAI,CAAC,CAAC,CAACC,WAAW,CAAC;IACpC,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,CAAC;EACjB;;EAEA;EACA,MAAMC,eAAe,GAAG;IACtB,GAAGvB,MAAM;IACTwB,QAAQ,EAAExB,MAAM,CAACwB,QAAQ,EAAEtB,IAAI,CAAC,CAAC,IAAI,kBAAkB;IACvDuB,IAAI,EAAEzB,MAAM,CAACyB,IAAI,EAAEvB,IAAI,CAAC,CAAC,IAAI,OAAO;IACpCwB,WAAW,EAAE1B,MAAM,CAAC0B,WAAW,EAAExB,IAAI,CAAC,CAAC,IAAI;EAC7C,CAAC;EAED,MAAMyB,aAAa,GAAG,CACpB7B,OAAO,CAAC8B,WAAW,CAAC,kBAAkB,EAAGC,OAAO,IAAK;IACnDjB,SAAS,EAAEkB,SAAS,GAAGD,OAAgC,CAAC;EAC1D,CAAC,CAAC,EACF/B,OAAO,CAAC8B,WAAW,CAAC,iBAAiB,EAAGC,OAAO,IAAK;IAClDjB,SAAS,EAAEK,QAAQ,GAAGY,OAA+B,CAAC;EACxD,CAAC,CAAC,EACF/B,OAAO,CAAC8B,WAAW,CAAC,iBAAiB,EAAE,MAAM;IAC3ChB,SAAS,EAAEmB,QAAQ,GAAG,CAAC;EACzB,CAAC,CAAC,EACFjC,OAAO,CAAC8B,WAAW,CAAC,gBAAgB,EAAE,MAAM;IAC1ChB,SAAS,EAAEoB,OAAO,GAAG,CAAC;EACxB,CAAC,CAAC,CACH;;EAED;EACAC,UAAU,CAAC,MAAMpC,gBAAgB,CAACqC,OAAO,CAACX,eAAsB,CAAC,EAAE,CAAC,CAAC;EAErE,OAAO,MAAM;IACXI,aAAa,CAACQ,OAAO,CAAEC,CAAC,IAAKA,CAAC,CAACC,MAAM,CAAC,CAAC,CAAC;EAC1C,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type TurboModule } from 'react-native';
|
|
2
|
+
export interface Spec extends TurboModule {
|
|
3
|
+
present(config: Object): void;
|
|
4
|
+
addListener(eventType: string): void;
|
|
5
|
+
removeListeners(count: number): void;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: Spec;
|
|
8
|
+
export default _default;
|
|
9
|
+
//# sourceMappingURL=NativeNetappspay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeNetappspay.d.ts","sourceRoot":"","sources":["../../../src/NativeNetappspay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;;AAED,wBAAoE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export type Currency = 'NGN' | 'USD';
|
|
2
|
+
export type PaymentChannel = 'card' | 'transfer' | 'ussd' | 'payattitude' | 'moniflow';
|
|
3
|
+
export type ChargeAllocation = 'CUSTOMER' | 'MERCHANT';
|
|
4
|
+
export interface PaymentConfig {
|
|
5
|
+
/** Your NetAppsPay public key */
|
|
6
|
+
publicKey: string;
|
|
7
|
+
/** Amount in minor units (kobo/cents). ₦15.00 = 1500 */
|
|
8
|
+
amount: number;
|
|
9
|
+
/** Currency */
|
|
10
|
+
currency: Currency;
|
|
11
|
+
/** Customer email */
|
|
12
|
+
email: string;
|
|
13
|
+
/** Customer full name */
|
|
14
|
+
fullName: string;
|
|
15
|
+
/** Payment description */
|
|
16
|
+
narration: string;
|
|
17
|
+
/** Channels to display */
|
|
18
|
+
paymentChannels: PaymentChannel[];
|
|
19
|
+
/** Initially selected channel */
|
|
20
|
+
defaultChannel: PaymentChannel;
|
|
21
|
+
/** Customer phone number */
|
|
22
|
+
phoneNumber?: string;
|
|
23
|
+
/** Address line 1 */
|
|
24
|
+
address1?: string;
|
|
25
|
+
/** Address line 2 */
|
|
26
|
+
address2?: string;
|
|
27
|
+
/** Customer city */
|
|
28
|
+
city?: string;
|
|
29
|
+
/** Custom key-value metadata */
|
|
30
|
+
metadata?: Record<string, any>;
|
|
31
|
+
/** Custom transaction reference */
|
|
32
|
+
transactionRef?: string;
|
|
33
|
+
/** Merchant display name */
|
|
34
|
+
businessName?: string;
|
|
35
|
+
/** Merchant logo URL */
|
|
36
|
+
logoURL?: string;
|
|
37
|
+
/** Product name */
|
|
38
|
+
productName?: string;
|
|
39
|
+
/** Pre-filled cardholder name */
|
|
40
|
+
cardHolderName?: string;
|
|
41
|
+
/** Your internal customer ID */
|
|
42
|
+
customerId?: string;
|
|
43
|
+
/** Postal code (default: "100248") */
|
|
44
|
+
postalCode?: string;
|
|
45
|
+
/** Country code (default: "NG") */
|
|
46
|
+
locality?: string;
|
|
47
|
+
/** State (default: "Lagos") */
|
|
48
|
+
administrativeArea?: string;
|
|
49
|
+
/** Who bears the charge */
|
|
50
|
+
chargeAllocation?: ChargeAllocation;
|
|
51
|
+
/** Allow saving cards */
|
|
52
|
+
enableSaveCard?: boolean;
|
|
53
|
+
/** Show transaction summary (default: true) */
|
|
54
|
+
showTransactionSummary?: boolean;
|
|
55
|
+
/** Test mode */
|
|
56
|
+
isTest?: boolean;
|
|
57
|
+
/** Debug logging */
|
|
58
|
+
debugMode?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface PaymentSuccessPayload {
|
|
61
|
+
status: 'success';
|
|
62
|
+
merchantRef: string;
|
|
63
|
+
transactionRef: string;
|
|
64
|
+
amount: number;
|
|
65
|
+
currency: string;
|
|
66
|
+
channel: string;
|
|
67
|
+
message: string;
|
|
68
|
+
timestamp: string;
|
|
69
|
+
}
|
|
70
|
+
export interface PaymentFailedPayload {
|
|
71
|
+
status: 'failed';
|
|
72
|
+
amount: number;
|
|
73
|
+
currency: string;
|
|
74
|
+
message: string;
|
|
75
|
+
timestamp: string;
|
|
76
|
+
merchantRef?: string;
|
|
77
|
+
transactionRef?: string;
|
|
78
|
+
channel?: string;
|
|
79
|
+
errorCode?: string;
|
|
80
|
+
}
|
|
81
|
+
export interface PaymentCallbacks {
|
|
82
|
+
onSuccess?: (payload: PaymentSuccessPayload) => void;
|
|
83
|
+
onFailed?: (payload: PaymentFailedPayload) => void;
|
|
84
|
+
onCancel?: () => void;
|
|
85
|
+
onReady?: () => void;
|
|
86
|
+
}
|
|
87
|
+
export declare function presentPayment(config: PaymentConfig, callbacks?: PaymentCallbacks): () => void;
|
|
88
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@netappsng/react-native-pay",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "netapps payment sdk",
|
|
5
|
+
"main": "./lib/module/index.js",
|
|
6
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"source": "./src/index.tsx",
|
|
10
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
11
|
+
"default": "./lib/module/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"lib",
|
|
18
|
+
"android",
|
|
19
|
+
"ios",
|
|
20
|
+
"cpp",
|
|
21
|
+
"*.podspec",
|
|
22
|
+
"react-native.config.js",
|
|
23
|
+
"!ios/build",
|
|
24
|
+
"!android/build",
|
|
25
|
+
"!android/gradle",
|
|
26
|
+
"!android/gradlew",
|
|
27
|
+
"!android/gradlew.bat",
|
|
28
|
+
"!android/local.properties",
|
|
29
|
+
"!**/__tests__",
|
|
30
|
+
"!**/__fixtures__",
|
|
31
|
+
"!**/__mocks__",
|
|
32
|
+
"!**/.*"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"example": "yarn workspace react-native-netappspay-example",
|
|
36
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
37
|
+
"prepare": "bob build",
|
|
38
|
+
"typecheck": "tsc",
|
|
39
|
+
"test": "jest",
|
|
40
|
+
"release": "release-it --only-version"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"react-native",
|
|
44
|
+
"ios",
|
|
45
|
+
"android"
|
|
46
|
+
],
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://gitlab.com/talktothelaw/react-native-netapps-pay.git"
|
|
50
|
+
},
|
|
51
|
+
"author": "lawrence <nwokolawrence6@gmail.com> (https://www.linkedin.com/in/talktothelaw/)",
|
|
52
|
+
"license": "MIT",
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "https://gitlab.com/talktothelaw/react-native-netapps-pay/issues"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://gitlab.com/talktothelaw/react-native-netapps-pay#readme",
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"registry": "https://registry.npmjs.org/"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@react-native/babel-preset": "0.83.0",
|
|
62
|
+
"@release-it/conventional-changelog": "^10.0.1",
|
|
63
|
+
"@types/jest": "^29.5.14",
|
|
64
|
+
"@types/react": "^19.2.0",
|
|
65
|
+
"del-cli": "^6.0.0",
|
|
66
|
+
"jest": "^29.7.0",
|
|
67
|
+
"react": "19.2.0",
|
|
68
|
+
"react-native": "0.83.0",
|
|
69
|
+
"react-native-builder-bob": "^0.40.13",
|
|
70
|
+
"release-it": "^19.0.4",
|
|
71
|
+
"turbo": "^2.5.6",
|
|
72
|
+
"typescript": "^5.9.2"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"react": "*",
|
|
76
|
+
"react-native": "*"
|
|
77
|
+
},
|
|
78
|
+
"workspaces": [
|
|
79
|
+
"example"
|
|
80
|
+
],
|
|
81
|
+
"packageManager": "yarn@4.11.0",
|
|
82
|
+
"react-native-builder-bob": {
|
|
83
|
+
"source": "src",
|
|
84
|
+
"output": "lib",
|
|
85
|
+
"targets": [
|
|
86
|
+
[
|
|
87
|
+
"module",
|
|
88
|
+
{
|
|
89
|
+
"esm": true
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
[
|
|
93
|
+
"typescript",
|
|
94
|
+
{
|
|
95
|
+
"project": "tsconfig.build.json"
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"codegenConfig": {
|
|
101
|
+
"name": "NetappspaySpec",
|
|
102
|
+
"type": "modules",
|
|
103
|
+
"jsSrcsDir": "src",
|
|
104
|
+
"android": {
|
|
105
|
+
"javaPackageName": "com.netappspay"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"jest": {
|
|
109
|
+
"preset": "react-native",
|
|
110
|
+
"modulePathIgnorePatterns": [
|
|
111
|
+
"<rootDir>/example/node_modules",
|
|
112
|
+
"<rootDir>/lib/"
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
"release-it": {
|
|
116
|
+
"git": {
|
|
117
|
+
"commitMessage": "chore: release ${version}",
|
|
118
|
+
"tagName": "v${version}"
|
|
119
|
+
},
|
|
120
|
+
"npm": {
|
|
121
|
+
"publish": true
|
|
122
|
+
},
|
|
123
|
+
"github": {
|
|
124
|
+
"release": true
|
|
125
|
+
},
|
|
126
|
+
"plugins": {
|
|
127
|
+
"@release-it/conventional-changelog": {
|
|
128
|
+
"preset": {
|
|
129
|
+
"name": "angular"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"create-react-native-library": {
|
|
135
|
+
"type": "turbo-module",
|
|
136
|
+
"languages": "kotlin-objc",
|
|
137
|
+
"tools": [
|
|
138
|
+
"jest",
|
|
139
|
+
"release-it"
|
|
140
|
+
],
|
|
141
|
+
"version": "0.57.2"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TurboModuleRegistry, type TurboModule } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export interface Spec extends TurboModule {
|
|
4
|
+
present(config: Object): void;
|
|
5
|
+
addListener(eventType: string): void;
|
|
6
|
+
removeListeners(count: number): void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default TurboModuleRegistry.getEnforcing<Spec>('Netappspay');
|