Payment System Architecture and Integration in Apps and Games

Lecture



Integrating payment systems on web, mobile and desktop platforms requires accounting for a range of technical and business aspects: from the choice of API and payment methods to ensuring security and user convenience. In practice, the key differences relate to UX, security (PCI DSS, HTTPS, tokenization) and support for local payment methods.

Integrating payment systems into applications is not just about «accepting money», but also about properly organizing the payment lifecycle, the roles of the participants, subscriptions, recurring charges, refunds, access restoration and error handling. Below are the main aspects.

General integration considerations

  • Choosing a provider: fees (2.5–4%), card/wallet support, geography, API quality.

  • APIs and SDKs: Stripe, PayPal, Adyen, YooKassa and Robokassa provide ready-made libraries for popular languages.

  • Webhooks/IPN: asynchronous notifications about transaction status.

  • Security: HTTPS, card tokenization, verification of notification signatures, storing keys in secure vaults.

  • Testing: sandbox environments, verification of successful/failed payments and refunds.

Web applications

  • UX: minimizing the number of steps to payment, support for «one-click payment».

  • Integration: RESTful API, redirect to a payment page or embedded forms.

  • Examples: Stripe Checkout, PayPal Smart Buttons.

  • Consideration: it is important to account for cross-browser compatibility and a responsive interface.

Mobile applications

  • SDKs: ready-made libraries for iOS/Android (Stripe SDK, PayPal Mobile SDK).

  • UX: Apple Pay, Google Pay, biometric authentication.

  • Consideration: integration with system APIs for a seamless experience (Face ID, Touch ID).

  • Risks: the need for strict control over the storage of tokens and keys on the device.

Desktop applications

  • Integration: via embedded browser components (WebView) or direct API calls.

  • Examples: enterprise ERP systems with a payment module.

  • Consideration: more common in the B2B segment, where reporting and transaction control matter.

  • Risks: SDK updates and OS compatibility.

Comparison table

Platform UX Integration Specifics
Web One-click payment, redirect REST API, webhooks Cross-browser support
Mobile Apple Pay, Google Pay, biometrics SDKs for iOS/Android Integration with system APIs
Desktop Less critical WebView, API B2B orientation, reporting

These problems need to be solved at the architecture level:

  • Checkout Snapshot
  • Order Draft
  • Cart Locking
  • Optimistic Locking
  • Checkout Race Condition
  • TOCTOU (Time Of Check To Time Of Use)

Cart Lockout
These directly describe the problem: the user has started checkout, but in the meantime the cart may change, or even two checkout processes may start simultaneously. The solution is a combination of cart versioning (optimistic locking) and moving the cart into the SUBMISSION_IN_PROGRESS state.

During checkout it would be dangerous if the user could make changes to their cart. They could change prices or other important information, which would let them complete checkout in a way that should not have been possible (for example, overpaying or underpaying, skipping a validation step, and so on). In addition, multiple checkout processes could be started simultaneously for a single cart, which would lead to a failure because they compete for the same resources, or potentially even to charging the user multiple times.

To prevent this, Broadleaf uses an implicit locking mechanism whereby users lose control over their cart during checkout. This is achieved through a combination of optimistic locking (see Cart Versioning) and a change of cart status (see Cart Statuses).

Thanks to optimistic locking, we know that the state of the cart in the database will never be overwritten by a stale version. This helps guarantee that if multiple or duplicate requests to modify the cart arrive, only one of them will succeed and the cart state will remain valid. The status change to SUBMISSION_IN_PROGRESS, which happens at the first stage of the checkout process, effectively takes control of the cart away from the user, and only the currently running checkout process should be able to make changes to it. If multiple checkout processes are started, only one of the write operations (and checkout processes) will succeed thanks to optimistic locking. The combination of optimistic locking and the change of ownership guarantees that:

  1. Only one checkout process will run at a time for a single cart.

  2. Users cannot change the contents of the cart during checkout.

