Skip to content

baasith6/Bpoint-Testing-Angular-.net

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BPOINT v3 Iframe Payment Module

.NET Angular SQL Server BPOINT License

Production-grade CommBank BPOINT Version 3 3-party iframe payment integration with a .NET 8 Web API backend and Angular 18 frontend.

Card data is entered only inside the BPOINT iframe. The Angular app never handles card numbers, expiry, CVV, or BPOINT credentials.


Table of contents


Overview

This repository demonstrates a secure, production-ready integration with CommBank BPOINT v3 using the 3-party iframe model. The backend creates an AuthKey, the frontend renders the BPOINT-hosted iframe, and payment confirmation is handled server-side via webhook and ResultKey lookup.

Designed for booking/invoice payment flows (e.g. Optimo portal integration) where PCI scope must stay minimal — your application never touches raw card data.

Features

  • 3-party BPOINT iframe — card data never touches Angular or your API
  • Backend-confirmed payments — webhook + ResultKey confirm; redirect query params are not trusted
  • Idempotent webhook handling — duplicate callbacks deduplicated by BPointTransactionNumber
  • Auto database bootstrap — API creates BpointPayments schema on startup
  • Pending payment expiry — stale payments auto-expired per booking
  • Optimo-compatible receipt stub — JSON:API creditCardReceipt payload logged for phase 1

Tech stack

Layer Technology Version
API ASP.NET Core Web API .NET 8
Frontend Angular (standalone components) 18.2
Database SQL Server / LocalDB
Gateway CommBank BPOINT v3 iframe API UAT + Production
Dev tunnel ngrok

Solution structure

├── backend/
│   ├── BpointPayment.sln
│   └── BpointPayment.Api/          # .NET 8 Web API
│       └── Payments/               # Payment module
├── database/
│   └── 001_CreatePaymentTables.sql
├── frontend/
│   └── bpoint-payment-web/         # Angular 18 SPA
│       └── src/app/bpoint-payment/
└── scripts/
    └── setup-ngrok.ps1             # Local tunnel helper

Architecture

Controller → Service → Repository → SQL Server
                    ↘ Gateway Client → BPOINT API
                    ↘ Receipt Posting Service (stub)
Layer Class Responsibility
Controller BPointPaymentsController Thin HTTP layer
Service BPointPaymentService Business rules, idempotency
Repository PaymentRepository ADO.NET parameterized SQL
Gateway BPointGatewayClient BPOINT AuthKey HTTP calls
Receipt StubReceiptPostingService JSON:API receipt payload (stub)

Payment flow

sequenceDiagram
    participant User
    participant Angular
    participant Api as DotNetApi
    participant Db as SqlServer
    participant BPoint as BPOINT_v3

    User->>Angular: Click Pay Now
    Angular->>Api: POST /api/payments/bpoint/create-iframe
    Api->>Db: Insert Payment Pending
    Api->>BPoint: POST /txns/processtxnauthkey
    BPoint-->>Api: AuthKey
    Api->>Db: Save AuthKey + InternalReference
    Api-->>Angular: paymentId + iframeUrl only
    Angular->>User: Render BPOINT iframe
    User->>BPoint: Enter card in iframe
    BPoint->>Angular: Redirect to /payment/bpoint/return?paymentId=...
    Angular->>Api: GET /api/payments/bpoint/status/{paymentId}
    BPoint->>Api: POST /api/payments/bpoint/webhook
    Api->>Db: Idempotent update to Paid
Loading

Important: Final payment confirmation comes from the backend — either via POST /confirm (ResultKey lookup against BPOINT) or the webhook. The Angular return page never marks a payment successful on redirect query params alone.


