import * as plugins from './bunq.plugins'; import { BunqAccount } from './bunq.classes.account'; import { BunqMonetaryAccount } from './bunq.classes.monetaryaccount'; import { IBunqPaymentRequest, IBunqPayment, IBunqAmount, IBunqAlias, IBunqPaginationOptions } from './bunq.interfaces'; 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 { 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 { 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 { 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 = {}; 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 { 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 { 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 { 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; } }