diff --git a/components/adyen/actions/cancel-payment/cancel-payment.mjs b/components/adyen/actions/cancel-payment/cancel-payment.mjs new file mode 100644 index 0000000000000..96350172a0497 --- /dev/null +++ b/components/adyen/actions/cancel-payment/cancel-payment.mjs @@ -0,0 +1,49 @@ +import app from "../../adyen.app.mjs"; + +export default { + key: "adyen-cancel-payment", + name: "Cancel Payment", + description: "Cancels a payment that has not yet been captured. [See the documentation](https://docs.adyen.com/api-explorer/checkout/71/post/payments/(paymentpspreference)/cancels)", + version: "0.0.1", + type: "action", + props: { + app, + paymentPspReference: { + propDefinition: [ + app, + "paymentPspReference", + ], + }, + merchantAccount: { + propDefinition: [ + app, + "merchantAccount", + ], + }, + }, + methods: { + cancelPayment({ + paymentPspReference, data, + } = {}) { + return this.app.getCheckoutAPI() + .ModificationsApi + .cancelAuthorisedPaymentByPspReference(paymentPspReference, data); + }, + }, + async run({ $ }) { + const { + cancelPayment, + paymentPspReference, + merchantAccount, + } = this; + + const response = await cancelPayment({ + paymentPspReference, + data: { + merchantAccount, + }, + }); + $.export("$summary", "Successfully cancelled payment."); + return response; + }, +}; diff --git a/components/adyen/actions/capture-payment/capture-payment.mjs b/components/adyen/actions/capture-payment/capture-payment.mjs new file mode 100644 index 0000000000000..c99e6bf4eb9fa --- /dev/null +++ b/components/adyen/actions/capture-payment/capture-payment.mjs @@ -0,0 +1,68 @@ +import app from "../../adyen.app.mjs"; + +export default { + key: "adyen-capture-payment", + name: "Capture Payment", + description: "Captures an authorized payment. This is typically used for delayed capture scenarios, such as when you need to verify the order before capturing the funds.", + version: "0.0.1", + type: "action", + props: { + app, + paymentPspReference: { + propDefinition: [ + app, + "paymentPspReference", + ], + }, + merchantAccount: { + propDefinition: [ + app, + "merchantAccount", + ], + }, + amountCurrency: { + propDefinition: [ + app, + "amountCurrency", + ], + }, + amountValue: { + propDefinition: [ + app, + "amountValue", + ], + }, + }, + methods: { + capturePayment({ + paymentPspReference, data, + } = {}) { + return this.app.getCheckoutAPI() + .ModificationsApi + .captureAuthorisedPayment(paymentPspReference, data); + }, + }, + async run({ $ }) { + const { + capturePayment, + paymentPspReference, + merchantAccount, + amountCurrency, + amountValue, + } = this; + + const response = await capturePayment({ + paymentPspReference, + data: { + merchantAccount, + amount: { + currency: amountCurrency, + value: amountValue, + }, + }, + }); + + $.export("$summary", "Successfully captured payment."); + return response; + }, +}; diff --git a/components/adyen/actions/create-payment/create-payment.mjs b/components/adyen/actions/create-payment/create-payment.mjs new file mode 100644 index 0000000000000..c1a091112fb92 --- /dev/null +++ b/components/adyen/actions/create-payment/create-payment.mjs @@ -0,0 +1,92 @@ +import app from "../../adyen.app.mjs"; + +export default { + key: "adyen-create-payment", + name: "Create Payment", + description: "Creates a payment for a shopper. [See the documentation](https://docs.adyen.com/api-explorer/Checkout/71/post/payments)", + version: "0.0.1", + type: "action", + props: { + app, + merchantAccount: { + propDefinition: [ + app, + "merchantAccount", + ], + }, + amountCurrency: { + propDefinition: [ + app, + "amountCurrency", + ], + }, + amountValue: { + propDefinition: [ + app, + "amountValue", + ], + }, + reference: { + type: "string", + label: "Reference", + description: "The reference to uniquely identify a payment. This reference is used in all communication with you about the payment status. We recommend using a unique value per payment; however, it is not a requirement. If you need to provide multiple references for a transaction, separate them with hyphens (`-`). Maximum length: 80 characters.", + }, + returnUrl: { + type: "string", + label: "Return URL", + description: "The URL to return to in case of a redirection. The format depends on the channel. For more information refer the [documentation](https://docs.adyen.com/api-explorer/Checkout/71/post/payments#request-returnUrl).", + }, + paymentMethodType: { + propDefinition: [ + app, + "paymentMethodType", + ({ merchantAccount }) => ({ + merchantAccount, + }), + ], + }, + paymentMethodDetails: { + type: "object", + label: "Payment Method Details", + description: "The payment method details object required for submitting additional payment details. Should contain relevant payment details fields. For more information refer the [documentation](https://docs.adyen.com/api-explorer/Checkout/71/post/payments#request-paymentMethod).", + optional: true, + }, + }, + methods: { + createPayment({ data } = {}) { + return this.app.getCheckoutAPI() + .PaymentsApi + .payments(data); + }, + }, + async run({ $ }) { + const { + createPayment, + amountCurrency, + amountValue, + merchantAccount, + reference, + returnUrl, + paymentMethodType, + paymentMethodDetails, + } = this; + + const response = await createPayment({ + data: { + amount: { + currency: amountCurrency, + value: amountValue, + }, + merchantAccount, + reference, + returnUrl, + paymentMethod: { + ...paymentMethodDetails, + type: paymentMethodType, + }, + }, + }); + $.export("$summary", "Successfully created payment."); + return response; + }, +}; diff --git a/components/adyen/actions/refund-payment/refund-payment.mjs b/components/adyen/actions/refund-payment/refund-payment.mjs new file mode 100644 index 0000000000000..cb74c1bb9c599 --- /dev/null +++ b/components/adyen/actions/refund-payment/refund-payment.mjs @@ -0,0 +1,67 @@ +import app from "../../adyen.app.mjs"; + +export default { + key: "adyen-refund-payment", + name: "Refund Payment", + description: "Refunds a captured payment. [See the documentation](https://docs.adyen.com/api-explorer/checkout/71/post/payments/(paymentpspreference)/refunds)", + version: "0.0.1", + type: "action", + props: { + app, + paymentPspReference: { + propDefinition: [ + app, + "paymentPspReference", + ], + }, + merchantAccount: { + propDefinition: [ + app, + "merchantAccount", + ], + }, + amountCurrency: { + propDefinition: [ + app, + "amountCurrency", + ], + }, + amountValue: { + propDefinition: [ + app, + "amountValue", + ], + }, + }, + methods: { + refundPayment({ + paymentPspReference, data, + } = {}) { + return this.app.getCheckoutAPI() + .ModificationsApi + .refundCapturedPayment(paymentPspReference, data); + }, + }, + async run({ $ }) { + const { + refundPayment, + paymentPspReference, + merchantAccount, + amountCurrency, + amountValue, + } = this; + + const response = await refundPayment({ + paymentPspReference, + data: { + merchantAccount, + amount: { + currency: amountCurrency, + value: amountValue, + }, + }, + }); + $.export("$summary", `Successfully refunded payment with PSP Reference \`${response.paymentPspReference}\`.`); + return response; + }, +}; diff --git a/components/adyen/actions/submit-details/submit-details.mjs b/components/adyen/actions/submit-details/submit-details.mjs new file mode 100644 index 0000000000000..e3591015c2488 --- /dev/null +++ b/components/adyen/actions/submit-details/submit-details.mjs @@ -0,0 +1,55 @@ +import app from "../../adyen.app.mjs"; +import utils from "../../common/utils.mjs"; + +export default { + key: "adyen-submit-details", + name: "Submit Additional Payment Details", + description: "Submits additional details for a payment. [See the documentation](https://docs.adyen.com/api-explorer/Checkout/71/post/payments/details)", + version: "0.0.1", + type: "action", + props: { + app, + details: { + type: "object", + label: "Details", + description: "Use this collection to submit the details that were returned as a result of the **Create Payment** action call.", + }, + authenticationData: { + type: "string", + label: "Authentication Data", + description: "The authentication data that you received from the 3D Secure 2 SDK.", + optional: true, + }, + paymentData: { + type: "string", + label: "Payment Data", + description: "The payment data that you received from the **Create Payment** action call. [See the documentation](https://docs.adyen.com/api-explorer/Checkout/71/post/payments/details#request-paymentData).", + optional: true, + }, + }, + methods: { + submitAdditionalDetails({ data } = {}) { + return this.app.getCheckoutAPI() + .PaymentsApi + .paymentsDetails(data); + }, + }, + async run({ $ }) { + const { + submitAdditionalDetails, + details, + authenticationData, + paymentData, + } = this; + + const response = await submitAdditionalDetails({ + data: { + details: utils.parse(details), + authenticationData: utils.parse(authenticationData), + paymentData, + }, + }); + $.export("$summary", "Successfully submitted additional payment details."); + return response; + }, +}; diff --git a/components/adyen/adyen.app.mjs b/components/adyen/adyen.app.mjs index fad4791b3f88f..3102d1707a0da 100644 --- a/components/adyen/adyen.app.mjs +++ b/components/adyen/adyen.app.mjs @@ -1,11 +1,74 @@ +import adyen from "@adyen/api-library"; + export default { type: "app", app: "adyen", - propDefinitions: {}, + propDefinitions: { + merchantAccount: { + type: "string", + label: "Merchant Account", + description: "The merchant account identifier, with which you want to process the transaction.", + }, + amountCurrency: { + type: "string", + label: "Currency", + description: "The currency of the payment amount. The three-character [ISO currency code](https://docs.adyen.com/development-resources/currency-codes).", + }, + amountValue: { + type: "integer", + label: "Value", + description: "The amount of the transaction, in [minor units](https://docs.adyen.com/development-resources/currency-codes).", + }, + paymentMethodType: { + type: "string", + label: "Payment Method Type", + description: "The payment method used for the payment. For example `scheme` or `paypal`. For the full list of payment methods, refer to the [documentation](https://docs.adyen.com/api-explorer/Checkout/71/post/payments#request-paymentMethod).", + async options({ merchantAccount }) { + if (!merchantAccount) { + return []; + } + const { paymentMethods } = await this.listPaymentMethods({ + data: { + merchantAccount, + }, + }); + return paymentMethods.map(({ + name: label, type: value, + }) => ({ + label, + value, + })); + }, + }, + paymentPspReference: { + type: "string", + label: "Payment PSP Reference", + description: "The PSP reference of the payment for which you want to perform the action.", + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + getClient() { + const { + api_key: apiKey, + live_endpoint_url_prefix: liveEndpointUrlPrefix, + environment, + } = this.$auth; + const isLiveEnv = environment === "LIVE"; + return new adyen.Client({ + apiKey, + environment, + ...(isLiveEnv && { + liveEndpointUrlPrefix, + }), + }); + }, + getCheckoutAPI() { + return new adyen.CheckoutAPI(this.getClient()); + }, + listPaymentMethods({ + data, options, + } = {}) { + return this.getCheckoutAPI().PaymentsApi.paymentMethods(data, options); }, }, }; diff --git a/components/adyen/common/utils.mjs b/components/adyen/common/utils.mjs new file mode 100644 index 0000000000000..3a9330095d785 --- /dev/null +++ b/components/adyen/common/utils.mjs @@ -0,0 +1,24 @@ +import { ConfigurationError } from "@pipedream/platform"; + +function emptyStrToUndefined(value) { + const trimmed = typeof(value) === "string" && value.trim(); + return trimmed === "" + ? undefined + : value; +} + +function parse(value) { + const valueToParse = emptyStrToUndefined(value); + if (typeof(valueToParse) === "object" || valueToParse === undefined) { + return valueToParse; + } + try { + return JSON.parse(valueToParse); + } catch (e) { + throw new ConfigurationError("Make sure the custom expression contains a valid JSON object."); + } +} + +export default { + parse, +}; diff --git a/components/adyen/package.json b/components/adyen/package.json index e093ab42712c3..4ba585f7935ab 100644 --- a/components/adyen/package.json +++ b/components/adyen/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/adyen", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Adyen Components", "main": "adyen.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@adyen/api-library": "^20.0.0" } -} \ No newline at end of file +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c48a19d33f6b8..2a4b81e446fcc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -272,7 +272,10 @@ importers: '@pipedream/platform': 1.5.1 components/adyen: - specifiers: {} + specifiers: + '@adyen/api-library': ^20.0.0 + dependencies: + '@adyen/api-library': 20.0.0 components/aero_workflow: specifiers: @@ -11948,6 +11951,17 @@ packages: - supports-color dev: false + /@adyen/api-library/20.0.0: + resolution: {integrity: sha512-C+jj5XBTCNs7AFwufOkPLhuqn9bdgSDcqLB6b/Ppi9Fujwt613vWmA1hxeG76RX49vzHZIDJLq6N/v0o2SY1sA==} + engines: {node: '>=18'} + dependencies: + https-proxy-agent: 5.0.1 + optionalDependencies: + '@types/node': 14.18.63 + transitivePeerDependencies: + - supports-color + dev: false + /@algolia/cache-browser-local-storage/4.20.0: resolution: {integrity: sha512-uujahcBt4DxduBTvYdwO3sBfHuJvJokiC3BP1+O70fglmE1ShkH8lpXqZBac1rrU3FnNYSUs4pL9lBdTKeRPOQ==} dependencies: