Apple Pay
Integration in a Web-Page and App using Web-View
Here is the step-by-step integration guide for accepting Apple Pay on the Web or in hybrid App using web view.
-
Confirm that the use of Apple Pay is acceptable.
-
Confirm that the pay-page layout comply with the Human Interface Guidelines.
-
Confirm that the pay-page is fulfilling the requirements for accepting Apple Pay.
-
There are two certificates options:
- Use our certificate and identity
merchant.com.unzer.austria.test
with validated domain as described in this guide. - Provide us with your own identity and processing certificates which are registered and validated with your domain. We need private keys for both certificates (identity and processing).
- Use our certificate and identity
-
Implement the
CreateApplePayToken
operation.
The operation is similar to the CreatePaymentToken but the amount and currency should be provided for the Apple Pay session.
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:etp="https://www.mpay24.com/soap/etp/1.5/ETP.wsdl">
<soap:Body>
<etp:CreateApplePayToken>
<merchantID>92883</merchantID>
<amount>10</amount>
<currency>EUR</currency>
<domain>https://test.mpay24.com</domain>
<order>
<description>ApplepayExample</description>
</order>
</etp:CreateApplePayToken>
</soap:Body>
</soap:Envelope>
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:etp="https://www.mpay24.com/soap/etp/1.5/ETP.wsdl">
<SOAP-ENV:Body>
<etp:CreateApplePayTokenResponse>
<status>OK</status>
<returnCode>OK</returnCode>
<token>EYPoIyp2sF4YqiZzG2x1rG9AQkkFU8uw5upbVysiPdU=</token>
<apiKey>810232bfb087480b4559dfd1beb76a3efb5d8721157478aad0311316c5d4be60</apiKey>
</etp:CreateApplePayTokenResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The returned token
is used for the AcceptPayment
operation (the actual payment) and the apiKey is used to initialize the ApplePayAPI
class in the client browser.
- Integrate the ApplePayAPI in the payment page.
- Include the API JavaScript in the pay-page
<script src="https://www.mpay24.com/app/tokenizer/default/js/applepay.js"></script>
- Check if the customer can use Apple Pay (payments are possible). See here for details.
var api = new ApplePayAPI('merchant.com.unzer.austria.test', 'https://test.mpay24.com/app/bin/tokenizer/api/v1/applepay');
async function onLoad() {
try {
let available = await api.isAvailable();
if (available) {
// show the Apple Pay button
}
}
catch (err) {
...
}
};
- Initialize the API with the apiKey created in step 5. This should be done before the Apple Pay button is activated or shown.
async function initialize() {
try {
let initialized = await api.init(apiKey);
if (initialized) {
// Enable Apple Pay button
}
}
catch (err) {
...
}
}
- Authorize the payment when the Apple Pay button is clicked.
async function onApplePayButtonClicked() {
try {
await api.authorisePayment();
// the payment was authorized proceed with AcceptPayment
}
catch (err) {
...
}
}
- When the payment is authorized by the customer proceed with AcceptPayment as with credit-cards. The amount and currency should be the same as in the
CreateApplePayToken
operation (step 5) or the payment request will be declined.
In iOS, Apple Pay is supported in Safari and in SFSafariViewController objects.
For development use our test identity
merchant.com.unzer.austria.test
available on our test system
Integration in native iOS App
Here is the step-by-step integration guide for accepting Apple Pay in an native iOS App.
Please consult the official page for detailed information. There is also an example project here which can be used as a starting point. Note the changes in the PaymentHandler.swift
file below.
-
The requirements for iOS application are the same (see step 1, 2 and 3 above). Apple will reject the App if they are not met.
-
Create and provide us your processing certificate which is used to create the app. We need also the private key.
-
Implement the
CreateApplePayToken
operation in your back-end (see step 5 above). The application should call your back-end to retrieve the apiKey for the payment. -
The API is accessible under following url:
https://www.mpay24.com/app/bin/tokenizer/api/v1/applepay/{resource}
- To call the API the client should be authenticated using following HTTP headers and the apiKey from step 3.
Content-Type: application/json;charset=utf-8
Api-Key: f720b61277546ad090dd4625465cfce4df2cfc6802a936aabaa397a35e834013
- Following resources can be used with the POST method.
getSessionRequest
(optional) can be used for creation of thePKPaymentRequest
according to the merchant configured payment methods and the data provided in theCreateApplePayToken
call. Alternatively generate it in the App but currency and amount should match.
{
"merchantCapabilities": [
"supports3DS"
],
"supportedNetworks": [
"amex",
"discover",
"electron",
"jcb",
"Maestro",
"MasterCard",
"Visa",
"vPay"
],
"countryCode": "AT",
"total": {
"label": "Demo (card not charged)",
"type": "final",
"amount": "0.10"
},
"currencyCode": "EUR"
}
completePayment
(required) Creates thePKPaymentAuthorizationResult
by validating and decoding thePKPayment data
.
Example request Generation (completePaymentRequest
) and token submission (submitToken
) based on the sample code from Apple (PaymentHandler.swift
file):
class PaymentHandler: NSObject {
...
func postRequest(url: String, payload: String, apiKey: String, completion: @escaping (String?) -> Void) {
let url = URL(string: url)!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue(apiKey, forHTTPHeaderField: "Api-Key")
request.setValue("application/json;charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpBody = payload.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if (data != nil) {
completion(String(data: data!, encoding: .utf8))
}
else {
if (error != nil) {
print("Error: \(error.debugDescription)")
}
completion(nil)
}
}
task.resume()
}
func completePaymentRequest(merchantIdentifier: String, payment: PKPayment) -> String? {
let paymentData = String(data: payment.token.paymentData, encoding: .utf8)
if (paymentData == nil) {
return nil
}
let displayName = payment.token.paymentMethod.displayName ?? "unknown"
let network = payment.token.paymentMethod.network?.rawValue ?? "unknown"
let type = payment.token.paymentMethod.type
let txId = payment.token.transactionIdentifier
return """
{\"merchantIdentifier\":\"\(merchantIdentifier)\",\
\"payment\":{\"token\":{
\"paymentData\":\(paymentData!),\
\"paymentMethod\":{\"displayName\":\"\(displayName)\",\"network\":\"\(network)\",\"type\":\"\(type)\"},\
\"transactionIdentifier\":\"\(txId)\"}}}
"""
}
func submitToken(apiKey: String, payment: PKPayment, completion: @escaping (PKPaymentAuthorizationResult) -> Void) {
print("submitToken")
let result = PKPaymentAuthorizationResult(status: .failure, errors: nil)
if let request = self.completePaymentRequest(merchantIdentifier: Configuration.Merchant.identifier, payment: payment) {
print("request:\n\(request)")
let apiUrl = "https://test.mpay24.com/app/bin/tokenizer/api/v1/applepay/completePayment"
self.postRequest(url: apiUrl, payload: request, apiKey: apiKey) { apiResponse in
if apiResponse != nil {
print("completePayment response:\n\(apiResponse!)")
struct Response: Codable {
let status: String
}
if let jsonData = apiResponse?.data(using: .utf8) {
do {
let response = try JSONDecoder().decode(Response.self, from: jsonData)
result.status = response.status == "0" ? .success : .failure
completion(result)
} catch {
print("error parsing completePaymentResponse: \(error.localizedDescription)")
completion(result)
}
}
}
}
}
completion(result)
}
}
/*
Convert the PKPaymentMethodType to string
for the JSON generation in completePaymentRequest
*/
extension PKPaymentMethodType: CustomStringConvertible {
public var description: String {
switch self {
case .credit: return "credit"
case .debit: return "debit"
case .prepaid: return "prepaid"
case .store: return "store"
default:
return "unknown"
}
}
}
extension PaymentHandler: PKPaymentAuthorizationControllerDelegate {
...
func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) {
...
// Here you would send the payment token to your server or payment provider to process
// Once processed, return an appropriate status in the completion handler (success, failure, etc)
// get the apiKey from your back-end (call CreateApplePayToken operation)
let apiKey = "... "
self.submitToken(apiKey: apiKey, payment: payment) { submitTokenResponse in
self.paymentStatus = submitTokenResponse.status
completion(submitTokenResponse)
}
...
}
...
}
The response JSON object should be used to create a PKPaymentAuthorizationResult
object and complete the payment by calling the completion handler.
{
"merchantIdentifier": "merchant.com.yourdomain",
"payment": {
"token": {
"paymentData": {
"data": "...",
"signature": "...",
"header": {
"publicKeyHash": "...",
"ephemeralPublicKey": "...",
"transactionId": "..."
},
"version": "EC_v1"
},
"paymentMethod": {
"displayName": "...",
"network": "...",
"type": "..."
},
"transactionIdentifier": "..."
}
}
}
{
"status": "0"
}
- When the payment is authorized by the customer the App should proceed with
AcceptPayment
at the back-end as with credit-cards. The amount and currency should be the same as in theCreateApplePayToken
(step 2) or the payment request will be declined.
Updated 5 days ago