Technology
BillingMeld: Why the Server Should Verify Purchases Instead of the App
BillingMeld serves as a central source of information about purchases and subscriptions. It verifies transactions through the App Store and Google Play, tracks status changes, and connected services operate only with confirmed BillingMeld status.
In-app purchases on mobile devices often seem simple from the user's perspective. They press a button, confirm the payment, gain access to a feature or subscription — and expect everything to work automatically afterward.
However, behind this button, a much more complex process begins for the developer. It’s necessary to confirm the purchase itself, account for renewals, subscription expirations, refunds, transaction reviews, device changes, and differences between Apple and Google stores.
The main issue arises when the server starts considering the client application as the source of truth.
If the app reports: "Purchase completed," the server grants access and continues to rely on that single reported state. But the purchase lifecycle doesn’t end there.
A subscription can be renewed, auto-renewal may be disabled, a payment can be refunded, and the transaction itself can be revoked by the store.
That’s why in BillingMeld, purchase confirmation is handled by the server, not the app.
The client reports but doesn’t decide
In BillingMeld's architecture, the mobile device application is not the main source of purchase information.
The client may send transaction data, but this only serves as a basis for verification. The final decision is made by the BillingMeld backend system, which verifies the information through the Apple or Google infrastructure.
This is a fundamental difference.
The app on the device may operate with outdated data, miss timely updates, or send information that no longer reflects the current purchase status.
Moreover, the client should not have the ability to independently decide whether the user has paid for access.
BillingMeld checks, for example:
whether the purchase exists;
whether it pertains to the correct app and product;
whether the paid period is currently active;
whether a renewal has occurred;
whether auto-renewal is disabled;
whether a refund has been issued;
whether the operation has been revoked;
whether the paid period has expired.
Thus, a client message becomes not proof of purchase but a prompt to verify its actual status.
A single source of truth for servers
Connected services don’t need to implement full integrations simultaneously with Apple and Google.
They connect to BillingMeld and receive already normalized purchase states.
For example: access is active, the paid period has ended, a renewal is confirmed, auto-renewal is off, or the purchase has been revoked.
This approach clearly separates responsibilities.
Apple and Google are sources of the purchase transaction states. BillingMeld verifies this data, normalizes it, and maintains the current state. The final access decision is based on the BillingMeld status.
For product servers, this means a unified contract instead of multiple independent integrations.
There’s no need to separately implement App Store rules in each service, then reconcile different data formats, events, and statuses into a unified logic.
Why not fully trust the client
The client application runs on the user’s device.
It can be closed, restarted, restored from backup, updated later, or launched on another device. It might operate with stale data or miss events that occurred after the initial purchase.
Even without user interference, this makes the client a poor source of the final subscription state.
For example, a user subscribes and gains access, then later a refund is issued, or the store revokes the transaction.
If the server only knows about the initial client message, it will continue to consider the purchase valid.
In another case, a user might disable auto-renewal. The already paid period should still remain active until its end date.
If the system operates only on a basic "subscription exists / does not exist" status, it risks prematurely cutting off access or leaving it active after the rights have ended.
BillingMeld is built around a different logic: the client does not confirm its own rights. The client reports an event, and the server determines the actual purchase state.
Purchases are not a single event
A common mistake in billing architecture is treating a purchase as a one-time event.
In reality, it has a lifecycle.
Initially, there’s an operation. Then it’s confirmed by the store. For subscriptions, a paid period begins. Later, it might be renewed again.
The user can disable auto-renewal but still use the subscription until the paid period ends.
A payment might fail on renewal. Refunds can be issued. The purchase can be revoked in some cases.
Therefore, the fact that "this purchase once existed" is not enough.
The server needs to understand what is happening with the purchase now.
Revocations are not overlooked
This need for server-side logic is especially clear in cases of refunds and revocations.
The initial purchase may have been perfectly valid. The user paid and gained access.
But the situation can change later.
If BillingMeld receives information about changes, it updates its purchase status and may additionally verify data through the store.
Connected services then work with the new status.
This approach prevents the app from endlessly trusting the fact that the client once reported a successful purchase weeks or months ago.
If the store no longer recognizes that right as valid, BillingMeld reflects it in its status.
Subscription cancellation and access expiration are different
There’s an important distinction here.
If the user disables auto-renewal, it doesn’t necessarily mean access should be immediately revoked.
The current paid period can still be valid.
BillingMeld must retain information that auto-renewal is off but also keep track of the end date of the already paid period.
Access becomes inactive only after the period ends if no new confirmation occurs.
This exemplifies why a simple boolean subscription = true isn’t enough for proper billing.
The subscription state always ties to timing and lifecycle events.
Renewals are also a separate verification
Subscriptions don’t end after the first payment.
The server must verify whether a renewal has occurred and if the next paid period is confirmed by the store.
BillingMeld tracks such changes and updates the subscription state accordingly.
If renewal is confirmed, access continues.
If a renewal fails or the store no longer confirms the period, the system shouldn’t just extend access based on assumptions.
To the user, it should look consistent: access exists as long as the paid subscription is active.
For developers, this means not re-implementing similar renewal logic in each app.
An example typical scenario
The user subscribes through a mobile app.
The client receives purchase info and sends necessary data to BillingMeld. But this message alone doesn’t finalize the purchase confirmation.
BillingMeld verifies with the store.
If Apple or Google confirms the purchase and its status meets the product rules, BillingMeld marks the right as active.
Connected services then provide the user with paid features.
From this point, the status persists independently from the initial client message.
If the subscription is renewed, BillingMeld updates with the new paid period.
If the user disables auto-renewal, the current period continues until its end.
If a refund or revocation occurs, the status updates again.
This scheme does not require the app to store its own separate "truth" about the purchase — it works with the state confirmed and stored by BillingMeld.
Device change considerations
Server-side logic is especially useful when a user changes phones or reinstalls the app.
The right to a purchase should not exist solely because a specific app instance recorded a successful transaction.
Similarly, reinstalling the app shouldn’t erase the user’s confirmed rights.
If the purchase's status is stored on the server linked to a confirmed store operation, the new device can retrieve the current state via the server.
This underscores why access logic should not be stored only within the mobile app.
Benefits for developers
For teams releasing multiple mobile apps or working across iOS and Android, billing quickly becomes an infrastructure challenge.
They need to handle:
different data formats from Apple and Google;
initial purchase confirmation;
subscription renewals;
period endings;
auto-renewal disablement;
refunds;
revocations;
app reinstallation;
device changes;
purchase restoration;
status changes without user participation.
BillingMeld encapsulates this logic into a dedicated, specialized layer.
Product servers interact with it under a unified contract and don’t need to interpret each store’s specific features.
This reduces duplicated code and, more importantly, the risk that different apps from the same company understand a payment scenario differently.
The focus shifts from receipts to actual rights
What intrigued me most about this architecture is the shift from verifying individual purchases to controlling current states.
The historical payment record alone doesn’t answer the key product question:
Does the user currently have the right to the paid feature?
A purchase might have been successful initially but the period has ended.
A subscription might have auto-renewal disabled but still be within an active paid term.
Renewals might be confirmed, refunds issued, or the operation revoked.
Therefore, instead of a receipt or an initial confirmation, the central object becomes the user’s current rights, based on the confirmed purchase state.
This state is what BillingMeld transmits to other services.
BillingMeld as the boundary between stores and products
This creates a clear architectural boundary.
On one side are App Store and Google Play, with their formats, events, rules, and purchase lifecycles.
On the other are apps and internal services, which most often only need a simpler answer: what rights does the user currently possess?
BillingMeld acts as the intermediary.
It takes store data, verifies it, maps it to its own model, and provides the normalized result to the rest of the infrastructure.
This allows products not to need deep knowledge of each store’s internal specifics.
What it means for the user
For users, a well-designed billing architecture should remain largely invisible.
If a purchase is confirmed and the paid period is active, access must work smoothly.
If the user disables auto-renewal, the ongoing paid period shouldn’t end prematurely.
If a renewal occurs successfully, access should be extended.
If a store confirms a refund or revocation, the system must reflect this change correctly.
When changing devices or reinstalling the app, the user shouldn’t need to manually prove each component that the purchase exists.
Ultimately, the rule is straightforward:
a client reports a purchase, the store is an external source of its status, BillingMeld verifies and normalizes this status, and other services base their decisions on the verified data.
This is why BillingMeld is not just another payment module.
It’s a server trust layer between the mobile app, Apple and Google stores, and the services that need to accurately understand the user's paid rights at any moment.
For more about the project: billingmeld.de.