npm.io
1.12.1 • Published 2 weeks ago

@munchi_oy/payments

Licence
UNLICENSED
Version
1.12.1
Deps
0
Size
287 kB
Vulns
0
Weekly
0

@munchi_oy/payments

Payment SDK for Munchi POS clients, including Viva app-to-app support.

Installation

pnpm add @munchi_oy/payments @munchi_oy/core axios

Core Exports

import {
  MunchiPaymentSDK,
  PaymentInteractionState,
  SdkPaymentStatus,
  type AppToAppAdapter,
  type AppToAppConfig,
  type PaymentResult,
} from "@munchi_oy/payments";

App-to-App Integration (Viva)

1) Provide a messaging adapter

The SDK needs a messaging adapter for non-app-to-app providers and fallback flows.

import type { IMessagingAdapter } from "@munchi_oy/payments";

export class MessagingAdapter implements IMessagingAdapter {
  subscribe<T>(_channel: string, _event: string, _onMessage: (data: T) => void) {
    return () => {};
  }
}
2) Provide an app-to-app adapter

Implement openUrl + subscribe using your platform deep-link APIs.

import type { AppToAppAdapter } from "@munchi_oy/payments";
import { Linking } from "react-native";

export class VivaAppToAppAdapter implements AppToAppAdapter {
  async openUrl(url: string) {
    await Linking.openURL(url);
  }

  subscribe(listener: (url: string) => void) {
    const subscription = Linking.addEventListener("url", ({ url }) => {
      listener(url);
    });

    return () => subscription.remove();
  }
}
3) Configure SDK

Use full callback URL in callbackUrl and control Viva callback query format using callbackParamFormat.

import { MunchiPaymentSDK, type AppToAppConfig } from "@munchi_oy/payments";
import { PaymentProvider, ProviderEnum } from "@munchi_oy/core";
import axios from "axios";
import { Platform } from "react-native";

const appToApp: AppToAppConfig = {
  enabled: true,
  appId: "com.example.pos",
  callbackUrl: "myapp://result",
  callbackParamFormat: Platform.OS === "ios" ? "scheme-only" : "full-url",
  adapter: new VivaAppToAppAdapter(),
};

const sdk = new MunchiPaymentSDK(
  axios,
  new MessagingAdapter(),
  {
    channel: ProviderEnum.MunchiPos,
    provider: PaymentProvider.Viva,
    kioskId: "kiosk-123",
    storeId: "351",
  },
  {
    timeoutMs: 120000,
    appToApp,
  },
);
4) Initiate payment
const result = await sdk.initiateTransaction(
  {
    orderRef: "order-123",
    amountCents: 8000,
    currency: "EUR",
    displayId: "display-1",
    options: {
      tipAmount: 0,
      sourceCode: "6532",
    },
  },
  {
    onConnecting: () => {},
    onRequiresInput: () => {},
    onSuccess: (successResult) => console.log(successResult),
    onError: (errorResult) => console.log(errorResult),
  },
);

Platform Setup

iOS
  1. Register your app URL scheme.
  2. Add Viva scheme to query list:
  3. Use callbackParamFormat: "scheme-only" in app-to-app config.

Example (app.config.ts):

export default {
  ios: {
    bundleIdentifier: "com.example.pos",
    infoPlist: {
      LSApplicationQueriesSchemes: ["vivapayclient"],
    },
  },
  scheme: "myapp",
};
Android
  1. Register intent filter for callback scheme.
  2. Ensure vivapayclient can be resolved on device.
  3. Use callbackParamFormat: "full-url" for standard Android app-to-app query behavior.

Callback Semantics

Cancellation vs decline

The SDK maps Viva callback payloads to Munchi failure codes:

  • User-cancel patterns map to payment.cancelled_by_user.
  • Decline patterns (declined, failed status variants) map to payment.declined.

Example iOS cancel callback:

myapp://result?action=sale&status=failure&errorCode=1000&message=Transaction%20canceled%20by%20user
Amount units

All callback monetary fields are treated as minor units (cents):

  • amount
  • tipAmount
  • surchargeAmount

No conversion to major units is done by the SDK.

Fees mapping

For successful Viva callbacks, transaction fees are derived as:

  • tipAmount > 0 -> TIP_AMOUNT
  • surchargeAmount > 0 -> SURCHARGE
  1. Keep appId equal to the native bundle/package id of the installed app.
  2. Keep callbackUrl as full callback URL (<scheme>://result).
  3. Set callbackParamFormat per platform.
  4. Subscribe to SDK state and always handle FAILED, CANCELLED, and SUCCESS.
  5. Persist deep-link debug logs while troubleshooting app-switch flows.

Troubleshooting

canOpenUrl true but no callback arrives
  • Validate appId matches the installed app variant.
  • Validate callback scheme registration.
  • Validate iOS LSApplicationQueriesSchemes includes vivapayclient.
  • Verify the callback URL in logs exactly matches the app scheme.
Callback arrives but result mapping looks wrong
  • Inspect callback status, message, errorCode.
  • Ensure callback is forwarded to SDK listener.
  • Verify callback belongs to current clientTransactionId or ISV_clientTransactionId.
Security note

Do not print ISV_clientSecret or other credentials in production logs.

License

UNLICENSED - Private package.