Skip to content

Commit 1578b90

Browse files
committed
ifthenpay init
1 parent 637b342 commit 1578b90

File tree

5 files changed

+355
-6
lines changed

5 files changed

+355
-6
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import ifthenpay from "../../ifthenpay.app.mjs";
2+
import { axios } from "@pipedream/platform";
3+
4+
export default {
5+
key: "ifthenpay-create-payment-reference",
6+
name: "Create Payment Reference",
7+
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/)",
8+
version: "0.0.{{ts}}",
9+
type: "action",
10+
props: {
11+
ifthenpay,
12+
paymentMethod: {
13+
propDefinition: [
14+
ifthenpay,
15+
"paymentMethod",
16+
],
17+
},
18+
amount: {
19+
propDefinition: [
20+
ifthenpay,
21+
"amount",
22+
],
23+
},
24+
customerDetails: {
25+
propDefinition: [
26+
ifthenpay,
27+
"customerDetails",
28+
],
29+
},
30+
expirationDate: {
31+
propDefinition: [
32+
ifthenpay,
33+
"expirationDate",
34+
],
35+
optional: true,
36+
},
37+
description: {
38+
propDefinition: [
39+
ifthenpay,
40+
"description",
41+
],
42+
optional: true,
43+
},
44+
},
45+
async run({ $ }) {
46+
const response = await this.ifthenpay.generatePaymentReference({
47+
paymentMethod: this.paymentMethod,
48+
amount: this.amount,
49+
customerDetails: this.customerDetails,
50+
expirationDate: this.expirationDate,
51+
description: this.description,
52+
});
53+
54+
$.export("$summary", `Successfully created payment reference with Order ID: ${response.OrderId}`);
55+
return response;
56+
},
57+
};
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import ifthenpay from "../../ifthenpay.app.mjs";
2+
import { axios } from "@pipedream/platform";
3+
4+
export default {
5+
key: "ifthenpay-issue-refund",
6+
name: "Issue Refund",
7+
description: "Issue a full or partial refund for a previously completed payment via Ifthenpay. [See the documentation](https://ifthenpay.com/docs/en/)",
8+
version: "0.0.{{ts}}",
9+
type: "action",
10+
props: {
11+
ifthenpay,
12+
originalPaymentId: {
13+
propDefinition: [
14+
ifthenpay,
15+
"originalPaymentId",
16+
],
17+
},
18+
refundAmount: {
19+
propDefinition: [
20+
ifthenpay,
21+
"refundAmount",
22+
],
23+
},
24+
reasonForRefund: {
25+
propDefinition: [
26+
ifthenpay,
27+
"reasonForRefund",
28+
],
29+
optional: true,
30+
},
31+
},
32+
async run({ $ }) {
33+
const response = await this.ifthenpay.refundPayment({
34+
originalPaymentId: this.originalPaymentId,
35+
refundAmount: this.refundAmount,
36+
reasonForRefund: this.reasonForRefund,
37+
});
38+
39+
$.export("$summary", `Successfully issued a refund for payment ID: ${this.originalPaymentId}`);
40+
return response;
41+
},
42+
};
Lines changed: 174 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,180 @@
1+
import { axios } from "@pipedream/platform";
2+
13
export default {
24
type: "app",
35
app: "ifthenpay",
4-
propDefinitions: {},
6+
propDefinitions: {
7+
paymentMethod: {
8+
type: "string",
9+
label: "Payment Method",
10+
description: "The payment method to use for Ifthenpay (e.g., MB WAY, Multibanco)",
11+
options: [
12+
"MB WAY",
13+
"Multibanco",
14+
],
15+
},
16+
amount: {
17+
type: "string",
18+
label: "Amount",
19+
description: "The amount to be paid",
20+
},
21+
customerDetails: {
22+
type: "object",
23+
label: "Customer Details",
24+
description: "Details of the customer",
25+
properties: {
26+
clientCode: {
27+
type: "string",
28+
label: "Client Code",
29+
description: "The client's code",
30+
},
31+
clientName: {
32+
type: "string",
33+
label: "Client Name",
34+
description: "The name of the client",
35+
},
36+
clientEmail: {
37+
type: "string",
38+
label: "Client Email",
39+
description: "The email address of the client",
40+
},
41+
clientUsername: {
42+
type: "string",
43+
label: "Client Username",
44+
description: "The username of the client",
45+
},
46+
clientPhone: {
47+
type: "string",
48+
label: "Client Phone",
49+
description: "The phone number of the client",
50+
},
51+
mobileNumber: {
52+
type: "string",
53+
label: "Mobile Number",
54+
description: "The mobile phone number of the client",
55+
},
56+
},
57+
required: [
58+
"clientCode",
59+
"clientName",
60+
"clientEmail",
61+
],
62+
},
63+
expirationDate: {
64+
type: "string",
65+
label: "Expiration Date",
66+
description: "Expiration date of the payment reference",
67+
optional: true,
68+
},
69+
description: {
70+
type: "string",
71+
label: "Description",
72+
description: "Description of the payment",
73+
optional: true,
74+
},
75+
originalPaymentId: {
76+
type: "string",
77+
label: "Original Payment ID",
78+
description: "The ID of the original payment to refund",
79+
},
80+
refundAmount: {
81+
type: "string",
82+
label: "Refund Amount",
83+
description: "The amount to refund",
84+
},
85+
reasonForRefund: {
86+
type: "string",
87+
label: "Reason for Refund",
88+
description: "The reason for the refund",
89+
optional: true,
90+
},
91+
},
592
methods: {
6-
// this.$auth contains connected account data
7-
authKeys() {
8-
console.log(Object.keys(this.$auth));
93+
_baseUrl() {
94+
return "https://api.ifthenpay.com";
95+
},
96+
async _makeRequest(opts = {}) {
97+
const {
98+
$ = this, method = "GET", path = "/", headers = {}, ...otherOpts
99+
} = opts;
100+
return axios($, {
101+
...otherOpts,
102+
method,
103+
url: this._baseUrl() + path,
104+
headers: {
105+
...headers,
106+
"Authorization": `Bearer ${this.$auth.api_key}`,
107+
"Content-Type": "application/json",
108+
},
109+
});
110+
},
111+
async generatePaymentReference({
112+
paymentMethod,
113+
amount,
114+
customerDetails,
115+
expirationDate,
116+
description,
117+
}) {
118+
let path;
119+
const data = {
120+
orderId: new Date().getTime()
121+
.toString(), // Unique order ID
122+
amount,
123+
description,
124+
...customerDetails,
125+
};
126+
127+
if (paymentMethod === "Multibanco") {
128+
path = "/multibanco/reference/init";
129+
if (expirationDate !== undefined) {
130+
data.expiryDays = expirationDate;
131+
}
132+
data.mbKey = this.$auth.mbKey;
133+
} else if (paymentMethod === "MB WAY") {
134+
path = "/spg/payment/mbway";
135+
data.mbWayKey = this.$auth.mbWayKey;
136+
data.mobileNumber = customerDetails.mobileNumber;
137+
data.email = customerDetails.clientEmail;
138+
}
139+
140+
return this._makeRequest({
141+
method: "POST",
142+
path,
143+
data,
144+
});
145+
},
146+
async refundPayment({
147+
originalPaymentId,
148+
refundAmount,
149+
reasonForRefund,
150+
}) {
151+
const data = {
152+
backofficekey: this.$auth.backofficeKey,
153+
requestId: originalPaymentId,
154+
amount: refundAmount,
155+
};
156+
157+
if (reasonForRefund !== undefined) {
158+
data.reason = reasonForRefund;
159+
}
160+
161+
return this._makeRequest({
162+
method: "POST",
163+
path: "/endpoint/payments/refund",
164+
data,
165+
});
166+
},
167+
async emitPaymentCompletedEvent(paymentDetails) {
168+
const data = {
169+
paymentDetails,
170+
event: "payment_completed",
171+
};
172+
173+
return this._makeRequest({
174+
method: "POST",
175+
path: "/events",
176+
data,
177+
});
9178
},
10179
},
11-
};
180+
};

components/ifthenpay/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
"publishConfig": {
1313
"access": "public"
1414
}
15-
}
15+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { axios } from "@pipedream/platform";
2+
import ifthenpay from "../../ifthenpay.app.mjs";
3+
4+
export default {
5+
key: "ifthenpay-new-payment",
6+
name: "New Payment Completed",
7+
description: "Emit new event when a payment is successfully completed through Ifthenpay. [See the documentation](https://ifthenpay.com/docs/en/)",
8+
version: "0.0.{{ts}}",
9+
type: "source",
10+
dedupe: "unique",
11+
props: {
12+
ifthenpay,
13+
db: "$.service.db",
14+
timer: {
15+
type: "$.interface.timer",
16+
default: {
17+
intervalSeconds: 1800, // Poll every 30 minutes
18+
},
19+
},
20+
paymentMethod: {
21+
propDefinition: [
22+
ifthenpay,
23+
"paymentMethod",
24+
],
25+
},
26+
},
27+
hooks: {
28+
async deploy() {
29+
const pastEvents = await this.getCompletedPayments();
30+
const eventsToEmit = pastEvents.slice(0, 50);
31+
32+
for (const event of eventsToEmit) {
33+
this.$emit(event, {
34+
id: event.requestId,
35+
summary: `New Payment: ${event.amount} ${event.entity}`,
36+
ts: Date.parse(event.paymentDate),
37+
});
38+
}
39+
40+
if (eventsToEmit.length > 0) {
41+
this.setLastProcessedTimestamp(eventsToEmit[0].paymentDate);
42+
}
43+
},
44+
},
45+
methods: {
46+
async getCompletedPayments() {
47+
const lastProcessedTimestamp = this.getLastProcessedTimestamp();
48+
const payments = await this.ifthenpay._makeRequest({
49+
method: "POST",
50+
path: "/v2/payments/read",
51+
data: {
52+
boKey: this.ifthenpay.$auth.api_key,
53+
entity: this.paymentMethod,
54+
dateStart: new Date(lastProcessedTimestamp).toISOString(),
55+
},
56+
});
57+
return payments.payments;
58+
},
59+
getLastProcessedTimestamp() {
60+
return this.db.get("lastProcessedTimestamp") || Date.now() - 86400000;
61+
},
62+
setLastProcessedTimestamp(ts) {
63+
this.db.set("lastProcessedTimestamp", new Date(ts).toISOString());
64+
},
65+
},
66+
async run() {
67+
const completedPayments = await this.getCompletedPayments();
68+
69+
for (const payment of completedPayments) {
70+
this.$emit(payment, {
71+
id: payment.requestId,
72+
summary: `New Payment: ${payment.amount} ${payment.entity}`,
73+
ts: Date.parse(payment.paymentDate),
74+
});
75+
}
76+
77+
if (completedPayments.length > 0) {
78+
this.setLastProcessedTimestamp(completedPayments[0].paymentDate);
79+
}
80+
},
81+
};

0 commit comments

Comments
 (0)