Delad betalning POC: App Builder orchestrator AI prompt

Använd den här sidan om du vill kopiera den fullständiga uppmaningen som genererar projektet split-payment-orchestrator: webbåtgärderna payment-orchestrator I/O Event-konsumenten, payment-accept och payment-deny, demo-dashboard och Commerce REST-klienten.

Hur du använder den här uppmaningen

Kopiera allt från PROMPT START till End of prompt till Cursor (med Claude) eller direkt till Claude. Kör frågan från katalogen split-payment-orchestrator/ (App Builder-projektroten).

Innan du kör

Uppmaningen

UPPMANA START

Du genererar en komplett Adobe App Builder-applikation för att organisera delningar i Adobe Commerce. Programmet tar emot I/O-händelser från Commerce, bearbetar delade betalningsbeslut och återanropar Commerce via REST.

Projekt: split-payment-orchestrator
Runtime: Node.js 18
Nyckelberoenden: @adobe/aio-sdk ^6.0.0, got ^11.8.6, oauth-1.0a ^2.2.6

Generera alla filer som listas nedan. Programmet måste fungera med Adobe I/O Runtime (aio app deploy).

Filstruktur att generera

split-payment-orchestrator/
├── package.json
├── app.config.yaml
├── .env.example
└── actions/
    ├── payment-orchestrator/
    │   ├── index.js         ← I/O Event entry point
    │   ├── commerce-client.js
    │   ├── threshold.js
    │   ├── cash-payment.js
    │   ├── order-update.js
    │   └── store-credit.js  ← Deprecated stub; kept for reference
    ├── payment-accept/
    │   └── index.js
    ├── payment-decline/
    │   └── index.js
    └── demo-dashboard/
        └── index.js

package.json

{
  "name": "split-payment-orchestrator",
  "version": "1.0.0",
  "private": true,
  "description": "Adobe App Builder action — split payment PoC orchestrator",
  "engines": { "node": ">=18" },
  "scripts": {
    "deploy": "NODE_OPTIONS=--disable-warning=DEP0040 aio app deploy",
    "aio": "NODE_OPTIONS=--disable-warning=DEP0040 aio"
  },
  "dependencies": {
    "@adobe/aio-sdk": "^6.0.0",
    "@adobe/exc-app": "^1.5.9",
    "got": "^11.8.6",
    "oauth-1.0a": "^2.2.6"
  }
}

app.config.yaml

Definiera fyra åtgärder i paketet split_payment_orchestrator:

payment-orchestrator

  • web: "no" (Endast I/O-händelseutlösare - kan inte anropas direkt via HTTP)
  • runtime: nodejs:18
  • require-adobe-auth: true, final: true
  • Indata från omv: LOG_LEVEL, COMMERCE_BASE_URL, COMMERCE_CONSUMER_KEY, COMMERCE_CONSUMER_SECRET, COMMERCE_ACCESS_TOKEN, COMMERCE_ACCESS_TOKEN_SECRET, PAYMENT_THRESHOLD

payment-accept

  • web: "yes" (HTTP-webbåtgärd - kan anropas av kontrollpanelen eller ERP)
  • runtime: nodejs:18
  • require-adobe-auth: true, final: true
  • Samma Commerce-autentiseringsuppgifter (ingen PAYMENT_THRESHOLD)

payment-decline

  • web: "yes"
  • runtime: nodejs:18
  • require-adobe-auth: true, final: true
  • Samma inloggningsuppgifter för Commerce

demo-dashboard

  • web: "yes"
  • runtime: nodejs:18
  • require-adobe-auth: false¥ Dashboard är offentligt tillgänglig (skyddas endast av DEMO_UI_SECRET om den anges)
  • Indata: alla Commerce-autentiseringsuppgifter + DEMO_UI_SECRET, DEMO_UI_BASE_URL

Händelseregistrering (under events.registrations):

Split payment — sales order place before:
  description: Invokes payment-orchestrator when an order is about to be placed
  events_of_interest:
    - provider_metadata: dx_commerce_events
      event_codes:
        - com.adobe.commerce.observer.sales_order_place_before
  runtime_action: split_payment_orchestrator/payment-orchestrator

actions/payment-orchestrator/commerce-client.js

Delad OAuth 1.0a REST-klient för Adobe Commerce. Implementerar:

createCommerceClient(params, logger) - returnerar { request, baseUrl }

  • Läser COMMERCE_BASE_URL, COMMERCE_CONSUMER_KEY, COMMERCE_CONSUMER_SECRET, COMMERCE_ACCESS_TOKEN, COMMERCE_ACCESS_TOKEN_SECRET från params
  • Utlöses om någon referens saknas
  • Använder oauth-1.0a med HMAC-SHA256 (Node.js crypto.createHmac)
  • Använder got@11 (inte got@12+ - projektet använder CJS) med prefixUrl = ${baseUrl}/rest/V1/
  • Lägger till Authorization-huvud via beforeRequest-krok
  • request(method, path, options) - normaliserar sökvägen (inledande strips /), returnerar { statusCode, body }
  • throwHttpErrors: false - utlöses aldrig 4xx/5xx; returnerar alltid statuskoden

actions/payment-orchestrator/threshold.js

evaluateThreshold({ orderTotal, storeCreditAmount, cashAmount, params, logger }) - returnerar { pass: boolean, reason: string }

Logic:

  1. Läs params.PAYMENT_THRESHOLD; tolka som flyttal; använd som standard 100 om den saknas, NaN eller ≤ 0
  2. If orderTotal > threshold: return { pass: false, reason: 'PAYMENT_THRESHOLD_EXCEEDED' }
  3. If Math.abs((storeCreditAmount + cashAmount) - orderTotal) > 0.02: return { pass: false, reason: 'SPLIT_AMOUNT_MISMATCH' }
  4. Annars: returnera { pass: true, reason: '' }

actions/payment-orchestrator/cash-payment.js

recordCashPending({ commerce, orderId, cashAmount, logger }) - returnerar { ok: boolean, error? }

  • Samtal POST orders/${orderId}/comments med:

    code language-json
    {
      "statusHistory": {
        "comment": "Cash payment of $X.XX pending. Awaiting admin confirmation.",
        "entity_name": "order",
        "parent_id": "<orderId>",
        "is_visible_on_front": true,
        "is_customer_notified": false,
        "status": "pending_payment"
      }
    }
    
  • Returnerar { ok: true } på 2xx; annars returneras { ok: false, error: { code, message } }

  • Omslutningar i try/catch; returnerar felobjekt, utlöser aldrig

actions/payment-orchestrator/order-update.js

updateOrderAfterOrchestration({ commerce, orderId, success, detail, logger }) - returnerar { ok: boolean, error? }

  • Om success: skickar en historikkommentar "Split payment orchestration completed. Order awaiting cash confirmation."
  • Om !success: inlägg "Payment could not be processed. Please try again or contact support." — inkluderar aldrig detail i den kundsynliga kommentaren; logga bara internt detail
  • Returnerar { ok: boolean, error? } - utlöses aldrig

actions/payment-orchestrator/store-credit.js

applyStoreCredit({ commerce, cartId, amount, logger }) - borttagen implementering utan åtgärd

Inkludera den här filen med ett JSDoc @deprecated-meddelande som förklarar:

Orchestrator använder inte längre butikskrediter via REST. Butikskrediten används vid utcheckning i Commerce PHP-modulen (PlaceOrderPlugin) med BalanceManagementInterface::apply(), vilket kräver en aktiv kundvagn. När App Builder tar emot I/O-händelsen är vagnen inaktiv. Den här filen sparas som referens eller för anpassade flöden där butikskrediter används efter beställningen.

Behåll en fungerande implementering (samma form som andra moduler) så att utvecklare kan studera mönstret, men markera det tydligt som om det inte används i det aktuella flödet.

actions/payment-orchestrator/index.js

Startpunkt för I/O-händelse. Implementerar async function main(params).

Nyttolastextrahering:

Adobe Commerce I/O Events kan leverera nyttolasten i flera former. Extrahera ordervärdesobjektet genom att kontrollera sökvägarna i ordning:

  1. params.__ow_body (parsa JSON-sträng om det behövs) → .event.data.value
  2. params.data.value
  3. params.value
  4. params.body.event.data.value
  5. Fall tillbaka till själva params

Fältextrahering från värde:

  • orderId = value.entity_id || value.id

  • orderTotal = parseFloat(value.grand_total ?? value.base_grand_total ?? value.subtotal ?? '0')

  • Dela belopp från value.extension_attributes (markera både extension_attributes och extensionAttributes):

    • storeCredit = parseFloat(ext.split_store_credit_amount ?? value.split_store_credit_amount ?? '0')
    • cash = parseFloat(ext.split_cash_amount ?? value.split_cash_amount ?? '0')

Flöde:

  1. Extrahera värde. Om orderId saknas loggar du fel och returnerar { statusCode: 200, body: { ok: false, message: PUBLIC_ERROR } }
  2. Ring evaluateThreshold(...) - logga och returnera samma svar från 200 om det misslyckas
  3. Anropa createCommerceClient(params, logger) - returnera 200-fel om det misslyckas
  4. Om storeCredit > 0 loggas den butikskrediten vid utcheckning (inget REST-anrop krävs)
  5. Anropa recordCashPending(...) - om det misslyckas, anropa updateOrderAfterOrchestration(..., success: false) och returnera 200-fel
  6. Ring updateOrderAfterOrchestration(..., success: true)
  7. Returnera { statusCode: 200, body: { ok: true, message: 'processed' } }

Viktigt! Returnera alltid statusCode: 200 - I/O-körningsmiljön försöker utföra icke-200-svar igen, vilket skulle orsaka dubblettorderbearbetning. Fel rapporteras i kroppen.

PUBLIC_ERROR-konstanten "Payment could not be processed. Please try again or contact support." - används för alla externa felmeddelanden.

actions/payment-accept/index.js

HTTP-webbåtgärd. Samtal POST /V1/split-payment/orders/:orderId/cash-received.

Upplösning för beställnings-ID: Kontrollera params.orderId, sedan params.payload.orderId och sedan params.__ow_body (parsad JSON). Returnera 400 om det saknas.

Flöde:

  1. Lös orderId; returnera 400 om det saknas
  2. Init commerce client; return 500 if fails
  3. Anropa POST split-payment/orders/${orderId}/cash-received med tom JSON-brödtext
  4. Om 2xx: returnera { statusCode: 200, body: { ok: true, orderId, message: 'accepted' } }
  5. Om fel: logga och returnera { statusCode: 200, body: { ok: false, message: PUBLIC_ERROR } }

actions/payment-decline/index.js

HTTP-webbåtgärd. Samma mönster som payment-accept men anropar POST /V1/split-payment/orders/:orderId/cash-decline.

Returnera { ok: true, orderId, message: 'declined' } när åtgärden lyckades.

actions/demo-dashboard/index.js

Instrumentpanel för självständiga demonstrationsoperatorer. Skapar en HTML-kontrollpanel för att lista väntande kassaorder och utlösa åtgärder för att acceptera/avböja. Detta är en enda webbåtgärd som fungerar för både HTML användargränssnitt och JSON API.

Säkerhet:

  • Valfri DEMO_UI_SECRET-kontroll: Om den anges krävs ?secret=<value>-frågeparam eller x-demo-secret-huvud för alla begäranden. Returnera 401 om det saknas/är fel.
  • Logga en varning om DEMO_UI_SECRET inte har angetts (instrumentpanelen är oskyddad)

Routning (baserat på HTTP-metod + sökväg/brödtext):

Åtgärden tar emot alla begäranden. Bestäm metod från:

  • params.__ow_method (GET/POST) och params.__ow_path eller åtgärdsparametrar
  • GET utan åtgärd → använd HTML kontrollpanel
  • GET med action=list param → returnera JSON-lista över väntande order
  • POST med action=accept och orderId → anropa payment-accept logik (eller infoga Commerce REST-anropet)
  • POST med action=decline och orderId → anropa payment-decline-logik

Hämtar väntande order:

  • Ring GET orders?searchCriteria[pageSize]=50 från Commerce REST
  • Filtrera till order där extension_attributes.split_cash_status === 'pending' AND-ordningen inte är i ett slutläge (complete, closed, canceled, cancelled)
  • Sortera det senaste i minnet
  • Returnera upp till 20 (konfigurerbara via limit param)

HTML Dashboard:
Kontrollpanelen är en HTML-sträng som returneras med Content-Type: text/html. Den bör

  • Lista väntande kassaorder i en tabell: Ordernr (increment_id), enhets_id, kundnamn, kassabelopp, butikskreditbelopp, datum
  • Ange knapparna Acceptera och Avböj för varje ordning som anropar åtgärdens egen API-slutpunkt
  • Visa slutförda/felsvar infogat
  • Inkludera en uppdateringsknapp
  • Formateras tillräckligt för att kunna användas (minimal CSS fungerar; inga externa CDN-beroenden undviker CORS-problem i körningsmiljön)
  • Visa en varningsbanderoll om DEMO_UI_SECRET inte har angetts

Fel i gränssnittet:
När ett Commerce REST-anrop misslyckas inkluderar du HTTP-statusen och en kort beskrivning av Commerce-felmeddelandet (sanera — strip HTML-taggar, trunkera till 500 tecken). Visa inte autentiseringsuppgifter.

Hjälp med svar:

function jsonResponse(statusCode, obj, extraHeaders = {}) { ... }
function htmlResponse(html) { ... }

.env.example

# Commerce REST base URL — no trailing slash
COMMERCE_BASE_URL=

# OAuth 1.0a integration credentials (Admin → System → Integrations)
COMMERCE_CONSUMER_KEY=
COMMERCE_CONSUMER_SECRET=
COMMERCE_ACCESS_TOKEN=
COMMERCE_ACCESS_TOKEN_SECRET=

# PoC threshold — must match split_payment/general/threshold in Commerce (default: 100)
PAYMENT_THRESHOLD=100

LOG_LEVEL=info

# Demo dashboard optional shared secret
DEMO_UI_SECRET=
DEMO_UI_BASE_URL=

Distribuera kommando

När du har genererat alla filer från katalogen split-payment-orchestrator/:

npm install
cp .env.example .env
# Edit .env with your credentials
aio app deploy

Observera URL-adresserna som skrivs ut av aio app deploy efter distributionen. URL:en demo-dashboard är den plats där du kommer åt kontrollpanelen för operatorer.

Frågeslut

Relaterade POC-resurser för delad betalning

recommendation-more-help
commerce-learn-help-home