@achyutlabsau/vue-payment-gateway 0.2.6 → 0.2.8

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/README.md CHANGED
@@ -1,141 +1,141 @@
1
- # Vue Payment Gateway
2
-
3
- A Vue.js payment gateway library to handle payments with ease.
4
-
5
- ## Installation
6
-
7
- To install the library, run the following command:
8
-
9
- ```bash
10
- npm install @achyutlabsau/vue-payment-gateway
11
- ```
12
-
13
- ## Plugin Initialization
14
-
15
- To use the payment gateway, you need to initialize the plugin in your Vue app. Here’s an example of how to set it up:
16
-
17
- ```javascript
18
- import VuePaymentGateway from "@achyutlabsau/vue-payment-gateway";
19
-
20
- app.use(VuePaymentGateway, {
21
- productName: "Pratham Respos", // Name of your product
22
- productVersion: "3.3.0", // Version of your product
23
- productVendorName: "Achyutlabs", // Name of the product vendor
24
- posId: "unique-pos-id", // Unique identifier for the POS system
25
- posRegisterId: "pos-register-id", // Unique identifier for the POS register
26
- posRegisterName: "register-name", // Name of the POS register
27
- posBusinessName: "business name", // Name of the business using the POS system
28
- tyroApiKey: "tyro-api-key", // API key for Tyro integration
29
- environment: "development", // Set environment to 'development' or 'production'
30
- });
31
- ```
32
-
33
- > **Note:** Replace the placeholder values with the actual details of your POS system, product, and Tyro API key.
34
-
35
- ## Using the Payment Gateway
36
-
37
- This library supports multiple payment providers, such as Tyro, SmartPay, and Linkly. Here’s how to use them in your application.
38
-
39
- ### Using Tyro
40
-
41
- To use the Tyro payment gateway, import and initialize it as shown below:
42
-
43
- ```javascript
44
- import { useTyro } from "@achyutlabsau/vue-payment-gateway/tyro";
45
-
46
- const tyro = useTyro();
47
-
48
- // Example usage
49
- await tyro.processPayment(amount, options);
50
- ```
51
-
52
- ### Using SmartPay
53
-
54
- To use the SmartPay payment gateway, import and initialize it as shown below:
55
-
56
- ```javascript
57
- import { useSmartPay } from "@achyutlabsau/vue-payment-gateway/smartpay";
58
-
59
- const smartPay = useSmartPay();
60
-
61
- // Example usage
62
- await smartPay.processPayment(amount, options);
63
- ```
64
-
65
- ### Using Linkly
66
-
67
- To use the Linkly payment gateway, import and initialize it as shown below:
68
-
69
- ```javascript
70
- import { useLinkly } from "@achyutlabsau/vue-payment-gateway/linkly";
71
-
72
- const linkly = useLinkly();
73
-
74
- // Example usage
75
- await linkly.processPayment(amount, options);
76
- ```
77
-
78
- ## Payment Method API
79
-
80
- Each payment provider (Tyro, SmartPay, Linkly) provides methods to process payments. Here are some of the most commonly used methods:
81
-
82
- ### `processPayment(amount: number, options?: object)`
83
-
84
- Processes a payment for the specified amount.
85
-
86
- **Parameters:**
87
-
88
- - `amount`: The amount to be charged.
89
- - `options`: (Optional) Additional options for the payment.
90
-
91
- ### `cancelPayment()`
92
-
93
- Cancels an ongoing payment.
94
-
95
- ### `getStatus()`
96
-
97
- Gets the status of the current payment transaction.
98
-
99
- > **Note:** The methods may differ slightly between Tyro, SmartPay, and Linkly. Refer to the official documentation of each payment provider for more details.
100
-
101
- ## Environment Configuration
102
-
103
- The environment can be set to either `development` or `production`. Make sure to use `development` during testing and switch to `production` in a live environment to ensure security and proper tracking.
104
-
105
- ```javascript
106
- app.use(VuePaymentGateway, {
107
- ...
108
- environment: "production", // Set to 'production' in a live environment
109
- });
110
- ```
111
-
112
- ## Example Usage
113
-
114
- Here’s a complete example of how you might use the payment gateway to process a payment with Tyro:
115
-
116
- ```javascript
117
- import { useTyro } from "@achyutlabsau/vue-payment-gateway/tyro";
118
-
119
- const tyro = useTyro();
120
-
121
- async function handlePayment() {
122
- try {
123
- const paymentResult = await tyro.processPayment(100, { currency: "USD" });
124
- console.log("Payment successful:", paymentResult);
125
- } catch (error) {
126
- console.error("Payment failed:", error);
127
- }
128
- }
129
- ```
130
-
131
- ## Troubleshooting
132
-
133
- - **Environment Issues**: Make sure `environment` is set correctly (`development` or `production`).
134
- - **Invalid API Key**: Ensure the Tyro API key is valid and correctly set in the configuration.
135
- - **Payment Processing Issues**: Check if the payment provider's service is online and available.
136
-
137
- ## Additional Resources
138
-
139
- For more details and usage examples, refer to the official documentation or support channels provided by [Achyutlabs](https://achyutlabs.com/).
140
-
141
- With this guide, you should be able to set up and use the Vue Payment Gateway efficiently to handle payments with Tyro, SmartPay, and Linkly integrations.
1
+ # Vue Payment Gateway
2
+
3
+ A Vue.js payment gateway library to handle payments with ease.
4
+
5
+ ## Installation
6
+
7
+ To install the library, run the following command:
8
+
9
+ ```bash
10
+ npm install @achyutlabsau/vue-payment-gateway
11
+ ```
12
+
13
+ ## Plugin Initialization
14
+
15
+ To use the payment gateway, you need to initialize the plugin in your Vue app. Here’s an example of how to set it up:
16
+
17
+ ```javascript
18
+ import VuePaymentGateway from "@achyutlabsau/vue-payment-gateway";
19
+
20
+ app.use(VuePaymentGateway, {
21
+ productName: "Pratham Respos", // Name of your product
22
+ productVersion: "3.3.0", // Version of your product
23
+ productVendorName: "Achyutlabs", // Name of the product vendor
24
+ posId: "unique-pos-id", // Unique identifier for the POS system
25
+ posRegisterId: "pos-register-id", // Unique identifier for the POS register
26
+ posRegisterName: "register-name", // Name of the POS register
27
+ posBusinessName: "business name", // Name of the business using the POS system
28
+ tyroApiKey: "tyro-api-key", // API key for Tyro integration
29
+ environment: "development", // Set environment to 'development' or 'production'
30
+ });
31
+ ```
32
+
33
+ > **Note:** Replace the placeholder values with the actual details of your POS system, product, and Tyro API key.
34
+
35
+ ## Using the Payment Gateway
36
+
37
+ This library supports multiple payment providers, such as Tyro, SmartPay, and Linkly. Here’s how to use them in your application.
38
+
39
+ ### Using Tyro
40
+
41
+ To use the Tyro payment gateway, import and initialize it as shown below:
42
+
43
+ ```javascript
44
+ import { useTyro } from "@achyutlabsau/vue-payment-gateway/tyro";
45
+
46
+ const tyro = useTyro();
47
+
48
+ // Example usage
49
+ await tyro.processPayment(amount, options);
50
+ ```
51
+
52
+ ### Using SmartPay
53
+
54
+ To use the SmartPay payment gateway, import and initialize it as shown below:
55
+
56
+ ```javascript
57
+ import { useSmartPay } from "@achyutlabsau/vue-payment-gateway/smartpay";
58
+
59
+ const smartPay = useSmartPay();
60
+
61
+ // Example usage
62
+ await smartPay.processPayment(amount, options);
63
+ ```
64
+
65
+ ### Using Linkly
66
+
67
+ To use the Linkly payment gateway, import and initialize it as shown below:
68
+
69
+ ```javascript
70
+ import { useLinkly } from "@achyutlabsau/vue-payment-gateway/linkly";
71
+
72
+ const linkly = useLinkly();
73
+
74
+ // Example usage
75
+ await linkly.processPayment(amount, options);
76
+ ```
77
+
78
+ ## Payment Method API
79
+
80
+ Each payment provider (Tyro, SmartPay, Linkly) provides methods to process payments. Here are some of the most commonly used methods:
81
+
82
+ ### `processPayment(amount: number, options?: object)`
83
+
84
+ Processes a payment for the specified amount.
85
+
86
+ **Parameters:**
87
+
88
+ - `amount`: The amount to be charged.
89
+ - `options`: (Optional) Additional options for the payment.
90
+
91
+ ### `cancelPayment()`
92
+
93
+ Cancels an ongoing payment.
94
+
95
+ ### `getStatus()`
96
+
97
+ Gets the status of the current payment transaction.
98
+
99
+ > **Note:** The methods may differ slightly between Tyro, SmartPay, and Linkly. Refer to the official documentation of each payment provider for more details.
100
+
101
+ ## Environment Configuration
102
+
103
+ The environment can be set to either `development` or `production`. Make sure to use `development` during testing and switch to `production` in a live environment to ensure security and proper tracking.
104
+
105
+ ```javascript
106
+ app.use(VuePaymentGateway, {
107
+ ...
108
+ environment: "production", // Set to 'production' in a live environment
109
+ });
110
+ ```
111
+
112
+ ## Example Usage
113
+
114
+ Here’s a complete example of how you might use the payment gateway to process a payment with Tyro:
115
+
116
+ ```javascript
117
+ import { useTyro } from "@achyutlabsau/vue-payment-gateway/tyro";
118
+
119
+ const tyro = useTyro();
120
+
121
+ async function handlePayment() {
122
+ try {
123
+ const paymentResult = await tyro.processPayment(100, { currency: "USD" });
124
+ console.log("Payment successful:", paymentResult);
125
+ } catch (error) {
126
+ console.error("Payment failed:", error);
127
+ }
128
+ }
129
+ ```
130
+
131
+ ## Troubleshooting
132
+
133
+ - **Environment Issues**: Make sure `environment` is set correctly (`development` or `production`).
134
+ - **Invalid API Key**: Ensure the Tyro API key is valid and correctly set in the configuration.
135
+ - **Payment Processing Issues**: Check if the payment provider's service is online and available.
136
+
137
+ ## Additional Resources
138
+
139
+ For more details and usage examples, refer to the official documentation or support channels provided by [Achyutlabs](https://achyutlabs.com/).
140
+
141
+ With this guide, you should be able to set up and use the Vue Payment Gateway efficiently to handle payments with Tyro, SmartPay, and Linkly integrations.
@@ -1,6 +1,6 @@
1
1
  import { Spi, TransactionOptions, SuccessState, TransactionType } from "@mx51/spi-client-js";
2
2
  const spiSettings = {
3
- secureWebSockets: window.location.protocol === "https:" ? true : false,
3
+ secureWebSockets: true,
4
4
  // checks for HTTPs
5
5
  printMerchantCopyOnEftpos: false,
6
6
  // prints merchant receipt from terminal instead of POS
@@ -37,16 +37,31 @@ const pairingData = getPairingData();
37
37
  const spi = new Spi(
38
38
  pairingData.posId ?? "",
39
39
  pairingData.serialNumber ?? "",
40
- localStorage.getItem("eftposAddress") ?? "192.168.31.246",
40
+ localStorage.getItem("eftposAddress") ?? "",
41
41
  getSecrets()
42
42
  );
43
- spi.SetAutoAddressResolution(!!pairingData.autoAddressResolution);
44
43
  spi.SetTenantCode(pairingData.tenantCode ?? "gko");
45
44
  spi.SetSecureWebSockets(spiSettings.secureWebSockets);
46
45
  spi.Config.PrintMerchantCopy = spiSettings.printMerchantCopyOnEftpos;
47
46
  spi.Config.PromptForCustomerCopyOnEftpos = spiSettings.promptForCustomerCopyOnEftpos;
48
47
  spi.Config.SignatureFlowOnEftpos = spiSettings.signatureFlowOnEftpos;
49
48
  const receiptOptions = new TransactionOptions();
49
+ const spiEvents = {
50
+ spiAutoAddressResolutionFailed: "AutoAddressResolutionFailed",
51
+ spiBatteryLevelChanged: "BatteryLevelChanged",
52
+ spiDeviceAddressChanged: "DeviceAddressChanged",
53
+ spiSecretsChanged: "SecretsChanged",
54
+ spiFlowChanged: "spiFlowChanged",
55
+ spiPairingFlowStateChanged: "PairingFlowStateChanged",
56
+ spiPong: "SpiPong",
57
+ spiStatusChanged: "StatusChanged",
58
+ spiTerminalSetupsChanged: "TerminalConfigChanged",
59
+ spiTerminalStatusChanged: "TerminalStatusChanged",
60
+ spiTxFlowStateChanged: "TxFlowStateChanged",
61
+ spiTxUpdateMessage: "TransactionUpdateMessage",
62
+ spiCancelTransactionResponse: "cancel_response",
63
+ TerminalStatusResponse: "terminal_status"
64
+ };
50
65
  function log(message, event) {
51
66
  if (event) {
52
67
  spi._log.info(`${message} -> `, event);
@@ -64,7 +79,7 @@ document.addEventListener("SecretsChanged", (e) => {
64
79
  window.localStorage.setItem("secrets", JSON.stringify(e.detail));
65
80
  }
66
81
  });
67
- document.addEventListener("PairingFlowStateChanged", (e) => {
82
+ document.addEventListener(spiEvents.spiPairingFlowStateChanged, (e) => {
68
83
  var _a, _b, _c, _d, _e, _f, _g;
69
84
  log("Pairing flow state changed", e);
70
85
  log(
@@ -74,7 +89,7 @@ document.addEventListener("PairingFlowStateChanged", (e) => {
74
89
  spi.AckFlowEndedAndBackToIdle();
75
90
  }
76
91
  });
77
- document.addEventListener("TxFlowStateChanged", (e) => {
92
+ document.addEventListener(spiEvents.spiTxFlowStateChanged, (e) => {
78
93
  log("Transaction flow state changed", e);
79
94
  if (e.detail.AwaitingSignatureCheck) ;
80
95
  else if (e.detail.AwaitingPhoneForAuth) ;
@@ -98,9 +113,9 @@ document.addEventListener("TxFlowStateChanged", (e) => {
98
113
  document.addEventListener("DeviceAddressChanged", (e) => {
99
114
  log("Device address changed", e);
100
115
  if (e == null ? void 0 : e.detail.ip) {
101
- window.localStorage.setItem("eftposAddress", JSON.stringify(e.detail.ip));
116
+ window.localStorage.setItem("eftposAddress", e.detail.ip);
102
117
  } else if (e == null ? void 0 : e.detail.fqdn) {
103
- window.localStorage.setItem("eftposAddress", JSON.stringify(e.detail.fqdn));
118
+ window.localStorage.setItem("eftposAddress", e.detail.fqdn);
104
119
  }
105
120
  });
106
121
  spi.TerminalConfigurationResponse = (e) => {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { s as setState, a as setEnvironment, i as isPluginInitialized } from "./
2
2
  import "quasar";
3
3
  import { T as TYRO_CONSTANTS } from "./tyro.enums-OZuKaM2C.js";
4
4
  import { useScriptTag } from "@vueuse/core";
5
- import { s as spi } from "./event-Zm-ArxiV.js";
5
+ import { s as spi } from "./event-DqmWpDvf.js";
6
6
  import "vue";
7
7
  import "@mx51/spi-client-js";
8
8
  import "uuid";
package/dist/mx51.d.ts CHANGED
@@ -30,7 +30,7 @@ export declare function getTransaction(posRefId?: string): void;
30
30
 
31
31
  export declare function log(message: string, event?: any): void;
32
32
 
33
- export declare const PairMX51: DefineComponent< {}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, HTMLDivElement>;
33
+ export declare const PairMX51: DefineComponent< {}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, HTMLElement>;
34
34
 
35
35
  /**
36
36
  * Initiates a purchase transaction
package/dist/mx51.js CHANGED
@@ -1,19 +1,23 @@
1
- import { l as log, s as spi, g as getPairingData, a as getTenants, r as receiptOptions } from "./event-Zm-ArxiV.js";
2
- import { defineComponent, ref, computed, onMounted, resolveDirective, openBlock, createElementBlock, createVNode, unref, withCtx, createElementVNode, createCommentVNode, createBlock, toDisplayString, withDirectives } from "vue";
3
- import { QForm, QSelect, QInput, QCheckbox, QIcon, QBtn, QDialog, QCard, QCardSection, Dialog } from "quasar";
1
+ import { l as log, s as spi, g as getPairingData, a as getTenants, r as receiptOptions } from "./event-DqmWpDvf.js";
2
+ import { defineComponent, ref, computed, onMounted, watch, resolveDirective, openBlock, createElementBlock, createVNode, unref, withCtx, createElementVNode, createCommentVNode, createBlock, toDisplayString, withDirectives, createTextVNode } from "vue";
3
+ import { QCard, QForm, QSelect, QInput, QCheckbox, QIcon, QBtn, QDialog, QCardSection, Dialog } from "quasar";
4
4
  import { useEventListener, useLocalStorage } from "@vueuse/core";
5
5
  import { SpiStatus, SuccessState, TransactionType } from "@mx51/spi-client-js";
6
6
  import { b as state } from "./state-D014QcxX.js";
7
7
  import { v4 } from "uuid";
8
- function pair(pairingInput) {
8
+ async function pair(pairingInput) {
9
9
  spi.SetTenantCode(pairingInput.tenantCode);
10
10
  spi.SetEftposAddress(pairingInput.eftposAddress);
11
11
  spi.SetSerialNumber(pairingInput.serialNumber);
12
12
  spi.SetPosId(pairingInput.posId);
13
13
  spi.SetAutoAddressResolution(pairingInput.autoAddressResolution);
14
14
  spi.SetTestMode(pairingInput.testMode);
15
+ if (pairingInput.autoAddressResolution) {
16
+ const res = await spi.GetTerminalAddress();
17
+ if (!res) return false;
18
+ }
15
19
  log("Pairing...");
16
- spi.Pair();
20
+ return spi.Pair();
17
21
  }
18
22
  function unpair() {
19
23
  if (!spi) return;
@@ -28,23 +32,24 @@ function cancelPairing() {
28
32
  log("Pairing cancelled");
29
33
  spi.PairingCancel();
30
34
  }
31
- const _hoisted_1$1 = { class: "my-6 w-full max-w-lg rounded-md bg-white p-6 shadow-md" };
32
- const _hoisted_2$1 = { class: "rounded bg-gray-100 p-3" };
33
- const _hoisted_3$1 = {
35
+ const _hoisted_1$1 = { class: "my-6 flex w-full max-w-5xl flex-row flex-nowrap justify-between gap-6" };
36
+ const _hoisted_2$1 = { class: "mb-0 grid grid-cols-2 gap-x-3" };
37
+ const _hoisted_3$1 = { class: "rounded bg-gray-100 p-3" };
38
+ const _hoisted_4$1 = {
34
39
  key: 0,
35
40
  class: "flex items-center gap-1 font-semibold"
36
41
  };
37
- const _hoisted_4$1 = {
42
+ const _hoisted_5$1 = {
38
43
  key: 1,
39
44
  class: "flex items-center gap-1 font-semibold"
40
45
  };
41
- const _hoisted_5$1 = {
46
+ const _hoisted_6$1 = {
42
47
  key: 2,
43
48
  class: "flex items-center gap-1 font-semibold"
44
49
  };
45
- const _hoisted_6$1 = { class: "text-center font-semibold text-gray-500 uppercase" };
46
- const _hoisted_7$1 = { class: "py-3 text-center text-2xl font-semibold text-slate-700 uppercase" };
47
- const _hoisted_8 = { class: "text-center font-semibold text-gray-500 uppercase" };
50
+ const _hoisted_7$1 = { class: "text-center font-semibold text-gray-500 uppercase" };
51
+ const _hoisted_8 = { class: "py-3 text-center text-2xl font-semibold text-slate-700 uppercase" };
52
+ const _hoisted_9 = { class: "text-center font-semibold text-gray-500 uppercase" };
48
53
  const _sfc_main$1 = /* @__PURE__ */ defineComponent({
49
54
  __name: "PairMX51",
50
55
  setup(__props) {
@@ -53,40 +58,79 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
53
58
  const regex = new RegExp(`^${octet}\\.${octet}\\.${octet}\\.${octet}$`);
54
59
  return regex.test(str);
55
60
  }
61
+ function isValidFQDN(str) {
62
+ const fqdnRegex = new RegExp("^(?=.{1,253}$)(?!-)(?:[a-zA-Z0-9-]{1,63}(?<!-)\\.)+[a-zA-Z]{2,}$");
63
+ return fqdnRegex.test(str);
64
+ }
65
+ function isAlphanumeric(str) {
66
+ const alphanumericRegex = /^[a-zA-Z0-9]+$/;
67
+ return alphanumericRegex.test(str);
68
+ }
56
69
  const tenants = ref([]);
57
70
  const model = ref(false);
58
- const pairStatus = ref(spi._currentStatus);
71
+ const pairStatus = ref(spi._currentStatus ?? SpiStatus.Unpaired);
59
72
  const isPaired = computed(() => {
60
73
  return [SpiStatus.PairedConnected, SpiStatus.PairedConnecting].includes(pairStatus.value);
61
74
  });
75
+ const selectedTenant = ref("");
62
76
  const pairForm = ref({
63
77
  posId: "",
64
78
  serialNumber: "",
65
79
  tenantCode: "",
66
- eftposAddress: "",
67
80
  testMode: false,
68
- autoAddressResolution: false,
69
- ...getPairingData()
81
+ autoAddressResolution: true,
82
+ ...getPairingData(),
83
+ eftposAddress: localStorage.getItem("eftposAddress") ?? ""
70
84
  });
71
85
  const pairInfo = ref({
72
86
  state: "INPROGRESS",
73
- message: "Connecting to eftpos",
87
+ message: "Connecting...",
74
88
  confirmationCode: ""
75
89
  });
76
- const onPairTerminal = () => {
77
- pair(pairForm.value);
90
+ const isOtherTenantSelected = computed(() => selectedTenant.value === "other");
91
+ const resetPairForm = () => {
92
+ localStorage.removeItem("pairingData");
93
+ localStorage.removeItem("eftposAddress");
94
+ pairForm.value = {
95
+ posId: "",
96
+ serialNumber: "",
97
+ tenantCode: "",
98
+ testMode: false,
99
+ autoAddressResolution: true,
100
+ ...getPairingData(),
101
+ eftposAddress: localStorage.getItem("eftposAddress") ?? ""
102
+ };
103
+ };
104
+ const onPairTerminal = async () => {
105
+ model.value = true;
106
+ const isPairingStarted = await pair(pairForm.value);
107
+ if (!isPairingStarted) {
108
+ pairInfo.value.state = "FINISHED";
109
+ pairInfo.value.message = "Sorry, we were unable to pair with the EFTPOS terminal. Please check the Serial Number and Payment Provider have been entered correctly and try again.";
110
+ }
78
111
  };
79
112
  const onUnpairTerminal = () => {
80
113
  unpair();
114
+ resetPairForm();
81
115
  Dialog.create({
82
116
  title: "Successfully Unpaired!",
83
117
  message: "Unpair the terminal from the device menu if it remains paired."
84
118
  });
85
119
  };
86
120
  onMounted(async () => {
121
+ pairForm.value.posId = "T1";
122
+ pairForm.value.serialNumber = "500-099-001";
87
123
  const res = await getTenants(state.productVendorName, state.mx51DeviceApiKey);
88
124
  if (res) {
89
125
  tenants.value = res;
126
+ tenants.value.push({
127
+ code: "other",
128
+ name: "Other Bank"
129
+ });
130
+ const mappedTenants = tenants.value.map((v) => v.code);
131
+ if (pairForm.value.tenantCode) {
132
+ selectedTenant.value = mappedTenants.includes(pairForm.value.tenantCode) ? pairForm.value.tenantCode : "other";
133
+ }
90
134
  }
91
135
  });
92
136
  useEventListener(document, "StatusChanged", (e) => {
@@ -114,178 +158,261 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
114
158
  return;
115
159
  }
116
160
  });
161
+ watch(selectedTenant, (val) => {
162
+ if (val && val !== "other") {
163
+ pairForm.value.tenantCode = val;
164
+ }
165
+ });
166
+ useEventListener(document, "DeviceAddressChanged", (e) => {
167
+ if (e == null ? void 0 : e.detail.ip) {
168
+ pairForm.value.eftposAddress = e.detail.ip;
169
+ } else if (e == null ? void 0 : e.detail.fqdn) {
170
+ pairForm.value.eftposAddress = e.detail.fqdn;
171
+ }
172
+ });
173
+ setInterval(() => pairStatus.value = spi._currentStatus ?? SpiStatus.Unpaired, 1e3);
117
174
  return (_ctx, _cache) => {
118
175
  const _directive_close_popup = resolveDirective("close-popup");
119
- return openBlock(), createElementBlock("div", _hoisted_1$1, [
120
- createVNode(unref(QForm), {
121
- onSubmit: onPairTerminal,
122
- class: "space-y-4"
176
+ return openBlock(), createElementBlock("section", _hoisted_1$1, [
177
+ createVNode(unref(QCard), {
178
+ flat: "",
179
+ bordered: "",
180
+ class: "flex-grow rounded-md p-6"
123
181
  }, {
124
182
  default: withCtx(() => [
125
- _cache[10] || (_cache[10] = createElementVNode("div", { class: "font-sans text-lg font-semibold text-gray-600" }, "MX 51 - SPI Terminal Pairing", -1)),
126
- createVNode(unref(QSelect), {
127
- disable: isPaired.value,
128
- dense: "",
129
- class: "my-6",
130
- outlined: "",
131
- label: "Tenant",
132
- modelValue: pairForm.value.tenantCode,
133
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => pairForm.value.tenantCode = $event),
134
- options: tenants.value,
135
- "map-options": "",
136
- "option-value": "code",
137
- "option-label": "name",
138
- "emit-value": "",
139
- rules: [(v) => !!v || "Please select tenant"],
140
- hint: "Choose the Tenant"
141
- }, null, 8, ["disable", "modelValue", "options", "rules"]),
142
- createVNode(unref(QInput), {
143
- disable: isPaired.value,
144
- dense: "",
145
- outlined: "",
146
- modelValue: pairForm.value.posId,
147
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => pairForm.value.posId = $event),
148
- label: "POS ID",
149
- rules: [
150
- (v) => !!v || "POS ID is required",
151
- (val) => /^[a-zA-Z0-9]+$/.test(val) || "Pos id is not valid",
152
- (val) => val && val.length <= 16 || "POS ID must be less than 16 characters"
153
- ]
154
- }, null, 8, ["disable", "modelValue", "rules"]),
155
- createVNode(unref(QInput), {
156
- disable: isPaired.value,
157
- dense: "",
158
- outlined: "",
159
- modelValue: pairForm.value.serialNumber,
160
- "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => pairForm.value.serialNumber = $event),
161
- label: "Serial Number",
162
- rules: [(v) => !!v || "Serial Number is required"],
163
- hint: "Enter the Serial Number associated with the terminal"
164
- }, null, 8, ["disable", "modelValue", "rules"]),
165
- createVNode(unref(QInput), {
166
- disable: isPaired.value,
167
- dense: "",
168
- outlined: "",
169
- modelValue: pairForm.value.eftposAddress,
170
- "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => pairForm.value.eftposAddress = $event),
171
- label: "Eftpos Address",
172
- rules: [
173
- (v) => !!v || "Eftpos Address is required",
174
- (v) => isValidIP(v) || "The Eftpos address is not in the right format"
175
- ],
176
- hint: "Enter the Eftpos Address associated with the terminal"
177
- }, null, 8, ["disable", "modelValue", "rules"]),
178
- createElementVNode("div", null, [
179
- createVNode(unref(QCheckbox), {
180
- label: "Test Mode",
181
- modelValue: pairForm.value.testMode,
182
- "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => pairForm.value.testMode = $event),
183
- disable: isPaired.value,
184
- dense: ""
185
- }, null, 8, ["modelValue", "disable"])
186
- ]),
187
- createElementVNode("div", _hoisted_2$1, [
188
- _cache[9] || (_cache[9] = createElementVNode("div", { class: "text-sm font-medium text-gray-500" }, "Pairing Status", -1)),
189
- pairStatus.value === unref(SpiStatus).PairedConnected ? (openBlock(), createElementBlock("div", _hoisted_3$1, [
190
- createVNode(unref(QIcon), {
191
- name: "check_circle",
192
- size: "xs",
193
- color: "green"
194
- }),
195
- _cache[6] || (_cache[6] = createElementVNode("div", null, "Paired and Connected", -1))
196
- ])) : pairStatus.value === unref(SpiStatus).Unpaired ? (openBlock(), createElementBlock("div", _hoisted_4$1, [
197
- createVNode(unref(QIcon), {
198
- name: "cancel",
199
- size: "xs",
200
- color: "red"
201
- }),
202
- _cache[7] || (_cache[7] = createElementVNode("div", null, "Unpaired", -1))
203
- ])) : pairStatus.value === unref(SpiStatus).PairedConnecting ? (openBlock(), createElementBlock("div", _hoisted_5$1, [
204
- createVNode(unref(QIcon), {
205
- name: "check_circle",
206
- size: "xs",
207
- color: "yellow-8"
208
- }),
209
- _cache[8] || (_cache[8] = createElementVNode("div", null, "Paired and trying to connect", -1))
210
- ])) : createCommentVNode("", true)
211
- ]),
212
- !isPaired.value ? (openBlock(), createBlock(unref(QBtn), {
213
- key: 0,
214
- label: "Pair Terminal",
215
- type: "submit",
216
- color: "primary",
217
- class: "!w-full",
218
- unelevated: "",
219
- "no-caps": "",
220
- ripple: false
221
- })) : (openBlock(), createBlock(unref(QBtn), {
222
- key: 1,
223
- label: "Unpair",
224
- type: "button",
225
- color: "primary",
226
- class: "!w-full",
227
- unelevated: "",
228
- "no-caps": "",
229
- onClick: onUnpairTerminal,
230
- outline: "",
231
- ripple: false
232
- }))
183
+ _cache[14] || (_cache[14] = createElementVNode("div", { class: "text-lg font-semibold text-gray-600" }, "Pairing configuration", -1)),
184
+ createVNode(unref(QForm), {
185
+ onSubmit: onPairTerminal,
186
+ class: "space-y-4"
187
+ }, {
188
+ default: withCtx(() => [
189
+ createElementVNode("div", _hoisted_2$1, [
190
+ createVNode(unref(QSelect), {
191
+ "no-error-icon": "",
192
+ disable: isPaired.value,
193
+ dense: "",
194
+ class: "my-6",
195
+ outlined: "",
196
+ label: "Payment Provider",
197
+ modelValue: selectedTenant.value,
198
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedTenant.value = $event),
199
+ options: tenants.value,
200
+ "map-options": "",
201
+ "option-value": "code",
202
+ "option-label": "name",
203
+ "emit-value": "",
204
+ rules: [(v) => !!v || "Please select Payment Provider"]
205
+ }, null, 8, ["disable", "modelValue", "options", "rules"]),
206
+ createVNode(unref(QInput), {
207
+ "no-error-icon": "",
208
+ disable: isPaired.value || !isOtherTenantSelected.value,
209
+ dense: "",
210
+ class: "my-6",
211
+ outlined: "",
212
+ label: "Other (Please specify)",
213
+ modelValue: pairForm.value.tenantCode,
214
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => pairForm.value.tenantCode = $event),
215
+ "map-options": "",
216
+ "option-value": "code",
217
+ "option-label": "name",
218
+ "emit-value": "",
219
+ rules: [
220
+ (v) => !!v && v.length < 10 || "Please enter a supported provider less than 10 characters",
221
+ (v) => isAlphanumeric(v) || "Tenant must contain only alphanumeric characters"
222
+ ]
223
+ }, null, 8, ["disable", "modelValue", "rules"])
224
+ ]),
225
+ createVNode(unref(QInput), {
226
+ "no-error-icon": "",
227
+ disable: isPaired.value,
228
+ dense: "",
229
+ outlined: "",
230
+ modelValue: pairForm.value.posId,
231
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => pairForm.value.posId = $event),
232
+ label: "POS ID",
233
+ rules: [
234
+ (v) => !!v || "POS ID is required",
235
+ (val) => isAlphanumeric(val) || "Pos ID must contain only alphanumeric characters",
236
+ (val) => val && val.length <= 16 || "POS ID must be less than 16 characters"
237
+ ]
238
+ }, null, 8, ["disable", "modelValue", "rules"]),
239
+ createVNode(unref(QInput), {
240
+ "no-error-icon": "",
241
+ disable: isPaired.value,
242
+ dense: "",
243
+ outlined: "",
244
+ modelValue: pairForm.value.serialNumber,
245
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => pairForm.value.serialNumber = $event),
246
+ label: "Serial Number",
247
+ rules: [(v) => !!v || "Serial Number is required"],
248
+ hint: "Enter the Serial Number associated with the terminal"
249
+ }, null, 8, ["disable", "modelValue", "rules"]),
250
+ createVNode(unref(QInput), {
251
+ "no-error-icon": "",
252
+ disable: isPaired.value || pairForm.value.autoAddressResolution,
253
+ dense: "",
254
+ outlined: "",
255
+ modelValue: pairForm.value.eftposAddress,
256
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => pairForm.value.eftposAddress = $event),
257
+ label: "Eftpos Address",
258
+ rules: [
259
+ (v) => !!v || "Eftpos Address is required",
260
+ (v) => isValidIP(v) || isValidFQDN(v) || "The Eftpos address is not in the right format"
261
+ ],
262
+ hint: "Enter the Eftpos Address associated with the terminal"
263
+ }, null, 8, ["disable", "modelValue", "rules"]),
264
+ createElementVNode("div", null, [
265
+ createVNode(unref(QCheckbox), {
266
+ label: "Test Mode",
267
+ modelValue: pairForm.value.testMode,
268
+ "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => pairForm.value.testMode = $event),
269
+ disable: isPaired.value,
270
+ dense: ""
271
+ }, null, 8, ["modelValue", "disable"])
272
+ ]),
273
+ createVNode(unref(QCheckbox), {
274
+ disable: isPaired.value,
275
+ dense: "",
276
+ label: "Auto Address Mode",
277
+ modelValue: pairForm.value.autoAddressResolution,
278
+ "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => pairForm.value.autoAddressResolution = $event)
279
+ }, null, 8, ["disable", "modelValue"]),
280
+ createElementVNode("div", _hoisted_3$1, [
281
+ _cache[11] || (_cache[11] = createElementVNode("div", { class: "text-sm font-medium text-gray-500" }, "Pairing Status", -1)),
282
+ pairStatus.value === unref(SpiStatus).PairedConnected ? (openBlock(), createElementBlock("div", _hoisted_4$1, [
283
+ createVNode(unref(QIcon), {
284
+ name: "check_circle",
285
+ size: "xs",
286
+ color: "green"
287
+ }),
288
+ _cache[8] || (_cache[8] = createElementVNode("div", null, "Paired and Connected", -1))
289
+ ])) : pairStatus.value === unref(SpiStatus).Unpaired ? (openBlock(), createElementBlock("div", _hoisted_5$1, [
290
+ createVNode(unref(QIcon), {
291
+ name: "cancel",
292
+ size: "xs",
293
+ color: "red"
294
+ }),
295
+ _cache[9] || (_cache[9] = createElementVNode("div", null, "Unpaired", -1))
296
+ ])) : pairStatus.value === unref(SpiStatus).PairedConnecting ? (openBlock(), createElementBlock("div", _hoisted_6$1, [
297
+ createVNode(unref(QIcon), {
298
+ name: "check_circle",
299
+ size: "xs",
300
+ color: "yellow-8"
301
+ }),
302
+ _cache[10] || (_cache[10] = createElementVNode("div", null, "Paired and trying to connect", -1))
303
+ ])) : createCommentVNode("", true)
304
+ ]),
305
+ !isPaired.value ? (openBlock(), createBlock(unref(QBtn), {
306
+ key: 0,
307
+ label: "Pair",
308
+ type: "submit",
309
+ color: "primary",
310
+ class: "!w-full",
311
+ unelevated: "",
312
+ "no-caps": "",
313
+ ripple: false
314
+ })) : (openBlock(), createBlock(unref(QBtn), {
315
+ key: 1,
316
+ label: "Unpair",
317
+ type: "button",
318
+ color: "primary",
319
+ class: "!w-full",
320
+ unelevated: "",
321
+ "no-caps": "",
322
+ onClick: onUnpairTerminal,
323
+ outline: "",
324
+ ripple: false
325
+ }))
326
+ ]),
327
+ _: 1
328
+ }),
329
+ createVNode(unref(QDialog), {
330
+ modelValue: model.value,
331
+ "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => model.value = $event),
332
+ persistent: ""
333
+ }, {
334
+ default: withCtx(() => [
335
+ createVNode(unref(QCard), { class: "w-full p-3" }, {
336
+ default: withCtx(() => [
337
+ pairInfo.value.state === "INPROGRESS" ? (openBlock(), createBlock(unref(QCardSection), { key: 0 }, {
338
+ default: withCtx(() => [
339
+ createElementVNode("div", _hoisted_7$1, toDisplayString(pairInfo.value.message), 1),
340
+ createVNode(unref(QBtn), {
341
+ label: "Cancel",
342
+ onClick: unref(cancelPairing),
343
+ color: "primary",
344
+ outline: "",
345
+ class: "!mt-6 !w-full",
346
+ unelevated: "",
347
+ "no-caps": "",
348
+ ripple: false
349
+ }, null, 8, ["onClick"])
350
+ ]),
351
+ _: 1
352
+ })) : pairInfo.value.state === "CONFIRMATION" ? (openBlock(), createBlock(unref(QCardSection), { key: 1 }, {
353
+ default: withCtx(() => [
354
+ _cache[12] || (_cache[12] = createElementVNode("div", { class: "text-center font-semibold text-gray-500 uppercase" }, "Confirm your pairing code", -1)),
355
+ createElementVNode("div", _hoisted_8, toDisplayString(pairInfo.value.confirmationCode), 1),
356
+ _cache[13] || (_cache[13] = createElementVNode("div", { class: "text-center text-sm text-gray-500" }, "Confirm the matching pairing code on the terminal", -1))
357
+ ]),
358
+ _: 1
359
+ })) : pairInfo.value.state === "FINISHED" ? (openBlock(), createBlock(unref(QCardSection), { key: 2 }, {
360
+ default: withCtx(() => [
361
+ createElementVNode("div", _hoisted_9, toDisplayString(pairInfo.value.message), 1),
362
+ withDirectives(createVNode(unref(QBtn), {
363
+ label: "OK",
364
+ color: "primary",
365
+ outline: "",
366
+ class: "!mt-6 !w-full",
367
+ unelevated: "",
368
+ "no-caps": "",
369
+ ripple: false
370
+ }, null, 512), [
371
+ [_directive_close_popup]
372
+ ])
373
+ ]),
374
+ _: 1
375
+ })) : createCommentVNode("", true)
376
+ ]),
377
+ _: 1
378
+ })
379
+ ]),
380
+ _: 1
381
+ }, 8, ["modelValue"])
233
382
  ]),
234
383
  _: 1
235
384
  }),
236
- createVNode(unref(QDialog), {
237
- modelValue: model.value,
238
- "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => model.value = $event),
239
- persistent: ""
385
+ createVNode(unref(QCard), {
386
+ class: "h-fit max-w-sm",
387
+ flat: "",
388
+ bordered: ""
240
389
  }, {
241
390
  default: withCtx(() => [
242
- createVNode(unref(QCard), { class: "w-full p-3" }, {
243
- default: withCtx(() => [
244
- pairInfo.value.state === "INPROGRESS" ? (openBlock(), createBlock(unref(QCardSection), { key: 0 }, {
245
- default: withCtx(() => [
246
- createElementVNode("div", _hoisted_6$1, toDisplayString(pairInfo.value.message), 1),
247
- createVNode(unref(QBtn), {
248
- label: "Cancel",
249
- onClick: unref(cancelPairing),
250
- color: "primary",
251
- outline: "",
252
- class: "!mt-6 !w-full",
253
- unelevated: "",
254
- "no-caps": "",
255
- ripple: false
256
- }, null, 8, ["onClick"])
391
+ createVNode(unref(QCardSection), null, {
392
+ default: withCtx(() => _cache[15] || (_cache[15] = [
393
+ createElementVNode("div", { class: "text-xl" }, [
394
+ createTextVNode(" Steps to pair for: "),
395
+ createElementVNode("br"),
396
+ createElementVNode("b", null, "Simple Payments Integration")
397
+ ], -1),
398
+ createElementVNode("ul", { class: "mt-3 list-inside list-decimal space-y-2 text-base" }, [
399
+ createElementVNode("li", null, "Select your payment provider."),
400
+ createElementVNode("li", null, "On the terminal: Go to “Manage POS pairing” to create a new POS Pairing."),
401
+ createElementVNode("li", null, [
402
+ createTextVNode("On the terminal: Select "),
403
+ createElementVNode("b", null, "“Simple Payments Integration”"),
404
+ createTextVNode(".")
257
405
  ]),
258
- _: 1
259
- })) : pairInfo.value.state === "CONFIRMATION" ? (openBlock(), createBlock(unref(QCardSection), { key: 1 }, {
260
- default: withCtx(() => [
261
- _cache[11] || (_cache[11] = createElementVNode("div", { class: "text-center font-semibold text-gray-500 uppercase" }, "Confirm your pairing code", -1)),
262
- createElementVNode("div", _hoisted_7$1, toDisplayString(pairInfo.value.confirmationCode), 1),
263
- _cache[12] || (_cache[12] = createElementVNode("div", { class: "text-center text-sm text-gray-500" }, "Confirm the matching pairing code on the terminal", -1))
264
- ]),
265
- _: 1
266
- })) : pairInfo.value.state === "FINISHED" ? (openBlock(), createBlock(unref(QCardSection), { key: 2 }, {
267
- default: withCtx(() => [
268
- createElementVNode("div", _hoisted_8, toDisplayString(pairInfo.value.message), 1),
269
- withDirectives(createVNode(unref(QBtn), {
270
- label: "OK",
271
- color: "primary",
272
- outline: "",
273
- class: "!mt-6 !w-full",
274
- unelevated: "",
275
- "no-caps": "",
276
- ripple: false
277
- }, null, 512), [
278
- [_directive_close_popup]
279
- ])
280
- ]),
281
- _: 1
282
- })) : createCommentVNode("", true)
283
- ]),
406
+ createElementVNode("li", null, "Enter the serial number and IP address provided from the terminal."),
407
+ createElementVNode("li", null, "Create a POS ID to identify the pairing connection."),
408
+ createElementVNode("li", null, "Tap “Pair” to initiate the pairing on both devices.")
409
+ ], -1)
410
+ ])),
284
411
  _: 1
285
412
  })
286
413
  ]),
287
414
  _: 1
288
- }, 8, ["modelValue"])
415
+ })
289
416
  ]);
290
417
  };
291
418
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@achyutlabsau/vue-payment-gateway",
3
3
  "private": false,
4
- "version": "0.2.6",
4
+ "version": "0.2.8",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",