کاربر دکمه پرداخت را می‌زند، پاسخ دیر می‌رسد و Client دوباره درخواست می‌فرستد. Callback هم دو بار تحویل می‌شود. صفحه Success است، اما آیا پول یک بار ثبت شده یا سه بار؟ وضعیت «موفق» دقیقاً به Authorization، Capture، Settlement یا واریز به ذی‌نفع اشاره می‌کند؟ تست نرم‌افزار مالی زمانی ارزش دارد که از نمایش ظاهری فراتر برود و برای هر واحد پول، رویداد، ثبت دفترکل، وضعیت، مانده و مغایرت شواهد قابل‌ردگیری بسازد.

این راهنما بر هسته‌ای تمرکز دارد که بسیاری از مقاله‌های عمومی فین‌تک نادیده می‌گیرند: Money Contract، Transaction State Machine، Idempotency، Double-entry Ledger، Settlement و Reconciliation. از تعریف مبلغ و Currency شروع می‌کنیم، سپس concurrency، duplicate، refund، fee، rounding، close، migration، downtime، authorization و Release Evidence را با یک آزمایش کاملاً ساختگی به هم متصل می‌کنیم.

مرز مسئولیت: این مطلب آموزش تست نرم‌افزار است، نه مشاوره مالی، حسابداری، حقوقی، امنیتی یا مقرراتی. QA نمی‌تواند با Pass شدن تست، صحت صورت‌های مالی، انطباق سازمان، امنیت پول یا نبود زیان را تضمین کند. Product scope، Accounting policy، Currency/rounding rule، مجوزها، قانون و استاندارد قابل اعمال، Risk appetite و پذیرش ریسک باید توسط صاحبان صلاحیت تعیین و نسخه‌دار شوند؛ QA شواهد همان قرارداد را تولید می‌کند.

خلاصه عملی تست نرم‌افزار مالی

پرسششاهد ضعیفشاهد تصمیم‌ساز
آیا پرداخت موفق است؟صفحه Success یا HTTP ۲۰۰State مصوب، اثر مالی یکتا، Ledger postings، provider evidence و reconciliation
آیا مبلغ درست است؟متن «۱۰۰ هزار»amount units + currency + scale + rounding policy + breakdown
آیا retry امن است؟در Happy Path دوبار نشدtimeout-after-commit، idempotency scope، fingerprint، replay و conflict آزموده شد
آیا دفترکل صحیح است؟Balance نهایی منطقی استimmutable postings، Debit=Credit، source event، reversal و period controls
آیا Settlement کامل است؟فایل وارد شدcompleteness، duplicate، missing، amount/state mismatch، exception و aging روشن است
آیا Release آماده است؟Pass rate بالاInvariantهای حیاتی، Unknownها، open exposure، rollback/reconcile و تصمیم مالک ثبت شده‌اند

مرز صفحه: نرم‌افزار مالی، فین‌تک و درگاه پرداخت یکی نیستند

Accounting، کیف پول، Billing، Lending، Treasury، Trading، Insurance، Payroll، پرداخت و بانکداری Failure mode و Oracleهای متفاوت دارند. همین محصول نیز ممکن است فقط یک Instruction ثبت کند یا واقعاً پول، تعهد، دارایی یا گزارش رسمی را تغییر دهد. قبل از Test Plan، System of Record، مالک پول و لحظه اثر مالی را مشخص کنید.

دامنهپرسش اصلیInvariant نمونهOwner نمونه
Accounting/ERPکدام Posting و Period منبع حقیقت است؟سند تراز، immutable history، close controlFinance/Accounting
PaymentIntent، authorization، capture و settlement کجا جدا می‌شوند؟هر اثر دقیقاً یک بار در business semanticsPayments/Product/Finance
Wallet/LedgerBalance چگونه از Postingها مشتق می‌شود؟Debit=Credit و no orphan postingLedger/Finance
LendingSchedule، accrual، payment allocation و correction چه Contractی دارند؟نسخه Policy و traceable calculationCredit/Finance/Legal
TradingOrder، execution، position و settlement چگونه وصل‌اند؟quantity/price/fee/cancel lifecycleTrading/Risk/Operations
Reportingکدام snapshot، cut-off و mapping گزارش را می‌سازد؟source-to-report lineage و reproducibilityFinance/Compliance/Data

راهنمای تست فین‌تک مالک راهبرد گسترده Compliance، Security و حجم تراکنش است و راهنمای تست درگاه پرداخت روی IPG و Sandbox تمرکز دارد. صفحه حاضر مالک درستی پول، دفترکل و Reconciliation است تا این صفحات یکدیگر را تکرار نکنند.

تست مالی چه چیزی را اثبات می‌کند و چه چیزی را نه؟

یک Run معتبر می‌تواند بگوید: «برای Rule set، Currency، Timestamp، Account graph، Build، Config و Fixture مشخص، Postingها با Oracle نسخه X مطابق بودند.» این گزاره محدود است. داده واقعی، رفتار Partner، تغییر نرخ یا قانون، concurrency دیگر، خطای انسانی و مسیر اجرا‌نشده می‌توانند نتیجه متفاوت بسازند.

  • Pass شدن Calculation، Accounting policy را تصویب نمی‌کند.
  • تراز بودن Debit و Credit، درست بودن Account، Amount یا Business purpose را ثابت نمی‌کند.
  • HTTP ۲۰۰ یا Callback معتبر، Settlement نهایی را ثابت نمی‌کند.
  • نبود مغایرت در یک روز، Completeness تاریخی یا نبود fraud را تضمین نمی‌کند.
  • اسکن امنیتی یا Penetration Test، منطق مالی درست را ثابت نمی‌کند.
  • PCI DSS، AML/KYC، Privacy یا هر الزام دیگر فقط پس از تصمیم Applicability وارد Test Plan می‌شود.
  • Automation تعداد بیشتری Example اجرا می‌کند؛ صحت Oracle و پوشش ریسک را خودکار تضمین نمی‌کند.

Financial Context Contract بسازید

تست از Context شروع می‌شود. مبلغی که در یک Billing system «طلب» است ممکن است در Payment system هنوز «Intent» و در Bank statement «Settled» باشد. اصطلاح Success بدون Stage و Source مبهم است.

Financial Context Contract
Product/function:       [نام و نسخه]
Business event:         [purchase/refund/fee/...]
Economic meaning:       [تعهد/دریافت/پرداخت/انتقال]
Systems of record:      [intent, ledger, provider, bank, report]
Money owner/custodian:  [نقش سازمانی]
Currencies/scale:       [canonical definitions]
Accounting policy:      [version + approver]
State model:            [version + terminal states]
Cut-off/timezone:       [event/effective/posted/settled]
Partners/interfaces:    [contract versions]
Applicable controls:    [legal/security/compliance decision]
Excluded use:           [خارج Scope]
Release identities:     
Risk/evidence owners:   [نام نقش‌ها]

