Версия: 0.0.17
На главную

Использование

Установка:

Добавьте тэг <script> в ваш index.html:

<script src="https://dev-sdk.paybetget.cash/0-0-17/sdk.js"></script>

TLDR (React)

Typescript типы

Принцип работы:

SDK добавляет в window новый объект: paymentWidgetSDK. В нём есть метод render. Его можно вызывать множество раз, работает как render в React (и похожих библиотеках). Для работы виджета нужно передать ряд данных о вашем приложении:

  1. Название бренда вашего приложения (напр. “mostbet”)
  2. Код сайта. Он сообщает какой именно бэкенд используется. Например “mostbet” для production и “mostbet_dev17” для dev стенда.
  3. Payment token. Это токен, который нужен для общения с бэком виджета. Его получает ваше приложение у вашего же бэка.
  4. Тип виджета. Пополнение или вывод денег. Если пользователь пополняет счёт - значит “refill”, если выводит деньги - значит “payout”
  5. Валюта пользователя. Пользователь в вашем приложении выбрал валюту с которой работает. Вот её нужно передать.
  6. Окружение: дев стенд или продакшн.

Полный список параметров:

export interface Options {
  /**
   * Контейнер для виджета. Может быть HTMLElement или CSS-селектор.
   * В этот контейнер добавится iframe в котором отобразится виджет
   */
  container: Container;
  /**
   * Этим свойством регулируем стили и прочие особенности для конкретного бренда.
   * Например вы работаете над сайтом 'mostbet.com', значит сюда надо передать 'mostbet'.
   * Таким образом виждет будет отображаться со стилями предназначенными для вашего сайта.
   */
  brand: string;
  /**
   * Код вашего сайта, указывающий на конкретный API для использования.
   * Например `mostbet` или `mostbet_dev17` 
   */
  siteCode: string;
  /**
   * Тип виджета - пополнение или вывод
   */
  widgetType: WidgetType;
  /** Текущая валюта пользователя. Нужно для аналитики */
  userCurrency: string | null | undefined;
  /** Показать / скрыть виджет */
  isVisible: boolean;
  /**
   * Перед каждым запросом на бэк, виджету нужно иметь токен.
   * Как правило он получается вами от вашего бэка.
   * При любом изменении пользователя, его настроек, нужно получить новый токен.
   *  `null` означает, что токен запросили, но пока не получен.
   * В этом случае виджет покажет экран загрузки.
   */
  paymentToken: string | null;
  /**
   * Подписка на события виджета: редиректы, запрос открытия страниц настроек и прочее:
   * 
   * 
   * https://confluence.dats.tech/pages/viewpage.action?pageId=809240783 
   */
  onWidgetEvent?: (event: WidgetEvent) => void;
  /**
   * имя css класса для iframe
   */
  className?: string;
  /**
   * Функция для отправки GET запросов к API.
   * Если у вас модифицирован `fetch` (старые версии next.js) или вы хотите
   * как-то модифицировать запросы - передайте сюда свою функцию.
   * @default window.fetch
   */
  makeGetRequest?: (url: string) => Promise<
    {
      status?: number;
      statusText?: string;
    } & (
      | {
          data: unknown;
        }
      | {
          json: () => Promise<unknown>;
        }
    )
  >;
  /**
   * Функция для отправки аналитики
   */
  rstatPushHandler?: (eventName: string, eventData: Record<string, unknown>) => void;
  /**
   * Определяет к какому API будет стучаться виджет, к проду или деву:
   * 
   * dev: апи запросы шлёт в 'https://dev.paybet.cash', либо в dev указаный
   * в куке `PW_DEV`, например 'https://dev-1.paybet.cash'
   * prod: апи запросы шлёт в 'https://paybet.cash'
   * 
   */
  environment: 'dev' | 'prod';
}

Для показа виджета нужно вызвать paymentWidgetSDK.render(options). При каждом изменении options следует вызывать paymentWidgetSDK.render(options), чтобы UI всегда был синхронизирован. Его можно вызывать много раз, если значения внутри options не изменились, то и виджет ничего не сделает.

Чтобы скрыть/показать виджет, просто поменяйте значение isVisible и вызовите render


События виджета

В некоторых случаях виджет должен осуществлять редирект на страницы вашего приложения Для этого воспользуйтесь параметром Options['onWidgetEvent']:

paymentWidgetSDK.render({
  ...options,
  onWidgetEvent: (event) => {
    switch (event.type) {
      case 'PW_WIDGET_CLOSE':
        window.location.assign('/');
        return;
      case 'PW_WIDGET_OPEN_RULES_PAGE':
        window.location.assing('/rules');
        return;
      case 'PW_WIDGET_OPEN_PROFILE_EDIT_PAGE':
        window.location.assing('/profile');
        return;
      case 'PW_WIDGET_OPEN_BONUS_PROGRESS':
        window.location.assing('/bonuses');
        return;
      default:
        return;
    }
  }
})

