حزمة SDK لـ .NET
Anis.Partners.Sdk — لـ .NET 8 و .NET 10.
dotnet add package Anis.Partners.Sdk
سجّلها
builder.Services
.AddAnisPartners(builder.Configuration.GetSection("AnisPartners"))
.WithSigner(EcdsaP256Signer.FromPemFile("/secure/partner-key.pem", keyId));
{
"AnisPartners": {
"Authority": "https://<the address Anis gave you>",
"SignatureLifetime": "00:01:00",
"AcceptLanguage": "English",
"SigningKeyCacheDuration": "00:10:00",
"Timeout": "00:00:30"
}
}
ثم خذ IAnisPartnersClient من الحاوية. تُفحص الإعدادات عند بدء تشغيل تطبيقك: فغياب العنوان، أو مدة صلاحية توقيع
خارج النطاق من 1 إلى 60 ثانية، يوقفه عند تلك النقطة.
المُوقِّع خطوة منفصلة عن قصد — إذ لا يوجد خيار افتراضي آمن لمكان حفظ مفتاحك الخاص. يوقّع EcdsaP256Signer
باستخدام ملف مفتاح؛ أما مع خزنة أسرار أو وحدة أمان عتادية، فنفّذ IRequestSigner — معرّف مفتاحك، ودالة توقّع
البايتات وتعيد التوقيع ذا الـ 64 بايت — ولا يدخل المفتاح إلى برنامجك أبدًا.
استخدمها
var profile = await anis.Profile.GetAsync(ct);
await foreach (var wallet in anis.Wallets.ListAsync(ct)) // pages followed for you
Console.WriteLine($"{wallet.Name} {wallet.Balance}");
var cards = await anis.Catalogue.ListCardsAsync(walletId, subcategoryId, cancellationToken: ct);
var credential = await anis.OwnedCards.RevealAsync(walletId, soldCardId, ct);
طلبات الشراء
var operationId = Guid.NewGuid(); // yours: store it with the request BEFORE sending
var outcome = await anis.Orders.CreateAsync(walletId, operationId, new CreateOrderRequest
{
CardId = card.Id,
Quantity = 2,
ExpectedUnitPrice = card.UnitPrice!.Value,
ExpectedTotal = card.UnitPrice!.Value.Multiply(2), // exact decimal
}, ct);
switch (outcome)
{
case OrderCompleted completed: await vault.StoreAsync(completed.Credentials, ct); break; // store FIRST
case OrderProcessing processing: await ResumeAfterAsync(operationId, processing.RetryAfter); break;
case OrderReplayed replayed: await EnsureStoredAsync(replayed.Order, ct); break;
// sent earlier: if you never stored them (the first answer was lost), reveal by replayed.Order.InvoiceId
}
يرسل ResumeAsync طلب الشراء نفسه مرة أخرى بالمعرّف نفسه — وهذه هي طريقة الاستعادة. راجع
طلبات الشراء والاستعادة للاطلاع على القواعد كاملةً وعلى معالجة الأخطاء.
حالات الرفض
كل رفض هو AnisApiException (أو صنف فرعي منه للحالات التي تعالجها بطريقة مختلفة) يحمل Code وRequestId
وRetryAfter وIsReplayed، و— في طلب الشراء — OrderOutcome: إما NotPlaced أو Unknown. وكل
صفحة خطأ تذكر الاستثناء الخاص بها.
ثلاثة استثناءات أخرى تعني شيئًا مختلفًا:
| الاستثناء | المعنى | في طلب الشراء |
|---|---|---|
UnverifiableResponseException |
ردّ تعذّر إثبات أنه صادر من أنيس؛ فجرى التخلّص منه | استأنف بالمعرّف نفسه |
RequestSigningException |
أخفق المُوقِّع لديك؛ لم يُرسَل شيء | أرسله مرة أخرى بعد أن يعمل المُوقِّع |
TaskCanceledException، HttpRequestException |
انتهت المهلة، أو فشل الاتصال | استأنف بالمعرّف نفسه |
عدة تطبيقات أنيس في مضيف واحد
builder.Services.AddAnisPartners("brand-a", config.GetSection("AnisPartners:BrandA")).WithSigner(signerA);
builder.Services.AddAnisPartners("brand-b", config.GetSection("AnisPartners:BrandB")).WithSigner(signerB);
var brandA = factory.GetClient("brand-a"); // IAnisPartnersClientFactory, or [FromKeyedServices("brand-a")]
لكل تطبيق خط معالجة ومفتاح خاصان به، وتحمل تتبّعاته ومقاييسه anis.client.
لا إعادة محاولات تلقائية على هذا العميل
سياسة إعادة المحاولة التي تُضاف إلى كل عميل HTTP (مثل الإعدادات الافتراضية لخدمات .NET Aspire) تتخلّى عن كل
محاولة بعد 10 ثوانٍ افتراضيًا، أي قبل الـ 30 ثانية التي تعتمدها حزمة SDK. عندها قد يكتمل طلب شراء بطيء
لدى أنيس بينما يُتخلَّص من ردّه — ومعه رموز البطاقات. أعد محاولة عمليات القراءة بنفسك إن شئت؛ أما طلبات الشراء
فاستعِدها بـ ResumeAsync.
المراقبة
التتبّعات والمقاييس تحت Anis.Partners.Sdk؛ والسجلات عبر نظام التسجيل الخاص بك. راجع
المراقبة لمعرفة أسماء المقاييس وما يستحق التنبيه عليه.
إذا كان مضيفك يستبدل الحاوية المدمجة في .NET
تستخدم حزمة SDK الخدمات ذات المفاتيح (keyed services) في .NET 8. ويجب أن تدعمها أي حاوية من طرف ثالث —
وكلٌّ من Autofac 9 أو أحدث، وLamar 12.1 أو أحدث، وSimpleInjector يدعمها. وإلا فأنشئ AnisPartnersClient
مباشرةً باستخدام HttpClient يحمل PartnerVerifyingHandler حول PartnerSigningHandler.