Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
in_app_purchase.hpp
Go to the documentation of this file.
1#pragma once
2
3// pulp::events::IapClient — host-overridable in-app purchase seam.
4//
5// Pulp does not ship a production billing, marketplace, or entitlement
6// layer. This API gives hosts a small testable seam they can replace with
7// product-specific StoreKit / Microsoft Store / Play Billing code while the
8// built-in backend reports `Unavailable` everywhere.
9//
10// Supported operations:
11// * Product lookup: `request_products(skus, callback)` resolves an SKU list
12// into `Product` records (title / description / localized price).
13// * Purchase: `purchase(sku, callback)` initiates a purchase flow and
14// reports the resulting `Purchase` (state + transaction id + receipt).
15// * Restore: `restore(callback)` re-issues previously-completed purchases
16// so the user can recover entitlements on a new device.
17// * Observer: `set_observer(callback)` registers a single sink that fires
18// whenever the backend resolves a purchase asynchronously (out-of-band
19// transactions, subscription renewals, family-sharing grants).
20//
21// Not currently implemented by Pulp's built-in backend:
22// * Real StoreKit2 wiring on Apple platforms (sandbox round-trip).
23// * Microsoft Store SDK / StoreContext wiring on Windows.
24// * Google Play Billing on Android.
25// * Server-side receipt validation helpers.
26// * Subscription-specific surfaces (auto-renew status, grace periods,
27// promotional offers).
28//
29// Built-in behavior:
30// * All platforms default to the stub backend unless a host or test installs
31// another `IapClient` with `install_iap_backend()`.
32// * The stub returns `is_available() == false`, `backend_id() == "none"`,
33// and every operation reports `Unavailable` / empty result.
34// * Production billing stays host-owned so Pulp remains MIT-clean and avoids
35// app-store-specific policy, packaging, and receipt-validation choices.
36
37#include <cstdint>
38#include <functional>
39#include <memory>
40#include <string>
41#include <string_view>
42#include <vector>
43
44namespace pulp::events {
45
57
65
67struct Product {
68 std::string sku;
69 std::string title;
70 std::string description;
71 std::string price_formatted;
72 std::string price_currency_code;
73 double price_amount = 0.0;
74 bool is_subscription = false;
75};
76
80 std::vector<Product> products;
81 std::vector<std::string> unknown_skus;
82 std::string error;
83};
84
86struct Purchase {
87 std::string sku;
89 std::string transaction_id;
90 std::string receipt;
91 std::string error;
92};
93
94using ProductLookupCallback = std::function<void(const ProductLookupResult&)>;
95using PurchaseCallback = std::function<void(const Purchase&)>;
96using RestoreCallback = std::function<void(const std::vector<Purchase>&)>;
97using PurchaseObserver = std::function<void(const Purchase&)>;
98
107public:
109
110 virtual ~IapClient() = default;
111
114 virtual bool is_available() const = 0;
115
119 virtual std::string backend_id() const = 0;
120
124 virtual void request_products(const std::vector<std::string>& skus,
125 ProductLookupCallback callback) = 0;
126
131 virtual void purchase(const std::string& sku, PurchaseCallback callback) = 0;
132
135 virtual void restore(RestoreCallback callback) = 0;
136
141 virtual void set_observer(PurchaseObserver observer) = 0;
142
146 virtual bool finish_transaction(const std::string& transaction_id) = 0;
147
148protected:
149 IapClient() = default;
150 IapClient(const IapClient&) = delete;
151 IapClient& operator=(const IapClient&) = delete;
152};
153
154} // namespace pulp::events
IapClient(const IapClient &)=delete
virtual void set_observer(PurchaseObserver observer)=0
Register a callback that fires for any backend-resolved purchase (including out-of-band transactions ...
virtual ~IapClient()=default
virtual void restore(RestoreCallback callback)=0
Ask the backend to re-issue every previously-completed purchase.
IapClient & operator=(const IapClient &)=delete
virtual void request_products(const std::vector< std::string > &skus, ProductLookupCallback callback)=0
Ask the backend for metadata + localized pricing of the given SKUs.
virtual bool is_available() const =0
Returns true when a real IAP backend is wired up on this build.
virtual void purchase(const std::string &sku, PurchaseCallback callback)=0
Initiate a purchase flow for sku.
static IapClient & instance()
virtual bool finish_transaction(const std::string &transaction_id)=0
Acknowledge / finish a purchase so the backend stops re-delivering it.
virtual std::string backend_id() const =0
Short identifier of the active backend.
Definition child_process_manager.hpp:18
std::function< void(const ProductLookupResult &)> ProductLookupCallback
Definition in_app_purchase.hpp:94
std::function< void(const Purchase &)> PurchaseObserver
Definition in_app_purchase.hpp:97
std::function< void(const std::vector< Purchase > &)> RestoreCallback
Definition in_app_purchase.hpp:96
std::function< void(const Purchase &)> PurchaseCallback
Definition in_app_purchase.hpp:95
ProductLookupStatus
Outcome of a product lookup.
Definition in_app_purchase.hpp:59
@ PartiallyOk
Some SKUs resolved; unknown_skus lists the misses.
Definition in_app_purchase.hpp:61
@ Unavailable
No IAP backend on this build.
Definition in_app_purchase.hpp:63
@ Ok
All requested SKUs resolved.
Definition in_app_purchase.hpp:60
PurchaseState
Lifecycle state of a Purchase returned by the backend.
Definition in_app_purchase.hpp:47
@ Unavailable
No IAP backend on this build / SKU not configured.
Definition in_app_purchase.hpp:55
@ Deferred
Awaiting external action (Ask-to-Buy / parental approval).
Definition in_app_purchase.hpp:54
@ Purchasing
User has been prompted; payment in flight.
Definition in_app_purchase.hpp:49
@ Restored
Re-issued via restore(); entitlement should be granted.
Definition in_app_purchase.hpp:51
@ Unknown
Backend hasn't resolved the transaction yet.
Definition in_app_purchase.hpp:48
@ Cancelled
User cancelled the purchase prompt.
Definition in_app_purchase.hpp:53
@ Purchased
Payment cleared; entitlement should be granted.
Definition in_app_purchase.hpp:50
@ Failed
Backend reported an error (see Purchase::error).
Definition in_app_purchase.hpp:52
Outcome of a single product lookup invocation.
Definition in_app_purchase.hpp:78
std::vector< std::string > unknown_skus
SKUs the backend didn't recognize.
Definition in_app_purchase.hpp:81
std::string error
Empty on Ok / PartiallyOk.
Definition in_app_purchase.hpp:82
std::vector< Product > products
Definition in_app_purchase.hpp:80
ProductLookupStatus status
Definition in_app_purchase.hpp:79
Resolved product metadata.
Definition in_app_purchase.hpp:67
bool is_subscription
True for auto-renewing subscriptions.
Definition in_app_purchase.hpp:74
std::string price_currency_code
ISO 4217 (e.g. "USD").
Definition in_app_purchase.hpp:72
std::string title
Localized product title.
Definition in_app_purchase.hpp:69
std::string price_formatted
Localized price string ("$0.99", "€0,99").
Definition in_app_purchase.hpp:71
double price_amount
Numeric price in price_currency_code units.
Definition in_app_purchase.hpp:73
std::string sku
Caller-supplied identifier.
Definition in_app_purchase.hpp:68
std::string description
Localized long description.
Definition in_app_purchase.hpp:70
Single transaction record.
Definition in_app_purchase.hpp:86
std::string transaction_id
Backend-assigned transaction identifier.
Definition in_app_purchase.hpp:89
std::string receipt
Opaque receipt bytes from a host backend, if any.
Definition in_app_purchase.hpp:90
std::string sku
Matches the SKU passed to purchase().
Definition in_app_purchase.hpp:87
std::string error
Empty unless state == Failed.
Definition in_app_purchase.hpp:91
PurchaseState state
Definition in_app_purchase.hpp:88