Compatibility
Integrate Amwal’s prebuilt payment Sheet into the checkout of your iOS app with the PaymentSheet DSL friendly APIs.
Screenshots
Table of Contents
Intoduction
AmwalPayment SDK offers the flexibility to use pass keys for enhanced security during the payment process. Pass keys provide an additional layer of protection by replacing traditional OTPs (One-Time Passwords) and ensuring a secure payment experience. Here's how you can generate and integrate pass keys into the Payment Sheet
Install SDK
Swift Package Manager (SPM)
Add the following line to your Package.swift
file's dependencies:
dependencies: [
.package(url: "https://github.com/amwal/payment-sdk-ios.git", from: "1.0.10")
]
CocoaPods
pod 'AmwalPayment', '~> 1.0.10'
⚠️ Important : Add AmwalPay in your associated domains
- In Xcode > Choose your target
- Head to Signing & Capabilities
- Press + Capability
- Search and choose Associated Domains
- In the newly added Associated Domains section add
webcredentials:pay.sa.amwal.tech
⚠️ Important : Add your Bundle Identifier and iOS App Id Prefix to Merchant dashboard
- Head to your Merchant dashboard settings
- Choose IOS SETTINGS tab
- Select your Store
- Add your iOS App Id Prefix aka Your team Id
- Add your iOS Bundle Id
- Click Save and you should see "iOS Settings Updated" message ✅
2. Initialize the PaymentSheet
you can use in SwiftUI with .sheet
and UIKit with modalPresentationStyle
.
1-
import AmwalPayment
2- initialize View
AmwalPaymentView(
currency: .SAR,
amount: 110,
vat: 20,
merchantId: "merchantId",
completion: { transactionId in
isPresented = false
}
)
3. Showing Payment Sheet
SwiftUI Sheet
import SwiftUI
import AmwalPay
struct ContentView: View {
@SwiftUI.State var isPresented: Bool = false
var body: some View {
VStack {
Button {
isPresented = true
} label: {
Label("Pay With Amwal", systemImage: "dollarsign.circle")
.padding(10)
.foregroundColor(.white)
.background(Color.blue)
.clipShape(Capsule(style: .continuous))
}
}
.frame(maxWidth: .infinity)
.padding()
.sheet(isPresented: $isPresented) {
AmwalPaymentView(
currency: .SAR,
amount: 110,
vat: 20,
merchantId: "merchantId",
completion: { transactionId in
isPresented = false
})
}
}
}
SwiftUI AmwalPayButton
import AmwalPay
import SwiftUI
enum PayResult: String {
case success
case failure
}
struct ContentView: View {
@State var isPresented: Bool = false
@State var amount: String = "110"
@State var vat: String = "20"
@State var merchantId: String = "sandbox-amwal-3db24246-8d09-4f78-a3eb-0d4b8b03bd4b"
@State var transactionID: String = ""
@State var result: PayResult?
var body: some View {
VStack {
Text("Enter your values to test")
.font(.largeTitle)
HStack(alignment: .center) {
VStack(alignment: .leading, spacing: 20) {
Text("Amount:")
Text("Vat:")
}
VStack(spacing: 5) {
TextField("Amount", text: $amount)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
TextField("Vat", text: $vat)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
}
}
.padding([.top, .horizontal])
VStack(alignment: .leading) {
Text("MerchantID")
TextField("MerchantID", text: $merchantId)
.keyboardType(.default)
.textFieldStyle(.roundedBorder)
}
.padding([.bottom, .horizontal])
Text("TransactionID: \(transactionID)")
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
HStack {
Image(systemName: "circle.fill")
.foregroundColor(
result == .success
? .green
: result == nil
? .gray
: .red
)
Text(result?.rawValue ?? "none")
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
Spacer()
AmwalPayButton(
currency: .SAR,
amount: Double(amount) ?? 110,
vat: Double(vat) ?? 20,
merchantId: merchantId
) { status in
switch status {
case let .success(transactionId):
self.transactionID = transactionId
result = .success
case let .fail(error):
result = .failure
print(error)
}
}
}
.padding(.bottom)
}
}
UIKit Sheet
import UIKit
import SwiftUI
import AmwalPay
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
func dismissPayment() {
self.dismiss(animated: true)
}
func presentPaymentView() {
let paymentView = AmwalPaymentView(
currency: .SAR,
amount: 110,
vat: 20,
merchantId: "merchantId",
completion: { [weak self] transactionId in
self?.dismissPayment()
})
let viewController = UIHostingController(rootView: paymentView)
self.present(viewController, animated: true)
}
}
UIKIT AmwalPayButton
import AmwalPay
import SwiftUI
import UIKit
class ViewController: UIViewController {
lazy var payButton: UIView = {
let button = AmwalPayButton(
currency: .SAR,
amount: 110,
vat: 20,
merchantId: "sandbox-amwal-3db24246-8d09-4f78-a3eb-0d4b8b03bd4b"
) { status in
switch status {
case let .success(transactionId):
debugPrint(transactionId)
case let .fail(error):
debugPrint(error)
}
}
let ButtonView = UIHostingController(rootView: button)
return ButtonView.view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(resource: .custom)
setupConstrains()
}
private func setupConstrains() {
let stackView = UIStackView(arrangedSubviews: [payButton])
stackView.axis = .horizontal
stackView.alignment = .center
stackView.spacing = 10
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
// Set constraints
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10),
payButton.heightAnchor.constraint(equalToConstant: 60),
])
}
}
4. Listen for results
we are return status success with transaction id and fail with error
Tips
🚧 Securely store your keys
The merchantId should be securely stored and not hard-coded as shown in this example. For more information on securely storing keys in iOS, see this article.
Updated about 1 year ago