Subscriptions (Recurring API)
Nets EASY supports subscriptions allowing charging customers on a regular basis. The API contains subscription creation and charging of subscriptions. Merchant is responsible for managing subscriptions after they’re created with Nets EASY recurring API. The following code samples demonstrate the steps required to create and charge subscriptions.
Create a Subscription with Nets EASY Recurring API
To create a subscription, include a subscription JSON object in the request body of the POST payment request as shown in Nets Easy API reference.
IMPORTANT: While making the API call for creating a subscription , make sure you add "commercePlatformTag" : "iOSSDK"
in the request header. This is critical to identify the platform from which the payment is initiated.
let headers: HTTPHeaders = [
"Authorization": token,
"Content-Type": "application/json",
"commercePlatformTag" : "iOSSDK"
]
/// Subscription request body
struct SubscriptionRequest: Encodable {
let order: Order
let checkout: Checkout
let merchantNumber: String?
let notifications: String?
let subscription: Subscription
struct Subscription: Encodable {
let endDate: String
let interval: Int = 0
}
}
/// Response object following subscription creation
struct SubscriptionRegistration: Decodable {
let paymentId: String
let hostedPaymentPageUrl: String
}
// E.g. subscription creation request. See MiaSample app for more
func createSubscription(success: @escaping (SubscriptionRegistration) -> Void) {
let url = baseURL.appending(path: "payments/")!
var request = URLRequest(for: url, method: .post, headers: authorizationHeaders)
request.httpBody = try! JSONEncoder().encode(SubscriptionRequest())
URLSession.shared.fetchJson(with: request, decodeDelegate: self, success: success)
}
A subscription object contains an endDate
, last date of the subscription, and an interval
representing the interval (in number of days) at which the subscription can be charged.
For recurring payments chargeable at any given time (with no regular interval), interval = 0
should be used.
Nets EASY recurring API expects the endDate
to have the following format: yyyy-MM-dd'T'HH:mm:ss+zz:zz
.
e.g. 2019-07-18T00:00:00+01:00
for timezone GMT + 1 hour.
The following extension on DateFormatter
can be used to convert a given date
and timezone
to this format:
extension DateFormatter {
/// Returns date formatted for Nets EASY recurring API
/// e.g. output: "2019-07-18T00:00:00+00:00"
static func easyAPIFormatted(_ date: Date, timezone: TimeZone = .current) -> String {
let timezoneOffset: String = {
DateFormatter.shared.timeZone = timezone
let seconds = DateFormatter.shared.timeZone.secondsFromGMT()
let hours = seconds / 3600
let minutes = abs(seconds / 60 % 60)
return String(format: "%+.2d:%.2d", hours, minutes)
}()
return DateFormatter.shared.string(from: date) + timezoneOffset
}
private static let shared: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
return dateFormatter
}()
}
Retrieve a Newly Created Subscription
Nets EASY recurring API returns paymentID
following subscription creation. To obtain the subscription details, use this ID to fetch subscription ID for the newly created subscription.
/// Response object following fetch request of subscription with `paymentId`
/// Object contains subscription ID that can be used to fetch subscription details
struct SubscriptionPaymentDetails: Decodable {
let payment: Payment
struct Payment: Decodable {
let created: String
let subscription: Subscription
}
struct Subscription: Decodable { let id: String }
}
// E.g. payment (for subscription) request. See MiaSample app for more
func fetchSubscriptionPayment(success: success: @escaping (SubscriptionPaymentDetails) -> Void) {
let url = baseURL.appending(path: "payments/\(paymentID)")!
let request = URLRequest(for: url, method: .get, headers: headers)
URLSession.shared.fetchJson(with: request, decodeDelegate: self, success: success, failure: nil)
}
Subscription details can be obtained from Nets EASY using a subscription ID.
// E.g. subscription details fetch request. See MiaSample app for more
func fetchSubscriptionDetails(subscriptionID: String, success: @escaping (SubscriptionDetails) -> Void) {
let url = baseURL.appending(path: "subscriptions/\(subscriptionID)")!
let request = URLRequest(for: url, method: .get, headers: headers)
URLSession.shared.fetchJson(with: request, decodeDelegate: self, success: success, failure: failure)
}
/// Subscription Details - Response to subscriptions fetch for given `subscriptionID`
struct SubscriptionDetails: Decodable {
let subscriptionId: String
let frequency, interval: Int
let endDate: String
let paymentDetails: PaymentDetails
}
Charging Subscription
Subscriptions can be charged via a POST charge request providing subscription ID and a charge request body containing order details.
/// Success response following charge-subscription request
struct ChargeSubscriptionResponse: Decodable {
let paymentId: String, chargeId: String
}
// E.g. charge request. See MiaSample app for more
func chargeSubscription(subscriptionID: String, success: @escaping (ChargeSubscriptionResponse) -> Void) {
let url = baseURL.appending(path: "subscriptions/\(subscriptionID)/charges")!
var request = URLRequest(for: url, method: .post, headers: headers)
struct ChargeRequest: Encodable { let order: Order }
request.httpBody = try! JSONEncoder().encode(ChargeRequest(order: TheOrder))
URLSession.shared.fetchJson(with: request, decodeDelegate: self, success: success, failure: failure)
}
After creating a subscription, merchant is responsible for storing and managing the subscription.
(Note that the MiaSample app stores subscriptions in the device for demo purposes but we recommend your app backend for storage)