Skip to content

feat: Add Status Change Source#20156

Open
ooi2018 wants to merge 11 commits intoPipedreamHQ:masterfrom
ooi2018:add-source-statuschange
Open

feat: Add Status Change Source#20156
ooi2018 wants to merge 11 commits intoPipedreamHQ:masterfrom
ooi2018:add-source-statuschange

Conversation

@ooi2018
Copy link

@ooi2018 ooi2018 commented Mar 3, 2026

WHY

  • Introduce a new source to let user receive notification when a new order's status matched with the user's setting.
  • Useful for merchants to monitor the orders anytime without the needs of login to their site.
  • Can be integrate with other actions to complete the workflow.

Summary by CodeRabbit

  • New Features

    • Added a FraudLabs Pro Status Change Trigger to receive and emit status-change events from FraudLabs Pro.
  • Updates

    • Component package version bumped from 0.4.0 to 0.5.0.

@vercel
Copy link

vercel bot commented Mar 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
pipedream-docs-redirect-do-not-edit Ignored Ignored Mar 5, 2026 3:47pm

Request Review

@pipedream-component-development
Copy link
Collaborator

Thank you so much for submitting this! We've added it to our backlog to review, and our team has been notified.

@pipedream-component-development
Copy link
Collaborator

Thanks for submitting this PR! When we review PRs, we follow the Pipedream component guidelines. If you're not familiar, here's a quick checklist:

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Bumps package version to 0.5.0 and adds a FraudLabs Pro "status_changed" webhook source that subscribes/unsubscribes hooks, stores hookId in DB, handles incoming POSTs, emits deduplicated events, and responds 200.

Changes

Cohort / File(s) Summary
Package Version Update
components/fraudlabs_pro/package.json
Version changed from "0.4.0" to "0.5.0".
Webhook Trigger Source
components/fraudlabs_pro/sources/status_changed/status_change.mjs
New source added implementing FraudLabs Pro status_changed webhook: activate subscribes and stores hookId in DB, deactivate unsubscribes and clears DB, run validates incoming payloads, emits events with deduplication (by order_id), and returns 200 acknowledgments.

Sequence Diagram(s)

sequenceDiagram
    participant Source as FraudLabs Pro Source
    participant API as FraudLabs Pro API
    participant DB as Database
    participant Sender as FraudLabs Pro Service

    rect rgba(100, 200, 100, 0.5)
    Note over Source,DB: Activation
    Source->>DB: check hookId
    DB-->>Source: null / hookId
    alt no hookId
      Source->>API: POST /subscribe (endpoint, description, api_key)
      API-->>Source: { hookId }
      Source->>DB: store hookId
    end
    end

    rect rgba(100, 150, 200, 0.5)
    Note over Sender,Source: Event delivery
    Sender->>Source: POST /<endpoint> status_changed payload
    Source->>Source: validate & emit (dedupe by order_id)
    Source-->>Sender: 200 OK { success: true }
    end

    rect rgba(200, 100, 100, 0.5)
    Note over Source,DB: Deactivation
    Source->>DB: retrieve hookId
    DB-->>Source: hookId
    Source->>API: GET /unsubscribe (hookId, api_key)
    API-->>Source: success
    Source->>DB: clear hookId
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Add Status Change Source' clearly and concisely summarizes the main change—introducing a new webhook source for FraudLabs Pro status change notifications.
Description check ✅ Passed The pull request description follows the required template with the 'WHY' section completed, explaining the purpose, user benefits, and integration capabilities of the new status change source.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/fraudlabs_pro/package.json`:
- Line 3: The package.json version was bumped to "0.5.0" but there is no
CHANGELOG entry; add or update CHANGELOG.md with a new release section for 0.5.0
describing the changes included in this PR and the release date, and commit that
file alongside the package.json change so the version bump in package.json and
the CHANGELOG entry are merged together.

In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs`:
- Around line 9-16: Add a user-configurable status prop and filter emitted
webhook events against it: extend the existing props object (the "props" symbol
near fraudlabsProApp and db) to include a status or statuses prop (string or
array) that users can set, then update the webhook handler that currently emits
every event (the HTTP handler / webhook processor in this module) to check the
incoming event's status field and only emit/forward the event when it matches
the configured status(s). Apply the same props+filter change to the duplicate
block referenced around lines 69-79 so both handlers use the user-configured
status filter.
- Around line 61-67: The code currently clears this.db.set("hookId", null)
unconditionally after calling fetch (in the unsubscribe flow), which can orphan
an active webhook if the remote unsubscribe failed; update the unsubscribe logic
(the async method containing the fetch call) to only clear this.db.set("hookId",
null) after verifying the remote call succeeded (e.g., response.ok and/or
expected response body) and also handle fetch/network errors with a catch so you
don't clear the local hookId on failure; reference the fetch invocation and the
this.db.set("hookId", null) line to implement the conditional clear and error
handling.
- Around line 75-78: The current dedupe key in status_change.mjs uses only
order_id in the this.$emit call (id: body.order_id) which collapses multiple
status updates for the same order; change the emitted id to include the status
and/or a stable event timestamp so each status-change is unique (for example
compose id from body.order_id + body.flp_status + (body.updated_at ||
Date.now())), updating the id field in the this.$emit invocation so it uses that
composite key while keeping summary and ts as-is.
- Around line 71-77: The code assumes event.body is a valid object and directly
accesses body.flp_status and body.order_id in the this.$emit call; add a guard
that verifies event.body is an object (and not null) before accessing fields,
assign a safe fallback object (e.g., {}) to the local variable body when
event.body is missing or malformed, and use safe fallback values for the summary
and id (e.g., "unknown" for flp_status and a timestamp or UUID for id) so
this.$emit(body, {...}) will not throw when event.body is absent or not an
object.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de720ba and e26c931.

