@moneygraph/sdk
Version:
AI-native SDK for global payouts powered by StratosPay
272 lines (271 loc) • 9.64 kB
JavaScript
;
/**
* Accept Payments Module
*
* For merchants to accept payments via cards, widget embed, or popup checkout.
* Uses public key (pk_test_* or pk_live_*) for client-side operations.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.PaymentsModule = exports.TEST_CARDS = void 0;
// =============================================================================
// Test Cards (Sandbox Only)
// =============================================================================
exports.TEST_CARDS = {
// Success cards
VISA_SUCCESS: '4917484589897107',
MASTERCARD_SUCCESS: '5555555555554444',
DISCOVER_SUCCESS: '6011000990139424',
// Failure cards
CARD_BLOCKED: '6011000991300009',
INSUFFICIENT_FUNDS: '6011111111111117',
DO_NOT_HONOUR: '378282246310005',
// Special states
PENDING: '374245455400126',
REQUIRES_3DS: '4263982640269299',
REQUIRES_3DS_ALT: '5425233430109903',
REQUIRES_CONFIRMATION: '4000000000001976',
// Blocked countries for testing
BLOCKED_COUNTRIES: ['AF', 'KP'], // Afghanistan, North Korea
// Amount limits for testing
MIN_AMOUNT: 10,
MAX_AMOUNT: 100,
};
// =============================================================================
// Module
// =============================================================================
class PaymentsModule {
constructor(client, publicKey, mode) {
this.client = client;
this.publicKey = publicKey;
this.mode = mode;
this.mockPayments = new Map();
}
// ---------------------------------------------------------------------------
// Card Payments (Server-side)
// ---------------------------------------------------------------------------
/**
* Charge a card directly (server-side only, requires PCI compliance)
*/
async chargeCard(params) {
if (this.mode === 'sandbox') {
return this.mockChargeCard(params);
}
const response = await this.client.post('/payments/charge', {
...params,
public_key: this.publicKey,
});
return response;
}
/**
* Verify a payment by reference
*/
async verifyPayment(externalReference) {
if (this.mode === 'sandbox') {
return this.mockVerifyPayment(externalReference);
}
const response = await this.client.get(`/payments/verify/${externalReference}`);
return response;
}
// ---------------------------------------------------------------------------
// Widget/Popup Configuration (Client-side)
// ---------------------------------------------------------------------------
/**
* Generate configuration for the embed widget
* Use with: <script src="https://stratospay.com/embed.js"></script>
*/
generateWidgetConfig(params) {
return {
...params,
public_key: this.publicKey,
};
}
/**
* Generate configuration for the popup checkout
* Use with: <script src="https://stratospay.com/popup.js"></script>
*/
generatePopupConfig(params) {
return {
...params,
public_key: this.publicKey,
};
}
/**
* Generate a unique external reference
*/
generateReference(prefix) {
const timestamp = Date.now();
const random = Math.floor(Math.random() * 1000000);
return prefix ? `${prefix}_${timestamp}_${random}` : `${timestamp}_${random}`;
}
// ---------------------------------------------------------------------------
// React/Frontend Helpers
// ---------------------------------------------------------------------------
/**
* Get the widget script URL
*/
getWidgetScriptUrl() {
return 'https://stratospay.com/embed.js';
}
/**
* Get the popup script URL
*/
getPopupScriptUrl() {
return 'https://stratospay.com/popup.js';
}
/**
* Generate inline script for widget initialization
*/
generateWidgetScript(config) {
return `
const TRANSACTING_PARAMETERS = ${JSON.stringify(config, null, 2)};
checkout.init(TRANSACTING_PARAMETERS);
`;
}
// ---------------------------------------------------------------------------
// Sandbox Mock Implementation
// ---------------------------------------------------------------------------
mockChargeCard(params) {
const { card, amount, currency, external_reference, billing_address } = params;
// Check blocked countries
if (exports.TEST_CARDS.BLOCKED_COUNTRIES.includes(billing_address.country)) {
return {
id: `pay_mock_${Date.now()}`,
status: 'blocked',
amount,
currency,
external_reference,
message: 'Country blocked',
};
}
// Check amount limits
if (amount < exports.TEST_CARDS.MIN_AMOUNT) {
return {
id: `pay_mock_${Date.now()}`,
status: 'declined',
amount,
currency,
external_reference,
message: 'Amount below minimum limit',
};
}
if (amount > exports.TEST_CARDS.MAX_AMOUNT) {
return {
id: `pay_mock_${Date.now()}`,
status: 'declined',
amount,
currency,
external_reference,
message: 'Amount above maximum limit',
};
}
// Check card expiry
const [expMonth, expYear] = card.expire.split('/').map(Number);
const expDate = new Date(2000 + expYear, expMonth - 1);
if (expDate < new Date()) {
return {
id: `pay_mock_${Date.now()}`,
status: 'blocked',
amount,
currency,
external_reference,
message: 'Card expired',
};
}
// Check test card numbers
const cardNumber = card.card_number.replace(/\s/g, '');
switch (cardNumber) {
case exports.TEST_CARDS.VISA_SUCCESS:
case exports.TEST_CARDS.MASTERCARD_SUCCESS:
case exports.TEST_CARDS.DISCOVER_SUCCESS:
return {
id: `pay_mock_${Date.now()}`,
status: 'success',
amount,
currency,
external_reference,
message: 'Payment successful',
};
case exports.TEST_CARDS.CARD_BLOCKED:
return {
id: `pay_mock_${Date.now()}`,
status: 'blocked',
amount,
currency,
external_reference,
message: 'Card blocked',
};
case exports.TEST_CARDS.PENDING:
return {
id: `pay_mock_${Date.now()}`,
status: 'pending',
amount,
currency,
external_reference,
message: 'Transaction pending',
};
case exports.TEST_CARDS.INSUFFICIENT_FUNDS:
return {
id: `pay_mock_${Date.now()}`,
status: 'declined',
amount,
currency,
external_reference,
message: 'Insufficient funds',
};
case exports.TEST_CARDS.DO_NOT_HONOUR:
return {
id: `pay_mock_${Date.now()}`,
status: 'declined',
amount,
currency,
external_reference,
message: 'Do not honour',
};
case exports.TEST_CARDS.REQUIRES_3DS:
case exports.TEST_CARDS.REQUIRES_3DS_ALT:
return {
id: `pay_mock_${Date.now()}`,
status: 'requires_action',
amount,
currency,
external_reference,
message: '3DS authentication required',
action_url: `https://stratospay.com/3ds/mock/${external_reference}`,
};
case exports.TEST_CARDS.REQUIRES_CONFIRMATION:
return {
id: `pay_mock_${Date.now()}`,
status: 'pending',
amount,
currency,
external_reference,
message: 'Transaction to be confirmed',
};
default:
return {
id: `pay_mock_${Date.now()}`,
status: 'declined',
amount,
currency,
external_reference,
message: 'Card not supported',
};
}
}
mockVerifyPayment(externalReference) {
const cached = this.mockPayments.get(externalReference);
if (cached) {
return cached;
}
// Return a mock successful payment for testing
return {
id: `pay_mock_${Date.now()}`,
status: 'success',
amount: 100,
currency: 'USD',
external_reference: externalReference,
message: 'Payment verified',
};
}
}
exports.PaymentsModule = PaymentsModule;