WindowsService - Structure Analysis

Executive Summary

The Psyter Payment Inquiry Service is a well-structured Windows Service with clear separation of concerns across Data Access Layer (DAL), Data Transfer Objects (DTOs), and service logic. The architecture follows traditional layered patterns with timer-based background processing for payment reconciliation and notification delivery.

Directory Structure

WindowsService/
├── PsyterPaymentInquiry/              # Main service project
│   ├── DAL/                           # Data Access Layer
│   │   ├── DBConstants.cs             # 14 stored procedure constants
│   │   ├── DBHelper.cs                # Base class with data mapping utilities
│   │   ├── PaymentDataAccess.cs       # 11 data access methods
│   │   └── XmlHelper.cs               # XML serialization helper
│   ├── DTO/                           # Data Transfer Objects
│   │   ├── AppConfigSetting.cs        # Application configuration models
│   │   ├── FCMNotificationModal.cs    # 6 notification/reminder models
│   │   ├── InquiryPayment.cs          # 11 payment processing models
│   │   ├── PendingPaymentModal.cs     # 5 pending payment models
│   │   └── PsyterAPIAuth.cs           # API authentication models
│   ├── Properties/
│   │   └── AssemblyInfo.cs            # Assembly metadata
│   ├── App.config                     # Configuration (DB, APIs, URLs)
│   ├── packages.config                # NuGet dependencies
│   ├── PaymentInquiryService.cs       # Core service logic (1000+ lines)
│   ├── PaymentInquiryService.Designer.cs
│   ├── Program.cs                     # Service entry point
│   ├── ProjectInstaller.cs            # Windows Service installer
│   ├── ProjectInstaller.Designer.cs
│   └── ProjectInstaller.resx
├── Psyter Payment Inquiry Service/    # Installer project
│   ├── Psyter Payment Inquiry Service.aip  # Advanced Installer project
│   └── Setup Files/
├── packages/                          # NuGet package binaries
│   ├── Microsoft.Practices.EnterpriseLibrary.Common.dll.3.1.0/
│   ├── Microsoft.Practices.EnterpriseLibrary.Data.dll.3.1.0/
│   ├── Microsoft.Practices.ObjectBuilder.dll.3.1.0/
│   └── Newtonsoft.Json.13.0.1/
└── PsyterPaymentInquiry.sln          # Visual Studio solution file

Architecture Overview

Layered Architecture

┌─────────────────────────────────────────────────┐
│         Windows Service Host                     │
│                                                   │
│  ┌────────────────────────────────────────────┐ │
│  │      PaymentInquiryService                 │ │
│  │                                            │ │
│  │  ┌──────────┐  ┌──────────┐  ┌─────────┐ │ │
│  │  │  Timer1  │  │  Timer2  │  │ Timer3  │ │ │
│  │  │ Payment  │  │   FCM    │  │ SCHFS   │ │ │
│  │  │  (10m)   │  │  (10m)   │  │  (24h)  │ │ │
│  │  └────┬─────┘  └────┬─────┘  └────┬────┘ │ │
│  │       │             │             │       │ │
│  │       v             v             v       │ │
│  │  ┌──────────────────────────────────────┐│ │
│  │  │     Thread Management Layer          ││ │
│  │  └────────────────┬─────────────────────┘│ │
│  │                   │                       │ │
│  │                   v                       │ │
│  │  ┌──────────────────────────────────────┐│ │
│  │  │     Business Logic Layer             ││ │
│  │  │  - Payment Inquiry                   ││ │
│  │  │  - Refund Processing                 ││ │
│  │  │  - Notification Sending              ││ │
│  │  │  - Secure Hash Generation            ││ │
│  │  └────────────────┬─────────────────────┘│ │
│  └─────────────────────┼──────────────────────┘ │
└────────────────────────┼────────────────────────┘
                         │
         ┌───────────────┼───────────────┐
         │               │               │
         v               v               v