Money Contract: عدد بدون Currency و Scale پول نیست

فیلد `amount=۱۰۰۰۰۰` به‌تنهایی Oracle ندارد. باید معلوم باشد Currency چیست، عدد در واحد canonical ذخیره می‌شود یا واحد نمایشی، scale چند است، sign چه معنایی دارد، precision کجاست و rounding در کدام مرحله و با کدام Policy اعمال می‌شود. تومانِ UI نباید بی‌صدا با ریال API یا Ledger مخلوط شود.

Money Contract
amountUnits:      integer/decimal representation
currency:         ISO/business code approved for the product
scale:            explicit; never inferred from UI label
displayUnit:      canonical / toman / other presentation
sign semantics:   debit/credit or inflow/outflow contract
roundingMode:     versioned business/accounting rule
roundingPoint:    line/item/tax/invoice/settlement
precision:        intermediate and persisted precision
breakdown:        principal + fee + tax + discount + adjustment
exchangeRate:     source, pair, direction, time and version
effectiveTime:    business time and timezone
policyVersion:    immutable reference
CaseخطرOracle لازم
IRR در API، تومان در UIضریب ۱۰ یا label اشتباهcanonical amount + conversion/display rule
Decimal از Floatخطای نمایش دودویی/جمعdecimal/integer model و tolerance ممنوع یا مصوب
Fee روی هر line یا totalاختلاف roundingrounding point و allocation policy
Negative amountrefund و reversal یکی گرفته می‌شوندevent type + posting direction
Currency ناشناختهdefault خاموشreject/quarantine؛ بدون حدس
عدد فارسی/لاتینparse یا separator غلطinput normalization و canonical persistence جدا

Rounding را Property و Metamorphic تست کنید

چند Example معمول برای Rounding کافی نیست. مرزهای نصف واحد، علامت منفی، جمع lineها، تقسیم نامساوی، refund جزئی، نرخ تبدیل و اجرای دوباره را پوشش دهید. Expected value باید از یک Oracle مستقل و Rule مصوب بیاید، نه همان Function تولید که نرم‌افزار استفاده می‌کند.

  • مجموع allocationها دقیقاً با total مصوب برابر است.
  • Permutation lineها نتیجه را تغییر نمی‌دهد، مگر Policy ترتیب‌محور باشد.
  • Refund کامل از نظر economic effect با reversal مصوب تطبیق دارد، نه لزوماً همان Event type.
  • تقسیم و جمع مجدد، residual unit را طبق policy به مقصد مشخص می‌دهد.
  • تبدیل A→B→A لزوماً identity نیست؛ spread/rounding و tolerance باید مصوب باشند.
  • اجرای یک Rule set با ورودی و Version ثابت deterministic است.
  • Migration یا تغییر library بدون approval نتیجه historical را بازنویسی نمی‌کند.

مبلغ را به Breakdown و Lineage وصل کنید

کاربر یک Total می‌بیند، اما Ledger ممکن است principal، fee، tax، discount، reserve و adjustment داشته باشد. Test باید از Quote/Order تا Posting و Statement نشان دهد هر جزء از کدام Rule و Source آمده است. Total درست با breakdown غلط می‌تواند گزارش، refund یا revenue recognition را بشکند.

جزءSourceVersionAmount/CurrencyPosting destinationEvidence
PrincipalOrder lineO-v3Fixture valueReceivable/Payable contractsource ID
FeeFee ruleF-v7Fixture valueFee accountcalculation trace
TaxApproved ruleT-v2Fixture valueTax accountowner-approved oracle
DiscountPromotionP-v4Fixture valueContra/reduction accounteligibility trace
AdjustmentManual workflowA-v1Fixture valueAdjustment accountrole/reason/approval

Transaction State Machine را از Ledger جدا کنید

State برای Workflow و تجربه کاربر است؛ Posting برای اثر مالی. این دو مرتبط‌اند اما یکی نیستند. یک State ممکن است قبل از Settlement تغییر کند یا یک correction با Posting جبرانی انجام شود بدون اینکه History پاک شود. مدل دقیق باید از Contract محصول بیاید.

Payment State Contract — illustrative only
Intent:       created → requires_action → authorized/failed/expired
Funds flow:   authorized → captured → settled
Corrections:  captured/settled → partially_refunded/refunded
Exceptions:   disputed/reversed/chargeback-like states per product

For every transition:
- allowed source and destination
- actor and authorization
- significant transaction data fingerprint
- effective/posting/received time
- side effects and postings
- retry/idempotency behavior
- notification and audit
- terminal/reopen policy
- reconciliation expectation
  • Step skipping: Created مستقیماً به Settled نرود مگر Contract چنین مسیر قانونی داشته باشد.
  • Terminal transition: Failed یا Refunded بی‌دلیل دوباره Active نشود.
  • Out-of-order: Version قدیمی Current state را عقب نبرد.
  • Concurrent actions: Capture و Cancel هم‌زمان Invariant را نشکنند.
  • Partial action: مجموع refundها از مقدار مجاز مصوب عبور نکند.
  • Reopen/correction: History immutable و reason/actor ثبت شود.
  • UI wording: «پرداخت شد» Stage واقعی و محدودیت آن را گمراه‌کننده نمایش ندهد.

Idempotency: Retry باید اثر کسب‌وکاری دوم نسازد

Retry در شبکه توزیع‌شده عادی است. پاسخ ممکن است پس از Commit گم شود؛ Client نمی‌داند درخواست اعمال شده یا نه. RFC ۹۱۱۰ معنای روش Idempotent در HTTP را تعریف می‌کند و هشدار می‌دهد روش non-idempotent بدون دانستن semantics نباید خودکار retry شود. برای Payment POST، تیم معمولاً به Contract کاربردی idempotency نیاز دارد؛ نام Header به‌تنهایی کافی نیست.

Idempotency Contract
Key owner:          client/server/partner
Scope:              tenant + operation + business entity
Request fingerprint: significant immutable fields
First response:     status/body/reference/error class
Replay response:    same business result, documented transport response
Conflict:           same key + different fingerprint = explicit reject
Persistence point: before external/financial side effect
Concurrency:        one winner; others wait/read/reject deterministically
Expiry:             based on maximum replay horizon and policy
Failure recovery:   pending/unknown state with reconciliation
Audit/metrics:      first/replay/conflict/expired/unknown counts
ScenarioتزریقInvariant
Double clickدو request نزدیکیک business effect و پاسخ‌های قابل توضیح
Timeout after commitپاسخ اول حذف می‌شودretry reference همان نتیجه را می‌دهد
Concurrent same keyدو worker هم‌زمانrace دو Posting نسازد
Same key, changed amountfingerprint متفاوتConflict صریح؛ مقدار اول یا دوم خاموش پذیرفته نشود
Expired keyreplay بعد از TTLPolicy روشن؛ duplicate historical کشف شود
Downstream committedprovider success، local crashreconciliation و recovery بدون double capture

Exactly Once شعار است؛ اثر مالی یکتا را طراحی و تست کنید

Message broker ممکن است at-least-once delivery داشته باشد و همان Event چند بار برسد. حتی اگر Broker ویژگی خاصی ارائه دهد، side effect بیرونی، Database و Partner ممکن است در همان atomic boundary نباشند. هدف آزمون بهتر این است: «برای Business Event یکتا، اثر مالی مجاز طبق Contract بیش از یک بار ایجاد نمی‌شود و duplicate قابل مشاهده است.»

  • Event ID یا business key در boundary مناسب unique است.
  • Inbox/deduplication پیش از side effect یا در atomic unit مناسب ثبت می‌شود.
  • Outbox انتشار Event را با transaction محلی هماهنگ می‌کند.
  • Consumer پس از crash قبل/بعد از ack دوباره اجرا می‌شود.
  • Poison message silent drop نمی‌شود و quarantine/owner دارد.
  • Duplicate arrival در Audit دیده می‌شود اما Posting دوم نمی‌سازد.
  • Retention dedupe از replay horizon واقعی کوتاه‌تر نیست، مگر risk پذیرفته شده باشد.

Double-entry Ledger: تراز شرط لازم است، نه کافی

در مدل ثبت دوطرفه، هر Transaction group باید مجموع Debit و Credit برابر داشته باشد؛ بااین‌حال دو Account اشتباه نیز می‌توانند کاملاً تراز باشند. Test باید تراز، Account mapping، Currency، effective time، source event، posting type، reversal link و immutability را هم‌زمان بررسی کند.

Ledger Posting Contract
transactionGroupId: unique accounting unit
postingId:          immutable unique row/event
sourceEventId:      business provenance
accountId/type:     chart version + permitted direction
amountUnits:        non-negative canonical magnitude
currency:           explicit and account-compatible
side:               debit | credit
effectiveAt:        economic time
postedAt:           ledger time
periodId:           open/closed policy
reversalOf:         original posting/group reference
metadata:           minimal, versioned, auditable

Core invariant per group and currency:
Σ debit(amountUnits) = Σ credit(amountUnits)
InvariantFailure نمونهتست
Balanced groupیک Posting گم شدهproperty query و commit rejection
Account mappingFee به principal account رفتهRule-version fixture
Currency consistencyIRR و currency دیگر در یک balance جمع شدهnegative schema/domain test
ImmutabilityUPDATE رکورد تاریخی را عوض می‌کندpermission/API/database audit test
Reversal linkageمنفی خام بدون مرجع ساخته شدهoriginal-reference and amount policy
No orphanPosting بدون source/groupreferential/reconciliation scan
Period policyتغییر مخفی در دوره بستهclose/reopen/adjustment workflow

Balance را از Posting مشتق و Cache را قابل بازسازی کنید

Balance ذخیره‌شده برای سرعت مفید است، اما باید Contract روشن داشته باشد: آیا authoritative است یا projection؟ اگر projection است، از Postingها قابل rebuild باشد و اختلاف آن با منبع حقیقت monitor شود. Update هم‌زمان balance بدون کنترل می‌تواند Lost Update یا overspend بسازد.

  • Opening balance + all in-scope postings = closing balance.
  • Available، pending، held و settled balance به‌وضوح جدا هستند.
  • Projection rebuild از checkpoint و از ابتدا نتیجه یکسان می‌دهد.
  • Duplicate event balance را تغییر نمی‌دهد.
  • Reversal history را پاک نمی‌کند و effect خالص مطابق Policy است.
  • Concurrent debitها از limit/available invariant عبور نمی‌کنند.
  • Cache stale با version/freshness آشکار می‌شود، نه عدد قطعی ظاهری.

Concurrency و Isolation را با Business Invariant بسنجید

تست تک‌کاربره race را نشان نمی‌دهد. دو برداشت، دو refund، close هم‌زمان با Posting یا دو تخصیص اعتبار ممکن است جداگانه معتبر و در ترکیب نامعتبر باشند. Isolation level نامی، جای آزمون workload و invariant نیست.

مستندات جاری PostgreSQL درباره Transaction Isolation تفاوت Read Committed، Repeatable Read و Serializable و امکان Serialization failure را توضیح می‌دهد. این منبع فقط نمونه‌ای برای محصولی است که PostgreSQL دارد؛ رفتار DB، ORM و retry implementation واقعی خود را مستند و آزمایش کنید.

RaceSchedule آزمونInvariant
Double spendدو debit پس از خواندن یک available balanceحد مجاز نقض نشود یا نتیجه policy-defined باشد
Refund raceدو refund جزئی هم‌زمانمجموع از refundable amount عبور نکند
Close vs postperiod close و late postingیا قبل close ثبت یا به adjustment path هدایت شود
Idempotency raceدو request با یک keyیک side effect
Limit updatelimit و transaction هم‌زمانversion/authorization policy رعایت شود
Serializable retryconflict عمدیکل transaction logic retry؛ duplicate external effect ممنوع

Retry فقط SQL statement آخر می‌تواند تصمیم‌های قبلی را با snapshot جدید ناسازگار کند. Side effect بیرونی را نیز داخل retry loop خام قرار ندهید. Fault schedule، barrier و correlation ID لازم‌اند تا race deterministic و نتیجه قابل تکرار شود.

Authorization تراکنش را از Login جدا کنید

Authenticated بودن کاربر لزوماً به معنای مجازبودن همان Transaction نیست. Actor، account، amount، beneficiary، currency، purpose، limit، device/risk context و separation of duties می‌توانند در تصمیم دخیل باشند. Significant data که کاربر تأیید می‌کند نباید پس از authorization تغییر کند.

راهنمای رسمی OWASP برای Transaction Authorization بر پیوند authorization با داده مهم تراکنش، اجرای server-side، جلوگیری از تغییر پس از تأیید و کنترل ترتیب Stateها تأکید دارد. این Cheat Sheet راهنمای امنیتی است، نه قانون، تضمین یا نسخه یکسان برای همه محصولات.

  • What-you-confirm با beneficiary/amount/currency واقعی server-side تطبیق دارد.
  • تغییر هر field مهم، challenge/approval قبلی را invalidate می‌کند.
  • Authorization token به Transaction و زمان محدود bind است.
  • Stepها با URL یا API مستقیم skip نمی‌شوند.
  • روش ضعیف‌تر با parameter tampering انتخاب نمی‌شود.
  • Maker نمی‌تواند Checker خود باشد، اگر Policy جداسازی نقش دارد.
  • Limit و policy در execution دوباره enforce می‌شوند، نه فقط UI.
  • Failure، retry و expiry اطلاعات کافی برای حمله یا replay نمی‌دهند.

برای Threat model، authorization عمومی، secret/session و تست نفوذ، به راهنمای تست امنیت نرم‌افزار ارجاع دهید. این صفحه منطق مالی را مالک است، نه کل AppSec.

Settlement را با Payment Status یکی نگیرید

ممکن است محصول Transaction را Captured نشان دهد، Partner آن را در Batch بگذارد و Bank statement بعداً مبلغ خالصی با fee/adjustment ثبت کند. هر Stage منبع، زمان، ID و Finality متفاوت دارد. «موفق» باید مشخص کند از نگاه چه System و چه مرحله‌ای است.

StageSource evidenceIDTimeFailure/unknown
Intentمحصولpayment/order IDcreatedclient abandoned
Authorizationprovider responseprovider referenceauthorizedtimeout/unknown
Capturecapture recordcapture IDcapturedduplicate/partial
Settlement batchpartner file/APIbatch/line IDsettlement datemissing/rejected
Bank/financial statementexternal statementstatement referencevalue datenet fee/adjustment
Internal ledgerposting groupgroup/event IDeffective/postedmapping/period error

Reconciliation یک Query آخر روز نیست؛ Control است

Reconciliation باید Completeness و Correctness را بین منابع مستقل بررسی کند، اختلاف را طبقه‌بندی کند و تا resolution قابل پیگیری نگه دارد. صرف اینکه Sum کل دو سیستم برابر است کافی نیست؛ دو missing و دو duplicate می‌توانند یکدیگر را خنثی کنند.

Reconciliation Contract
Source A/B:          authoritative scope and snapshot IDs
Population:          date/cut-off/currency/entity/state
Matching keys:       stable IDs + fallback hierarchy
Amount comparison:   gross/net/fee/tax/currency/tolerance policy
State comparison:    explicit mapping/version
Completeness:        A-only, B-only, duplicate, rejected
Timing window:       expected lag and aging buckets
Exceptions:          reason, owner, SLA, evidence, disposition
Adjustments:         approval and posting linkage
Rerun:               immutable inputs + run ID + reproducible result
Closure:             zero/unresolved accepted by authorized owner
Mismatchمعنای ممکناقدام تست/عملیات
A-onlydelay، loss، wrong cut-off یا false recordtrace source→transport→destination
B-onlyunknown ingestion، duplicate key یا missing sourceprovenance و ownership
Amountfee، rounding، partial، currency یا mappingbreakdown compare؛ no blind tolerance
Statelag، stale event یا mapping errorversion/timeline compare
Duplicateretry یا file re-importidempotency and unique controls
Unmatched agingمسئله ماندگار و exposureescalation، reserve/hold طبق policy
Offsetting totalsخطاهای متقابل پنهانrow/event-level matching

Refund، Reversal، Void و Dispute را یکی نکنید

واژه‌ها و lifecycle دقیق به محصول و Partner بستگی دارند. Test Plan باید تفاوت Business event، زمان مجاز، مقدار قابل انجام، fee، authorization، Posting، notification و settlement را نسخه‌دار کند. استفاده از amount منفی برای همه مسیرها History و گزارش را مبهم می‌کند.

ScenarioپرسشInvariant نمونه
Full refundکدام مقدار و fee برمی‌گردد؟effect طبق policy و original link
Partial refundsترتیب و مجموع چگونه است؟cumulative ≤ refundable amount مصوب
Concurrent refundدو agent هم‌زمانrace over-refund نسازد
Refund retrytimeout بعد از provider commitیک refund business effect
Reversal/correctionاصل حذف یا جبران می‌شود؟immutable original + linked corrective entries
Dispute-like eventچه کسی و در کدام state اقدام می‌کند؟separate workflow، evidence و posting mapping
Closed periodاصلاح تاریخی چگونه ثبت می‌شود؟current-period adjustment طبق policy

Fee، Tax، Discount و FX را Version کنید

قانون مالی در Code تنها زندگی نمی‌کند؛ Configuration، جدول، قرارداد Partner و تاریخ اثر آن را تغییر می‌دهند. هر محاسبه باید Rule ID/version، effective window، source و breakdown داشته باشد تا Test تاریخی و بازتولید گزارش ممکن شود.

  • مرز قبل/در/بعد از Effective time و timezone؛
  • Ruleهای overlap و gap؛
  • Minimum/maximum، tier و cumulative threshold؛
  • Discount stacking و ترتیب اعمال؛
  • Fee refundability و partial allocation؛
  • FX pair direction، source timestamp، stale/missing rate و rounding؛
  • Retroactive correction بدون بازنویسی silent historical output؛
  • Fallback فقط اگر Owner صریحاً تصویب کرده باشد.

Time، Cut-off و Period Close را مدل کنید

CreatedAt، AuthorizedAt، EffectiveAt، PostedAt، SettledAt و ValueDate یک timestamp نیستند. گزارش روزانه نیز به timezone، تعطیلی، cut-off و late event وابسته است. Timestamp را با رشته محلی یا تاریخ شمسی منبع حقیقت نکنید؛ نمایش را از instant canonical و business date جدا نگه دارید.

Caseتزریقبررسی
مرز روزیک ثانیه قبل/بعد cut-offbusiness date/period طبق policy
Late eventevent قدیمی امروز دریافت می‌شودeffective vs received time
Clock skewPartner جلو/عقبترتیب به timestamp نامطمئن واگذار نشود
Closed periodcorrection پس از closeadjustment/reopen authorization
Tehran displayUTC→Asia/Tehran→شمسینمایش درست، instant/provenance حفظ
Batch rerunjob دوباره در همان/روز بعدrun identity و idempotency

Audit Trail باید پاسخ‌گو باشد، نه مخزن راز

Audit خوب نشان می‌دهد چه Actor یا Service، کدام Business entity را، با چه Action، version، reason، authorization و outcome تغییر داده است. Log نباید PAN، credential، OTP، token، secret یا payload حساس کامل را برای راحتی Debug ذخیره کند. Access، retention و integrity آن نیز کنترل می‌خواهند.

  • Actor، service identity و impersonation context؛
  • Business entity/event/reference، نه فقط URL؛
  • قبل/بعد به‌شکل حداقل و مجاز یا version reference؛
  • Reason و approval برای manual adjustment؛
  • Correlation از request تا provider، ledger و reconciliation؛
  • UTC instant، timezone context و clock source؛
  • Success/failure/unknown و error class بدون secret؛
  • Tamper detection، access review و export control؛
  • قابلیت جست‌وجو بدون افشای داده شخصی نامرتبط.

PCI DSS و Compliance را با Applicability آغاز کنید

نام Industry یا وجود Button پرداخت به‌تنهایی Scope هیچ استاندارد یا قانون را تعیین نمی‌کند. Data flow، نقش سازمان، قرارداد، بازار، نوع Account Data، outsourcing، network segmentation و اثر سیستم بر محیط مشمول باید توسط نقش‌های حقوقی، امنیتی و Compliance ارزیابی شوند. QA تصمیم را به Control و Evidence تبدیل می‌کند.

کتابخانه رسمی PCI Security Standards Council در زمان این بازبینی PCI DSS v4.۰.۱ و اسناد پشتیبان آن را فهرست می‌کند. این واقعیت به معنای مشمول‌بودن خودکار هر اپ مالی، ایرانی یا غیرایرانی نیست. نسخه، Scope، SAQ/assessment path و مسئول ارزیابی باید برای سازمان مشخص شود.

فیلد Applicabilityپرسشخروجی QA پس از تصمیم
Authority/sourceقانون، استاندارد، قرارداد یا policy کدام است؟نسخه و Requirement ID
Entity/roleسازمان چه نقش تعریف‌شده‌ای دارد؟Scope actor/system
Data/processچه داده‌ای کجا store/process/transmit یا affect می‌شود؟data-flow test points
EnvironmentBoundary و segmentation مصوب چیست؟control validation scope
Third partyمسئولیت shared چگونه تقسیم شده؟evidence request و interface tests
Effective dateکدام نسخه در چه زمانی لازم است؟time-bound regression plan
Exceptionچه استثنا/compensating process تأیید شده؟testable control + expiry

برای روش تبدیل منبع نسخه‌دار به Requirement و Evidence از راهنمای تست انطباق و برای GDPR/CCPA/HIPAA و داده شخصی از راهنمای تست حریم خصوصی استفاده کنید. هیچ Test Suite به‌تنهایی Compliance کل سازمان را certify نمی‌کند.

داده تست مالی: Synthetic-first و بدون راز

داده مالی واقعی فقط مبلغ نیست؛ Account، PAN، نام، شناسه، device، IP، description، beneficiary، token، statement و log می‌توانند حساس باشند. Fixture مصنوعی باید از فرمت‌های رزروشده و واضح استفاده کند و هرگز قابلیت Route شدن به Provider یا حساب واقعی نداشته باشد.

  • Account/merchant/customer/payment IDهای `SYN-*` و namespace جدا؛
  • هیچ PAN، CVV2، PIN، OTP، credential، token یا کلید واقعی؛
  • Provider/Bank/PSP stub محلی و denylist/allowlist شبکه؛
  • Currency و Amountهای خیالی اما Contract-valid؛
  • Generator version، seed، checksum و expected postings؛
  • Edge catalog برای zero، max، negative-disallowed، boundary و overflow؛
  • Retention، access، export و destruction محیط تست؛
  • Log/screenshot/ticket redaction و secret scanning؛
  • Production-like distribution فقط با synthetic generation یا تصمیم رسمی داده.

Property-based و Model-based Testing برای پول

Example مشخص لازم است، اما فضای State، Currency، retry و concurrency بزرگ است. Property-based testing ورودی‌های متعدد می‌سازد و invariant را می‌سنجد؛ Model-based testing مسیرهای مجاز State را تولید می‌کند. هر دو به Oracle و Generator سالم و shrinking قابل توضیح نیاز دارند.

PropertyGeneratorCounterexample مورد انتظار
Debit=Credit per group/currencyevent و posting breakdownگروه/ردیف حداقل نامتوازن
Duplicate no extra effectsequence با replayکوتاه‌ترین sequence با effect دوم
State monotonic by versionpermutation نسخه‌هاlate event که Current را عقب برد
Refund boundچند refund جزئی/concurrentکمترین مجموع عبورکننده
Projection rebuild equalityposting history/checkpointنخستین event اختلاف‌ساز
Allocation conservationtotal و N destinationresidual گم یا اضافه
Reconciliation completenessmissing/duplicate/mismatch pairsموردی که aggregate پنهان کرد

Propertyها قانون مالی عمومی نیستند. مثلاً «refund کامل همیشه net zero است» ممکن است با fee غیرقابل‌برگشت یا Policy دیگر غلط باشد. هر invariant باید منبع، Scope و Version داشته باشد.

Migration و Backfill را با Trial Balance تمام نکنید

تراز کل قبل و بعد می‌تواند با Account mapping غلط، Currency مخلوط، lost lineage، duplicate event یا تاریخ اثر اشتباه همراه باشد. Migration باید population، mapping version، reject manifest، source snapshot، delta/cutover، semantic invariants، reproducibility و rollback/reconcile داشته باشد.

کنترلمعیار ضعیفمعیار بهتر
Completenessrow count کلentity/state/currency/period slices + rejects
Balancegrand totalaccount/currency/period/customer aggregate + event sample
Lineageمقدار منتقل شدsource ID→target posting/event mapping
Semanticsfield non-nullstate/account/rule/time meaning preserved
Historycurrent balance درستoriginal/correction/reversal chain intact
Cutoverjob succeededsnapshot + delta + no gap/double-write
Rollbackbackup existsrestore rehearsed + post-rollback reconciliation

Performance: Throughput بدون Correctness خطرناک است

سیستم می‌تواند هزار Request در ثانیه پاسخ دهد اما duplicate Posting، backlog نامرئی یا stale balance بسازد. Workload مالی باید mix واقعی Stateها، retry، hot account، batch، close، statement import و reconciliation را مدل کند و پس از Load، invariantها را دوباره بررسی کند.

بعدMetricCorrectness companion
Latencyp50/p95/p99 per operationresult state و timeout-after-commit outcome
Throughputaccepted/completed per secondunique business effects
Queuedepth/oldest ageno lost/duplicate events
Ledgerposting ratebalanced groups و projection lag
Reconciliationrun durationpopulation completeness و deterministic result
Recoverycatch-up timepost-recovery balance/state/reconcile
Hot keylock/conflict/retry ratelimit/refund invariant

طراحی مدل بار، percentile، saturation و معیار پذیرش در راهنمای برنامه تست عملکرد آمده است. Threshold را از SLA، ظرفیت، Risk و فرآیند واقعی بگیرید؛ عدد عمومی این مقاله Oracle نیست.

Failure Injection: Unknown مالی را آشکار کنید

