-
Notifications
You must be signed in to change notification settings - Fork 5.6k
[Components] paykickstart #19881
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
[Components] paykickstart #19881
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| import app from "../../paykickstart.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "paykickstart-cancel-subscription", | ||
| name: "Cancel Subscription", | ||
| description: "Cancels an active subscription in PayKickstart. [See the documentation](https://docs.paykickstart.com/)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| props: { | ||
| app, | ||
| invoiceId: { | ||
| propDefinition: [ | ||
| app, | ||
| "invoiceId", | ||
| ], | ||
| }, | ||
| cancelAt: { | ||
| type: "integer", | ||
| label: "Cancel At", | ||
| description: "Unix timestamp for specific cancellation date (optional)", | ||
| optional: true, | ||
| }, | ||
| fireEvent: { | ||
| type: "integer", | ||
| label: "Fire Event", | ||
| description: "Whether to trigger cancellation events (1 = yes, 0 = no)", | ||
| optional: true, | ||
| default: 1, | ||
| options: [ | ||
| { | ||
| label: "Yes", | ||
| value: 1, | ||
| }, | ||
| { | ||
| label: "No", | ||
| value: 0, | ||
| }, | ||
| ], | ||
| }, | ||
| chargeOverage: { | ||
| type: "integer", | ||
| label: "Charge Overage", | ||
| description: "Calculate and charge overage fees during cancellation (1 = yes, 0 = no)", | ||
| optional: true, | ||
| default: 0, | ||
| options: [ | ||
| { | ||
| label: "Yes", | ||
| value: 1, | ||
| }, | ||
| { | ||
| label: "No", | ||
| value: 0, | ||
| }, | ||
| ], | ||
| }, | ||
| }, | ||
| annotations: { | ||
| readOnlyHint: false, | ||
| destructiveHint: true, | ||
| openWorldHint: true, | ||
| idempotentHint: true, | ||
| }, | ||
| async run({ $ }) { | ||
| const { | ||
| app, | ||
| invoiceId, | ||
| cancelAt, | ||
| fireEvent, | ||
| chargeOverage, | ||
| } = this; | ||
|
|
||
| const data = { | ||
| invoice_id: invoiceId, | ||
| fire_event: fireEvent, | ||
| charge_overage: chargeOverage, | ||
| }; | ||
|
|
||
| if (cancelAt) { | ||
| data.cancel_at = cancelAt; | ||
| } | ||
|
|
||
| const response = await app.cancelSubscription({ | ||
| $, | ||
| data, | ||
| }); | ||
|
|
||
| $.export("$summary", `Successfully cancelled subscription ${invoiceId}`); | ||
| return response; | ||
| }, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| import app from "../../paykickstart.app.mjs"; | ||
| import constants from "../../common/constants.mjs"; | ||
|
|
||
| export default { | ||
| key: "paykickstart-create-purchase", | ||
| name: "Create Purchase", | ||
| description: "Creates a new purchase transaction. [See the documentation](https://docs.paykickstart.com/)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| annotations: { | ||
| readOnlyHint: false, | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| }, | ||
| props: { | ||
| app, | ||
| product: { | ||
| propDefinition: [ | ||
| app, | ||
| "campaignId", | ||
| ], | ||
| }, | ||
| plan: { | ||
| propDefinition: [ | ||
| app, | ||
| "productId", | ||
| ], | ||
| }, | ||
| firstName: { | ||
| type: "string", | ||
| label: "First Name", | ||
| description: "Buyer's first name", | ||
| }, | ||
| lastName: { | ||
| type: "string", | ||
| label: "Last Name", | ||
| description: "Buyer's last name", | ||
| }, | ||
| email: { | ||
| type: "string", | ||
| label: "Email", | ||
| description: "Buyer's email address", | ||
| }, | ||
| quantity: { | ||
| type: "integer", | ||
| label: "Quantity", | ||
| description: "The quantity of the product being purchased. NOTE: The charge amount will be calculated by multiplying the price and quantity fields before adding tax, shipping etc. If the product's is `0` then don't set this field.", | ||
| optional: true, | ||
| }, | ||
| price: { | ||
| type: "integer", | ||
| label: "Price", | ||
| description: "Override the product's price amount for this purchase. If this field is not set, the price from the product's settings is used.", | ||
| optional: true, | ||
| }, | ||
| isRecurring: { | ||
| type: "boolean", | ||
| label: "Is Recurring", | ||
| description: "Enable a subscription-based product purchase. This field is not required unless you are setting up the purchase to be a subscription (see fields below).", | ||
| optional: true, | ||
| }, | ||
| recurringFreq: { | ||
| type: "integer", | ||
| label: "Recurring Frequency", | ||
| description: "The number of **Recurring Frequency Type** units. If `2` and a **Recurring Frequency Type** is `months`, means the subscription will charge every 2 months. This field is required when **Is Recurring** is set.", | ||
| optional: true, | ||
| }, | ||
| recurringFreqType: { | ||
| type: "string", | ||
| label: "Recurring Frequency Type", | ||
| description: "The recurring period for the recurring payment. This field is required when **Is Recurring** is set.", | ||
| options: constants.FREQUENCY_TYPES, | ||
| optional: true, | ||
| }, | ||
| cycles: { | ||
| type: "string", | ||
| label: "Cycles", | ||
| description: "The number of payments for your subscription. Set as null for an infinite subscription. This field is required when **Is Recurring** is set.", | ||
| optional: true, | ||
| }, | ||
| hasTrial: { | ||
| type: "boolean", | ||
| label: "Has Trial", | ||
| description: "Enable trial period for the purchase. Please note this is only currently possible for recurring subscription products. This field is not required unless you which to create a trial period for your product.", | ||
| optional: true, | ||
| }, | ||
| trialAmount: { | ||
| type: "string", | ||
| label: "Trial Amount", | ||
| description: "The initial amount to charge for the trial. Amount may be set to `0` for free trial. This field is not required unless you have **Has Trial** enabled.", | ||
| optional: true, | ||
| }, | ||
| trialDays: { | ||
| type: "integer", | ||
| label: "Trial Days", | ||
| description: "The number of days before the subscription transactions begin. For example, if you want to set a 14 day free trial, make sure the product is set to recurring in its settings or via the API, then set **Trial Amoun** to `0` and **Trial Days** to `14`. This field is not required unless you have **Has Trial** enabled.", | ||
|
Comment on lines
+47
to
+96
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix user-facing typos and align wording with options. There are a few typos and a pluralization mismatch in the descriptions that can confuse users. ✏️ Suggested text fixes- description: "The quantity of the product being purchased. NOTE: The charge amount will be calculated by multiplying the price and quantity fields before adding tax, shipping etc. If the product's is `0` then don't set this field.",
+ description: "The quantity of the product being purchased. NOTE: The charge amount will be calculated by multiplying the price and quantity fields before adding tax, shipping, etc. If the product's price is `0` then don't set this field.",
@@
- description: "The number of **Recurring Frequency Type** units. If `2` and a **Recurring Frequency Type** is `months`, means the subscription will charge every 2 months. This field is required when **Is Recurring** is set.",
+ description: "The number of **Recurring Frequency Type** units. If `2` and a **Recurring Frequency Type** is `month`, the subscription will charge every 2 months. This field is required when **Is Recurring** is set.",
@@
- description: "Enable trial period for the purchase. Please note this is only currently possible for recurring subscription products. This field is not required unless you which to create a trial period for your product.",
+ description: "Enable trial period for the purchase. Please note this is only currently possible for recurring subscription products. This field is not required unless you wish to create a trial period for your product.",
@@
- description: "The number of days before the subscription transactions begin. For example, if you want to set a 14 day free trial, make sure the product is set to recurring in its settings or via the API, then set **Trial Amoun** to `0` and **Trial Days** to `14`. This field is not required unless you have **Has Trial** enabled.",
+ description: "The number of days before the subscription transactions begin. For example, if you want to set a 14 day free trial, make sure the product is set to recurring in its settings or via the API, then set **Trial Amount** to `0` and **Trial Days** to `14`. This field is not required unless you have **Has Trial** enabled.",🤖 Prompt for AI Agents |
||
| optional: true, | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const { | ||
| app, | ||
| product, | ||
| plan, | ||
| firstName, | ||
| lastName, | ||
| email, | ||
| price, | ||
| quantity, | ||
| isRecurring, | ||
| recurringFreq, | ||
| recurringFreqType, | ||
| cycles, | ||
| hasTrial, | ||
| trialAmount, | ||
| trialDays, | ||
| } = this; | ||
|
|
||
| const response = await app.createPurchase({ | ||
| $, | ||
| data: { | ||
| product, | ||
| plan, | ||
| first_name: firstName, | ||
| last_name: lastName, | ||
| email, | ||
| price, | ||
| quantity, | ||
| is_recurring: isRecurring, | ||
| recurring_freq: recurringFreq, | ||
| recurring_freq_type: recurringFreqType, | ||
| cycles, | ||
| has_trial: hasTrial, | ||
| trial_amount: trialAmount, | ||
| trial_days: trialDays, | ||
| }, | ||
| }); | ||
|
|
||
| $.export("$summary", "Successfully created purchase"); | ||
| return response; | ||
| }, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| const FREQUENCY_TYPES = [ | ||
| "day", | ||
| "month", | ||
| "year", | ||
| ]; | ||
|
|
||
| export default { | ||
| FREQUENCY_TYPES, | ||
| }; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,11 +1,110 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { axios } from "@pipedream/platform"; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| export default { | ||||||||||||||||||||||||||||||||||||||||||||||||
| type: "app", | ||||||||||||||||||||||||||||||||||||||||||||||||
| app: "paykickstart", | ||||||||||||||||||||||||||||||||||||||||||||||||
| propDefinitions: {}, | ||||||||||||||||||||||||||||||||||||||||||||||||
| propDefinitions: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| campaignId: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| type: "integer", | ||||||||||||||||||||||||||||||||||||||||||||||||
| label: "Campaign ID", | ||||||||||||||||||||||||||||||||||||||||||||||||
| description: "The campaign ID", | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| productId: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| type: "integer", | ||||||||||||||||||||||||||||||||||||||||||||||||
| label: "Product ID", | ||||||||||||||||||||||||||||||||||||||||||||||||
| description: "The campaign ID for the product", | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| invoiceId: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||||||||||||||||||||||||
| label: "Invoice ID", | ||||||||||||||||||||||||||||||||||||||||||||||||
| description: "The unique purchase/subscription invoice ID", | ||||||||||||||||||||||||||||||||||||||||||||||||
| async options() { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const { transactions } = await this.getTransactions(); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return transactions | ||||||||||||||||||||||||||||||||||||||||||||||||
| .filter((transaction) => transaction.invoice_id) | ||||||||||||||||||||||||||||||||||||||||||||||||
| .map((transaction) => ({ | ||||||||||||||||||||||||||||||||||||||||||||||||
| label: `${transaction.invoice_id} - ${transaction.buyer_email || transaction.buyer_name || "No name"} - $${transaction.total_amount || 0}`, | ||||||||||||||||||||||||||||||||||||||||||||||||
| value: transaction.invoice_id, | ||||||||||||||||||||||||||||||||||||||||||||||||
| })); | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| affiliateId: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||||||||||||||||||||||||
| label: "Affiliate ID", | ||||||||||||||||||||||||||||||||||||||||||||||||
| description: "The affiliate ID or email", | ||||||||||||||||||||||||||||||||||||||||||||||||
| async options({ campaignId }) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!campaignId) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return []; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| const affiliates = await this.getAffiliates({ | ||||||||||||||||||||||||||||||||||||||||||||||||
| campaignId, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return affiliates.map((affiliate) => ({ | ||||||||||||||||||||||||||||||||||||||||||||||||
| label: `${affiliate.name || affiliate.email} - ${affiliate.email}`, | ||||||||||||||||||||||||||||||||||||||||||||||||
| value: affiliate.id, | ||||||||||||||||||||||||||||||||||||||||||||||||
| })); | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| methods: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| // this.$auth contains connected account data | ||||||||||||||||||||||||||||||||||||||||||||||||
| authKeys() { | ||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(Object.keys(this.$auth)); | ||||||||||||||||||||||||||||||||||||||||||||||||
| _baseUrl() { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return "https://app.paykickstart.com/api"; | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| async _makeRequest({ | ||||||||||||||||||||||||||||||||||||||||||||||||
| $ = this, path, ...otherOpts | ||||||||||||||||||||||||||||||||||||||||||||||||
| }) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await axios($, { | ||||||||||||||||||||||||||||||||||||||||||||||||
| ...otherOpts, | ||||||||||||||||||||||||||||||||||||||||||||||||
| debug: true, | ||||||||||||||||||||||||||||||||||||||||||||||||
| url: `${this._baseUrl()}${path}`, | ||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| "Content-Type": "application/json", | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| data: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| auth_token: this.$auth.api_key, | ||||||||||||||||||||||||||||||||||||||||||||||||
| ...otherOpts?.data, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (response.error) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(JSON.stringify(response.error, null, 2)); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| return response; | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| createPurchase(opts = {}) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return this._makeRequest({ | ||||||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||||||
| path: "/purchase", | ||||||||||||||||||||||||||||||||||||||||||||||||
| ...opts, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| cancelSubscription(opts = {}) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return this._makeRequest({ | ||||||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||||||
| path: "/subscriptions/cancel", | ||||||||||||||||||||||||||||||||||||||||||||||||
| ...opts, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| getTransactions(opts = {}) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return this._makeRequest({ | ||||||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||||||
| path: "/transactions", | ||||||||||||||||||||||||||||||||||||||||||||||||
| ...opts, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| getAffiliates({ | ||||||||||||||||||||||||||||||||||||||||||||||||
| campaignId, ...opts | ||||||||||||||||||||||||||||||||||||||||||||||||
| }) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return this._makeRequest({ | ||||||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||||||
| path: "/affiliates/all", | ||||||||||||||||||||||||||||||||||||||||||||||||
| data: { | ||||||||||||||||||||||||||||||||||||||||||||||||
| campaign_id: campaignId, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| ...opts, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+97
to
+107
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Prevent Spreading ♻️ Suggested refactor- getAffiliates({
- campaignId, ...opts
- }) {
+ getAffiliates({ campaignId, ...opts }) {
+ const { data, ...rest } = opts;
return this._makeRequest({
method: "POST",
path: "/affiliates/all",
data: {
campaign_id: campaignId,
+ ...data,
},
- ...opts,
+ ...rest,
});
},📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
@pipedream/platform axios undefined values request payload💡 Result:
In Pipedream,
import { axios } from "@pipedream/platform"ultimately sends JSON request bodies, and JSON cannot representundefined. When the payload is serialized, any object properties whose values areundefinedare omitted (andundefinedarray items becomenull). This often looks like “axios dropped my fields” or “payload has missing values”. [1]Fix options (pick one):
null(or"") instead ofundefinedbefore callingaxios:undefinedkeys explicitly (so you’re intentional about what’s sent):undefined→nullrecursively viaJSON.stringifyreplacer:Also make sure you’re calling Pipedream’s axios correctly as
axios($, config)(passing$as the first argument), otherwise you can get confusing behavior/errors. [2][3]Sources: [1] https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify | [2] https://pipedream.com/docs/http | [3] https://pipedream.com/community/t/help-with-axios-request/2630
Remove the truthy guard on
cancelAt.The
if (cancelAt)check blocks valid falsy values like0(which may be a valid timestamp). Since@pipedream/platformaxios automatically excludesundefinedfrom request payloads, there's no need for the manual truthiness check.✅ Suggested fix
const data = { invoice_id: invoiceId, fire_event: fireEvent, charge_overage: chargeOverage, + cancel_at: cancelAt, }; - - if (cancelAt) { - data.cancel_at = cancelAt; - }📝 Committable suggestion
🤖 Prompt for AI Agents