278 lines
7.0 KiB
TypeScript
278 lines
7.0 KiB
TypeScript
import * as plugins from './bunq.plugins.js';
|
|
import { BunqAccount } from './bunq.classes.account.js';
|
|
import { BunqMonetaryAccount } from './bunq.classes.monetaryaccount.js';
|
|
import { BunqPayment } from './bunq.classes.payment.js';
|
|
import type {
|
|
IBunqAmount,
|
|
IBunqAlias,
|
|
IBunqSchedulePayment,
|
|
IBunqSchedule
|
|
} from './bunq.interfaces.js';
|
|
|
|
export interface ISchedulePaymentOptions {
|
|
payment: {
|
|
amount: IBunqAmount;
|
|
counterparty_alias: IBunqAlias;
|
|
description: string;
|
|
attachment_id?: number;
|
|
merchant_reference?: string;
|
|
};
|
|
schedule: {
|
|
time_start: string;
|
|
time_end: string;
|
|
recurrence_unit: 'ONCE' | 'HOURLY' | 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'YEARLY';
|
|
recurrence_size: number;
|
|
};
|
|
}
|
|
|
|
export class BunqSchedulePayment {
|
|
private bunqAccount: BunqAccount;
|
|
|
|
constructor(bunqAccount: BunqAccount) {
|
|
this.bunqAccount = bunqAccount;
|
|
}
|
|
|
|
/**
|
|
* Create a scheduled payment
|
|
*/
|
|
public async create(
|
|
monetaryAccount: BunqMonetaryAccount,
|
|
options: ISchedulePaymentOptions
|
|
): Promise<number> {
|
|
await this.bunqAccount.apiContext.ensureValidSession();
|
|
|
|
const response = await this.bunqAccount.getHttpClient().post(
|
|
`/v1/user/${this.bunqAccount.userId}/monetary-account/${monetaryAccount.id}/schedule-payment`,
|
|
options
|
|
);
|
|
|
|
if (response.Response && response.Response[0] && response.Response[0].Id) {
|
|
return response.Response[0].Id.id;
|
|
}
|
|
|
|
throw new Error('Failed to create scheduled payment');
|
|
}
|
|
|
|
/**
|
|
* Get scheduled payment details
|
|
*/
|
|
public async get(
|
|
monetaryAccount: BunqMonetaryAccount,
|
|
scheduleId: number
|
|
): Promise<IBunqSchedulePayment> {
|
|
await this.bunqAccount.apiContext.ensureValidSession();
|
|
|
|
const response = await this.bunqAccount.getHttpClient().get(
|
|
`/v1/user/${this.bunqAccount.userId}/monetary-account/${monetaryAccount.id}/schedule-payment/${scheduleId}`
|
|
);
|
|
|
|
if (response.Response && response.Response[0] && response.Response[0].SchedulePayment) {
|
|
return response.Response[0].SchedulePayment;
|
|
}
|
|
|
|
throw new Error('Scheduled payment not found');
|
|
}
|
|
|
|
/**
|
|
* List scheduled payments
|
|
*/
|
|
public async list(
|
|
monetaryAccount: BunqMonetaryAccount,
|
|
options?: {
|
|
count?: number;
|
|
older_id?: number;
|
|
newer_id?: number;
|
|
}
|
|
): Promise<IBunqSchedulePayment[]> {
|
|
await this.bunqAccount.apiContext.ensureValidSession();
|
|
|
|
const params = {
|
|
count: options?.count || 10,
|
|
older_id: options?.older_id,
|
|
newer_id: options?.newer_id
|
|
};
|
|
|
|
const response = await this.bunqAccount.getHttpClient().list(
|
|
`/v1/user/${this.bunqAccount.userId}/monetary-account/${monetaryAccount.id}/schedule-payment`,
|
|
params
|
|
);
|
|
|
|
const schedules: IBunqSchedulePayment[] = [];
|
|
|
|
if (response.Response) {
|
|
for (const item of response.Response) {
|
|
if (item.SchedulePayment) {
|
|
schedules.push(item.SchedulePayment);
|
|
}
|
|
}
|
|
}
|
|
|
|
return schedules;
|
|
}
|
|
|
|
/**
|
|
* Update scheduled payment
|
|
*/
|
|
public async update(
|
|
monetaryAccount: BunqMonetaryAccount,
|
|
scheduleId: number,
|
|
updates: Partial<ISchedulePaymentOptions>
|
|
): Promise<void> {
|
|
await this.bunqAccount.apiContext.ensureValidSession();
|
|
|
|
await this.bunqAccount.getHttpClient().put(
|
|
`/v1/user/${this.bunqAccount.userId}/monetary-account/${monetaryAccount.id}/schedule-payment/${scheduleId}`,
|
|
updates
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Delete (cancel) scheduled payment
|
|
*/
|
|
public async delete(
|
|
monetaryAccount: BunqMonetaryAccount,
|
|
scheduleId: number
|
|
): Promise<void> {
|
|
await this.bunqAccount.apiContext.ensureValidSession();
|
|
|
|
await this.bunqAccount.getHttpClient().delete(
|
|
`/v1/user/${this.bunqAccount.userId}/monetary-account/${monetaryAccount.id}/schedule-payment/${scheduleId}`
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create a builder for scheduled payments
|
|
*/
|
|
public static builder(
|
|
bunqAccount: BunqAccount,
|
|
monetaryAccount: BunqMonetaryAccount
|
|
): SchedulePaymentBuilder {
|
|
return new SchedulePaymentBuilder(bunqAccount, monetaryAccount);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Builder for creating scheduled payments
|
|
*/
|
|
export class SchedulePaymentBuilder {
|
|
private bunqAccount: BunqAccount;
|
|
private monetaryAccount: BunqMonetaryAccount;
|
|
private paymentData: any = {};
|
|
private scheduleData: any = {};
|
|
|
|
constructor(bunqAccount: BunqAccount, monetaryAccount: BunqMonetaryAccount) {
|
|
this.bunqAccount = bunqAccount;
|
|
this.monetaryAccount = monetaryAccount;
|
|
}
|
|
|
|
/**
|
|
* Set payment amount
|
|
*/
|
|
public amount(value: string, currency: string): SchedulePaymentBuilder {
|
|
this.paymentData.amount = { value, currency };
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set recipient by IBAN
|
|
*/
|
|
public toIban(iban: string, name?: string): SchedulePaymentBuilder {
|
|
this.paymentData.counterparty_alias = {
|
|
type: 'IBAN',
|
|
value: iban,
|
|
name: name || iban
|
|
};
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set recipient by email
|
|
*/
|
|
public toEmail(email: string, name?: string): SchedulePaymentBuilder {
|
|
this.paymentData.counterparty_alias = {
|
|
type: 'EMAIL',
|
|
value: email,
|
|
name: name || email
|
|
};
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set payment description
|
|
*/
|
|
public description(description: string): SchedulePaymentBuilder {
|
|
this.paymentData.description = description;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Schedule once at specific time
|
|
*/
|
|
public scheduleOnce(dateTime: string): SchedulePaymentBuilder {
|
|
this.scheduleData = {
|
|
time_start: dateTime,
|
|
time_end: dateTime,
|
|
recurrence_unit: 'ONCE',
|
|
recurrence_size: 1
|
|
};
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Schedule daily
|
|
*/
|
|
public scheduleDaily(startDate: string, endDate: string): SchedulePaymentBuilder {
|
|
this.scheduleData = {
|
|
time_start: startDate,
|
|
time_end: endDate,
|
|
recurrence_unit: 'DAILY',
|
|
recurrence_size: 1
|
|
};
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Schedule weekly
|
|
*/
|
|
public scheduleWeekly(startDate: string, endDate: string, interval: number = 1): SchedulePaymentBuilder {
|
|
this.scheduleData = {
|
|
time_start: startDate,
|
|
time_end: endDate,
|
|
recurrence_unit: 'WEEKLY',
|
|
recurrence_size: interval
|
|
};
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Schedule monthly
|
|
*/
|
|
public scheduleMonthly(startDate: string, endDate: string, dayOfMonth?: number): SchedulePaymentBuilder {
|
|
this.scheduleData = {
|
|
time_start: startDate,
|
|
time_end: endDate,
|
|
recurrence_unit: 'MONTHLY',
|
|
recurrence_size: 1
|
|
};
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Create the scheduled payment
|
|
*/
|
|
public async create(): Promise<number> {
|
|
if (!this.paymentData.amount || !this.paymentData.counterparty_alias || !this.paymentData.description) {
|
|
throw new Error('Incomplete payment data');
|
|
}
|
|
|
|
if (!this.scheduleData.time_start || !this.scheduleData.recurrence_unit) {
|
|
throw new Error('Incomplete schedule data');
|
|
}
|
|
|
|
const schedulePayment = new BunqSchedulePayment(this.bunqAccount);
|
|
return schedulePayment.create(this.monetaryAccount, {
|
|
payment: this.paymentData,
|
|
schedule: this.scheduleData
|
|
});
|
|
}
|
|
} |