SuperQiSdk 1.0.3
dotnet add package SuperQiSdk --version 1.0.3
NuGet\Install-Package SuperQiSdk -Version 1.0.3
<PackageReference Include="SuperQiSdk" Version="1.0.3" />
<PackageVersion Include="SuperQiSdk" Version="1.0.3" />
<PackageReference Include="SuperQiSdk" />
paket add SuperQiSdk --version 1.0.3
#r "nuget: SuperQiSdk, 1.0.3"
#:package SuperQiSdk@1.0.3
#addin nuget:?package=SuperQiSdk&version=1.0.3
#tool nuget:?package=SuperQiSdk&version=1.0.3
SuperQiSdk
C# SDK for the Super Qi (QiNEO) mini-program OpenAPI platform. Handles RSA-SHA256 request signing, token management, payments, refunds, user queries, and messaging.
Requirements
- .NET 9.0 or .NET 10.0
Installation
dotnet add package SuperQiSdk
Configuration
Register the SDK in your DI container using one of two approaches:
Option 1: Inline
services.AddSuperQi(new SuperQiOptions
{
ClientId = "your-client-id",
MerchantId = "your-merchant-id",
GatewayUrl = "https://gateway.qi.iq",
PrivateKey = "base64-encoded-pem-private-key",
PublicKey = "base64-encoded-pem-public-key",
});
Option 2: Configuration binding
// appsettings.json
{
"SuperQi": {
"ClientId": "your-client-id",
"MerchantId": "your-merchant-id",
"GatewayUrl": "https://gateway.qi.iq",
"PrivateKey": "base64-encoded-pem-private-key",
"PublicKey": "base64-encoded-pem-public-key"
}
}
services.AddSuperQi(configuration.GetSection("SuperQi"));
Both overloads register ISuperQiService as a singleton with IHttpClientFactory.
Usage
Inject ISuperQiService and call the desired method:
public class PaymentController(ISuperQiService superQi) : ControllerBase
{
[HttpPost("pay")]
public async Task<IActionResult> Pay()
{
var response = await superQi.PayAsync(new Pay.Request
{
ProductCode = Pay.ProductCode.OnlinePurchase,
PaymentRequestId = Guid.NewGuid().ToString(),
PaymentAmount = new Amount { Value = "1000", Currency = "IQD" },
Order = new Pay.Order
{
OrderDescription = "Test order",
},
PaymentRedirectUrl = "https://example.com/callback",
PaymentNotifyUrl = "https://example.com/notify"
});
if (response.Result?.IsSuccess == true)
return Ok(new { response.PaymentId });
return BadRequest(response.Result?.ResultMessage);
}
}
API Reference
Authorization
| Method | Description |
|---|---|
PrepareAsync |
Prepare authorization and get an auth URL |
ApplyTokenAsync |
Exchange auth code or refresh token for access token |
User Information
| Method | Description |
|---|---|
InquiryUserInfoAsync |
Get user profile (name, contact, avatar, etc.) |
InquiryUserAccountListAsync |
List user bank accounts |
InquiryUserCardListAsync |
List user debit/credit cards |
Payments
| Method | Description |
|---|---|
PayAsync |
Initiate a payment (Online Purchase, Auth+Capture, Agreement, Escrow) |
InquiryPaymentAsync |
Query payment status |
MerchantAcceptAsync |
Accept payment in escrow/auth+capture flows |
ConfirmAsync |
Confirm an authorized payment |
CancelAsync |
Cancel a pending payment |
VoidAsync |
Void/reverse a completed payment |
Refunds
| Method | Description |
|---|---|
RefundAsync |
Initiate a full or partial refund |
InquiryRefundAsync |
Query refund status |
Messaging
| Method | Description |
|---|---|
SendInboxAsync |
Send an in-app inbox message |
SendPushAsync |
Send a push notification |
Webhooks
| Method | Description |
|---|---|
VerifyPaymentNotification |
Verify the RSA-SHA256 signature on an inbound payment notification |
Request Signing
All outbound API calls are automatically signed. The SDK:
- Builds the sign content:
POST {endpoint}\n{ClientId}.{RequestTime}.{jsonBody} - Signs with RSA-SHA256 (PKCS#1 v1.5) using your private key
- Sets the
Client-Id,Request-Time, andSignatureheaders
No manual signing is required.
Webhook Verification
Verify inbound payment notifications to ensure they originate from Super Qi:
[HttpPost("notify")]
public IActionResult HandleNotification([FromBody] JsonElement body, [FromHeader] string signature)
{
var notification = new PaymentNotification.Request
{
NotifyPath = "/v1/payments/notify",
ClientId = Request.Headers["Client-Id"]!,
RequestTime = Request.Headers["Request-Time"]!,
SignatureHeader = Request.Headers["Signature"]!,
Body = JsonSerializer.Deserialize<PaymentNotification.RequestBody>(body)!
};
if (!superQi.VerifyPaymentNotification(notification))
return Unauthorized();
// Process the notification
return Ok();
}
Building
dotnet build
Testing
dotnet test
The test project (SuperQiSdk.Tests) targets .NET 9 and uses xUnit and Moq. All tests are pure unit tests — no network access or real credentials required.
Test coverage
Endpoint tests (EndpointTests)
Every service method is covered. Each test:
- Verifies the correct HTTP path is called (e.g.
/v1/payments/pay) - Supplies a canned JSON response and asserts all relevant fields are deserialized correctly
| Area | Methods covered |
|---|---|
| Authorization | ApplyTokenAsync (authorization code + refresh token), PrepareAsync |
| User info | InquiryUserInfoAsync, InquiryUserAccountListAsync, InquiryUserCardListAsync |
| Payments | PayAsync (cashier + agreement), InquiryPaymentAsync, MerchantAcceptAsync, ConfirmAsync, CancelAsync, VoidAsync |
| Refunds | RefundAsync, InquiryRefundAsync |
| Messaging | SendInboxAsync, SendPushAsync |
| Result status | Failed (F) and unknown (U) result deserialization |
| Constants | ApplyToken.GrantType, Pay.ProductCode |
Signature / notification tests (SuperQiServiceTests)
| Test | What it checks |
|---|---|
VerifyPaymentNotification_ValidSignature_ReturnsTrue |
Valid RSA-SHA256 signature passes |
VerifyPaymentNotification_TamperedBody_ReturnsFalse |
Modified body after signing is rejected |
VerifyPaymentNotification_MissingSignatureField_ReturnsFalse |
Header without signature= is rejected |
VerifyPaymentNotification_InvalidBase64Signature_ReturnsFalse |
Malformed base64 is rejected |
VerifyPaymentNotification_WrongKey_ReturnsFalse |
Signature from a different key is rejected |
ResultModel_IsSuccess_CorrectForStatus |
IsSuccess is true only for S, false for F/U/A |
ContactType_SerializesAsExpectedStrings |
Enum serializes to MOBILE_PHONE, not MobilePhone |
PaymentNotification_RequestBody_SerializesCorrectly |
JSON property names match API spec |
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Configuration.Binder (>= 10.0.8)
- Microsoft.Extensions.Http (>= 10.0.8)
-
net9.0
- Microsoft.Extensions.Configuration.Binder (>= 10.0.8)
- Microsoft.Extensions.Http (>= 10.0.8)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.3 | 193 | 5/27/2026 |