Định nghĩa interface theo ngôn ngữ nghiệp vụ của bạn, rồi viết một Adapter dịch từ interface đó sang SDK.
ts
// interface do domain của bạn định nghĩa, không copy tên của SDK
interface PaymentGateway {
createPayment(input: { orderId: string; amount: number }): Promise<{ payUrl: string }>
verifyWebhook(raw: string, signature: string): boolean
}
class SepayGateway implements PaymentGateway {
async createPayment(input) {
const res = await sepaySdk.transactions.create({ /* map field ở đây */ })
return { payUrl: res.checkout_url }
}
verifyWebhook(raw, signature) { /* ... */ }
}Code nghiệp vụ chỉ nhìn thấy PaymentGateway. Đổi cổng = viết adapter mới, phần còn lại không đổi. Test cũng dễ vì thay adapter bằng bản giả.
Điểm mấu chốt hay bị làm sai: đừng để interface của bạn là bản sao chữ ký của SDK. Nếu PaymentGateway cũng có charge_id, metadata giống hệt nhà cung cấp thì mô hình của họ đã rò vào domain của bạn, và lần đổi nhà cung cấp sau vẫn phải sửa khắp nơi. Interface phải phản ánh cái ứng dụng của bạn cần, adapter chịu trách nhiệm dịch — đây chính là ý tưởng anti-corruption layer ở quy mô lớn hơn.