RDCW Slip Verify SDK for Node.js - Verify Thai bank transfer slips via QR code scanning
npm install node-rdcw-slipverifyAn unofficial SDK for RDCW Slip Verify with a clean factory function API combining functional and OOP paradigms.
``bash`
npm install node-rdcw-slipverify
`typescript
import { createRdcwVerify } from "node-rdcw-slipverify";
const rdcw = createRdcwVerify({
clientId: "your-client-id",
secret: "your-client-secret",
});
// Verify a slip from payload
const result = await rdcw.inquiryPayload(
"0038000600000101030060217Bf870bf26685f55526203TH9104CF62"
);
if (result.error) {
console.log("Error:", result.error.message);
} else {
console.log("Success:", result.data);
}
`
The SDK supports multiple locales for error messages. By default, it uses English (en), but you can configure it to use Thai (th) or provide custom messages.
`typescript
import { createRdcwVerify } from "node-rdcw-slipverify";
const rdcw = createRdcwVerify({
clientId: "your-client-id",
secret: "your-client-secret",
locale: "th", // Use Thai locale
});
// All error messages will now be in Thai
const result = await rdcw.inquiryPayload(invalidPayload);
if (result.error) {
console.log(result.error.message); // "สลิปไม่ถูกต้อง" instead of "Invalid slip"
}
`
You can also provide custom messages to override the default locale messages:
`typescript`
const rdcw = createRdcwVerify({
clientId: "your-client-id",
secret: "your-client-secret",
locale: "en",
customMessages: {
validation: {
invalidSlip: "The slip you provided is not valid",
slipExpired: "This slip is too old to be processed",
},
qr: {
notFound: "We couldn't find a QR code in your image",
},
},
});
- en - English (default)th
- - Thai (ภาษาไทย)
`typescript
import { createRdcwVerify } from "node-rdcw-slipverify";
const rdcw = createRdcwVerify({
clientId: "your-client-id",
secret: "your-client-secret",
});
// Verify from payload
const result = await rdcw.inquiryPayload(payload);
// Verify from image
const imageResult = await rdcw.inquiryImage(imageBuffer);
if (result.data) {
console.log("Transaction details:", result.data);
}
`
`typescript
const result = await rdcw.inquiryPayload(payload, {
expectedAccount: "1234567890",
expectedBank: "014",
expectedAmount: "100.00", // Optional
});
if (result.error) {
console.log("Validation failed:", result.error.message);
// Handle specific error types
switch (result.error.type) {
case "INVALID_SLIP":
// Handle invalid slip
break;
case "EXPIRED_SLIP":
// Handle expired slip
break;
case "VALIDATION_ERROR":
// Handle validation errors
break;
case "API_ERROR":
// Handle API errors
break;
case "QR_CODE_ERROR":
// Handle QR code errors
break;
}
} else {
console.log("Validation successful!", result.data);
}
`
`typescript
const result = await rdcw.inquiryImage(imageBuffer, {
expectedAccount: "1234567890",
expectedBank: "014",
onSuccess: (data) => {
console.log("✅ Verification successful!");
console.log("Amount:", data.data.amount);
console.log("From:", data.data.sender.displayName);
},
onError: (error) => {
console.log("❌ API Error:", error.message);
},
onValidationError: (error) => {
console.log("⚠️ Validation failed:", error.message);
},
});
// Result is still returned for further processing
if (result.data) {
// Save to database, etc.
}
`
`typescript
// First, verify the slip
const verifyResult = await rdcw.inquiryPayload(payload);
if (verifyResult.data) {
// Then, validate manually
const validateResult = rdcw.validate(verifyResult.data, {
expectedAccount: "1234567890",
expectedBank: "014",
expectedAmount: "100.00",
onSuccess: (data) => console.log("Validation passed!"),
onValidationError: (error) =>
console.log("Validation failed:", error.message),
});
if (validateResult.data) {
console.log("All checks passed!");
}
}
`
`typescript
import fs from "fs";
// From file buffer
const imageBuffer = fs.readFileSync("path/to/qr-code-image.png");
const result = await rdcw.inquiryImage(imageBuffer, {
expectedAccount: "1234567890",
expectedBank: "014",
});
// From base64 string
const base64Image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...";
const result2 = await rdcw.inquiryImage(base64Image);
`
#### createRdcwVerify(config)
Creates a new RDCW Verify instance.
Parameters:
- config.clientId (string, required): Your SlipVerify client IDconfig.secret
- (string, required): Your SlipVerify client secretconfig.baseUrl
- (string, optional): Custom API base URL (default: "https://suba.rdcw.co.th")config.locale
- (Locale, optional): Locale for error messages - "en" or "th" (default: "en")config.customMessages
- (Partial
Returns: RdcwVerify instance
#### inquiryPayload(payload, options?)
Verifies a slip using its payload string.
Parameters:
- payload (string): The QR code payload stringoptions
- (ValidationOptions, optional): Validation options
Returns: Promise
#### inquiryImage(imageData, options?)
Reads a QR code from an image and verifies the slip.
Parameters:
- imageData (ArrayBuffer | Buffer | string): Image data (buffer or base64 string)options
- (ValidationOptions, optional): Validation options
Returns: Promise
#### validate(result, options)
Manually validates a verification result.
Parameters:
- result (VerifySlipResult): The result from inquiryoptions
- (ValidationOptions): Validation options
Returns: Result
#### Locale
`typescript`
type Locale = "en" | "th";
#### LocaleMessages
`typescript`
interface LocaleMessages {
qr: {
invalidDimensions: string;
notFound: string;
readFailed: string;
};
api: {
invalidResponse: string;
requestFailed: string;
unexpectedError: string;
};
validation: {
invalidSlip: string;
slipAlreadyUsed: string;
slipExpired: string;
invalidAccount: string;
invalidBank: string;
invalidQRFormat: string;
amountMismatch: string;
};
}
#### Result
`typescript
type Result
interface Success
data: T;
error?: never;
}
interface Failure
data?: never;
error: E;
}
`
#### ValidationOptions
`typescript`
interface ValidationOptions {
expectedAccount?: string;
expectedBank?: string;
expectedAmount?: string;
onSuccess?: (data: VerifySlipResult) => void;
onError?: (error: SlipError) => void;
onValidationError?: (error: SlipError) => void;
}
#### SlipError
`typescript
interface SlipError {
type: ErrorType;
message: string;
}
type ErrorType =
| "INVALID_SLIP"
| "EXPIRED_SLIP"
| "QR_CODE_ERROR"
| "API_ERROR"
| "VALIDATION_ERROR";
`
#### VerifySlipResult
`typescript
interface VerifySlipResult {
discriminator: string;
valid: boolean;
data: Data;
quota: Quota;
subscription: Subscription;
isCached: boolean;
}
interface Data {
language: string;
transRef: string;
sendingBank: string;
receivingBank: string;
transDate: string;
transTime: string;
sender: Receiver;
receiver: Receiver;
amount: string;
paidLocalAmount: string;
paidLocalCurrency: string;
countryCode: string;
transFeeAmount: string;
ref1: string;
ref2: string;
ref3: string;
toMerchantId: string;
}
`
The SDK validates slips based on the following criteria:
1. Validity: The slip must be marked as valid by the API
2. Cache Status: The slip must not have been used before (not cached)
3. Age: The slip must not be older than 1 day
4. Account Number: Matches the expected account (if provided)
5. Bank Code: Matches the expected bank (if provided)
6. Amount: Matches the expected amount (if provided)
All methods return a Result type that contains either data or error:
`typescript
const result = await rdcw.inquiryPayload(payload);
if (result.error) {
// Handle error
console.error(result.error.type, result.error.message);
} else {
// Process data
console.log(result.data);
}
`
- INVALID_SLIP: The slip is invalidEXPIRED_SLIP
- : The slip is older than 1 dayQR_CODE_ERROR
- : Failed to read or parse QR codeAPI_ERROR
- : API request failedVALIDATION_ERROR
- : Validation checks failed
`bashInstall dependencies
npm install
$3
-
npm run build - Build the package
- npm run dev - Run the package in development mode
- npm run clean - Remove build artifacts
- npm run prepare` - Prepare the package for publishingISC