{"id":34866164,"url":"https://github.com/tpay-com/tpay-ios","last_synced_at":"2026-06-03T15:00:33.582Z","repository":{"id":199723437,"uuid":"702885129","full_name":"tpay-com/tpay-ios","owner":"tpay-com","description":"This repository provides our iOS SDK source code","archived":false,"fork":false,"pushed_at":"2026-05-08T14:06:09.000Z","size":7169,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":6,"default_branch":"master","last_synced_at":"2026-05-08T16:14:08.547Z","etag":null,"topics":["bank-transfer","blik","credit-card","ios","payment","payments","sdk","tpay"],"latest_commit_sha":null,"homepage":"https://tpay.com/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tpay-com.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-10-10T07:40:52.000Z","updated_at":"2026-05-08T14:08:27.000Z","dependencies_parsed_at":"2024-12-15T20:42:55.665Z","dependency_job_id":"1161e322-3bfc-4696-b96a-e41e8eec650b","html_url":"https://github.com/tpay-com/tpay-ios","commit_stats":{"total_commits":50,"total_committers":2,"mean_commits":25.0,"dds":0.06000000000000005,"last_synced_commit":"e62999ab16f24a1e5b1c61b414955d55293b6b8e"},"previous_names":["tpay-com/tpay-ios"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/tpay-com/tpay-ios","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpay-com%2Ftpay-ios","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpay-com%2Ftpay-ios/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpay-com%2Ftpay-ios/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpay-com%2Ftpay-ios/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tpay-com","download_url":"https://codeload.github.com/tpay-com/tpay-ios/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpay-com%2Ftpay-ios/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33870026,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bank-transfer","blik","credit-card","ios","payment","payments","sdk","tpay"],"created_at":"2025-12-25T22:28:08.665Z","updated_at":"2026-06-03T15:00:33.514Z","avatar_url":"https://github.com/tpay-com.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tpay\n\n[![Min](https://img.shields.io/badge/12.0-informational.svg?logo=ios)](https://shields.io/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## About\n\nThis SDK allows your app to make payments with Tpay.\nPackage documentation is available [here](https://tpay-com.github.io/tpay-ios/documentation/tpay/).\n\nMinimum supported versions:\n\n| Library | Version |\n|---------|---------|\n| iOS     | 12.0    |\n\n\u003e [!warning]\n\u003e For this SDK to work you will need `client_id` and `client_secret` tokens. You can find\n\u003e in [merchant's panel](https://panel.tpay.com/?lang=1).\n\u003e\n\u003e If you are partner, you can obtain them in your merchant partner account. For detailed\n\u003e instructions how to do that or how to create such an account\n\u003e check [this site](https://docs-api.tpay.com/en/merchant-accounts/).\n\n\u003e [!tip]\n\u003e To be able to test the SDK properly,\n\u003e use [mock data](https://support.tpay.com/sprzedawca/srodowisko-testowe-sandbox).\n\n## Install\n\nHow to install the SDK.\n\n### SPM\n\n```\nFile \u003e Swift Packages \u003e Add Package Dependency\nAdd https://github.com/tpay-com/tpay-ios.git\nSelect \"Up to Next Major\" with \"1.0.0\"\n```\n\n### CocoaPods\n\n```ruby\nuse_frameworks!\n\ntarget :MyTarget do\n  pod 'Tpay-SDK'\nend\n```\n\nOnce you have completed your Podfile, simply run `pod install`.\n\n### Manually\n\nSimply, drag the `Tpay.xcframework` into the `Frameworks, Libraries and Embedded Content` section of\nyour target.\n\n## Import\n\nTo begin, make sure you have imported the `Tpay` framework into your project. You can do this by\nadding the following line at the top of your Swift file:\n\n```swift\nimport Tpay\n```\n\n## Configuration\n\n\u003e [!note]\n\u003e In this section we will provide examples for each configuration to the TpayModule class\n\u003e you will be able to make.\n\n\u003e [!important]\n\u003e Beneath you will find all configurations that are **MANDATORY**.\n\n### Initialization\n\nAt first, you have to configure your app to be able to make any requests by providing SDK info about\nyour merchant account.\nInfo about `client_id` and `client_secret` you will find in your merchant's panel at `Integration -\u003e\nAPI`.\n\n```swift\nTpayModule.configure(\n    merchant: Merchant(\n        authorization: Merchant.Authorization(\n            clientId: \"client_id\",\n            clientSecret: \"client_secret\",\n        ),\n    )\n)\n```\n\n### Environment\n\nTpay SDK provides two types of environments you can use in your app:\n\n* `Environment.sandbox` - used only for tests and in stage/dev flavor.\n* `Environment.production` - used for production flavors.\n\n```swift\nTpayModule.configure(\n    merchant: Merchant(\n        authorization: Merchant.Authorization(\n            clientId: \"client_id\",\n            clientSecret: \"client_secret\",\n        ),\n        environment: .sandbox,\n    )\n)\n```\n\n### Payment methods\n\nFor users to be able to use a specific payment method you have declared it in the configuration.\n\n| Method                      | Description                                                              |\n|-----------------------------|--------------------------------------------------------------------------|\n| BLIK                        | [Web docs](https://docs-api.tpay.com/en/payment-methods/blik/)           |\n| Pbl **(Pay-By-Link)**       | [Web docs](https://docs-api.tpay.com/en/payment-methods/pbl/)            |\n| Card                        | [Web docs](https://docs-api.tpay.com/en/payment-methods/cards/)          |\n| DigitalWallets              | [APPLE_PAY](https://docs-api.tpay.com/en/payment-methods/apple-pay/)     |\n| InstallmentPayments         | [RATY_PEKAO](https://docs-api.tpay.com/en/payment-methods/installments/) |\n| DeferredPayments **(BNPL)** | [PAY_PO](https://docs-api.tpay.com/en/payment-methods/bnpl/)             |\n\n\u003e [!note]\n\u003e As default, if no method were provided, all methods are being set up.\n\n\u003cbr\u003e\n\n```swift\nTpayModule.configure(\n    paymentMethods: [\n        PaymentMethod.card,\n        PaymentMethod.blik,\n        PaymentMethod.payPo,\n        PaymentMethod.pbl,\n        PaymentMethod.digitalWallet(DigitalWallet.applePay),\n        PaymentMethod.installmentPayments(InstallmentPayment.ratyPekao),\n    ],\n)\n```\n\n### Card\n\nIf you decide to enable the credit card payment option, you have to provide SSL certificates.\n\n\u003e [!tip]\n\u003e You can find public key on you merchant panel:\n\u003e - Acquirer Elavon: `Credit card payments -\u003e API`\n\u003e - Acquirer Pekao: `Integrations -\u003e API -\u003e Cards API`\n\nAt first, create your own implementation of `SSLCertificatesProvider`:\n\n```swift\nstruct SSLCertProvider: SSLCertificatesProvider {\n    var apiConfiguration: Tpay.CertificatePinningConfiguration = CertificatePinningConfiguration(\n        publicKeyHashes: [\"ssl_cert_hash\"],\n    )\n}\n```\n\nthen, simply use it in the `TpayModule.configure` func.\n\n```swift\nTpayModule.configure(\n    sslCertificatesProvider: SSLCertProvider()\n)\n```\n\n### Apple Pay configuration\n\nIn order to be able to use Apple Pay method you have to provide your `merchant_id` and `country_code` to the SDK.\nBoth those information, you just put in the merchant configuration object with `walletConfiguration` field.\n\n\u003e [!Warning]\n\u003e - Apple Pay is available exclusively on Apple devices (iPhone, iPad, MacBook, iMac).\n\u003e - Apple Pay supports only **Visa** and **Mastercard**.\n\n\u003e [!important]\n\u003e Before using Apple Pay, make sure the following prerequisites are met:\n\u003e - Card payments are enabled in your merchant account.\n\u003e - Apple Pay payment channel is activated in your merchant panel.\n\n\u003e [!important]\n\u003e To obtain the merchantIdentifier, follow these steps:\n\u003e 1. Log in to your Apple Developer account.\n\u003e 2. Navigate to the `Certificates, Identifiers \u0026 Profiles` section.\n\u003e 3. Under `Identifiers,` select `Merchant IDs.`\n\u003e 4. Click the `+` button to create a new Merchant ID.\n\u003e 5. Fill in the required information and associate it with your app's Bundle ID.\n\u003e 6. Set up a **Payment Processing Certificate** for the Merchant ID.\n\u003e 7. Once created, the merchant identifier can be found in the list of Merchant IDs.\n\u003e 8. For more details, please follow [Apple Pay documentation](https://developer.apple.com/documentation/passkit/apple_pay/setting_up_apple_pay).\n\n\u003e [!tip]\n\u003e As for the country code, SDK provides predefined `CountryCode.pl` value.\n\u003e For more codes, check our `CountryCode.init` func.\n\n```swift\nTpayModule.configure(\n    merchant: Merchant(\n        // previous config,\n        walletConfiguration: Merchant.WalletConfiguration.init(\n            applePayConfiguration: Merchant.WalletConfiguration.ApplePayConfiguration(\n                merchantIdentifier: \"merchant_id\",\n                countryCode: Merchant.WalletConfiguration.ApplePayConfiguration.CountryCode.pl,\n            ),\n        )\n    )\n)\n```\n\n### Merchant details\n\nAs a merchant, you can configure how information about you will be shown.\nYou can set up your `display name`, `headquarters` and `regulations link`.\nYou can choose to provide different copy for each language or simply use one for all.\n\nAt first, create your own implementation of `MerchantDetailsProvider`:\n\n```swift\nstruct MerchantDetails: MerchantDetailsProvider {\n    func merchantDisplayName(for language: Tpay.Language) -\u003e String {\n        let displayName = switch language {\n            case Language.pl:\n                \"Sprzedawca\"\n            \n            case Language.en:\n                \"Merchant\"\n            \n            default :\n                 \"Unknown\"\n        }\n        \n        return displayName\n    }\n    \n    func merchantHeadquarters(for language: Tpay.Language) -\u003e String? {\n        let displayName = switch language {\n        case Language.pl:\n            \"Warszawa\"\n            \n        case Language.en:\n            \"Warsaw\"\n            \n        default :\n            \"City\"\n        }\n        \n        return displayName\n    }\n    \n    func regulationsLink(for language: Tpay.Language) -\u003e URL {\n        let displayName = switch language {\n        case Language.pl:\n            URL.init(string: \"regulations_link/pl\")\n            \n        case Language.en:\n            URL.init(string: \"regulations_link/en\")\n            \n        default :\n            URL.init(string: \"regulations_link\")\n        }\n        \n        return displayName!\n    }\n}\n```\n\nthen, simply use it in the `TpayModule.configure` func.\n\n```swift\nTpayModule.configure(merchantDetailsProvider: MerchantDetails())\n```\n\n### Wallet Configuration\n\n\u003e [!important]\n\u003e Beneath you will find all configurations that are **OPTIONAL**.\n\n### Languages\n\nTpay SDK lets you decide what languages will be available in the Tpay's screen and which one of them\nwill be preferred/default.\n\nRight now, SDK allows you to use 2 languages:\n\n* `Language.pl` - polish\n* `Language.en` - english\n\n\u003e [!warning]\n\u003e If you do not choose to configure languages at all, by default, all available languages will be\n\u003e supported and polish will be preferred one.\n\n```swift\nTpayModule.configure(\n    preferredLanguage: Language.pl,\n    supportedLanguages: [Language.pl, Language.en],\n)\n```\n\n### Callbacks\n\nTpay SDK allows you to add your custom callbacks, which includes `successRedirectUrl`, `errorRedirectUrl`, `notificationsUrl` and `notificationEmail`.\n\n\u003e [!warning]\n\u003e `notificationUrl` should be the URL handled by your backend, because there will be sent token from\n\u003e the successful token creation.\n\n```swift\nTpayModule.configure(\n    callbacks: CallbacksConfiguration(\n        successRedirectUrl:  URL.init(string: \"\"),\n        errorRedirectUrl: URL.init(string: \"\"),\n        notificationsUrl: URL.init(string: \"\"),\n        notificationEmail:  \"\",\n    ),\n)\n```\n\n### Checking configuration\n\nTo wrap up whole configuration and therefore install it, you have to use `checkConfiguration` func and check for the configuration result.\n\n```swift\nlet configResult = TpayModule.checkConfiguration()\n\nswitch configResult {\ncase .valid:\n    // Configuration is complete and valid, proceed with payment processes\ncase .invalid(let error):\n    // Configuration is invalid, handle the specific error accordingly\n@unknown default:\n    print(\"Unknown case\")\n    // Handle default value\n}\n```\n\n## Handling payments\n\n\u003e [!warning]\n\u003e Beofre using any payment method, you **HAVE TO** configure the TpayModule using `checkConfiguration` func.\n\nTpay SDK provides two ways of handling payments:\n\n- `Official SDK screens` - you can use Tpay's official screens where you just need to provide \"soft\"\n  information, like price, description or payer info.\n- `Screenless` - you can use screenless functionalities, where you set callbacks for payments and\n  display all necessary information on your own screens.\n  \n## Official SDK screens\n\n\u003e [!warning]\n\u003e Screens made by the Tpay team are based on UIViewController system!\n\nTo make integration with the SDK faster, we created 4 types of sheets that can be used to handle\npayments:\n\n* `Payment` - the most simple screen where the user can choose any payment method and proceed with it.\n* `AddCard` - screen that handles generating payment token from the credit card.\n* `CardTokenPayment` - screen that handles payment with a previously created token for a credit card.\n* `Payment.WebView` - screens that handle payment through webview with a specific link generated via API.\n\n### Delegate\n\nEach payment gives you a way of reacting to it's result. Simply, create and use instance of `PaymentDelegate`.\n\n```swift\nclass PaymentResultDelegate : PaymentDelegate {\n    func onPaymentCreated(transactionId: Tpay.TransactionId) {\n        print(\"Created\")\n    }\n    \n    func onPaymentCompleted(transactionId: Tpay.TransactionId){\n        print(\"Completed\")\n    }\n    \n    func onPaymentCancelled(transactionId: Tpay.TransactionId){\n        print(\"Cancelled\")\n    }\n    \n    func onPaymentClosed(){\n        print(\"Closed\")\n    }\n    \n    func onErrorOccured(error: any Tpay.ModuleError){\n        print(\"Error: \\(error.localizedDescription)\")\n    }\n}\n```\n\n### Payment\n\nPayment flow opens a UI module and allows the customer to pick one of defined the payment methods.\nThis method requires setting up a few things in order to fulfill payment:\n\n* `amount` - simply the price of the transaction\n* `description` - transaction description\n* `hiddenDescription` (optional) - description visible only to the merchant\n* `payerContext` - information about payer\n    * `payer` - information about the person who is making the payment\n        * `name` - payer name\n        * `email` - payer email\n        * `phone` - payer phone number\n        * `address` - payer address\n            * `city` - city name\n            * `country` - country code in ISO 3166-1 alpha-2 format\n            * `address` - street address\n            * `postalCode` - postal code\n    * `automaticPaymentMethods` - (optional) configuration of automatic payments\n        * `tokenizedCards` - previously saved credit cards\n            * `token` - card token\n            * `cardTail` - last 4 digits of the card\n            * `brand` - card brand\n        * `registeredBlikAlias` - previously saved BLIK alias\n            * `value` - alias value\n            * `label` - alias label\n\n#### Transaction\n\n```swift\nSingleTransaction(\n    amount: 250,\n    description: \"test\",\n    hiddenDescription: \"hidden message\",\n    payerContext: PayerContext(\n        payer: Payer(\n            name: \"Test\",\n            email: \"email@address.com\",\n        ),\n    ),\n  )\n```\n\n#### Display with code\n\nThe Payment/Sheet is designed to guide the user through the payment process. Payment sheet is presented in a modal style, providing a focused and intuitive payment interaction. The class interacts with the provided PaymentDelegate to notify about payment events.\n\n```swift\nPayment.Sheet(\n    transaction: SingleTransaction(\n        amount: 250,\n        description: \"test\",\n        hiddenDescription: \"hidden message\",\n        payerContext: PayerContext(\n            payer: Payer(\n                name: \"Test\",\n                email: \"email@address.com\",\n            ),\n        ),\n    ), \n    delegate: PaymentResultDelegate(),\n)\n```\n\nUse the ``Payment/Sheet/present(from:)`` method to present the payment sheet from a view controller:\n\n```swift\ndo {\n    try paymentSheet.present(from: presentingViewController)\n} catch {\n    // Handle configuration errors or other exceptions\n}\n```\n\nTo dismiss the payment sheet manually, call the `dismiss()` method:\n\n```swift\npaymentSheet.dismiss()\n```\n\n#### Display with SwiftUI\n\nTo make your life easier and fasten our SDK implementation, we also provide a way of presenting Payment modal with simple button's extension func.\n\n```swift\nstruct ContentView: View {\n    @State private var isPaymentSheetPresented = false\n\n    var body: some View {\n        Button(\"Show Payment modal\") {\n            isPaymentSheetPresented.toggle()\n        }\n        .presentPaymentSheet(for: transaction, isPresented: $isPaymentSheetPresented) { transactionId in\n            // Handle payment completed\n        } onPaymentCancelled: { transactionId in\n            // Handle payment cancelled\n        } onErrorOccured: { error in\n            // Handle payment error\n        }\n    }\n}\n```\n\n#### Automatic Payments\n\nUsing `Payment.Sheet` screen you can set up automatic BLIK or card payments.\nThanks to that, user will not have to enter BLIK/card data all over again each time making the\npayment.\n\n##### Automatic Card Payments\n\nIf a user using a card as a payment method will opt-in saving card, on successful payment, on the link\nspecified as `notificationUrl`, Tpay backend will send information about saved card token, tail and\nbrand.\nNext, your backend has to send it to you, so you can use this info next time the same user wants\nto pay with the card.\nWhen you already have all required information, you can add `automaticPaymentMethods` to the\n`payerContext`.\n\n```swift\nautomaticPaymentMethods: .init(\n    tokenizedCards: [\n        CardToken(token: \"token\", cardTail: \"1234\", brand: .visa),\n    ],\n),\n```\n\n##### Automatic BLIK Payments\n\nIf a user using BLIK as a payment method will opt-in saving BLIK alias, next time the same user will\nwant to pay with BLIK, you can simply use a previously saved alias to make the payment even faster.\nWhen you already have all the required information, you can add `automaticPaymentMethods` to the\n`payerContext`.\n\n```swift\nlet blikConfiguration = Merchant.BlikConfiguration(aliasToBeRegistered: .init(value: .uid(\"myBlikAlias\")))\nlet merchant = Merchant(authorization: authorization, blikConfiguration: blikConfiguration)\n```\n\nNext, after successfuly registering your alias, you can use it in a the transaction like so:\n\n```swift\nautomaticPaymentMethods: .init(\n    registeredBlikAlias: RegisteredBlikAlias(value: .uid(\"myBlikAlias\")),\n),\n```\n\n#### Recurring Payment\n\nPayment class lets you use recurring payments as well. To do so, simply use `RecursiveTransaction` class.\n\n\u003e [!important]\n\u003e You can choose one of the specified recurring payment frequencies:\n\u003e `.daily`, `.weekly`, `.monthly`,`.quarterly` or `.yearly`.\n\n\u003e [!important]\n\u003e You can choose to either charge user specified times using `Quantity.specified` option,\n\u003e or to set it up to being charged until expiration date is being hit or user cancels subscription\n\u003e on his own with `Quantity.indefinite`.\n\n```swift\nRecursiveTransaction(\n    wrapping: SingleTransaction(\n        amount: 250,\n        description: \"test\",\n        hiddenDescription: \"hidden message\",\n        payerContext: PayerContext(\n            payer: Payer(\n                name: \"Test\",\n                email: \"email@address.com\",\n            ),\n        ),\n    ),\n    frequency: .monthly,\n    quantity: .specified(5),\n    expiryDate: Date(),\n)\n```\n\n## Tokenization\n\nTpay SDK allows you to make credit card transactions without need of entering card's data each time.\nInstead, you can create and use a token, associated with a specific card and user.\n\n\u003e [!important]\n\u003e There are 2 types of tokens you can use in transactions:\n\u003e * [Simple tokens](https://docs-api.tpay.com/en/tokenization/#tokenization-without-charging) -\n    tokens that go with card data upon transaction.\n\u003e * [Network tokens](https://docs-api.tpay.com/en/tokenization/#tokenization-plus) -\n    tokens that can be used without exposing the card details. Also, this token persists even if\n    card expires and the user requests a new one.\n\n\u003e [!warning]\n\u003e This view only allows creating card token,\n\u003e to make an actual payment, you have to then use it in the `Payment.Sheet`.\n\n\u003e [!warning]\n\u003e For recurring payments, you can simply use created token in the authomatic payments\n\u003e to make transaction without need of user interaction.\n\n### Creating card token\n\nThe AddCard/Sheet is designed to guide the user through the card tokenization process. Sheet is presented in a modal style, providing a focused and intuitive interaction. The class interacts with the provided AddCardDelegate to notify about tokenization events.\n\n```swift\nlet addCardSheet = AddCard.Sheet(\n    payer: Payer(\n        name: \"Test\",\n        email: \"email@address.com\",\n    ),\n    delegate: PaymentResultDelegate(),\n)\n```\n\n\u003e [!warning]\n\u003e Card token will be sent to the url provided in the `merchant configuration` -\u003e `callbacks` -\u003e `notificationsUrl`\n\n### Display with code\n\nUse the AddCard/Sheet/present(from:) method to present the sheet from a view controller:\n\n```swift\ndo {\n    try addCardSheet.present(from: presentingViewController)\n} catch {\n    // Handle configuration errors or other exceptions\n}\n```\n\nTo dismiss the sheet manually, call the dismiss() method:\n\n```swift\naddCardSheet.dismiss()\n```\n\n### Display with SwiftUI\n\n```swift\nstruct ContentView: View {\n    @State private var isTokenizationSheetPresented = false\n\n    var body: some View {\n        Button(\"Add Card\") {\n            isTokenizationSheetPresented.toggle()\n        }\n        .presentCardTokenizationSheet(isPresented: $isTokenizationSheetPresented) {\n            // Handle card tokenization completed\n        } onTokenizationCancelled: {\n            // Handle card tokenization cancelled\n        } onErrorOccured: { error in\n            // Handle tokenization error\n        }\n    }\n}\n```\n\n## Web view\n\nTpay SDK provides you also way of handling transactions via WebView. During configuration, you have to\nprovide 3 URL links:\n\n1) `transactionPaymentUrl` - for the user to make an actual payment.\n2) `onSuccessRedirectUrl` - for redirecting the user to the success page.\n3) `onErrorRedirectUrl` - for redirecting the user to the failure page.\n\n\u003e [!warning]\n\u003e `transactionPaymentUrl` - you or your backend can generate transactionUrl using specific\n\u003e [Tpay API endpoint](https://docs-api.tpay.com/en/first-steps/first-transaction/#create-a-transaction).\n\n```swift\nlet transaction = ExternallyGeneratedTransaction(\n    transactionPaymentUrl: transactionPaymentUrl,\n    onSuccessRedirectUrl: onSuccessUrl,\n    onErrorRedirectUrl: onErrorUrl,\n)\n\nlet paymentWebView = Payment.WebView(\n    transaction: transaction,\n    delegate: delegate,\n)\n\ndo {\n    try paymentWebView?.present(from: self)\n} catch {\n    // Handle configuration errors or other exceptions\n}\n```\n\n### Webview Delegate\n\nWebview delegate differs from simple transaction delegate\n\n```swift\nclass WebviewResultDelegate: WebViewPaymentDelegate {\n    func onPaymentCompleted() {\n        // On payment completed\n    }\n    \n    func onPaymentCancelled() {\n        // On payment cancelled\n    }\n    \n    func onPaymentError() {\n        // On payment error\n    }\n}\n```\n\n## Screenless Payments\n\nScreenless payments are a special type of payment functionality that gives you the whole power of\npayment process, but do not limit you to using predefined Tpay screens.\n\n### Get payment channels\n\nTo be able to use screenless functionalities you will need to know which payment methods are\navailable to your merchant account. To get them, you can simply call `Headless.getAvailablePaymentChannels`\nand set up result observer for them.\n\nLast but not least, we have to filter them by the specific methods we have enabled in our app and by\nthe amount of the transaction using.\n\n```swift\nHeadless.getAvailablePaymentChannels { result in\n    switch result {\n    case .success(let paymentChannels):\n        // Filter payment methods by the transaction amount\n    case .failure(let error):\n        // Handle error\n    }\n}\n```\n\n\u003e [!important]\n\u003e Available methods are being filtered for the specific transaction amount, so you should use this\n\u003e functionality each time you want to start a payment process.\n\n### Screenless Credit Card Payment\n\nTpay SDK allows you to make payment without any predefined screen.\nTo do so use `Tpay.Headless.Models.Card` class.\n\n```swift\ndo {\n    try Headless.invokePayment(\n        for: SingleTransaction(\n            amount: 250,\n            description: \"test\",\n            hiddenDescription: \"hidden message\",\n            payerContext: PayerContext(\n                payer: Payer(\n                    name: \"Test\",\n                    email: \"email@address.com\",\n                ),\n            ),\n        ),\n        using: chosenPaymentChannel,\n        with: Tpay.Headless.Models.Card(\n            number: \"4056 2178 4359 7258\",\n            expiryDate: Headless.Models.Card.ExpiryDate(month: 12, year: 35),\n            securityCode: \"123\",\n            shouldTokenize: false,\n        )\n    ) { result in\n        switch result {\n        case .success(let paymentResult):\n            // Handle payment result\n        case .failure(let error):\n            // Handle payment error\n        }\n    }\n} catch {\n    // Handle invocation errors or other exceptions\n}\n```\n\n\u003e [!warning]\n\u003e If `paymentResult` returns `continueUrl`, you have to handle it\n\u003e and redirect user to it in order to complete the payment.\n\n\u003e [!warning]\n\u003e If `paymentResult` returns `paid` in `status`,\n\u003e it means that transaction has been paid automatically during creation.\n\n\u003e [!warning]\n\u003e Generated card token will be sent to `notificationUrl` specified in the notifications callbacks.\n\n#### Tokenization\n\nYou can also Opt-in to generate a credit card token for future payments\nif you want to let users pay for transactions with previously used card.\nTo do so, in `Tpay.Headless.Models.Card` class, set the `shouldTokenize` to true.\n\n```swift\nwith: Tpay.Headless.Models.Card(\n    number: \"4056 2178 4359 7258\",\n    expiryDate: Headless.Models.Card.ExpiryDate(month: 12, year: 35),\n    securityCode: \"123\",\n    shouldTokenize: true,\n)\n```\n\nIf you already have a credit card token, you can then set up token payment omitting credit card\ninfo.\nTo do so, use `Tpay.Headless.Models.CardToken` class instead of `Tpay.Headless.Models.Card` one.\n\n```swift\ndo {\n    try Headless.invokePayment(\n        for: SingleTransaction(\n            amount: 250,\n            description: \"test\",\n            hiddenDescription: \"hidden message\",\n            payerContext: PayerContext(\n                payer: Payer(\n                    name: \"Test\",\n                    email: \"email@address.com\",\n                ),\n            ),\n        ),\n        using: chosenPaymentChannel,\n        with: Tpay.Headless.Models.CardToken(\n            token: \"saved_card_token\",\n            cardTail: \"1234\",\n            brand: CardToken.Brand.visa,\n        )\n    ) { result in\n        switch result {\n        case .success(let paymentResult):\n            // Handle payment result\n        case .failure(let error):\n            // Handle payment error\n        }\n    }\n} catch {\n    // Handle invocation errors or other exceptions\n}\n```\n\n\u003e [!warning]\n\u003e For recurring payments, you can simply use created token in the haedless payments\n\u003e to make transaction without need of user interaction.\n\n### Screenless BLIK Payment\n\nTpay SDK let's make transactions with BLIK as well. In order to do so, simply use `Headless.invokePayment` with proper arguments.\n\n```swift\ndo {\n    try Headless.invokePayment(\n        for: SingleTransaction(\n            amount: 250,\n            description: \"test\",\n            hiddenDescription: \"hidden message\",\n            payerContext: PayerContext(\n                payer: Payer(\n                    name: \"Test\",\n                    email: \"email@address.com\",\n                ),\n            ),\n        ),\n        using: chosenPaymentChannel,\n        with: Headless.Models.Blik.Regular(\n            token: \"777834\",\n            aliasToBeRegistered: nil,\n        ),\n    ) { result in\n        switch result {\n        case .success(let paymentResult):\n            // Handle payment result\n        case .failure(let error):\n            // Handle payment error\n        }\n    }\n} catch {\n    // Handle invocation errors or other exceptions\n}\n```\n\n#### BLIK Alias Payment\n\nIf you have returning users and you want to make their BLIK payments even smoother,\nyou can register BLIK Alias for them, so they will only be prompted to accept payment in their\nbanking app, without need of entering BLIK code each time they want to make the payment.\n\nIn order to do that, you have to pass the alias in the `aliasToBeRegistered` argument.\n\n```swift\nwith: Headless.Models.Blik.Regular(\n    token: \"777834\",\n    aliasToBeRegistered: Headless.Models.NotRegisteredBlikAlias(\n        value: Headless.Models.NotRegisteredBlikAlias.Value.uid(\"my_alias\")\n    )\n)\n```\n\n\u003e [!warning]\n\u003e To properly register alias in sandbox, use `amount = 0.15`.\n\n\u003e [!important]\n\u003e Provided alias cannot be assumed as registered until receiving webhook notification about its status. Notification should be received by dedicated backend server, for implementation details check official [documentation](https://docs-api.tpay.com/en/webhooks/) . Additionally your backend server should implement other BLIK related [notifications](https://docs-api.tpay.com/en/webhooks/#blik-one-clickblik-recurring-payments-after-expiration-update-or-delete-alias) to ensure BLIK alias is valid and usable.\n\nOnce alias is registered for a user, in order to pay with only an alias, just use `Headless.Models.Blik.OneClick` class instead of the Regular.\n\n```swift\nwith: Headless.Models.Blik.OneClick(\n    registeredAlias: Headless.Models.RegisteredBlikAlias(\n        value: Headless.Models.RegisteredBlikAlias.Value.uid(\"my_alias\")\n    )\n)\n```\n\u003e [!warning]\n\u003e Before testing BLIK alias functionality check sandbox environment limitations listed in [documentation](https://docs-api.tpay.com/en/first-steps/environments/#blik-payments)\n\n#### BLIK Ambiguous Alias Payment\n\nSometimes, there is a possibility for one alias to be registered more than once. For example, if\nyou register alias associated with one user for the multiple banks.\nIn such a situation, you have to fetch those aliases from Tpay API and show them to user to let him\nchoose one for the payment.\n\nIn the payment result you can get `BlikPaymentResultWithAmbiguousAliases` type, that will indicate that the current alias was registered more than once.\nThis result holds all possible variations of the alias you used to start payment with.\nYou have to simply show them to the user, let him choose, and then use the chosen alias to retry the\npayment.\n\n```swift\nswitch result {\ncase .success(let paymentResult):\n    if paymentResult is Headless.Models.BlikPaymentResultWithAmbiguousAliases {\n        let ambiguousAliasesResult = (\n            paymentResult as! Headless.Models.BlikPaymentResultWithAmbiguousAliases\n        )\n        \n        showAmbiguousAliases(ambiguousAliasesResult.applications)\n    }\ncase .failure(let error):\n    // Handle failure\n}\n```\n\n\u003e [!warning]\n\u003e In such scenario, you have to use different class to make the payment than at the beginning.\n\u003e Where `chosenApplication` is the alias's application chosen by user from multiple aliases\n\u003e ```swift\n\u003e do {\n\u003e    try Headless.continuePayment(\n\u003e        for: ambiguousAliasesResult.ongoingTransaction,\n\u003e        with: Headless.Models.Blik.AmbiguousBlikAlias(\n\u003e            registeredAlias: Headless.Models.RegisteredBlikAlias(\n\u003e                value: Headless.Models.RegisteredBlikAlias.Value.uid(\"test_ios\")\n\u003e            ),\n\u003e            application: chosenApplication,\n\u003e        )\n\u003e    ) { blikResult in\n\u003e        switch blikResult{\n\u003e        case .success(let result):\n\u003e            // Handle amibuous blik payment success\n\u003e        case .failure(let error):\n\u003e            // Handle amibuous blik payment failure\n\u003e        }\n\u003e    }\n\u003e} catch {\n\u003e    // Handle error\n\u003e}\n\u003e ```\n\n\u003e [!important]\n\u003e Right now, Tpay SDK does NOT support recurring payments with BLIK\n\u003e In order to achieve that, check\n\u003e our [API support for BLIK recurring payments](https://docs-api.tpay.com/en/payment-methods/blik/#blik-recurring-payments).\n\n### Screenless Transfer Payment\n\nTpay SDK allows you to make transfer payments with bank available to your merchant account.\n\n\u003e [!tip]\n\u003e To get banks with their channel ids check\n\u003e the [Get Payment Channels](https://docs-api.tpay.com/en/first-steps/list-of-payment-methods/)\n\u003e section.\n\u003e Then, you have get banks available for you from the available payment methods.\n\nAfter your customer chooses their bank from the list, you can use it's `channelId` to make the payment.\n\n```swift\nHeadless.getAvailablePaymentChannels { result in\n    switch result {\n    case .success(let paymentChannels):\n        do {\n            let channels = paymentChannels.filter{ channel in\n                channel.paymentKind == .pbl\n            }\n            \n            try Headless.invokePayment(\n                for: createTransaction(),\n                using: channels[12], // replace with user chosen channel from `channels`\n            ) { result in\n                switch result {\n                case .success(let paymentResult):\n                    // Handle success\n                case .failure(let error):\n                    // Handle failure\n                }\n            }\n        } catch {\n            // Handle invocation errors or other exceptions\n        }\n    case .failure(let error):\n        // Handle payment channels error\n    }\n}\n```\n\n\u003e [!warning]\n\u003e If `paymentResult` returns `continueUrl`, you have to handle it\n\u003e and redirect user to it in order to complete the payment.\n\n### Screenless Installment Payments\n\nTpay SDK allows you to create long term installment payments.\n\n```swift\nHeadless.getAvailablePaymentChannels { result in\n    switch result {\n    case .success(let paymentChannels):\n        do {\n            let channels = paymentChannels.filter{ channel in\n                channel.paymentKind == .installmentPayments\n            }\n            \n            try Headless.invokePayment(\n                for: createTransaction(),\n                using: channels[0], // // replace with installmentPayment channel from `channels`\n            ) { result in\n                switch result {\n                case .success(let paymentResult):\n                    // Handle success\n                case .failure(let error):\n                    // Handle failure\n                }\n            }\n        } catch {\n            // Handle invocation errors or other exceptions\n        }\n    case .failure(let error):\n        // Handle payment channels error\n    }\n}\n```\n\n\u003e [!warning]\n\u003e If `paymentResult` returns `continueUrl`, you have to handle it\n\u003e and redirect user to it in order to complete the payment.\n\n### Screenless Deferred Payments\n\nTpay SDK allows you to create deferred payments (BNPL) using PayPo method.\n\n\u003e [!warning]\n\u003e For PayPo payment to work, amount of the payment must be at least 40PLN!\n\u003e For more information about PayPo payments\n\u003e check [our PayPo documentation](https://docs-api.tpay.com/en/payment-methods/bnpl/#paypo).\n\n\u003e [!tip]\n\u003e For sandbox, working phone number is `500123456`\n\n```swift\nHeadless.getAvailablePaymentChannels { result in\n    switch result {\n    case .success(let paymentChannels):\n        do {\n            let channels = paymentChannels.filter{ channel in\n                channel.paymentKind == .payPo\n            }\n            \n            try Headless.invokePayment(\n                for: createTransaction(),\n                using: channels[0], // replace with PayPo channel from `channels`\n            ) { result in\n                switch result {\n                case .success(let paymentResult):\n                    // Handle success\n                case .failure(let error):\n                    // Handle failure\n                }\n            }\n        } catch {\n            // Handle invocation errors or other exceptions\n        }\n    case .failure(let error):\n        // Handle payment channels error\n    }\n}\n```\n\n\u003e [!warning]\n\u003e If `paymentResult` returns `continueUrl`, you have to handle it\n\u003e and redirect user to it in order to complete the payment.\n\n### Screenless Apple Pay payment\n\nTpay SDK allows you to perform Apple Pay transactions.\n\n\u003e [!warning]\n\u003e To be able to complete Apple Pay payment, you will need `apple_pay_token`. You **HAVE TO**\n\u003e acquire a token by yourself. To do that check\n\u003e official [Apple Pay documentation](https://developer.apple.com/design/human-interface-guidelines/apple-pay#app-top)\n\n```swift\nHeadless.getAvailablePaymentChannels { result in\n    switch result {\n    case .success(let paymentChannels):\n        do {\n            let channels = paymentChannels.filter{ channel in\n                channel.paymentKind == .applePay\n            }\n            \n            try Headless.invokePayment(\n                for: createTransaction(),\n                using: channels[0], // // replace with ApplePay channel from `channels`\n                with: Tpay.Headless.Models.ApplePay(token: \"token\"),\n            ) { result in\n                switch result {\n                case .success(let paymentResult):\n                    // Handle success\n                case .failure(let error):\n                    // Handle failure\n                }\n            }\n        } catch {\n            // Handle invocation errors or other exceptions\n        }\n    case .failure(let error):\n        // Handle payment channels error\n    }\n}\n```\n\n### Screenless Payment Status\n\nIf you would need checking payment status in real time, Tpay SDK provides way of doing that.\nAll you need, is `Tpay.Headless.Models.OngoingTransaction` object from the current transaction.\n\n```swift\nHeadless.getPaymentStatus(\n    for: ongoingTransaction\n) { statusResult in\n    switch statusResult {\n    case .success(let status):\n        // Handle new payment status\n    case .failure(let error):\n        // Handle obtaining payment status failure\n    }\n}\n```\n\n## License\n\nThis library is released under the [MIT License](https://opensource.org/license/mit/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftpay-com%2Ftpay-ios","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftpay-com%2Ftpay-ios","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftpay-com%2Ftpay-ios/lists"}