Swift / iOS SDK
Swift 5.9+ iOS 15+ macOS 12+
Native Swift SDK using URLSession and Apple's CryptoKit. async/await throughout. Distributed via Swift Package Manager.
Install
Xcode
File → Add Package Dependencies → paste:
https://github.com/neptune-astro/neptune-astroSelect the AstroSDK product.
Package.swift
swift
// Package.swift
dependencies: [
.package(url: "https://github.com/neptune-astro/neptune-astro.git", from: "1.0.0")
],
targets: [
.target(name: "MyApp", dependencies: [
.product(name: "AstroSDK", package: "neptune-astro")
])
]Quick Start
swift
import AstroSDK
let astro = AstroClient(config: AstroConfig(
baseURL: URL(string: "https://astro.neptune.ly/api/v1")!,
merchantKey: ProcessInfo.processInfo.environment["ASTRO_KEY"]
))
// Create session (call from your backend in production — not from the app directly)
let session = try await astro.payments.createSession(
CreateSessionRequest(
amount: 50_000, // 50.000 LYD
currency: "LYD",
destination: Destination(type: "alias", value: "mtellesy"),
reference: "order_1042",
redirectUrl: "myapp://payment/result"
)
)
// Open checkout URL
if let url = URL(string: session.checkoutUrl) {
await UIApplication.shared.open(url)
}Handle the Result (Deep Link)
swift
// In your @main App (SwiftUI) or SceneDelegate (UIKit)
// SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in
handlePaymentCallback(url)
}
}
}
}
func handlePaymentCallback(_ url: URL) {
guard url.scheme == "myapp", url.host == "payment" else { return }
let params = URLComponents(url: url, resolvingAgainstBaseURL: false)?
.queryItems?.reduce(into: [String: String]()) { $0[$1.name] = $1.value }
if params?["status"] == "completed" {
NotificationCenter.default.post(name: .paymentCompleted, object: params?["session_id"])
}
}Payments
swift
// Get session
let updated = try await astro.payments.getSession("ops_01HZGV...")
print(updated.status) // "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED"
// List sessions
let sessions = try await astro.payments.listSessions(status: "COMPLETED")
// Cancel
let cancelled = try await astro.payments.cancelSession(session.sessionId)Alias Resolution
swift
// Resolve alias → IBAN + bank
let resolved = try await astro.alias.resolve("mtellesy")
print("\(resolved.bankHandle): \(resolved.iban)")
// Get linked accounts
let accounts = try await astro.alias.getAccounts("mtellesy")Open Banking
swift
// 1. Create consent
let consent = try await astro.openBanking.createConsent(
bankHandle: "andalus",
scopes: ["accounts:read", "transactions:read"],
redirectUri: "myapp://ob/callback",
state: UUID().uuidString,
codeChallenge: pkce.challenge
)
// 2. Open consent URL
if let url = URL(string: consent.consentUrl) {
await UIApplication.shared.open(url)
}
// 3. Handle callback deep link and exchange code
let tokens = try await astro.openBanking.exchangeCode(
code: callbackURL.queryParam("code")!,
redirectUri: "myapp://ob/callback",
consentId: consent.consentId,
codeVerifier: pkce.verifier
)
// 4. Fetch data
let accounts = try await astro.openBanking.getAccounts(
accessToken: tokens.accessToken,
consentId: consent.consentId
)
let txns = try await astro.openBanking.getTransactions(
accessToken: tokens.accessToken,
consentId: consent.consentId,
accountId: accounts[0].accountId
)Webhook Verification (Vapor server-side)
swift
import AstroSDK
import Vapor
let verifier = astro.webhookVerifier(
secret: Environment.get("ASTRO_WEBHOOK_SECRET")!
)
app.post("webhooks", "astro") { req async throws -> HTTPStatus in
let body = req.body.string ?? ""
let sig = req.headers.first(name: "X-OpenWave-Signature") ?? ""
try verifier.handle(rawBody: body, signature: sig, handlers: [
"payment.completed": { payload in
if let data = payload["data"] as? [String: Any],
let ref = data["reference"] as? String {
await db.markPaid(ref)
}
},
"payment.failed": { payload in
// handle failure
}
])
return .ok
}Error Handling
swift
do {
let session = try await astro.payments.createSession(...)
} catch let error as AstroError {
switch error.code {
case "INSUFFICIENT_FUNDS":
showAlert("Insufficient balance")
case "ALIAS_NOT_FOUND":
showAlert("Alias not found")
default:
showAlert("Payment error: \(error.localizedDescription)")
}
}Source
packages/astro-swift/ in the neptune-astro repo.