مهم‌ترین حالت همیشه Success یا Fail نیست؛ «نمی‌دانیم اعمال شد یا نه» است. قطع بین Commit و Response، crash بین Provider و Ledger، فایل ناقص، clock skew، disk full، delayed webhook و serialization failure را در محیط مجاز تزریق کنید.

Fault pointUnknownRecovery invariant
قبل local commitدرخواست پذیرفته شد؟no financial effect یا retry safe
بعد local commit/قبل responseClient نتیجه را نمی‌داندidempotent lookup/retry
بعد provider/قبل local recordexternal success، internal unknownreconciliation repairs once
Outbox publish gapledger ثبت، event غایبrepublish without double effect
Consumer before ackevent دوباره می‌رسدdedupe/no second posting
Partial statement filepopulation ناقصatomic/manifest validation؛ no false closure
Serialization failuretransaction abortedwhole logic retry without external replay

راهنمای تست تاب‌آوری نحوه تعریف steady state، fault boundary، recovery evidence و stop condition را پوشش می‌دهد. Fault injection در Production مالی بدون مجوز، blast radius، guardrail و rollback اقدامی پرخطر است و از متن مقاله مجوز نمی‌گیرد.

Backup، Restore و Reconciliation پس از بازیابی

Backup موفق ثابت نمی‌کند Ledger قابل بازیابی یا Statementها کامل‌اند. Restore را در محیط پاک با schema/config/key سازگار اجرا کنید، posting invariants و balances را بسنجید، سپس Eventها و Partner changes بعد از Recovery Point را reconcile کنید.

  • Manifest دقیق database، object store، config، rule و key dependency؛
  • Checksum و قابلیت decrypt با access کنترل‌شده؛
  • Restore time و recovery point مشاهده‌شده، نه فقط هدف قراردادی؛
  • Debit=Credit و no orphan/currency mismatch پس از Restore؛
  • Projection rebuild و balance comparison؛
  • Gap event replay با idempotency؛
  • Partner/statement reconciliation پس از بازگشت؛
  • Return-to-service gate، monitoring و owner؛
  • Action item و effectiveness retest.

Observability: Metric را به پول و Control وصل کنید

CPU و Error rate سبز می‌توانند کنار duplicate payment و stale settlement باشند. Signalهای مالی باید numerator، denominator، currency، stage، source، time window، late-arrival policy، slice و owner داشته باشند. مبلغ Aggregate بدون Count و Distribution نیز می‌تواند مسئله را پنهان کند.

SignalCounter-signalSliceRunbook
Requests acceptedunique effects/completed/unknownoperation/partneridempotency trace
Provider successlocal posting/reconcile statusprovider/currencyrepair/hold
Ledger balancedaccount mapping/recon mismatchaccount/currency/periodstop posting/escalate
Reconcile differencecount/amount/agingreason/partner/dayowner/SLA
Refund successcumulative/refundable amountchannel/reasonover-refund containment
Queue deptholdest age/business exposureevent typescale/replay/reconcile

Metric label نباید account/card/customer ID با cardinality و Privacy risk بالا حمل کند. Correlation ID کنترل‌شده، access محدود، retention و redaction را با Security/Privacy تعیین کنید.

Release Identity شامل Rule و Config است

Fee table، account mapping، limit، routing، currency enablement، cut-off و Feature Flag می‌توانند بدون Code deploy اثر مالی را تغییر دهند. Release Evidence باید کل Configuration مؤثر را pin کند.

Financial Release Identity
Code/image digest:        ___
Database schema/migration:___
Money/currency contract:  ___
Accounting/chart mapping: ___
Fee/tax/discount rules:   ___
State machine version:    ___
Partner/API mapping:      ___
Idempotency/TTL policy:   ___
Limits/authorization:     ___
Cut-off/calendar/timezone:___
Feature flags/routing:    ___
Fixture/generator seed:   ___
Evidence pack/checksum:   ___

Release Gate را بر Invariant و Exposure بنا کنید

صد UI test سبز یک Idempotency race اجرا‌نشده را خنثی نمی‌کند. Gate باید critical money invariants، reconciliation، migration، failure/recovery، Security/Compliance references، blocked evidence و rollback را جدا گزارش کند.

Financial Release Memo
Scope and release identity:       ___
Money/state/ledger contracts:     ___
Critical invariants and evidence: ___
Provider/settlement/reconciliation:___
Concurrency/failure/recovery:     ___
Security/privacy/compliance refs: ___
Open defects and exposure:        ___
Blocked/inconclusive/not-run:     ___
Rollback/repair/runbooks:         ___
Monitoring and owners:            ___
Residual risk:                    ___
Recommendation: Go / Conditional / Hold
Authorized decision and expiry:   ___
Evidence statusمعنارفتار Gate
Passدر Scope/Oracle مشاهده‌شده مطابق بودlimitation حفظ شود
FailInvariant یا requirement نقض شدfix/contain/authorized decision
Blockedتست اجرا نشدUnknown، نه Pass
InconclusiveOracle/evidence کافی نیستExposure و investigation
Staleبه Rule/config قبلی مربوط استimpact analysis/retest
Reconciled exceptionاختلاف توضیح و حل شدهevidence و approval لازم
Accepted exceptionاختلاف باز با تصمیم محدودowner/limit/expiry/monitor

آزمایش بازتولیدپذیر: Delivery count در برابر Ledger

برای نشان‌دادن مکانیک duplicate و stale state، یک Fixture کاملاً ساختگی اجرا شد. هیچ کاربر، حساب، کارت، PSP، بانک، Merchant، سفارش یا پول واقعی وجود ندارد. Currency برچسب IRR دارد، اما Amountها صرفاً اعداد آموزشی‌اند و هیچ نرخ، fee، tax یا قاعده حسابداری واقعی را نمایش نمی‌دهند.

Fixture: fictional-payment-ledger-v1
Payment: PAY-SYN-100
Events delivered: 6

1 INIT v1 pending, effect 0
2 CAP v2 captured, effect +120000 units
3 duplicate CAP v2, effect +120000 units
4 REF v3 partially_refunded, effect -20000 units
5 duplicate REF v3, effect -20000 units
6 STATUS-OLD v1 pending, effect 0

Fictional independent statement net: 100000 IRR units

مصرف‌کننده ساده هر Delivery را اثر تازه و آخرین Arrival را State جاری می‌گیرد. مصرف‌کننده قراردادی Event ID را یک‌بار اعمال می‌کند، State را فقط با Version بزرگ‌تر جلو می‌برد و برای Capture/Refund دو Posting متقارن آموزشی می‌سازد.