┌─────────────────┐ ┌─────────────┐ ┌──────────────┐
│  Data Access    │ │  External   │ │   File I/O   │
│     Layer       │ │   APIs      │ │   (Logging)  │
│                 │ │             │ │              │
│ ┌─────────────┐ │ │ ┌─────────┐ │ │ ┌──────────┐ │
│ │PaymentData  │ │ │ │ Psyter  │ │ │ │   Logs/  │ │
│ │  Access     │ │ │ │   API   │ │ │ │  *.txt   │ │
│ └─────────────┘ │ │ └─────────┘ │ │ └──────────┘ │
│ ┌─────────────┐ │ │ ┌─────────┐ │ │              │
│ │  DBHelper   │ │ │ │Scheduling│ │ │              │
│ │             │ │ │ │   API   │ │ │              │
│ └─────────────┘ │ │ └─────────┘ │ │              │
│ ┌─────────────┐ │ │ ┌─────────┐ │ │              │
│ │ XmlHelper   │ │ │ │ Payment │ │ │              │
│ │             │ │ │ │ Gateway │ │ │              │
│ └─────────────┘ │ │ └─────────┘ │ │              │
└─────────────────┘ └─────────────┘ └──────────────┘
         │
         v
┌─────────────────────────────────┐
│      SQL Server Database         │
│                                  │
│  - Pending Payment Records       │
│  - App Configuration Settings    │
│  - User Notifications            │
│  - Appointment Reminders         │
│  - Payment Transaction History   │
└─────────────────────────────────┘

Component Interaction Flow

Service Start
    │
    ├──> Initialize 4 Timers
    │       │
    │       ├──> timer (Payment Inquiry/Refund) - 10 minutes
    │       ├──> timerForDeleteLogFiles - 15 days
    │       ├──> timerNotifySCHFSCardExpiry - 24 hours
    │       └──> timerSendFCMNotification - 10 minutes
    │
    └──> Write startup logs
         │
         └──> Wait for timer events
              │
              ├──> OnElapsedTime() 
              │       │
              │       └──> CreateThread()
              │               │
              │               └──> GetPendingPayment()
              │                       ├──> Process Booking Payments
              │                       ├──> Process Refunds
              │                       ├──> Process Wallet Purchases
              │                       └──> Process Package Purchases
              │
              ├──> OnElapsedTimeForFCMNotificationsAndReminders()
              │       │
              │       └──> CreateThreadForSendFCMNotificationsAndReminders()
              │               │
              │               └──> GetPendingFCMNotificationsAndReminders()
              │
              ├──> OnElapsedTimeNotifySCHFSExpiry()
              │       │
              │       └──> CallNotifySCHFSExpiryAPI()
              │
              └──> OnElapsedTime30Days()
                      │
                      └──> DeleteLogFilesOfPreviousMonth()

Data Access Layer (DAL)

DBHelper.cs

Purpose: Base database helper class with generic data mapping utilities

Key Features:
- Enterprise Library Database wrapper
- Generic DataTable to Object/List mapping
- Query string parsing utility
- Uses reflection for automatic property mapping

Methods:

+ MapDataTableToList<T>(DataTable) : IList<T>
+ MapDataTableToObject<T>(DataTable) : T
+ ParseQueryString(string) : NameValueCollection

Extension Methods:

DataRowExtention.Fill<T>(DataRow, ref T obj)

PaymentDataAccess.cs

Purpose: Concrete implementation for payment-related database operations

Methods (11 total):

Method Stored Procedure Purpose
GETPendingPayments() ws_GetPendingPaymentsList_AppConfigSetting Fetch pending booking payments
GETPendingForRefundPayments() ws_GetPendingPaymentsListForRefund_AppConfigSetting Fetch pending refund requests
GETPendingWalletPurchasePayments() ws_GetPendingWalletPurchasesList_AppConfigSetting Fetch pending wallet recharges
GETPendingPackagePurchasePayments() ws_GetPendingPackagePaymentsList_AppConfigSetting Fetch pending package purchases
UpdateBookingOrderPayForData() ws_UpdatePaymentInquiryStatus Update booking payment status
UpdateBookingRefundStatus() ws_UpdatePendingPaymentRefundStatus Update refund status
UpdateWalletPurchasePayForData() ws_UpdateWalletPurchasePaymentInquiryStatus Update wallet payment status
UpdatePackagePurchasePayForData() ws_UpdatePackagePaymentInquiryStatus Update package payment status
GetPsyterApplicationToken() AppConfig_GetAppConfigSettingsByGroupId Retrieve API authentication token
GetPendingFCMNotificationsAndRemindersToSend() Notification_GetNotificationsListToSentUsingFCM Fetch pending notifications
MarkFCMNotificationSent() Notification_UpdateNotificationSentStatus Mark notification as sent
MarkReminderSent() Reminder_UpdateReminderSentStatus Mark reminder as sent
GetUserRemindersList() Reminder_GetUserReminderList Get user’s reminder list

