# Apple Pay

The payment method is limited to be used in the following devices manufactured by Apple:

**iOS Devices** | **Mac OS Devices**
--|--
Safari browser , on an Apple Pay-enabled iOS device | Safari browser on a Macbook Pro with Touch ID or a Mac model 2012 or later paired to a compatible iOS/Apple Watch with handoff enabled. 

In order to be able to accept Apple Pay payments on your website, first contact PayMe Partners partners@payme.io to start integration process.
Then you will need to complete the following steps:

1. Adding the file to your website, under the proper folder (Explained in [Step 1](#step-1-domain-verification)).
2. Signing up your website to Apple Pay via [/api/vas-enable](/payments-migrated/api?v=page:apple-pay:post-vas-enable) request.
3. Logging in to a [Testing iCloud account](#step-3-add-apple-icloud-account-and-testing-cards). (The account credentials will be provided by PayMe)
4. Use our API to [generate a new payment using Apple Pay](/payments-migrated/api?v=page:apple-pay:post-generate-sale).
5. Test your integration (Explained in [step 5](#step-5-test-your-integration))

### Devices supported for Sandbox Testing
You can use the following devices for testing in sandbox:
- iPhone 6 or later
- iPad mini 3 or later
- iPad Air 2
- iPad Pro
- Apple Watch

**Please note that you can not use Mac device for testing.**


## Step 1: Domain Verification

The first step in the process of accepting Apple Pay on your webiste will be to register your domains. You will need to register both top-level domains and sub-domains serperately.

Top-level domain example: `www.payme.io`

Sub-domain example: `www.marketplace.payme.io`


### Hosting the Apple Pay's domain verification file on your server

Host the file at `/.well-known/apple-developer-merchantid-domain-association` on your domain(s) that will display the Apple Pay button.

>Apple Pay can be tested in Production environment only. 

### File to Host

Create a text file with the following text, then add it to the `.well-known` folder under the name `apple-developer-merchantid-domain-association`. 


Make sure the folder is public, save the file without .txt ending.

```json
7B227073704964223A2230384641324636393342433744413942333336423031373431303038333532374133413243354339343039354142463539333535363042443944434639333032222C2276657273696F6E223A312C22637265617465644F6E223A313632383030303737393730352C227369676E6174757265223A223330383030363039326138363438383666373064303130373032613038303330383030323031303133313066333030643036303936303836343830313635303330343032303130353030333038303036303932613836343838366637306430313037303130303030613038303330383230336533333038323033383861303033303230313032303230383463333034313439353139643534333633303061303630383261383634386365336430343033303233303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330316531373064333133393330333533313338333033313333333233353337356131373064333233343330333533313336333033313333333233353337356133303566333132353330323330363033353530343033306331633635363336333264373336643730326436323732366636623635373232643733363936373665356635353433333432643530353234663434333131343330313230363033353530343062306330623639346635333230353337393733373436353664373333313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330353933303133303630373261383634386365336430323031303630383261383634386365336430333031303730333432303030346332313537376564656264366337623232313866363864643730393061313231386463376230626436663263323833643834363039356439346166346135343131623833343230656438313166333430376538333333316631633534633366376562333232306436626164356434656666343932383938393365376330663133613338323032313133303832303230643330306330363033353531643133303130316666303430323330303033303166303630333535316432333034313833303136383031343233663234396334346639336534656632376536633466363238366333666132626266643265346233303435303630383262303630313035303530373031303130343339333033373330333530363038326230363031303530353037333030313836323936383734373437303361326632663666363337333730326536313730373036633635326536333666366432663666363337333730333033343264363137303730366336353631363936333631333333303332333038323031316430363033353531643230303438323031313433303832303131303330383230313063303630393261383634383836663736333634303530313330383166653330383163333036303832623036303130353035303730323032333038316236306338316233353236353663363936313665363336353230366636653230373436383639373332303633363537323734363936363639363336313734363532303632373932303631366537393230373036313732373437393230363137333733373536643635373332303631363336333635373037343631366536333635323036663636323037343638363532303734363836353665323036313730373036633639363336313632366336353230373337343631366536343631373236343230373436353732366437333230363136653634323036333666366536343639373436393666366537333230366636363230373537333635326332303633363537323734363936363639363336313734363532303730366636633639363337393230363136653634323036333635373237343639363636393633363137343639366636653230373037323631363337343639363336353230373337343631373436353664363536653734373332653330333630363038326230363031303530353037303230313136326136383734373437303361326632663737373737373265363137303730366336353265363336663664326636333635373237343639363636393633363137343635363137353734363836663732363937343739326633303334303630333535316431663034326433303262333032396130323761303235383632333638373437343730336132663266363337323663326536313730373036633635326536333666366432663631373037303663363536313639363336313333326536333732366333303164303630333535316430653034313630343134393435376462366664353734383138363839383937363266376535373835303765373962353832343330306530363033353531643066303130316666303430343033303230373830333030663036303932613836343838366637363336343036316430343032303530303330306130363038326138363438636533643034303330323033343930303330343630323231303062653039353731666537316531653733356235356535616661636234633732666562343435663330313835323232633732353130303262363165626436663535303232313030643138623335306135646436646436656231373436303335623131656232636538376366613365366166366362643833383038393064633832636464616136333330383230326565333038323032373561303033303230313032303230383439366432666266336139386461393733303061303630383261383634386365336430343033303233303637333131623330313930363033353530343033306331323431373037303663363532303532366636663734323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303165313730643331333433303335333033363332333333343336333333303561313730643332333933303335333033363332333333343336333333303561333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303539333031333036303732613836343863653364303230313036303832613836343863653364303330313037303334323030303466303137313138343139643736343835643531613565323538313037373665383830613265666465376261653464653038646663346239336531333335366435363635623335616532326430393737363064323234653762626130386664373631376365383863623736626236363730626563386538323938346666353434356133383166373330383166343330343630363038326230363031303530353037303130313034336133303338333033363036303832623036303130353035303733303031383632613638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635373236663666373436333631363733333330316430363033353531643065303431363034313432336632343963343466393365346566323765366334663632383663336661326262666432653462333030663036303335353164313330313031666630343035333030333031303166663330316630363033353531643233303431383330313638303134626262306465613135383333383839616134386139396465626562646562616664616362323461623330333730363033353531643166303433303330326533303263613032616130323838363236363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353732366636663734363336313637333332653633373236633330306530363033353531643066303130316666303430343033303230313036333031303036306132613836343838366637363336343036303230653034303230353030333030613036303832613836343863653364303430333032303336373030333036343032333033616366373238333531313639396231383666623335633335366361363262666634313765646439306637353464613238656265663139633831356534326237383966383938663739623539396639386435343130643866396465396332666530323330333232646435343432316230613330353737366335646633333833623930363766643137376332633231366439363466633637323639383231323666353466383761376431623939636239623039383932313631303639393066303939323164303030303331383230313863333038323031383830323031303133303831383633303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333032303834633330343134393531396435343336333030643036303936303836343830313635303330343032303130353030613038313935333031383036303932613836343838366637306430313039303333313062303630393261383634383836663730643031303730313330316330363039326138363438383666373064303130393035333130663137306433323331333033383330333333313334333233363331333935613330326130363039326138363438383666373064303130393334333131643330316233303064303630393630383634383031363530333034303230313035303061313061303630383261383634386365336430343033303233303266303630393261383634383836663730643031303930343331323230343230343532666263656430373962393232386666393763353931643362326432323364633239376139383561376338376235613337393836653438653736626133373330306130363038326138363438636533643034303330323034343733303435303232303165336531373939663330343731633339366166626635316463346637643035333239303139393734326163373836383634353133646462383464343835383030323231303065656463653563356138313661623366666263323664613830623637383064646261313933313538323261393839656330396264306665386136623766326134303030303030303030303030227D


```

**When completing your testing process, you will need to exchange the sandbox file with the production file.**


## Step 2: Enabling the Apple Pay Payment Method

By using the [VAS-Enable API request](/payments-migrated/api?v=page:apple-pay:post-vas-enable), you will need to register your websites to PayMe's system.

```json
{
  "payme_client_key": "payme_partner_key",
  "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
  "vas_payme_id": "VASLDEMO-VASLDEMO-VASLDEMO-1234567",
  "vas_data": {
      "websites": [
      "payme.io", "marketplace.payme.io"
      ]
  },
  "language": "en"
}
```

A successful response will be 200 and includes a payload in the form of:

```json
{
    "status_code": 0,
    "seller_payme_id": "MPLDEMO-MPLDEMO-MPLDEMO-1234567",
    "vas_payme_id": "VASLDEMO-VASLDEMO-VASLDEMO-1234567",
    "vas_description": "Payments Account",
    "vas_type": "AlternativePaymentMethod",
    "vas_api_key": "",
    "vas_is_active": true,
    "vas_payer_type": 2,
    "vas_price_currency": "ILS",
    "vas_price_setup_fixed": 0,
    "vas_price_periodic_fixed": 0,
    "vas_price_periodic_variable": "0.00",
    "vas_price_usage_fixed": 0,
    "vas_price_usage_variable": "0.00",
    "vas_market_fee": null,
    "vas_period": 1,
    "vas_data": {
        "websites": [
            "test5.paymeservice.com"
        ]
    }
}
```

A failed response will be 500 and includes a payload in the form of:
```json
{
    "status_code": 1,
    "status_error_details": "The service was not activated",
    "status_additional_info": null,
    "status_error_code": 720
}
```

## Step 3: Add Apple iCloud account and Testing Cards

> **Testing iCloud account will be provided by PayMe.**

You can find credit cards for testing purposes [Test Cards and Payment Methods](/payments-migrated/introduction/test-cards-and-payment-methods#apple-pay-testing-information).


## Step 4: Add and Present the Apple Pay Button

Before you can start _Apple Payment_ you have to create an _Apple Sale_, which will be paid by your customer.

>
> **Apple sale** - You will need to generate a new sale using the API `generate-sale` method presented in our documentation [here](/payments-migrated/api?v=page:apple-pay:post-generate-sale) and briefly below.
>

_Request_
```raw
POST https://<env>.payme.io/api/generate-sale
Content-Type: application/json
PayMe-Public-Key: 9ec*****-****-****-****-*********881

{
  "seller_payme_id":"MPL14950-********-********-HMWATSBQ",
  "sale_price":"1000",
  "currency":"ILS",
  "product_name": "Test",
  "installments":"1",
  "sale_payment_method": "apple-pay",
  "language": "en"
}
```
```json http 
{
  "method": "post",
  "url": "https://<env>.payme.io/api/generate-sale",
  "headers": {
    "Content-Type": "application/json"
  },
  "body": {
  "seller_payme_id":"MPL14950-07133Z9S-DBJVLQ8I-HMWATSBQ",
  "sale_price":"1000",
  "currency":"ILS",
  "product_name": "Test",
  "installments":"1",
  "sale_payment_method": "apple-pay",
  "language": "en"
  }
}
```

_Response_

```json
{
    "status_code": 0,
    "sale_url": "https://<env>.payme.io/sale/generate/SALE1645-********-********-F2DUVUQI",
    "payme_sale_id": "SALE1645-********-********-F2DUVUQI",
    "payme_sale_code": 1027305,
    "price": 1000,
    "transaction_id": "",
    "currency": "ILS",
    "sale_payment_method": "apple-pay"
}
```

After a successful sale creation, please save the `payme_sale_id` value from the response you receive for future usage.

### Add libraries
For security reasons Apple allows to use Apple Pay only with their hosted library. It means you
should add it before PayMe integration library.
<!--
lineNumbers: true
-->
```html
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  
  <!-- Add official Apple Pay JS API -->
  <script src="https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js"></script>
  <!-- Add PayMe JS API -->
  <script src="https://cdn.paymeservice.com/hf/v1/hostedfields.js"></script>
  
</head>
<body>
...
</body>
```

This will allow you to use `PayMe` global object later

### Check if the client's system supports Apple Pay

> **Rule of thumb**
>
> You must check Apple Payment availability for your client!
>

In order check if a payment thorough Apple Pay is available for your client we provide two helper methods:

1. `PayMe.isApplePayAvailable()`
2. `PayMe.isSupportsApplePayVersion()`

Also you can check what version of Apple Payment API you are using in `PayMe.applePayApiVersion`

**If the client's environment has no support for Apple Payments, please do not show Apple Pay button** (described in the following step).

<!--
title: "Integrator must check availability before start"
lineNumbers: true
-->
```javascript
if(PayMe.isApplePayAvailable()){
  console.log('ApplePay available');
} else {
  console.log('ApplePay unavailable');
}

if(PayMe.isSupportsApplePayVersion()) {
  console.log('ApplePay version ' + PayMe.applePayApiVersion + ' supported');
} else {
  console.log('This ApplePay version is not supported');
}
```


### “Fast and Simple”: Pay with Apple button

Please follow the [**Buttons and Marks**](https://developer.apple.com/design/human-interface-guidelines/apple-pay/overview/buttons-and-marks/) article in the Apple official website.

<!--
lineNumbers: true
-->
```html

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">

  <!-- Add official Apple Pay JS API -->
  <script src="https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js"></script>
  <!-- Add PayMe JS API -->
  <script src="https://cdn.paymeservice.com/hf/v1/hostedfields.js"></script>

</head>
<body>
    <!-- Pay with Apple button STARTS HERE -->
    <apple-pay-button
      id="pay-with-apple-pay"
      buttonstyle="black"
      type="buy"
      locale="he-IL"></apple-pay-button>
    <!-- Pay with Apple button ENDS HERE -->

    <!-- My Integration -->
    <script>
      var isApplePayAvailable;
    
      if(PayMe.isApplePayAvailable() && PayMe.isSupportsApplePayVersion()) {
        isApplePayAvailable = true;
      } else {
        isApplePayAvailable = false;
      }
      
      const applePayButton = document.getElementById('pay-with-apple-pay');
      if(!isApplePayAvailable) {
        applePayButton.classList.add('hidden');
      }
    </script>
</body>

```

Please pay attention on the `id` and `locale` attribute. You will need `id` or `class` or other CSS selector
to tell integration library how to find _Pay Button_. The `locale` is a custom attribute, one of many which
let you [customize Apple Pay Button appearance](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaybuttonstyle).
If your use case is not meet this type of implementation you can provide any CSS selector (even for non existing DOM element) and 
follow [***“Manual”: Initiate Payment manually approach***](#manual-initiate-payment-manually)


### Initialization

After implementing the certificate file, update PayMe Partners partners@payme.io to verify your domain was approved by apple, and to provide your Merchant API key.

```javascript
...
// This is the Merchant API key (Test API key in this case)
var apiKey = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
...
```

Second, you must obtain integration **instance** for the merchant
<!--
lineNumbers: true
-->
```javascript
var apiKey = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';

// There is optional configuration object with testMode: true
// because we are using the API key from the test server
PayMe.create(apiKey, { testMode: true })
    .then(function (instance) {
    
      // Here we can work with successfully initialized
      // integration instance - Integration Manager
       ...
    })
    .catch(function(error) {
      // Here you can handle instantiation error
      ...
    });
    
...
```

#### Initialization settings

Property          |   Default value  |   Available values  | Description
----------------- | :--------------: | :-----------------: | -------------
`testMode`        | false            | true / false        | `Test mode` - used to control in which environment payment will be processed

Next step - to initialize integration type and get corresponding manager

> **Note**
>
> Integration Manager **instance** also can be used for [Hosted Fields](LINK_TO_HF) integration


### ApplePay sale

Using initialized integration manager you need to use earlier created Sale to create Apple Sale.
Just call `.appleSale(...)` method and get back _AppleSale_. We will use it to initiate Payment Flow
and be notified on progress.

<!--
lineNumbers: true
-->
```html
<html lang="en">
    <head>
        <!-- Include Client API Library into your page -->
        ...
    </head>
    <body>
        <!-- Pay with Apple button STARTS HERE -->
        ...
        <!-- Pay with Apple button ENDS HERE -->

        <!-- My Integration -->
        <script>
            
            var apiKey = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'; // Merchant API key from Settings page in the dashboard
            
            PayMe.create(apiKey, { testMode: true }).then(function (instance) {
           
              var sale = instance.appleSale({
                
                // Optional. In case you want to debug Apple Sale internal transitions
                debugFn: function (message){
                  console.log(message);
                },
                
                
                merchantId: , // Will be provided by your PayMe integration manager
                saleGuid: <payme_sale_id> // See Prerequisites. Create a Sale
              });
              
              ...
              
            }).catch(function(error) {
                // Instantiation error occurs 
            })
        
        </script>
    </body>
</html>    
```

### Allow user to Start payment

Because of security reasons you can't just start Apple Payment flow, only user action 
(click or tap Apple Pay Button) can trigger this flow. Because of that you must initiate
this for your user with `.letsRock(...)` method with Apple Pay Button selector.
Or you should check [***“Manual”: Initiate Payment manually***](#manual-initiate-payment-manually)  section for additional options.

<!--
lineNumbers: true
-->
```html
<html lang="en">
    <head>
        <!-- Include Client API Library into your page -->
        ...
    </head>
    <body>
        <!-- Pay with Apple button STARTS HERE -->
        ...
        <!-- Pay with Apple button ENDS HERE -->

        <!-- My Integration -->
        <script>
            
            var apiKey = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'; // Merchant API key from Settings page in the dashboard
            
            PayMe.create(apiKey, { testMode: true }).then(function(instance) {
           
              var saleConfig = {...};
              var sale = instance.appleSale(saleConfig);
              
              sale.letsRock('#pay-with-apple-pay')
                .then(function(){
                  console.log('Sale verified and wait for user action');
                })
                .catch(function(err) {
                  console.error('Apple Pay Initialization error'+ err.message);
                });
              
            }).catch(function(error) {
                // Instantiation error occurs 
            })
        
        </script>
    </body>
</html>
```




#### Interaction Facade

Highly likely, you will need to receive information of the status of your payment to
build your own  user experience, _Apple Sale_ provides this option by defining plain configuration
object for `.letsRock(...)` method.

<!--
lineNumbers: true
-->
```javascript
var config = {
  
  // Required
  payButtonSelector: '#pay-with-apple-pay',
  
  // Optional
  canceled: function(){
    console.log('AppleSale cancelled');
  },
  
  // Optional
  validated: function(err) {
    if(!!err){
      console.error('AppleSale validation error '+err.message);
    } else {
      console.log('AppleSale validated successfully');
    }
  },
  
  // Optional
  paymentCompleted: function (err, sale) {
    if(!!err){
      console.error('AppleSale failed ' + err.message);
    } else {
      console.log('Sale Payed' + JSON.stringify(sale, null, 2));
    }
  },
};
```

#### Interaction Facade

Property          | Default value |     Available values     | Description
----------------- |:-------------:|:------------------------:| -------------
`payButtonSelector`        |     _none_      | _any valid CSS selector_ | Selector to find _Apple Pay Button_ on the page
`canceled` | () => {} |   _callback function_    | This function will be called on _Apple Sale_ cancellation
`validated` | () => {} |   _callback function_    | This function will be called after _Apple Sale_ validated by the user
`paymentCompleted` | () => {} |   _callback function_    | This function will on _Apple Sale_ completion with the result


This facade will allow you to register your callbacks and handle changes in your application.

### “Manual”: Initiate Payment manually

Sometimes you will need to use our integration library to solve some tricky edge case and you can not provide
*Pay Button* on your page to be picked by the library. This require to provide alternative way to kick-off Apple
payment flow programmatically. We are letting you todo that by calling `startPayment()` function for the prepared ApplePay sale.

Lets review a technical meaning by adapting example from Allow user to Start payment


```html
<html lang="en">
    <head>
        <!-- Include Client API Library into your page -->
        ...
    </head>
    <body>
        ...
        <!-- My Integration -->
        <script>
            var apiKey = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'; // Merchant API key from Settings page in the dashboard

            PayMe.create(apiKey, { testMode: true }).then(function(instance) {
           
              var saleConfig = {...};
              var sale = instance.appleSale(saleConfig);
              sale
                // !!! THE CHANGES STARTS HERE !!!
                .letsRock('.i-dont-have-pay-button')
                .then(function(startPaymentFn){
                  // In case you want to query ApplePay button yourself
                  document.getElementById('my-custom-button').addEventListener('click', startPaymentFn);
                  
                  // Or even you want to react on Window message
                  window.addEventListener('message', () => {
                    // Do important preparations and ...
                    startPaymentFn();
                  });
                });
                // !!! THE CHANGES ENDS HERE !!!
    
            });
        </script>
    </body>
</html>
```
> **Only user action can initiate Apple Payment flow!**
>
>
>As a reminder we would like to repeat the limitation from Apple:
>
>***You can not just start Apple Payment flow with startPayment() function, only user action (click or tap on the DOM node) can trigger this flow.***
>
>It means even if you will try to postMessage from iFrame using `setTimeout()` in hope to catch it on the host page,
>this case will be detected by Apple and will end up with error ***"Must create a new ApplePaySession from a user gesture handler"***
>([Creating an Apple Pay Session | Apple Developer Documentation](https://developer.apple.com/documentation/apple_pay_on_the_web/apple_pay_js_api/creating_an_apple_pay_session))

As code listing shows, we just defined argument for the `letsRock.then(...)` callback with name `startPaymentFn`
(you can give it any name). This argument is a synchronous function, you can use it as an event handler for
your implementation., like we did in our example.

## Step 5: Test your integration
To verify the ingeration works as expected:
1. Add our test page under your domain. For example: `{your domain}/apple-pay-test.html` see page below.
2. Fill merchant.paymeproduction under merchantIdentifier
3. Enter your apiKey under publickKey
4. Generate sale as described in step 4 and enter the sale id received
5. Start interaction - will initiate the payment flow with apple pay


Test Page:
![test page.png](<../../assets/images/test page.png>)


```json
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">

  <title>Example Bootstrap implementation</title>

  <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">

  <script src="https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js"></script>
  <script src="https://cdn.paymeservice.com/hf/v1/hostedfields.js"></script>
</head>
<body>
<div>&nbsp;</div>
<div class="container">
  <div class="row">
    <div class="col-xs-12 col-sm-8 col-sm-offset-2">
      <div class="panel panel-default credit-card-box">
        <div class="panel-body">
          <form id="init-payment-form">
            <div class="row">
              <div class="col-xs-12">
                <div class="form-group">
                  <label for="merchantIdentifier" class="control-label">merchantIdentifier</label>
                  <input
                    id="merchantIdentifier"
                    class="form-control input-lg"
                    value="merchant.paymeproduction">

                </div>
              </div>
              <div class="col-xs-12">
                <div class="form-group">
                  <label for="publicKey" class="control-label">publicKey</label>
                  <input
                    id="publicKey"
                    class="form-control input-lg"
                    value="e780113a-9ac8-4ece-8c64-66b2b8308cb3">

                </div>
              </div>
              <div class="col-xs-12">
                <div class="form-group">
                  <label for="saleId" class="control-label">saleId</label>
                  <input
                    id="saleId"
                    class="form-control input-lg"
                    value="SALE1737-563287XL-NCQMEHY9-KLO4ZJFJ">

                </div>
              </div>
              <div class="col-xs-12">
                <div class="form-group">
                  <button class="btn" id="start-interaction">Start interaction</button>
                </div>
              </div>
            </div>
          </form>
        </div>
      </div>
    </div>
  </div>

  <div class="row hidden" id="applepay-button-wrapper">
    <div class="col-xs-12 col-sm-8 col-sm-offset-2">
      <div class="text-center">
        <div>Pay button below</div>
        <apple-pay-button
          id="pay-with-apple-pay"
          buttonstyle="black" type="buy" locale="he-IL"></apple-pay-button>
      </div>
    </div>
  </div>
</div>

<hr>

<pre id="console-pre"></pre>

<script>
  const consolePre = document.getElementById('console-pre');

  function log(txt) {
    consolePre.innerText += txt + '\n';
  }

  function clear() {
    consolePre.innerText = '----- log cleared -----\n\n';
  }
</script>
<script>
  let _currentSale;
  const PayMe = window.PayMe;

  function startApplePayStuff({merchantIdentifier, publicKey, saleId}) {
    const options = {
      testMode: false,
      language: 'he',
      // Extended
      // tokenIsPermanent: false, // default true
      // buyerIsPrivate: true    // default false,
      // buyerPerformValidation: // default true,
    };

    return PayMe.create(publicKey, options).then((instance) => {
      try {
        const currentSale = instance.appleSale({
          debugFn: log,
          merchantId: merchantIdentifier,
          saleGuid: saleId
        });

        // Config can de String
        const config = {
          // Required
          payButtonSelector: '#pay-with-apple-pay',
          // Optional
          canceled: () => {
            log('\nCancelled\n----------------------------------');
          },
          // Optional
          validated: (err) => {
            if(!!err){
              log('\nValidated error\n'+ err.message +'\n----------------------------------');
              console.error(err);
            } else {
              log('\nValidated\n----------------------------------');
            }
          },
          // Optional
          paymentCompleted: (err, sale) => {
            if(!!err){
              log('\nCompleted error\n'+ err.message +'\n----------------------------------');
              console.error(err);
            } else {
              log('\nCompleted\n'+ JSON.stringify(sale, null, 2) +'\n----------------------------------');
            }
          },
        };

        currentSale.letsRock(config)
          .then(() => {
            log('\nSale initialized\n----------------------------------');
          })
          .catch(err => {
            log('\nsale initialization error\n'+ err.message +'\n----------------------------------');
            console.error(err);
          });

        return currentSale;

      } catch (e) {
        log(e.message);
      }
    });
  }

  const paramsForm = document.getElementById('init-payment-form');
  const applePayButtonWrapper = document.getElementById('applepay-button-wrapper');

  function hideButton() {
    if(!applePayButtonWrapper.classList.contains('hidden')){
      applePayButtonWrapper.classList.add('hidden');
    }
  }

  function displayButton() {
    applePayButtonWrapper.classList.remove('hidden');
  }

  //
  // Integrator must check availability before start
  if(PayMe.isApplePayAvailable()){
    log('ApplePay available');
  } else {
    log('ApplePay unavailable');
  }

  if(PayMe.isSupportsApplePayVersion()) {
    log(`ApplePay version "${PayMe.applePayApiVersion}" supported`);
  } else {
    log('This ApplePay version is not supported');
  }

  paramsForm.addEventListener('submit', event => {
    event.preventDefault();

    clear();

    if(_currentSale) {
      _currentSale.destroy();
      hideButton();
    }

    const merchantIdentifier = document.getElementById('merchantIdentifier');
    const publicKey = document.getElementById('publicKey');
    const saleId = document.getElementById('saleId');

    const values = {
      merchantIdentifier: merchantIdentifier.value,
      publicKey: publicKey.value,
      saleId: saleId.value,
    };

    startApplePayStuff(values)
      .then(appleSale => {
        _currentSale = appleSale;
        displayButton();
      })
      .catch(err => {
        hideButton();
        log(err.message);
      });
  });
</script>


</body>
</html>

```



## Errors and Reasons

Your responsibility is to handle possible errors related to the Apple Pay. We provide a limited list of logical errors to help you easily identify and handle mistakes or show localized descriptions for your users.
Below, you will be ale to find  detailed information and hints for you to help your end-users.

##### 1. NOT_SUPPORTED_DEVICE (`no-supported:apple-pay-not-available-for-device`) and NO_APPLE_PAY (`no-supported:apple-pay-jsapi-not-available`)
> **A context**
>
> Apple Payment can work only in Safari Browsers on Apple Devices.
>
> Before you can offer your clients this payment method, you have to check is it possible to execute
> Apple Payment on the client device. To do this check we are providing special helper-methods
> (`PayMe.isApplePayAvailable()` and `PayMe.isSupportsApplePayVersion()`). But there is possible situation
> when you ignored this check and tried to create _AppleSale_. In case of unsupported environment
> you will receive this error
>

**Reason**

Attempt to create _AppleSale_ on unsupported environment (not an Apple Browser, not an Apple Device)

**Possible Solutions**

1. You must use `PayMe.isApplePayAvailable()` and `PayMe.isSupportsApplePayVersion()` before _Apple Sale_ creation
   and fallback to the alternative logic in case of negative result.





##### 2. NOT_SUPPORTED_VERSION (`no-supported:apple-pay-version-not-supported`)
> **A context**
>
> Our integration library is based on the official Apple Pay JSAPI. The official library offers
> different integration versions. We use v4 to cover as many devices as possible.
>

**Reason**

Attempt to create _AppleSale_ on environment which is not supported by the current version of Apple Payment

**Possible Solutions**

1. Unfortunately, we have no solution for this situation (_TODO - discuss this_);




##### 3. VALIDATION_NO_NETWORKS (`validation-error:no-supported-networks`)
> **A context**
>
> Each of our merchants has limited set of supported Credit Card Brands aka Networks.
> These networks will be checked before start of Apple Payment.
>

**Reason**

Current merchant has no Networks supported by Apple

**Possible Solutions**

1. Please reach our support service to solve this issue.




##### 4. VALIDATION_NO_NETWORKS (`validation-error:no-supported-networks`)
> **A context**
>
> Each of our merchants has limited set of supported Credit Card Brands aka Networks.
> These networks will be checked before the Apple Pay flow starts.
>

**Reason**

Current merchant has no Networks supported by Apple

**Possible Solutions**

1. Please reach our support service to solve this issue.




##### 5. INVALID_CFG_PARAM (`validation:unknown-configuration-parameter`)
> **A context**
>
> To start Apple Payment Flow you must provide simple config data.
>

**Reason**

Invalid configuration provided for `letsRock(...)` method

**Possible Solutions**

1. Please check what was provided as config data




##### 6. INVALID_VALIDATED_CB (`validation:invalid-type-for-validated-callback`) and INVALID_CANCELLED_CB (`validation:invalid-type-for-cancelled-callback`) end INVALID_COMPLETED_CB (`validation:invalid-type-for-payment-completed-callback`)
> **A context**
>
> To let your code know about status of Apple Sale we let you provide
> callback functions. These functions will be called by the integration on status change.
>

**Reason**

Invalid configuration provided for `letsRock(...)` method

**Possible Solutions**

1. Please check what is callback provided as part of config data




##### 7. NOT_A_FUNCTION (`validation:argument-is-not-a-function`)
> **A context**
>
> According to previous sections you must provide a callback functions if you interested to be
> notified on Apple Sale state change
>

**Reason**

Provided not function but something else as a callback(s)

**Possible Solutions**

1. Please check what provided as part of config data







#### Error messages localization

To keep the integration in place, we are not providing any translation possibilities in favor of mnemonic messages. It means our error
messages will look to user too technical. To make them human-readable you have to transform it to messages you want
<!--
lineNumbers: true
-->
```javascript
var translatedMessages = {
  'not-found:apple-pay-button-not-found': 'Unable to find Pay button on your page',
  'no-supported:apple-pay-not-available-for-device': 'This device does not support Apple Pay',
  'no-supported:apple-pay-jsapi-not-available': 'This device does not support Apple Pay',
  'no-supported:apple-pay-version-not-supported': 'This device does not support current Apple Pay API version',
  // Other errors ...
};

// Other code...

// Run Apple Payment
sale.letsRock(config).catch(function (err) {
  // Getting translated human-readable error message
  const hriMessage = translatedMessages[err.message];
  alert(hriMessage);
});

// Other code...

```

For your convenience, we gathered all of the possible error-messages in to the Hash inside _PayMe_ global object, it means
instead of doing the following:
<!--
lineNumbers: true
-->
```javascript
var translatedMessages = {
  'not-found:apple-pay-button-not-found': 'Unable to find Pay button on your page',
  'no-supported:apple-pay-not-available-for-device': 'This device does not support Apple Pay',
  'no-supported:apple-pay-jsapi-not-available': 'This device does not support Apple Pay',
  'no-supported:apple-pay-version-not-supported': 'This device does not support current Apple Pay API version',
  // Other errors ...
};
```

A better option would be to do the following:
<!--
lineNumbers: true
-->
```javascript
// Doing shortcut, for convenience
var messages = PayMe.ERR_MESSAGES;

// Defining hri messages
var translatedMessages = {
  // Errors related to the client environment
  [messages.NO_PAY_BUTTON]: 'Unable to find Pay button on your page',
  [messages.NOT_SUPPORTED_DEVICE]: 'This device does not support Apple Pay',
  [messages.NO_APPLE_PAY]: 'This device does not support Apple Pay',
  [messages.NOT_SUPPORTED_VERSION]: 'This device does not support current Apple Pay API version',

  // Technical errors (ideally should not occur on production)
  [messages.VALIDATION_NO_NETWORKS]: 'There are no supported Credit Card networks for this seller',
  [messages.INVALID_VALIDATED_CB]: 'There is incorrect sale Validatied callback provided by the implementer',
  [messages.INVALID_CANCELLED_CB]: 'There is incorrect sale Cancelled callback provided by the implementer',
  [messages.INVALID_COMPLETED_CB]: 'There is incorrect sale Completed callback provided by the implementer',
  [messages.INVALID_CFG_PARAM]: 'Implementer provided invaid configuration paramener',
  [messages.NOT_A_FUNCTION]: 'This is not a function!'
};
```

## Apple Pay Impelementation using iFrame
If you are willing to implement the apple pay button using an iframe, please get in touch with our integration team for further information.