📒 Files selected for processing (2)
  • components/fraudlabs_pro/package.json
  • components/fraudlabs_pro/sources/status_changed/status_change.mjs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs`:
- Around line 5-7: Update the component metadata: change the key symbol from
"fraudlabspro_status_change" to the Pipedream-conformant
"fraudlabs_pro-status-change", and correct the description string (the symbol
"description") to read "Trigger to receive data from FraudLabs Pro Screen Order
API if the status change matches your setting." Ensure you update only the key
and description values (leaving version and other fields intact) so the
component follows naming conventions and fixes the grammar.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e26c931 and b98f2e7.

📒 Files selected for processing (1)
  • components/fraudlabs_pro/sources/status_changed/status_change.mjs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
components/fraudlabs_pro/sources/status_changed/status_change.mjs (1)

9-16: ⚠️ Potential issue | 🔴 Critical

Implement the user-configured status filter end-to-end.

Line 9-16 and Line 86 currently allow emitting every valid webhook payload. This does not meet the PR objective (“status matches user-configured setting”). Add a user prop and guard before $emit.

Proposed fix
   props: {
     fraudlabsProApp,
+    status: {
+      type: "string",
+      label: "Status to Match",
+      description: "Only emit events when the incoming order status matches this value.",
+      optional: true,
+    },
     db: "$.service.db",
     http: {
       type: "$.interface.http",
       customResponse: true,
     },
   },
@@
   async run(event) {
     // 2. Capture the incoming POST data from the API
     const body = event.body;
      if (!body || typeof body !== "object") {
        this.http.respond({
          status: 400,
          body: { message: "Invalid payload" },
        });
        return;
      }
+
+    if (this.status && body.flp_status !== this.status) {
+      this.http.respond({
+        status: 200,
+        body: { message: "Ignored (status does not match filter)" },
+      });
+      return;
+    }
 
     // Emit the data so it can be used in workflow steps

Also applies to: 73-90

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs` around
lines 9 - 16, Add a new user prop (e.g., statusFilter) to the existing props
block and enforce it before emitting webhook payloads: update the props object
that currently lists fraudlabsProApp/db/http to include statusFilter (string,
optional, default empty or "any"), then in the webhook handler where $emit is
called (the code block around the existing $emit in lines ~73-90) add a guard
that reads the incoming payload.status and only calls $emit when payload.status
=== props.statusFilter (or when statusFilter is empty/"any" to allow all). Use
the exact prop name you add (statusFilter) in the comparison and normalize both
values (trim/lowercase) to be robust.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs`:
- Around line 43-48: The activation flow currently treats a successful subscribe
response as success even when the webhook `id` is missing; update the logic
around the response.json() handling so that after obtaining `data` you verify
`data.id` and, if it's absent, treat activation as failed (e.g., throw an error
or return a rejected result) instead of proceeding — ensure you do not call
this.db.set("hookId", ...) when data.id is falsy and surface an error so the
source does not become active without persisted hook state; modify the function
that awaits response.json() and sets the hookId accordingly to enforce this
check and early-fail on missing id.

---

Duplicate comments:
In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs`:
- Around line 9-16: Add a new user prop (e.g., statusFilter) to the existing
props block and enforce it before emitting webhook payloads: update the props
object that currently lists fraudlabsProApp/db/http to include statusFilter
(string, optional, default empty or "any"), then in the webhook handler where
$emit is called (the code block around the existing $emit in lines ~73-90) add a
guard that reads the incoming payload.status and only calls $emit when
payload.status === props.statusFilter (or when statusFilter is empty/"any" to
allow all). Use the exact prop name you add (statusFilter) in the comparison and
normalize both values (trim/lowercase) to be robust.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b98f2e7 and 3da4be2.

