{
  "name": "Usakey: send a signed license request",
  "nodes": [
    {
      "parameters": {},
      "id": "782cd58b-82c2-4b3b-b287-1f27bc110fa5",
      "name": "When clicking Test workflow",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// 購入の内容（例）。自分のトリガー（フォーム・ストア・CRM など）のノードに置き換えてください。\n// Sample purchase. Replace this node with your own trigger (a form, a store, a CRM, ...).\nreturn [{\n  json: {\n    action: \"issue\",            // issue / change / renew / suspend / resume / revoke\n    purchase_id: \"order-1001\",  // the same purchase keeps the same value\n    item: \"pro-yearly\",         // the item code mapped in Usakey\n    email: \"buyer@example.com\",\n    name: \"Taro Yamada\"\n  }\n}];"
      },
      "id": "7dff8b74-8a90-4fdd-85a4-6e7060af8b29",
      "name": "Sample purchase",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Usakey の汎用の受け口へ送る本文と、署名する文字列（\"<時刻>.<イベントID>.<本文>\"）を作る。\n// Builds the body for the Usakey generic endpoint and the string to sign (\"<timestamp>.<event id>.<body>\").\nreturn $input.all().map((item) => {\n  const input = item.json;\n  const payload = {\n    action: input.action,\n    purchase_id: String(input.purchase_id),\n  };\n  if (input.item) payload.item = String(input.item);\n  if (input.email || input.name) {\n    payload.customer = {};\n    if (input.email) payload.customer.email = String(input.email);\n    if (input.name) payload.customer.name = String(input.name);\n  }\n  if (input.expires_at) payload.expires_at = String(input.expires_at);\n  if (input.reason) payload.reason = String(input.reason);\n  const body = JSON.stringify(payload);\n  const timestamp = String(Math.floor(Date.now() / 1000));\n  // イベントIDは出来事ごとに一意にし、送り直すときだけ同じ値にする（Usakey は同じIDを1回だけ処理する）。\n  // トリガーが出来事のID（event_id）を持っていればそれを、無ければこの実行のIDを使う。\n  // Use one unique ID per event and the same ID only when resending (Usakey processes each ID once).\n  // Use the trigger's own event_id when it has one, otherwise this execution's ID.\n  const rawId = input.event_id ? String(input.event_id) : `${input.action}-${input.purchase_id}-${$execution.id}`;\n  const eventId = rawId.replace(/[^A-Za-z0-9._:-]/g, \"-\").slice(0, 128);\n  return { json: { body, timestamp, eventId, signedPayload: `${timestamp}.${eventId}.${body}` } };\n});"
      },
      "id": "5c0b9a0b-456b-4067-9295-88a1e8fa9d57",
      "name": "Build signed request",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "action": "hmac",
        "type": "SHA256",
        "value": "={{ $json.signedPayload }}",
        "dataPropertyName": "signatureHex",
        "encoding": "hex"
      },
      "id": "9db3e71a-8e8c-455e-af9f-c8b94c120463",
      "name": "Sign with the Usakey signing secret",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 2,
      "position": [
        660,
        0
      ],
      "notes": "Create a Crypto credential and put the signing secret shown in Usakey (usk_sales_...) in Hmac Secret."
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://usakey.jp/integrations/sales/REPLACE_WITH_YOUR_ENDPOINT_TOKEN/webhook",
        "sendHeaders": true,
        "specifyHeaders": "keypair",
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Usakey-Event-Id",
              "value": "={{ $json.eventId }}"
            },
            {
              "name": "X-Usakey-Timestamp",
              "value": "={{ $json.timestamp }}"
            },
            {
              "name": "X-Usakey-Signature",
              "value": "=v1={{ $json.signatureHex }}"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ $json.body }}",
        "options": {}
      },
      "id": "69600942-2953-43a0-a498-720edb0aff97",
      "name": "Send to Usakey",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        0
      ],
      "notes": "Paste the receiving URL shown on the Usakey integration page."
    }
  ],
  "connections": {
    "When clicking Test workflow": {
      "main": [
        [
          {
            "node": "Sample purchase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sample purchase": {
      "main": [
        [
          {
            "node": "Build signed request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build signed request": {
      "main": [
        [
          {
            "node": "Sign with the Usakey signing secret",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sign with the Usakey signing secret": {
      "main": [
        [
          {
            "node": "Send to Usakey",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false
  }
}