Also useful:

Stripe — Dynamically update line items
Stripe writes separately about inventory checks and dynamically changing the composition of an order during a Checkout Session. This shows that the cart and the payment session are treated as different entities.

To understand the race problem itself:

Race Condition / TOCTOU
The classic description of the situation "checked the data → the data changed → used a stale result". This is exactly what can happen between creating a payment session and finalizing the order.

Risks and challenges

  • Regulatory requirements: PCI DSS, PSD2, GDPR.

  • Multi-currency support: support for local payment methods.

  • Security: tokenization, mutual API authentication.

  • Conversion optimization: fewer steps, saved cards, «one-click payment».

1) Integration options

  • Redirect — the user is redirected to the provider's page (PayPal, YooKassa). Simple and secure, but the UX is worse.

  • Embedded forms — an iframe or JS widget on the site. Convenient, but requires protection against XSS.

  • API/SDK — direct interaction with the provider's server. Flexible, but with higher PCI DSS requirements.

  • Native methods — Apple Pay, Google Pay, Samsung Pay. The most convenient UX on mobile.

2) Workflow sequence

  1. Payment initiation — the customer selects a payment method.

  2. Transaction creation — the server generates an order and sends a request to the payment gateway.

  3. Authentication — 3-D Secure, biometrics, tokenization.

  4. Processing — the gateway checks the card, balance and limits.

  5. Notification — the status (success, decline, refund) arrives via webhook/IPN.

  6. Order update — the server changes the status and executes business logic (subscription activation, delivery).

3) The impact of data context on transaction declines

  • False negatives — a genuine payment is declined. Causes: suspicious patterns, bank limits, validation errors.

  • False positives — a fraudulent payment is accepted. Causes: weak anti-fraud rules, insufficient data.

  • How to improve:

    • Use anti-fraud systems (Riskified, Sift).

    • Apply machine learning to analyze patterns.

    • Configure dynamic rules: limits by country, IP and device.

    • Introduce multi-factor authentication (SMS, push, biometrics).

4) Verifying webhook authenticity

  • Why: to make sure the notification came from the payment provider and not from an attacker.

  • Verification methods:

    • HMAC signature — the provider signs the payload with a secret key.

    • Certificates — verification of TLS and root certificates.

    • IP allowlist — accept requests only from trusted addresses.

    • Re-validation — the server makes a request back to the provider's API to confirm the transaction.

When integrating payment systems, design and the brand book play a key role: the payment interface must be visually consistent with the company's corporate style in order to increase trust and conversion, while still complying with the provider's requirements (for example, Yandex Pay or Apple Pay) regarding the use of their logos and elements.

5) Design requirements

  • Brand consistency: colors, fonts and logos must match the main site or application. This reduces the feeling of a «foreign» interface and increases trust.

  • UX and simplicity: minimizing steps, clear buttons («Pay», «Confirm»), no unnecessary forms.

  • Localization: support for the languages and currencies relevant to the target audience.

  • Responsiveness: correct rendering on mobile phones, tablets and desktops.

Brand book requirements

  • Logo usage rules: for example, Yandex Pay requires the payment button to carry the branded badge and not be altered in color or shape.

  • Interface elements: buttons, badges and popups must be embedded strictly according to the guidelines (size, padding, placement).

  • A unified experience: the brand book requires the user to see the same payment scenario across the different sites and applications where the system is used.

  • No modifications allowed: you may not change the brand colors or add shadows or animations to payment system logos.

Comparison of approaches

Approach Pros Cons
Full customization (own gateway) Full control over design, UX in the company's style High security requirements, PCI DSS
BaaS platforms Seamless integration under the company's brand, ready-made infrastructure Functional limitations, dependence on the provider
Ready-made SDKs/widgets Fast integration, compliance with the provider's brand book Less design freedom, mandatory elements