روشNet unitsCurrent stateDuplicate/StaleLedgerStatement difference
Naive delivery sum200000pending v1همه اعمال شدندندارد+100000
Contract-aware100000partially_refunded v3۲ duplicate، ۱ stale کنار گذاشته۴ posting؛ Debit=Credit=۱۴۰۰۰۰0
{
  "fixture": "fictional-payment-ledger-v1",
  "deliveries": 6,
  "naive": {
    "netUnits": 200000,
    "state": "pending",
    "statementDifferenceUnits": 100000
  },
  "contractAware": {
    "uniqueNetUnits": 100000,
    "currentState": "partially_refunded",
    "currentStateVersion": 3,
    "duplicatesIgnored": 2,
    "staleStatesIgnored": 1,
    "postings": 4,
    "debitUnits": 140000,
    "creditUnits": 140000,
    "balanced": true,
    "statementDifferenceUnits": 0
  }
}

محدودیت‌ها اساسی‌اند: Fixture عمداً برای تولید Failure ساخته شده، فقط شش Event دارد و هیچ concurrency واقعی، provider، database، security، accounting policy، FX، fee، tax، close، fraud، availability یا رفتار انسانی را نمی‌سنجد. تراز آموزشی Accountهای خیالی، صحت حسابداری یا ایمنی مالی هیچ محصولی را ثابت نمی‌کند. اعداد Probability، benchmark، خسارت، حجم، threshold یا نمونه آماری نیستند.

درس محدود این است: Delivery count و آخرین timestamp باید با Event identity، Version rule، Posting invariant و منبع مستقل Reconciliation تکمیل شوند. Account mapping و Contract واقعی را Finance/Accounting/Product محصول تعیین می‌کنند.

سناریوی بومی: پرداخت آزمایشی IRR بدون اتصال واقعی

یک فروشگاه فرضی فارسی را در محیط کاملاً جدا تصور کنید. Order و Payment ID با `SYN-` آغاز می‌شوند، Provider یک Stub محلی است، هیچ IPG/PSP/بانک واقعی فراخوانی نمی‌شود و هیچ PAN، CVV2، PIN، OTP، حساب، موبایل، نام، کد ملی، Token یا پول واقعی وجود ندارد. این Lab درباره مقررات، شبکه پرداخت یا قواعد حسابداری ایران ادعایی ندارد.

ریسکتزریق ساختگیInvariantEvidence
ریال/تومانAPI IRR، UI تومان با labelconversion صریح و round-trip canonicalAPI/UI/ledger compare
رقم و RTL۰۱۲/۰۱۲/۰۱۲ و mixed IDsparse درست؛ ID و amount جابه‌جا نشوندinput/display/print checks
Double clickدو submit با یک keyیک payment effectrequest/event/posting trace
Timeout after commitStub ثبت، response حذفretry همان reference را بازیابی کندidempotency/reconcile
Duplicate callbackCAP دو باریک Capture effectdedupe metric + ledger
Late statusPending v1 پس از Refund v3Current state عقب نرودhistory/current query
Tehran/JalaliUTC instant نزدیک cut-offbusiness date طبق policy؛ شمسی فقط نمایشreport/statement slice
Recoverycrash بین Stub و local postingunknown آشکار و repair فقط یک بارrunbook + reconciliation

Dependencyها در cache داخلی، Artifactها با checksum و Fixture با seed ذخیره می‌شوند. Egress محیط به مقصدهای واقعی deny است. اگر تیم بعدها Sandbox بیرونی اضافه کند، Scope داده، credential، Terms، rate limit، webhook verification، cleanup و تفاوت Sandbox/Production باید دوباره بررسی شود.

نقش‌ها و Decision Rights

نقشمسئولیت نمونهنباید به‌تنهایی تعیین کند
Finance/Accountingpolicy، chart، posting oracle، closeimplementation correctness بدون Evidence
Product/Paymentsjourney، state semantics، partner contractAccounting/Compliance applicability
Engineeringdesign، atomicity، idempotency، observabilityپذیرش مستقل residual risk
QA/Testrisk scenarios، execution، limitations، evidenceتضمین پول/قانون یا ساخت Oracle مالی
Security/Fraudthreat، authorization، detection/controlصحت Ledger کامل
Legal/Compliance/Privacyapplicability و requirement approvalفنی‌بودن Control بدون test
Operations/SREdeploy، monitoring، recovery، runbookmanual adjustment بدون approval
Authorized risk ownerrelease/residual risk decisionتغییر evidence یا requirement history

برنامه ۳۰روزه Pilot

هفتهخروجیکارمعیار اتمام
۱: ContractContext، Money و State contractsیک flow محدود، owner، currency، stages، source of truthابهام Success/Amount/Time رفع شده
۲: LedgerPosting/Idempotency/Reconcile contractsevent IDs، account mapping، duplicate/late/unknown casesinvariantها owner و version دارند
۳: EvidenceSynthetic fixtures و deterministic testsboundary، property، concurrency، failure، migrationfailure قابل بازتولید و traceable است
۴: DecisionRelease memo، dashboard و runbooksrestore/reconcile exercise، unknown review، gateresidual risk/owner/expiry روشن‌اند
  • کل بانک یا ERP را انتخاب نکنید؛ یک Capture→Refund→Reconcile flow کافی است.
  • Finance/Accounting را پیش از Expected Result وارد کنید.
  • یک Money Contract و یک State diagram نسخه‌دار بسازید.
  • سه Invariant حیاتی: unique effect، balanced postings و reconciliation را اول اجرا کنید.
  • حداقل timeout-after-commit و concurrent retry را تزریق کنید.
  • گزارش را بر Exposure و Unknown بنا کنید، نه تعداد Test Case.

ضدالگوهای رایج تست نرم‌افزار مالی

ضدالگومسئلهاصلاح
Success page = paidStage و source مبهم استstate/ledger/provider/reconcile evidence
amount بدون currencyواحد و scale حدس زده می‌شودMoney Contract
Float everywhereprecision/rounding کنترل‌نشدهapproved representation and oracle
Retry POST blindlyeffect دوم ممکن استidempotency contract
Exactly once labelboundary بیرونی نادیده گرفته می‌شودunique business effect + reconcile
Debit=Credit = correctmapping غلط نیز تراز استaccount/source/currency checks
Balance mutablehistory و race پنهانimmutable postings + rebuildable projection
Last arrival winslate event State را عقب می‌بردversion/state contract
Sum reconciliationoffsetting errors گم می‌شوندevent-level matching
Blind toleranceمغایرت واقعی پذیرفته می‌شودreason-specific policy
Production financial data in testprivacy/security exposuresynthetic-first isolation
PCI for every fintechApplicability حدس زده می‌شودformal scope decision
Automation guarantees accuracyoracle/common-code defect پنهانindependent model/review/properties
Load test without ledger checkسریع اما غلطpost-load invariants
Backup green = recoverablerestore/reconcile آزموده نشدهclean recovery exercise
Blocked hidden as skippedunknown exposure حذف می‌شودexplicit gate status

