Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 25x 25x 25x 25x 25x 34x 34x 34x 2x 2x 34x 3x 3x 32x 3x 3x 8x 2x 8x 6x 6x 6x 6x 6x 6x 3x 29x 26x 26x 26x 26x 26x 26x 26x 34x 25x 1x 1x 1x 1x 1x 1x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 1x 1x 9x 9x 11x 11x 11x 11x 11x 11x 11x 2x 2x 2x 2x 2x 2x 2x 11x 1x 1x 1x 1x 1x 1x 1x 9x 9x 9x 9x 9x 9x 9x 9x 9x 1x 1x 8x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 3x 3x 9x 9x | /**
* Modal form submission utilities
*/
import { SDKError } from '../types';
import { decodeBase64 } from './helpers';
/**
* Creates hidden input fields from a data object
*/
export function createFormFields(
formElement: HTMLFormElement,
data: Record<string, unknown>,
prefix = ''
): void {
for (const [key, value] of Object.entries(data)) {
const fieldName = prefix ? `${prefix}[${key}]` : key;
if (value === null || value === undefined) {
// Skip null/undefined values
continue;
} else if (typeof value === 'object' && !Array.isArray(value)) {
// Recursively handle nested objects
createFormFields(formElement, value as Record<string, unknown>, fieldName);
} else if (Array.isArray(value)) {
// Handle arrays
value.forEach((item, index) => {
if (typeof item === 'object' && item !== null) {
createFormFields(formElement, item as Record<string, unknown>, `${fieldName}[${index}]`);
} else {
const input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', `${fieldName}[${index}]`);
input.setAttribute('value', String(item));
formElement.appendChild(input);
}
});
} else {
// Create hidden input for primitive values
const input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', fieldName);
input.setAttribute('value', String(value));
formElement.appendChild(input);
}
}
}
/**
* Submits the form to load 3DS authentication page in iframe
* Decodes base64 data, parses JSON, and creates hidden form fields
*/
export function submitRedirectForm(
formElement: HTMLFormElement,
url: string,
method: string,
base64Data: string,
add3dsSdkFlag = false,
log?: (message: string, ...args: unknown[]) => void
): void {
// Set form action and method
formElement.setAttribute('action', url);
formElement.setAttribute('method', method.toUpperCase());
// Clear any existing inputs
formElement.innerHTML = '';
try {
// Decode base64 data
log?.('Decoding base64 data');
const decodedData = decodeBase64(base64Data);
// Parse JSON object
log?.('Parsing JSON data');
const parsedData = JSON.parse(decodedData) as Record<string, unknown>;
// Adding flag so that paymentengine know it come from 3ds sdk
if (add3dsSdkFlag) {
parsedData.from3dsSdk = true;
}
// Create hidden input fields from parsed JSON object
log?.('Creating form fields from parsed data', parsedData);
createFormFields(formElement, parsedData);
// Submit the form
log?.('Submitting form to', url, 'with method', method);
formElement.submit();
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
log?.('Error processing form data', error);
throw new SDKError(
`Failed to process form data: ${errorMessage}`,
'FORM_DATA_PROCESSING_FAILED'
);
}
}
/**
* Submits form to iframe for action flow
* Creates a form that submits to the action URL with the value object as JSON string
* The form will submit to the modal iframe, similar to redirect flow
*/
export function submitActionForm(
formElement: HTMLFormElement,
iframeElement: HTMLIFrameElement,
actionUrl: string,
value: Record<string, unknown>,
log?: (message: string, ...args: unknown[]) => void
): void {
// Get the iframe name to target it
const iframeName = iframeElement.getAttribute('name');
if (!iframeName) {
throw new SDKError('Iframe name not found', 'IFRAME_NAME_NOT_FOUND');
}
log?.('Submitting action form to', actionUrl, 'with value object', value);
// Set form action, method, and target (iframe instead of _top)
formElement.setAttribute('action', actionUrl);
formElement.setAttribute('method', 'post');
formElement.setAttribute('target', iframeName);
formElement.setAttribute('name', 'form1');
// Clear any existing inputs
formElement.innerHTML = '';
// Convert the entire value object to JSON string
const valueJsonString = JSON.stringify(value);
log?.('Converted value object to JSON string', valueJsonString);
// Create hidden input for data with the JSON stringified value
const dataInput = document.createElement('input');
dataInput.setAttribute('type', 'hidden');
dataInput.setAttribute('name', 'data');
dataInput.setAttribute('value', valueJsonString);
dataInput.setAttribute('id', 'data');
formElement.appendChild(dataInput);
// Auto-submit the form after a brief delay to ensure it's in the DOM
// Using setTimeout to ensure the form is fully rendered
setTimeout(() => {
log?.('Auto-submitting form to', actionUrl);
formElement.submit();
}, 100);
}
|