Risks and challenges

  • Failure to follow the brand book may result in certification being refused or the integration being blocked.

  • Reduced trust: if the design of the payment page differs sharply from the main site, users may suspect fraud.

  • Legal requirements: using someone else's logos without consent violates the rules and may lead to fines.

6) Payment initiators

1. Who initiates the payment

The customer (Customer-Initiated Transaction, CIT)

The most common scenario.

The user:

  1. Clicks «Buy».
  2. Confirms the payment.
  3. Enters a card or uses Apple Pay / Google Pay.
  4. The payment goes through.

Examples:

  • buying a product in an online store;
  • buying a subscription for the first time;
  • a donation;
  • paying for a taxi ride.

Characteristics:

  • an explicit user action is required;
  • usually fewer risks for the payment system;
  • easier to pass bank checks.

The merchant (Merchant-Initiated Transaction, MIT)

The merchant initiates the charge without the user's participation at the moment of payment.

Examples:

  • a monthly subscription;
  • Netflix auto-renewal;
  • charging for exceeding a cloud service limit;
  • charging for a trip after a car rental ends.

The flow:

  1. The user grants permission for future charges once.
  2. The payment provider stores the payment method or token.
  3. From then on, the merchant initiates charges on its own.

Characteristics:

  • special MIT flags are required in the payment gateway;
  • an initial successful CIT transaction is often required;
  • a higher likelihood of bank declines.

7 One-off and recurring payments

7.1. One-off payments

The simplest type of integration.

The flow:

Application
    ↓
Backend
    ↓
Payment Provider
    ↓
Bank

After a successful payment:

  • the provider sends a webhook;
  • the backend updates the order status;
  • the application receives confirmation.

Critical points:

  • never trust the client's response alone;
  • the source of truth is the backend + webhook.

7.2. Subscriptions

Subscriptions are substantially more complex than one-off payments.

The main entities:

Subscription

For example:

{
  "plan": "Premium",
  "period": "monthly",
  "nextBillingDate": "2026-07-01"
}

Billing Cycle

The billing period:

  • monthly;
  • yearly;
  • weekly.

Trial

The trial period:

7 days free
↓
automatic charge

7.3. Recurring Payments

When a user signs up for a subscription:

First payment
↓
Saving the payment method
↓
Automatic charges

Technically, it is usually not the card that is stored but a token.

For example:

card
↓
payment token
↓
merchant

Advantages:

  • security;
  • PCI DSS compliance;
  • you can change the partner bank without storing cards.

8. Handling failed payments and the Grace Period

8.1. What happens when a charge fails

A very important part of subscriptions.

Causes:

  • insufficient funds;
  • the card is blocked;
  • the card has expired;
  • the bank declined the operation;
  • the user revoked the authorization.

The standard scenario:

Day 1: charge attempt
↓
Error
↓
Retry after 1 day
↓
Error
↓
Retry after 3 days
↓
Error
↓
The subscription becomes Past Due

This is called retry logic or dunning management.

8.2. Grace Period

So as not to cut the user off immediately.

Example:

The subscription has ended
↓
The charge failed
↓
Access is kept for another 7 days
↓
If payment is not recovered —
access is switched off

Very common in SaaS.

9. Architecture and payment integration specifics in online stores

9.1 Apple App Store specifics

Subscriptions on iOS follow Apple's model.

The user buys a subscription through:

the Apple App Store.

The developer does not receive card data.

Apple manages:

  • payments;
  • renewals;
  • refunds;
  • repeated charge attempts.

Billing Retry

If the renewal failed:

The subscription has expired
↓
Apple keeps trying to charge the money
↓
For several days or weeks
↓
If it succeeds —
the subscription is restored

During this period the user may remain in a special state.

Billing Grace Period

Apple allows you to enable a Grace Period.

Example:

The subscription has ended
↓
A problem with the card
↓
The user keeps using the service
↓
Apple tries to collect payment

If the money is charged:

The subscription status is Active again

Billing Recovery

Apple can automatically restore a subscription after a successful retry charge.

Events arrive via:

  • App Store Server Notifications;
  • receipt validation;
  • the App Store Server API.

For the backend it looks roughly like this:

DID_FAIL_TO_RENEW
↓
GRACE_PERIOD
↓
DID_RENEW

9.2 Google Play specifics

Similar logic exists in:

Google Google Play.

States:

ACTIVE
↓
IN_GRACE_PERIOD
↓
ON_HOLD
↓
CANCELED

If the user tops up the card:

ON_HOLD
↓
ACTIVE

without signing up for the subscription again.

10. Architecture specifics of an application's billing system

10.1 Maintaining security

Many people do it like this:

The client said:
"Payment successful"
↓
We grant access

This is insecure.

The correct way:

Provider
↓ webhook (with digital signature verification)
Backend
↓
Database update
↓
The client receives the status

The source of truth is always the server.

10.2. A typical subscription state model

ACTIVE
↓
PAST_DUE
↓
GRACE_PERIOD
↓
SUSPENDED
↓
CANCELED

or

TRIAL
↓
ACTIVE
↓
FAILED_PAYMENT
↓
RECOVERED

Such a state machine usually underpins any serious subscription integration.

10.3. What is usually stored in the database

User
Subscription
Payment Method Token
Invoice
Payment Attempt
Webhook Event

For example:

{
  "subscriptionId": "sub_123",
  "status": "active",
  "nextBillingDate": "2026-07-01",
  "paymentProvider": "apple"
}

11. Restore Purchases

11.1. The scenario:

  1. The user bought a subscription or a premium feature.
  2. Deleted the application.
  3. Bought a new phone.
  4. Reinstalled the application.
  5. Expects to get access to the already purchased content without paying again.

This is what the purchase restoration mechanism is for.

Why this is needed

Example:

A user bought Premium for $50.

A month later:

Deleted the application
↓
Installed it again
↓
Signed in to the account

If restoration is not implemented, the application may display:

Buy Premium

even though the user has already paid.

This is a poor user experience and may violate app store requirements.

11.2 Restore Purchases in the Apple App Store

In Apple's ecosystem, purchases belong not to the application but to the user's Apple ID.

Therefore the application can ask Apple for a list of previously purchased products.

The flow looks like this:

User
↓
Taps Restore Purchases
↓
App Store
↓
Returns the purchase history
↓
The application restores access

What can be restored

Usually:

  • non-consumable purchases (for example, "Pro Version");
  • active subscriptions;
  • some auto-renewable subscriptions.

Examples:

Premium Unlock
No Ads
Pro Features
Monthly Subscription

What cannot be restored

Consumable items (consumables):

100 coins
500 gems
1 extra life

Once used, they are considered consumed.

The Restore Purchases button

Apple recommends having a button:

Restore Purchases

especially if the application sells:

  • subscriptions;
  • premium unlock;
  • lifetime purchase.

How it works technically

The application requests data from the App Store.

Apple returns:

{
  "productId": "premium_monthly",
  "transactionId": "123456",
  "purchaseDate": "...",
  "expiresDate": "..."
}

The backend validates the data.

If the purchase is valid:

User
↓
Premium = true

Restoration through the application account

Many applications additionally have their own account system.

For example:

The purchase is made
↓
Linked to user_id
↓
Saved in the backend

Then restoration happens in two ways:

Through the App Store

If the user changed devices.

Through the service account

If the user simply signed in to their account again.

For example:

Login
↓
Backend
↓
You already have Premium
↓
Access granted

11.3. Restore Purchases in Google Play

Google works with a similar scheme.

Purchases are tied to the Google account.

After reinstalling the application:

Google Play
↓
Returns purchase details
↓
The application restores access

Server architecture

A reliable scheme usually looks like this:

Purchase
↓
Store
↓
Receipt / Purchase Token
↓
Backend
↓
Validation with the Store
↓
Saving the access entitlement

On restoration:

Restore Purchases
↓
Store
↓
Receipt
↓
Backend validation
↓
Entitlement restoration

The key concept here is the entitlement (the right of access).

The application should not be asking:

Was there a purchase?

It should be asking:

Is there currently a right to use the feature?

For example:

{
  "userId": "123",
  "premium": true,
  "expiresAt": "2026-08-01"
}

11.4 Typical mistakes when implementing Restore Purchases

Mistake #1

Storing the information only on the device.

UserDefaults
SharedPreferences

After a reinstall everything disappears.

Mistake #2

Granting access based only on a local flag.

isPremium = true
The user changes devices — access is lost.

Mistake #3

Not supporting restoration for lifetime purchases.

The user once bought:

Premium Forever

After changing phones, they see the purchase screen again.

This is a frequent cause of complaints and refunds.

As for testing payments in payment systems, it has a number of specifics.

The main types of testing

  1. Functional testing
    • Successful payment.
    • Payment cancelled by the user.
    • Insufficient funds.
    • A bank or processing error.
    • Refund.
    • Partial refund.
    • Repeat payment.
  2. Integration testing
    • Correct data transfer between the site/application and the payment gateway.
    • Handling of API responses.
    • Operation of webhooks and payment status notifications.
  3. Security testing
    • Protection of payment data.
    • Traffic encryption (TLS/HTTPS).
    • Compliance with PCI Security Standards Council requirements (PCI DSS).
    • Verification of protection against fraud and attacks.
  4. Performance testing
    • Operation under heavy load.
    • Bulk transaction processing.
    • Payment service response time.

12 Specifics of testing payment systems

  • Test (sandbox) environments, test card numbers, test PIN codes, SMS codes and so on are used so that no real money is charged.
  • A payment may pass through several participants: the issuing bank, the acquiring bank, the processing center and the payment gateway.
  • Different currencies and payment methods must be checked.
  • It is important to test scenarios with an unstable internet connection, request retries and interrupted payments.
  • Statuses must be verified for correctness:
    • Created
    • Pending
    • Authorized
    • Captured
    • Failed
    • Refunded

Typical risks

  • Double charging.
  • Loss of payment information.
  • Incorrect refunds.
  • Status mismatch between the store's system and the payment provider.
  • Errors handling timeouts and repeated requests.

What a tester's checklist usually includes

  • Checking all payment methods.
  • Checking limits and fees.
  • Checking refunds and cancellations.
  • Checking customer notifications.
  • Reconciling data in the database and in reports.
  • Checking operation logging and auditing.

13 Practical advice on integrating payment systems for monetization in applications and games

For modern mobile applications, the usual approach is:

  1. The purchase goes through the App Store or Google Play, and in some regions or for some applications it may also be possible to integrate with any payment gateway (banking system).
  2. The backend receives confirmation from the store.
  3. The backend stores the user's entitlement.
  4. When the user signs in to their account, the entitlement is restored automatically.
  5. The Restore Purchases button is used as a fallback mechanism if synchronization has been lost for some reason.

This approach is considered the most reliable and matches the recommendations of the mobile platforms.

From the point of view of mobile application architecture, today you usually have to support three different classes of payments at the same time:

  1. In-App Purchases/App Store/Google Play — digital content and subscriptions inside mobile applications.
  2. Payment gateways (for example, Stripe, Adyen, PayPal) — for the web and many service payments.
  3. Merchant-Initiated payments for auto-renewals, invoicing and recurring charges.

It is precisely the handling of subscription states, retry attempts, grace periods and recovery that usually accounts for 70–80% of the complexity of a payment integration, rather than the initial payment itself.

Comments

To leave a comment

If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Lectures and tutorial on "Software and information systems development"

Terms: Software and information systems development