Quick start

  1. Clone the repository and install .NET 8 SDK, Node.js 18+, and SQL Server LocalDB (included with Visual Studio) or a local SQL Server instance.

  2. Configure BPOINT credentials via User Secrets (see Backend configuration):

    cd backend/BpointPayment.Api
    dotnet user-secrets set "BPoint:Username" "<api-username>"
    dotnet user-secrets set "BPoint:Password" "<api-password>"
    dotnet user-secrets set "BPoint:MerchantNumber" "<merchant-number>"
    dotnet user-secrets set "BPoint:MerchantShortName" "<merchant-short-name>"
  3. Start the API (auto-creates the database):

    cd backend/BpointPayment.Api
    dotnet run
  4. Start the frontend:

    cd frontend/bpoint-payment-web
    npm install
    npm start
  5. Open checkout at http://localhost:4200/payment/bpoint/checkout.

For full redirect and webhook testing locally, use ngrok.


Prerequisites

  • .NET 8 SDK
  • Node.js 18+ and npm
  • SQL Server LocalDB or a local/remote SQL Server instance
  • BPOINT v3 sandbox or production API credentials from CommBank

Database setup

The API automatically creates the BpointPayments database and tables on startup.

Default connection string in backend/BpointPayment.Api/appsettings.json:

"ConnectionStrings": {
  "PaymentDb": "Server=(localdb)\\MSSQLLocalDB;Database=BpointPayments;Integrated Security=True;TrustServerCertificate=True"
}
  • (localdb)\MSSQLLocalDB — SQL Server LocalDB (default for local dev on Windows)
  • Uses Windows Integrated Security (no SQL password required for local dev)

Alternative for a full local SQL Server instance, change Server to .:

"PaymentDb": "Server=.;Database=BpointPayments;Integrated Security=True;TrustServerCertificate=True"

Just start the API — no manual sqlcmd step is required:

cd backend/BpointPayment.Api
dotnet run

Optional manual script

If you prefer to create the schema manually, run:

sqlcmd -S "(localdb)\MSSQLLocalDB" -E -i database/001_CreatePaymentTables.sql

For a full SQL Server instance, use -S . instead.


Backend configuration

Edit backend/BpointPayment.Api/appsettings.json:

"BPoint": {
  "BaseUrl": "https://bpoint.uat.linkly.com.au/webapi/v3",
  "PaymentBaseUrl": "https://bpoint.uat.linkly.com.au/pay",
  "Username": "<your-bpoint-api-username>",
  "Password": "<your-bpoint-api-password>",
  "MerchantNumber": "<merchant-number>",
  "MerchantShortName": "<merchant-short-name>",
  "BillerCode": "",
  "RedirectUrl": "http://localhost:4200/payment/bpoint/return",
  "WebhookUrl": "https://<your-public-tunnel>/api/payments/bpoint/webhook",
  "TestMode": true
}

UAT vs production

Environment API BaseUrl PaymentBaseUrl
UAT (test) https://bpoint.uat.linkly.com.au/webapi/v3 https://bpoint.uat.linkly.com.au/pay
Production https://www.bpoint.com.au/webapi/v3 https://www.bpoint.com.au/pay

UAT credentials must use UAT URLs. Using UAT credentials against production causes Invalid login details.

Optimo / portal credential mapping

Portal setting Config key Example value
Bpoint Url BaseUrl https://bpoint.uat.linkly.com.au/webapi/v3
Merchant ID MerchantNumber <merchant-number>
API Username Username <api-username>
API User Password Password (in User Secrets)
MerchantShortName MerchantShortName <merchant-short-name>
DefaultBillerCode BillerCode `` (empty)
Bpoint Payment Url host PaymentBaseUrl https://bpoint.uat.linkly.com.au/pay

BPOINT credential fields

CommBank provides separate values — do not mix them up:

Config key Example Used for
Username API user from BPOINT Basic auth: username|merchantnumber:password → Base64
Password API user password Same Basic auth header
MerchantNumber <merchant-number> Basic auth + ProcessTxnData.MerchantNumber in API body
MerchantShortName <merchant-short-name> Hosted payment page: {PaymentBaseUrl}/{MerchantShortName}?in_pay_token={authKey}
PaymentBaseUrl https://bpoint.uat.linkly.com.au/pay Base for redirect/HPP flow only

