Fynn Functions erlaubt es den Entwicklern das Verhalten der Backend Logik zu erweitern. Hier erfährst du wie du Fynn Functions einrichtest und verwendest.

Diese Erweiterung befindet sich aktuell in einer geschlossenen Beta-Phase. Bitte kontaktiere uns, um Zugang zu erhalten.

Wie funktioniert Fynn Functions?

Fynn Functions erlaubt es dir, eigene Funktionen zu schreiben, die auf Ereignisse in Fynn reagieren.

Hierfür stellen wir verschiedene Erweiterungs-Punkte zur Verfügung, die du nutzen kannst, um eigene Logik zu schreiben. Sofern für einen Erweiterungs-Punkt eine oder mehrere Funktionen registriert sind, wird diese bei dem entsprechenden Ereignis ausgeführt. Hierbei wird ein Kontext-Objekt übergeben, das Informationen zum Ereignis enthält, dies kann bspw. ein Warenkorb sein. Innerhalb der Funktion kannst du dann beliebige Aktionen ausführen, wie bspw. eine externe API aufrufen. Jede Funktion muss am Ende eine oder mehrere vordefinierte Operationen zurück geben, die anschließend von Fynn ausgeführt werden.

Jeder Erweiterungs-Punkt hat unterschiedliche Kontext-Objekte und Operationen, die du verwenden kannst.

Laufzeiten

Jede Funktion wird in einer isolierten Umgebung ausgeführt, die auf 5 Sekunden begrenzt ist. Bitte beachte, dass sich die Laufzeit einer Funktion direkt auf die Antwortzeit von Fynn auswirkt.

Funktionalitäten in Fynn Functions

Innerhalb von Fynn Functions kannst du alle JavaScript Funktionen verwenden, die auch im Browser verfügbar sind.

Erweiterungs-Punkte

Fynn Functions unterstützt aktuell folgende Erweiterungs-Punkte:

  • Checkout: checkout.cart.delivery, checkout.cart.cart_item_option

Lieferkosten hinzufügen

Der checkout.cart.delivery Erweiterungs-Punkt kann dazu verwendet werden, um Lieferkosten zum Warenkorb hinzuzufügen. Ist der Preis der Lieferkosten einmalig, wird dieser nur in der 1. Rechnung berechnet und ist nicht wiederkehrend. Andernfalls wird der Preis der Lieferkosten in jeder Rechnung berechnet.

Kontext-Objekt

context
DeliveryContext

Operationen

checkout:add_delivery
AddDelivery

Beispiel

function run (input) {
    const countryCode = input?.deliveryCountryCode;
    const itemsCount = input?.cart?.items.length;

  if (itemsCount === 0) return [];

    if (countryCode === 'DE') {
        return [{
            __type: 'checkout:add_delivery',
            product: '14937550-26d0-454a-b4d4-64eabac67663'
        }];
    }

    if (countryCode === 'CH') {
        return [{
            __type: 'checkout:add_delivery',
            product: '5a7f267a-087b-4bdf-a620-79a4e2942545'
        }];
    }

    // more custom logic, e.g. by zip, best price, etc.

    return [];
}

Produkt-Optionen hinzufügen

Der checkout.cart.cart_item_option Erweiterungs-Punkt kann dazu verwendet werden, um Auswahl-Optionen im Warenkorb am Produkt anzuzeigen.

Kontext-Objekt

product
CartItemProductInput
context
CartItemInput

Operationen

checkout:add_cart_item_option_set
AddCartItemOptionSet

Alternativ können Produkt-Optionen auf Basis eines Benutzerdefiniertes Attributes im Produkt hinzugefügt werden.

checkout:add_custom_field_list:as_option_set
AddCustomFieldListAsOptionSet

Beispiel

function run(input) {
  return [
    {
      __type: 'checkout:add_cart_item_option_set',
      product: '0ba377f0-d9e9-4338-a107-9209a6e0f1fb',
      name: 'ab Ausgabe',
      label: 'ab Ausgabe',
      options: [
        {
          label: 'Nr. 24',
          value: '24'
        },
        {
          label: 'Nr. 25',
          value: '25',
          preselected: true,
        },
        {
          label: 'Nr. 26',
          value: '26'
        },
      ]
    }
  ];
}

Funktion registrieren

Um eine Funktion zu registrieren, erstelle ein Support-Ticket um den Zugang zu Fynn Functions zu erhalten.

Globale Kontext-Objekte

export type CartItemProduct

export type CartPublicCustomerAddress = {
  id: string;
  firstName?: string;
  lastName?: string;
  companyName?: string;
  street: string;
  houseNumber?: string;
  zip: string;
  city: string;
  addition?: string;
  countryCode: string;
  costCentre?: string;
  vatId?: string;
}

export type CartPublicItem = {
  name: string;
  description?: string;
  quantity: number;
  type: 'product' | 'plan' | 'delivery';
  id: string;
  periods?: {
    contractPeriod: string;
    cancellationPeriod: string;
  }[],
  quantityDetails: {
    aggregationType: 'count' | 'count_unique' | 'max' | 'sum' | 'average' | 'last_value';
    unit: string;
    description?: string;
    quantityEditable: boolean;
  },
  price: {
    currencyCode: string;
    taxRate?: number;
    totalNetAmount: number;
    type: 'recurring' | 'instant_metered' | 'metered';
    calculationType: 'flat_fee' | 'per_unit' | 'tiered' | 'volume' | 'stair_step' | 'percentage';
    payInAdvance: boolean;
    freeUnits?: number;
    price: {
      amount?: number;
      items?: {
        from: number;
        to?: number;
        amount: number;
        flatAmount: number;
      },
      percentage?: number;
      fixedAmount?: number;
    };
    recurring?: {
      interval: 'day' | 'week' | 'month' | 'year';
      intervalCount?: number;
      trialPeriodDays?: number;
      recurringAmount?: number;
    }
  },
  optionSets: CartPublicItemOptionSet[];
}

export type CartPublicItemOptionSet = {
  label: string;
  name: string;
  options: CartPublicItemOption[];
}

export type CartPublicItemOption = {
  label: string;
  value: string | number | boolean;
  preselected: boolean;
  product?: string | null;
  pricePlan?: string | null;
}

export type CartDiscountDetails = {
  discount: {
    code: string;
    name: string;
    type: 'percentage' | 'fixed_amount';
    percentage?: number;
    fixedAmount?: string;
    frequency: 'once' | 'limited' | 'lifetime';
    frequencyInterval?: number;
  };
  totalAmount: string;
  totalNetBeforeDiscount: string;
};

export type CartPublicPrice = {
  amountDue: number;
  currencyCode: string;
  netAmount?: number;
  taxes?: {
    netAmount: number;
    taxAmount: number;
    rate: number;
  }[];
  discountDetails?: CartDiscountDetails;
}

export type CartPublicSettings = {
  allowCoupons: boolean;
  forceCompany: boolean;
  backButton?: {
    label?: string;
    url: string;
  };
  showDeliveryAddress: boolean;
}

export type CartPublic = {
  id: string;
  customer?: string;
  email?: string;
  invoiceAddress?: CartPublicCustomerAddress;
  deliveryAddress?: CartPublicCustomerAddress;
  items: CartPublicItem[];
  price: CartPublicPrice;
  completionDetails?: {
    invoice: {
      number: string;
      downloadLink: string;
      amount: string;
    } | null,
    payment: {
      reference: string | null;
      method: string;
      bankAccount?: {
        iban: string;
        bic: string;
        bankName: string;
        accountHolder: string;
        reference: string;
      },
      qrCode?: string;
    },
    subscription?: {
      number: string;
    },
    confirmationMessage?: string;
    backToProviderUrl?: string | null;
  },
  settings: CartPublicSettings;
}