Tiburon logo color

Gustafsbergs Porslinsfabrik integrerar ERP/affärssystem med Shopify Flow

Gustafsbergs Porslinsfabrik integrerar ERP/affärssystem med Shopify Flow

En oro de flesta företag har när de ska göra en integration mellan två system är hur det ska förvaltas över tid och om kompetens kommer finnas kvar för att göra det. Låter man en konsult göra arbetet finns en risk att man hamnar i knät på denne och en beroendeställning skapas. Vem har inte varit involverat i ett projekt där en av de drivande faktorerna bakom är att ingen längre förstår hur nuvarande system fungerar? Just därför är vi så nöjda med just den här lösningen.

Koppla ihop system med lättförståeliga flödesscheman

I många fall finns det Shopify-appar som är gjorda just för att koppla ihop ett specifikt affärssystem med Shopify, men i andra fall behöver man skapa en egen integration. Historiskt har det gått till så att man skrivit kod som körts på en server som agerat som en slags brygga mellan butiken och affärssystemet. Den typen av lösning kräver underhåll och drift av kod och server vilket setts som ett nödvändigt ont, fram till nu. Se screenshot nedan på Gustafsbergs integration:

The full Shopify -> ERP flow

Den första integrationspunkten, och denna bloggpost, handlar om att få en order som läggs i Shopify att även skapas i affärssystemet. Detta går att göra i Shopify flow med tre olika byggstenar:

  • Trigger: En händelse som startar flödet. Det kan exempelvis vara ett klockslag eller att en order läggs.
  • Condition: Ett villkor som t.ex. att en order innehåller en viss mängd produkter eller att kunden är från ett visst land.
  • Action: En handling, som att skicka ett email, göra ett HTTP-anrop eller uppdatera ett fält på en kund.

Dessa byggklossar använder vi sedan för att konstruera ett flöde som går att dela in i dessa moment:

  1. Autentisering: Med hjälp av en hemlig nyckel identifierar sig Shopify Flow och får access till API för ERP.
  2. Skapa kund i ERP: En kund skapas i ERP med email, postadress, namn osv från Shopify.
  3. Skapa order i ERP: En order skapas i ERP med de artiklar som beställdes i Shopify.

1. Autentisering

Detta är den mest komplicerade delen av flödet fram till helt nyligen inte var möjlig att göra med enbart Shopify Flow. Externa API:er kan sköta autentisering på lite olika sätt, i Gustafsbergs fall bygger det på att göra ett HTTP-anrop med en hemlig nyckel till en endpoint som i sin tur returnerar en kortlivad så kallad "Bearer token". Denna token sparar vi sedan i en variabel för att använda i kommande anrop till ERP.

Authentication Flow

Det absolut första blocket är "Order created" och är bara en trigger som får detta flow att köras varje gång en order skapas, dvs när någon köper något i butiken. När det händer körs nästa block, "Send HTTP request", vars uppgift är att visa för ERP att vi är vi och att vi vill ha en token för att kunna göra fler anrop. Öppnar man upp själva blocket ser det ut såhär:

Send HTTP request

Get bearer token

Det varierar som sagt mellan API och API exakt hur detta ser ut. Ibland är det en "GET" som i screenshot, ibland en "POST". Ibland skickas den hemliga nyckeln i en header, ibland i "BODY". En viktig sak är att spara hemliga nycklar i vad shopify kallar "Secrets". Då syns de inte i klartext och minimerar risken för läckor. För att göra det är det bara att klicka "Add secret".

Run code

Run code

Detta är blocket vi valt för att hantera responsen från "Send HTTP request". I vissa fall behövs det inte då den råa-responsen går att använda i varje efterföljande block, men i just detta fall är svaret i JSON-format och vi behöver "klippa ut" själva nyckeln och formatera den så att den enkelt kan användas i kommande anrop till ERP. Koden nedan används i några varitioner på tre ställen i detta Flow och är den enda tradionella koden som behövs i detta fall.

export default function main(input) {
  const body = JSON.parse(input.sendHttpRequest.body);
  return {
    token: `Bearer ${body.access_token}`
  }
}

Shopify flow har stöd för ECMA2020 Javascript med vissa begränsningar. På dessa rader görs två saker:

  1. JSON.parse - tar den textbaserade JSON-responsen från ERP och omvandlar den till ett javascript-object
  2. return - Tar propertyn access_token och returnerar den med text-strängen "Bearer " i stil med Bearer x5!j8%f92GP)t.

Det går att skriva mycket mer kraftfull och invecklad kod i detta block, men en av de fina sakerna med Flow är hur lätt man får överblick över hela flödet och hur snabbt en ny person kan sätta sig in i det. Därför bör "Run code"-block bara användas när de verkligen behövs.

Condition

Condition

Efter detta kör vi vårt första "Condition"-block vars uppgift är att avgöra om kunden som la ordern är ny eller redan existerar i ERP. Det enda vi gör är egentligen att kontrollera om ett metafield på kunden har ett värde eller ej. Om det har det innebär det att vi redan har kört detta flöde en gång tidigare och i detta metafield sparat det kundnummer kunden har fått i ERP. I denna genomgång kommer vi bara hantera den gren som körs om kunden inte redan existerar. Flödet som skulle körts om kunden redan existerar är nämligen bara en förenklad version och denna bloggpost är redan lång som den är.

2. Skapa kund i ERP

Skapa kund i ERP - screenshot

Nu när vi verifierat att kunden inte existerar i ERP kan vi med tre block skapa en kund i ERP och sedan spara kundnumret som ett metafield på kunden i Shopify så att vi vet vilken Shopify-kund matchar vilken ERP-kund.

Send HTTP request

Post customer to ERP - screenshot

Om vi jämför detta HTTP-anrop med det som gjordes vid autentiseringen ser vi dessa skillnader:

  1. HTTP-metoden är satt till "POST" istället för "GET" vilket indikerar att vi skapar något i ERP, en kund.
  2. Det finns en header med namnet "Authorization" och värdet {{runCode.token}}. Detta är en referens till den token vi sparade tidigare och som behöver skickas med så att ERP förstår att vilka vi är och att vi har rättigheter att skapa en kund.
  3. Body innehåller ett gäng parametrar som "name", "email" osv. Värderna, som ser ut som {{order.email}} och alltså hämtar email från ordern i Shopify och skickar in den till ERP.

Run code

export default function main(input) {
  const body = JSON.parse(input.sendHttpRequest2.body);
  return {
    customerID: body.customer.customerID
  }
}

Detta block är mycket likt föregående "Run code"-block och dess syfte är att ta fram kundnumret så vi i nästa block kan spara det.

Update customer metafield

Update customer metafield - screenshot

Här tar vi värdet från det det föregående blocket "Run code" och sparar det som ett metafield på kunden i Shopify. Detta är för att i framtida körningar kunna se att kunden redan har skapats i ERP så att vi inte skapar dubbletter. Det är dessutom smidigt att kunna se vilket kundnummer en kund har i ERP när man tittar på en kund i Shopify admin.

3. Skapa order i ERP

Create order in ERP - screenshot

Detta är det tredje och sista momentet i detta flöde och handlar om att skapa den faktiska ordern i ERP. Detta gör på ett sätt väldigt likt hur vi skapade kunden tidigare med en skillnad; vi gör inte som med kunden och kontrollerar och kontrollerar om ordern redan är skapad då vi kan räkna med att varje order är unik. I övrigt är denna del av flödet nästan identiskt, men vi går igenom det för tydlighetens skull.

Send HTTP request

Post order to ERP - screenshot

I detta anrop som skapar själva ordern i ERP görs en ny sak som inte görs i tidigare HTTP-anrop. Vi loopar igenom alla orderradline-items i beställningen för att få in varje enskild rad i ERP.

"rows": [{
  % for lineItems_item in order.lineItems %}
    { 
      "sku": "{{lineItems_item.sku}}",
      "quantity": {{lineItems_item.quantity}}
    }
    {% unless forloop.last %}, {% endunless -%}
  {% endfor %}]

Det denna kod gör är att plocka ut SKU och quantity för varje orderrad och lägga dem i en lista i JSON-format. Exakt vad som behöver skickas med är olika mellan olika ERP, men normalt är det minst just SKU och quantity. Andra ERP kan behöva ytterligare fält eller vara formaterade i XML eller andra format.

Run Code

export default function main(input) {
  const body = JSON.parse(input.sendHttpRequest3.body);
  return {
    erpOrderID: body.cuorder.orderID
  }
}

Ytterligare ett "Run Code"-block som likt tidigare bara tar fram ett id, i detta fall ett ordernummer från ERP, så att vi kan använda det i vårt allra sista block. Ett ERP returnerar inte nödvändigtvis ett ordernummer vid skapandet av en order och man kan då behöva ytterligare ett "Sent HTTP Request"-block för att hämta upp det.

Update Order Metafield

Update Order Metafield - screenshot

I det sista blocket tar vi det ordernummer vi fick från ERP och sparar det som en metafield på ordern i Shopify. På så sätt vet vi vilken den matchande ordern är i ERP, vilket kan hjälpa oss att expediera ordern, men det är en saga för en annan gång.

Sammanfattning

Detta framstår kanske som ett långrandigt och krångligt sätt att skapa en order i ERP jämfört med det traditionella sättet att skriva 50-100 rader kod och sköta allt där. Vi anser dock att detta visuella flöde har flera fördelar.

  1. Tydligt - Det är lättare att förstå för en icke-tekniker. Även om de individuella blocken kan vara svåra att förstå är schemat som helhet lätt att greppa.
  2. Vidareutveckling - Eftersom det är lättare att förstå vad som händer är det även lättare att lägga till och ändra funktionalitet. Kanske vill vi lägga till en tagg på kund eller order; det finns block för det.
  3. Underhåll - Shopify uppdaterar sina API:er med jämna mellanrum, men oftast är det inte "Breaking changes". Många integrationer som dessa kan köras i år.
  4. Loggning - Vid varje körning skapar Shopify en logg där man enkelt kan se vad som hände i varje enskilt block om man skulle behöva felsöka flödet.
  5. Ingen server - Ni slipper installera säkerhetsuppdateringar och ha ytterligare en sak att bry er om.
  6. Snabb utveckling - Det tar inte lång tid att bygga ett enklare flöde som detta.

Bygg er nästa integration i Flow! Se hur långt det tar er. Antingen är det en interimslösning medan ni bygger en större integration eller så duger detta gott.