Seamlessly integrate multiple payment gateways into your ASP.NET Core applications.
Features • Getting Started • Usage • Sample Payloads & Responses • Contributing • License
The redesigned docs site is published on GitHub Pages:
Use it as the canonical operational guide for setup, security hardening, routing, idempotency, and integration testing.
- Unified API: Interact with multiple payment gateways (e.g., Flutterwave, Paystack, Stripe, Korapay, PeachPayments) through a single, consistent interface.
- Database Flexibility: Choose between PayBridge's default database or integrate with your own.
- Transaction Logging: Automatically records transaction details for auditing and reporting.
- Extensible Architecture: Built with Clean Architecture principles for maintainability and scalability.
- .NET 8.0 SDK
- SQL Server or another supported database
git clone https://github.com/teesofttech/PayBridge.git
cd PayBridgeKeep connection strings out of tracked configuration. For local development, store one with .NET user-secrets:
dotnet user-secrets set"ConnectionStrings:PayBridgeDbContext" \
"<your-local-connection-string>" \
--project PayBridge.SDK.Example/PayBridge.SDK.Example.csprojKorapay website: https://www.korahq.com/
dotnet user-secrets set"PaymentGatewayConfig:EnabledGateways:0""Korapay" \
--project PayBridge.SDK.Example/PayBridge.SDK.Example.csproj
dotnet user-secrets set"PaymentGatewayConfig:Korapay:PublicKey""<sandbox-public-key>" \
--project PayBridge.SDK.Example/PayBridge.SDK.Example.csproj
dotnet user-secrets set"PaymentGatewayConfig:Korapay:SecretKey""<sandbox-secret-key>" \
--project PayBridge.SDK.Example/PayBridge.SDK.Example.csprojUse environment variables or a managed secret store in deployed environments.
Never commit sandbox or live credentials to appsettings*.json.
dotnet ef database updatedotnet build
dotnet run[Route("api/[controller]")][ApiController]publicclassPaymentController:ControllerBase{privatereadonlyIPaymentService_paymentService;privatereadonlyILogger<PaymentController>_logger;publicPaymentController(IPaymentServicepaymentService,ILogger<PaymentController>logger){_paymentService=paymentService??thrownewArgumentNullException(nameof(paymentService));_logger=logger??thrownewArgumentNullException(nameof(logger));}[HttpPost]publicasyncTask<IActionResult>CreatePayment([FromBody]CreatePaymentRequestrequest){try{_logger.LogInformation("Creating payment for {Amount} {Currency}",request.Amount,request.Currency);varpaymentRequest=PaymentRequestMapper.MapToPaymentRequest(request);varpaymentGateway=request.Gateway??PaymentGatewayType.Automatic;varresponse=await_paymentService.CreatePaymentAsync(paymentRequest,paymentGateway);if(response.Success){_logger.LogInformation("Payment created successfully: {Reference}",response.TransactionReference);returnOk(response);}else{_logger.LogWarning("Payment creation failed: {Message}",response.Message);returnBadRequest(newErrorResponse{Message=response.Message,ErrorCode="PAYMENT_FAILED"});}}catch(Exceptionex){_logger.LogError(ex,"Error creating payment");returnStatusCode(500,newErrorResponse{Message="An error occurred while processing your payment",ErrorCode="INTERNAL_ERROR"});}}[HttpGet("verify-transaction")]publicasyncTask<IActionResult>VerifyTransaction(){try{varqueryParams=HttpContext.Request.Query;varallParams=newDictionary<string,string>();foreach(varparaminqueryParams){if(param.Key.Contains("reference",StringComparison.OrdinalIgnoreCase)||param.Key.Contains("tx_ref",StringComparison.OrdinalIgnoreCase)){allParams["reference"]=param.Value!;}}PaymentGatewayTypegateway=GatewayExtractor.DetectGatewayFromWebhook(allParams.Values);stringreference=allParams.Values.FirstOrDefault()!.ToString()!;if(string.IsNullOrEmpty(reference)){_logger.LogWarning("Could not extract transaction reference from Query");returnBadRequest(newErrorResponse{Message="Could not extract transaction reference from Query",ErrorCode="INVALID_REQUEST"});}varresponse=await_paymentService.VerifyPaymentAsync(reference,gateway);if(response.Success){_logger.LogInformation("Query verification successful: {Reference}, Status: {Status}",reference,response.Status);returnOk(new{success=true,response});}else{_logger.LogWarning("Query verification failed: {Message}",response.Message);returnBadRequest(newErrorResponse{Message=response.Message,ErrorCode="QUERY_VERIFICATION_FAILED"});}}catch(Exceptionex){_logger.LogError(ex,"Error processing Query");returnStatusCode(500,newErrorResponse{Message="An error occurred while processing the Query",ErrorCode="INTERNAL_ERROR"});}}}{
"amount": 1000,
"currency": "NGN",
"description": "est",
"customerEmail": "tunde@yopmail.com",
"customerName": "string",
"customerPhone": "string",
"redirectUrl": "https://localhost:7252/api/payment/verify-transaction",
"webhookUrl": "https://localhost:7252/api/payment/verify-transaction",
"metadata": {
"additionalProp1": "string",
"additionalProp2": "string",
"additionalProp3": "string"
},
"paymentMethodType": 0,
"savedPaymentMethodId": "string",
"gateway": 1
}{
"success": true,
"transactionReference": "FLW_dc324e96d52b4bd48c401ff9194c15e8",
"message": "Hosted Link",
"checkoutUrl": "https://checkout-v2.dev-flutterwave.com/v3/hosted/pay/207b10ab0a05ddf19746",
"status": 0,
"gatewayResponse": {
"link": "https://checkout-v2.dev-flutterwave.com/v3/hosted/pay/207b10ab0a05ddf19746"
}
}We welcome your ideas, improvements, and fixes!
- Fork the repo → PayBridge on GitHub
- Clone your fork:
git clone https://github.com/teesofttech/PayBridge.git- Create a feature branch:
git checkout -b feature/your-feature-name- Implement, Commit, and Push:
git commit -m "feat: add new feature"
git push origin feature/your-feature-name- Create a Pull Request and describe your changes.
🙌 Your support helps make PayBridge better for everyone!
PayBridge is released under the MIT License.
You're free to use, modify, and distribute this software as long as the original license is included.