Web
TypeScript SDK
Fully typed implementation for YardPay Pro with interfaces, enums, and generic responses. Drop these files into any TypeScript project.
Types & Interfaces
Create yardpaypro-types.ts — shared types used across all modules.
// yardpaypro-types.ts
export interface YardPayProConfig {
apiKey: string;
baseUrl?: string; // default: window.location.origin
timeout?: number; // default: 30000
}
export class YardPayProError extends Error {
status: number;
code: string;
constructor(status: number, code: string, message: string) {
super(message);
this.name = 'YardPayProError';
this.status = status;
this.code = code;
}
}
// --- Payments ---
export interface CardInfo {
name: string;
cardNumber: string;
expiryDate: string;
cvv: string;
}
export interface BillingAddress {
firstName: string;
lastName: string;
addressLine1: string;
city: string;
country: string;
}
export interface PayInvoiceRequest {
invoiceId?: number;
invoiceIdentifier?: string;
paymentOptionId: number;
fundingSourceId?: number;
card?: CardInfo;
billingAddress?: BillingAddress;
sessionToken?: string;
}
export type ApprovalAction = 'None' | 'Redirect' | 'FormData' | 'QrCode';
export interface PaymentResponse {
referenceNumber?: string;
clientReferenceNumber?: string;
invoiceIdentifier?: string;
amountPaid?: number;
amountDue?: number;
feePaid?: number;
currency?: string;
paymentStatusId?: string;
paymentDateTime?: string;
paymentMethod?: string;
isSuccess: boolean;
approvalAction?: ApprovalAction;
approvalDataOrUrl?: string;
is3DSecureAuth?: boolean;
authorizationCode?: string;
hostMessage?: string;
}
export interface FundingSource {
id: number;
name: string;
paymentOptionId: number;
statusId: string;
isVerified: boolean;
maskedAccountNumber: string;
expiryDate?: string;
}
export interface PaymentMethod {
id: number;
code: string;
name: string;
paymentMethodId: string;
paymentProviderTypeId?: string;
paymentChannel?: string;
isEnabled: boolean;
currencyCode?: string;
}
// --- Invoices ---
export type InvoiceStatus = 'Draft' | 'Pending' | 'Sent' | 'PartiallyPaid' | 'Paid' | 'Overdue' | 'Cancelled' | 'Expired';
export type InvoiceItemType = 'Product' | 'Service' | 'Subscription' | 'Fee' | 'Discount' | 'Tax';
export interface InvoiceItem {
id?: number;
name: string;
description?: string;
unitCost: number;
quantity: number;
discount?: number;
taxRate?: number;
taxAmount?: number;
totalCost?: number;
invoiceItemTypeId?: InvoiceItemType;
}
export interface CounterPartyInfo {
firstName: string;
lastName: string;
email: string;
}
export interface Invoice {
id: number;
identifier: string;
referenceNumber?: string;
invoiceNumber?: string;
description?: string;
status: InvoiceStatus;
totalDue?: number;
totalPaid?: number;
subTotal?: number;
taxAmount?: number;
totalCost: number;
currencyCode: string;
items?: InvoiceItem[];
sourceInfo?: CounterPartyInfo;
paymentDueDate?: string;
successUrl?: string;
cancelUrl?: string;
}
export interface CreateInvoiceRequest {
description?: string;
currencyCode: string;
paymentDueDate?: string;
notes?: string;
items: Omit<InvoiceItem, 'id' | 'totalCost' | 'taxAmount'>[];
sourceInfo: CounterPartyInfo;
successUrl?: string;
cancelUrl?: string;
}
// --- Subscriptions ---
export type SubscriptionProductType = 'Service' | 'Digital' | 'Physical';
export type SubscriptionPlanStatus = 'Active' | 'Inactive' | 'Archived';
export type SubscriptionBillingType = 'Recurring' | 'OneTime' | 'Usage';
export type TimeUnit = 'Day' | 'Week' | 'Month' | 'Year';
export type InventoryItemStatus = 'Available' | 'Rented' | 'Reserved' | 'Discontinued';
export interface SubscriptionProduct {
id: number;
merchantId: number;
name: string;
description?: string;
subscriptionProductType: SubscriptionProductType;
}
export interface SubscriptionPlan {
id: number;
merchantId: number;
productId: number;
productName?: string;
name: string;
description?: string;
status: SubscriptionPlanStatus;
amount: string;
currency: string;
timeUnit: TimeUnit;
timeInterval: number;
subscriptionBillingType: SubscriptionBillingType;
}
export interface SubscriptionInventoryItem {
id: number;
productId: number;
productName?: string;
serialNumber?: string;
status: InventoryItemStatus;
}
// --- OData ---
export interface ODataParams {
$filter?: string;
$orderby?: string;
$top?: number;
$skip?: number;
$expand?: string;
$select?: string;
$count?: boolean;
}API Client
Create yardpaypro-client.ts — the typed HTTP client.
// yardpaypro-client.ts
import { YardPayProConfig, YardPayProError } from './yardpaypro-types';
export class YardPayProClient {
private apiKey: string;
private baseUrl: string;
private timeout: number;
constructor(config: YardPayProConfig) {
this.apiKey = config.apiKey;
this.baseUrl = config.baseUrl ?? window.location.origin;
this.timeout = config.timeout ?? 30000;
}
async request<T>(method: string, path: string, options?: {
body?: unknown;
params?: Record<string, string | number | boolean | undefined>;
}): Promise<T> {
let url = this.baseUrl + path;
if (options?.params) {
const qs = new URLSearchParams();
Object.entries(options.params).forEach(([k, v]) => {
if (v !== undefined && v !== null) qs.append(k, String(v));
});
const str = qs.toString();
if (str) url += '?' + str;
}
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), this.timeout);
try {
const res = await fetch(url, {
method,
headers: {
'Content-Type': 'application/json',
'x-api-key': this.apiKey,
},
body: options?.body ? JSON.stringify(options.body) : undefined,
signal: controller.signal,
});
clearTimeout(timer);
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new YardPayProError(res.status, err.code ?? 'api_error', err.message ?? res.statusText);
}
if (res.status === 204) return null as T;
const data = await res.json();
return (data.value !== undefined ? data.value : data) as T;
} catch (err) {
clearTimeout(timer);
if (err instanceof YardPayProError) throw err;
if ((err as Error).name === 'AbortError') {
throw new YardPayProError(0, 'timeout', 'Request timed out');
}
throw err;
}
}
get<T>(path: string, params?: Record<string, string | number | boolean | undefined>) {
return this.request<T>('GET', path, { params });
}
post<T>(path: string, body: unknown) {
return this.request<T>('POST', path, { body });
}
put<T>(path: string, body: unknown) {
return this.request<T>('PUT', path, { body });
}
delete(path: string) {
return this.request<void>('DELETE', path);
}
}Service Modules
Create yardpaypro-services.ts — typed wrappers for each API area.
// yardpaypro-services.ts
import { YardPayProClient } from './yardpaypro-client';
import type {
PayInvoiceRequest, PaymentResponse, FundingSource, PaymentMethod,
Invoice, CreateInvoiceRequest, ODataParams,
SubscriptionProduct, SubscriptionPlan, SubscriptionInventoryItem,
} from './yardpaypro-types';
// --- Payments ---
export class PaymentsService {
constructor(private client: YardPayProClient) {}
payInvoice(data: PayInvoiceRequest) {
return this.client.post<PaymentResponse>('/api/payment/payinvoice', data);
}
getPaymentMethods(invoiceId: number) {
return this.client.get<PaymentMethod[]>(`/v1/invoice/${invoiceId}/PaymentMethods`);
}
getFundingSources() {
return this.client.get<FundingSource[]>('/v1/FundingSource');
}
registerCard(data: { card: { name: string; cardNumber: string; expiryDate: string; cvv: string }; name: string }) {
return this.client.post<{ fundingSourceId: number; paymentResponse: PaymentResponse }>('/v1/payment/RegisterCard', data);
}
verifyCard(fundingSourceId: number, code: string) {
return this.client.post<void>(`/v1/fundingSource/${fundingSourceId}/verify`, { VerificationCode: code });
}
}
// --- Invoices ---
export class InvoicesService {
constructor(private client: YardPayProClient) {}
getByReference(code: string) {
return this.client.get<Invoice>(`/v1/invoice/getByReference(code='${code}')`);
}
getById(id: number, expand?: string) {
return this.client.get<Invoice>(`/v1/invoice/${id}`, expand ? { $expand: expand } : undefined);
}
list(params?: ODataParams) {
return this.client.get<Invoice[]>('/v1/invoice', params as Record<string, string | number | boolean | undefined>);
}
create(data: CreateInvoiceRequest) {
return this.client.post<Invoice>('/v1/invoice', data);
}
getQrCodeUrl(identifier: string) {
return `/v1/invoice/qrcode/${identifier}`;
}
}
// --- Subscriptions ---
export class SubscriptionsService {
constructor(private client: YardPayProClient) {}
listProducts(params?: ODataParams) {
return this.client.get<SubscriptionProduct[]>('/v1/SubscriptionProduct', params as Record<string, string | number | boolean | undefined>);
}
createProduct(data: Partial<SubscriptionProduct>) {
return this.client.post<SubscriptionProduct>('/v1/SubscriptionProduct', data);
}
updateProduct(id: number, data: Partial<SubscriptionProduct>) {
return this.client.put<SubscriptionProduct>(`/v1/SubscriptionProduct/${id}`, data);
}
deleteProduct(id: number) {
return this.client.delete(`/v1/SubscriptionProduct/${id}`);
}
listPlans(params?: ODataParams) {
return this.client.get<SubscriptionPlan[]>('/v1/SubscriptionPlan', params as Record<string, string | number | boolean | undefined>);
}
createPlan(data: Partial<SubscriptionPlan>) {
return this.client.post<SubscriptionPlan>('/v1/SubscriptionPlan', data);
}
updatePlan(id: number, data: Partial<SubscriptionPlan>) {
return this.client.put<SubscriptionPlan>(`/v1/SubscriptionPlan/${id}`, data);
}
deletePlan(id: number) {
return this.client.delete(`/v1/SubscriptionPlan/${id}`);
}
listInventory(params?: ODataParams) {
return this.client.get<SubscriptionInventoryItem[]>('/v1/SubscriptionInventoryItem', params as Record<string, string | number | boolean | undefined>);
}
createInventoryItem(data: Partial<SubscriptionInventoryItem>) {
return this.client.post<SubscriptionInventoryItem>('/v1/SubscriptionInventoryItem', data);
}
updateInventoryItem(id: number, data: Partial<SubscriptionInventoryItem>) {
return this.client.put<SubscriptionInventoryItem>(`/v1/SubscriptionInventoryItem/${id}`, data);
}
deleteInventoryItem(id: number) {
return this.client.delete(`/v1/SubscriptionInventoryItem/${id}`);
}
}Usage
import { YardPayProClient } from './yardpaypro-client';
import { YardPayProError } from './yardpaypro-types';
import { PaymentsService, InvoicesService, SubscriptionsService } from './yardpaypro-services';
const client = new YardPayProClient({ apiKey: 'sk_test_YOUR_KEY' });
const payments = new PaymentsService(client);
const invoices = new InvoicesService(client);
const subs = new SubscriptionsService(client);
// Create invoice → pay it → handle 3DS
const invoice = await invoices.create({
description: 'Order #1234',
currencyCode: 'JMD',
items: [{ name: 'Widget', unitCost: 100, quantity: 2 }],
sourceInfo: { firstName: 'Test', lastName: 'User', email: '[email protected]' },
});
const methods = await payments.getPaymentMethods(invoice.id);
const cardMethod = methods.find(m => m.paymentMethodId === 'CreditCard')!;
try {
const result = await payments.payInvoice({
invoiceIdentifier: invoice.identifier,
paymentOptionId: cardMethod.id,
card: { name: 'Test User', cardNumber: '4111111111111111', expiryDate: '12/28', cvv: '123' },
});
if (result.isSuccess && result.approvalAction === 'Redirect') {
window.location.href = result.approvalDataOrUrl!; // 3D Secure
} else if (result.isSuccess) {
console.log('Paid:', result.referenceNumber);
}
} catch (err) {
if (err instanceof YardPayProError) {
console.error(`[${err.status}] ${err.code}: ${err.message}`);
}
}Requirements
- TypeScript 4.7+ (for
satisfiesand module resolution) - No external dependencies — uses native
fetch - Works in browser and Node.js 18+
- Compatible with React, Vue, Angular, Svelte, and any TypeScript project