diff --git a/components/bika_ai/bika_ai.app.mjs b/components/bika_ai/bika_ai.app.mjs index dd1114844862b..b645dd98f96a3 100644 --- a/components/bika_ai/bika_ai.app.mjs +++ b/components/bika_ai/bika_ai.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/ifthenpay/actions/create-payment-reference/create-payment-reference.mjs b/components/ifthenpay/actions/create-payment-reference/create-payment-reference.mjs new file mode 100644 index 0000000000000..701aee469a526 --- /dev/null +++ b/components/ifthenpay/actions/create-payment-reference/create-payment-reference.mjs @@ -0,0 +1,145 @@ +import { PAYMENT_METHOD_OPTIONS } from "../../common/constants.mjs"; +import ifthenpay from "../../ifthenpay.app.mjs"; + +export default { + key: "ifthenpay-create-payment-reference", + name: "Create Payment Reference", + description: "Generates a Multibanco or MB WAY payment reference with a specified amount, entity code, and deadline. [See the documentation](https://ifthenpay.com/docs/en/)", + version: "0.0.1", + type: "action", + props: { + ifthenpay, + paymentMethod: { + type: "string", + label: "Payment Method", + description: "The payment method to use for Ifthenpay (e.g., MB WAY, Multibanco)", + options: PAYMENT_METHOD_OPTIONS, + reloadProps: true, + }, + mbKey: { + propDefinition: [ + ifthenpay, + "mbKey", + ], + hidden: true, + }, + mbWayKey: { + propDefinition: [ + ifthenpay, + "mbWayKey", + ], + hidden: true, + }, + orderId: { + type: "string", + label: "Order Id", + description: "Payment identifier defined by the client (e.g., invoice number, order number, etc.)", + }, + amount: { + type: "string", + label: "Amount", + description: "The amount to be paid with decimal separator \".\"", + }, + mobileNumber: { + type: "string", + label: "Mobile Number", + description: "Place the country code before the mobile number without any spaces (use '#'' to separate the country code from the mobile number - p.e. 351#912345678)", + hidden: true, + }, + description: { + type: "string", + label: "Description", + description: "Description of the payment, with a maximum length of 200 characters", + optional: true, + }, + url: { + type: "string", + label: "URL", + description: "URL address, with a maximum length of 200 characters", + optional: true, + hidden: true, + }, + clientCode: { + type: "string", + label: "Client Code", + description: "Client's code, with a maximum length of 200 characters", + optional: true, + hidden: true, + }, + clientName: { + type: "string", + label: "Client Name", + description: "Client's name, with a maximum length of 200 characters", + optional: true, + hidden: true, + }, + email: { + type: "string", + label: "Email", + description: "The Client's name.", + optional: true, + }, + clientUsername: { + type: "string", + label: "Client Username", + description: "Client's username, with a maximum length of 200 characters", + optional: true, + hidden: true, + }, + clientPhone: { + type: "string", + label: "Client Phone", + description: "Client's cell phone or phone number, with a maximum length of 200 characters", + optional: true, + hidden: true, + }, + expiryDays: { + type: "integer", + label: "Expiry Days", + description: "How many days the payment reference is valid for. [See the documentation](https://ifthenpay.com/docs/en/api/multibanco/#tag/multibanco/POST/init) for further details.", + optional: true, + hidden: true, + }, + }, + async additionalProps(props) { + const isMb = this.paymentMethod === "Multibanco"; + props.mbKey.hidden = !isMb; + props.mbWayKey.hidden = isMb; + props.mobileNumber.hidden = isMb; + props.url.hidden = isMb; + props.clientCode.hidden = isMb; + props.clientName.hidden = isMb; + props.email.label = "Client Email"; + props.email.description = "Client's email address, with a maximum length of 200 characters"; + props.clientUsername.hidden = isMb; + props.clientPhone.hidden = isMb; + props.expiryDays.hidden = isMb; + return {}; + }, + async run({ $ }) { + const response = await this.ifthenpay.generatePaymentReference({ + $, + paymentMethod: this.paymentMethod, + data: { + mbKey: this.mbKey, + mbWayKey: this.mbWayKey, + orderId: this.orderId, + amount: parseFloat(this.amount), + mobileNumber: this.mobileNumber, + email: this.email, + description: this.description, + url: this.url, + clientCode: this.clientCode, + clientName: this.clientName, + clientUsername: this.clientUsername, + clientPhone: this.clientPhone, + expiryDays: this.expiryDays, + expirationDate: this.expirationDate, + clientEmail: this.email, + }, + }); + + $.export("$summary", `Successfully created payment reference with Order ID: ${response.OrderId}`); + return response; + }, +}; diff --git a/components/ifthenpay/actions/issue-refund/issue-refund.mjs b/components/ifthenpay/actions/issue-refund/issue-refund.mjs new file mode 100644 index 0000000000000..4f0e8440abc79 --- /dev/null +++ b/components/ifthenpay/actions/issue-refund/issue-refund.mjs @@ -0,0 +1,36 @@ +import ifthenpay from "../../ifthenpay.app.mjs"; + +export default { + key: "ifthenpay-issue-refund", + name: "Issue Refund", + description: "Issue a full or partial refund for a previously completed payment via Ifthenpay. [See the documentation](https://ifthenpay.com/docs/en/)", + version: "0.0.1", + type: "action", + props: { + ifthenpay, + requestId: { + propDefinition: [ + ifthenpay, + "requestId", + ], + }, + amount: { + type: "string", + label: "Amount", + description: "The amount to be refunded.", + }, + }, + async run({ $ }) { + const response = await this.ifthenpay.refundPayment({ + $, + data: { + backofficekey: this.ifthenpay.$auth.backoffice_key, + requestId: this.requestId, + amount: this.amount, + }, + }); + + $.export("$summary", `Successfully issued a refund for payment ID: ${this.requestId}`); + return response; + }, +}; diff --git a/components/ifthenpay/common/constants.mjs b/components/ifthenpay/common/constants.mjs new file mode 100644 index 0000000000000..40f0241433d18 --- /dev/null +++ b/components/ifthenpay/common/constants.mjs @@ -0,0 +1,4 @@ +export const PAYMENT_METHOD_OPTIONS = [ + "MB WAY", + "Multibanco", +]; diff --git a/components/ifthenpay/ifthenpay.app.mjs b/components/ifthenpay/ifthenpay.app.mjs index 76bfc78de653d..f0efa4a0c5c7a 100644 --- a/components/ifthenpay/ifthenpay.app.mjs +++ b/components/ifthenpay/ifthenpay.app.mjs @@ -1,11 +1,101 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "ifthenpay", - propDefinitions: {}, + propDefinitions: { + requestId: { + type: "string", + label: "Request ID", + description: "Token associated with the payment request transaction", + async options({ prevContext }) { + const { payments } = await this.listPayments({ + data: { + dateStart: prevContext.token, + }, + }); + + return { + options: payments.map(({ + requestId: value, orderId: label, + }) => ({ + label, + value, + })), + context: { + token: payments.length + ? payments[0].paymentDate + : null, + }, + }; + }, + }, + mbWayKey: { + type: "string", + label: "Mb Way Key", + description: "The key for the MB Way payment method.", + secret: true, + }, + mbKey: { + type: "string", + label: "Mb Key", + description: "The key for the Multibanco payment method.", + secret: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.ifthenpay.com"; + }, + _data(data) { + return { + "boKey": `${this.$auth.backoffice_key}`, + ...data, + }; + }, + _makeRequest({ + $ = this, path, data, ...opts + }) { + return axios($, { + url: this._baseUrl() + path, + headers: { + "accept": "application/json", + }, + data: this._data(data), + ...opts, + }); + }, + generatePaymentReference({ + paymentMethod, data, ...opts + }) { + let path; + if (paymentMethod === "Multibanco") { + path = "/multibanco/reference/init"; + } else if (paymentMethod === "MB WAY") { + path = "/spg/payment/mbway"; + } + + return this._makeRequest({ + method: "POST", + path, + data, + ...opts, + }); + }, + refundPayment(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/endpoint/payments/refund", + ...opts, + }); + }, + listPayments(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/v2/payments/read", + ...opts, + }); }, }, }; + diff --git a/components/ifthenpay/package.json b/components/ifthenpay/package.json index e356c221c34eb..01d3a79b7b986 100644 --- a/components/ifthenpay/package.json +++ b/components/ifthenpay/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/ifthenpay", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream ifthenpay Components", "main": "ifthenpay.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3" } -} \ No newline at end of file +} diff --git a/components/ifthenpay/sources/new-payment/new-payment.mjs b/components/ifthenpay/sources/new-payment/new-payment.mjs new file mode 100644 index 0000000000000..1d21488e5ba64 --- /dev/null +++ b/components/ifthenpay/sources/new-payment/new-payment.mjs @@ -0,0 +1,63 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; +import ifthenpay from "../../ifthenpay.app.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + key: "ifthenpay-new-payment", + name: "New Payment Completed", + description: "Emit new event when a payment is successfully completed through Ifthenpay. [See the documentation](https://ifthenpay.com/docs/en/)", + version: "0.0.1", + type: "source", + dedupe: "unique", + props: { + ifthenpay, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + _getLastDate() { + return this.db.get("lastDate") || "1970-01-01 00:00:00"; + }, + _setLastDate(lastDate) { + this.db.set("lastDate", lastDate); + }, + async emitEvent(maxResults = false) { + const lastDate = this._getLastDate(); + + const { payments: response } = await this.ifthenpay.listPayments({ + data: { + dateStart: lastDate, + }, + }); + + if (response.length) { + if (maxResults && (response.length > maxResults)) { + response.length = maxResults; + } + this._setLastDate(response[0].paymentDate); + } + + for (const item of response.reverse()) { + this.$emit(item, { + id: item.requestId, + summary: `New Payment: ${parseFloat(item.amount)} ${item.entity}`, + ts: Date.parse(item.paymentDate), + }); + } + }, + }, + hooks: { + async deploy() { + await this.emitEvent(25); + }, + }, + async run() { + await this.emitEvent(); + }, + sampleEmit, +}; diff --git a/components/ifthenpay/sources/new-payment/test-event.mjs b/components/ifthenpay/sources/new-payment/test-event.mjs new file mode 100644 index 0000000000000..a1d937e5c37af --- /dev/null +++ b/components/ifthenpay/sources/new-payment/test-event.mjs @@ -0,0 +1,13 @@ +export default { + "amount": 22750, + "entity": "MB", + "fee": 0.86, + "netAmount": 22749.14, + "orderId": "000017273", + "paymentDate": "21-10-2024 15:41:00", + "procDate": "20241021", + "reference": "007875810", + "requestId": "wIh3HzFByfmj75Adl98x", + "subEntity": "XXX-000000", + "terminal": "5-0000000000-CAIXA GERAL DE " +} \ No newline at end of file diff --git a/components/inferable/inferable.app.mjs b/components/inferable/inferable.app.mjs index 1865b70cb5494..5666e1ad689c5 100644 --- a/components/inferable/inferable.app.mjs +++ b/components/inferable/inferable.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/instasent/instasent.app.mjs b/components/instasent/instasent.app.mjs index 081d582acfb27..6308cb1f22c81 100644 --- a/components/instasent/instasent.app.mjs +++ b/components/instasent/instasent.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/peerdom/peerdom.app.mjs b/components/peerdom/peerdom.app.mjs index edc5aa5f4c81a..c38375fda2339 100644 --- a/components/peerdom/peerdom.app.mjs +++ b/components/peerdom/peerdom.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/urltopdf/urltopdf.app.mjs b/components/urltopdf/urltopdf.app.mjs index cd1040391b908..d0d0814b34588 100644 --- a/components/urltopdf/urltopdf.app.mjs +++ b/components/urltopdf/urltopdf.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a097411ad9e86..7e9e16d960f33 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6307,7 +6307,11 @@ importers: components/if_else: {} - components/ifthenpay: {} + components/ifthenpay: + dependencies: + '@pipedream/platform': + specifier: ^3.0.3 + version: 3.0.3 components/ifttt: dependencies: