# কাস্টম লাইসেন্সিং সিস্টেম ইন্টিগ্রেশন নির্দেশিকা

বর্তমান সোর্স কোড দুটি লাইসেন্স প্রদানকারী সমর্থন করে: 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` সরাসরি গ্রাহক অ্যাপের রানটাইম অনুমতি নয়।

নির্ভরযোগ্যতার প্রয়োজনীয়তা:

- অন্তত একবার ডেলিভারি; গ্রহীতাকে ব্যবসায়িক idempotency নিশ্চিত করতে হবে; নেটওয়ার্ক স্তরে “মাত্র একবার কল” প্রতিশ্রুতি দেওয়া যায় না।
- একই ইভেন্ট ID ও মূল অনুরোধ বডিতে বিদ্যমান ফল ফেরত দিন; একই ID-তে ভিন্ন বডি হলে HTTP 409 `IDEMPOTENCY_CONFLICT` ফেরত দিন।
- পুরোনো সংস্করণ নতুন সংস্করণ ওভাররাইট করতে পারবে না। একই ক্রয় সংস্করণের ভিন্ন ইভেন্ট বা লক্ষ্য নিঃশব্দে গ্রহণ নয়; যাচাইয়ের জন্য HTTP 409 `STATE_VERSION_CONFLICT` ফেরত দিন।
- POST প্রতিক্রিয়া হারালে বা প্রক্রিয়া পুনরায় শুরু হলে Launch প্রথমে মূল ইভেন্টের GET করে; স্পষ্ট `EVENT_NOT_FOUND` পেলেই কেবল মূল ID ও বডি আবার পাঠায়।
- দূরবর্তী বাস্তব ইস্যুর ফল অনিশ্চিত হলে ইন্টিগ্রেশনকারী নিজস্ব স্থায়ী idempotency রেফারেন্স দিয়েও যাচাই করবে; পুনরায় পাঠিয়ে দ্বিতীয় লাইসেন্স তৈরি করা যাবে না।
- 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` non-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 পাতলা অ্যাডাপ্টারের উদাহরণ](/bn/launch-documents/custom-licensing-example/) স্বাক্ষর, nonce, ইভেন্ট ডুপ্লিকেট নিয়ন্ত্রণ ও রসিদ স্থায়ী সংরক্ষণের গ্রহীতা কাঠামো দেয়; প্রকৃত লাইসেন্স প্রক্রিয়ায় বিক্রেতার সিস্টেম যুক্ত করতে হবে।

কাস্টম প্রোটোকলের [OpenAPI](/bn/assets/launch/external-licensing-openapi.json) এবং Launch-এর নিজস্ব [OpenAPI](/bn/assets/launch/openapi.json) পৃথকভাবে দুই দিক বর্ণনা করে। গ্রহীতাকে Licentivo পণ্য ক্যাটালগ, নীতি ক্যাটালগ বা পরিচয় বিশ্বাস ইন্টারফেস বাস্তবায়ন করতে হয় না।

স্থানীয় যাচাই বিচ্ছিন্ন MySQL, বাস্তব HTTP অ্যাডাপ্টার ও সিমুলেটেড লাইসেন্স/পেমেন্ট পরিষেবা ব্যবহার করে; প্রতিক্রিয়া হারানো, পুনরায় শুরু, নবায়ন, আপগ্রেড, রিফান্ড, অ্যাকাউন্ট নিষ্ক্রিয়, রসিদ অমিল ও ডেলিভারি বিচ্ছিন্নতা অন্তর্ভুক্ত। উৎপাদন গ্রহণযোগ্যতা পরীক্ষায় বিক্রেতার নিজস্ব লাইসেন্সিং পরিষেবা ও অ্যাপও দরকার। অঘোষিত ডিভাইস, শেয়ার্ড অ্যাকাউন্ট লগইন ও অফলাইন সক্ষমতা Launch পূরণ করে না।
