Skip to content

makecryptoio/makepay-swift-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MakePay Swift SDK

Official Swift SDK for MakePay server-side integrations and Swift apps that need MakePay API and checkout helpers. Use it to create crypto payment links, donation pages, invoices, bookkeeping records, subscriptions, POS terminals, products, Simple Shop storefronts, customer portals, branded domains, and signed webhook handlers.

Install

Add the package to Package.swift:

dependencies: [
    .package(url: "https://github.com/makecryptoio/makepay-swift-sdk.git", from: "0.3.2")
]

Then add MakePay to your target dependencies:

.target(
    name: "YourApp",
    dependencies: ["MakePay"]
)

The SDK targets Swift 5.9 or newer and uses async/await.

Xcode

In Xcode, use File > Add Package Dependencies... and enter:

https://github.com/makecryptoio/makepay-swift-sdk.git

Select version 0.3.2 or the default "up to next major" rule from 0.3.2, then add the MakePay library product to your app or server target.

Requirements

  • Swift 5.9 or newer.
  • iOS 13+, macOS 10.15+, tvOS 13+, or watchOS 6+.
  • A trusted backend or server-side Swift runtime for authenticated API calls.
  • MAKEPAY_KEY_ID and MAKEPAY_KEY_SECRET for partner API requests.
  • MAKEPAY_WEBHOOK_SECRET for webhook signature verification.

Configure

Create a MakePay API key in MakeCrypto and keep the secret on trusted backend infrastructure only. Do not ship API key secrets inside iOS, macOS, tvOS, or watchOS apps.

import MakePay

let makepay = MakePayClient(
    keyID: ProcessInfo.processInfo.environment["MAKEPAY_KEY_ID"]!,
    keySecret: ProcessInfo.processInfo.environment["MAKEPAY_KEY_SECRET"]!
)

The client sends X-MakeCrypto-Key-Id and X-MakeCrypto-Key-Secret headers to the MakePay partner API.

Use the optional baseURL, checkoutBaseURL, and transport initializer arguments for staging environments, custom checkout domains, or tests:

let makepay = MakePayClient(
    keyID: keyID,
    keySecret: keySecret,
    baseURL: URL(string: "https://www.makecrypto.io")!,
    checkoutBaseURL: URL(string: "https://makepay.io")!
)

Quick Start

Create a payment link on your backend, save the returned payment UID or public URL with your order, then redirect the shopper to hosted checkout.

let response = try await makepay.createPaymentLink(
    MakePayPaymentLinkPayload(
        amount: "49.00",
        currency: "USDT",
        fiatCurrency: "USD",
        title: "Order #1042",
        orderID: "order_1042",
        successURL: URL(string: "https://merchant.example/orders/1042/success"),
        failureURL: URL(string: "https://merchant.example/orders/1042/pay")
    ),
    sendPaymentRequestEmail: true
)

let paymentLink = response["paymentLink"]?.objectValue
let paymentUID = paymentLink?["uid"]?.stringValue
let checkoutURL = paymentUID.flatMap { try? makepay.hostedCheckoutURL(paymentUID: $0) }
let publicURL = paymentLink?["publicUrl"]?.stringValue

Payment Links

let response = try await makepay.createPaymentLink(
    MakePayPaymentLinkPayload(
        amount: "129.99",
        currency: "USDT",
        title: "Order #1042",
        description: "Checkout for order #1042",
        orderID: "order_1042",
        customerEmail: "buyer@example.com",
        returnURL: URL(string: "https://merchant.example/orders/1042"),
        successURL: URL(string: "https://merchant.example/orders/1042/success"),
        failureURL: URL(string: "https://merchant.example/orders/1042/pay"),
        expirationTime: "12h"
    )
)

let paymentLink = response["paymentLink"]?.objectValue
let publicURL = paymentLink?["publicUrl"]?.stringValue

Read, update, and email existing links:

