Skip to content

Cartenvo Integration Hub docs

Pipedream

Connect nopCommerce to Pipedream: check webhook signatures, send orders to Google Sheets and Slack, and call the store.

On this page

Pipedream receives store events with its HTTP / Webhook trigger, and can check their signatures and call the store in a Node.js code step.

1. Paid order → Google Sheets row

Catch the event

  1. In Pipedream, create a workflow. For the trigger, choose HTTP / Webhook → New Requests and save it. Pipedream shows the endpoint URL: copy it.
  2. In the store's admin, open Configuration → Integration Hub → Webhooks → Add webhook and choose Zapier, Make or n8n.
    • Name: "Pipedream: orders"
    • URL: the endpoint you copied
    • Events: only order.paid
    • Save, and copy the signing secret it shows once.
  3. Send a sample: open Preview, choose order.paid, an order and the Pipedream webhook, click Show message and then Send to this webhook. The event appears in the trigger; select it.

Check the signature

Pipedream gives the raw body to code steps, so you can refuse messages that didn't come from the store. In the workflow's Settings → Environment variables (or your project's), add CARTENVO_SECRET with the signing secret, make the trigger's HTTP Response "Return a custom response from your workflow", then add a Node.js step:

JavaScript
import crypto from 'crypto';

export default defineComponent({
  async run({ steps, $ }) {
    const event = steps.trigger.event;
    const raw = typeof event.body === 'string' ? event.body : JSON.stringify(event.body);
    const timestamp = event.headers['x-cartenvo-timestamp'];
    const expected = 'sha256=' + crypto.createHmac('sha256', process.env.CARTENVO_SECRET)
      .update(`${timestamp}.${raw}`).digest('hex');
    const signature = event.headers['x-cartenvo-signature'] ?? '';
    const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;
    const valid = fresh && signature.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
    await $.respond({ status: valid ? 200 : 401, body: valid ? 'ok' : 'bad signature' });
    if (!valid) return $.flow.exit('Not signed by the store');
    return typeof event.body === 'string' ? JSON.parse(event.body) : event.body;
  },
});

The signature is over the raw body exactly as sent. Set the trigger to pass the raw body (its event data setting): rebuilding the body with JSON.stringify can change numbers such as 132.00 and fail the check.

Add the row

Add the Google Sheets app's add-row action, connect your Google account, choose the spreadsheet, and fill the columns from the previous step (steps.check_signature.$return_value.data.number and so on):

ColumnValue
Orderdata.number
Customerdata.customer.firstName and data.customer.lastName
Emaildata.customer.email
Totaldata.totals.total
Items{{steps.check_signature.$return_value.data.items.map(i => i.sku).join(", ")}}

Deploy the workflow.

2. New order → Slack message

Another workflow (or the same one, with order.placed added to the webhook's events and a filter on type), then the Slack app's send-message action with:

Example
New order {{steps.check_signature.$return_value.data.number}}: {{steps.check_signature.$return_value.data.totals.total}} {{steps.check_signature.$return_value.data.currency}}

3. Calling the store

Add an API key in admin under API keys, store it as the environment variable CARTENVO_KEY, and call the API from a Node.js step:

JavaScript
export default defineComponent({
  async run({ steps, $ }) {
    const response = await fetch('https://shop.example.com/api/cartenvo/v1/stock', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.CARTENVO_KEY}`,
        'Content-Type': 'application/json',
        'Idempotency-Key': steps.trigger.context.id,
      },
      body: JSON.stringify({ lines: [{ sku: 'MUG-01', adjustment: -1 }] }),
    });
    return await response.json();
  },
});

The Idempotency-Key makes a retried step safe: the store applies the change once. The API guide lists every call.

Things to know

  • Repeats: the store retries a delivery that fails or times out, with the same id. Use it with Pipedream's data stores to skip an event you've already handled.
  • Samples: messages from Send to this webhook have context.sample = true.