Current iframe flow uses {BaseUrl}/txns/iframe/{authKey} (e.g. https://bpoint.uat.linkly.com.au/webapi/v3/txns/iframe/{authKey}).

Auth is already Base64-encoded in BPointGatewayClient — you do not need to encode credentials manually.

Production secrets

Do not commit real credentials. Override via:

  • User Secrets (local dev, recommended):
    cd backend/BpointPayment.Api
    dotnet user-secrets set "BPoint:Username" "<api-username>"
    dotnet user-secrets set "BPoint:Password" "<api-password>"
    dotnet user-secrets set "BPoint:MerchantNumber" "<merchant-number>"
    dotnet user-secrets set "BPoint:MerchantShortName" "<merchant-short-name>"
  • Environment variables: BPoint__Password, BPoint__Username, etc.
  • Azure Key Vault or your secret manager

BPOINT auth format: The API uses Basic auth with username|merchantnumber:password (pipe + colon). This is built automatically from Username, MerchantNumber, and Password in config. Use a dedicated API user from BPOINT Merchant Back Office — not your normal login.

If Pay Now fails in Development with "Payment gateway authentication failed", the BPOINT API user, password, or merchant number is incorrect — not the local RedirectUrl.


Run the backend

cd backend/BpointPayment.Api
dotnet run
  • Swagger: https://localhost:7044/swagger
  • API base: https://localhost:7044

API endpoints

Method Path Description
POST /api/payments/bpoint/create-iframe Create pending payment + BPOINT AuthKey
POST /api/payments/bpoint/confirm Confirm payment via BPOINT ResultKey (return page)
POST /api/payments/bpoint/webhook BPOINT webhook callback
GET /api/payments/bpoint/status/{paymentId} Poll payment status

Create iframe request

{
  "bookingId": 10001,
  "invoiceIds": [20001],
  "amount": 660.00,
  "customerEmail": "customer@example.com",
  "customerName": "John Smith"
}

Create iframe response

{
  "paymentId": 123,
  "iframeUrl": "https://bpoint.uat.linkly.com.au/webapi/v3/txns/iframe/{authKey}",
  "status": "Pending"
}

Run the frontend

cd frontend/bpoint-payment-web
npm start
  • Checkout: http://localhost:4200/payment/bpoint/checkout
  • Return page: http://localhost:4200/payment/bpoint/return

The dev server proxies /api to https://localhost:7044 via proxy.conf.json.

See frontend/bpoint-payment-web/README.md for frontend-only commands.


Local network / iframe redirect (Chrome)

After entering card details, Chrome may block the BPOINT iframe with:

The connection is blocked because it was initiated by a public page to connect to devices or servers on your local network.

This happens because the iframe loads from public BPOINT (https://bpoint.uat.linkly.com.au) but RedirectUrl is http://localhost:4200. Modern browsers block public pages from navigating to localhost (Private Network Access).

Fix for local testing: expose the Angular app on a public HTTPS URL and use that for RedirectUrl:

# Terminal 1 — Angular (already running on 4200)
ng serve

# Terminal 2 — public tunnel to the Angular dev server
ngrok http 4200

Or use the helper script: scripts/setup-ngrok.ps1

Set BPoint:RedirectUrl (User Secrets or appsettings.Development.json) to:

https://<tunnel-host>/payment/bpoint/return

Open checkout via the tunnel URL (not localhost:4200) when testing the full redirect flow.

The checkout page also polls payment status while the iframe is open, so if the iframe redirect is blocked but the webhook succeeds, you are still sent to the return page automatically.


Webhook testing (local)

BPOINT must reach your webhook over HTTPS on port 443. Use a tunnel:

# Recommended: direct tunnel to the API (more reliable for server-to-server webhooks)
ngrok http https://localhost:7044

Set BPoint:WebhookUrl to:

https://<api-tunnel-host>/api/payments/bpoint/webhook

For the redirect URL, use a separate ngrok tunnel to Angular (or the same host if you proxy both):

ngrok http 4200

Set BPoint:RedirectUrl to:

https://<angular-tunnel-host>/payment/bpoint/return

Notes:

  • WebHookUrl is registered when the AuthKey is created. Restart the API after changing User Secrets, then start a new payment to pick up the new webhook URL.
  • API logs BPOINT AuthKey will include WebHookUrl when a webhook is configured, or warns when it is omitted.
  • Check ngrok inspector at http://127.0.0.1:4040 to see if BPOINT POSTed the webhook.
  • ngrok free interstitial can block BPOINT server callbacks — direct tunnel to port 7044 is more reliable than routing webhooks through the Angular proxy.

BPOINT retries failed webhooks hourly for 24 hours. Duplicate webhooks are handled idempotently by BPointTransactionNumber.


Security notes

  • BPOINT credentials exist only in backend configuration
  • Angular environment.ts contains only apiBaseUrl (empty in dev — uses proxy)
  • No card input fields in Angular
  • iframe URL comes from backend only; sanitized with DomSanitizer.bypassSecurityTrustResourceUrl
  • Webhook payloads are sanitized before storage (card number / CVN redacted)
  • Safe error messages returned to frontend; technical details logged server-side only
  • Return URL query parameters are not trusted for payment confirmation
  • Optional: restrict webhook endpoint to BPOINT webhook IP ranges

Receipt posting (phase 1 stub)

StubReceiptPostingService builds the Optimo-compatible creditCardReceipt JSON:API payload and logs it. Enable in development:

"ReceiptPosting": { "Enabled": true }

When ready for production, replace the stub with a real gateway client posting to POST /api/v4.1/payments.


Testing checklist

  • POST create-iframe returns paymentId + iframeUrl only
  • iframe loads at {BaseUrl}/txns/iframe/{authKey}
  • BPOINT test card completes; iframe redirects to return URL with paymentId
  • Return page calls /confirm when ResultKey is present, then shows Paid
  • Return page shows Pending then Paid after webhook (if user closes browser early)
  • Webhook updates DB to Paid with txn fields populated
  • Duplicate webhook does not create duplicate receipt (ReceiptPosted stays single)
  • Failed BPOINT AuthKey marks payment Failed; checkout shows error
  • Network tab / Angular bundle contains no BPOINT credentials
  • Angular has no card input elements
  • Active pending payment blocked for same booking
  • GET status never returns AuthKey or passwords

Troubleshooting

Issue Likely cause
AuthKey fails Missing/invalid BPOINT credentials or merchant config
iframe blank Wrong BaseUrl or AuthKey expired
Status stays Pending (redirect shows Success) Webhook not received; return page should call /confirm with ResultKey. Check API logs and ngrok inspector
Redirect shows Success but page says Pending Expected until backend confirms — reload return URL or wait for /confirm + polling
"blocked... local network" in iframe after card submit RedirectUrl points to localhost; use ngrok tunnel URL for Angular + webhook tunnel for API
409 on create Another Pending/Processing payment exists for the booking
DB errors Run 001_CreatePaymentTables.sql and verify connection string

Repository metadata

These settings improve discoverability on GitHub. They are configured in the repository settings, not in source files.

Recommended description:

Production-grade BPOINT v3 3-party iframe payment integration with .NET 8 Web API and Angular 18.

Recommended topics:

bpoint · payment-gateway · payment-integration · commbank · commonwealth-bank · iframe-payment · dotnet · dotnet-8 · aspnet-core · webapi · angular · angular18 · typescript · sql-server · rxjs · pci-compliant · webhook · ngrok · australia · fintech

Apply via GitHub CLI:

gh repo edit baasith6/Bpoint-Testing-Angular-.net --description "Production-grade BPOINT v3 3-party iframe payment integration with .NET 8 Web API and Angular 18."
gh repo edit baasith6/Bpoint-Testing-Angular-.net --add-topic bpoint,payment-gateway,payment-integration,commbank,dotnet,dotnet-8,aspnet-core,angular,angular18,typescript,sql-server,webhook,fintech

Or set description and topics manually under Settings → General on GitHub.


Related links


License

This project is licensed under the MIT License.

Copyright (c) 2026 Abdul Baasith

About

Production-grade BPOINT v3 3-party iframe payment integration with .NET 8 Web API and Angular 18.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors