Magic Checkout Events

onExpressCheckout

It's the event related to the express checkout on the product page.
Returns the current product details and order amount details

/**
   * Express checkout on product page
   * Get the product details on the current product page
   * @returns {Checkout} - a cart with the current product details
   */
  onExpressCheckout: async () => {
    return {
      id: '86749-Ibowbvoo',
      orderAmount: {
        currency: 'EUR',
        amount: '30.00',
      },
      items: [
        {
          id: '84689-2879',
          name: 'Ac-Tion Exfoliating Tonic 90ml',
          quantity: 3,
          unitPrice: {
            currency: 'EUR',
            amount: '10',
          },
          totalAmount: {
            currency: 'EUR',
            amount: '30',
          },
          productUrl: 'https://example.com',
          imageUrl: 'https://picsum.photos/200/300',
          category: 'Perfume',
          variant: [
            {
              color: 'blue',
              size: 'XXXXXXL',
            },
          ],
        },
      ],
    };
  },

onCheckout

It's the event related to the express checkout on the cart and mini cart page.
Returns the current product details and order amount details

onCheckout: async () => {
    return {
      id: '86749-Ibowbvoo',
      orderAmount: {
        currency: 'EUR',
        amount: '60.00',
      },
      orderAmountDetails: {
        shippingAmount: {
          currency: 'EUR',
          amount: '6.00',
        },
        taxAmount: {
          currency: 'EUR',
          amount: '9.00',
        },
        discountAmount: {
          currency: 'EUR',
          amount: '5.00',
        },
        itemSubtotalAmount: {
          currency: 'EUR',
          amount: '50.00',
        },
      },
      items: [
        {
          id: '84689-28979',
          name: 'Cherry Charge 150ml',
          quantity: 4,
          unitPrice: {
            currency: 'EUR',
            amount: '5.00',
          },
          totalAmount: {
            currency: 'EUR',
            amount: '20.00',
          },
          brand: 'Cartier',
          productUrl: 'https://example.com',
          imageUrl: 'https://picsum.photos/200/300',
          variant: [
            {
              color: 'blue',
              size: 'XXXXXXL',
            },
          ],
        },
        {
          id: '84689-2879',
          name: 'Ac-Tion Exfoliating Tonic 90ml',
          quantity: 3,
          unitPrice: {
            currency: 'EUR',
            amount: '10.00',
          },
          totalAmount: {
            currency: 'EUR',
            amount: '30',
          },
          productUrl: 'https://example.com',
          imageUrl: 'https://picsum.photos/200/300',
          category: 'Perfume',
        },
      ],
    };
  },

onCustomerUpdate

Get the updated information from the customer.
This action will be called every time the user will change his information.

/**
   * @param {String} data.checkoutId
   * @param {Array<CustomerInfo>} data.customerInfo - information of the customer.
   * @returns Object - empty object
   */
  onCustomerUpdate: async ({ checkoutId, customerInfo }) => {
    return {};
  },

onShippingAddressChange

Get shipping options with a given address and checkoutId
Returns a list of shipping options with checkoutId

/**
   * get shipping options with given address and returns a list of shipping options with checkoutId
   * @param {String} data.checkoutId
   * @param {Array<Address>} data.shippingAddress - shipping address
   * @returns {Array<ShippingMethod>} shippingMethods- An array of shipping methods
   */
  onShippingAddressChange: async ({ checkoutId, shippingAddress }) => {
    return {
      shippingMethods: [
        {
          name: 'Free shipping',
          amount: { currency: 'EUR', amount: '0' },
          token: 'free',
          isDefault: true,
        },
        {
          name: 'Flat rate',
          amount: { currency: 'EUR', amount: '4.99' },
          token: 'flat',
          isDefault: false,
        },
      ],
    };
  },

onShippingMethodChange

Get order amount details with selected shipping method

/**
   * get order amount with selected shipping method
   * @param {String} data.checkoutId
   * @param {String} data.shippingMethodToken - shipping address
   * @returns {OrderCheckoutAmountDetails}
   */
  onShippingMethodChange: async ({ checkoutId, shippingMethodToken }) => {
    let test = new Promise((resolve) => {
      setTimeout(() => {
        if (shippingMethodToken === 'free') {
          resolve({
            orderAmount: {
              currency: 'EUR',
              amount: '30.00',
            },
          });
        } else {
          resolve({
            orderAmount: {
              currency: 'EUR',
              amount: '31.00',
            },
            orderAmountDetails: {
              shippingAmount: {
                currency: 'EUR',
                amount: '6.00',
              },
              taxAmount: {
                currency: 'EUR',
                amount: '15.00',
              },
              discountAmount: {
                currency: 'EUR',
                amount: '10.00',
              },
              itemSubtotalAmount: {
                currency: 'EUR',
                amount: '20.00',
              },
            },
          });
        }
      }, 1500);
    });

    const result = await test;
    return result;
  },

onCouponCodeAdd

Get updated order amount, checkout items, shipping methods and applied coupons with adding a new coupon

