# कस्टम लाइसेंसिंग सिस्टम एकीकरण मार्गदर्शिका

वर्तमान स्रोत कोड दो लाइसेंस प्रदाताओं का समर्थन करता है: Licentivo और `custom_http`। व्यापारी **सिस्टम सेटिंग → लाइसेंसिंग सिस्टम** में एक प्रदाता चुनकर सक्षम करता है; सभी उत्पाद और sandbox/live वातावरण उसी प्रदाता का उपयोग करते हैं। कस्टम कनेक्शन और प्लान मैपिंग प्रत्येक उत्पाद और वातावरण के लिए अलग से कॉन्फ़िगर की जाती हैं। इस सुविधा में स्व-निर्मित लाइसेंसिंग सिस्टम शामिल नहीं है; व्यापारी अपनी लाइसेंसिंग सेवा और SDK का उपयोग जारी रखता है।

मौजूदा Licentivo खाता विनिमय, नौ-भाषा SDK और डिवाइस प्रबंधन अपनी वर्तमान प्रक्रिया का उपयोग जारी रखते हैं। कस्टम उत्पाद इस दस्तावेज़ के प्रोटोकॉल से खरीद की स्थिति सिंक्रनाइज़ करते हैं; ग्राहक खाता केंद्र में लाइसेंस डिलीवरी देखता है और Licentivo SDK प्रक्रिया में प्रवेश नहीं करता।

## त्वरित शुरुआत

1. अपनी सेवा में नीचे दिए गए चार HTTP इंटरफ़ेस लागू करें और प्रत्येक कनेक्शन के लिए अलग HMAC हस्ताक्षर कुंजी तथा पहचानकर्ता कॉन्फ़िगर करें।
2. “लाइसेंसिंग सिस्टम” में “कस्टम लाइसेंसिंग सेवा” चुनें, नया कनेक्शन जोड़ें, पता, वातावरण, कनेक्शन पहचानकर्ता, key ID और मानक Base64 कुंजी भरें। सत्यापन के बाद सहेजें और “कस्टम लाइसेंसिंग सेवा सक्षम करें” पर क्लिक करें।
3. उत्पाद और बिक्री प्लान के ड्राफ़्ट बनाएँ। खरीद प्रकार और मूल्य Launch में प्रबंधित होते हैं; लाइसेंस नियम आपके अपने सिस्टम में प्रबंधित होते हैं।
4. उत्पाद और वातावरण चुनें, कनेक्शन चुनें, बाहरी उत्पाद और प्लान संदर्भ भरें और सहेजें। प्रदाता पूरे साइट के चयन से तय होता है; अन्य उत्पादों के लिए साथ में Licentivo सक्षम नहीं किया जा सकता।
5. बिक्री प्लान पृष्ठ पर परीक्षण संस्करण प्रकाशित करें, भुगतान, डिलीवरी, नवीनीकरण, अपग्रेड, रिफ़ंड और विफलता से पुनर्प्राप्ति का स्वीकृति परीक्षण पूरा करें, फिर उत्पादन वातावरण अलग से कॉन्फ़िगर करें।

बनाने के बाद पता, वातावरण, कनेक्शन पहचानकर्ता और नेटवर्क पहुँच नीति बदली नहीं जा सकती; आवश्यकता होने पर नया कनेक्शन बनाएँ। हस्ताक्षर कुंजी बदली जा सकती है; खाली छोड़ने पर पुरानी कुंजी बनी रहती है। दूसरे लाइसेंसिंग सिस्टम के ऑर्डर मौजूद होने पर पूरे साइट का प्रदाता सीधे नहीं बदला जा सकता; पहले माइग्रेशन पूरा करें। बदलाव के बाद पुराने प्लान केवल पूर्वावलोकन के लिए रह जाते हैं और उन्हें फिर प्रकाशित करना होता है; सहेजे गए कनेक्शन क्रेडेंशियल और मैपिंग बनी रहती हैं। जिन उत्पादों के ऑर्डर मौजूद हैं उनका कनेक्शन सीधे नहीं बदला जा सकता और बिक्री में उपयोग हो रही मैपिंग भी सीधे नहीं बदली जा सकती; नई कीमत या मैपिंग के लिए प्लान का नया संस्करण उपयोग करें।

