Files
bunq/ts/bunq.classes.payment.ts
Juergen Kunz 596efa3f06 update
2025-07-18 10:43:39 +00:00

283 lines
6.8 KiB
TypeScript

import * as plugins from './bunq.plugins.js';
import { BunqAccount } from './bunq.classes.account.js';
import { BunqMonetaryAccount } from './bunq.classes.monetaryaccount.js';
import {
IBunqPaymentRequest,
IBunqPayment,
IBunqAmount,
IBunqAlias,
IBunqPaginationOptions
} from './bunq.interfaces.js';
export class BunqPayment {
private bunqAccount: BunqAccount;
private monetaryAccount: BunqMonetaryAccount;
private paymentData: IBunqPaymentRequest;
// Properties populated after creation
public id?: number;
public created?: string;
public updated?: string;
public status?: string;
constructor(
bunqAccount: BunqAccount,
monetaryAccount: BunqMonetaryAccount,
paymentData: IBunqPaymentRequest
) {
this.bunqAccount = bunqAccount;
this.monetaryAccount = monetaryAccount;
this.paymentData = paymentData;
}
/**
* Create the payment
*/
public async create(): Promise<number> {
await this.bunqAccount.apiContext.ensureValidSession();
const response = await this.bunqAccount.getHttpClient().post(
`/v1/user/${this.bunqAccount.userId}/monetary-account/${this.monetaryAccount.id}/payment`,
this.paymentData
);
if (response.Response && response.Response[0] && response.Response[0].Id) {
this.id = response.Response[0].Id.id;
return this.id;
}
throw new Error('Failed to create payment');
}
/**
* Get payment details
*/
public async get(): Promise<IBunqPayment> {
if (!this.id) {
throw new Error('Payment ID not set');
}
await this.bunqAccount.apiContext.ensureValidSession();
const response = await this.bunqAccount.getHttpClient().get(
`/v1/user/${this.bunqAccount.userId}/monetary-account/${this.monetaryAccount.id}/payment/${this.id}`
);
if (response.Response && response.Response[0] && response.Response[0].Payment) {
return response.Response[0].Payment;
}
throw new Error('Payment not found');
}
/**
* List payments for a monetary account
*/
public static async list(
bunqAccount: BunqAccount,
monetaryAccountId: number,
options?: IBunqPaginationOptions
): Promise<IBunqPayment[]> {
await bunqAccount.apiContext.ensureValidSession();
const response = await bunqAccount.getHttpClient().list(
`/v1/user/${bunqAccount.userId}/monetary-account/${monetaryAccountId}/payment`,
options
);
const payments: IBunqPayment[] = [];
if (response.Response) {
for (const item of response.Response) {
if (item.Payment) {
payments.push(item.Payment);
}
}
}
return payments;
}
/**
* Create a payment builder
*/
public static builder(
bunqAccount: BunqAccount,
monetaryAccount: BunqMonetaryAccount
): PaymentBuilder {
return new PaymentBuilder(bunqAccount, monetaryAccount);
}
}
/**
* Builder class for creating payments
*/
export class PaymentBuilder {
private bunqAccount: BunqAccount;
private monetaryAccount: BunqMonetaryAccount;
private paymentData: Partial<IBunqPaymentRequest> = {};
constructor(bunqAccount: BunqAccount, monetaryAccount: BunqMonetaryAccount) {
this.bunqAccount = bunqAccount;
this.monetaryAccount = monetaryAccount;
}
/**
* Set the amount
*/
public amount(value: string, currency: string = 'EUR'): this {
this.paymentData.amount = { value, currency };
return this;
}
/**
* Set the counterparty by IBAN
*/
public toIban(iban: string, name?: string): this {
this.paymentData.counterparty_alias = {
type: 'IBAN',
value: iban,
name
};
return this;
}
/**
* Set the counterparty by email
*/
public toEmail(email: string, name?: string): this {
this.paymentData.counterparty_alias = {
type: 'EMAIL',
value: email,
name
};
return this;
}
/**
* Set the counterparty by phone number
*/
public toPhoneNumber(phoneNumber: string, name?: string): this {
this.paymentData.counterparty_alias = {
type: 'PHONE_NUMBER',
value: phoneNumber,
name
};
return this;
}
/**
* Set the description
*/
public description(description: string): this {
this.paymentData.description = description;
return this;
}
/**
* Set merchant reference
*/
public merchantReference(reference: string): this {
this.paymentData.merchant_reference = reference;
return this;
}
/**
* Allow bunq.to payments
*/
public allowBunqto(allow: boolean = true): this {
this.paymentData.allow_bunqto = allow;
return this;
}
/**
* Add attachments
*/
public attachments(attachmentIds: number[]): this {
this.paymentData.attachment = attachmentIds.map(id => ({ id }));
return this;
}
/**
* Build and create the payment
*/
public async create(): Promise<BunqPayment> {
if (!this.paymentData.amount) {
throw new Error('Amount is required');
}
if (!this.paymentData.counterparty_alias) {
throw new Error('Counterparty is required');
}
if (!this.paymentData.description) {
throw new Error('Description is required');
}
const payment = new BunqPayment(
this.bunqAccount,
this.monetaryAccount,
this.paymentData as IBunqPaymentRequest
);
await payment.create();
return payment;
}
}
/**
* Batch payment class for creating multiple payments at once
*/
export class BunqBatchPayment {
private bunqAccount: BunqAccount;
private monetaryAccount: BunqMonetaryAccount;
private payments: IBunqPaymentRequest[] = [];
constructor(bunqAccount: BunqAccount, monetaryAccount: BunqMonetaryAccount) {
this.bunqAccount = bunqAccount;
this.monetaryAccount = monetaryAccount;
}
/**
* Add a payment to the batch
*/
public addPayment(payment: IBunqPaymentRequest): this {
this.payments.push(payment);
return this;
}
/**
* Create all payments in the batch
*/
public async create(): Promise<number> {
if (this.payments.length === 0) {
throw new Error('No payments in batch');
}
await this.bunqAccount.apiContext.ensureValidSession();
const response = await this.bunqAccount.getHttpClient().post(
`/v1/user/${this.bunqAccount.userId}/monetary-account/${this.monetaryAccount.id}/payment-batch`,
{
payments: this.payments
}
);
if (response.Response && response.Response[0] && response.Response[0].Id) {
return response.Response[0].Id.id;
}
throw new Error('Failed to create batch payment');
}
/**
* Get batch payment details
*/
public async get(batchId: number): Promise<any> {
await this.bunqAccount.apiContext.ensureValidSession();
const response = await this.bunqAccount.getHttpClient().get(
`/v1/user/${this.bunqAccount.userId}/monetary-account/${this.monetaryAccount.id}/payment-batch/${batchId}`
);
return response.Response;
}
}