/**
   * get updated order amount, checkout items, shipping methods and applied coupons with adding a new coupon
   * @param {String} data.checkoutId
   * @param {String} data.couponCode
   * @returns {CouponResponse}
   */
  onCouponCodeAdd: async ({ checkoutId, couponCode }) => {
    const response = {
      orderAmount: {
        amount: '64.00',
        currency: 'EUR',
      },
      orderAmountDetails: {
        shippingAmount: {
          currency: 'EUR',
          amount: '0.00',
        },
        taxAmount: {
          currency: 'EUR',
          amount: '9.00',
        },
        discountAmount: {
          currency: 'EUR',
          amount: '5.00',
        },
        itemSubtotalAmount: {
          currency: 'EUR',
          amount: '50.00',
        },
      },
      items: [
        {
          id: '84689-28979',
          name: 'Cherry Charge 150ml',
          quantity: 4,
          unitPrice: {
            currency: 'EUR',
            amount: '5.00',
          },
          totalAmount: {
            currency: 'EUR',
            amount: '20.00',
          },
          brand: 'Cartier',
          productUrl: 'https://www.ditano.com/shop/product/22593',
          imageUrl: 'https://picsum.photos/300',
          variant: [
            {
              color: 'blue',
              size: 'XXXXXXL',
            },
          ],
        },
        {
          id: '84689-2879',
          name: 'Ac-Tion Exfoliating Tonic 90ml',
          quantity: 3,
          unitPrice: {
            currency: 'EUR',
            amount: '10.00',
          },
          totalAmount: {
            currency: 'EUR',
            amount: '30',
          },
          productUrl: 'https://www.ditano.com/shop/product/22593',
          imageUrl: 'https://picsum.photos/300',
          category: 'Perfume',
        },
        {
          id: '84689-289',
          name: 'New item added by coupon',
          quantity: 1,
          unitPrice: {
            currency: 'EUR',
            amount: '0',
          },
          totalAmount: {
            currency: 'EUR',
            amount: '0',
          },
          productUrl: 'https://www.ditano.com/shop/product/22593',
          imageUrl: 'https://picsum.photos/300',
          category: 'Perfume',
        },
      ],
    };

    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (couponCode === 'invalid') {
          reject(new Error('Invalid coupon'));
        } else {
          magicCheckout.coupons.push({ code: couponCode })
          resolve({
            ...response,
            coupons: magicCheckout.coupons,
          });
        }

      }, 1000);
    });
  }

onCouponCodeRemove

Get updated order amount, checkout items, shipping methods and applied coupons with removing a coupon

/**
   * get updated order amount, checkout items, shipping methods and applied coupons with removing a coupon
   * @param {String} data.checkoutId
   * @param {String} data.couponCode
   * @returns {CouponResponse}
   */
  onCouponCodeRemove: async ({ checkoutId, couponCode }) => {
    const response = {
      orderAmount: {
        amount: '50.00',
        currency: 'EUR',
      }
    };

    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (couponCode === 'cannotremove') {
          reject(new Error('Cannot remove the applied coupon'));
          return;
        } else {
          magicCheckout.coupons = magicCheckout.coupons.filter(coupon => coupon.code !== couponCode);
          resolve({
            ...response,
            coupons: magicCheckout.coupons,
          });
        }
      }, 1000);
    });
  }

onOrderCreate

Request that the order get created in the magic server

/**
   * Creates an order in the merchant platform and in the magic backend
   * @param {OrderRequest} data
   * @returns {OrderCreateResponse}
   */
  onOrderCreate: async (data) => {
    const requestBody = {
      orderAmount: {
        currency: 'EUR',
        amount: '76.00',
      },
      taxAmount: {
        currency: 'EUR',
        amount: '1.00',
      },
      shippingAmount: {
        currency: 'EUR',
        amount: '7.60',
      },
      orderReference: 'testorder123',
      items: [
        {
          name: 'Must Parfum',
          quantity: '1',
          unitPrice: { currency: 'EUR', amount: '76.00' },
          totalAmount: { currency: 'EUR', amount: '76.00' },
          productUrl: 'https://example.com',
          imageUrl:
            'https://picsum.photos/200/300',
        },
      ],
      shipping: {
        shippingMethodReference: 'express',
        name: {
          firstName: 'John',
          lastName: 'Smith',
        },
        address: {
          line2: 'Floor 2',
          line1: 'Squires Way',
          locality: 'North Wollongong',
          region: 'New South Wales',
          country: 'Australia',
          countryCode: 'AU',
          notes: 'driveway',
          postalCode: '2500',
        },
      },
      billing: {
        name: {
          firstName: 'John',
          lastName: 'Smith',
        },
        address: {
          line1: 'Squires Way',
          line2: 'Floor 2',
          locality: 'North Wollongong',
          region: 'New South Wales',
          country: 'Australia',
          countryCode: 'AU',
          notes: 'driveway',
          postalCode: '2500',
        },
      },
    };

    const orderId = 'plugin-order-123';

    const createOrderResult = await fetch('http://localhost/v1/orders', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Basic ${btoa(
          'xxxxxx:yyyyyyyy'
        )}`,
      },
      body: JSON.stringify(requestBody),
    }).then((res) => res.json());

    return {
      orderId,
      magicOrderToken: createOrderResult.orderToken,
    };
  },

onOrderComplete

This is used to capture the order on the magic server backend after sucesfully taking payment

onOrderComplete: async (data) => {
    const { orderId, magicOrderToken } = data;

    const getOrderResult = await fetch(
      `http://localhost:8080/v1/orders/${magicOrderToken}`,
      {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Basic ${btoa(
            'xxxxxxxx:yyyyyyyyyy'
          )}`,
        },
      }
    ).then((res) => res.json());

    // use given orderId to validate orders with database

    const captureOrderResult = await fetch(
      `http://localhost:8080/v1/orders/${magicOrderToken}/capture`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Basic ${btoa(
            'xxxxxxxx:yyyyyyy'
          )}`,
        },
      }
    );

    // update merchant platform order status to 'complete'

    if (captureOrderResult.status === 200) {
      return {
        success: true,
        redirectConfirmUrl: 'https://yoursite.com/successpage',
      }
    }

    throw new Error('order complete failed');
  },
};