API से कॉन्फ़िगर करते समय पहले `PUT /api/v1/admin/licensing/provider` कॉल करें, जिसका अनुरोध निकाय `{"provider":"custom_http"}` या `{"provider":"licentivo"}` हो, फिर उत्पाद मैपिंग सहेजें। जो प्रदाता सक्षम नहीं है उसके लिए उत्पाद लाइसेंस बाइंडिंग या Licentivo प्लान नीति मैपिंग सहेजी नहीं जा सकती।

कनेक्शन जाँच प्रोटोकॉल, प्रमाणीकरण, वातावरण और समर्थित खरीद प्रकारों की पुष्टि करती है; यह व्यापारी के लिए बाहरी प्लान बनाती या उसकी पुष्टि नहीं करती। वास्तविक भुगतान लेने से पहले वास्तविक बाहरी प्लान के साथ sandbox एकीकरण का स्वीकृति परीक्षण पूरा करना आवश्यक है।

## 3. व्यापारी एकीकरण प्रक्रिया

1. मौजूदा लाइसेंसिंग सिस्टम के सामने इस दस्तावेज़ के चार इंटरफ़ेस लागू करें; सिस्टम का मौजूदा लाइसेंस तर्क बनाए रखें।
2. Launch में नया “कस्टम लाइसेंसिंग सेवा” कनेक्शन बनाएँ और HTTPS पता, कनेक्शन पहचानकर्ता, वातावरण तथा हस्ताक्षर कुंजी कॉन्फ़िगर करें।
3. Launch क्षमता जाँच इंटरफ़ेस कॉल करके प्रोटोकॉल संस्करण, स्थायी/सीमित अवधि की खरीद के समर्थन और डिलीवरी विधि की पुष्टि करता है।
4. उत्पाद के लिए यह कनेक्शन चुनें; बिक्री प्लान संस्करण को बाहरी `product_ref` और `plan_ref` से मैप करें। बाहरी पहचानकर्ता व्यापारी की अपनी स्ट्रिंग हो सकते हैं; Licentivo UUID अनिवार्य नहीं है।
5. sandbox में भुगतान, नवीनीकरण, अपग्रेड, रिफ़ंड और विफलता से पुनर्प्राप्ति का स्वीकृति परीक्षण पूरा करें, फिर live कॉन्फ़िगरेशन अलग से प्रकाशित करें।
6. भुगतान सत्यापित करने के बाद Launch उसी डेटाबेस लेनदेन में ऑर्डर, खरीद कवरेज और भेजे जाने वाले कार्य सहेजता है।
7. बैकग्राउंड प्रक्रिया पूरा खरीद स्नैपशॉट कस्टम लाइसेंसिंग सेवा को भेजती है; वह सेवा प्राप्ति रिकॉर्ड स्थायी रूप से सहेजने के बाद प्राप्ति की पुष्टि करती है।
8. लाइसेंसिंग सेवा लक्ष्य स्थिति संसाधित करती है। Launch मूल इवेंट की रसीद पूछता है और केवल `applied` मिलने पर इस सिंक्रनाइज़ेशन को पूर्ण मानता है।
9. Launch लॉग इन कर चुके और इस खरीद के स्वामी ग्राहक के लिए डिलीवरी जानकारी पढ़ता है और ग्राहक केंद्र में लाइसेंस कोड, सक्रियण लिंक या सादा पाठ निर्देश दिखाता है। ऐप व्यापारी के अपने लाइसेंसिंग सिस्टम से जुड़ता है।
10. नवीनीकरण, अपग्रेड, रिफ़ंड, भुगतान वापसी, निलंबन और समाप्ति सभी पूरे स्नैपशॉट का नया संस्करण बनाते हैं। लाइसेंसिंग सेवा नवीनतम लक्ष्य स्थिति के अनुसार संसाधित करती है।

एक ही उत्पाद के sandbox/live अलग-अलग कनेक्शन से जुड़े होते हैं। खरीद मौजूद होने के बाद प्रदाता बदलने के लिए अलग माइग्रेशन प्रक्रिया चाहिए; पुराने ऑर्डर और कार्य बैकग्राउंड चयन के कारण चुपचाप नई सेवा को नहीं भेजे जा सकते।

## 4. कस्टम लाइसेंसिंग सेवा द्वारा लागू किए जाने वाले API

नीचे के सभी इंटरफ़ेस **व्यापारी की लाइसेंसिंग सेवा प्राप्त करती है और Launch सर्वर कॉल करता है**। `base_url` में स्थिर पथ उपसर्ग हो सकता है; तालिका के पथ उस उपसर्ग के बाद जोड़े जाते हैं।

| विधि और पथ | उद्देश्य |
| --- | --- |
| `GET /launch/v1/capabilities` | कनेक्शन जाँच, प्रोटोकॉल और क्षमताओं की घोषणा |
| `POST /launch/v1/events` | पूरी खरीद लक्ष्य स्थिति प्राप्त करना; पुनः प्रयास में मूल इवेंट का उपयोग करना |
| `GET /launch/v1/events/{event_id}` | जाँचना कि इवेंट वास्तव में लागू हुआ या नहीं, ताकि खोई हुई प्रतिक्रिया पुनः प्राप्त हो सके |
| `GET /launch/v1/entitlements/{entitlement_ref}/delivery` | मौजूदा लाइसेंस की डिलीवरी जानकारी पढ़ना, दूसरा लाइसेंस बनाए बिना |

पहले संस्करण में रसीद सक्रिय रूप से पूछी जाती है; ऑर्डर बदलने के लिए बाहरी कॉलबैक का नया प्रवेश बिंदु नहीं जोड़ा जाता। कस्टम सेवा को भुगतान की पुष्टि करने, कीमत बदलने या खरीद अवधि बदलने का अधिकार नहीं है।

### 4.1 सामान्य नियम और प्रमाणीकरण

- JSON में UTF-8 और समय के लिए UTC RFC 3339 का उपयोग करें; `version` एक धनात्मक पूर्णांक है।
- सफल प्रतिक्रिया `{"data": {...}, "request_id": "..."}` है; त्रुटि प्रतिक्रिया `{"error": {"code": "...", "message": "..."}, "request_id": "..."}` है।
- प्रत्येक वातावरण और कनेक्शन के लिए अलग कुंजी उपयोग करें। कुंजी कम से कम 32 यादृच्छिक बाइट की हो और Launch में मौजूदा एन्क्रिप्टेड कुंजी स्टोरेज को संदर्भित करे; इसे फ़्रंटएंड कॉन्फ़िगरेशन, उदाहरण या ऐप इंस्टॉलेशन पैकेज में न रखें।
- हर अनुरोध में `X-Launch-Key-Id`, `X-Launch-Timestamp`, `X-Launch-Nonce`, `X-Launch-Signature` शामिल होते हैं।
- टाइमस्टैम्प दशमलव Unix सेकंड में है। nonce कम से कम 128 बिट के यादृच्छिक मान का बिना पैडिंग वाला base64url एन्कोडिंग है; हर नेटवर्क प्रयास के लिए नया मान बनाएँ।

हस्ताक्षर इनपुट नीचे दी गई सात वस्तुओं को एक-एक न्यूलाइन से जोड़कर बने UTF-8 बाइट हैं; अंत में न्यूलाइन न जोड़ें:

```text
v1
<key_id>
<timestamp>
<nonce>
<UPPERCASE HTTP method>
<encoded request path and raw query, including the base_url path prefix>
<lowercase hexadecimal SHA-256 digest of the exact request body>
```

`X-Launch-Signature`, `v1=` के बाद `HMAC-SHA256` परिणाम का बिना पैडिंग वाला base64url एन्कोडिंग है। GET अनुरोध का निकाय खाली होता है। प्राप्तकर्ता पहले हस्ताक्षर और समय सीमा जाँचे, फिर डीसिरियलाइज़ करे; स्थिर समय तुलना उपयोग करे, डिफ़ॉल्ट रूप से दोनों दिशाओं में 300 सेकंड का अंतर स्वीकार करे और रीप्ले रोकने के लिए nonce कम से कम 600 सेकंड रखे। पुनः प्रयासों में nonce दोबारा उपयोग न करें, लेकिन इवेंट ID और व्यावसायिक अनुरोध निकाय अपरिवर्तित रहें।

हस्ताक्षर HTTPS का विकल्प नहीं है। अनुरोध में ग्राहक पासवर्ड, भुगतान कुंजी या Licentivo प्रशासन कुंजी नहीं होती; डिफ़ॉल्ट रूप से केवल अनाम खाता संदर्भ भेजा जाता है, ईमेल नहीं। सर्वर के HTTP क्लाइंट में टाइमआउट, प्रतिक्रिया आकार सीमा और क्रेडेंशियल के साथ रीडायरेक्ट का अनुसरण रोकने की व्यवस्था आवश्यक है। कस्टम पता कॉन्फ़िगर करते समय लक्ष्य पते की जाँच करें; आंतरिक नेटवर्क तक पहुँच प्रशासक द्वारा स्पष्ट रूप से कॉन्फ़िगर की गई डिप्लॉयमेंट क्षमता होनी चाहिए।

### 4.2 क्षमता जाँच

`GET /launch/v1/capabilities` HTTP 200 लौटाता है, उदाहरण के लिए:

```json
{
  "data": {
    "protocol": "launch-external-licensing-v1",
    "connection_ref": "merchant-01-sandbox",
    "environment": "sandbox",
    "purchase_types": ["perpetual", "fixed_term"],
    "delivery_types": ["license_key", "activation_url", "instructions"],
    "devices": false,
    "identity_exchange": false
  },
  "request_id": "check-001"
}
```

`protocol`, `connection_ref`, `environment`, `purchase_types`, `delivery_types` अनिवार्य हैं। अंतिम दो गैर-रिक्त सरणियाँ होनी चाहिए; असमर्थित खरीद प्रकार बिक्री के लिए प्रकाशित नहीं किए जा सकते। पहले संस्करण में `devices` और `identity_exchange` का मान `false` होना चाहिए; विस्तारित अनुबंध और कार्यान्वयन पूरा होने के बाद ही समर्थन घोषित किया जा सकता है।

### 4.3 खरीद स्नैपशॉट

`POST /launch/v1/events` के अनुरोध का उदाहरण:

```json
{
  "schema": "launch-external-licensing-v1",
  "event_id": "7bf84b91-2749-4b01-a6a7-bd527c488ee8",
  "connection_ref": "merchant-01-sandbox",
  "environment": "sandbox",
  "type": "entitlement.snapshot",
  "change_reason": "purchase",
  "account_ref": "customer_opaque_001",
  "entitlement_ref": "purchase_opaque_001",
  "launch_product_id": "c6dd463e-50f7-4b76-8239-0a8ec6fc304b",
  "launch_plan_version_id": "5459a073-9362-4b46-949d-9b0c5d84421a",
  "product_ref": "desktop-editor",
  "plan_ref": "professional-yearly-v1",
  "version": 1,
  "desired_state": "active",
  "valid_from": "2026-10-25T00:00:00Z",
  "valid_until": "2027-10-25T00:00:00Z"
}
```

ऊपर दिए गए उदाहरण के सभी फ़ील्ड अनिवार्य हैं। `valid_until` का `null` स्थायी खरीद दर्शाता है; अन्य मान `valid_from` के बाद होने चाहिए।

