# PayTR Enterprise SDK ### Production-oriented PayTR integration for ASP.NET Core 10 and Node.js 20+ A security-focused, server-side PayTR integration toolkit with runnable API applications, callback verification, financial-operation safeguards, health checks, OpenAPI documentation, SQL Server reference persistence, and CI quality gates.
Bilhost Bilişim Teknolojileri A.Ş. Sponsored by Bilhost Infrastructure sponsorship and project support provided by Bilhost Bilişim Teknolojileri A.Ş.

Release License Documentation

.NET ASP.NET Core Node.js OpenAPI SQL Server

HMAC Callbacks API Versioning

**Current release:** `2.5.0` **Runtimes:** `.NET 10 / ASP.NET Core 10` and `Node.js 20+` **Payment provider:** [PayTR](https://www.paytr.com/) **Official provider documentation:** [dev.paytr.com](https://dev.paytr.com/)
--- ## Table of contents - [Overview](#overview) - [Project status](#project-status) - [What this project provides](#what-this-project-provides) - [Supported PayTR capabilities](#supported-paytr-capabilities) - [Engineering principles](#engineering-principles) - [Runtime matrix](#runtime-matrix) - [Requirements](#requirements) - [Quick start](#quick-start) - [ASP.NET Core](#aspnet-core) - [Node.js](#nodejs) - [Configuration](#configuration) - [ASP.NET configuration](#aspnet-configuration) - [Node.js configuration](#nodejs-configuration) - [Configuration precedence](#configuration-precedence) - [Production secret management](#production-secret-management) - [Authentication and authorization](#authentication-and-authorization) - [API surface](#api-surface) - [Payment flow](#payment-flow) - [Callback processing](#callback-processing) - [Direct API and card-data boundary](#direct-api-and-card-data-boundary) - [Refund and financial mutation safety](#refund-and-financial-mutation-safety) - [Stored cards and recurring payments](#stored-cards-and-recurring-payments) - [Link API](#link-api) - [Platform and returned transfers](#platform-and-returned-transfers) - [Reporting](#reporting) - [Persistence and idempotency](#persistence-and-idempotency) - [Background reconciliation](#background-reconciliation) - [Health checks](#health-checks) - [Observability](#observability) - [Security controls](#security-controls) - [OpenAPI and Postman](#openapi-and-postman) - [SQL Server reference schema](#sql-server-reference-schema) - [Reverse proxy and HTTPS](#reverse-proxy-and-https) - [Testing and quality gates](#testing-and-quality-gates) - [CI and static analysis](#ci-and-static-analysis) - [Troubleshooting](#troubleshooting) - [Versioning](#versioning) - [Security policy](#security-policy) - [Contributing](#contributing) - [License](#license) - [Provider responsibility notice](#provider-responsibility-notice) --- ## Overview PayTR Enterprise SDK is an independent server-side integration project that organizes PayTR payment operations into a reusable, auditable, and production-oriented backend layer for ASP.NET Core and Node.js applications. The project intentionally goes beyond a minimal request example. It includes application-level controls required around payment integrations: input validation, HMAC signing, callback verification, internal API authorization, rate limiting, CORS policy, request-size limits, correlation IDs, health checks, reconciliation primitives, example persistence models, operational documentation, and deployment assets. Two implementation families are maintained: | Runtime | Primary application | Runnable example | Configuration | Hosting model | |---|---|---|---|---| | ASP.NET Core | `PayTR` | `PayTRExample` | `appsettings*.json` + standard ASP.NET environment overrides | Kestrel / IIS / reverse proxy | | Node.js | `PayTR` | `PayTRExample` | `appsettings*.json` + explicit environment-variable overrides | Native Node.js HTTP server / reverse proxy | The primary applications contain the project code and the PayTR integration layer. The example applications are designed to be runnable references for local integration testing and application wiring. > [!IMPORTANT] > This repository is an independent integration toolkit. It is **not an official PayTR SDK**. Provider-side permissions, field requirements, endpoints, callback semantics, commercial conditions, and merchant-account capabilities must always be validated against the current PayTR documentation and the merchant account before production rollout. > [!CAUTION] > Payment systems are financial systems. Never treat a redirect page, browser response, or client-side state as final payment confirmation. Final order state must be driven by an authenticated server-to-server provider callback and an idempotent business transition. --- ## Project status The current repository release is `2.5.0`. The Node.js applications include automated tests and syntax-oriented quality scripts. The repository also includes GitHub Actions definitions for Node.js, .NET, and CodeQL-oriented analysis. For production release decisions, use **your own CI results from the exact commit you intend to deploy**. Do not rely on README text as build evidence. A complete release should require, at minimum: - clean dependency restore; - successful compilation/build; - automated test success; - security/static-analysis review; - provider callback verification in a non-production environment; - a successful end-to-end payment scenario using approved test settings; - confirmation that no secrets are committed; - confirmation that production feature flags match PayTR merchant permissions; - explicit rollback and reconciliation procedures. --- ## What this project provides ### Server-side integration layer The project centralizes provider-facing behavior such as: - credential loading; - request validation; - request signing; - callback signature verification; - PayTR HTTP calls; - provider-response handling; - payment status lookup; - refund requests; - link operations; - stored-card operations; - recurring payment requests; - transfer workflows; - reporting requests. ### Runnable APIs Both runtime families expose runnable HTTP APIs for integration testing and reference hosting. Their public server-side responsibilities include: - provider operations behind an internal API key; - PayTR callback endpoints; - readiness and liveness endpoints; - safe configuration-status output; - reconciliation queue entry points where implemented. ### Operational baseline The repository also includes: - OpenAPI `3.1` contract assets; - Postman collection assets; - SQL Server reference persistence objects; - GitHub Actions workflows; - security policy; - contribution policy; - detailed changelog; - production-oriented documentation. --- ## Supported PayTR capabilities The codebase exposes integration support for the following PayTR-oriented workflows. ### Checkout - iFrame token creation; - iFrame V2-compatible options exposed by the implementation; - Havale / EFT iFrame token creation; - Direct API signed form-field generation; - BKM Express signed form-field generation behind a feature gate. ### Payment lifecycle - payment-result callback verification; - merchant-order payment-status query; - full refund requests; - partial refund requests; - reconciliation queueing. ### Link API - payment-link creation; - link deletion; - link delivery by SMS; - link delivery by email; - Link API callback verification. ### Stored-card and recurring operations - stored-card listing by user token; - stored-card deletion; - recurring payment requests using provider-issued card tokens. ### Card metadata - BIN lookup; - installment-rate lookup. ### Platform operations - platform transfer request; - platform transfer callback verification; - returned-transfer list operation; - returned-transfer send operation; - returned-transfer callback verification. ### Reports - transaction statement; - payment summary; - payment detail. > [!NOTE] > A locally exposed operation does not prove that the corresponding PayTR capability is enabled for a merchant. Some services require account-specific authorization or commercial enablement. --- ## Engineering principles ### 1. Secrets stay on trusted servers `merchant_id`, `merchant_key`, `merchant_salt`, production internal API keys, access tokens, PAN, CVV/CVC, and comparable sensitive data must never be embedded in frontend code or public repositories. ### 2. Callback verification precedes business mutation No callback should change payment, order, transfer, or refund state until its signature has been validated. ### 3. Callbacks are treated as repeatable delivery Provider callbacks can be delivered more than once. Business transitions must therefore be idempotent. ### 4. Financial mutations are not blindly retried Refunds, transfers, and other money-changing operations may create ambiguous outcomes when network failures occur after the provider accepted a request. Reconciliation and status lookup are safer than automatic repetition. ### 5. High-risk capabilities are feature-gated Direct API and BKM Express support are disabled by default in the application configuration. ### 6. Runtime behavior is explicit The project uses explicit configuration files, explicit environment overrides, bounded request sizes, bounded timeouts, and named health endpoints. ### 7. Error responses do not reveal secrets API errors are normalized and should not expose merchant credentials, provider tokens, stack traces, or cardholder data. --- ## Runtime matrix | Capability | ASP.NET Core | Node.js | |---|---:|---:| | Target/runtime | `.NET 10` | `Node.js >=20` | | Primary API application | Yes | Yes | | Runnable example application | Yes | Yes | | HMAC-SHA256 signing | Yes | Yes | | Constant-time hash comparison | Yes | Yes | | JSON appsettings | Yes | Yes | | Environment overrides | ASP.NET configuration providers | Explicit environment mapping | | Internal API key | Yes | Yes | | Rate limiting | Yes | Yes | | Request-size limit | Yes | Yes | | Correlation IDs | Yes | Yes | | Security headers | Yes | Yes | | CORS allowlist | Yes | Yes | | Liveness endpoint | Yes | Yes | | Readiness endpoint | Yes | Yes | | Reconciliation worker/loop | Yes | Yes | | Automated tests in repository | Runtime-dependent | Yes | --- ## Requirements ### ASP.NET Core Required: - .NET SDK compatible with target framework `net10.0`; - an operating system supported by the selected .NET runtime; - outbound HTTPS access to PayTR; - valid PayTR merchant credentials for provider-connected requests. Useful tools: - Visual Studio with .NET 10 support; - Visual Studio Code with C# tooling; - `curl`, Postman, or an HTTP client; - SQL Server if adopting the reference persistence model. Check your SDK: ```bash dotnet --version ``` ### Node.js Required: - Node.js `20` or newer; - npm compatible with the selected Node.js version; - outbound HTTPS access to PayTR; - valid PayTR merchant credentials for provider-connected requests. Check your runtime: ```bash node --version npm --version ``` ### PayTR merchant account Before production enablement, confirm: - merchant credentials are active; - notification/callback URL configuration is correct; - required service permissions are enabled; - Direct API permission is enabled before turning on Direct API locally; - Non3D permission exists before using recurring flows that require it; - transfer/reporting services are available to the merchant account; - production URLs use the correct scheme and certificate configuration. --- # Quick start ## ASP.NET Core ### Primary application Restore: ```bash dotnet restore ASP.NET/PayTR/PayTR.sln ``` Build: ```bash dotnet build ASP.NET/PayTR/PayTR.sln -c Release ``` Run: ```bash dotnet run --project ASP.NET/PayTR/PayTR/PayTR.csproj ``` Default development URLs are defined in the project's `launchSettings.json` and include: - `http://localhost:5080` - `https://localhost:7080` Health checks: ```bash curl http://localhost:5080/health/live curl http://localhost:5080/health/ready ``` ### Example application Restore: ```bash dotnet restore ASP.NET/PayTRExample/PayTRExample.sln ``` Build: ```bash dotnet build ASP.NET/PayTRExample/PayTRExample.sln -c Release ``` Run: ```bash dotnet run --project ASP.NET/PayTRExample/PayTRExample/PayTRExample.csproj ``` Default development URLs include: - `http://localhost:5180` - `https://localhost:7180` Health checks: ```bash curl http://localhost:5180/health/live curl http://localhost:5180/health/ready ``` ### Development internal API key The development configuration includes a local-only internal API key: ```text paytr-local-development-key ``` Use it only for local development. Never copy this value into a production deployment. Example: ```bash curl \ -H "X-Internal-Api-Key: paytr-local-development-key" \ http://localhost:5080/api/v1/system/configuration ``` ## Node.js No external runtime dependencies are required by the current application packages. ### Primary application ```bash cd NodeJS/PayTR npm test npm run lint npm run build npm start ``` Default port: ```text 3100 ``` Health checks: ```bash curl http://localhost:3100/health/live curl http://localhost:3100/health/ready ``` ### Example application ```bash cd NodeJS/PayTRExample npm test npm run lint npm run build npm start ``` Default port: ```text 3200 ``` Health checks: ```bash curl http://localhost:3200/health/live curl http://localhost:3200/health/ready ``` ### Select environment Node.js reads `NODE_ENV` and then merges the matching `appsettings..json` file over `appsettings.json`. Examples: ```bash NODE_ENV=Development npm start ``` ```bash NODE_ENV=Production npm start ``` --- # Configuration ## ASP.NET configuration The ASP.NET applications bind three main sections. ### `PayTR` | Setting | Purpose | Production guidance | |---|---|---| | `MerchantId` | PayTR merchant identifier | Supply through a secret-aware configuration provider | | `MerchantKey` | PayTR merchant key | Secret; never commit a real value | | `MerchantSalt` | PayTR merchant salt | Secret; never commit a real value | | `BaseUri` | PayTR base URI | Keep on official HTTPS provider endpoint unless explicitly testing a controlled substitute | | `Timeout` | Outbound HTTP timeout | Keep bounded; default is 20 seconds | ### `Security` | Setting | Purpose | Default posture | |---|---|---| | `InternalApiKey` | Protects `/api/v1/paytr` and `/api/v1/system` | Empty outside development until supplied securely | | `AllowedOrigins` | CORS allowlist | Empty in production template | | `DirectApiEnabled` | Enables Direct API wrapper routes | `false` | | `BkmExpressEnabled` | Enables BKM Express wrapper route | `false` | | `RateLimitPerMinute` | Per-client fixed-window request limit | `120` | | `MaxRequestBodyBytes` | Maximum request body size | `65536` | ### `BackgroundJobs` | Setting | Purpose | Default | |---|---|---| | `ReconciliationEnabled` | Enables background reconciliation processing | `false` in base configuration | | `Interval` | Worker interval | `00:05:00` | ### Production environment variables ASP.NET Core supports hierarchical environment-variable overrides using double underscores. Examples: ```bash PayTR__MerchantId=... PayTR__MerchantKey=... PayTR__MerchantSalt=... Security__InternalApiKey=... Security__DirectApiEnabled=false Security__BkmExpressEnabled=false BackgroundJobs__ReconciliationEnabled=true ``` Do not commit real values to `appsettings.json` or `appsettings.Production.json`. ## Node.js configuration The Node.js configuration loader supports JSON appsettings plus explicit environment-variable overrides. | Environment variable | Maps to | Notes | |---|---|---| | `NODE_ENV` | runtime environment | Defaults to `Development` | | `PORT` | server port | Valid range `1..65535` | | `PAYTR_MERCHANT_ID` | merchant ID | Secret-adjacent merchant configuration | | `PAYTR_MERCHANT_KEY` | merchant key | Secret | | `PAYTR_MERCHANT_SALT` | merchant salt | Secret | | `PAYTR_BASE_URL` | provider base URL | Defaults to `https://www.paytr.com` | | `PAYTR_TIMEOUT_MS` | provider timeout | Valid range `1..120000` | | `INTERNAL_API_KEY` | internal wrapper API key | Secret | | `ALLOWED_ORIGINS` | CORS allowlist | Comma-separated | | `PAYTR_DIRECT_API_ENABLED` | Direct API feature flag | Boolean | | `PAYTR_BKM_EXPRESS_ENABLED` | BKM Express feature flag | Boolean | | `PAYTR_RECONCILIATION_ENABLED` | reconciliation flag | Boolean | | `PAYTR_RECONCILIATION_INTERVAL_MS` | reconciliation interval | `10000..86400000` | | `PAYTR_RATE_LIMIT_PER_MINUTE` | request rate limit | `1..10000` | | `PAYTR_MAX_BODY_BYTES` | request body limit | `1024..1048576` | Example production shell configuration: ```bash export NODE_ENV=Production export PORT=3100 export PAYTR_MERCHANT_ID="..." export PAYTR_MERCHANT_KEY="..." export PAYTR_MERCHANT_SALT="..." export INTERNAL_API_KEY="..." export ALLOWED_ORIGINS="https://example.com" export PAYTR_DIRECT_API_ENABLED=false export PAYTR_BKM_EXPRESS_ENABLED=false npm start ``` ## Configuration precedence ### ASP.NET Core Use standard ASP.NET Core configuration precedence. Environment variables and secret-aware providers should override committed JSON values in production. ### Node.js The effective configuration follows this model: 1. `appsettings.json`; 2. `appsettings..json`; 3. supported environment-variable overrides. This allows development defaults without requiring tracked `.env` files. ## Production secret management Recommended secret sources include: - platform-native secret stores; - managed platform secret stores; - operating-system environment injection; - Azure Key Vault, AWS Secrets Manager, Google Secret Manager, HashiCorp Vault, or equivalent managed systems; - encrypted deployment variables supplied by CI/CD. Never: - commit real merchant keys; - place secrets in frontend JavaScript; - paste secrets into issue trackers; - write secrets to logs; - persist CVV/CVC; - include production secrets in screenshots or support tickets. --- # Authentication and authorization The application-facing provider routes are protected by an internal API key header: ```http X-Internal-Api-Key: ``` Protected route groups include: - `/api/v1/paytr/*` - `/api/v1/system/*` PayTR callback routes are intentionally not protected by the internal API key because they must be callable by PayTR. Their trust boundary is the provider signature verification logic. > [!IMPORTANT] > The internal API key mechanism is an integration boundary, not a substitute for a complete product authentication and authorization model. If the wrapper is exposed to multiple applications, users, tenants, or administrative roles, place it behind your real identity, authorization, network, and service-to-service controls. Recommended production controls: - private network exposure where possible; - gateway/service-mesh authentication; - workload identity or mTLS for service-to-service traffic; - secret rotation; - least-privilege network rules; - request auditing that excludes sensitive payloads. --- # API surface The following routes represent the current wrapper/application surface. ## System and health | Method | Route | Authentication | Purpose | |---|---|---|---| | `GET` | `/` | No | Service metadata/root response | | `GET` | `/health/live` | No | Process liveness | | `GET` | `/health/ready` | No | Configuration/readiness state | | `GET` | `/api/v1/system/configuration` | Internal API key | Safe configuration-status view | Node.js also exposes system callback/reconciliation inspection routes implemented by its router. Treat these as administrative/internal surfaces and keep them protected. ## PayTR operations | Method | Route | Purpose | |---|---|---| | `POST` | `/api/v1/paytr/iframe/token` | Create iFrame token | | `POST` | `/api/v1/paytr/eft/iframe/token` | Create Havale/EFT iFrame token | | `POST` | `/api/v1/paytr/direct/form-fields` | Build signed Direct API form fields | | `POST` | `/api/v1/paytr/direct/bkm-express/form-fields` | Build signed BKM Express fields | | `POST` | `/api/v1/paytr/direct/recurring` | Submit recurring payment request | | `POST` | `/api/v1/paytr/status` | Query payment status | | `POST` | `/api/v1/paytr/refunds` | Request full/partial refund | | `POST` | `/api/v1/paytr/bin` | BIN lookup | | `POST` | `/api/v1/paytr/installments` | Installment-rate lookup | | `POST` | `/api/v1/paytr/links` | Create payment link | | `DELETE` | `/api/v1/paytr/links/{id}` | Delete payment link | | `POST` | `/api/v1/paytr/links/sms` | Send payment link by SMS | | `POST` | `/api/v1/paytr/links/email` | Send payment link by email | | `POST` | `/api/v1/paytr/cards/list` | List stored cards | | `DELETE` | `/api/v1/paytr/cards` | Delete stored card | | `POST` | `/api/v1/paytr/platform/transfers` | Create platform transfer | | `POST` | `/api/v1/paytr/returned-transfers/list` | List returned transfers | | `POST` | `/api/v1/paytr/returned-transfers/send` | Send returned transfer | | `POST` | `/api/v1/paytr/reports/transactions` | Transaction statement | | `POST` | `/api/v1/paytr/reports/payment-summary` | Payment summary | | `POST` | `/api/v1/paytr/reports/payment-detail` | Payment detail | | `POST` | `/api/v1/paytr/reconciliation/enqueue` | Enqueue reconciliation work | All `/api/v1/paytr/*` routes require the internal API key in the current application implementation. ## Provider callbacks | Method | Route | Internal API key | Trust mechanism | |---|---|---:|---| | `POST` | `/api/v1/callbacks/paytr/payment` | No | PayTR callback signature verification | | `POST` | `/api/v1/callbacks/paytr/link` | No | Link callback hash verification | | `POST` | `/api/v1/callbacks/paytr/platform-transfer` | No | Platform-transfer callback hash verification | | `POST` | `/api/v1/callbacks/paytr/returned-transfer` | No | Returned-transfer callback hash verification | Provider callbacks must remain reachable from PayTR while still being protected by signature validation, rate controls appropriate to your topology, and idempotent persistence. --- # Payment flow A safe iFrame-oriented payment lifecycle should be modeled as follows. 1. Your application creates an internal order record. 2. Your backend assigns a unique merchant order identifier. 3. Your backend validates price, customer, basket, callback/redirect, and merchant input. 4. Your backend requests an iFrame token from PayTR. 5. The frontend opens the PayTR-hosted payment interface using the returned token. 6. Browser navigation to success/failure pages is treated as user experience only. 7. PayTR sends the server-to-server result to the configured notification URL. 8. Your callback endpoint verifies the received hash. 9. Your persistence layer atomically checks idempotency and applies the allowed state transition. 10. Your endpoint returns the provider-required acknowledgement only after accepted processing. 11. Any ambiguous state is reconciled through status-query/reporting logic rather than guessed from client behavior. PayTR documents iFrame integration as a two-step process: server-side token acquisition followed by a separately implemented callback/notification endpoint. The callback is the authoritative server-side integration point. --- # Callback processing ## Required callback guarantees A production callback handler should guarantee all of the following: - public reachability from PayTR; - no end-user session dependency; - exact provider signature verification; - constant-time comparison where applicable; - deterministic extraction of the merchant order identifier; - idempotent callback persistence; - atomic payment/order transition; - no duplicate fulfillment; - no sensitive payload logging; - bounded execution time; - correct provider acknowledgement; - durable operational audit data that does not include secrets. ## Recommended callback transaction Conceptually: ```text receive callback -> parse bounded form payload -> verify provider hash -> reject invalid hash -> begin database transaction -> insert callback receipt using a unique idempotency key -> if duplicate: return prior accepted outcome -> load internal payment/order by merchant order id -> validate allowed state transition -> update payment/order state -> write audit/outbox event -> commit -> return provider acknowledgement ``` Never send goods, activate subscriptions, provision services, or mark an invoice as paid before an authenticated callback has been applied successfully. --- # Direct API and card-data boundary Direct API changes the security and compliance boundary because the merchant application participates directly in the payment form flow. The project therefore keeps Direct API disabled by default: ```json { "Security": { "DirectApiEnabled": false } } ``` The Node.js reusable request path explicitly rejects raw card-data fields in the SDK request model for the server-side signing flow. The intention is to keep reusable server code focused on merchant-side signing and provider-issued token operations instead of normalizing cardholder-data collection into generic APIs. Before enabling Direct API: - obtain required PayTR authorization; - complete security architecture review; - determine PCI DSS scope with qualified expertise; - ensure cardholder data is never logged; - ensure CVV/CVC is never persisted; - isolate payment-form handling; - deploy CSP and browser-side security controls appropriate to the chosen flow; - test 3D Secure and failure paths; - validate provider-required notification behavior; - perform threat modeling and penetration testing appropriate to your risk profile. --- # Refund and financial mutation safety The wrapper exposes refund support for full and partial refund workflows. Refunds and transfers are **financial mutations**. A network timeout does not prove that the provider rejected the operation. The provider may have accepted the request while the client failed to receive the response. Therefore: - do not automatically retry a refund because of a timeout; - use a merchant-generated reference when the provider operation supports one; - persist intent before dispatch; - record provider response when available; - reconcile ambiguous outcomes using status/report endpoints and merchant-panel evidence; - require operator review for unresolved discrepancies; - expose safe operational states such as `Pending`, `Submitted`, `Succeeded`, `Failed`, and `Unknown/ReconciliationRequired` instead of forcing a false binary state. PayTR's refund documentation explicitly warns that incorrect integration can lead to erroneous refunds and financial loss. Treat refund code changes as high-risk changes requiring deterministic tests and review. --- # Stored cards and recurring payments Stored-card operations use PayTR-issued identifiers such as `utoken` and `ctoken`. The supported workflow includes: - list cards for a provider user token; - delete a selected provider card token; - construct recurring requests using stored-card identifiers. Recurring payment requirements can include Non3D merchant permission. PayTR documentation states that recurring payment using registered cards can proceed without interactive user entry and requires the relevant Non3D authorization. Production guidance: - treat `utoken` and `ctoken` as sensitive identifiers; - avoid exposing them to unrelated clients; - never convert this flow into local PAN storage; - keep authorization checks tied to the internal customer who owns the token; - record consent/business basis for recurring charging according to your legal obligations; - provide cancellation and dispute handling in the product layer. --- # Link API The integration surface supports: - link creation; - link deletion; - SMS delivery; - email delivery; - Link callback verification. A Link API callback URL is conceptually distinct from the merchant-panel payment notification URL used by standard payment flows. Keep business routing for these callbacks explicit. Operational guidance: - associate each link with an internal business record; - validate currency, amount, product/collection mode, callback URL, and quantity rules; - never trust a client-provided callback status without provider hash verification; - make successful fulfillment idempotent. --- # Platform and returned transfers Transfer operations have direct financial consequences and should be placed behind stronger authorization than ordinary read-only payment queries. Recommended controls: - dedicated operator/service role; - multi-step approval for high-value transfers when the product requires it; - durable request identifiers; - transactionally persisted transfer intent; - no blind retries; - callback verification; - reconciliation of pending/unknown outcomes; - immutable audit trail; - alerting for rejected or returned transfers. The project exposes server-side methods and API routes for platform transfer and returned-transfer workflows, but production policy, approval thresholds, tenant ownership, and accounting behavior belong to the integrating application. --- # Reporting Reporting operations include: - transaction statement requests; - payment summary requests; - payment detail requests. Treat reports as reconciliation tools rather than as a replacement for callback-driven order state. Recommended uses: - daily financial reconciliation; - investigating ambiguous requests; - validating settlement expectations; - operational dashboards; - exception reporting; - finance-team exports. Date ranges should be bounded and validated before provider requests. --- # Persistence and idempotency The repository includes a SQL Server reference schema for durable payment-state infrastructure. The application examples currently also include in-memory stores/queues for runnable demonstration behavior. In-memory implementations are not a substitute for durable production storage. Production callback state should be persisted in a database that can enforce uniqueness. Recommended uniqueness boundaries include combinations such as: - provider + event type + provider callback identifier; - provider + merchant order ID + terminal payment state; - provider + refund reference; - provider + transfer reference. An effective idempotency design prevents: - duplicate order fulfillment; - duplicate subscription activation; - duplicate refund dispatch; - duplicate transfer dispatch; - duplicate notification/outbox events. --- # Background reconciliation Both runtime families include reconciliation concepts. Reconciliation exists to resolve cases such as: - provider request outcome unknown after a timeout; - callback received but internal processing failed; - internal payment remains pending beyond expected duration; - refund response is ambiguous; - transfer status requires later confirmation. Base configuration keeps reconciliation disabled, while production configuration templates can enable it. Recommended production worker properties: - durable queue; - bounded batch size; - distributed lease/lock if multiple workers run; - exponential scheduling for read-only checks; - no automatic repeat of non-idempotent financial mutations; - dead-letter/manual-review state; - metrics for queue depth and oldest pending item. --- # Health checks ## Liveness ```http GET /health/live ``` Liveness answers whether the application process is running and able to handle basic HTTP execution. It should not depend on PayTR availability. ## Readiness ```http GET /health/ready ``` Readiness evaluates whether the application has sufficient local configuration to perform intended work. In ASP.NET, the PayTR configuration health check can report a degraded state. The current health mapping treats degraded readiness as HTTP `200` and unhealthy as HTTP `503`. In Node.js, readiness reports whether a PayTR service instance could be created from effective merchant configuration. Do not make readiness dependent on an unnecessary external provider ping on every probe. Doing so can cause provider outages to cascade into unnecessary service restarts or failover events. --- # Observability Payment observability must provide enough evidence to investigate a transaction without leaking sensitive information. ## Safe fields to consider logging - correlation/trace identifier; - merchant order identifier; - internal payment identifier; - operation name; - provider endpoint category; - HTTP/provider outcome category; - elapsed time; - retry/reconciliation state; - sanitized provider error code; - deployment version. ## Fields that must not be logged - merchant key; - merchant salt; - internal API key; - raw HMAC source strings containing secrets; - PAN; - CVV/CVC; - complete sensitive authorization payloads; - unnecessary personal data. ## Recommended production telemetry - request latency percentiles; - callback verification failure count; - callback duplicate count; - provider failure rate; - reconciliation queue depth; - oldest unresolved reconciliation age; - refund unknown-state count; - transfer unknown-state count; - readiness degradation count; - rate-limit rejection count. --- # Security controls The application code contains a baseline set of server-side defenses. ### HMAC signing Provider request tokens are generated with HMAC-SHA256 and Base64 encoding where required by the PayTR integration formulas implemented by the project. ### Constant-time comparison Callback hash comparison uses constant-time comparison helpers to reduce timing side-channel exposure. ### Internal API key Privileged wrapper operations require `X-Internal-Api-Key`. ### Request limits Request body sizes are bounded: - ASP.NET uses Kestrel request limits derived from `Security:MaxRequestBodyBytes`; - Node.js uses the configured `PAYTR_MAX_BODY_BYTES`/appsettings value. ### Rate limiting A per-client fixed-window limit is enabled in the current server implementations. ### CORS allowlist Production templates use an empty allowlist by default. Add only exact trusted origins. ### Security headers The applications apply baseline HTTP security headers through middleware. ### HTTPS posture ASP.NET enables HSTS and HTTPS redirection outside Development. Reverse-proxy deployments must preserve the original scheme correctly through trusted forwarded headers. ### Fail-closed configuration Privileged API routes fail when the internal API key is not configured instead of becoming anonymously accessible. ### Feature gates Direct API and BKM Express stay disabled until explicitly enabled. For the complete policy, read [`SECURITY.md`](SECURITY.md). --- # OpenAPI and Postman ## OpenAPI A repository-level OpenAPI `3.1` contract documents the wrapper API surface. Use it for: - client generation; - contract review; - request/response discovery; - gateway import where compatible; - automated contract checks. The OpenAPI document describes application-facing routes; it does not replace PayTR's official provider documentation. ## ASP.NET development OpenAPI The ASP.NET applications register OpenAPI support and expose mapped OpenAPI endpoints in Development. ## Postman The repository includes a Postman collection for local integration testing. Before executing provider-connected requests: - set the correct local base URL; - set the local internal API key; - configure merchant credentials on the server, not in shared Postman exports; - use non-production test data unless a production operation is explicitly intended and approved. --- # SQL Server reference schema The SQL Server script models durable records for: - payments; - provider callbacks; - payment links; - refunds; - platform transfers; - returned transfers; - reconciliation jobs; - outbox messages; - payment audit events. The script is a reference persistence baseline. The runnable applications currently use in-memory abstractions for callback storage and reconciliation queueing unless an integrating application replaces those registrations. Before production use: - review data types and indexes for expected scale; - add tenant/account ownership if needed; - define retention policy; - encrypt backups; - restrict database roles; - protect personal data; - add unique constraints that implement your idempotency policy; - test migration/rollback procedure; - verify recovery objectives. --- # Reverse proxy and HTTPS For Nginx, IIS, Azure Application Gateway, Cloudflare, Kubernetes ingress, or another reverse proxy: - preserve `X-Forwarded-For` and `X-Forwarded-Proto` only from trusted proxies; - prevent clients from spoofing trusted forwarding headers; - terminate TLS with a valid certificate; - restrict callback and API routes according to business need; - preserve the exact callback response body expected by PayTR; - configure body and header limits consistently across proxy and application; - configure timeouts so the proxy does not retry financial mutations; - retain original correlation IDs only when your trust boundary allows it. --- # Testing and quality gates ## Node.js primary application ```bash cd NodeJS/PayTR npm test npm run lint npm run build ``` ## Node.js example application ```bash cd NodeJS/PayTRExample npm test npm run lint npm run build ``` ## ASP.NET primary application ```bash dotnet restore ASP.NET/PayTR/PayTR.sln dotnet build ASP.NET/PayTR/PayTR.sln -c Release --no-restore ``` ## ASP.NET example application ```bash dotnet restore ASP.NET/PayTRExample/PayTRExample.sln dotnet build ASP.NET/PayTRExample/PayTRExample.sln -c Release --no-restore ``` ## Minimum release gate A release should not be declared production-ready unless all applicable gates have evidence: 1. restore/install succeeds; 2. compilation or syntax build succeeds; 3. unit/integration tests succeed; 4. callback signature tests succeed; 5. duplicate callback tests succeed; 6. invalid-signature tests succeed; 7. feature-gate tests succeed; 8. production configuration review succeeds; 9. OpenAPI contract is valid; 10. dependency/security scan is reviewed; 11. end-to-end PayTR test flow succeeds; 12. rollback and reconciliation procedure is documented. --- # CI and static analysis The repository includes GitHub Actions definitions for: - .NET restore/build/publish; - Node.js testing, linting, and build checks on supported Node versions; - CodeQL-oriented analysis configuration. Treat CI configuration as code. If the repository layout changes, update workflow paths in the same pull request and verify the workflow on GitHub before relying on it as release evidence. Recommended additions for mature production environments: - secret scanning; - software composition analysis; - signed build provenance; - SBOM generation; - dependency license policy; - branch protection; - required reviewers for payment/security code; - deployment approvals for production. --- # Troubleshooting ## `503 Internal API key is not configured` Cause: The application-facing privileged route was called without a configured `Security:InternalApiKey` / `INTERNAL_API_KEY`. Resolution: Configure a secret internal API key and call the route with: ```http X-Internal-Api-Key: ``` Do not use the local development key in production. ## `401 Unauthorized request` Cause: The supplied internal API key does not match the configured key. Check: - header name is exactly `X-Internal-Api-Key`; - reverse proxy is forwarding the header; - the application loaded the expected environment configuration; - no extra whitespace or secret-store encoding changed the value. ## Readiness is degraded Common cause: PayTR merchant configuration is incomplete. Check: - merchant ID; - merchant key; - merchant salt; - environment selection; - secret-provider injection. ## Callback is rejected Check: - correct merchant key/salt for the environment; - exact form values used in the provider hash formula; - no transformations before verification; - callback route receives form-encoded body expected by the implementation; - test and production merchant credentials are not mixed. Do not disable signature verification to make a callback test pass. ## Direct API returns disabled response This is expected while the feature flag is false. Enable only after merchant authorization, compliance review, and integration testing. ## Provider request times out Do not immediately repeat refunds, transfers, or other financial mutations. First establish whether the provider accepted the original request by using reconciliation/status/reporting mechanisms. ## Local callback cannot be reached by PayTR `localhost` is not externally routable from PayTR. Use a controlled HTTPS development tunnel or a staging environment. Do not expose unrelated local services and do not use a tunnel that bypasses your callback verification. --- # Versioning The project uses semantic-version-style release numbers: ```text MAJOR.MINOR.PATCH ``` For this repository: - **major** changes can include intentional compatibility breaks; - **minor** changes can add integration capabilities or substantial behavior; - **patch** changes should remain backward-compatible bug/security/documentation fixes where possible. The historical release record from `1.0.0` through `2.5.0` is maintained in [`CHANGELOG.md`](CHANGELOG.md). When publishing a new release: - update package/project version metadata; - update API documentation version; - update runtime-reported version; - update changelog; - run all release gates; - create immutable release artifacts; - record provider-documentation assumptions that influenced the release. --- # Security policy Security issues must not be reported with live merchant credentials, cardholder data, customer personal data, or active exploitation details in a public issue. Read the complete policy in [`SECURITY.md`](SECURITY.md). --- # Contributing Contributions must preserve the payment-security invariants of the project. Important rules include: - do not weaken signature verification; - do not add cardholder-data logging; - do not add blind retries for financial mutations; - add deterministic signing tests when a token formula changes; - keep provider-protocol behavior inside the integration layer; - update documentation and changelog for externally visible changes. Read [`CONTRIBUTING.md`](CONTRIBUTING.md) before opening a pull request. --- # License The project is licensed under the **GNU General Public License v3.0 (GPL-3.0)**. See [`LICENSE.md`](LICENSE.md). GPL-3.0 applies to this repository's original code and documentation. Distribution and modification must comply with the license terms, including the source-availability and copyleft obligations that apply when covered works are conveyed. The license does not grant rights to PayTR trademarks, merchant services, proprietary provider documentation, commercial services, or third-party APIs. --- # Provider responsibility notice PayTR is an external payment provider. This project does not control PayTR availability, merchant approvals, service eligibility, pricing, settlement rules, API changes, compliance requirements, or account-level permissions. Before deploying: 1. review the current official PayTR documentation; 2. verify the merchant account configuration; 3. validate the exact payment flow in a controlled environment; 4. perform security and compliance review appropriate to the business; 5. verify accounting, refund, chargeback, reconciliation, and support procedures; 6. retain release evidence for the exact deployed commit. **Never deploy a payment integration solely because sample requests work locally. Production readiness requires provider validation, durable idempotency, operational monitoring, reconciliation, and tested failure handling.**