98 lines
3.0 KiB
TypeScript
98 lines
3.0 KiB
TypeScript
import crypto from 'crypto'
|
|
|
|
const BASE_URL = process.env.AMANPAY_BASE_URL ?? 'https://api.amanpay.net'
|
|
const MERCHANT_ID = process.env.AMANPAY_MERCHANT_ID ?? ''
|
|
const SECRET_KEY = process.env.AMANPAY_SECRET_KEY ?? ''
|
|
const WEBHOOK_SECRET = process.env.AMANPAY_WEBHOOK_SECRET ?? ''
|
|
|
|
export interface AmanPayCreateParams {
|
|
amount: number
|
|
currency: string
|
|
orderId: string
|
|
description: string
|
|
customerEmail?: string
|
|
customerName?: string
|
|
successUrl: string
|
|
failureUrl: string
|
|
webhookUrl: string
|
|
}
|
|
|
|
export interface AmanPayCheckoutResult {
|
|
transactionId: string
|
|
checkoutUrl: string
|
|
status: string
|
|
}
|
|
|
|
async function getAuthHeaders() {
|
|
return {
|
|
'Content-Type': 'application/json',
|
|
'x-merchant-id': MERCHANT_ID,
|
|
'x-api-key': SECRET_KEY,
|
|
}
|
|
}
|
|
|
|
export async function createCheckout(params: AmanPayCreateParams): Promise<AmanPayCheckoutResult> {
|
|
const res = await fetch(`${BASE_URL}/v1/payments`, {
|
|
method: 'POST',
|
|
headers: await getAuthHeaders(),
|
|
body: JSON.stringify({
|
|
merchant_id: MERCHANT_ID,
|
|
amount: params.amount,
|
|
currency: params.currency,
|
|
order_id: params.orderId,
|
|
description: params.description,
|
|
customer_email: params.customerEmail,
|
|
customer_name: params.customerName,
|
|
success_url: params.successUrl,
|
|
failure_url: params.failureUrl,
|
|
webhook_url: params.webhookUrl,
|
|
}),
|
|
})
|
|
|
|
if (!res.ok) {
|
|
const err = await res.json().catch(() => ({})) as Record<string, unknown>
|
|
throw new Error(`AmanPay checkout failed: ${(err?.message as string) ?? res.statusText}`)
|
|
}
|
|
|
|
const json = await res.json() as Record<string, unknown>
|
|
return {
|
|
transactionId: (json.transaction_id ?? json.id) as string,
|
|
checkoutUrl: (json.checkout_url ?? json.payment_url) as string,
|
|
status: (json.status ?? 'PENDING') as string,
|
|
}
|
|
}
|
|
|
|
export async function getTransaction(transactionId: string) {
|
|
const res = await fetch(`${BASE_URL}/v1/payments/${transactionId}`, {
|
|
headers: await getAuthHeaders(),
|
|
})
|
|
if (!res.ok) throw new Error('AmanPay: failed to fetch transaction')
|
|
return res.json()
|
|
}
|
|
|
|
export async function refundTransaction(transactionId: string, amount: number, reason?: string) {
|
|
const res = await fetch(`${BASE_URL}/v1/payments/${transactionId}/refund`, {
|
|
method: 'POST',
|
|
headers: await getAuthHeaders(),
|
|
body: JSON.stringify({ amount, reason }),
|
|
})
|
|
if (!res.ok) {
|
|
const err = await res.json().catch(() => ({})) as Record<string, unknown>
|
|
throw new Error(`AmanPay refund failed: ${(err?.message as string) ?? res.statusText}`)
|
|
}
|
|
return res.json()
|
|
}
|
|
|
|
export function verifyWebhookSignature(rawBody: string, signature: string): boolean {
|
|
if (!WEBHOOK_SECRET) return false
|
|
const expected = crypto
|
|
.createHmac('sha256', WEBHOOK_SECRET)
|
|
.update(rawBody)
|
|
.digest('hex')
|
|
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
|
|
}
|
|
|
|
export function isConfigured(): boolean {
|
|
return !!(MERCHANT_ID && SECRET_KEY && MERCHANT_ID !== 'your-amanpay-merchant-id')
|
|
}
|