This is a simplified DRM-X 5.0 custom login-page integration example for Python and Django. It uses zeep to read the WSDL and call DRM-X methods directly.
The demo is not a complete LMS. In a production system, replace the fixed account and course list with the customer's user system, orders, subscriptions, enrollments, or course-access records.
DRM-X5_Python_Django_Integration_Example/
├─ drmx5_demo/
│ ├─ config.py # DRM-X, demo account, and course settings
│ ├─ settings.py # Django and Session settings
│ └─ urls.py
├─ integration/
│ ├─ views.py # Login, course validation, and the complete DRM-X workflow
│ ├─ urls.py
│ └─ templates/ # Login, relay, license, and error pages
├─ manage.py
└─ requirements.txt
The main business logic is concentrated in integration/views.py, making the execution flow easy to read from top to bottom.
ZJGet POST /licstore5
│
├─ Same-origin POST relay restores the existing Session Cookie
├─ Save POST parameters in the Django Session
├─ Check the login Session
│ └─ Not logged in: show the login page, then continue after login
├─ Validate the course using POST yourproductid
├─ CheckUserExists
│ └─ User does not exist: AddNewUser
├─ Existing user: CheckUserIsRevoked
├─ Existing user: GetUserDetails and read IsLockedOut
├─ UpdateRightWithDisableVirtualMachine
└─ getLicenseRemoteToTableWithVersionWithMac
Both the permission update and license request use the same rightsid received from the ZJGet POST request.
Open drmx5_demo/config.py:
DRMX5_ADMIN_EMAIL = "YOUR_ADMIN_EMAIL"
DRMX5_WEB_SERVICE_AUTH_STR = "YOUR_WEB_SERVICE_AUTH_STR"
DRMX5_GROUP_ID = "YOUR_GROUP_ID"
# China service
DRMX5_SERVICE_URL = "https://5.drm-x.cn/haihaisoftlicenseservice.asmx"
# International service
# DRMX5_SERVICE_URL = "https://5.drm-x.com/haihaisoftlicenseservice.asmx"The code automatically appends ?wsdl to the service URL, so configure only the .asmx address.
The demo account and course settings are in the same file:
DEMO_USERNAME = "student"
DEMO_PASSWORD = "123456"
DEMO_EMAIL = "student@example.com"
DEMO_FULL_NAME = "Demo Student"
DEMO_PURCHASED_COURSE_IDS = ("1001",)
DEMO_COURSE_BEGIN_DATE = "2026-01-01"
DEMO_COURSE_EXPIRATION_DATE = "2036-01-01"
DEMO_BIND_NUMBER = "1"DEMO_PURCHASED_COURSE_IDS only simulates course-purchase records. DRM-X 5.0 and ZJGet read yourproductid from the current encrypted video's License Profile and submit it to the integration URL by POST.
cd "DRM-X5_Python_Django_Integration_Example"
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
python manage.py check
python manage.py runserver 8080To run without activating the virtual environment:
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe manage.py runserver 8080Demo login page: http://localhost:8080/login
Default username: student; password: 123456.
Set the course ID in the License Profile's Product ID field, for example:
1001
To allow a License Profile to match multiple courses, separate the IDs with hyphens:
1001-1002
Validation succeeds when the user has purchased any one of the listed courses. If multiple IDs match, the demo selects the first purchased course in POST order. This does not grant access to the other courses in the list.
Under Account Settings → Website Integration Settings → Custom Login Page Integration, set the license URL to:
http://localhost:8080/licstore5
Then open an encrypted video with ZJGet. Do not browse directly to /licstore5, because the license workflow requires parameters submitted by ZJGet.
| Parameter | Purpose |
|---|---|
profileid |
License Profile ID, passed as ProfileID when requesting the license. |
clientinfo |
Client license data generated by ZJGet. |
rightsid |
RightsID selected in the License Profile; used to update permissions and obtain the license. |
yourproductid |
Product ID configured in the License Profile; this demo interprets it as a course ID. |
platform |
ZJGet platform information. |
contenttype |
Protected content type. |
version |
ZJGet client version. |
return_url |
Return address or identifier used after the license is obtained. |
mac |
Device or client binding information. |
profileid, clientinfo, yourproductid, and rightsid are required.
CheckUserExists: Checks whether the current website user already exists in DRM-X.AddNewUser: Creates the DRM-X user when the account does not exist.CheckUserIsRevoked: Refuses the license when an existing user has been revoked.GetUserDetails: ReadsIsLockedOut; a locked user cannot obtain a license.UpdateRightWithDisableVirtualMachine: Updates the permission using POSTrightsid, withExpirationAfterFirstUse=-1.getLicenseRemoteToTableWithVersionWithMac: Obtains the license using the same POSTrightsid.
zeep generates the SOAP request and SOAPAction from the DRM-X 5.0 WSDL, so the demo does not construct SOAP XML manually.
- Replace the fixed login with Django Authentication, SSO, or the customer's existing identity system.
- Query the database or LMS for the courses actually purchased by the current authenticated user.
- Use HTTPS and set
DEBUG=FalseandSESSION_COOKIE_SECURE=True. - Never commit real AdminEmail, WebServiceAuthStr, or other credentials to a public repository.
- Adjust expiration, play count, watermark, binding, and virtual-machine restrictions to match business requirements.
- If multiple License Profiles share one RightsID, consider the concurrency impact of updating the same permission template.