feat: implement InterswitchGateway (Nigeria - Quickteller/Webpay)#28
Conversation
|
Warning Review limit reached
More reviews will be available in 15 minutes and 26 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe PR adds Interswitch (Nigeria's largest payment network) as a new gateway to PayBridge SDK. A new ChangesInterswitch Payment Gateway
Sequence Diagram(s)The diagram above illustrates the three main payment operations (create, verify, refund) executed by Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds support for the Interswitch (Quickteller/Webpay) payment gateway to the PayBridge SDK, enabling Nigeria (NGN) routing and transaction-reference based gateway detection.
Changes:
- Introduces a new
InterswitchGatewayimplementation with OAuth token retrieval, request signing, create/verify/refund flows, and sandbox/live switching. - Extends configuration and enums to support the new gateway (
PaymentGatewayType.Interswitch,InterswitchConfig). - Wires Interswitch into gateway selection/routing and DI/factory registration.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| PayBridge.SDK/Services/PaymentService.cs | Prefer Interswitch for NGN and detect ISW_ references as Interswitch. |
| PayBridge.SDK/Gateways/InterswitchGateway.cs | New gateway implementation: OAuth token fetch, signing headers, create/verify/refund calls. |
| PayBridge.SDK/Factories/PaymentGatewayFactory.cs | Adds Interswitch to factory initialization and resolution switch. |
| PayBridge.SDK/Externsions/IServiceCollectionExtensions.cs | Registers InterswitchGateway in DI for “all gateways” and “enabled gateways” modes. |
| PayBridge.SDK/Enums/PaymentGatewayType.cs | Adds Interswitch = 7 enum member. |
| PayBridge.SDK/Dtos/PaymentGatewayConfig.cs | Adds InterswitchConfig settings section to the SDK config model. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var accessToken = await GetAccessTokenAsync(); | ||
| var txRef = $"ISW_{Guid.NewGuid():N}"; |
| services.AddScoped<CheckoutGateway>(); | ||
| services.AddScoped<BenefitPayGateway>(); | ||
| services.AddScoped<KnetGateway>(); | ||
| services.AddScoped<InterswitchGateway>(); |
559103d to
3c51bcc
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@PayBridge.SDK/Externsions/IServiceCollectionExtensions.cs`:
- Line 140: InterswitchGateway is only registered as the concrete type
(services.AddScoped<InterswitchGateway>), so PaymentService (which resolves
IEnumerable<IPaymentGateway>) never receives it; change the registration to
register it as IPaymentGateway as well (e.g., register InterswitchGateway with
the IPaymentGateway service) in the same places where InterswitchGateway is
currently added (the default registration at
services.AddScoped<InterswitchGateway>() and the PaymentGatewayType.Interswitch
branch) so PaymentService can discover it via IEnumerable<IPaymentGateway>.
In `@PayBridge.SDK/Gateways/InterswitchGateway.cs`:
- Around line 73-74: The code is logging full Interswitch response bodies (e.g.,
the _logger.LogDebug call that prints "Interswitch auth response: {Body}" and
the similar calls at the other sites), which can expose tokens and PII; update
the InterswitchGateway logging so it no longer emits raw response bodies—instead
parse the JSON/response in the methods where those LogDebug calls occur (in the
InterswitchGateway class), extract and log only safe fields such as status,
correlationId/transactionId, and HTTP status code, and redact or omit sensitive
fields (access_token, customer data, payment details) before any logging; apply
the same change to the other occurrences referenced (the similar
LogDebug/LogInformation calls) and ensure any exception-path logs also avoid
printing full response payloads.
- Around line 116-117: In InterswitchGateway replace the unsafe truncating cast
for request.Amount -> amount (currently "(int)(request.Amount * 100)") with a
rounded, checked conversion: compute the kobo value using rounding (e.g.
Math.Round or equivalent with MidpointRounding.AwayFromZero) and then cast
inside a checked context so overflow raises an exception you can handle; ensure
you catch/handle OverflowException and log/return a clear error rather than
sending a wrong amount to the gateway. Apply the same change to the other
occurrence that sets amount (the second block similar to currencyCode = "566")
so both conversions use rounded+checked conversion and proper error handling.
- Around line 43-44: The constructor for InterswitchGateway currently validates
MerchantCode but not PaymentItemCode, allowing runtime failures in
CreatePaymentAsync; add a guard in the InterswitchGateway constructor to
validate _config.Interswitch.PaymentItemCode (same pattern as the existing
MerchantCode check) and throw an InvalidOperationException with a clear message
like "Interswitch PaymentItemCode is required" so misconfiguration is caught at
startup rather than at CreatePaymentAsync when payableCode is sent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: b5f55c72-1c94-48ac-ae4e-88d8837c0783
📒 Files selected for processing (6)
PayBridge.SDK/Dtos/PaymentGatewayConfig.csPayBridge.SDK/Enums/PaymentGatewayType.csPayBridge.SDK/Externsions/IServiceCollectionExtensions.csPayBridge.SDK/Factories/PaymentGatewayFactory.csPayBridge.SDK/Gateways/InterswitchGateway.csPayBridge.SDK/Services/PaymentService.cs
| services.AddScoped<SquadGateway>(); | ||
| services.AddScoped<KorapayGateway>(); | ||
| services.AddScoped<IPaymentGateway>(sp => sp.GetRequiredService<KorapayGateway>()); | ||
| services.AddScoped<InterswitchGateway>(); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== PaymentService dependency shape =="
rg -n -C2 'IEnumerable<IPaymentGateway>|ToDictionary\(g => g\.GatewayType\)' PayBridge.SDK/Services/PaymentService.cs
echo
echo "== Interswitch registrations =="
rg -n -C2 'InterswitchGateway|PaymentGatewayType\.Interswitch|IPaymentGateway' \
PayBridge.SDK/Externsions/IServiceCollectionExtensions.cs \
PayBridge.SDK/Factories/PaymentGatewayFactory.csRepository: teesofttech/PayBridge
Length of output: 6282
Fix InterswitchGateway registration so PaymentService can resolve it via IEnumerable<IPaymentGateway>
PaymentService injects IEnumerable<IPaymentGateway> and builds _gateways with gateways.ToDictionary(g => g.GatewayType), but InterswitchGateway is only registered as the concrete type (services.AddScoped<InterswitchGateway>();) in both the default path (line 140) and case PaymentGatewayType.Interswitch (178-180). Unlike other gateways, it is not also registered as IPaymentGateway, so PaymentGatewayType.Interswitch won’t be present in PaymentService’s gateway map.
Suggested fix
services.AddScoped<InterswitchGateway>();
+services.AddScoped<IPaymentGateway>(sp => sp.GetRequiredService<InterswitchGateway>());
...
case PaymentGatewayType.Interswitch:
services.AddScoped<InterswitchGateway>();
+ services.AddScoped<IPaymentGateway>(sp => sp.GetRequiredService<InterswitchGateway>());
break;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@PayBridge.SDK/Externsions/IServiceCollectionExtensions.cs` at line 140,
InterswitchGateway is only registered as the concrete type
(services.AddScoped<InterswitchGateway>), so PaymentService (which resolves
IEnumerable<IPaymentGateway>) never receives it; change the registration to
register it as IPaymentGateway as well (e.g., register InterswitchGateway with
the IPaymentGateway service) in the same places where InterswitchGateway is
currently added (the default registration at
services.AddScoped<InterswitchGateway>() and the PaymentGatewayType.Interswitch
branch) so PaymentService can discover it via IEnumerable<IPaymentGateway>.
| if (string.IsNullOrEmpty(_config.Interswitch.MerchantCode)) | ||
| throw new InvalidOperationException("Interswitch MerchantCode is required"); |
There was a problem hiding this comment.
Validate PaymentItemCode in constructor like other required credentials.
CreatePaymentAsync always sends payableCode; allowing empty config here shifts a deterministic misconfiguration into runtime API failures.
Suggested fix
if (string.IsNullOrEmpty(_config.Interswitch.MerchantCode))
throw new InvalidOperationException("Interswitch MerchantCode is required");
+if (string.IsNullOrEmpty(_config.Interswitch.PaymentItemCode))
+ throw new InvalidOperationException("Interswitch PaymentItemCode is required");📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (string.IsNullOrEmpty(_config.Interswitch.MerchantCode)) | |
| throw new InvalidOperationException("Interswitch MerchantCode is required"); | |
| if (string.IsNullOrEmpty(_config.Interswitch.MerchantCode)) | |
| throw new InvalidOperationException("Interswitch MerchantCode is required"); | |
| if (string.IsNullOrEmpty(_config.Interswitch.PaymentItemCode)) | |
| throw new InvalidOperationException("Interswitch PaymentItemCode is required"); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@PayBridge.SDK/Gateways/InterswitchGateway.cs` around lines 43 - 44, The
constructor for InterswitchGateway currently validates MerchantCode but not
PaymentItemCode, allowing runtime failures in CreatePaymentAsync; add a guard in
the InterswitchGateway constructor to validate
_config.Interswitch.PaymentItemCode (same pattern as the existing MerchantCode
check) and throw an InvalidOperationException with a clear message like
"Interswitch PaymentItemCode is required" so misconfiguration is caught at
startup rather than at CreatePaymentAsync when payableCode is sent.
| _logger.LogDebug("Interswitch auth response: {Body}", body); | ||
|
|
There was a problem hiding this comment.
Avoid logging raw Interswitch response bodies.
These logs can expose access tokens, customer data, and transaction metadata. Log status/correlation fields instead.
Suggested hardening
- _logger.LogDebug("Interswitch auth response: {Body}", body);
+ _logger.LogDebug("Interswitch auth response received. StatusCode: {StatusCode}", (int)response.StatusCode);
- _logger.LogDebug("Interswitch create payment response: {Response}", responseBody);
+ _logger.LogDebug("Interswitch create payment response received. StatusCode: {StatusCode}", (int)response.StatusCode);
- _logger.LogDebug("Interswitch verify response: {Response}", responseBody);
+ _logger.LogDebug("Interswitch verify response received. StatusCode: {StatusCode}", (int)response.StatusCode);
- _logger.LogDebug("Interswitch refund response: {Response}", responseBody);
+ _logger.LogDebug("Interswitch refund response received. StatusCode: {StatusCode}", (int)response.StatusCode);Also applies to: 134-135, 189-190, 277-278
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@PayBridge.SDK/Gateways/InterswitchGateway.cs` around lines 73 - 74, The code
is logging full Interswitch response bodies (e.g., the _logger.LogDebug call
that prints "Interswitch auth response: {Body}" and the similar calls at the
other sites), which can expose tokens and PII; update the InterswitchGateway
logging so it no longer emits raw response bodies—instead parse the
JSON/response in the methods where those LogDebug calls occur (in the
InterswitchGateway class), extract and log only safe fields such as status,
correlationId/transactionId, and HTTP status code, and redact or omit sensitive
fields (access_token, customer data, payment details) before any logging; apply
the same change to the other occurrences referenced (the similar
LogDebug/LogInformation calls) and ensure any exception-path logs also avoid
printing full response payloads.
| amount = (int)(request.Amount * 100), // in kobo | ||
| currencyCode = "566", // ISO 4217 numeric code for NGN |
There was a problem hiding this comment.
Use rounded checked conversion for kobo amounts.
Direct (int)(amount * 100) truncates fractional values and can overflow. That can send wrong amounts to the gateway.
Suggested fix
+ private static long ToKobo(decimal amount) =>
+ checked((long)Math.Round(amount * 100m, MidpointRounding.AwayFromZero));
...
- amount = (int)(request.Amount * 100), // in kobo
+ amount = ToKobo(request.Amount), // in kobo
...
- amount = (int)(request.Amount * 100),
+ amount = ToKobo(request.Amount),Also applies to: 261-262
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@PayBridge.SDK/Gateways/InterswitchGateway.cs` around lines 116 - 117, In
InterswitchGateway replace the unsafe truncating cast for request.Amount ->
amount (currently "(int)(request.Amount * 100)") with a rounded, checked
conversion: compute the kobo value using rounding (e.g. Math.Round or equivalent
with MidpointRounding.AwayFromZero) and then cast inside a checked context so
overflow raises an exception you can handle; ensure you catch/handle
OverflowException and log/return a clear error rather than sending a wrong
amount to the gateway. Apply the same change to the other occurrence that sets
amount (the second block similar to currencyCode = "566") so both conversions
use rounded+checked conversion and proper error handling.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Summary
Implements the Interswitch payment gateway (Quickteller/Webpay) for Nigerian payments.
Changes
Interswitch = 7toPaymentGatewayTypeenumInterswitchConfig(ClientId, ClientSecret, MerchantCode, PaymentItemCode, IsSandbox) toPaymentGatewayConfig.csInterswitchGateway.cswith full implementation:api.interswitchgroup.com) / Sandbox (sandbox.interswitchng.com) toggle00= success,T0= pendingISW_InterswitchGatewayinIServiceCollectionExtensions.csPaymentGatewayFactory.csPaymentService.cs: NGN routing +ISW_prefix detectionCloses #11
Summary by CodeRabbit
New Features