Skip to content

Commit

Permalink
feat: bot barcode support
Browse files Browse the repository at this point in the history
  • Loading branch information
maythiwat committed Dec 24, 2023
1 parent 195bb19 commit f598811
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 18 deletions.
52 changes: 37 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ No dependency & Cross-platform. You can use it anywhere (Node.js, Deno, Bun), ev
## Usage

### Parsing data and get value from tag

```ts
import { parse } from 'promptparse'

Expand All @@ -27,6 +28,7 @@ ppqr.getTagValue('00') // Returns '01'
```

### Build QR data and append CRC tag

```ts
import { encode, tag, withCrcTag } from 'promptparse'

Expand All @@ -42,19 +44,21 @@ withCrcTag(encode(data), '63') // Returns '000201010211...'
```

### Generate PromptPay Bill Payment QR

```ts
import { generate } from 'promptparse'

const payload = generate.billPayment({
billerId: '1xxxxxxxxxxxx',
amount: 300.00,
ref1: 'INV12345'
amount: 300.0,
ref1: 'INV12345',
})

// TODO: Create QR Code from payload
```

### Validate & extract data from Slip Verify QR

```ts
import { validate } from 'promptparse'

Expand All @@ -69,24 +73,41 @@ const { sendingBank, transRef } = data
// TODO: Inquiry transaction from Bank Open API
```

### Convert BOT Barcode to PromptPay QR Tag 30 (Bill Payment)

```ts
import { parseBarcode } from 'promptparse'

const botBarcode = parseBarcode('|310109999999901\r...')

if (!botBarcode) {
console.error('Invalid Payload')
}

const payload = botBarcode.toQrTag30()

// TODO: Create QR Code from payload
```

### Use on browser via CDN

```html
<script src="https://cdn.jsdelivr.net/npm/promptparse"></script>

<script>
(function() {
// Generate QR code payload (use function from "promptparse" global)
const payload = promptparse.generate.truemoney({
mobileNo: '08xxxxxxxx',
amount: 10.00,
message: 'Hello World!'
})
// Quick & dirty way to show QR Code image
document.write(
`<img src="https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=${payload}">`
)
})()
;(function () {
// Generate QR code payload (use function from "promptparse" global)
const payload = promptparse.generate.truemoney({
mobileNo: '08xxxxxxxx',
amount: 10.0,
message: 'Hello World!',
})
// Quick & dirty way to show QR Code image
document.write(
`<img src="https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=${payload}">`,
)
})()
</script>
```

Expand All @@ -95,6 +116,7 @@ const { sendingBank, transRef } = data
- [EMV QR Code](https://www.emvco.com/emv-technologies/qrcodes/)
- [Thai QR Payment Standard](https://www.bot.or.th/content/dam/bot/fipcs/documents/FPG/2562/ThaiPDF/25620084.pdf)
- [Slip Verify API Mini QR Data](https://developer.scb/assets/documents/documentation/qr-payment/extracting-data-from-mini-qr.pdf)
- [BOT Barcode Standard](https://www.bot.or.th/content/dam/bot/documents/th/our-roles/payment-systems/about-payment-systems/Std_Barcode.pdf)

## License

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "promptparse",
"version": "1.0.0",
"version": "1.1.0",
"description": "All-in-one JS library for PromptPay & EMVCo QR Codes",
"author": "Maythiwat Chomchuen <maythiwat.chom@gmail.com>",
"license": "MIT",
Expand Down
24 changes: 24 additions & 0 deletions src/generate/BOTBarcode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { BOTBarcode } from '@/lib/BOTBarcode'

interface Config {
/** Biller ID (Tax ID + Suffix) */
billerId: string

/** Reference No. 1 / Customer No. */
ref1: string

/** Reference No. 2 */
ref2?: string | null

/** Transaction amount */
amount?: number | null
}

/**
* Generate BOT Barcode
*
* @returns Barcode Payload
*/
export function botBarcode({ billerId, ref1, ref2, amount }: Config) {
return new BOTBarcode(billerId, ref1, ref2, amount)
}
1 change: 1 addition & 0 deletions src/generate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './promptpay/AnyID'
export * from './promptpay/BillPayment'
export * from './TrueMoney'
export * from './SlipVerify'
export * from './BOTBarcode'
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export { EMVCoQR } from '@/lib/EMVCoQR'
export { BOTBarcode } from '@/lib/BOTBarcode'

export * from '@/lib/tlv'
export * from '@/lib/parser'

Expand Down
63 changes: 63 additions & 0 deletions src/lib/BOTBarcode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { billPayment } from '@/generate/promptpay/BillPayment'

export class BOTBarcode {
public billerId: string
public ref1: string
public ref2: string | null
public amount: number | null

constructor(
billerId: string,
ref1: string,
ref2: string | null = null,
amount: number | null = null,
) {
this.billerId = billerId
this.ref1 = ref1
this.ref2 = ref2
this.amount = amount
}

static fromString(payload: string) {
if (!payload.startsWith('|')) {
return null
}

const data = payload.slice(1).split('\r', 4)
if (data.length != 4) {
return null
}

const [billerId, ref1, ref2, amount] = data

return new BOTBarcode(
billerId,
ref1,
ref2.length > 0 ? ref2 : null,
amount != '0' ? Number((parseInt(amount) / 100).toFixed(2)) : null,
)
}

toString() {
const { billerId, ref1, ref2, amount } = this
const amountStr = amount ? String(Number(amount.toFixed(2)) * 100) : '0'
return `|${billerId}\r${ref1}\r${ref2 ?? ''}\r${amountStr}`
}

/**
* Converts BOT Barcode to PromptPay QR Tag 30 (Bill Payment)
*
* This method works for some biller, depends on destination bank
*
* @returns QR Code payload
*/
toQrTag30() {
const { billerId, ref1, ref2, amount } = this
return billPayment({
billerId,
ref1,
ref2: ref2 ?? undefined,
amount: amount ?? undefined,
})
}
}
2 changes: 1 addition & 1 deletion src/lib/EMVCoQR.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type TLVTag, encode, get, withCrcTag } from '@/lib/tlv'

export default class EMVCoQR {
export class EMVCoQR {
private payload: string
private tags: TLVTag[]

Expand Down
13 changes: 12 additions & 1 deletion src/lib/parser.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import EMVCoQR from '@/lib/EMVCoQR'
import { BOTBarcode } from '@/lib/BOTBarcode'
import { EMVCoQR } from '@/lib/EMVCoQR'
import { checksum, decode } from '@/lib/tlv'

/**
Expand Down Expand Up @@ -42,3 +43,13 @@ export function parse(payload: string, strict = false, subTags = true) {

return new EMVCoQR(payload, tags)
}

/**
* Parse barcode data string (BOT Barcode Standard)
*
* @param payload - Barcode data string from the scanner
* @returns BOT Barcode Instance
*/
export function parseBarcode(payload: string) {
return BOTBarcode.fromString(payload)
}

0 comments on commit f598811

Please sign in to comment.