Return Patterns:
- Complex objects with nested lists
- Uses DataSet with multiple tables
- Returns boolean for update operations
- Includes output parameters for status codes

DBConstants.cs

Purpose: Centralized stored procedure name constants

Constants (14 total):

GET_PENDING_PAYMENTS
GET_PENDING_REFUND_PAYMENTS
GET_PENDING_WALLET_PURCHASE_PAYMENTS
GET_PENDING_PACKAGE_PURCHASE_PAYMENTS
UPDATE_PENDING_PAYMENTS_STATUS
UPDATE_PENDING_REFUND_PAYMENTS_STATUS
UPDATE_WALLET_PURCHASE_PENDING_PAYMENTS_STATUS
UPDATE_PACKAGE_PURCHASE_PENDING_PAYMENTS_STATUS
GET_APPLICATION_CONFIG_BY_GROUP_ID
GET_PENDING_NOTIFICATIONS_FOR_FCM
UPDATE_NOTIFICATIONS_SENT_STATUS
UPDATE_REMINDER_SENT_STATUS
GET_USER_REMINDERS_LIST

XmlHelper.cs

Purpose: XML serialization utilities for database parameters

Usage Pattern:

var xml = XmlHelper.ObjectToXml(updateBookingPayForDataObj);
dataBase.AddInParameter(dbCommand, "@PaymentData", DbType.Xml, xml);

Data Transfer Objects (DTOs)

Payment Processing Models (InquiryPayment.cs)

11 Models:

  1. RequestRefund - Refund request parameters
  2. RequestSecureHash - Secure hash generation input
  3. SecureHashResponse - Generated hash output
  4. RequestProcessInquiry - Payment inquiry/refund request
  5. ProcessResponse - Gateway response wrapper
  6. UpdateScheduleBookingStatusRequest - Booking status update request
  7. UpdateBookingStatus - Individual booking status update
  8. BookingStatusUpdateResponseWrapper - API response wrapper
  9. BookingStatusUpdateResponse - Update response data
  10. BookingStatusUpdateInfoResponse - Individual update result
  11. ApplicationConfiguration - App config setting model

Pending Payment Models (PendingPaymentModal.cs)

5 Models:

  1. GetPendingPaymentsListResponse - Database query result wrapper

    + List<PendingPayment> PendingPaymentsList
    + List<ApplicationConfiguration> AppConfigSettingList
    + string ApplicationAPIToken
    

  2. PendingPaymentResponse - Service layer response

    + List<PendingPayment> PendingPaymentsList
    + PaymentApplicationConfiguration AppConfigSetting
    

  3. PendingPayment - Individual pending payment details

    + TransactionId, OrderId, PayForDataId
    + SlotBookingId, ConsumerId, PhysicianId
    + TotalAmount, PaymentStatus, InquiryCount
    + UserWalletId, ClientPackageMainId
    

  4. UpdateBookingOrderPayForData - Payment update parameters

    + Card details (name, number, expiry)
    + Gateway response (name, status codes, RRN)
    + Status codes and descriptions
    

  5. UpdateBookingRefundRequestData - Refund update parameters

FCM Notification Models (FCMNotificationModal.cs)

6 Models:

  1. UserNotification - Simple notification

    + Id, ForUserLoginInfoId
    + NotificationTitle, NotificationBody
    + FCMTopic
    

  2. UserReminder - Appointment reminder

    + Reminder details (title, text, datetime)
    + Booking information (SlotBookingId, VideoSDKMeetingId)
    + Patient details (name, image, ID)
    + Provider details (name, image, ID)
    + CatCommunicationTypeId
    

  3. UserReminderForFCMPayLoad - Reminder list item for FCM

  4. FCMConfiguration - FCM API settings
  5. UserNotificationsListWrapper - Notification query result
  6. SendCustomFCMNotification - FCM send request

API Authentication Models (PsyterAPIAuth.cs)

Model:

public class APIAuthTokenResponse
{
    public string AccessToken { get; set; }
    public string RefreshToken { get; set; }
    public string TokenExpiresIn { get; set; }
}

Configuration Models (AppConfigSetting.cs)

Model:

public class PaymentApplicationConfiguration
{
    + SmartRoutingSecretKey
    + SmartRoutingResponseBackURL
    + RedirectToPaymentMobileToken
    + SmartRoutingRedirectURL
    + SmartRoutingMerchantId
    + SmartRoutingCurrencyISOCode
    + SmartRoutingRefundInquiryUrl
    + SmartRoutingThemeId
    + SmartRoutingVersion
    + SmartRoutingItemId
}

Service Implementation (PaymentInquiryService.cs)

Class Structure

Timers (4):

System.Timers.Timer timer                           // Payment inquiry/refund
System.Timers.Timer timerForDeleteLogFiles          // Log cleanup
System.Timers.Timer timerNotifySCHFSCardExpiry      // SCHFS notifications
System.Timers.Timer timerSendFCMNotification        // FCM notifications

Threads (4):

Thread RefundAndInquiryThread
Thread DeleteLogFilesThread
Thread NotifySCHFSCardExpiryThread
Thread SendFCMNotifications

Properties:

protected string PsyterAPIApplicationToken
protected string PsyterAPIAuthToken
protected string SchedulingAPIApplicationToken
protected string SchedulingAPIAuthToken

Key Methods

Service Lifecycle

OnStart(string[] args)
  - Initialize timers with intervals
  - Enable all timers
  - Write startup logs

OnStop()
  - Write shutdown logs

Timer Event Handlers

OnElapsedTime(object, ElapsedEventArgs)
  - 10-minute interval
  - Creates RefundAndInquiryThread
  - Processes payments and refunds

OnElapsedTime30Days(object, ElapsedEventArgs)
  - 15-day interval
  - Creates DeleteLogFilesThread
  - Deletes logs older than 30 days

OnElapsedTimeNotifySCHFSExpiry(object, ElapsedEventArgs)
  - 24-hour interval
  - Creates NotifySCHFSCardExpiryThread
  - Calls SCHFS expiry notification API

OnElapsedTimeForFCMNotificationsAndReminders(object, ElapsedEventArgs)
  - 10-minute interval
  - Creates SendFCMNotifications thread
  - Sends pending notifications/reminders

Thread Management

CreateThread()
  - Checks if RefundAndInquiryThread is null or terminated
  - Creates new thread if needed
  - Logs thread state

CreateThreadForDeleteLogFiles()
CreateThreadForNotifySCHFSExpiry()
CreateThreadForSendFCMNotificationsAndReminders()
  - Similar pattern for specialized threads

Payment Processing

GetPendingPayment() : async Task<PendingPaymentResponse>
  - Fetch pending payments from DB
  - Retrieve payment gateway config
  - Loop through each payment:
    + Generate secure hash
    + Send inquiry to gateway
    + Parse response
    + Update database
    + Update booking status if successful
  - Call GetPendingRefundPayment()
  - Call GetPendingWalletPurchasedPayment()
  - Call GetPendingPackagePurchasedPayment()

GetPendingRefundPayment() : async Task<PendingPaymentResponse>
  - Fetch pending refunds
  - Generate refund transaction IDs
  - Process refunds through gateway
  - Send refund notifications

GetPendingWalletPurchasedPayment() : async Task<PendingPaymentResponse>
  - Process wallet recharge inquiries

GetPendingPackagePurchasedPayment() : async Task<PendingPaymentResponse>
  - Process package purchase inquiries

Security & Gateway Integration

GenerateSecureHash(RequestSecureHash, PaymentApplicationConfiguration) : SecureHashResponse
  - Build sorted dictionary of parameters
  - Create ordered string with secret key
  - Compute SHA256 hash
  - Return hex-encoded hash

ProcessInquiryOrRefund(RequestProcessInquiry, PaymentApplicationConfiguration, PendingPayment) : async Task<ProcessResponse>
  - Build NameValueCollection for gateway request
  - POST to payment gateway
  - Parse response
  - Update database based on status

Status Update Methods

UpdatePaymentInquiryStatus(RequestProcessInquiry, SortedDictionary, PendingPayment) : async Task
  - Build UpdateBookingOrderPayForData object
  - Authenticate with Scheduling API
  - If successful (00000):
    + Update booking status to "Booked" (status 1)
  - If failed after 3 attempts:
    + Cancel booking (status 8)
  - Update PayForData record

UpdateBookingRefundRequestData(...)
  - Update refund status
  - Send refund notification

UpdateWalletPurchasePaymentInquiryStatus(...)
  - Update wallet purchase status

UpdatePackagePurchasePaymentInquiryStatus(...)
  - Update package purchase status

API Integration

PsyterApiAuthenticationToken(string) : async Task<APIAuthTokenResponse>
  - Authenticate with Psyter API
  - Return access token, refresh token, expiry

SchedulingApiAuthenticationToken(string) : async Task<APIAuthTokenResponse>
  - Authenticate with Scheduling API

UpdateBookingStatusInScheduling(string) : async Task<JObject>
  - Call Scheduling API to update booking status
  - Return response as JObject

CallRefundNotificationAPI(string) : async Task<JObject>
  - Send refund notification via Psyter API

CallNotifySCHFSExpiryAPI() : async Task
  - Authenticate with Psyter API
  - Call SCHFS card expiry notification endpoint

CallSendFCMNotificationCommonAPI(string, string) : async Task
  - Send FCM notification via Psyter API
  - Used for appointment reminders

Notification Processing

GetPendingFCMNotificationsAndReminders() : void
  - Fetch pending notifications/reminders from DB
  - For each reminder:
    + Build FCM payload with user/booking details
    + Call CallSendFCMNotificationCommonAPI()
    + Mark as sent in database
  - Handles both patient (UserType=1) and provider (UserType=0) reminders

Utility Methods

WriteToFile(string Message, string logType) : void
  - Create Logs directory if not exists
  - Create daily log file if not exists
  - Append message with timestamp

DeleteLogFilesOfPreviousMonth() : void
  - Get all files in Logs directory
  - Delete files older than 30 days
  - Skip DeleteFileLog files
  - Log each deletion

AllwaysGoodCertificate(...) : bool
  - Accept all SSL certificates (for development)
  - Returns true for all certificates

Business Logic Flow

Payment Inquiry Flow

Timer (10 min) → OnElapsedTime()
                      ↓
                 CreateThread()
                      ↓
              GetPendingPayment()
                      ↓
    ┌─────────────────┴─────────────────┐
    │                                    │
    │  1. Fetch from DB:                │
    │     - PendingPaymentsList          │
    │     - AppConfigSettingList         │
    │     - ApplicationAPIToken          │
    │                                    │
    │  2. For each pending payment:     │
    │     ┌──────────────────────────┐  │
    │     │ Generate Secure Hash     │  │
    │     │   - MESSAGE_ID = "2"     │  │
    │     │   - TRANSACTION_ID       │  │
    │     │   - SHA256 calculation   │  │
    │     └──────────┬───────────────┘  │
    │                ↓                   │
    │     ┌──────────────────────────┐  │
    │     │ Call Payment Gateway     │  │
    │     │   - POST to inquiry URL  │  │
    │     │   - Send secure hash     │  │
    │     └──────────┬───────────────┘  │
    │                ↓                   │
    │     ┌──────────────────────────┐  │
    │     │ Parse Response           │  │
    │     │   - StatusCode           │  │
    │     │   - StatusDescription    │  │
    │     │   - Card details         │  │
    │     └──────────┬───────────────┘  │
    │                ↓                   │
    │     ┌──────────────────────────┐  │
    │     │ Update Database          │  │
    │     │   - XML serialization    │  │
    │     │   - Update PayForData    │  │
    │     └──────────┬───────────────┘  │
    │                ↓                   │
    │     ┌──────────────────────────┐  │
    │     │ If StatusCode = 00000    │  │
    │     │   → Authenticate API     │  │
    │     │   → Update Booking       │  │
    │     │     Status = Booked (1)  │  │
    │     └──────────┬───────────────┘  │
    │                ↓                   │
    │     ┌──────────────────────────┐  │
    │     │ If InquiryCount >= 3     │  │
    │     │   → Cancel Booking (8)   │  │
    │     └──────────────────────────┘  │
    │                                    │
    └────────────────────────────────────┘
                      ↓
         GetPendingRefundPayment()
                      ↓
    GetPendingWalletPurchasedPayment()
                      ↓
    GetPendingPackagePurchasedPayment()

Refund Processing Flow

GetPendingRefundPayment()
         ↓
┌────────────────────────────────────┐
│ 1. Fetch pending refunds from DB  │
│                                    │
│ 2. For each refund:               │
│    ┌────────────────────────────┐ │
│    │ Generate New Transaction   │ │
│    │   - "PSY" + Timestamp      │ │
│    │   - Amount in cents        │ │
│    └────────┬───────────────────┘ │
│             ↓                      │
│    ┌────────────────────────────┐ │
│    │ Generate Secure Hash       │ │
│    │   - MESSAGE_ID = "4"       │ │
│    │   - TRANSACTION_ID (new)   │ │
│    │   - AMOUNT, CURRENCY       │ │
│    │   - Original TX ID         │ │
│    └────────┬───────────────────┘ │
│             ↓                      │
│    ┌────────────────────────────┐ │
│    │ POST to Payment Gateway    │ │
│    │   - Refund endpoint        │ │
│    └────────┬───────────────────┘ │
│             ↓                      │
│    ┌────────────────────────────┐ │
│    │ Parse Response             │ │
│    └────────┬───────────────────┘ │
│             ↓                      │
│    ┌────────────────────────────┐ │
│    │ Update Refund Status in DB │ │
│    └────────┬───────────────────┘ │
│             ↓                      │
│    ┌────────────────────────────┐ │
│    │ If StatusCode = 00000      │ │
│    │   → Authenticate Psyter API│ │
│    │   → Send Refund Notification│ │
│    │     to Patient & Provider  │ │
│    └────────────────────────────┘ │
│                                    │
└────────────────────────────────────┘

FCM Notification Flow

Timer (10 min) → OnElapsedTimeForFCMNotificationsAndReminders()
                           ↓
          CreateThreadForSendFCMNotificationsAndReminders()
                           ↓
         GetPendingFCMNotificationsAndReminders()
                           ↓
         ┌─────────────────────────────────────┐
         │ Fetch from DB:                      │
         │   - UserNotificationsList           │
         │   - UserRemindersList               │
         │   - FCMConfiguration                │
         └──────────────┬──────────────────────┘
                        ↓
         ┌──────────────────────────────────────┐
         │ For each reminder:                   │
         │  ┌────────────────────────────────┐  │
         │  │ Determine User Type            │  │
         │  │   UserType=1 → Patient         │  │
         │  │   UserType=0 → Provider        │  │
         │  └──────────┬─────────────────────┘  │
         │             ↓                         │
         │  ┌────────────────────────────────┐  │
         │  │ Get User's Reminder List       │  │
         │  │   (all reminders for booking)  │  │
         │  └──────────┬─────────────────────┘  │
         │             ↓                         │
         │  ┌────────────────────────────────┐  │
         │  │ Build FCM Payload              │  │
         │  │   - NotificationType = 12      │  │
         │  │   - Booking details            │  │
         │  │   - User/Provider info         │  │
         │  │   - Reminder list              │  │
         │  │   - Video meeting ID           │  │
         │  └──────────┬─────────────────────┘  │
         │             ↓                         │
         │  ┌────────────────────────────────┐  │
         │  │ Authenticate Psyter API        │  │
         │  └──────────┬─────────────────────┘  │
         │             ↓                         │
         │  ┌────────────────────────────────┐  │
         │  │ POST to Psyter API             │  │
         │  │   /Notification/               │  │
         │  │     SendNotificationWithCustomData│ │
         │  └──────────┬─────────────────────┘  │
         │             ↓                         │
         │  ┌────────────────────────────────┐  │
         │  │ Mark Reminder as Sent          │  │
         │  │   - Update DB status           │  │
         │  │   - Create notification log    │  │
         │  └────────────────────────────────┘  │
         └──────────────────────────────────────┘

Configuration Management

App.config Structure

<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
  </startup>

  <appSettings>
    <!-- API Base URLs -->
    <add key="PsyterAPIBaseURL" value="..." />
    <add key="SchedulingAPIBaseURL" value="..." />
  </appSettings>

  <connectionStrings>
    <!-- Database Connection -->
    <add name="PsyterDatabase" 
         connectionString="..." 
         providerName="System.Data.SqlClient"/>
  </connectionStrings>
</configuration>

Database Configuration

Retrieved from Database:
- Payment gateway settings (Smart Routing)
- API authentication tokens
- FCM configuration

Stored in AppConfigSettings table:

SmartRoutingSecretKey
SmartRoutingResponseBackURL
RedirectToPaymentMobileToken
SmartRoutingRedirectURL
SmartRoutingMerchantId
SmartRoutingCurrencyISOCode
SmartRoutingRefundInquiryUrl
SmartRoutingThemeId
SmartRoutingVersion
SmartRoutingItemId

Integration Points

External Systems

  1. Psyter API (https://dvx.innotech-sa.com/Psyter/Master/APIs/)
    - Authentication (/Authenticate)
    - Refund notifications (/Notification/SendRefundBookingNotification)
    - FCM notifications (/Notification/SendNotificationWithCustomData)
    - SCHFS expiry (/Notification/NotifySCHFSCardExpiry)

  2. Scheduling API (https://dvx.innotech-sa.com/Scheduling/SchedulingAPI/)
    - Authentication (/Authenticate)
    - Booking status updates (/api/Schedule/UpdateBookingStatus)

  3. Payment Gateway (Smart Routing)
    - Inquiry/Refund endpoint (configured in DB)
    - Merchant authentication
    - Secure hash verification

  4. SQL Server Database
    - 14 stored procedures
    - Connection via Enterprise Library

Data Flow

┌──────────────────┐
│  Windows Service │
└────────┬─────────┘
         │
         ├─────────────────────────────────┐
         │                                 │
         v                                 v
┌─────────────────┐              ┌──────────────────┐
│  SQL Server DB  │              │  External APIs   │
│                 │              │                  │
│  - Pending      │              │  - Psyter API    │
│    Payments     │              │  - Scheduling    │
│  - Config       │              │  - Payment       │
│  - Notifications│              │    Gateway       │
└─────────────────┘              └──────────────────┘
         │                                 │
         │                                 │
         └────────────┬────────────────────┘
                      │
                      v
         ┌────────────────────────┐
         │   Updated Records:     │
         │  - Payment Status      │
         │  - Booking Status      │
         │  - Notification Logs   │
         └────────────────────────┘

Error Handling Patterns

Thread Safety

  • Single thread per operation type
  • Thread state checking before creation
  • Prevents concurrent execution of same task

Database Error Handling

  • Try-catch blocks around all DB operations
  • Exception logging to file
  • Output parameters for status codes
  • Boolean return values for success/failure

API Error Handling

  • Try-catch around all HTTP calls
  • SSL certificate bypass for development
  • Authentication token refresh on each cycle
  • Response parsing with null checks

Logging Strategy

  • Separate log files per operation type
  • Timestamped entries
  • Exception details captured
  • Daily log file creation
  • 30-day retention policy

Security Architecture

Secure Hash Generation (SHA256)

// Build sorted dictionary
SortedDictionary<string, string> dictionary = ...

// Create ordered string
StringBuilder orderedString = new StringBuilder();
orderedString.Append(SECRECT_KEY);
foreach (KeyValuePair<string, string> kv in dictionary)
{
    orderedString.Append(kv.Value);
}

// Compute SHA256
byte[] bytes = Encoding.UTF8.GetBytes(orderedString.ToString());
SHA256 sha256 = SHA256Managed.Create();
byte[] hash = sha256.ComputeHash(bytes);

// Convert to hex string
string secureHash = string.Join("", hash.Select(x => x.ToString("x2")));

Authentication Flow

Service Method
     ↓
Check if [API]AuthToken is null
     ↓
Call [API]AuthenticationToken()
     ↓
POST to /Authenticate endpoint
     - applicationtoken
     - grant_type=password
     ↓
Parse JObject response
     - access_token
     - refresh_token
     - expires_in
     ↓
Store token in service property
     ↓
Use token in subsequent API calls
     - Authorization: Bearer {token}

Sensitive Data Handling

Stored in App.config (Plaintext):
- Database credentials
- API base URLs

Stored in Database:
- Payment gateway secret key
- Merchant ID
- API tokens

Not Persisted:
- API access tokens (memory only)
- Card details (logged but not stored)

Performance Characteristics

Timer-Based Processing

Operation Frequency Typical Duration
Payment Inquiry 10 minutes 5-30 seconds
Refund Processing 10 minutes 5-30 seconds
FCM Notifications 10 minutes 10-60 seconds
SCHFS Expiry 24 hours 1-5 seconds
Log Cleanup 15 days 1-10 seconds

Scalability Considerations

Current Limitations:
- Single-threaded per operation type
- Sequential processing of pending items
- No batch database operations
- Token refresh on every cycle

Scalability Patterns Used:
- Thread pooling (via Thread class)
- Timer-based scheduling
- Asynchronous API calls (async/await)
- Connection pooling (Enterprise Library)

Code Metrics

Lines of Code

Component LOC (approx)
PaymentInquiryService.cs 1,000+
PaymentDataAccess.cs 250
DBHelper.cs 120
DTOs (all) 300
Total ~1,670

Complexity Indicators

  • Methods: 35+ across all classes
  • Stored Procedures: 14
  • Models: 20+
  • Timers: 4
  • Threads: 4
  • External APIs: 3
  • Database Tables: 10+ (estimated)

Dependencies

NuGet Packages: 4
- Enterprise Library (3 packages)
- Newtonsoft.Json

Framework: .NET Framework 4.8

External Services: 3
- Psyter API
- Scheduling API
- Payment Gateway

Deployment Structure

Installation Directory/
├── PsyterPaymentInquiry.exe          # Service executable
├── PsyterPaymentInquiry.exe.config   # Configuration
├── *.dll                             # Dependencies
│   ├── Microsoft.Practices.EnterpriseLibrary.Common.dll
│   ├── Microsoft.Practices.EnterpriseLibrary.Data.dll
│   ├── Microsoft.Practices.ObjectBuilder.dll
│   └── Newtonsoft.Json.dll
└── Logs/                             # Created at runtime
    ├── ServiceLog_Inquiry_[Date].txt
    ├── ServiceLog_Refund_[Date].txt
    ├── ServiceLog_NotifySCHFSCardExpiry_[Date].txt
    ├── ServiceLog_DeleteFileLog_[Date].txt
    └── ServiceLog_SendFCMNotificationAndReminders_[Date].txt

Maintenance Points

Regular Monitoring

  1. Service Status: Verify service is running
  2. Log Files: Review for errors/exceptions
  3. Database: Check pending payment counts
  4. API Connectivity: Ensure external APIs are accessible

Update Procedures

  1. Stop service
  2. Backup current binaries
  3. Deploy new version
  4. Update App.config if needed
  5. Start service
  6. Monitor logs

Troubleshooting Areas

  1. Database Connection: Enterprise Library database factory
  2. API Authentication: Token generation and refresh
  3. Thread Management: Thread state and lifecycle
  4. Payment Gateway: Secure hash generation and response parsing

Analysis Date: November 10, 2025
Analyzed By: AI Code Auditor
Service Version: Current production version