try await makepay.listPaymentLinks()
try await makepay.getPaymentLink("PAYMENT_LINK_UID")
try await makepay.updatePaymentLink("PAYMENT_LINK_UID", status: .paused)
try await makepay.sendPaymentRequestEmail("PAYMENT_LINK_UID", email: "buyer@example.com")

Donations

Donation pages are flexible-amount payment links with a public donation slug.

let donation = try await makepay.createDonationLink(
    MakePayDonationLinkPayload(
        defaultAmountUSD: "25",
        minimumAmountUSD: "5",
        donationSlug: "spring-campaign",
        title: "Spring campaign",
        description: "Support the 2026 spring fundraiser."
    )
)

let donationURL = try makepay.hostedDonationURL(donationSlug: "spring-campaign")

try await makepay.listDonationLinks()
try await makepay.getDonationLink("DONATION_UID")
try await makepay.updateDonationLink("DONATION_UID", status: .paused)

Anonymous Payment Links

Anonymous links do not use a MakePay API key. They require an explicit settlement route because MakePay cannot read merchant wallet settings.

let response = try await createAnonymousPaymentLink([
    "amount": "25",
    "title": "Invoice #1042",
    "webhookUrl": "https://merchant.example/webhooks/makepay",
    "settlement": [
        "currency": "USDT",
        "priorities": [
            [
                "chain": "ETH",
                "address": "0xYourSettlementWallet",
                "asset": "ETH.USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7",
            ],
        ],
    ],
])

MakePay does not create reusable static payment addresses for new orders. Migrate static-address flows to one-time or deposit payment links.

Checkout URLs And Embeds

Use hosted checkout for redirects, or the embed helpers when your frontend keeps the shopper on the merchant site.

let paymentUID = "PAYMENT_LINK_UID"

let hostedURL = try makepay.hostedCheckoutURL(paymentUID: paymentUID)
let embeddedURL = try makepay.embeddedCheckoutURL(
    paymentUID: paymentUID,
    parentOrigin: URL(string: "https://merchant.example")
)

let modalScriptURL = makepay.modalScriptURL()
let buttonHTML = try makepay.embedButtonHTML(paymentUID: paymentUID)
let iframeHTML = try makepay.iframeHTML(paymentUID: paymentUID)

Donation pages also have URL helpers:

try makepay.hostedDonationURL(donationSlug: "spring-campaign")
try makepay.embeddedDonationURL(
    donationSlug: "spring-campaign",
    parentOrigin: URL(string: "https://merchant.example")
)

Customers And Subscriptions

Advanced payloads use MakePayObject, which is a Swift alias for [String: JSONValue].

try await makepay.upsertCustomer([
    "email": "buyer@example.com",
    "name": "Buyer Example",
    "clientId": "crm_123",
])

try await makepay.createCustomerPortal(
    customerID: "CUSTOMER_ID",
    payload: ["returnUrl": "https://merchant.example/account"]
)

try await makepay.createSubscription([
    "amountUsd": "29",
    "customerEmail": "buyer@example.com",
    "label": "Monthly plan",
    "billingIntervalUnit": "month",
    "billingIntervalCount": 1,
])

POS Terminals

let terminal = try await makepay.createPosTerminal(
    MakePayPOSTerminalPayload(
        name: "Front counter",
        pin: "1234",
        allowedAssets: ["ETH.USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7"],
        emailCollectionMode: "optional_after_deposit",
        catalogEnabled: true
    )
)

try await makepay.listPosTerminals()
try await makepay.getPosTerminal("TERMINAL_UID")
try await makepay.updatePosTerminal("TERMINAL_UID", payload: ["status": "paused"])

Products And Simple Shop

try await makepay.createProduct([
    "name": "Digital guide",
    "productType": "digital",
    "basePriceUsd": "19",
    "shopSlug": "digital-guide",
    "images": [["url": "https://merchant.example/guide.png", "alt": "Guide cover"]],
    "variants": [["name": "PDF", "priceUsd": "19"]],
])

try await makepay.createProductDownload(
    productID: "PRODUCT_UID",
    payload: [
        "fileName": "guide.pdf",
        "contentType": "application/pdf",
        "url": "https://merchant.example/downloads/guide.pdf",
    ]
)

try await makepay.updateShop([
    "slug": "merchant-shop",
    "displayCurrency": "USD",
    "checkoutMode": "hosted",
    "branding": ["accentColor": "#14b8a6"],
])

try await makepay.updateShopDomain("shop.merchant.example")
try await makepay.refreshShopDomain()
try await makepay.createShopCoupon([
    "code": "SPRING10",
    "discountType": "percent",
    "value": "10",
])
try await makepay.listShopOrders(query: ["status": "paid", "limit": "25"])

Invoices And Bookkeeping

Bookkeeping APIs manage merchant invoices, expenses, supporting documents, OCR, and reconciliation links.

let created = try await makepay.createBookkeepingInvoice(
    MakePayBookkeepingInvoicePayload(
        currency: "USD",
        issueDate: "2026-05-15",
        dueDate: "2026-05-30",
        title: "Invoice #1042",
        counterparty: MakePayBookkeepingCounterpartyPayload(
            name: "Buyer Example",
            email: "buyer@example.com",
            clientID: "crm_123"
        ),
        lineItems: [
            MakePayBookkeepingInvoiceLineItemPayload(
                description: "Implementation services",
                quantity: "1",
                unitAmount: "500",
                taxAmount: "0"
            ),
        ],
        metadata: ["orderId": "order_1042"]
    )
)

try await makepay.createBookkeepingInvoicePaymentLink(
    invoiceID: "INVOICE_UID",
    options: ["sendPaymentRequestEmail": true]
)

try await makepay.listBookkeepingInvoices()
try await makepay.getBookkeepingInvoice("INVOICE_UID")
try await makepay.updateBookkeepingInvoice("INVOICE_UID", payload: ["status": "open"])

Expenses can be created manually or from wallet activity, then linked back to payments, transfers, invoices, or uploaded receipts.

try await makepay.createBookkeepingExpense([
    "title": "Hosting",
    "amount": "49",
    "currency": "USD",
    "incurredOn": "2026-05-15",
    "category": "Infrastructure",
    "counterparty": ["name": "Vendor Example", "type": "vendor"],
])

try await makepay.createBookkeepingExpenseFromActivity([
    "walletActivityEventKey": "CHAIN_EVENT_KEY",
    "category": "Settlement",
])

try await makepay.createBookkeepingReconciliation(
    MakePayBookkeepingReconciliationPayload(
        invoiceID: "INVOICE_UID",
        paymentSessionID: "PAYMENT_SESSION_ID",
        linkType: "payment"
    )
)

Document uploads use multipart form data.

try await makepay.uploadBookkeepingDocument(
    MakePayBookkeepingDocumentUpload(
        file: MakePayMultipartFile(
            data: receiptData,
            fileName: "receipt.pdf",
            contentType: "application/pdf"
        ),
        documentType: "receipt",
        expenseID: "EXPENSE_UID"
    )
)

try await makepay.listBookkeepingDocuments()
try await makepay.getBookkeepingDocumentDownloadURL("DOCUMENT_UID")
try await makepay.runBookkeepingDocumentOCR("DOCUMENT_UID")
try await makepay.getBookkeepingSummary()

Branding And Domains

try await makepay.updateBranding([
    "brandName": "Merchant",
    "supportEmail": "support@merchant.example",
    "brandingBrandColor": "#111827",
    "brandingAccentColor": "#14b8a6",
    "paymentLinkTheme": "system",
    "paymentLinkDomain": "pay.merchant.example",
    "emailSendingDomain": "mail.merchant.example",
])

try await makepay.refreshBrandingDomains(kind: .all)

Settings And Operational APIs

try await makepay.getSettings()
try await makepay.updateSettings([
    "callbackUrl": "https://merchant.example/webhooks/makepay",
])

try await makepay.listDestinationAssets()
try await makepay.listWebhookRequests(query: ["limit": "25"])

Responses And Errors

Most API methods return MakePayResponse, which is a [String: JSONValue]. Use typed payload structs for common create/update requests and MakePayObject for flexible partner API fields that may evolve between SDK releases.

do {
    let settings = try await makepay.getSettings()
    let callbackURL = settings["callbackUrl"]?.stringValue
} catch MakePayError.apiError(let statusCode, let message, let response) {
    print("MakePay API error", statusCode, message, response ?? .null)
} catch {
    print("Unexpected MakePay SDK error", error)
}

The SDK raises MakePayError.invalidConfiguration before network calls when required credentials are empty, and MakePayError.apiError for non-2xx API responses with the decoded response body when available.

Webhook Verification

Read the exact raw request body before parsing JSON.

let event = try MakePayWebhook.parse(
    rawBody: rawBodyData,
    signatureHeader: request.headers["x-makepay-signature"],
    secret: ProcessInfo.processInfo.environment["MAKEPAY_WEBHOOK_SECRET"]!
)

if event["event"]?.objectValue?["type"] == "status_changed" {
    // Update your local order status.
}

Use MakePayWebhook.verify when you only need a boolean result.

Testing Integrations

Inject a custom MakePayHTTPTransport to unit test request paths, headers, and JSON bodies without sending network traffic.

final class MockTransport: MakePayHTTPTransport, @unchecked Sendable {
    private(set) var requests: [URLRequest] = []

    func data(for request: URLRequest) async throws -> (Data, URLResponse) {
        requests.append(request)
        let response = HTTPURLResponse(
            url: request.url!,
            statusCode: 200,
            httpVersion: "HTTP/1.1",
            headerFields: ["Content-Type": "application/json"]
        )!
        return (Data(#"{"ok":true}"#.utf8), response)
    }
}

let transport = MockTransport()
let client = MakePayClient(keyID: "mk_test", keySecret: "mksec_test", transport: transport)
_ = try await client.getSettings()

Method Coverage

Area SDK methods
Payment links createPaymentLink, listPaymentLinks, getPaymentLink, updatePaymentLink, sendPaymentRequestEmail
Donations createDonationLink, listDonationLinks, getDonationLink, updateDonationLink
Anonymous links createAnonymousPaymentLink, createAnonymousMakePayPaymentLink
Checkout hosted, embedded, modal, button, iframe, and donation URL helpers
Customers listCustomers, upsertCustomer, createCustomerPortal
Subscriptions listSubscriptions, createSubscription
POS terminals listPosTerminals, createPosTerminal, getPosTerminal, updatePosTerminal
Products listProducts, createProduct, getProduct, updateProduct, listProductDownloads, createProductDownload
Simple Shop getShop, updateShop, getShopBuilder, updateShopBuilder, getShopDomain, updateShopDomain, coupons, orders
Bookkeeping summary, invoice, expense, document upload/OCR, and reconciliation methods
Branding getBranding, updateBranding, refreshBrandingDomains
Operations getSettings, updateSettings, listDestinationAssets, listWebhookRequests
Webhooks MakePayWebhook.verify, MakePayWebhook.parse

Model Conventions

  • SDK payloads use camelCase. Some API routes also accept snake_case for compatibility, but new integrations should send camelCase.
  • Use strings for decimal money values when precision matters, for example "129.99" instead of 129.99.
  • Dates are ISO strings. Date-only fields, such as invoice issueDate, should use YYYY-MM-DD.
  • IDs are usually public uid values. Bookkeeping detail endpoints accept an internal UUID or public UID.
  • API methods throw MakePayError.apiError for non-2xx responses with the HTTP status, message, and decoded response body.

Release Verification

Before tagging a release, maintainers should run:

swift build
swift run MakePayPackageCheck

Swift Package Manager users receive a new version when the corresponding Git tag is published.

About

Official MakePay Swift SDK for payment links, settings, checkout URLs, and webhook verification. Cryptocurrency payment gateway for direct self-custody merchant-wallet settlement, decentralized swaps, and 70+ coin/20+ chain auto-conversion.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages