@dodicandra/minesec-rn 1.0.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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +444 -0
  3. package/android/build.gradle +54 -0
  4. package/android/src/main/AndroidManifest.xml +12 -0
  5. package/android/src/main/java/expo/modules/minesecrn/MinesecrnHeadlessActivity.kt +5 -0
  6. package/android/src/main/java/expo/modules/minesecrn/MinesecrnModule.kt +87 -0
  7. package/android/src/main/java/expo/modules/minesecrn/PoiRequestMapper.kt +101 -0
  8. package/android/src/main/java/expo/modules/minesecrn/ResultMappers.kt +52 -0
  9. package/app.plugin.js +1 -0
  10. package/build/Minesecrn.types.d.ts +91 -0
  11. package/build/Minesecrn.types.d.ts.map +1 -0
  12. package/build/Minesecrn.types.js +3 -0
  13. package/build/Minesecrn.types.js.map +1 -0
  14. package/build/MinesecrnModule.d.ts +36 -0
  15. package/build/MinesecrnModule.d.ts.map +1 -0
  16. package/build/MinesecrnModule.js +3 -0
  17. package/build/MinesecrnModule.js.map +1 -0
  18. package/build/MinesecrnModule.web.d.ts +11 -0
  19. package/build/MinesecrnModule.web.d.ts.map +1 -0
  20. package/build/MinesecrnModule.web.js +22 -0
  21. package/build/MinesecrnModule.web.js.map +1 -0
  22. package/build/index.d.ts +3 -0
  23. package/build/index.d.ts.map +1 -0
  24. package/build/index.js +3 -0
  25. package/build/index.js.map +1 -0
  26. package/expo-module.config.json +10 -0
  27. package/ios/Minesecrn.podspec +24 -0
  28. package/ios/MinesecrnModule.swift +37 -0
  29. package/package.json +80 -0
  30. package/plugin/build/index.d.ts +22 -0
  31. package/plugin/build/index.d.ts.map +1 -0
  32. package/plugin/build/index.js +219 -0
  33. package/plugin/src/index.ts +239 -0
  34. package/plugin/tsconfig.json +17 -0
  35. package/plugin/tsconfig.tsbuildinfo +1 -0
  36. package/src/Minesecrn.types.ts +126 -0
  37. package/src/MinesecrnModule.ts +52 -0
  38. package/src/MinesecrnModule.web.ts +27 -0
  39. package/src/index.ts +2 -0