| फ़ील्ड | सीमाएँ और अर्थ |
| --- | --- |
| `event_id` | Launch द्वारा बनाया गया UUID; एक ही इवेंट के पुनः प्रयास में अपरिवर्तित रहता है |
| `connection_ref` / `environment` | हस्ताक्षर कुंजी के कनेक्शन और वातावरण से मेल खाना चाहिए |
| `account_ref` | स्थिर अनाम खाता संदर्भ; प्राप्तकर्ता कनेक्शन, वातावरण और इस संदर्भ से ग्राहक की पहचान करता है |
| `entitlement_ref` | एक खरीद संबंध का स्थिर संदर्भ; सब कुछ रद्द होने के बाद पुनः खरीद पर नया संदर्भ उपयोग करें |
| `launch_product_id` / `launch_plan_version_id` | Launch के उत्पाद और अपरिवर्तनीय प्लान संस्करण का UUID |
| `product_ref` / `plan_ref` | एकीकरण करने वाले द्वारा कॉन्फ़िगर बाहरी संदर्भ; 1–128 ASCII अक्षर, जिनमें अक्षर, अंक, `_`, `-`, `.` अनुमत हैं; बाहरी प्लान अपने आप नहीं बनाया जाता |
| `version` | एक ही कनेक्शन, वातावरण और खरीद संदर्भ के अंतर्गत लगातार बढ़ने वाला लक्ष्य संस्करण |
| `desired_state` | `active`、`suspended`、`expired`、`revoked` |
| `change_reason` | `purchase`、`renewal`、`upgrade`、`refund`、`reversal`、`suspension`、`resumption`、`expiry`、`reconciliation` |

`account_ref` और `entitlement_ref` में 1–128 अक्षर, अंक, अंडरस्कोर या हाइफ़न होते हैं। `schema` और `type` उदाहरण के मानों पर स्थिर हैं। प्राप्तकर्ता `desired_state` और पूरी निरपेक्ष अवधि के अनुसार परिणाम लागू करता है; कारण के आधार पर खुद दिन नहीं जोड़ता या पूरा लाइसेंस रद्द नहीं करता।

विशेष रूप से रिफ़ंड के मामले में: नवीनीकरण या अपग्रेड ऑर्डर का रिफ़ंड देने के बाद भी वैध मूल खरीद रह सकती है। तब स्नैपशॉट `active` रह सकता है, लेकिन अवधि कम हो सकती है या प्लान बदल सकता है। केवल लेजर की पुनर्गणना के बाद कोई वैध खरीद कवरेज न रहने पर संबंधित समाप्ति स्थिति भेजी जाती है।

### 4.4 प्राप्ति, रसीद और पुनर्प्राप्ति

प्राप्तकर्ता को इवेंट ID, मूल अनुरोध निकाय का डाइजेस्ट और निष्पादन हेतु कार्य स्थायी रूप से सहेजने के बाद ही HTTP 202 लौटाना चाहिए; पहले ही सिंक्रनाइज़ हो चुके डुप्लिकेट अनुरोध पर HTTP 200 लौटाया जा सकता है। दोनों नीचे दी गई रसीद संरचना लौटाते हैं।

```json
{
  "data": {
    "event_id": "7bf84b91-2749-4b01-a6a7-bd527c488ee8",
    "connection_ref": "merchant-01-sandbox",
    "environment": "sandbox",
    "entitlement_ref": "purchase_opaque_001",
    "version": 1,
    "payload_sha256": "<64-character lowercase hexadecimal SHA-256 digest of the exact event body>",
    "status": "pending",
    "error_code": null
  },
  "request_id": "receipt-001"
}
```

डाइजेस्ट प्लेसहोल्डर को वास्तविक डाइजेस्ट से बदलना आवश्यक है। रसीद में ऊपर दिए सभी फ़ील्ड अनिवार्य हैं; कोई त्रुटि न होने पर `error_code` का मान `null` है। `GET /launch/v1/events/{event_id}` पूछने पर वही संरचना HTTP 200 के साथ लौटती है; स्थिति इनमें से हो सकती है:

| `status` | अर्थ | Launch की कार्रवाई |
| --- | --- | --- |
| `pending` | स्थायी रूप से सहेजा गया, वास्तविक लाइसेंस बदलाव अभी पूरा नहीं हुआ | बाद में पूछें; सिंक्रनाइज़ेशन पूर्ण चिह्नित न करें |
| `applied` | लाइसेंसिंग सेवा पुष्टि करती है कि लक्ष्य स्थिति वास्तव में लागू हो गई है | सभी संबंधित फ़ील्ड और डाइजेस्ट जाँचने के बाद सिंक्रनाइज़ेशन पूर्ण होने की पुष्टि करें |
| `rejected` | निश्चित रूप से लागू नहीं हो सकता, जैसे बाहरी प्लान का मौजूद न होना | स्वचालित पुनः प्रयास रोकें और स्पष्ट त्रुटि दिखाएँ |
| `manual_review` | परिणाम अनिश्चित है या स्थिति में टकराव है; मैनुअल जाँच आवश्यक है | मूल कार्य और इवेंट सुरक्षित रखें, ऑडिट योग्य कार्रवाई की प्रतीक्षा करें |

