ไลบรารี่ Node.js (omise-node)
ไลบรารี่ omise-node มอบอินเทอร์เฟส Node.js สมัยใหม่สำหรับ Omise API พร้อมนิยาม TypeScript, การสนับสนุน Promise/async-await และการรวม Express และ NestJS ที่ยอดเยี่ยม
การติดตั้ง
การใช้ npm
npm install omise
การใช้ Yarn
yarn add omise
การใช้ pnpm
pnpm add omise
ข้อกำหนด
- Node.js 12 หรือสูงกว่า (แนะนำ Node.js 16+ เนื่องจาก Node.js 12 ถึง EOL ในเดือนเมษายน 2022)
- npm, yarn หรือ pnpm สำหรับการจัดการแพ็คเจจ
- TypeScript 4.0+ (เลือกได้, สำหรับโครงการ TypeScript)
เริ่มต้นอย่างรวดเร็ว
การกำหนดค่าพื้นฐาน
const omise = require('omise')({
secretKey: 'skey_test_123456789',
publicKey: 'pkey_test_123456789',
omiseVersion: '2019-05-29'
});
การกำหนดค่า TypeScript
ไลบรารี่ omise-node รวมถึง นิยาม TypeScript ที่สร้างไว้ - ไม่ต้องใช้แพ็คเจจ @types/omise แยกต่างหาก
import Omise from 'omise';
const omise = Omise({
secretKey: process.env.OMISE_SECRET_KEY!,
publicKey: process.env.OMISE_PUBLIC_KEY!,
omiseVersion: '2019-05-29'
});
// การเรียก API ที่ปลอดภัยจากประเภท
import type { Charges, Tokens } from 'omise';
// Charges มีการอนุมานประเภทแบบเต็ม
const charge: Charges.ICharge = await omise.charges.create({
amount: 100000,
currency: 'thb',
card: 'tokn_test_123'
});
// การตอบสนองของ Token มีการพิมพ์แบบเต็ม
const token: Tokens.IToken = await omise.tokens.create({
card: {
number: '4242424242424242',
expiration_month: 12,
expiration_year: 2027,
security_code: '123',
name: 'JOHN DOE'
}
});
คุณสมบัติ TypeScript:
- ✅ นิยามประเภทที่สร้างไว้ (ไม่ต้องใช้แพ็คเจจ @types)
- ✅ การสนับสนุน IntelliSense แบบเต็มในรหัส VS
- ✅ วัตถุคำขอ/การตอบสนองที่ปลอดภัยจากประเภท
- ✅ ประเภทการแจงนับสำหรับวิธีการชำระเงิน, สกุลเงิน, สถานะ
- ✅ การสนับสนุนการตรวจสอบ null ที่เข้มงวด
- ✅ พารามิเตอร์ประเภททั่วไปสำหรับการใช้งานขั้นสูง
ตำแหน่งนิยามประเภท: นิยาม TypeScript ที่เป็นทางการได้รับการบำรุงรักษาในที่เก็บข้อมูล omise-node
การกำหนดค่า Express
// config/omise.js
require('dotenv').config();
module.exports = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY,
publicKey: process.env.OMISE_PUBLIC_KEY,
omiseVersion: '2019-05-29'
});
ตัวแปรสภาพแวดล้อม
สร้างไฟล์ .env:
# การพัฒนา/การทดสอบ
OMISE_SECRET_KEY=skey_test_123456789
OMISE_PUBLIC_KEY=pkey_test_123456789
# การผลิต
# OMISE_SECRET_KEY=skey_live_123456789
# OMISE_PUBLIC_KEY=pkey_live_123456789
การดำเนินการทั่วไป
การสร้างค่าธรรมเนียม
ด้วย Promise
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});
omise.charges.create({
amount: 100000, // 1,000.00 บาท
currency: 'THB',
card: 'tokn_test_123',
description: 'Order #1234',
metadata: {
order_id: '1234',
customer_name: 'John Doe'
}
})
.then(charge => {
if (charge.paid) {
console.log(`การชำระเงินสำเร็จ: ${charge.id}`);
} else {
console.log(`ก ารชำระเงินล้มเหลว: ${charge.failure_message}`);
}
})
.catch(err => {
console.error('ข้อผิดพลาด:', err.message);
});
ด้วย Async/Await
async function createCharge(token, amount) {
try {
const charge = await omise.charges.create({
amount,
currency: 'THB',
card: token,
description: 'Order #1234',
metadata: {
order_id: '1234',
customer_name: 'John Doe'
}
});
if (charge.paid) {
console.log(`การชำระเงินสำเร็จ: ${charge.id}`);
return charge;
} else {
throw new Error(charge.failure_message);
}
} catch (error) {
console.error('การชำระเงินล้มเหลว:', error);
throw error;
}
}
ด้วย TypeScript
interface ChargeMetadata {
order_id: string;
customer_name: string;
}
interface CreateChargeParams {
amount: number;
currency: string;
card: string;
metadata: ChargeMetadata;
}
async function createCharge(params: CreateChargeParams): Promise<Omise.Charges.ICharge> {
const charge = await omise.charges.create({
amount: params.amount,
currency: params.currency,
card: params.card,
metadata: params.metadata
});
return charge;
}
ด้วย 3D Secure
async function createSecureCharge(token, amount, returnUri) {
const charge = await omise.charges.create({
amount,
currency: 'THB',
card: token,
return_uri: returnUri
});
if (charge.authorized) {
if (charge.authorize_uri) {
// เปลี่ยนเส้นทางลูกค้าไปยัง authorize_uri สำหรับ 3D Secure
return { redirect: charge.authorize_uri };
} else {
// การชำระเงินเสร็จสมบูรณ์โดยไม่ต้องใช้ 3D Secure
return { success: true, charge };
}
}
throw new Error(charge.failure_message);
}
การดึงค่าธรรมเนียม
// ตามแบบ Promise
omise.charges.retrieve('chrg_test_123')
.then(charge => {
console.log(`จำนวนเงิน: ${charge.amount}`);
console.log(`สกุลเงิน: ${charge.currency}`);
console.log(`สถานะ: ${charge.status}`);
});
// Async/await
async function getCharge(chargeId) {
const charge = await omise.charges.retrieve(chargeId);
return charge;
}
การแสดงรายชื่อค่าธรรมเนียม
async function listCharges(options = {}) {
const charges = await omise.charges.list({
limit: 20,
offset: 0,
order: 'reverse_chronological',
...options
});
charges.data.forEach(charge => {
console.log(`${charge.id}: ${charge.amount} ${charge.currency}`);
});
return charges;
}
// แสดงรายการค่าธรรมเนียมพร้อมตัวกรองวันที่
const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
const charges = await omise.charges.list({
from: weekAgo.toISOString().split('T')[0],
to: new Date().toISOString().split('T')[0]
});
การสร้างลูกค้า
async function createCustomer(email, description, metadata = {}) {
const customer = await omise.customers.create({
email,
description,
metadata
});
console.log(`Customer created: ${customer.id}`);
return customer;
}
// ตัวอย่างการใช้งาน
const customer = await createCustomer(
'customer@example.com',
'John Doe',
{ user_id: '12345', account_type: 'premium' }
);
การบันทึกบัตรเข้าไปในลูกค้า
// อัพเดตลูกค้าด้วยโทเคนบัต ร
async function addCardToCustomer(customerId, token) {
const customer = await omise.customers.update(customerId, {
card: token
});
console.log(`Card saved: ${customer.default_card}`);
return customer;
}
// สร้างลูกค้าด้วยบัตร
async function createCustomerWithCard(email, token) {
const customer = await omise.customers.create({
email,
card: token
});
return customer;
}
การแสดงรายชื่อบัตรลูกค้า
async function listCustomerCards(customerId) {
const customer = await omise.customers.retrieve(customerId);
customer.cards.data.forEach(card => {
console.log(`${card.brand} ending in ${card.last_digits}`);
console.log(`Expires: ${card.expiration_month}/${card.expiration_year}`);
});
return customer.cards.data;
}
การสร้างการคืนเงิน
// คืนเงินเต็มจำนวน
async function refundCharge(chargeId) {
const refund = await omise.charges.refund(chargeId);
return refund;
}
// คืนเงินบางส่วน
async function partialRefund(chargeId, amount, metadata = {}) {
const refund = await omise.charges.refund(chargeId, {
amount,
metadata
});
console.log(`Refund ${refund.id}: ${refund.amount} ${refund.currency}`);
return refund;
}
// ตัวอย่างการใช้งาน
await partialRefund('chrg_test_123', 25000, {
reason: 'customer_request',
ticket_id: 'TICKET-123'
});
การสร้างการโอน
async function createTransfer(amount, recipientId, metadata = {}) {
const transfer = await omise.transfers.create({
amount,
recipient: recipientId,
metadata
});
console.log(`Transfer ${transfer.id}: ${transfer.amount}`);
return transfer;
}
วิธีการชำระเงินแบบอื่น
การสร้างแหล่งที่มา
// QR PromptPay
async function createPromptPaySource(amount) {
const source = await omise.sources.create({
type: 'promptpay',
amount,
currency: 'THB'
});
console.log(`URL รหัส QR: ${source.scannable_code.image.download_uri}`);
// สร้างค่าธรรมเนียมด้วยแหล่งที่มา
const charge = await omise.charges.create({
amount,
currency: 'THB',
source: source.id,
return_uri: 'https://example.com/payment/callback'
});
return { source, charge };
}
ธนาคารอินเทอร์เน็ต
async function createInternetBankingCharge(amount, bankCode = 'scb') {
const source = await omise.sources.create({
type: `internet_banking_${bankCode}`,
amount,
currency: 'THB'
});
const charge = await omise.charges.create({
amount,
currency: 'THB',
source: source.id,
return_uri: 'https://example.com/payment/callback'
});
// คืนค่า authorize_uri เพื่อเปลี่ยนเส้นทาง
return charge.authorize_uri;
}
การผ่อนชำระ
async function createInstallmentCharge(amount, bank, term) {
const source = await omise.sources.create({
type: `installment_${bank}`,
amount,
currency: 'THB',
installment_term: term
});
const charge = await omise.charges.create({
amount,
currency: 'THB',
source: source.id,
return_uri: 'https://example.com/payment/callback'
});
return charge;
}
// ตัวอย่างการใช้งาน
const charge = await createInstallmentCharge(100000, 'kbank', 6);
การจัดการข้อผิดพลาด
const { OmiseError } = require('omise');
async function createChargeWithErrorHandling(params) {
try {
const charge = await omise.charges.create(params);
return charge;
} catch (error) {
if (error instanceof OmiseError) {
console.error('Omise Error:', error.message);
console.error('Status Code:', error.statusCode);
console.error('Error Code:', error.code);
// จัดการข้อผิดพลาดเฉพาะ
switch (error.code) {
case 'authentication_failure':
throw new Error('คีย์ API ไม่ถูกต้อง');
case 'invalid_card':
throw new Error('บัตรถูกปฏิเสธ');
case 'insufficient_fund':
throw new Error('เงินในบัตรไม่เพียงพอ');
default:
throw error;
}
}
// ข้อผิดพลาดเครือข่ายหรือข้อผิดพลาดอื่นๆ
throw error;
}
}
TypeScript การจัดการข้อผิดพลาด
import Omise, { OmiseError } from 'omise';
async function handleChargeError(error: unknown): Promise<never> {
if (error instanceof OmiseError) {
const errorMessages: Record<string, string> = {
insufficient_fund: 'เงินในบัตรไม่เพียงพอ',
stolen_or_lost_card: 'บัตรถูกรายงานว่าถูกขโมยหรือสูญหาย',
invalid_security_code: 'รหัส CVV ไม่ถูกต้อง',
payment_cancelled: 'การชำระเงินถูกยกเลิก'
};
const message = errorMessages[error.code] || error.message;
throw new Error(message);
}
throw error;
}
การรวม Express
ตัวอย่างตัวควบคุม
// controllers/paymentController.js
const omise = require('../config/omise');
const Order = require('../models/Order');
const Payment = require('../models/Payment');
exports.createPayment = async (req, res) => {
try {
const { orderId } = req.params;
const { omiseToken } = req.body;
const order = await Order.findById(orderId);
if (!order) {
return res.status(404).json({ error: 'Order not found' });
}
const charge = await omise.charges.create({
amount: Math.round(order.total * 100),
currency: 'THB',
card: omiseToken,
description: `Order #${order.id}`,
metadata: {
order_id: order.id,
customer_email: order.email
},
return_uri: `${req.protocol}://${req.get('host')}/payment/callback`
});
// บันทึกข้อมูลการชำระเงิน
const payment = await Payment.create({
orderId: order.id,
chargeId: charge.id,
amount: order.total,
status: charge.status,
paid: charge.paid
});
if (charge.paid) {
order.paymentStatus = 'paid';
await order.save();
return res.json({ success: true, charge });
} else if (charge.authorize_uri) {
return res.json({ redirect: charge.authorize_uri });
} else {
return res.status(400).json({ error: charge.failure_message });
}
} catch (error) {
console.error('Payment error:', error);
res.status(500).json({ error: 'Payment failed' });
}
};
exports.paymentCallback = async (req, res) => {
try {
const { id: chargeId } = req.query;
const charge = await omise.charges.retrieve(chargeId);
const payment = await Payment.findOne({ chargeId: charge.id });
if (!payment) {
return res.status(404).send('Payment not found');
}
payment.status = charge.status;
payment.paid = charge.paid;
await payment.save();
if (charge.paid) {
const order = await Order.findById(payment.orderId);
order.paymentStatus = 'paid';
await order.save();
res.redirect(`/orders/${order.id}?success=true`);
} else {
res.redirect(`/payment/${payment.orderId}?error=${charge.failure_message}`);
}
} catch (error) {
console.error('Callback error:', error);
res.status(500).send('Payment verification failed');
}
};
เส้นทาง
// routes/payment.js
const express = require('express');
const router = express.Router();
const paymentController = require('../controllers/paymentController');
router.post('/payment/:orderId', paymentController.createPayment);
router.get('/payment/callback', paymentController.paymentCallback);
module.exports = router;
มิดเดิลแวร์สำหรับการจัดการข้อผิดพลาด
// middleware/errorHandler.js
const { OmiseError } = require('omise');
function errorHandler(err, req, res, next) {
if (err instanceof OmiseError) {
console.error('Omise Error:', {
message: err.message,
code: err.code,
statusCode: err.statusCode
});
return res.status(err.statusCode || 500).json({
error: err.message,
code: err.code
});
}
console.error('Unexpected error:', err);
res.status(500).json({ error: 'Internal server error' });
}
module.exports = errorHandler;
การรวม NestJS
การตั้งค่าโมดูล
// omise/omise.module.ts
import { Module, Global } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { OmiseService } from './omise.service';
@Global()
@Module({
imports: [ConfigModule],
providers: [OmiseService],
exports: [OmiseService],
})
export class OmiseModule {}
บริการ
// omise/omise.service.ts
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import Omise from 'omise';
@Injectable()
export class OmiseService {
private omise: ReturnType<typeof Omise>;
constructor(private configService: ConfigService) {
this.omise = Omise({
secretKey: this.configService.get<string>('OMISE_SECRET_KEY')!,
publicKey: this.configService.get<string>('OMISE_PUBLIC_KEY')!,
omiseVersion: '2019-05-29'
});
}
async createCharge(params: Omise.Charges.CreatePayload): Promise<Omise.Charges.ICharge> {
return this.omise.charges.create(params);
}
async retrieveCharge(chargeId: string): Promise<Omise.Charges.ICharge> {
return this.omise.charges.retrieve(chargeId);
}
async createCustomer(params: Omise.Customers.CreatePayload): Promise<Omise.Customers.ICustomer> {
return this.omise.customers.create(params);
}
async refundCharge(chargeId: string, amount?: number): Promise<Omise.Refunds.IRefund> {
return this.omise.charges.refund(chargeId, amount ? { amount } : undefined);
}
}
ตัวควบคุม
// payment/payment.controller.ts
import { Controller, Post, Get, Body, Param, Query, HttpException, HttpStatus } from '@nestjs/common';
import { OmiseService } from '../omise/omise.service';
import { PaymentService } from './payment.service';
@Controller('payment')
export class PaymentController {
constructor(
private omiseService: OmiseService,
private paymentService: PaymentService
) {}
@Post(':orderId')
async createPayment(
@Param('orderId') orderId: string,
@Body('omiseToken') omiseToken: string
) {
try {
const order = await this.paymentService.findOrder(orderId);
const charge = await this.omiseService.createCharge({
amount: Math.round(order.total * 100),
currency: 'THB',
card: omiseToken,
description: `Order #${order.id}`,
metadata: {
order_id: order.id,
customer_email: order.email
},
return_uri: `${process.env.APP_URL}/payment/callback`
});
await this.paymentService.savePayment({
orderId: order.id,
chargeId: charge.id,
amount: order.total,
status: charge.status,
paid: charge.paid
});
if (charge.paid) {
await this.paymentService.markOrderPaid(order.id);
return { success: true, charge };
} else if (charge.authorize_uri) {
return { redirect: charge.authorize_uri };
} else {
throw new HttpException(charge.failure_message, HttpStatus.BAD_REQUEST);
}
} catch (error) {
throw new HttpException('การชำระเงินล้มเหลว', HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@Get('callback')
async paymentCallback(@Query('id') chargeId: string) {
const charge = await this.omiseService.retrieveCharge(chargeId);
await this.paymentService.updatePaymentStatus(charge.id, charge.status, charge.paid);
if (charge.paid) {
return { success: true, message: 'การชำระเงินสำเร็จ' };
} else {
throw new HttpException(charge.failure_message, HttpStatus.BAD_REQUEST);
}
}
}