@@ -0,0 +1,101 @@
1
+ package expo.modules.minesecrn
2
+
3
+ import com.theminesec.lib.dto.common.Amount
4
+ import com.theminesec.lib.dto.poi.CvmSignatureMode
5
+ import com.theminesec.lib.dto.poi.PoiRequest
6
+ import com.theminesec.lib.dto.transaction.PaymentMethod
7
+ import com.theminesec.lib.dto.transaction.TranType
8
+ import java.math.BigDecimal
9
+ import java.util.Currency
10
+
11
+ /**
12
+ * Boundary mapper: memvalidasi dan mengubah request Map dari JS menjadi PoiRequest SDK.
13
+ * Semua validasi input dilakukan di sini; gagal cepat dengan IllegalArgumentException.
14
+ */
15
+ internal object PoiRequestMapper {
16
+
17
+ fun toPoiRequest(map: Map<String, Any?>): PoiRequest {
18
+ val type = requireType(map)
19
+
20
+ return when (type) {
21
+ "ActionNew" -> {
22
+ val tranTypeStr = map["tranType"] as? String
23
+ ?: throw IllegalArgumentException("Missing 'tranType' for ActionNew")
24
+ val tranType = when (tranTypeStr) {
25
+ "SALE" -> TranType.SALE
26
+ "AUTH" -> TranType.AUTH
27
+ "REFUND" -> TranType.REFUND
28
+ else -> throw IllegalArgumentException("Unknown tranType: $tranTypeStr")
29
+ }
30
+ val amount = requireAmount(map, "ActionNew")
31
+ val profileId = map["profileId"] as? String
32
+ ?: throw IllegalArgumentException("Missing 'profileId' for ActionNew")
33
+
34
+ @Suppress("UNCHECKED_CAST")
35
+ val base = PoiRequest.ActionNew(
36
+ tranType = tranType,
37
+ amount = amount,
38
+ profileId = profileId,
39
+ primaryTid = map["primaryTid"] as? String,
40
+ description = map["description"] as? String,
41
+ posReference = map["posReference"] as? String,
42
+ tapToOwnDevice = map["tapToOwnDevice"] as? Boolean,
43
+ installmentPlan = (map["installmentPlan"] as? Number)?.toInt(),
44
+ preferredAcceptanceTag = "SME",
45
+ forceFetchProfile = true,
46
+ extra = map["extra"] as? Map<String, String>,
47
+ )
48
+ val cvmMode = when (map["cvmSignatureMode"] as? String) {
49
+ "ELECTRONIC_SIGNATURE" -> CvmSignatureMode.ELECTRONIC_SIGNATURE
50
+ "SIGN_ON_PAPER" -> CvmSignatureMode.SIGN_ON_PAPER
51
+ else -> null
52
+ }
53
+ cvmMode?.let { base.copy(cvmSignatureMode = it) } ?: base
54
+ }
55
+ else -> toServiceRequest(map)
56
+ }
57
+ }
58
+
59
+ fun toServiceRequest(map: Map<String, Any?>): PoiRequest {
60
+ val type = requireType(map)
61
+
62
+ return when (type) {
63
+ "ActionVoid" -> PoiRequest.ActionVoid(tranId = requireTranId(map, type))
64
+ "ActionLinkedRefund" -> PoiRequest.ActionLinkedRefund(
65
+ tranId = requireTranId(map, type),
66
+ amount = optionalAmount(map)
67
+ )
68
+ "ActionAdjust" -> PoiRequest.ActionAdjust(
69
+ tranId = requireTranId(map, type),
70
+ amount = requireAmount(map, type)
71
+ )
72
+ "ActionAuthComp" -> PoiRequest.ActionAuthComp(
73
+ tranId = requireTranId(map, type),
74
+ amount = requireAmount(map, type)
75
+ )
76
+ else -> throw IllegalArgumentException("Unknown PoiRequest type: $type")
77
+ }
78
+ }
79
+
80
+ private fun requireType(map: Map<String, Any?>): String =
81
+ map["type"] as? String ?: throw IllegalArgumentException("Missing 'type' in request")
82
+
83
+ private fun requireTranId(map: Map<String, Any?>, type: String): String =
84
+ map["tranId"] as? String ?: throw IllegalArgumentException("Missing 'tranId' for $type")
85
+
86
+ private fun requireAmount(map: Map<String, Any?>, type: String): Amount {
87
+ val amountMap = map["amount"] as? Map<*, *>
88
+ ?: throw IllegalArgumentException("Missing 'amount' for $type")
89
+ return parseAmount(amountMap)
90
+ }
91
+
92
+ private fun optionalAmount(map: Map<String, Any?>): Amount? =
93
+ (map["amount"] as? Map<*, *>)?.let { parseAmount(it) }
94
+
95
+ private fun parseAmount(amountMap: Map<*, *>): Amount = Amount(
96
+ BigDecimal(amountMap["value"] as? String ?: throw IllegalArgumentException("Missing amount.value")),
97
+ Currency.getInstance(
98
+ amountMap["currencyCode"] as? String ?: throw IllegalArgumentException("Missing amount.currencyCode")
99
+ )
100
+ )
101
+ }
@@ -0,0 +1,52 @@
1
+ package expo.modules.minesecrn
2
+
3
+ import com.theminesec.lib.dto.transaction.Transaction
4
+ import com.theminesec.sdk.headless.model.WrappedResult
5
+ import com.theminesec.sdk.headless.model.setup.SdkInitResp
6
+ import com.theminesec.sdk.headless.model.setup.SetupResp
7
+
8
+ /**
9
+ * Boundary mapper: mengubah model SDK menjadi Map yang dikirim ke JS.
10
+ * Bentuk map harus tetap sinkron dengan tipe di src/Minesecrn.types.ts.
11
+ */
12
+
13
+ internal fun WrappedResult<*>.toResultMap(): Map<String, Any?> = when (this) {
14
+ is WrappedResult.Success<*> -> mapOf(
15
+ "success" to true,
16
+ "value" to when (val v = value) {
17
+ is SdkInitResp -> mapOf("sdkVersion" to v.sdkVersion, "sdkId" to v.sdkId)
18
+ is Transaction -> v.toMap()
19
+ else -> v
20
+ }
21
+ )
22
+ is WrappedResult.Failure -> mapOf(
23
+ "success" to false,
24
+ "code" to code,
25
+ "message" to message,
26
+ "contextual" to contextual,
27
+ "extra" to extra
28
+ )
29
+ }
30
+
31
+ internal fun SetupResp.toSetupResultMap(): Map<String, Any?> = mapOf(
32
+ "sdkRes" to sdkRes.toResultMap(),
33
+ "emvRes" to emvRes.map { it.toResultMap() },
34
+ "capkRes" to capkRes.map { it.toResultMap() },
35
+ "termRes" to termRes.toResultMap(),
36
+ "keyRes" to keyRes.map { it.toResultMap() }
37
+ )
38
+
39
+ internal fun Transaction.toMap(): Map<String, Any?> = mapOf(
40
+ "id" to tranId,
41
+ "status" to tranStatus.name,
42
+ "tranType" to tranType.name,
43
+ "amount" to mapOf("value" to amount.value.toPlainString(), "currencyCode" to amount.currency.currencyCode),
44
+ "posReference" to posReference,
45
+ "approvalCode" to approvalCode,
46
+ "paymentMethod" to paymentMethod.name,
47
+ "accountMasked" to accountMasked,
48
+ "rrn" to rrn,
49
+ "batchNo" to batchNo,
50
+ "createdAt" to createdAt.toString(),
51
+ "updatedAt" to updatedAt?.toString()
52
+ )
package/app.plugin.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./plugin/build/index');
@@ -0,0 +1,91 @@
1
+ export type Amount = {
2
+ /** Nilai transaksi dalam string desimal, contoh: "1.00" */
3
+ value: string;
4
+ /** Kode mata uang ISO 4217, contoh: "HKD", "USD", "IDR" */
5
+ currencyCode: string;
6
+ };
7
+ export type TranType = 'SALE' | 'AUTH' | 'REFUND';
8
+ export type CvmSignatureMode = 'ELECTRONIC_SIGNATURE' | 'SIGN_ON_PAPER';
9
+ /** Memulai transaksi baru dengan NFC tap — membutuhkan UI HeadlessActivity */
10
+ export type PoiRequestActionNew = {
11
+ type: 'ActionNew';
12
+ tranType: TranType;
13
+ amount: Amount;
14
+ /** Profile ID dari Minesec backend untuk routing transaksi */
15
+ profileId: string;
16
+ primaryTid?: string;
17
+ description?: string;
18
+ /** Referensi POS internal untuk rekonsiliasi */
19
+ posReference?: string;
20
+ cvmSignatureMode?: CvmSignatureMode;
21
+ tapToOwnDevice?: boolean;
22
+ installmentPlan?: number;
23
+ extra?: Record<string, string>;
24
+ };
25
+ /** Void transaksi sebelum settlement — tidak perlu NFC */
26
+ export type PoiRequestActionVoid = {
27
+ type: 'ActionVoid';
28
+ tranId: string;
29
+ };
30
+ /** Refund tanpa tap ulang — hanya MPGS gateway yang support */
31
+ export type PoiRequestActionLinkedRefund = {
32
+ type: 'ActionLinkedRefund';
33
+ tranId: string;
34
+ /** Jika null, refund penuh */
35
+ amount?: Amount;
36
+ };
37
+ /** Adjustment jumlah (tip, incremental auth) */
38
+ export type PoiRequestActionAdjust = {
39
+ type: 'ActionAdjust';
40
+ tranId: string;
41
+ /** Total jumlah baru setelah adjustment */
42
+ amount: Amount;
43
+ };
44
+ /** Capture pre-authorized transaction */
45
+ export type PoiRequestActionAuthComp = {
46
+ type: 'ActionAuthComp';
47
+ tranId: string;
48
+ amount: Amount;
49
+ };
50
+ export type PoiRequest = PoiRequestActionNew | PoiRequestActionVoid | PoiRequestActionLinkedRefund | PoiRequestActionAdjust | PoiRequestActionAuthComp;
51
+ /** PoiRequest yang bisa digunakan tanpa UI (HeadlessService) */
52
+ export type PoiRequestBackground = Exclude<PoiRequest, PoiRequestActionNew>;
53
+ export type TransactionReferenceType = 'tranId' | 'posReference';
54
+ export type MinesecResult<T> = {
55
+ success: true;
56
+ value: T;
57
+ } | {
58
+ success: false;
59
+ code: number;
60
+ message: string;
61
+ contextual?: string;
62
+ extra?: Record<string, string>;
63
+ };
64
+ export type SdkInitResult = {
65
+ sdkVersion: string;
66
+ sdkId: string;
67
+ };
68
+ export type SetupResult = {
69
+ sdkRes: MinesecResult<SdkInitResult>;
70
+ emvRes: MinesecResult<unknown>[];
71
+ capkRes: MinesecResult<unknown>[];
72
+ termRes: MinesecResult<unknown>;
73
+ keyRes: MinesecResult<unknown>[];
74
+ };
75
+ export type Transaction = {
76
+ id: string;
77
+ status: string | null;
78
+ tranType: string | null;
79
+ amount: Amount | null;
80
+ posReference: string | null;
81
+ approvalCode: string | null;
82
+ /** Metode pembayaran, contoh: "VISA", "MASTERCARD" */
83
+ paymentMethod: string | null;
84
+ /** Nomor kartu yang disamarkan */
85
+ accountMasked: string | null;
86
+ rrn: string | null;
87
+ batchNo: string | null;
88
+ createdAt: string | null;
89
+ updatedAt: string | null;
90
+ };
91
+ //# sourceMappingURL=Minesecrn.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Minesecrn.types.d.ts","sourceRoot":"","sources":["../src/Minesecrn.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ // ─── Amount ───────────────────────────────────────────────────────────────────
2
+ export {};
3
+ //# sourceMappingURL=Minesecrn.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Minesecrn.types.js","sourceRoot":"","sources":["../src/Minesecrn.types.ts"],"names":[],"mappings":"AAAA,iFAAiF","sourcesContent":["// ─── Amount ───────────────────────────────────────────────────────────────────\n\nexport type Amount = {\n /** Nilai transaksi dalam string desimal, contoh: \"1.00\" */\n value: string;\n /** Kode mata uang ISO 4217, contoh: \"HKD\", \"USD\", \"IDR\" */\n currencyCode: string;\n};\n\n// ─── Transaction Type ──────────────────────────────────────────────────────────\n\nexport type TranType = 'SALE' | 'AUTH' | 'REFUND';\n\n// ─── CvmSignatureMode ─────────────────────────────────────────────────────────\n\nexport type CvmSignatureMode = 'ELECTRONIC_SIGNATURE' | 'SIGN_ON_PAPER';\n\n// ─── PoiRequest variants ───────────────────────────────────────────────────────\n\n/** Memulai transaksi baru dengan NFC tap — membutuhkan UI HeadlessActivity */\nexport type PoiRequestActionNew = {\n type: 'ActionNew';\n tranType: TranType;\n amount: Amount;\n /** Profile ID dari Minesec backend untuk routing transaksi */\n profileId: string;\n primaryTid?: string;\n description?: string;\n /** Referensi POS internal untuk rekonsiliasi */\n posReference?: string;\n cvmSignatureMode?: CvmSignatureMode;\n tapToOwnDevice?: boolean;\n installmentPlan?: number;\n extra?: Record<string, string>;\n};\n\n/** Void transaksi sebelum settlement — tidak perlu NFC */\nexport type PoiRequestActionVoid = {\n type: 'ActionVoid';\n tranId: string;\n};\n\n/** Refund tanpa tap ulang — hanya MPGS gateway yang support */\nexport type PoiRequestActionLinkedRefund = {\n type: 'ActionLinkedRefund';\n tranId: string;\n /** Jika null, refund penuh */\n amount?: Amount;\n};\n\n/** Adjustment jumlah (tip, incremental auth) */\nexport type PoiRequestActionAdjust = {\n type: 'ActionAdjust';\n tranId: string;\n /** Total jumlah baru setelah adjustment */\n amount: Amount;\n};\n\n/** Capture pre-authorized transaction */\nexport type PoiRequestActionAuthComp = {\n type: 'ActionAuthComp';\n tranId: string;\n amount: Amount;\n};\n\nexport type PoiRequest =\n | PoiRequestActionNew\n | PoiRequestActionVoid\n | PoiRequestActionLinkedRefund\n | PoiRequestActionAdjust\n | PoiRequestActionAuthComp;\n\n/** PoiRequest yang bisa digunakan tanpa UI (HeadlessService) */\nexport type PoiRequestBackground = Exclude<PoiRequest, PoiRequestActionNew>;\n\n// ─── Reference untuk query transaksi ──────────────────────────────────────────\n\nexport type TransactionReferenceType = 'tranId' | 'posReference';\n\n// ─── Result types ─────────────────────────────────────────────────────────────\n\nexport type MinesecResult<T> =\n | { success: true; value: T }\n | {\n success: false;\n code: number;\n message: string;\n contextual?: string;\n extra?: Record<string, string>;\n };\n\n// ─── SDK Init ─────────────────────────────────────────────────────────────────\n\nexport type SdkInitResult = {\n sdkVersion: string;\n sdkId: string;\n};\n\n// ─── Setup Result ──────────────────────────────────────────────────────────────\n\nexport type SetupResult = {\n sdkRes: MinesecResult<SdkInitResult>;\n emvRes: MinesecResult<unknown>[];\n capkRes: MinesecResult<unknown>[];\n termRes: MinesecResult<unknown>;\n keyRes: MinesecResult<unknown>[];\n};\n\n// ─── Transaction ───────────────────────────────────────────────────────────────\n\nexport type Transaction = {\n id: string;\n status: string | null;\n tranType: string | null;\n amount: Amount | null;\n posReference: string | null;\n approvalCode: string | null;\n /** Metode pembayaran, contoh: \"VISA\", \"MASTERCARD\" */\n paymentMethod: string | null;\n /** Nomor kartu yang disamarkan */\n accountMasked: string | null;\n rrn: string | null;\n batchNo: string | null;\n createdAt: string | null;\n updatedAt: string | null;\n};\n"]}
@@ -0,0 +1,36 @@
1
+ import { NativeModule } from 'expo';
2
+ import type { MinesecResult, PoiRequest, PoiRequestBackground, SdkInitResult, SetupResult, Transaction, TransactionReferenceType } from './Minesecrn.types';
3
+ declare class MinesecrnModule extends NativeModule<Record<string, never>> {
4
+ /**
5
+ * Inisialisasi Minesec SDK. Harus dipanggil setiap kali aplikasi launch.
6
+ * @param licenseFileName Nama file .license di folder assets, contoh: "license.license"
7
+ */
8
+ initSoftPos(licenseFileName: string): Promise<MinesecResult<SdkInitResult>>;
9
+ /**
10
+ * Setup awal SDK — download EMV params, CAPK, terminal config, dan inject keys.
11
+ * Cukup dipanggil sekali per instalasi.
12
+ * @param withTestCapk Set true untuk development/staging environment
13
+ */
14
+ initialSetup(withTestCapk?: boolean): Promise<SetupResult>;
15
+ /**
16
+ * Launch HeadlessActivity untuk memproses transaksi dengan UI dan NFC.
17
+ * Mendukung ActionNew, ActionVoid, ActionLinkedRefund, ActionAdjust, ActionAuthComp.
18
+ * @param request PoiRequest object
19
+ */
20
+ launchTransaction(request: PoiRequest): Promise<MinesecResult<Transaction>>;
21
+ /**
22
+ * Eksekusi aksi background tanpa UI (void, refund, adjust, auth-complete).
23
+ * Gunakan HeadlessService di backend — tidak ada NFC tap.
24
+ * @param request PoiRequest non-ActionNew
25
+ */
26
+ createAction(request: PoiRequestBackground): Promise<MinesecResult<Transaction>>;
27
+ /**
28
+ * Query transaksi berdasarkan referensi.
29
+ * @param refType 'tranId' (prefix tran_) atau 'posReference'
30
+ * @param refValue Nilai referensi
31
+ */
32
+ getTransaction(refType: TransactionReferenceType, refValue: string): Promise<MinesecResult<Transaction>>;
33
+ }
34
+ declare const _default: MinesecrnModule;
35
+ export default _default;
36
+ //# sourceMappingURL=MinesecrnModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MinesecrnModule.d.ts","sourceRoot":"","sources":["../src/MinesecrnModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AAEzD,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,WAAW,EACX,wBAAwB,EACzB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,OAAO,eAAgB,SAAQ,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACvE;;;OAGG;IACH,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;IAE3E;;;;OAIG;IACH,YAAY,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAE1D;;;;OAIG;IACH,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAE3E;;;;OAIG;IACH,YAAY,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAEhF;;;;OAIG;IACH,cAAc,CACZ,OAAO,EAAE,wBAAwB,EACjC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;CACvC;;AAED,wBAAiE"}
@@ -0,0 +1,3 @@
1
+ import { requireNativeModule } from 'expo';
2
+ export default requireNativeModule('Minesecrn');
3
+ //# sourceMappingURL=MinesecrnModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MinesecrnModule.js","sourceRoot":"","sources":["../src/MinesecrnModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAmDzD,eAAe,mBAAmB,CAAkB,WAAW,CAAC,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from 'expo';\n\nimport type {\n MinesecResult,\n PoiRequest,\n PoiRequestBackground,\n SdkInitResult,\n SetupResult,\n Transaction,\n TransactionReferenceType,\n} from './Minesecrn.types';\n\ndeclare class MinesecrnModule extends NativeModule<Record<string, never>> {\n /**\n * Inisialisasi Minesec SDK. Harus dipanggil setiap kali aplikasi launch.\n * @param licenseFileName Nama file .license di folder assets, contoh: \"license.license\"\n */\n initSoftPos(licenseFileName: string): Promise<MinesecResult<SdkInitResult>>;\n\n /**\n * Setup awal SDK — download EMV params, CAPK, terminal config, dan inject keys.\n * Cukup dipanggil sekali per instalasi.\n * @param withTestCapk Set true untuk development/staging environment\n */\n initialSetup(withTestCapk?: boolean): Promise<SetupResult>;\n\n /**\n * Launch HeadlessActivity untuk memproses transaksi dengan UI dan NFC.\n * Mendukung ActionNew, ActionVoid, ActionLinkedRefund, ActionAdjust, ActionAuthComp.\n * @param request PoiRequest object\n */\n launchTransaction(request: PoiRequest): Promise<MinesecResult<Transaction>>;\n\n /**\n * Eksekusi aksi background tanpa UI (void, refund, adjust, auth-complete).\n * Gunakan HeadlessService di backend — tidak ada NFC tap.\n * @param request PoiRequest non-ActionNew\n */\n createAction(request: PoiRequestBackground): Promise<MinesecResult<Transaction>>;\n\n /**\n * Query transaksi berdasarkan referensi.\n * @param refType 'tranId' (prefix tran_) atau 'posReference'\n * @param refValue Nilai referensi\n */\n getTransaction(\n refType: TransactionReferenceType,\n refValue: string\n ): Promise<MinesecResult<Transaction>>;\n}\n\nexport default requireNativeModule<MinesecrnModule>('Minesecrn');\n"]}
@@ -0,0 +1,11 @@
1
+ import { NativeModule } from 'expo';
2
+ declare class MinesecrnModule extends NativeModule<Record<string, never>> {
3
+ initSoftPos(_licenseFileName: string): Promise<never>;
4
+ initialSetup(_withTestCapk?: boolean): Promise<never>;
5
+ launchTransaction(_request: unknown): Promise<never>;
6
+ createAction(_request: unknown): Promise<never>;
7
+ getTransaction(_refType: string, _refValue: string): Promise<never>;
8
+ }
9
+ declare const _default: typeof MinesecrnModule;
10
+ export default _default;
11
+ //# sourceMappingURL=MinesecrnModule.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MinesecrnModule.web.d.ts","sourceRoot":"","sources":["../src/MinesecrnModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,MAAM,MAAM,CAAC;AAIvD,cAAM,eAAgB,SAAQ,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACzD,WAAW,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAIrD,YAAY,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;IAIrD,iBAAiB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;IAIpD,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC;IAI/C,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;CAG1E;;AAED,wBAA+D"}
@@ -0,0 +1,22 @@
1
+ import { NativeModule, registerWebModule } from 'expo';
2
+ // Minesec Headless SDK tidak tersedia di platform web atau iOS.
3
+ // Semua method akan throw error jika dipanggil di luar Android.
4
+ class MinesecrnModule extends NativeModule {
5
+ async initSoftPos(_licenseFileName) {
6
+ throw new Error('Minesec Headless SDK is only available on Android');
7
+ }
8
+ async initialSetup(_withTestCapk) {
9
+ throw new Error('Minesec Headless SDK is only available on Android');
10
+ }
11
+ async launchTransaction(_request) {
12
+ throw new Error('Minesec Headless SDK is only available on Android');
13
+ }
14
+ async createAction(_request) {
15
+ throw new Error('Minesec Headless SDK is only available on Android');
16
+ }
17
+ async getTransaction(_refType, _refValue) {
18
+ throw new Error('Minesec Headless SDK is only available on Android');
19
+ }
20
+ }
21
+ export default registerWebModule(MinesecrnModule, 'Minesecrn');
22
+ //# sourceMappingURL=MinesecrnModule.web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MinesecrnModule.web.js","sourceRoot":"","sources":["../src/MinesecrnModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAEvD,gEAAgE;AAChE,gEAAgE;AAChE,MAAM,eAAgB,SAAQ,YAAmC;IAC/D,KAAK,CAAC,WAAW,CAAC,gBAAwB;QACxC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,aAAuB;QACxC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,QAAiB;QACvC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAiB;QAClC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB,EAAE,SAAiB;QACtD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;CACF;AAED,eAAe,iBAAiB,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC","sourcesContent":["import { NativeModule, registerWebModule } from 'expo';\n\n// Minesec Headless SDK tidak tersedia di platform web atau iOS.\n// Semua method akan throw error jika dipanggil di luar Android.\nclass MinesecrnModule extends NativeModule<Record<string, never>> {\n async initSoftPos(_licenseFileName: string): Promise<never> {\n throw new Error('Minesec Headless SDK is only available on Android');\n }\n\n async initialSetup(_withTestCapk?: boolean): Promise<never> {\n throw new Error('Minesec Headless SDK is only available on Android');\n }\n\n async launchTransaction(_request: unknown): Promise<never> {\n throw new Error('Minesec Headless SDK is only available on Android');\n }\n\n async createAction(_request: unknown): Promise<never> {\n throw new Error('Minesec Headless SDK is only available on Android');\n }\n\n async getTransaction(_refType: string, _refValue: string): Promise<never> {\n throw new Error('Minesec Headless SDK is only available on Android');\n }\n}\n\nexport default registerWebModule(MinesecrnModule, 'Minesecrn');\n"]}
@@ -0,0 +1,3 @@
1
+ export { default } from './MinesecrnModule';
2
+ export * from './Minesecrn.types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,cAAc,mBAAmB,CAAC"}
package/build/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { default } from './MinesecrnModule';
2
+ export * from './Minesecrn.types';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,cAAc,mBAAmB,CAAC","sourcesContent":["export { default } from './MinesecrnModule';\nexport * from './Minesecrn.types';\n"]}
@@ -0,0 +1,10 @@
1
+ {
2
+ "platforms": ["apple", "android"],
3
+ "apple": {
4
+ "modules": ["MinesecrnModule"]
5
+ },
6
+ "android": {
7
+ "modules": ["expo.modules.minesecrn.MinesecrnModule"]
8
+ },
9
+ "plugin": "./plugin/build/index"
10
+ }
@@ -0,0 +1,24 @@
1
+ Pod::Spec.new do |s|
2
+ s.name = 'Minesecrn'
3
+ s.version = '1.0.0'
4
+ s.summary = 'A sample project summary'
5
+ s.description = 'A sample project description'
6
+ s.author = ''
7
+ s.homepage = 'https://docs.expo.dev/modules/'
8
+ s.platforms = {
9
+ :ios => '16.4',
10
+ :tvos => '16.4'
11
+ }
12
+ s.source = { git: '' }
13
+ s.static_framework = true
14
+
15
+ s.dependency 'ExpoModulesCore'
16
+ s.dependency 'ExpoUI'
17
+
18
+ # Swift/Objective-C compatibility
19
+ s.pod_target_xcconfig = {
20
+ 'DEFINES_MODULE' => 'YES',
21
+ }
22
+
23
+ s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
24
+ end
@@ -0,0 +1,37 @@
1
+ import ExpoModulesCore
2
+
3
+ // Minesec Headless SDK hanya tersedia di Android.
4
+ // Semua method di sini akan throw error jika dipanggil dari iOS.
5
+ public class MinesecrnModule: Module {
6
+ public func definition() -> ModuleDefinition {
7
+ Name("Minesecrn")
8
+
9
+ AsyncFunction("initSoftPos") { (_: String) throws -> [String: Any?] in
10
+ throw notSupportedError()
11
+ }
12
+
13
+ AsyncFunction("initialSetup") { (_: Bool) throws -> [String: Any?] in
14
+ throw notSupportedError()
15
+ }
16
+
17
+ AsyncFunction("launchTransaction") { (_: [String: Any?]) throws -> [String: Any?] in
18
+ throw notSupportedError()
19
+ }
20
+
21
+ AsyncFunction("createAction") { (_: [String: Any?]) throws -> [String: Any?] in
22
+ throw notSupportedError()
23
+ }
24
+
25
+ AsyncFunction("getTransaction") { (_: String, _: String) throws -> [String: Any?] in
26
+ throw notSupportedError()
27
+ }
28
+ }
29
+
30
+ private func notSupportedError() -> NSError {
31
+ NSError(
32
+ domain: "Minesecrn",
33
+ code: 0,
34
+ userInfo: [NSLocalizedDescriptionKey: "Minesec Headless SDK is not available on iOS"]
35
+ )
36
+ }
37
+ }
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@dodicandra/minesec-rn",
3
+ "version": "1.0.0",
4
+ "description": "Expo Native Module bridge for Minesec Headless SoftPOS SDK (Android)",
5
+ "main": "build/index.js",
6
+ "types": "build/index.d.ts",
7
+ "scripts": {
8
+ "build": "node internal/module_scripts/build.js",
9
+ "build:plugin": "node internal/module_scripts/build.js plugin",
10
+ "clean": "node internal/module_scripts/clean.js",
11
+ "lint": "eslint src/ plugin/src/",
12
+ "test": "node internal/module_scripts/test.js",
13
+ "prepare": "node internal/module_scripts/prepare.js && node internal/module_scripts/prepare.js plugin",
14
+ "open:ios": "node internal/module_scripts/open-ios.js",
15
+ "open:android": "node internal/module_scripts/open-android.js"
16
+ },
17
+ "keywords": [
18
+ "react-native",
19
+ "expo",
20
+ "minesecrn",
21
+ "minesec",
22
+ "softpos",
23
+ "payment",
24
+ "nfc"
25
+ ],
26
+ "repository": "https://github.com/dodicandra/minesec",
27
+ "bugs": {
28
+ "url": "https://github.com/dodicandra/minesec/issues"
29
+ },
30
+ "author": "dodicandra <dodicandra20@gmail.com> (dodicandra)",
31
+ "license": "MIT",
32
+ "homepage": "https://github.com/dodicandra/minesec#readme",
33
+ "expo": {
34
+ "autolinking": {}
35
+ },
36
+ "files": [
37
+ "build",
38
+ "android",
39
+ "ios",
40
+ "src",
41
+ "plugin",
42
+ "app.plugin.js",
43
+ "expo-module.config.json",
44
+ "!android/build",
45
+ "!android/.gradle",
46
+ "!android/.idea",
47
+ "!android/local.properties",
48
+ "!plugin/node_modules",
49
+ "!**/*.test.*",
50
+ "!**/__tests__/**"
51
+ ],
52
+ "dependencies": {},
53
+ "devDependencies": {
54
+ "@babel/core": "^7.26.0",
55
+ "@expo/config-plugins": "56.0.9",
56
+ "@types/jest": "^29.2.1",
57
+ "@types/react": "~19.1.1",
58
+ "babel-preset-expo": "~55.0.8",
59
+ "eslint": "~9.39.4",
60
+ "eslint-config-universe": "^15.0.3",
61
+ "expo": "^56.0.11",
62
+ "jest": "^29.7.0",
63
+ "jest-expo": "~55.0.9",
64
+ "prettier": "^3.0.0",
65
+ "react-native": "0.82.1",
66
+ "typescript": "^5.9.2"
67
+ },
68
+ "jest": {
69
+ "preset": "jest-expo",
70
+ "roots": [
71
+ "<rootDir>/src"
72
+ ]
73
+ },
74
+ "peerDependencies": {
75
+ "expo": "*",
76
+ "react": "*",
77
+ "react-native": "*"
78
+ },
79
+ "private": false
80
+ }
@@ -0,0 +1,22 @@
1
+ import { type ConfigPlugin } from '@expo/config-plugins';
2
+ export interface MinesecPluginOptions {
3
+ enableNfc?: boolean;
4
+ licenseFileName?: string;
5
+ username?: string;
6
+ usertoken?: string;
7
+ }
8
+ /**
9
+ * Expo Config Plugin untuk Minesec Headless SoftPOS SDK.
10
+ *
11
+ * Options (di app.json):
12
+ * enableNfc — tambah NFC permission/feature (default: true). Set false jika konflik dengan lib lain.
13
+ * licenseFileName — nama file lisensi SDK dari project root; dicopy ke android assets saat prebuild.
14
+ * username — Maven username; ditulis ke gradle.properties sebagai "username".
15
+ * usertoken — Maven token; ditulis ke gradle.properties sebagai "usertoken".
16
+ *
17
+ * Untuk production, gunakan ~/.gradle/gradle.properties atau env vars
18
+ * MINESEC_MAVEN_USER / MINESEC_MAVEN_TOKEN daripada menyimpan credentials di app.json.
19
+ */
20
+ declare const withMinesec: ConfigPlugin<MinesecPluginOptions>;
21
+ export default withMinesec;
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EAMlB,MAAM,sBAAsB,CAAC;AAM9B,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgMD;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,WAAW,EAAE,YAAY,CAAC,oBAAoB,CAcnD,CAAC;AAEF,eAAe,WAAW,CAAC"}