डिलीवरी स्थिति सिंक्रनाइज़ेशन रसीद से स्वतंत्र है; `applied` को ग्राहक ऐप की रनटाइम अनुमति सीधे नहीं मान सकते।

विश्वसनीयता आवश्यकताएँ:

- कम से कम एक बार डिलीवरी; प्राप्तकर्ता को व्यावसायिक इडेम्पोटेंसी सुनिश्चित करनी होगी; नेटवर्क स्तर पर “केवल एक बार कॉल” का वादा नहीं किया जा सकता।
- एक ही इवेंट ID और मूल अनुरोध निकाय पर मौजूदा परिणाम लौटाएँ; एक ही ID और अलग निकाय पर HTTP 409 `IDEMPOTENCY_CONFLICT` लौटाएँ।
- पुराना संस्करण नए को ओवरराइट नहीं कर सकता। एक ही खरीद संस्करण के अलग इवेंट या लक्ष्य चुपचाप स्वीकार नहीं होने चाहिए; जाँच के लिए HTTP 409 `STATE_VERSION_CONFLICT` लौटाएँ।
- POST प्रतिक्रिया खोने या प्रक्रिया पुनरारंभ होने के बाद Launch पहले मूल इवेंट का GET करता है; स्पष्ट `EVENT_NOT_FOUND` मिलने पर ही मूल ID और निकाय दोबारा भेजता है।
- दूरस्थ जारीकरण का वास्तविक परिणाम अस्पष्ट होने पर एकीकरणकर्ता को अपने स्थायी इडेम्पोटेंसी संदर्भ से भी जाँच करनी चाहिए; दोबारा भेजने पर दूसरा लाइसेंस नहीं बनाना चाहिए।
- HTTP 429 पर `Retry-After` का पालन करें; टाइमआउट और 5xx पर बैकऑफ़ से बहाल करें; सीमा पार होने पर मैनुअल जाँच। प्रमाणीकरण, कॉन्फ़िगरेशन और व्यावसायिक अस्वीकृति को सफल सिंक्रनाइज़ेशन न मानें।

सुझाए त्रुटि कोड: `SIGNATURE_INVALID`（401）、`SIGNATURE_EXPIRED`（401）、`NONCE_REPLAYED`（409）、`SCOPE_MISMATCH`（403）、`EVENT_NOT_FOUND`（404）、`IDEMPOTENCY_CONFLICT`（409）、`STATE_VERSION_CONFLICT`（409）、`PLAN_UNKNOWN`（422）、`PURCHASE_TYPE_UNSUPPORTED`（422）、`RATE_LIMITED`（429）、`SERVICE_UNAVAILABLE`（503）。 त्रुटि संदेश में क्रेडेंशियल नहीं होने चाहिए।

### 4.5 लाइसेंस डिलीवरी

`GET /launch/v1/entitlements/{entitlement_ref}/delivery` केवल उस कनेक्शन और वातावरण का मौजूदा डिलीवरी परिणाम पढ़ सकता है; क्वेरी को नया जारीकरण कमांड नहीं मानना चाहिए। HTTP 200 उदाहरण:

```json
{
  "data": {
    "connection_ref": "merchant-01-sandbox",
    "environment": "sandbox",
    "entitlement_ref": "purchase_opaque_001",
    "version": 1,
    "status": "ready",
    "delivery": {
      "type": "license_key",
      "value": "EXAMPLE-ONLY-NOT-A-REAL-LICENSE",
      "expires_at": null
    }
  },
  "request_id": "delivery-001"
}
```

`status` का मान `pending`, `ready` या `unavailable` है; ready न होने पर `delivery` का मान `null` है। ready होने पर `type` घोषित `license_key`, `activation_url` या `instructions` होना चाहिए, `value` अधिकतम 4096 UTF-8 बाइट है और `expires_at` UTC समय या `null` है। सभी प्रतिक्रिया संबद्ध फ़ील्ड Launch के वर्तमान खरीद संस्करण से मेल खाने चाहिए; पुराने संस्करण की डिलीवरी वर्तमान परिणाम नहीं है।

लाइसेंस कोड संवेदनशील डेटा है; डिलीवरी प्रतिक्रिया `Cache-Control: no-store` उपयोग करती है, निकाय लॉग नहीं होता और स्थायी रखने पर एन्क्रिप्टेड स्टोरेज उपयोग करें। सक्रियण URL केवल कनेक्शन कॉन्फ़िगरेशन द्वारा अनुमत HTTPS ओरिजिन से स्वीकार करें; instructions सादे पाठ में दिखाएँ, HTML या स्क्रिप्ट न चलाएँ। निरस्त, पूर्ण रिफ़ंड या वैध खरीद रहित खाते Launch से डिलीवरी जानकारी नहीं ले सकते; पहले दी क्रेडेंशियल का वास्तविक अमान्यकरण बाहरी सिस्टम करता है।

## Launch प्रशासन और ग्राहक API

ये इंटरफ़ेस व्यापारी द्वारा डिप्लॉय Launch origin के अंतर्गत हैं और बाहरी सेवा की HMAC कुंजी से प्रमाणित नहीं होते। व्यवस्थापक मौजूदा वेबसाइट सत्र उपयोग करता है, लेखन अनुरोध में `X-CSRF-Token` अनिवार्य है। ग्राहक केवल अपनी खरीद पढ़ सकता है।

| विधि और पथ | उद्देश्य |
| --- | --- |
| `GET /api/v1/admin/licensing/connections` | `connections`, `bindings`, `mappings` और `default_provider` लौटाता है; कनेक्शन सूची में केवल कस्टम कनेक्शन हैं, Licentivo मौजूदा प्रबंधन इंटरफ़ेस उपयोग करता है |
| `POST /api/v1/admin/licensing/connections` | कस्टम कनेक्शन सत्यापित करें और जोड़ें |
| `PUT /api/v1/admin/licensing/connections/{id}` | नाम, अनुमत सक्रियण ओरिजिन और हस्ताक्षर कॉन्फ़िगरेशन संपादित करें; ऐतिहासिक प्राप्ति पता अपरिवर्तित |
| `POST /api/v1/admin/licensing/connections/{id}/check` | फिर जाँचें; HTTP 200 में `last_check_error` गैर-null होने पर जाँच विफल है |
| `PUT /api/v1/admin/products/{id}/licensing` | उत्पाद के चयनित वातावरण हेतु प्रदाता, कनेक्शन और बाहरी प्लान मैपिंग कॉन्फ़िगर करें |
| `GET /api/v1/me/products/{id}/delivery?environment=sandbox` | वर्तमान ग्राहक अपनी वर्तमान वैध कस्टम खरीद की लाइसेंस डिलीवरी पढ़ता है; Cookie या desktop Bearer प्रमाणीकरण |
| `GET /api/v1/licensing/documentation` | यह दस्तावेज़, लॉगिन आवश्यक नहीं |
| `GET /api/v1/licensing/protocol` | कस्टम सेवा द्वारा लागू OpenAPI, लॉगिन आवश्यक नहीं |

नया कस्टम कनेक्शन जोड़ने का अनुरोध निकाय:

```json
{
  "provider": "custom_http",
  "name": "My licensing service",
  "base_url": "https://licenses.example.com",
  "environment": "sandbox",
  "connection_ref": "merchant-01-sandbox",
  "key_id": "key-1",
  "signing_key": "<standard Base64 encoding of 32 to 128 random bytes>",
  "allow_private_network": false,
  "allow_local_http": false,
  "activation_origins": ["https://activate.example.com"]
}
```

प्रतिक्रिया का `data` संवेदनशील जानकारी हटाया कनेक्शन ऑब्जेक्ट है; हस्ताक्षर कुंजी या secret ID नहीं लौटता। allow_local_http केवल sandbox के localhost/लूपबैक पते के लिए है; निजी नेटवर्क HTTPS को स्पष्ट व्यवस्थापक अनुमति चाहिए। खाली कुंजी केवल मौजूदा कनेक्शन संपादन में अनुमत है। Licentivo अब भी `POST /api/v1/admin/connections/licentivo` से सेट होता है।

उत्पाद कॉन्फ़िगर करने का अनुरोध निकाय:

```json
{
  "provider": "custom_http",
  "environment": "sandbox",
  "connection_id": "<id returned when creating the connection>",
  "mappings": [
    {
      "version_id": "<Launch plan version UUID>",
      "product_ref": "desktop-editor",
      "plan_ref": "professional-yearly-v1"
    }
  ]
}
```

Licentivo चुनते समय `{"provider":"licentivo","environment":"sandbox","mappings":[]}` भेजें, उसकी उत्पाद/नीति मैपिंग अब भी मूल इंटरफ़ेस उपयोग करती है। पहला बदलाव मौजूदा प्रकाशन को पूर्वावलोकन बनाता है; नए प्रदाता के अनुसार फिर जाँच और प्रकाशन आवश्यक है। mappings में केवल जोड़ने या रखने वाले संस्करण हो सकते हैं; छोड़ने से पुरानी मैपिंग नहीं हटती।

ग्राहक डिलीवरी HTTP 200 का मानक data envelope है; खरीद न होने पर 404, Licentivo उत्पाद पर 409 `LICENSING_DELIVERY_UNSUPPORTED`, सिंक न होने, निलंबन, समाप्ति या पूर्ण रिफ़ंड पर 409 `ENTITLEMENT_NOT_READY`, बाहरी सेवा अस्थायी अनुपलब्ध या रसीद बेमेल पर 503 लौटता है। ग्राहक केंद्र का “लाइसेंस डिलीवरी देखें” स्वामित्व और स्थिति फिर जाँचता है, क्रेडेंशियल URL या लॉग में नहीं लिखता।

कस्टम उत्पाद के Licentivo identity, device, integration-check इंटरफ़ेस 409 `CUSTOM_LICENSING_SDK_REQUIRED` लौटाते हैं। पुराना `/credential` अब भी 410 लौटाता है। ऐप व्यापारी का अपना SDK उपयोग करे, Launch की `ready` स्थिति को रनटाइम प्राधिकरण न माने।

## उदाहरण और स्वीकृति

[Python पतला एडाप्टर उदाहरण](/hi/launch-documents/custom-licensing-example/) हस्ताक्षर, nonce, इवेंट डुप्लिकेट नियंत्रण और रसीद स्थायित्व का प्राप्तकर्ता ढाँचा देता है; वास्तविक लाइसेंसिंग के लिए व्यापारी सिस्टम से जुड़ना आवश्यक है।

कस्टम प्रोटोकॉल का [OpenAPI](/hi/assets/launch/external-licensing-openapi.json) और Launch का [OpenAPI](/hi/assets/launch/openapi.json) दोनों दिशाएँ अलग बताते हैं। प्राप्तकर्ता को Licentivo उत्पाद कैटलॉग, नीति कैटलॉग या पहचान विश्वास इंटरफ़ेस लागू करने की आवश्यकता नहीं है।

स्थानीय सत्यापन अलग MySQL, वास्तविक HTTP एडाप्टर और सिमुलेटेड लाइसेंसिंग/भुगतान सेवाएँ उपयोग करता है, प्रतिक्रिया खोना, पुनरारंभ, नवीनीकरण, अपग्रेड, रिफ़ंड, खाता अक्षम होना, रसीद बेमेल और डिलीवरी अलगाव कवर करता है। उत्पादन स्वीकृति में व्यापारी की अपनी लाइसेंसिंग सेवा और ऐप भी आवश्यक हैं। अघोषित डिवाइस, साझा खाता लॉगिन और ऑफ़लाइन क्षमताएँ Launch पूरी नहीं करता।
