UNPKG

@sahabaplus/moyasar

Version:

A comprehensive TypeScript SDK for integrating with the Moyasar payment gateway

277 lines 9.16 kB
import { API_ENDPOINTS } from "../../shared/constants/index"; import { PaymentStatus } from "./enums"; import { PaymentUtils } from "./utils"; import { PaymentError } from "./errors"; import { MoyasarError } from "../../shared/errors"; export class PaymentService { constructor(p) { this.apiClient = p.apiClient; } /** * Create a new payment */ async create(params) { // Validate input const validation = PaymentUtils.validateCreatePaymentRequest(params); if (!validation.success) { throw new PaymentError(`Validation failed: ${validation.errors.join(", ")}`, 400); } try { const response = await this.apiClient.request({ method: "POST", url: API_ENDPOINTS.payments, data: params, }); return PaymentUtils.parsePayment(response); } catch (error) { const paymentError = this.handleError(error, `Failed to create payment`); throw paymentError; } } /** * List payments with optional filtering */ async list(options = {}) { try { // Convert metadata filters to proper query format const queryParams = this.parseBody(options); const response = await this.apiClient.request({ method: "GET", url: API_ENDPOINTS.payments, params: queryParams, }); const parsed = PaymentUtils.parseListPaymentsResponse(response); return parsed; } catch (error) { const paymentError = this.handleError(error, "Failed to list payments"); throw paymentError; } } /** * Retrieve a specific payment */ async retrieve(paymentId) { if (!paymentId) throw new PaymentError("Payment ID is required", 400); try { const response = await this.apiClient.request({ method: "GET", url: `${API_ENDPOINTS.payments}/${paymentId}`, }); // Parse and validate the response const payment = PaymentUtils.parsePayment(response); return payment; } catch (error) { const paymentError = this.handleError(error, `Failed to retrieve payment ${paymentId}`); throw paymentError; } } /** * Update a payment */ async update({ paymentId, update, }) { if (!paymentId) { throw new PaymentError("Payment ID is required", 400); } // Validate input const validation = PaymentUtils.validateUpdatePaymentRequest(update); if (!validation.success) { throw new PaymentError(`Validation failed: ${validation.errors.join(", ")}`, 400); } try { const response = await this.apiClient.request({ method: "PUT", url: `${API_ENDPOINTS.payments}/${paymentId}`, data: update, }); return response; } catch (error) { const paymentError = this.handleError(error, `Failed to update payment ${paymentId}`); throw paymentError; } } /** * Refund a payment (full or partial) */ async refund({ paymentId, refund, }) { if (!paymentId) { throw new PaymentError("Payment ID is required", 400); } refund.amount; // Validate input const validation = PaymentUtils.validateRefundRequest(refund); if (!validation.success) { throw new PaymentError(`Validation failed: ${validation.errors.join(", ")}`, 400); } try { const response = await this.apiClient.request({ method: "POST", url: `${API_ENDPOINTS.payments}/${paymentId}/refund`, data: refund, }); // Parse and validate the response const payment = PaymentUtils.parsePayment(response); return payment; } catch (error) { const paymentError = this.handleError(error, `Failed to refund payment ${paymentId}`); throw paymentError; } } /** * Capture an authorized payment (full or partial) */ async capture({ paymentId, capture, }) { if (!paymentId) throw new PaymentError("Payment ID is required", 400); // Validate input const validation = PaymentUtils.validateCaptureRequest(capture); if (!validation.success) { throw new PaymentError(`Validation failed: ${validation.errors}`, 400, { errors: validation.errors, }); } try { const response = await this.apiClient.request({ method: "POST", url: `${API_ENDPOINTS.payments}/${paymentId}/capture`, data: capture, }); // Parse and validate the response const payment = PaymentUtils.parsePayment(response); return payment; } catch (error) { const paymentError = this.handleError(error, `Failed to capture payment ${paymentId}`); throw paymentError; } } /** * Void an authorized payment */ async void(paymentId) { if (!paymentId) throw new PaymentError("Payment ID is required", 400); try { const response = await this.apiClient.request({ method: "POST", url: `${API_ENDPOINTS.payments}/${paymentId}/void`, }); // Parse and validate the response const payment = PaymentUtils.parsePayment(response); return payment; } catch (error) { const paymentError = this.handleError(error, `Failed to void payment ${paymentId}`); throw paymentError; } } /** * Search payments by metadata */ async searchByMetadata({ metadata, options, }) { const metadataQuery = PaymentUtils.buildMetadataQuery(metadata); return this.list({ ...options, ...metadataQuery, }); } /** * Get payments by status */ async getByStatus(status, options = {}) { return this.list({ ...options, status, }); } /** * Get paid payments */ async getPaid(options = {}) { return this.getByStatus(PaymentStatus.PAID, options); } /** * Get failed payments */ async getFailed(options = {}) { return this.getByStatus(PaymentStatus.FAILED, options); } /** * Get authorized payments */ async getAuthorized(options = {}) { return this.getByStatus(PaymentStatus.AUTHORIZED, options); } /** * Get refunded payments */ async getRefunded(options = {}) { return this.getByStatus(PaymentStatus.REFUNDED, options); } /** * Get payments by card last 4 digits */ async getByCardLast4({ last4, options, }) { if (!/^\d{4}$/.test(last4)) { throw new PaymentError("Last 4 digits must be exactly 4 digits", 400); } return this.list({ ...options, last_4: last4, }); } /** * Get payments by RRN (Retrieval Reference Number) */ async getByRRN({ rrn, options, }) { if (!/^\d{12}$/.test(rrn)) { throw new PaymentError("RRN must be exactly 12 digits", 400); } return this.list({ ...options, rrn, }); } /** * Check payment capabilities (what actions can be performed) */ async getPaymentCapabilities(paymentId) { const payment = await this.retrieve(paymentId); return { canRefund: PaymentUtils.canRefundPayment(payment), canCapture: PaymentUtils.canCapturePayment(payment), canVoid: PaymentUtils.canVoidPayment(payment), maxRefundAmount: PaymentUtils.getMaxRefundAmount(payment), maxCaptureAmount: PaymentUtils.getMaxCaptureAmount(payment), }; } handleError(error, message) { if (error instanceof PaymentError) return error; if (error instanceof MoyasarError) { return new PaymentError(`${message}: ${error.message}`, error.statusCode, { ...error.details }); } const errorMessage = error?.message || error?.toString() || "Unknown error"; return new PaymentError(`${message}: ${errorMessage}`, 500, { cause: errorMessage, }); } parseBody(p) { const copied = { ...p }; Object.entries(copied).forEach(([key, value]) => { if (typeof value === "object") { if (value instanceof Date) { // @ts-expect-error copied[key] = value.toISOString(); } } }); return copied; } } //# sourceMappingURL=service.js.map