Полный список методов:

export interface PaymentWidgetSDK {
  render: Render;
  /**
   * Отмонтирует, монтирует заново и рендерит виджет.
   * Для случаев когда есть некий баг и рассинхронизированный UI
   */
  reset: Reset;
  /**
   * Метод для отправки сообщений виджету.
   * В настоящее время в ней не должно быть необходимости,
   * всё делается на стороне sdk.
   * Но в будущем это может измениться
   */
  sendWidgetEvent: SendWidgetEvent;
  /** Текущая версия виджета */
  version: string;
  /**
   * Метод для удаления виджета из DOM и очистки памяти.
   * Повторный вызов `render` снова добавит виджет.
   */
  unmount: () => void;
}

Использование в React приложении:

import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useRequest } from 'some-fetching-library';

export const PaymentWidget = ({
  userCurrency,
  isVisible,
  onClose,
}: {
  userCurrency: string | null;
  isVisible: boolean
  onClose: () => void
}) => {
  const [container, setContainer] = useState<HTMLDivElement | null>(null);

  /**
   * @type {{ paymentToken: string | null }}
   */
  const { data: paymentToken = null } = useRequest(async () => {
    const response = await fetch(new URL('/api/get-payment-token', window.location.origin));
    const { paymentToken } = await response.json(); 
    return paymentToken;
  });

	useEffect(() => {
		return () => {
			window.paymentWidgetSDK.unmount();
		};
	}, []);

  const navigate = useNavigate();

  useEffect(() => {
    if (!container) {
      window.paymentWidgetSDK.unmount();
      return;
    }

    window.paymentWidgetSDK.render({
			container,
      brand: 'my_brand',
      siteCode: 'my_brand_site_code',
      widgetType: 'refill',
      environment: import.meta.env.DEV ? 'dev' : 'prod',
      paymentToken,
      userCurrency,
      isVisible,
      onWidgetEvent: (event) => {
        switch (event.type) {
          case 'PW_WIDGET_CLOSE':
            onClose();
            return;
          case 'PW_WIDGET_OPEN_RULES_PAGE':
            navigate('/rules');
            return;
          case 'PW_WIDGET_OPEN_PROFILE_EDIT_PAGE':
            navigate('/profile');
            return;
          case 'PW_WIDGET_OPEN_BONUS_PROGRESS':
            navigate('/progress');
            return;
          default:
            return;
        }
      },
    });
  }, [paymentToken, userCurrency, isVisible, onWidgetEvent, container]);

	return <div ref={setContainer} />;
};

Typescript

Опреледения типов можно скачать отсюда:

curl https://dev-sdk.paybetget.cash/0-0-17/sdk.d.ts -o ./sdk.d.ts

Или просто скопируйте себе это:

/**
 * Payment Widget SDK Type Definitions
 * Version: 0.0.17
 */

/**
 * Контейнер для виджета. Может быть HTMLElement или CSS-селектором
 */
export declare type Container = HTMLElement | CSSSelector;

export declare type CSSSelector = string;

declare type GetRequestFunction = (url: string) => Promise<{
    status?: number;
    statusText?: string;
} & ({
    data: unknown;
} | {
    json: () => Promise<unknown>;
})>;

declare type MessageFromWidget = {
    /**
     * Это сообщение означает, что приложение или не нашло в своём сторе токен,
     * или только запустилось.
     * То есть это не запрос на получение нового токена,
     * а просто такой вот getter
     */
    type: 'TOKEN_REQUEST';
    payload: null;
} | {
    type: 'PW_WIDGET_CLOSE';
    payload: null;
} | {
    type: 'PW_WIDGET_OPEN_RULES_PAGE';
    payload: null;
} | {
    type: 'PW_WIDGET_OPEN_PROFILE_EDIT_PAGE';
    payload: null;
} | {
    type: 'PW_WIDGET_REDIRECT_WITH_POPUP_VALUE';
    payload: {
        url: string;
    };
} | {
    type: 'PW_WIDGET_REDIRECT';
    payload: {
        url: string;
    };
} | {
    type: 'PW_WIDGET_REDIRECT_IN_NEW_TAB';
    payload: {
        url: string;
    };
} | {
    type: 'PW_WIDGET_IFRAME_LOADER_READY';
    payload: null;
} | {
    type: 'PW_WIDGET_OPEN_BONUS_PROGRESS';
    payload: null;
} | {
    type: 'PW_WIDGET_NOTIFICATION_REFILL';
    payload: {
        refillId: string;
        userId?: string;
    };
} | {
    type: 'PW_WIDGET_NOTIFICATION_PAYOUT';
    payload: {
        payoutId: string;
        userId?: string;
    };
};

declare type MessageToWidget = {
    type: 'PW_WIDGET_UPDATE_TOKEN';
    payload: {
        token: string;
    };
} | {
    type: 'PW_WIDGET_CLOSE';
    payload: null;
} | {
    type: 'PW_WIDGET_OPEN';
    payload: {
        token: string;
        widgetType: WidgetType_2;
    };
};

export declare interface Options {
    /**
     * Контейнер для виджета. Может быть HTMLElement или CSS-селектором.
     * В этот контейнер добавится iframe в котором отобразится виджет
     */
    container: Container;
    /**
     * Этим свойством регулируем стили и прочие особенности для конкретного бренда.
     * Например вы работаете над сайтом 'mostbet.com',
     * значит сюда надо передать 'mostbet'.
     * Таким образом виждет будет отображаться со стилями предназначенными
     * для вашего сайта.
     */
    brand: string;
    /**
     * Код вашего сайта.
     * Указывает на конкретный API для использования.
     * Например `mostbet` или `mostbet_dev17`
     */
    siteCode: string;
    /**
     * Тип виджета - пополнение, вывод и т.п.
     */
    widgetType: WidgetType;
    /** Текущая валюта пользователя. Нужно для аналитики */
    userCurrency: string | null | undefined;
    /** Показать / скрыть виджет */
    isVisible: boolean;
    /**
     * Перед каждым запросом на бэк, виджету нужно иметь токен.
     * Как правило он получается вами от вашего бэка.
     * При любом изменении пользователя, его настроек, нужно получить новый токен.
     * Проще всего получать токен при каждом открытии виджета (изменении `isVisible`)
     *  `null` означает, что токен запросили, но пока не получен
     */
    paymentToken: string | null;
    /**
     * Подписка на события виджета: редиректы, запрос открытия страниц настроек и прочее:
     *
     *
     * https://confluence.dats.tech/pages/viewpage.action?pageId=809240783
     */
    onWidgetEvent?: (event: WidgetEvent) => void;
    /**
     * имя css класса для iframe
     */
    className?: string;
    /**
     * Функция для отправки GET запросов к API.
     * Если у вас модифицирован `fetch` (старые версии next.js) или вы хотите
     * как-то модифицировать запросы - передайте сюда свою функцию.
     * @default window.fetch
     */
    makeGetRequest?: GetRequestFunction;
    /**
     * Функция для отправки аналитики
     */
    rstatPushHandler?: (eventName: string, eventData: Record<string, unknown>) => void;
    /**
     * Определяет к какому API будет стучаться виджет, к проду или деву:
     * ```
     * dev: апи запросы шлёт в 'https://dev.paybet.cash', либо в dev указаный
     * в куке `PW_DEV`
     * prod: апи запросы шлёт в 'https://paybet.cash'
     * ```
     */
    environment: 'dev' | 'prod';
}

export declare interface PaymentWidgetSDK {
    /**
     * Монтирует, если нужно, и показывает виджет.
     * При одинаковых Options ничего не делает.
     */
    render: Render;
    /**
     * unmount + mount + render
     */
    reset: Reset;
    /**
     * В настоящее время эта функция не нужна никому,
     * всё делается на стороне sdk.
     * Но в будущем это может измениться
     */
    sendWidgetEvent: SendWidgetEvent;
    /** Текущая версия виджета */
    version: string;
    /**
     * Метод для удаления виджета из DOM и очистки памяти
     */
    unmount: () => void;
}

declare type Render = (options: Options) => void;

declare type Reset = () => void;

export declare interface RStatCommonData {
    page_type: 'widget';
    currency?: string;
}

/**
 * В настоящее время эта функция не нужна никому,
 * всё делается на стороне sdk.
 * Но в будущем это может измениться
 */
export declare type SendWidgetEvent = (event: MessageToWidget) => void;

export declare type WidgetEvent = Extract<MessageFromWidget, {
    type: 'PW_WIDGET_CLOSE';
} | {
    type: 'PW_WIDGET_OPEN_RULES_PAGE';
} | {
    type: 'PW_WIDGET_OPEN_PROFILE_EDIT_PAGE';
} | {
    type: 'PW_WIDGET_REDIRECT_WITH_POPUP_VALUE';
} | {
    type: 'PW_WIDGET_IFRAME_LOADER_READY';
} | {
    type: 'PW_WIDGET_OPEN_BONUS_PROGRESS';
} | {
    type: 'PW_WIDGET_NOTIFICATION_REFILL';
} | {
    type: 'PW_WIDGET_NOTIFICATION_PAYOUT';
}> | {
    /**
     * Срабатывает на iframe.onload
     */
    type: 'IFRAME_LOADED';
    payload: {
        iframe: HTMLIFrameElement;
    };
} | {
    /**
     * Срабатывает когда виджет добавлен в DOM, загрузил скрипты и получил token
     */
    type: 'WIDGET_READY';
    payload: {
        iframe: HTMLIFrameElement;
    };
} | {
    type: 'SET_IFRAME_REF';
    payload: {
        iframe: HTMLIFrameElement | null;
    };
};

export declare type WidgetType = 'payout' | 'refill';

declare type WidgetType_2 = 'refill' | 'payout';

export { }
;