Skip to content

Commit

Permalink
feat(payment): switch to midtrans
Browse files Browse the repository at this point in the history
  • Loading branch information
tfkhdyt committed Oct 4, 2023
1 parent c9916e9 commit 1a48297
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 47 deletions.
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"dotenv": "^16.3.1",
"drizzle-orm": "^0.28.6",
"fastify": "^4.23.2",
"midtrans-node-client": "^0.0.6",
"telegraf": "^4.14.0",
"xendit-node": "^3.2.0"
},
Expand Down
2 changes: 2 additions & 0 deletions src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export default {
databaseUrl: process.env.DATABASE_URL as string,
databaseAuthToken: process.env.DATABASE_AUTH_TOKEN as string,
xenditSecret: process.env.XENDIT_SECRET as string,
midtransServerKey: process.env.MIDTRANS_SERVER_KEY as string,
midtransClientKey: process.env.MIDTRANS_CLIENT_KEY as string,
message: {
start: `Selamat datang di bot *KBBI*
Expand Down
13 changes: 6 additions & 7 deletions src/handlers/callback.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,17 @@ export const callbackHandler = async (
) => {
try {
const { body } = req
if (body.status !== 'PAID') {
return reply.status(400).send('Status should be PAID')
if (body.transaction_status !== 'settlement') {
return reply.status(400).send('Status should be settlement')
}

const userId = Number(body.external_id.split('_')[1])
const amount = body.items[0].quantity
const paymentChannel = body.payment_channel
const [amount, userId] = body.order_id.split('_')
const paymentChannel = body.payment_type

await increaseCredits(userId, amount)
await increaseCredits(Number(userId), Number(amount))
await bot.telegram.sendMessage(
userId,
`Topup sejumlah ${amount} saldo melalui ${paymentChannel} telah berhasil! Terima kasih telah menggunakan layanan kami`,
`Topup sejumlah ${amount} saldo melalui "${paymentChannel.toUpperCase()}" telah berhasil! Terima kasih telah menggunakan layanan kami`,
)

reply.status(200).send('Transaction success!')
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/invoice.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const invoiceHandler = async (
const price = calculatePrice(nominal).gross
const formattedPrice = formatCurrency(price)
const keyboard = Markup.inlineKeyboard([
Markup.button.webApp(`💵 Xendit Payment (${formattedPrice})`, invoiceUrl),
Markup.button.url(`💵 Midtrans Payment (${formattedPrice})`, invoiceUrl),
])

await ctx.reply(
Expand Down
9 changes: 9 additions & 0 deletions src/lib/midtrans.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { MidtransClient } from 'midtrans-node-client'

import config from '../config/config.js'

export const snap = new MidtransClient.Snap({
isProduction: config.nodeEnv === 'production',
serverKey: config.midtransServerKey,
clientKey: config.midtransClientKey,
})
78 changes: 48 additions & 30 deletions src/services/payment.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import crypto from 'crypto'
import { CreateInvoiceRequest, Invoice } from 'xendit-node/invoice/models'

import { User } from '../db/sqlite/schemas/user.schema.js'
import { xenditClient } from '../lib/xendit.js'
import { snap } from '../lib/midtrans.js'

export const calculatePrice = (amount: number) => {
const net = amount * 1000
Expand All @@ -13,36 +10,57 @@ export const calculatePrice = (amount: number) => {
}

export const createInvoice = async (amount: number, user: User) => {
const price = calculatePrice(amount)

const invoice: CreateInvoiceRequest = {
externalId: `TOPUP_${user.id}_${crypto.randomUUID()}`,
amount: price.gross,
currency: 'IDR',
customer: {
givenNames: user.firstName,
surname: user.lastName,
},
items: [
{
name: 'Saldo KBBI Bot',
quantity: amount,
price: 1000,
try {
const price = calculatePrice(amount)

// const authToken = Buffer.from(config.midtransServerKey + ':').toString(
// 'base64',
// )

const invoice = {
transaction_details: {
order_id: `${amount}_${user.id}_${crypto.randomUUID()}`,
gross_amount: price.gross,
},
],
fees: [
{
type: 'Biaya Admin',
value: price.adminFee,
item_details: [
{
name: 'Saldo KBBI Bot',
quantity: amount,
price: 1000,
},
{
name: 'Biaya Admin',
quantity: 1,
price: price.adminFee,
},
],
customer_details: {
first_name: user.firstName,
last_name: user.lastName,
},
],
}
}

const response: Invoice = await xenditClient.createInvoice({
data: invoice,
})
const response = await snap.createTransaction(invoice)
// const response = await fetch(
// 'https://app.sandbox.midtrans.com/snap/v1/transactions',
// {
// headers: {
// Accept: 'application/json',
// Authorization: `Basic ${authToken}`,
// 'Content-Type': 'application/json',
// },
// method: 'POST',
// body: JSON.stringify(invoice),
// },
// )
// const data = await response.json()
// console.log({ data })

return response.invoiceUrl
return response.redirect_url as string
} catch (error) {
console.error(error)
throw error
}
}

const formatter = new Intl.NumberFormat('id-ID', {
Expand Down
12 changes: 3 additions & 9 deletions src/types/paymentBody.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
export type PaymentBody = {
status: string
id: string
external_id: string
items: [
{
quantity: number
},
]
payment_channel: string
transaction_status: string
order_id: string
payment_type: string
}

0 comments on commit 1a48297

Please sign in to comment.