https://github.com/edx/ecommerce and https://github.com/edx/ecommerce-worker
We use a Django application called ecommerce to manage the edX product catalog and handle orders for those products. The ecommerce service extends Oscar, an open source Django ecommerce framework, and hosts internal tools for configuring courses and coupons.
The service is a source of truth for the following data:
As of this writing, these include seats and coupons. Seats, associated with an ecommerce-specific Course model, are abstractions on top of the LMS’ enrollment modes. Coupons are an abstraction on top of Oscar’s Voucher app used to represent benefits such as discounts.
Product variant information. For example, a seat in a course may have “audit” and “verified” variants, each with its own pricing information.
Product groupings, used to define a set of products to which an offer applies.
Rules used to determine if a basket qualifies for a benefit (e.g., a discount).
User-specific collections of products which have yet to be ordered. An order is created once the contents of a basket are paid for.
User-specific collections of products which have been paid for and the system must fulfill (e.g., by enrolling the user in a specific mode on the LMS).
The service relies on third-party services (e.g., CyberSource, PayPal) for payment processing. Records are kept of every payment processor response received by the service.
LMS usernames, full names, email addresses, and optional tracking context (e.g., Google Analytics client ID). The service requires user state in order to function. Django users which mirror LMS users interacting with the application are created using a custom JWT authentication handler.
See here for a high-level overview of service interactions involved in the order placement process. In more detail:
0) User’s basket is populated and frozen, initiating the checkout process.
1) If necessary, user is redirected to an external payment processor.
2) External payment processor makes a request back to the ecommerce service to signal that payment has completed.
3) Ecommerce records payment metadata, creates an order, and enqueues a task for its fulfillment.
4) Ecommerce worker pulls the task of the queue.
5) Ecommerce worker makes a request to ecommerce signaling that fulfillment for the given order should occur.
6) Ecommerce fulfills the order, making requests to the LMS if necessary (for enrollment).