Skip to main content

React

import { useEffect, useRef } from 'react';
import { MyazaPOS } from '@myazahq/pos-sdk';

export function CheckoutButton({ amount }: { amount: number }) {
  const posRef = useRef<MyazaPOS | null>(null);

  useEffect(() => {
    const pos = new MyazaPOS({
      merchantId: process.env.REACT_APP_MYAZA_MERCHANT_ID!,
      isSandbox: true,
    });

    pos.init().then(() => {
      posRef.current = pos;
    });

    pos.on('payment.confirmed', (event) => {
      alert(`Payment confirmed: ${event.session.id}`);
    });

    return () => {
      pos.terminate();
    };
  }, []);

  const handleCheckout = async () => {
    if (!posRef.current) return;
    await posRef.current.checkout({ amount, currency: 'USD' });
  };

  return <button onClick={handleCheckout}>Pay ${amount}</button>;
}

Next.js (App Router)

The SDK manipulates the DOM, so it must run client-side only.
'use client';

import { useEffect, useRef } from 'react';
import { MyazaPOS } from '@myazahq/pos-sdk';

export function PaymentButton({ amount }: { amount: number }) {
  const posRef = useRef<MyazaPOS | null>(null);

  useEffect(() => {
    const pos = new MyazaPOS({
      merchantId: process.env.NEXT_PUBLIC_MYAZA_MERCHANT_ID!,
      isSandbox: process.env.NODE_ENV !== 'production',
    });

    pos.init().then(() => {
      posRef.current = pos;
    });

    pos.on('payment.confirmed', (event) => {
      // Call your API route to verify and fulfill
      fetch('/api/verify-payment', {
        method: 'POST',
        body: JSON.stringify({ sessionId: event.session.id }),
      });
    });

    return () => {
      pos.terminate();
    };
  }, []);

  return (
    <button onClick={() => posRef.current?.checkout({ amount, currency: 'USD' })}>
      Pay with Crypto
    </button>
  );
}
Use 'use client' at the top of the file. The SDK requires browser APIs and cannot run during server-side rendering.

Vue 3

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { MyazaPOS } from '@myazahq/pos-sdk';

const props = defineProps<{ amount: number }>();
const pos = ref<MyazaPOS | null>(null);

onMounted(async () => {
  const instance = new MyazaPOS({
    merchantId: import.meta.env.VITE_MYAZA_MERCHANT_ID,
    isSandbox: true,
  });

  instance.on('payment.confirmed', (event) => {
    console.log('Confirmed:', event.session.id);
  });

  await instance.init();
  pos.value = instance;
});

onUnmounted(() => {
  pos.value?.terminate();
});

const checkout = () => {
  pos.value?.checkout({ amount: props.amount, currency: 'USD' });
};
</script>

<template>
  <button @click="checkout">Pay ${{ amount }}</button>
</template>

Nuxt 3

Wrap the SDK in a client-only component:
<!-- components/CryptoCheckout.client.vue -->
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { MyazaPOS } from '@myazahq/pos-sdk';

const props = defineProps<{ amount: number }>();
const pos = ref<MyazaPOS | null>(null);

onMounted(async () => {
  const instance = new MyazaPOS({
    merchantId: useRuntimeConfig().public.myazaMerchantId,
    isSandbox: true,
  });

  instance.on('payment.confirmed', (event) => {
    console.log('Confirmed:', event.session.id);
  });

  await instance.init();
  pos.value = instance;
});

onUnmounted(() => {
  pos.value?.terminate();
});
</script>

<template>
  <button @click="pos?.checkout({ amount, currency: 'USD' })">
    Pay ${{ amount }}
  </button>
</template>
The .client.vue suffix ensures Nuxt only renders this component in the browser.

Svelte / SvelteKit

<script lang="ts">
  import { onMount, onDestroy } from 'svelte';
  import { MyazaPOS } from '@myazahq/pos-sdk';

  export let amount: number;

  let pos: MyazaPOS | null = null;

  onMount(async () => {
    pos = new MyazaPOS({
      merchantId: import.meta.env.VITE_MYAZA_MERCHANT_ID,
      isSandbox: true,
    });

    pos.on('payment.confirmed', (event) => {
      console.log('Confirmed:', event.session.id);
    });

    await pos.init();
  });

  onDestroy(() => {
    pos?.terminate();
  });

  function checkout() {
    pos?.checkout({ amount, currency: 'USD' });
  }
</script>

<button on:click={checkout}>Pay ${amount}</button>

Plain JavaScript (CDN)

No build tools required. Include the UMD bundle via a script tag:
<!DOCTYPE html>
<html>
<head>
  <title>Pay with Crypto</title>
  <script src="https://unpkg.com/@myazahq/pos-sdk@latest/dist/index.umd.js"></script>
</head>
<body>
  <button id="pay-btn">Pay $25.00</button>

  <script>
    const pos = new MyazaPOS({
      merchantId: 'your-merchant-id',
      isSandbox: true,
    });

    pos.init().then(() => {
      document.getElementById('pay-btn').addEventListener('click', () => {
        pos.checkout({ amount: 25.00, currency: 'USD' });
      });
    });

    pos.on('payment.confirmed', (event) => {
      document.body.innerHTML = '<h1>Payment received!</h1>';
    });
  </script>
</body>
</html>

Server-Side Verification

Regardless of framework, always verify the payment on your backend before fulfilling:
// Your API route / server endpoint
app.post('/api/verify-payment', async (req, res) => {
  const { sessionId } = req.body;

  // Verify directly with Myaza API
  const session = await fetch(
    `https://secureapi.gridlog.io/api/v1/pos/sessions/${sessionId}`,
    { headers: { 'X-API-Key': process.env.MYAZA_API_KEY } }
  ).then(r => r.json());

  if (session.status === 'paid_out' || session.status === 'paid') {
    await fulfillOrder(session.metadata.orderId);
    return res.json({ success: true });
  }

  res.status(400).json({ error: 'Payment not confirmed' });
});