چک‌لیست نهایی تست نرم‌افزار مالی

  • System of Record، economic event و Stageهای Success مشخص‌اند.
  • Amount، Currency، Scale، Display، Sign، Precision و Rounding قرارداد دارند.
  • Breakdown هر Total به Source، Rule version و Posting متصل است.
  • State Machine، Actor، version و transitionهای ممنوع تعریف شده‌اند.
  • Idempotency scope، key، fingerprint، conflict، expiry و recovery روشن‌اند.
  • Duplicate، retry، timeout-after-commit و out-of-order آزموده شده‌اند.
  • Ledger groups به تفکیک Currency ترازند و Account mapping بررسی شده است.
  • Postingها immutable و correction/reversal linked هستند.
  • Balance projection از Postingها قابل rebuild و مقایسه است.
  • Concurrency برای debit/refund/close/idempotency با schedule کنترل‌شده اجرا شده است.
  • Transaction authorization به داده مهم و execution server-side وصل است.
  • Settlement stages، IDs، timestampها و source evidence جدا هستند.
  • Reconciliation event-level، complete، rerunnable و exception-owned است.
  • Refund/void/reversal/dispute و fee behavior از هم جدا شده‌اند.
  • Rule، Rate، Calendar، Cut-off و Timezone نسخه‌دارند.
  • Audit traceable است و secret/card/account data نامجاز نگه نمی‌دارد.
  • PCI/Privacy/AML/KYC/Reporting فقط طبق Applicability مصوب وارد Plan شده‌اند.
  • Fixtureها مصنوعی، isolated، seeded و غیرقابل Route به دنیای واقعی‌اند.
  • Migration به‌جز Count و Total، lineage/semantics/history را می‌سنجد.
  • Load test با unique effects، balance و reconciliation همراه است.
  • Failure، Restore و Reconciliation پس از recovery تمرین شده‌اند.
  • Release identity شامل Code، Schema، Rule، Mapping، Flag و Config است.
  • Blocked/Inconclusive/Stale به‌عنوان Unknown در Gate دیده می‌شوند.
  • Monitoring به business effect و exposure وصل است، نه فقط زیرساخت.

سؤالات متداول تست نرم‌افزار مالی

مهم‌ترین Invariant برای تست پرداخت چیست؟

یک پاسخ جهانی وجود ندارد، اما «هر Business Event یکتا حداکثر اثر مالی مجاز خود را ایجاد کند» معمولاً نقطه شروع مفیدی است. این Invariant باید با Money/State/Ledger contract، duplicate و timeout tests و Reconciliation تکمیل شود. Finance/Product باید معنای اثر مجاز را تصویب کنند.

آیا تراز بودن Debit و Credit یعنی دفترکل درست است؟

خیر. دو Posting با Account، Currency، مبلغ، زمان یا Source اشتباه نیز می‌توانند تراز باشند. علاوه بر Debit=Credit، mapping، provenance، immutability، period، reversal link، balance projection و reconciliation با منبع مستقل را تست کنید.

تفاوت Idempotency و Duplicate Detection چیست؟

Duplicate detection تشخیص می‌دهد Event یا Request قبلاً دیده شده؛ Idempotency قرارداد گسترده‌تری است که می‌گوید تکرار چگونه پاسخ می‌گیرد و چرا اثر کسب‌وکاری دوم نمی‌سازد. Scope، fingerprint، conflict، concurrency، persistence point، expiry و recovery بخش‌های مهم آن‌اند.

آیا همه نرم‌افزارهای مالی مشمول PCI DSS هستند؟

خیر؛ نام «مالی» یا داشتن مسیر پرداخت به‌تنهایی تصمیم Scope نیست. نوع Account Data، store/process/transmit یا اثر بر محیط مربوط، نقش سازمان، معماری، outsourcing و اسناد جاری باید توسط مسئولان Compliance/Security تعیین شوند. QA Requirement مصوب و نسخه‌دار را تست می‌کند.

برای شروع تست مالی چه سناریویی مناسب است؟

یک flow مصنوعی محدود مانند Capture→partial refund→reconciliation انتخاب کنید. Money Contract، State versions، Event IDs و Posting oracle بسازید؛ سپس duplicate callback، timeout-after-commit، concurrent refund، stale event و اختلاف Statement را اجرا کنید. هیچ حساب، کارت، درگاه یا پول واقعی لازم نیست.

جمع‌بندی: صحت مالی از Contract تا Reconciliation ساخته می‌شود

تست نرم‌افزار مالی با محاسبه چند Example یا سبزشدن صفحه پرداخت تمام نمی‌شود. Money Contract معنا و واحد را تثبیت می‌کند؛ State Machine مسیر را محدود می‌سازد؛ Idempotency و concurrency از اثر تکراری جلوگیری می‌کنند؛ Ledger اثر مالی را traceable نگه می‌دارد؛ Settlement و Reconciliation اختلاف واقعیت‌های مستقل را آشکار می‌کنند؛ و Failure/Restore/Monitoring نشان می‌دهند Control در شرایط دشوار چه می‌کند.

پرسش درست «چند تراکنش Pass شد؟» نیست. بپرسید: «برای این Currency، Rule و Release، کدام Business Event چه اثر یکتایی ساخت، چگونه در Ledger ثبت شد، با کدام Source مستقل reconcile شد، چه Unknownی باقی است و چه کسی ریسک آن را می‌پذیرد؟»

روش تدوین و منابع

این راهنما با بازبینی انتقادی نسخه قبلی، جداسازی intent صفحه از راهنمای عمومی FinTech/IPG/Security/Compliance و تطبیق ادعاهای فنی متغیر با منابع رسمی جاری تدوین شد. آزمایش شش‌رویدادی با Node.js ۲۴.۱۸.۰، بدون dependency و به‌صورت deterministic اجرا شد؛ تمام داده و Accountها ساختگی‌اند.

  • PCI Security Standards Council Document Library: PCI DSS v4.۰.۱ و اسناد پشتیبان جاری، فقط پس از Scope/Applicability.
  • OWASP Transaction Authorization Cheat Sheet: significant transaction data، server-side enforcement و state-flow controls.
  • RFC ۹۱۱۰ §۹.۲.۲: semantics روش‌های Idempotent و محدودیت retry خودکار.
  • PostgreSQL Current Documentation، Transaction Isolation: anomalies، isolation و retry؛ صرفاً مثال فناوری وابسته به محصول.

بازبینی محتوایی: مرداد ۱۴۰۵. Standard، Regulation، Partner contract، Currency rule، Accounting policy و API تغییر می‌کنند؛ نسخه جاری و Applicability محصول خود را پیش از استفاده تأیید کنید.

دیدگاهتان را بنویسید