اطمینان از سیستم های پرداخت قابل اعتماد با idempotency

پرداخت آنلاین باید یکپارچه باشد. اما وقتی چیزی پیش می رود-آیا این یک اتصال آهسته است یا دو بار کلیک کنید-آخرین چیزی که ما می خواهیم این است که مشتریان دو بار شارژ شوند. این جایی است که IdemPotency وارد می شود. این در مورد اطمینان از این است که اقدامات مکرر (مانند درخواست های پرداخت) باعث ایجاد عوارض جانبی ناخواسته مانند هزینه های متعدد برای همین موارد نمی شود.
بیایید با نحوه کار IdemPotency و چرا برای ایجاد یک تجربه پرداخت صاف و قابل اعتماد بسیار مهم است.
idempotency چیست؟
به زبان ساده ، IdemPotency به این معنی است که اگر یک عمل تکرار شود ، همیشه باید نتیجه مشابهی را بدست آورد. به عنوان مثال ، اگر مشتری سعی می کند دو بار (یا به طور تصادفی یا به دلیل سکسکه شبکه) هزینه ای را بپردازد ، فقط باید یک بار شارژ شود.
در مورد آن فکر کنید مانند این: شما به صورت آنلاین قهوه سفارش می دهید ، و درخواست پرداخت ارسال می شود ، اما پس از آن صفحه یخ می زند. شما دوباره سعی می کنید ، اما شما نمی خواهید با دو فنجان قهوه و یک بار مضاعف به پایان برسید ، درست است؟ idempotency تضمین می کند که اتفاق نمی افتد.
چرا idempotency اینقدر مهم است؟
سیستم های پرداخت قابل اعتماد با مشتریان اعتماد ایجاد می کنند. اگر مشتریان نگران این باشند که پرداخت آنها به دلیل خطاها قابل کپی یا از بین رفتن باشد ، کمتر احتمال دارد که دوباره از این سرویس استفاده کنند.
در اینجا چرا IdemPotency در سیستم های پرداخت ضروری است:
- از هزینه های تکراری جلوگیری می کند: گاهی اوقات ، به دلیل خرابی شبکه یا زمان بندی ، ممکن است درخواست پرداخت چندین بار پردازش شود. IdemPotency تضمین می کند که حتی اگر درخواست مجدداً انجام شود ، فقط یک پرداخت پردازش می شود.
- اعتماد به نفس مشتری را افزایش می دهد: وقتی مشتریان می دانند که دو بار به همان ترتیب شارژ نمی شوند ، به احتمال زیاد به سیستم ما اعتماد می کنند و از آن استفاده می کنند.
- از تجارت محافظت می کند: اگر ما به طور تصادفی مشتری را دو بار شارژ کنیم ، می تواند منجر به درخواست بازپرداخت ، شکایات یا حتی مسائل حقوقی شود. idempotency به ما کمک می کند تا از این امر جلوگیری کنیم.
idempotency چگونه کار می کند؟
اکنون که می دانیم چرا Idempotency مهم است ، بیایید نگاهی بیندازیم که چگونه در یک سیستم پرداخت کار می کند. این فرآیند حول یک کلید منحصر به فرد idempotency می چرخد ، که به سیستم کمک می کند تا درخواست های تکراری را تشخیص دهد.
در اینجا روند اساسی وجود دارد:
- کاربر درخواست پرداخت می کند و یک کلید منحصر به فرد Idempotency را ارائه می دهد.
- سیستم در صورت مشاهده این کلید قبلاً بررسی می کند:
- اگر کلید وجود داشته باشد ، سیستم به سادگی نتیجه قبلی پردازش شده را برمی گرداند (بدون بار کپی).
- اگر کلید وجود نداشته باشد ، سیستم پرداخت را پردازش می کند و نتیجه را به همراه کلید ذخیره می کند.
- پرداخت پردازش و ذخیره می شود و سیستم تضمین می کند که اگر کاربر درخواست را احیا کند ، پاسخ مشابهی ارسال می شود.
در اینجا یک نمودار جریان وجود دارد که این روند را تجسم می کند:
نمودار نمودار برای مدیریت تماس های idempotency
توضیح در مورد نمودار:
- درخواست مشتری: مشتری با ارسال یک کلید IDEMPotency ، درخواست پرداخت را آغاز می کند.
- کلید IDEMPotency را بررسی کنید: سرور بررسی می کند که آیا درخواست قبلاً پردازش شده است یا خیر.
- در صورت وجود کلید: سرور پاسخ ذخیره شده را برمی گرداند.
- اگر کلید وجود ندارد: سرور پرداخت را پردازش می کند.
- موفقیت پرداخت: بر اساس نتیجه پرداخت ، وضعیت به عنوان “موفقیت” یا “شکست خورده” ذخیره می شود.
- پاسخ پرداخت بازگشت: سرور تضمین می کند که همان پاسخ در مورد احیای مجدد بازگردانده می شود.
نحوه اجرای idempotency در یک سیستم پرداخت
حال ، بیایید به این موضوع بپردازیم که چگونه می توانیم IdemPotency را در سیستم پرداخت خودمان پیاده سازی کنیم. آنقدر پیچیده نیست که به نظر برسد ، و واقعاً می تواند قابلیت اطمینان سیستم ما را بهبود بخشد.
مرحله 1: یک کلید منحصر به فرد idempotency ایجاد کنید
هنگامی که کاربر یک پرداخت را آغاز می کند ، یک کلید منحصر به فرد idempotency را برای آن معامله ایجاد کنید. این کلید به عنوان شناسه برای ردیابی معامله ، اطمینان حاصل می شود که هرگونه درخواست کپی قابل تشخیص است.
مرحله 2: کلید IdemPotency را بررسی کنید
قبل از پردازش پرداخت ، سیستم باید بررسی کند که آیا از کلید IDEMPotency قبلاً استفاده شده است یا خیر. در صورت وجود ، پاسخ قبلاً ذخیره شده را برگردانید. اگر اینطور نیست ، با پرداخت ادامه دهید.
مرحله 3: نتیجه پرداخت را ذخیره کنید
پس از پردازش پرداخت ، نتیجه را در یک پایگاه داده و ذخیره آن ذخیره کنید. به این ترتیب ، اگر درخواست پرداخت دوباره وارد شود (به دلیل آزمایش مجدد) ، سیستم کلید را تشخیص می دهد و از پردازش دوباره پرداخت خودداری می کند.
در اینجا چگونه می توانیم این را به صورت کد پیاده سازی کنیم.
کد برای اجرای idempotency
بیایید با استفاده از جاوا ، یک زبان پس زمینه مشترک ، به یک مثال عملی نگاه کنیم. ما یک سرویس پرداخت ساده را که از یک کلید idempotency برای جلوگیری از پرداخت های تکراری استفاده می کند ، شبیه سازی می کنیم.
1. طرحواره پایگاه داده برای پرداخت
برای ذخیره سوابق پرداخت به یک جدول نیاز داریم. این جدول شامل موارد است idempotency_key
، مبلغ پرداخت ، ارز و وضعیت پرداخت (چه موفقیت آمیز باشد یا شکست خورده باشد).
CREATE TABLE payments (
id SERIAL PRIMARY KEY,
idempotency_key VARCHAR(255) UNIQUE NOT NULL,
amount DECIMAL(10,2),
currency VARCHAR(3),
status VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
2. سرویس پرداخت با بررسی idempotency
در اینجا نحوه اجرای منطق در جاوا برای بررسی و رسیدگی به idempotice آورده شده است.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
@Service
public class PaymentService {
@Autowired
private PaymentRepository paymentRepository; // Database repository for payment records
@Autowired
private CacheService cacheService; // Cache service (could be Redis or in-memory cache)
@Transactional
public Payment processPayment(String idempotencyKey, BigDecimal amount, String currency) throws PaymentException {
// Check if the request has already been processed by looking into cache first
Payment cachedPayment = cacheService.get(idempotencyKey); // Check cache for processed payment
if (cachedPayment != null) {
// If cached payment exists, return it (cached response)
return cachedPayment;
}
// If no cached response, check the database (fallback)
Payment existingPayment = paymentRepository.findByIdempotencyKey(idempotencyKey);
if (existingPayment != null) {
// Save to cache for faster future access
cacheService.put(idempotencyKey, existingPayment);
return existingPayment;
}
// Process the payment as it is a new request
Payment newPayment = new Payment(idempotencyKey, amount, currency, "PROCESSING");
paymentRepository.save(newPayment);
// Simulate payment processing (normally we'd call a payment gateway here)
boolean paymentSuccessful = simulatePaymentProcessing(amount);
if (paymentSuccessful) {
newPayment.setStatus("SUCCESS");
} else {
newPayment.setStatus("FAILED");
}
// Save payment status to database and cache
paymentRepository.save(newPayment);
cacheService.put(idempotencyKey, newPayment); // Cache the result for future requests
return newPayment;
}
private boolean simulatePaymentProcessing(BigDecimal amount) {
return amount.compareTo(BigDecimal.ZERO) > 0;
}
}
-
کلاس پرداخت:
- این سرویس درخواست های پرداخت را انجام می دهد و بررسی می کند که آیا کلید IDEMPotency قبلاً با نگاه کردن در حافظه نهان استفاده شده است. در صورت یافتن کلید ، سیستم پاسخ پرداخت ذخیره شده را برمی گرداند. اگر کلید پیدا نشود ، با پردازش پرداخت ادامه می یابد و نتیجه را هم در پایگاه داده و هم در حافظه نهان ذخیره می کند.
- در
processPayment
روش ابتدا حافظه نهان را برای کلید IDEMPotency ، سپس پایگاه داده بررسی می کند. اگر هیچ یک از پرداخت ها را شامل نمی شود ، پرداخت را پردازش می کند و نتیجه را ذخیره می کند.
-
کلاس Cacheservice:
- در
CacheService
یک حافظه پنهان در حافظه را با استفاده از a مدیریت می کندConcurrentHashMap
بشر این یک روش ساده برای ذخیره پرداخت های پردازش شده به طور موقت ، سرعت بخشیدن به درخواست های آینده با همان کلید IDEMPotency است. در سیستم های تولید ، ما به احتمال زیاد از حافظه نهان توزیع شده مانند Redis استفاده می کنیم.
- در
-
نهاد پرداخت:
- در
Payment
کلاس یک رکورد پرداخت با زمینه های کلید IDEMPotency ، مبلغ ، ارز ، وضعیت پرداخت و زمان بندی ایجاد را نشان می دهد. این مدل برای ذخیره جزئیات پرداخت در پایگاه داده استفاده می شود.
- در
3. اجرای سرویس حافظه پنهان
در این مثال ، ما از یک حافظه نهان در حافظه استفاده می کنیم.
import org.springframework.stereotype.Service;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class CacheService {
private final ConcurrentHashMap<String, Payment> cache = new ConcurrentHashMap<>();
public Payment get(String key) {
return cache.get(key); // Fetch from cache
}
public void put(String key, Payment payment) {
cache.put(key, payment); // Store in cache
}
public void remove(String key) {
cache.remove(key); // Remove from cache
}
}
4. نهاد پرداخت (با کلید idempotency)
این نهاد پرداختی است که نشان دهنده سوابق پرداخت است.
import javax.persistence.Entity;
import javax.persistence.Id;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Entity
public class Payment {
@Id
private String idempotencyKey; // Unique key for each payment request
private BigDecimal amount;
private String currency;
private String status; // SUCCESS / FAILED / PROCESSING
private LocalDateTime createdAt;
public Payment(String idempotencyKey, BigDecimal amount, String currency, String status) {
this.idempotencyKey = idempot
encyKey;
this.amount = amount;
this.currency = currency;
this.status = status;
this.createdAt = LocalDateTime.now();
}
// Getters and setters
}
افکار نهایی
IdemPotency یک جزئیات کوچک اما اساسی در سیستم های پرداخت است که تجربه ای نرم و بدون خطا را برای مشتریان ما تضمین می کند. با اجرای یک کلید IDEMPotency برای ردیابی هر معامله ، می توانیم اطمینان حاصل کنیم که کاربران ما به طور تصادفی دو بار شارژ نمی شوند ، مهم نیست که در طی فرآیند پرداخت چه اتفاقی می افتد.
من دوست دارم افکار شما را در این باره بشنوم! آیا قبلاً مجبور شده اید که در سیستم های خود idempotency را اداره کنید؟ یا شاید با ترمیم های پرداخت به چالش هایی بپردازید؟ احساس راحتی کنید که تجربیات خود را به اشتراک بگذارید یا نظر خود را در زیر بگذارید!