📒 Files selected for processing (1)
  • components/fraudlabs_pro/sources/status_changed/status_change.mjs

@michelle0927 michelle0927 moved this from Ready for PR Review to In Review in Component (Source and Action) Backlog Mar 3, 2026
Copy link
Collaborator

@michelle0927 michelle0927 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ooi2018 Thank you for your contribution. Can you point me to the FraudLabs documentation for these endpoints?
https://www.fraudlabspro.com/pipedream-webhook-subscribe
https://www.fraudlabspro.com/pipedream-webhook-unsubscribe

I located this link that describes creating a webhook "by entering the callback URL at the settings page", but it doesn't say anything about creating webhooks programmatically.

@michelle0927 michelle0927 moved this from In Review to Changes Required in Component (Source and Action) Backlog Mar 3, 2026
Fixed various errors and warnings from Lint Code Base.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
components/fraudlabs_pro/sources/status_changed/status_change.mjs (1)

90-94: ⚠️ Potential issue | 🟡 Minor

Summary may display "undefined" for missing fields.

If body.flp_status or body.order_id is missing, the summary will show "New Status: undefined for Order #undefined". Consider providing fallback values.

Proposed fix
     this.$emit(body, {
-      summary: `New Status: ${body.flp_status} for Order #${body.order_id}`,
-      id: `${body.order_id}-${body.flp_status}-${body.updated_at ?? body.timestamp ?? Date.now()}`,
+      summary: `New Status: ${body.flp_status ?? "unknown"} for Order #${body.order_id ?? "unknown"}`,
+      id: `${body.order_id ?? "unknown"}-${body.flp_status ?? "unknown"}-${body.updated_at ?? body.timestamp ?? Date.now()}`,
       ts: Date.now(),
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs` around
lines 90 - 94, The emitted summary and id currently interpolate body.flp_status
and body.order_id and can render "undefined"; update the this.$emit call (the
summary string and id construction) to use safe fallbacks (e.g., const status =
body.flp_status ?? 'unknown' and const orderId = body.order_id ?? 'unknown') and
use those variables when building the summary and id (retain the timestamp
fallback logic for the id: body.updated_at ?? body.timestamp ?? Date.now()) so
the summary reads "New Status: <status> for Order #<orderId>" even when fields
are missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs`:
- Around line 90-94: The emitted summary and id currently interpolate
body.flp_status and body.order_id and can render "undefined"; update the
this.$emit call (the summary string and id construction) to use safe fallbacks
(e.g., const status = body.flp_status ?? 'unknown' and const orderId =
body.order_id ?? 'unknown') and use those variables when building the summary
and id (retain the timestamp fallback logic for the id: body.updated_at ??
body.timestamp ?? Date.now()) so the summary reads "New Status: <status> for
Order #<orderId>" even when fields are missing.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3da4be2 and cb81c9b.

📒 Files selected for processing (1)
  • components/fraudlabs_pro/sources/status_changed/status_change.mjs

@ooi2018
Copy link
Author

ooi2018 commented Mar 3, 2026

@ooi2018 Thank you for your contribution. Can you point me to the FraudLabs documentation for these endpoints? https://www.fraudlabspro.com/pipedream-webhook-subscribe https://www.fraudlabspro.com/pipedream-webhook-unsubscribe

I located this link that describes creating a webhook "by entering the callback URL at the settings page", but it doesn't say anything about creating webhooks programmatically.

Hi @michelle0927,

There is currently no documentation available for these two endpoints. However, once a user adds the trigger to the workflow, the webhook URL will automatically be registered in the FraudLabs Pro database. The user will then just need to configure the order status settings in the FraudLabs Pro merchant dashboard.

A tutorial will be published once the trigger is approved.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
components/fraudlabs_pro/sources/status_changed/status_change.mjs (2)

9-16: ⚠️ Potential issue | 🔴 Critical

Implement user-configurable status filtering before emitting events.

The source still emits all status-change events and does not expose a prop for users to choose which status to match, so the core trigger behavior in the PR objective is not implemented.

Proposed fix
   props: {
     fraudlabsProApp,
+    status: {
+      type: "string",
+      label: "Status to match",
+      description: "Only emit events when flp_status matches this value.",
+      optional: true,
+    },
     db: "$.service.db",
     http: {
       type: "$.interface.http",
       customResponse: true,
     },
   },
@@
   async run(event) {
     // 2. Capture the incoming POST data from the API
     const body = event.body;
     if (!body || typeof body !== "object") {
       this.http.respond({
         status: 400,
         body: {
           message: "Invalid payload"
         },
       });
       return;
     }
+
+    if (this.status && body.flp_status !== this.status) {
+      this.http.respond({
+        status: 200,
+        body: {
+          message: "Ignored",
+        },
+      });
+      return;
+    }

Also applies to: 75-94

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs` around
lines 9 - 16, The source currently emits all status-change events without
allowing users to configure which statuses to match; add a new prop (e.g.,
statusFilter or allowedStatuses) to the props object alongside
fraudlabsProApp/db/http, expose it in the component config, and update the
status-change handler (the function that processes incoming HTTP payloads in
this file) to check the incoming event's status against the configured
allowedStatuses before emitting; ensure the prop accepts a string or array,
normalize it in initialization, and short-circuit/return early from the handler
when the status does not match so only configured status changes are emitted.

45-50: ⚠️ Potential issue | 🟠 Major

Fail activation when subscribe response has no webhook id.

If subscribe returns 2xx but omits id, activation currently succeeds without persisted state, which can cause duplicate subscriptions and broken deactivation.

Proposed fix
       const data = await response.json();

       // Store the ID returned by FraudLabs Pro
-      if (data && data.id) {
-        this.db.set("hookId", data.id);
-      }
+      if (!data?.id) {
+        throw new Error(`Activation failed: missing webhook id in response: ${JSON.stringify(data)}`);
+      }
+      this.db.set("hookId", data.id);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs` around
lines 45 - 50, The activation flow currently accepts a 2xx subscribe response
even when the parsed response (data from response.json()) lacks a webhook id, so
modify the activation logic around the response handling (the code that calls
response.json() and this.db.set("hookId", data.id)) to treat missing data.id as
a failure: after awaiting response.json(), if !data || !data.id then throw an
Error (or return a rejected promise) so activation fails and no hookId is
persisted; only call this.db.set("hookId", data.id) when data.id is present.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs`:
- Around line 90-93: The dedupe id uses Date.now() which makes retries appear
unique; change the id generation in the this.$emit call so it uses a
deterministic fallback instead of Date.now() — e.g. replace
`${body.order_id}-${body.flp_status}-${body.updated_at ?? body.timestamp ??
Date.now()}` with `${body.order_id}-${body.flp_status}-${body.updated_at ??
body.timestamp ?? 'missing_timestamp'}` (or `'0'`) so retrying the same webhook
produces the same id; update the expression where this.$emit is called to use
the deterministic fallback.

---

Duplicate comments:
In `@components/fraudlabs_pro/sources/status_changed/status_change.mjs`:
- Around line 9-16: The source currently emits all status-change events without
allowing users to configure which statuses to match; add a new prop (e.g.,
statusFilter or allowedStatuses) to the props object alongside
fraudlabsProApp/db/http, expose it in the component config, and update the
status-change handler (the function that processes incoming HTTP payloads in
this file) to check the incoming event's status against the configured
allowedStatuses before emitting; ensure the prop accepts a string or array,
normalize it in initialization, and short-circuit/return early from the handler
when the status does not match so only configured status changes are emitted.
- Around line 45-50: The activation flow currently accepts a 2xx subscribe
response even when the parsed response (data from response.json()) lacks a
webhook id, so modify the activation logic around the response handling (the
code that calls response.json() and this.db.set("hookId", data.id)) to treat
missing data.id as a failure: after awaiting response.json(), if !data ||
!data.id then throw an Error (or return a rejected promise) so activation fails
and no hookId is persisted; only call this.db.set("hookId", data.id) when
data.id is present.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb81c9b and 5849e3d.

📒 Files selected for processing (1)
  • components/fraudlabs_pro/sources/status_changed/status_change.mjs

@michelle0927 michelle0927 moved this from Changes Required to In Review in Component (Source and Action) Backlog Mar 4, 2026
Copy link
Collaborator

@michelle0927 michelle0927 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ooi2018. I made some updates to align the code better with Pipedream standards.

I'm able to create a webhook and get an id. However, I'm getting a 404 error when calling the unsubscribe endpoint (GET https://www.fraudlabspro.com/pipedream-webhook-unsubscribe). I tried changing a transaction from Approved to Reject, and then back to Approved, but I didn't receive any requests to the webhook.

Are you able to try testing the source by using the Pipedream CLI?

@michelle0927 michelle0927 moved this from In Review to Changes Required in Component (Source and Action) Backlog Mar 4, 2026
@ooi2018
Copy link
Author

ooi2018 commented Mar 5, 2026

Hi @michelle0927,

  • I have investigated and fixed the 404 issue related to the webhook unsubscribe endpoint on the server. Please try again and let me know if it works on your end.

  • I was able to test the changes locally. The API updates may take some time to be reflected, and I will provide another update next week. Please note that the webhook will only receive data if the order details are submitted to the /v2/order/screen API endpoint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

User submitted Submitted by a user

Projects

Development

Successfully merging this pull request may close these issues.

4 participants