[Proposal] In-App Purchases for Open edX (Purchases & Upgrades)
Status | Ready for Review |
|---|---|
Contributing Team | Raccoon Gang |
Coordinator |
|
Earlier Discovery | N/A |
Github | |
Linked Initiatives |
|
Type |
|
Overview |
|
- 1 Overview
- 2 Problem
- 3 Use Cases
- 4 Proposed solution
- 4.1 Key principles
- 4.2 In scope (v1)
- 4.3 Out of scope (v1)
- 5 Implementation plan
- 6 Long-term ownership & maintenance plans
- 7 Ownership & Collaboration
- 8 Contact person
- 9 Optional additions
- 10 Competitive Research (brief)
- 11 Impact on App Store Visibility
- 12 Telemetry & Success Criteria
- 12.1 Functional
- 12.2 Business
- 12.3 Technical/Reliability
- 13 Open Questions for Rollout/Releases
- 14 Implementation Plan
View the Github ticket for proposal status update
Overview
This proposal introduces a lightweight, compliant, and maintainable foundation for selling course access in Open edX across iOS/Android and the web - without reviving deprecated ecommerce. It supports two business models:
Pay-to-Enroll: the course is fully gated until purchase; buying grants enrollment into a paid mode (e.g., no-id-professional/professional).
Upgrade-Lite: learners start in audit; purchasing upgrades their mode to a paid one and unlocks graded assessments and a completion certificate.
Both flows run through one server pipeline driven by provider webhooks (default: RevenueCat), unifying entitlements across platforms.
Problem
Self-hosted Open edX lacks a maintained, first-party mobile purchase path; legacy ecommerce is deprecated. Operators need a review-safe way to sell access on mobile and web with minimal operational overhead, synchronized entitlements, and clear store compliance.
Use Cases
Learner Stories
Pay-to-Enroll Access
As a learner,
I need to purchase a course directly from my mobile app or the web,
In order to gain access to this course.
Upgrade from Audit Mode
As a learner,
I need to upgrade from the audit mode to a paid mode within the app or website,
in order to unlock graded assessments and receive a verified completion.
Purchase Restoration
As a learner using iOS or Android,
I need to restore my past purchases when reinstalling or switching devices,
in order to retain access to my paid courses without repurchasing them.
Pending Transaction Handling
As a learner on Android,
I need to see clear message when a payment is pending,
in order to understand that my purchase is being processed and will unlock access once confirmed.
Operator Stories
Unified Entitlement Management
As an operator,
I need to sell courses across the web and mobile platforms while keeping entitlements synchronized through a single server pipeline,
in order to avoid duplicate product configurations and ensure consistent learner access across devices.
Web Sales Integration
As an operator,
I need to use Stripe for web purchases that are automatically synced with mobile entitlements via the provider (e.g., RevenueCat),
in order to maintain compliance and operational simplicity across payment channels.
Compliance Stories
Refund and Revocation Management
As a finance or compliance officer,
I need to ensure that refunds or chargebacks automatically trigger access revocation in the LMS,
in order to keep financial records accurate and meet platform audit and refund requirements.
Proposed solution
Implement a Purchase Gateway - a thin server layer plus a receipt/entitlement provider (RevenueCat by default) that unifies App Store, Google Play, and Stripe into a single entitlement model. Clients (iOS/Android/Web) display store prices, initiate native purchase, and do not unlock locally; they wait for the server grant.
Key principles
Single logical_product_id per course (e.g.,
edu.acme.course.<slug>), reused across App Store, Play, and Stripe. The provider maps the logical ID to native store objects and unifies entitlements.Server as the source of truth: only the server modifies access via existing LMS APIs (enroll, changeMode, unenroll/downgrade).
Web and mobile in sync: Stripe purchases are ingested by the provider, which emits events to the server; the server updates LMS access.
Compliance-first: Mobile digital access goes through native IAP; web uses Stripe under the operator’s domain; prices come from store metadata/provider offerings (never hard-coded).
Minimal v1 scope (no subscriptions/IDV), with a clean path to future extensions via provider adapters.
In scope (v1)
Provider SDK on iOS/Android (plus web integration for Stripe).
Per-course non-consumable products (optional server-side TTL for time-boxed access).
Server-side validation via provider webhooks: purchase, refund, revoke (and renewal later).
Restore (iOS) and Pending (Android).
Admin mapping: course_id → logical_product_id → target_mode, active, optional expires_at.
Out of scope (v1)
ID-verification & proctoring.
Subscriptions, bundles, coupons, complex price experiments.
Building our own receipt/refund system (delegated to the provider).
Implementation plan
Milestone 1 - MVP (shared pipeline + Upgrade-Lite)
Mobile: fetch price (StoreKit/Play Billing or provider offerings); purchase; Restore/Pending; “Processing…” state; client polling of server//me/enrollments until access changes.
Web: Stripe Checkout/Payments; success ingested by the provider; same “Processing…” pattern until server grant.
Server: Purchase Gateway (mapping, webhook handler, idempotent enroll/changeMode/unenroll, LMS integration, audit log).
Operator setup: create store products/Stripe prices; fill mapping.
Milestone 2 - Operational polish
Admin UI/CSV import for mapping; localized copy; batch product prefetch.
Alerting for webhook failures; nightly reconciliation for drift.
Milestone 3 - Extensions (optional)
Time-boxed access via server expires_at; parity banners on web.
Subscriptions/bundles; coupons; selective IDV/proctoring per course/program.
Provider swapping (Adapty/Qonversion) via a thin adapter; server contracts unchanged.
Long-term ownership & maintenance plans
Long-term day-to-day ownership: AXIM Mobile WG, in collaboration with Open edX Mobile maintainers. Operators own their Stripe accounts and store products. Server interfaces and event logs are documented; the provider adapter is isolated for maintainability.
Ownership & Collaboration
Engineering/Tech: AXIM Mobile WG + Open edX Mobile maintainers.
Product UX/UI WG: paywall/process copy, localization, accessibility.
Compliance/Legal: adherence to store/Stripe policies and regional regulations.
Contact person
Ivan Stepanok - ivan.stepanok@raccoongang.com
Optional additions
Business Models & UX (detail)
Pay-to-Enroll: the course is locked; purchase ⇒ enroll(user, course_id, mode=paid) (e.g., no-id-professional/professional, configurable).
Upgrade-Lite: audit allows read-only learning; purchase ⇒ changeMode(..., new_mode) + unlocks graded/certificate. We intentionally exclude IDV/proctoring in v1 for simplicity.
Provider strategy
Default - RevenueCat: centralizes validation, refunds/revocations, entitlements, cross-platform identity, and web (Stripe) ingestion. The small fee replaces building/maintaining our own receipt/refund logic.
Alternatives: Adapty, Qonversion via a thin adapter; server contracts remain unchanged.
Security & Privacy
Signed webhooks, HTTPS everywhere, least-privilege keys.
Idempotency keyed by transaction_id.
Client is never the authority; only the server changes access.
Minimal PII; align with operator GDPR/FERPA requirements.
Error handling & edge cases
Network errors → retries with backoff; remain in “Processing…” until grant.
Duplicate webhooks → idempotent operations.
Refund/chargeback → provider event → server revokes → client reflects loss of access at next check.
User switch → logout clears provider session; entitlements are recalculated.
Competitive Research (brief)
Coursera/Udemy et al.: strict IAP compliance, unified storefronts, server-controlled access; fewer review rejections, consistent UX - industry standards.
Open edX opportunity: provide self-hosted operators with an “out-of-the-box” way to sell access without heavyweight ecommerce.
Impact on App Store Visibility
Compliant native IAP flows and predictable purchase→grant behavior reduce review risk and improve paywall→purchase conversion, which tends to lift behavioral metrics (sessions, active devices) and organic visibility in the stores.
Telemetry & Success Criteria
Functional
p95 “purchase → server grant” ≤ 30s.
Verified Restore/Pending scenarios on iOS/Android.
Zero reliance on deprecated ecommerce.
Business
Conversion from paywall_view → purchase (mobile/web), uplift vs. baseline.
Share of paid enrollments, revenue per course/device, refund/chargeback rate and resolution speed.
Fewer support tickets about access and “lost” purchases.
Technical/Reliability
All server operations idempotent; 100% event coverage in audit logs.
≥ 99.9% successful webhook processing; fast alerting.
Daily reconciliation limits entitlement drift to ≤ N records per 100k users.
Open Questions for Rollout/Releases
Ship site-config JSON for mapping first, or deliver an Admin UI from day one?
Which paid mode should be the default for upgrades (no-id-professional vs. professional)?
Keep time-boxed access purely as a server policy (expires_at) without subscriptions, or design an “upgrade-to-subscription” path early?
Implementation Plan
Raccoon Gang is currently looking for funding for this proposal.