Parse callback and remittance XML¶
This operation covers four small, closely related types that all do the same job — turn inbound XML from US Bank into typed .NET values — without performing any SOAP calls or database access. RealTimePaymentConfirmation and RealTimeNonPaymentNotification parse individual callback payloads; RemittanceDocument parses a batch remittance file and yields a RemittedPayment per detail row. All four are pure, lazily-evaluated readers over an in-memory XElement/XDocument.
| Field | Value |
|---|---|
| Operation ID | OP-EPAY-08 |
| Trigger | Caller constructs New RealTimePaymentConfirmation(xml), New RealTimeNonPaymentNotification(xml), or New RemittanceDocument(xDocument) from XML received from US Bank |
| Inputs | Raw XML text (payment confirmation, nonpayment notification) or an XDocument (remittance document) |
| Outputs | Typed, read-only properties: user ID, payment amount, policy number, transaction mode/frequency/duration/amount-type enums, confirmation ID, effective/business dates, product, payment network, card type (confirmation); user ID, policy number, product, unsuccessful-event description and timestamp (nonpayment notification); process date, biller ID, and a list of RemittedPayment rows (remittance document), each exposing confirmation ID, product, payment network, card type, amount, effective date, policy number, saved-balance ID, transaction type, user ID, and ACH return details |
| Primary components | RealTimePaymentConfirmation (structure), RealTimeNonPaymentNotification (structure), RemittanceDocument, RemittedPayment |
| Entry point | Business\SAIF.Business.EPay.USBank\RealTimePaymentConfirmation.vb |
Steps¶
- Load the root element lazily. Both
RealTimePaymentConfirmationandRealTimeNonPaymentNotificationstore the raw XML string in the constructor and defer parsing: the privateRootproperty callsXElement.Loadonly the first time any property is read, caching the result for subsequent reads. - Read simple scalar fields. Properties such as
UserId,PaymentAmount,TransactionModeCode,BillerProductCode, andUnsuccessfulEventread a single named child element's value directly offRoot. - Read parameter-style fields.
PolicyNumberandSavedBalanceId(confirmation) andPolicyNumber(notification) search theParameterchild elements for one whoseParameterNamematches, then return itsParameterValue;SavedBalanceIdreturns an empty string when no matching parameter exists instead of throwing. - Classify the transaction mode.
TransactionModeinspects the root element's local name (PaymentInfovs.RecurringPaymentInfo) and maps the transaction-mode code to the matching enum member, defaulting toOtherfor any unrecognized combination. - Derive recurring-specific fields.
IsRecurringis true when the mode isStartRecurring,EditRecurring, orStopRecurring;ConfirmationIdreadsRecurringReferenceIdwhen recurring orConfirmationIdotherwise;PaymentEffectiveDatereadsFirstScheduledPaymentDatewhen recurring orPaymentEffectiveDateotherwise;FrequencyandDurationare only meaningful (non-Other) when recurring. - Derive biller identifiers from the confirmation ID.
BillerGroupIdandBillerIdare computed by taking fixed-width substrings (first 3 characters, next 3 characters) ofConfirmationId. - Resolve enums shared with the rest of the library.
Productcalls the sharedConvertEPaymentServiceProduct/GetSaifProductCodehelpers (fromEnums.vb) against the raw biller product code;PaymentNetworkcallsConvertPaymentNetwork;CardTypemaps a raw code string to theCardTypesenum, defaulting toUnknown. - Parse fixed-format dates.
ConvertYYYMMDDToDate/ConvertUSBankDateStringToDateslice a fixed-widthYYYYMMDD-style string into year/month/day components and construct aDate. - Load a remittance document.
RemittanceDocument's constructor stores the caller-suppliedXDocument;ProcessDateandBillerIdare read from theHeaderelement nested underRemittance. - Enumerate remitted payments.
RemittedPaymentsiterates everyDetailelement in the document and constructs oneRemittedPaymentper element, passing along the parsedBillerGroupIdandBillerIdfrom the header so each payment can compute its own confirmation-ID suffix. - Read remitted-payment fields. Each
RemittedPaymentexposes the same category of typed accessors as the confirmation structure (product, payment network, card type, transaction type) plus ACH-specific fields (ACHReturnCode,ReturnReasonDescription,ReturnDate) and a computedConfirmationIdWithoutBillerGroupAndBillerthat strips the leading biller-group/biller prefix and parses the remainder as a decimal.
Process flow¶
The following diagram visualizes the lazy-parse pattern shared by the confirmation/notification structures and the remittance document's per-row expansion.
flowchart TD
Start{Which payload?}
Start -->|Payment confirmation| CLoad[Store XML string;<br>defer XElement.Load]
CLoad --> CRead[Read scalar and parameter fields<br>on first property access]
CRead --> CMode[Classify TransactionMode<br>from root name + code]
CMode --> CDerive[Derive recurring flags,<br>confirmation ID, dates, enums]
Start -->|Nonpayment notification| NLoad[Store XML string;<br>defer XElement.Load]
NLoad --> NRead[Read scalar and parameter fields]
Start -->|Remittance document| RLoad[Store XDocument]
RLoad --> RHeader[Read ProcessDate, BillerId<br>from Header element]
RHeader --> RLoop[For each Detail element:<br>construct a RemittedPayment]
RLoop --> RFields[Expose typed fields<br>per remitted payment]
CDerive --> Done([Typed values returned<br>to caller on demand])
NRead --> Done
RFields --> Done
Failure and edge-case behavior¶
- All property reads assume the expected element is present; a missing element (other than the explicitly guarded
SavedBalanceIdandPaymentTypeAttempt/PaymentAmountcases) raises an unhandled null-reference-style exception fromXElementnavigation rather than a handled parsing error.* SavedBalanceIdonRealTimePaymentConfirmationandPaymentTypeAttempt/PaymentAmountonRealTimeNonPaymentNotificationare the only fields with explicit missing-element handling, returning an empty string or zero instead of throwing.RecurringRefIdonly reads a value whenTransactionMode = Declined; for every other mode it returns an empty string without checking whether the underlying element exists.- Because
Rootis cached after first access, constructing one of these structures with malformed XML defers the parse failure until the first property is actually read, not at construction time.* RemittedPayment's constructor isFriend, so instances can only be created byRemittanceDocumentwithin this library — there is no public way to construct aRemittedPaymentdirectly from a caller-supplied XML fragment.
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.
Related documentation¶
Sources¶
Business\SAIF.Business.EPay.USBank\RealTimePaymentConfirmation.vbBusiness\SAIF.Business.EPay.USBank\RealTimeNonPaymentNotification.vbBusiness\SAIF.Business.EPay.USBank\RemittanceDocument.vbBusiness\SAIF.Business.EPay.USBank\RemittedPayment.vbBusiness\SAIF.Business.EPay.USBank\Enums.vb