Skip to content

Apple Pay Integration via Iframe

Overview

The Apple Pay integration enables merchants to accept Apple Pay payments through Tranzila's iframe solution. The implementation is fully automated - merchants only need to include a script and create an iframe. All Apple Pay session management, token handling, and communication are handled transparently by Tranzila.

Prerequisites

Merchant Requirements

The following requirements must be met before implementation:

  • Active credit card terminal with Tranzila, approved with an internet merchant number
  • Apple Pay service purchased from Tranzila (paid service)
  • Domain registration with Tranzila for Apple Pay service
  • Valid SSL certificate (HTTPS required)
  • Server access for verification file deployment

Technical Requirements

Supported Devices

  • iPhone with Touch ID or Face ID
  • iPad with Touch ID or Face ID
  • Mac with Touch ID or authenticated via connected iPhone/iPad

Supported Browsers

On Mac:

  • Safari - Full support
  • Chrome - Supported (version 78+)
  • Edge - Supported (version 79+)
  • Firefox - Supported (version 119+)
  • Opera - Supported

On iPhone/iPad:

  • Safari - Full support
  • Chrome - Supported
  • Edge - Supported
  • Firefox - Supported
  • Other iOS browsers - Generally supported

Note: All browsers on iOS use Safari's WebKit engine, ensuring Apple Pay compatibility across all major browsers on Apple mobile devices.

For a complete list of supported devices, refer to Apple's device compatibility documentation.

Implementation Guide

If you are implementing hosted fields, you must also follow steps 1 and 2

Step 1: Domain Verification

Apple requires domain verification to enable Apple Pay. This process involves hosting a verification file on your domain.

1.1 Obtain Verification File

Download the verification file from Tranzila:

  • URL: https://api.tranzila.com/assets/apple_pay/merchant_authentication_file.zip
  • Extract the .dat file from the archive
  • Preserve the original filename

1.2 Deploy Verification File

The verification file must be accessible at the following URL structure:

Text
https://[your-domain]/.well-known/apple-developer-merchantid-domain-association

Deployment Requirements:

  • The file must be served without a file extension
  • The URL path is case-sensitive
  • HTTPS protocol is mandatory

1.3 Framework-Specific Deployment

Static Hosting

Place the file in your public directory:

Text
public/
└── .well-known/
    └── apple-developer-merchantid-domain-association

React/Next.js/Remix

Place the file in the public directory:

Text
public/
└── .well-known/
    └── apple-developer-merchantid-domain-association

Vue.js

Place the file in the public directory:

Text
public/
└── .well-known/
    └── apple-developer-merchantid-domain-association

Angular

  1. Create the directory structure in your source folder:
Text
src/
└── .well-known/
    └── apple-developer-merchantid-domain-association
  1. Configure angular.json to include the file in the build:
JSON
{
  "projects": {
    "your-app": {
      "architect": {
        "build": {
          "options": {
            "assets": [
              "src/favicon.ico",
              "src/assets",
              {
                "glob": "apple-developer-merchantid-domain-association",
                "input": "src/.well-known/",
                "output": ".well-known/"
              }
            ]
          }
        }
      }
    }
  }
}

Express/Node.js

Configure static file serving:

JavaScript
app.use('/.well-known', express.static('.well-known'));

1.4 Verify Deployment

Confirm file accessibility using the following command:

Shell
curl https://[your-domain]/.well-known/apple-developer-merchantid-domain-association

Expected response: The contents of the verification file

1.5 Complete Registration

Important: After successful file deployment, you must contact Tranzila support to complete the Apple Pay activation and domain registration for your terminal. The service will not work until Tranzila confirms the registration.

Contact support at: 073-222-4444

Step 2: Include Required Scripts

Add jQuery and the Tranzila Apple Pay script to your page. jQuery is required as a dependency for the Tranzila Apple Pay script to function properly.

Standard Implementation

HTML
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script>document.write('<script src="https://directng.tranzila.com/assets/js/tranzilanapple_v3.js?v=' + Date.now() + '"><\/script>');</script>
<script>var $n = jQuery.noConflict(true);</script>

Alternative Dynamic Loading Implementation with Error Handling

For modern JavaScript applications with proper error handling:

JavaScript
// Load jQuery first with error handling
const jqueryScript = document.createElement('script');
jqueryScript.src = 'https://code.jquery.com/jquery-3.6.0.js';
jqueryScript.async = true;
document.head.appendChild(jqueryScript);

jqueryScript.onload = function() {
    console.log('jQuery loaded successfully');
    
    // Load Tranzila Apple Pay script after jQuery loads
    const tranzilaScript = document.createElement('script');
    tranzilaScript.src = 'https://directng.tranzila.com/assets/js/tranzilanapple_v3.js?v=' + Date.now();
    tranzilaScript.async = true;
    document.head.appendChild(tranzilaScript);
    
    tranzilaScript.onload = function() {
        console.log('Tranzila Apple Pay script loaded successfully');
        // Set jQuery noConflict mode
        if (window.jQuery) {
            window.$n = jQuery.noConflict(true);
        }
    };
    
    tranzilaScript.onerror = function() {
        console.error('Failed to load Tranzila Apple Pay script');
        // Handle error - perhaps show a message to the user
    };
};

jqueryScript.onerror = function() {
    console.error('Failed to load jQuery');
    // Handle error - perhaps show a message to the user
};

Notes:

  • jQuery is required for the Tranzila Apple Pay script to function
  • The noConflict mode prevents conflicts with existing jQuery instances
  • The timestamp parameter ensures the latest version is loaded
  • The scripts must be included on the same page that contains the payment iframe
  • Use the standard implementation for simple HTML pages
  • Use the dynamic loading approach for SPAs or when scripts need to be loaded conditionally

Step 3: Create Payment Iframe

Configure the iframe with Apple Pay enabled. When Apple Pay is available on the user's device, it will automatically appear as a payment option within the iframe.

Option 1: GET Method (URL Parameters)

HTML
<iframe 
    src="https://direct.tranzila.com/[terminal-name]/iframenew.php?sum=100&currency=1&apple_pay=1&lang=en"
    width="100%"
    height="600"
    frameborder="0"
    allowpaymentrequest="true">
</iframe>

Option 2: POST Method (Form Submission)

HTML
<form id="payment-form" 
      action="https://direct.tranzila.com/[terminal-name]/iframenew.php" 
      method="POST" 
      target="payment-iframe">
    
    <!-- Required Parameters -->
    <input type="hidden" name="sum" value="100">
    <input type="hidden" name="currency" value="1">
    <input type="hidden" name="apple_pay" value="1">
    
    <!-- Response URLs -->
    <input type="hidden" name="success_url_address" value="https://your-domain.com/success">
    <input type="hidden" name="fail_url_address" value="https://your-domain.com/failure">
    
    <!-- Optional Parameters -->
    <input type="hidden" name="lang" value="en">
    <input type="hidden" name="contact" value="customer@email.com">
    <input type="hidden" name="company" value="Customer Name">
    <input type="hidden" name="pdesc" value="Product Description">
</form>

<iframe name="payment-iframe" 
        width="100%" 
        height="600" 
        frameborder="0"
        allowpaymentrequest="true">
</iframe>

<script>
    // Submit form to load iframe
    document.getElementById('payment-form').submit();
</script>

Complete Implementation Examples

HTML Implementation

Using GET Method

HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Checkout - Apple Pay Enabled</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
        }
        
        .checkout-container {
            max-width: 600px;
            margin: 0 auto;
            background: white;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            padding: 30px;
        }
        
        h1 {
            color: #333;
            margin-bottom: 30px;
        }
        
        .payment-iframe {
            width: 100%;
            height: 600px;
            border: none;
            border-radius: 8px;
        }
    </style>
</head>
<body>
    <div class="checkout-container">
        <h1>Complete Your Payment</h1>
        
        <!-- Required Scripts for Apple Pay -->
        <script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>
        <script>document.write('<script src="https://directng.tranzila.com/assets/js/tranzilanapple_v3.js?v=' + Date.now() + '"><\/script>');</script>
        <script>var $n = jQuery.noConflict(true);</script>
        
        <!-- Payment Iframe with Apple Pay Enabled -->
        <iframe 
            class="payment-iframe"
            src="https://direct.tranzila.com/[terminal-name]/iframenew.php?sum=100&currency=1&apple_pay=1&lang=en&success_url_address=https://your-domain.com/success&fail_url_address=https://your-domain.com/failure"
            allowpaymentrequest="true">
        </iframe>
    </div>
</body>
</html>

Using POST Method

HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Checkout - Apple Pay with POST</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
        }
        
        .checkout-container {
            max-width: 600px;
            margin: 0 auto;
            background: white;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            padding: 30px;
        }
        
        h1 {
            color: #333;
            margin-bottom: 30px;
        }
        
        .payment-iframe {
            width: 100%;
            height: 600px;
            border: none;
            border-radius: 8px;
        }
    </style>
</head>
<body>
    <div class="checkout-container">
        <h1>Complete Your Payment</h1>
        
        <!-- Required Scripts for Apple Pay -->
        <script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.js"></script>
        <script>document.write('<script src="https://directng.tranzila.com/assets/js/tranzilanapple_v3.js?v=' + Date.now() + '"><\/script>');</script>
        <script>var $n = jQuery.noConflict(true);</script>
        
        <!-- POST Form for Iframe -->
        <form id="payment-form" 
              action="https://direct.tranzila.com/[terminal-name]/iframenew.php" 
              method="POST" 
              target="payment-iframe">
            
            <!-- Required Parameters -->
            <input type="hidden" name="sum" value="100">
            <input type="hidden" name="currency" value="1">
            <input type="hidden" name="apple_pay" value="1">
            
            <!-- Response URLs -->
            <input type="hidden" name="success_url_address" value="https://your-domain.com/success">
            <input type="hidden" name="fail_url_address" value="https://your-domain.com/failure">
            
            <!-- Optional Parameters -->
            <input type="hidden" name="lang" value="en">
            <input type="hidden" name="contact" value="customer@email.com">
            <input type="hidden" name="company" value="John Doe">
            <input type="hidden" name="pdesc" value="Premium Package">
        </form>
        
        <!-- Payment Iframe -->
        <iframe name="payment-iframe" 
                class="payment-iframe"
                allowpaymentrequest="true">
        </iframe>
        
        <script>
            // Submit form when page loads
            window.onload = function() {
                document.getElementById('payment-form').submit();
            };
        </script>
    </div>
</body>
</html>

React Implementation

Using GET Method

JSX
// PaymentPage.jsx
import React, { useEffect } from 'react';

const PaymentPage = () => {
    // Configuration
    const TERMINAL_NAME = 'your-terminal';
    const AMOUNT = '100';
    const CURRENCY = '1'; // 1=ILS, 2=USD, 978=EUR
    
    useEffect(() => {
        // Load jQuery
        const jquery = document.createElement('script');
        jquery.src = 'https://code.jquery.com/jquery-3.6.0.js';
        jquery.async = true;
        document.body.appendChild(jquery);
        
        jquery.onload = () => {
            // Load Tranzila Apple Pay script after jQuery
            const script = document.createElement('script');
            script.innerHTML = `document.write('<script src="https://directng.tranzila.com/assets/js/tranzilanapple_v3.js?v=' + Date.now() + '"><\\/script>');`;
            document.body.appendChild(script);
            
            // Set jQuery noConflict
            const noConflict = document.createElement('script');
            noConflict.innerHTML = 'var $n = jQuery.noConflict(true);';
            document.body.appendChild(noConflict);
        };
        
        // Cleanup
        return () => {
            const scripts = document.querySelectorAll('script[src*="jquery"], script[src*="tranzilanapple"]');
            scripts.forEach(script => script.remove());
        };
    }, []);
    
    // Build iframe URL with parameters
    const iframeUrl = `https://direct.tranzila.com/${TERMINAL_NAME}/iframenew.php?` + 
        new URLSearchParams({
            sum: AMOUNT,
            currency: CURRENCY,
            apple_pay: '1',
            lang: 'en',
            success_url_address: window.location.origin + '/success',
            fail_url_address: window.location.origin + '/failure'
        }).toString();
    
    return (
        <div className="payment-container">
            <h1>Complete Your Payment</h1>
            
            <iframe
                src={iframeUrl}
                width="100%"
                height="600"
                frameBorder="0"
                allowPaymentRequest={true}
                title="Payment Form"
            />
        </div>
    );
};

export default PaymentPage;

Using POST Method

JSX
// PaymentPagePost.jsx
import React, { useEffect, useRef } from 'react';

const PaymentPagePost = () => {
    const formRef = useRef(null);
    
    // Configuration
    const TERMINAL_NAME = 'your-terminal';
    const paymentData = {
        sum: '100',
        currency: '1', // 1=ILS, 2=USD, 978=EUR
        apple_pay: '1',
        lang: 'en',
        success_url_address: window.location.origin + '/success',
        fail_url_address: window.location.origin + '/failure',
        contact: 'customer@example.com',
        company: 'John Doe',
        pdesc: 'Premium Package'
    };
    
    useEffect(() => {
        // Load jQuery
        const jquery = document.createElement('script');
        jquery.src = 'https://code.jquery.com/jquery-3.6.0.js';
        jquery.async = true;
        document.body.appendChild(jquery);
        
        jquery.onload = () => {
            // Load Tranzila Apple Pay script after jQuery
            const script = document.createElement('script');
            script.innerHTML = `document.write('<script src="https://directng.tranzila.com/assets/js/tranzilanapple_v3.js?v=' + Date.now() + '"><\\/script>');`;
            document.body.appendChild(script);
            
            // Set jQuery noConflict
            const noConflict = document.createElement('script');
            noConflict.innerHTML = 'var $n = jQuery.noConflict(true);';
            document.body.appendChild(noConflict);
            
            // Submit form after scripts load
            setTimeout(() => {
                if (formRef.current) {
                    formRef.current.submit();
                }
            }, 100);
        };
        
        // Cleanup
        return () => {
            const scripts = document.querySelectorAll('script[src*="jquery"], script[src*="tranzilanapple"]');
            scripts.forEach(script => script.remove());
        };
    }, []);
    
    return (
        <div className="payment-container">
            <h1>Complete Your Payment</h1>
            
            <form 
                ref={formRef}
                action={`https://direct.tranzila.com/${TERMINAL_NAME}/iframenew.php`}
                method="POST"
                target="payment-iframe"
                style={{ display: 'none' }}>
                
                {Object.entries(paymentData).map(([key, value]) => (
                    <input key={key} type="hidden" name={key} value={value} />
                ))}
            </form>
            
            <iframe
                name="payment-iframe"
                width="100%"
                height="600"
                frameBorder="0"
                allowPaymentRequest={true}
                title="Payment Form"
            />
        </div>
    );
};

export default PaymentPagePost;
JSX
// App.jsx - Complete React Application Example
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import PaymentPage from './PaymentPage';
import SuccessPage from './SuccessPage';
import FailurePage from './FailurePage';

function App() {
    return (
        <Router>
            <Routes>
                <Route path="/checkout" element={<PaymentPage />} />
                <Route path="/success" element={<SuccessPage />} />
                <Route path="/failure" element={<FailurePage />} />
            </Routes>
        </Router>
    );
}

export default App;
CSS
/* PaymentPage.css */
.payment-container {
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
    background: white;
    border-radius: 10px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.payment-container h1 {
    color: #333;
    margin-bottom: 30px;
    font-size: 24px;
}

.payment-container iframe {
    border: none;
    border-radius: 8px;
}

Angular Implementation

Using GET Method

TypeScript
// payment.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

@Component({
  selector: 'app-payment',
  templateUrl: './payment.component.html',
  styleUrls: ['./payment.component.css']
})
export class PaymentComponent implements OnInit, OnDestroy {
  iframeUrl: SafeResourceUrl;
  
  // Configuration
  private readonly TERMINAL_NAME = 'your-terminal';
  private readonly AMOUNT = '100';
  private readonly CURRENCY = '1'; // 1=ILS, 2=USD, 978=EUR
  
  constructor(private sanitizer: DomSanitizer) {
    // Build iframe URL
    const params = new URLSearchParams({
      sum: this.AMOUNT,
      currency: this.CURRENCY,
      apple_pay: '1',
      lang: 'en',
      success_url_address: window.location.origin + '/success',
      fail_url_address: window.location.origin + '/failure'
    });
    
    const url = `https://direct.tranzila.com/${this.TERMINAL_NAME}/iframenew.php?${params}`;
    this.iframeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(url);
  }
  
  ngOnInit(): void {
    // Load jQuery
    this.loadScript('https://code.jquery.com/jquery-3.6.0.js', () => {
      // Load Tranzila Apple Pay script after jQuery
      const script = document.createElement('script');
      script.innerHTML = `document.write('<script src="https://directng.tranzila.com/assets/js/tranzilanapple_v3.js?v=' + Date.now() + '"><\\/script>');`;
      document.body.appendChild(script);
      
      // Set jQuery noConflict
      const noConflict = document.createElement('script');
      noConflict.innerHTML = 'var $n = jQuery.noConflict(true);';
      document.body.appendChild(noConflict);
    });
  }
  
  ngOnDestroy(): void {
    // Remove scripts on component destroy
    const scripts = document.querySelectorAll('script[src*="jquery"], script[src*="tranzilanapple"]');
    scripts.forEach(script => script.remove());
  }
  
  private loadScript(src: string, callback?: () => void): void {
    const script = document.createElement('script');
    script.src = src;
    script.async = true;
    if (callback) {
      script.onload = callback;
    }
    document.body.appendChild(script);
  }
}

Using POST Method

TypeScript
// payment-post.component.ts
import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';

@Component({
  selector: 'app-payment-post',
  template: `
    <div class="payment-container">
      <h1>Complete Your Payment</h1>
      
      <form #paymentForm
            [action]="formAction"
            method="POST"
            target="payment-iframe"
            style="display: none">
        
        <input type="hidden" name="sum" [value]="paymentData.sum">
        <input type="hidden" name="currency" [value]="paymentData.currency">
        <input type="hidden" name="apple_pay" value="1">
        <input type="hidden" name="lang" [value]="paymentData.lang">
        <input type="hidden" name="success_url_address" [value]="paymentData.success_url_address">
        <input type="hidden" name="fail_url_address" [value]="paymentData.fail_url_address">
        <input type="hidden" name="contact" [value]="paymentData.contact">
        <input type="hidden" name="company" [value]="paymentData.company">
        <input type="hidden" name="pdesc" [value]="paymentData.pdesc">
      </form>
      
      <iframe name="payment-iframe"
              width="100%"
              height="600"
              frameborder="0"
              allowpaymentrequest="true"
              title="Payment Form">
      </iframe>
    </div>
  `,
  styleUrls: ['./payment.component.css']
})
export class PaymentPostComponent implements OnInit, AfterViewInit {
  @ViewChild('paymentForm') paymentForm!: ElementRef<HTMLFormElement>;
  
  // Configuration
  private readonly TERMINAL_NAME = 'your-terminal';
  formAction: string;
  
  paymentData = {
    sum: '100',
    currency: '1', // 1=ILS, 2=USD, 978=EUR
    lang: 'en',
    success_url_address: window.location.origin + '/success',
    fail_url_address: window.location.origin + '/failure',
    contact: 'customer@example.com',
    company: 'John Doe',
    pdesc: 'Premium Package'
  };
  
  constructor(private sanitizer: DomSanitizer) {
    this.formAction = `https://direct.tranzila.com/${this.TERMINAL_NAME}/iframenew.php`;
  }
  
  ngOnInit(): void {
    // Load jQuery
    this.loadScript('https://code.jquery.com/jquery-3.6.0.js', () => {
      // Load Tranzila Apple Pay script after jQuery
      const script = document.createElement('script');
      script.innerHTML = `document.write('<script src="https://directng.tranzila.com/assets/js/tranzilanapple_v3.js?v=' + Date.now() + '"><\\/script>');`;
      document.body.appendChild(script);
      
      // Set jQuery noConflict
      const noConflict = document.createElement('script');
      noConflict.innerHTML = 'var $n = jQuery.noConflict(true);';
      document.body.appendChild(noConflict);
    });
  }
  
  ngAfterViewInit(): void {
    // Submit form after view initialization
    setTimeout(() => {
      if (this.paymentForm && this.paymentForm.nativeElement) {
        this.paymentForm.nativeElement.submit();
      }
    }, 500);
  }
  
  private loadScript(src: string, callback?: () => void): void {
    const script = document.createElement('script');
    script.src = src;
    script.async = true;
    if (callback) {
      script.onload = callback;
    }
    document.body.appendChild(script);
  }
}
HTML
<!-- payment.component.html -->
<div class="payment-container">
  <h1>Complete Your Payment</h1>
  
  <iframe
    [src]="iframeUrl"
    width="100%"
    height="600"
    frameborder="0"
    allowpaymentrequest="true"
    title="Payment Form">
  </iframe>
</div>
CSS
/* payment.component.css */
.payment-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
  background: white;
  border-radius: 10px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.payment-container h1 {
  color: #333;
  margin-bottom: 30px;
  font-size: 24px;
}

.payment-container iframe {
  border: none;
  border-radius: 8px;
}
TypeScript
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PaymentComponent } from './payment/payment.component';
import { SuccessComponent } from './success/success.component';
import { FailureComponent } from './failure/failure.component';

const routes: Routes = [
  { path: 'checkout', component: PaymentComponent },
  { path: 'success', component: SuccessComponent },
  { path: 'failure', component: FailureComponent },
  { path: '', redirectTo: '/checkout', pathMatch: 'full' }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
TypeScript
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PaymentComponent } from './payment/payment.component';
import { SuccessComponent } from './success/success.component';
import { FailureComponent } from './failure/failure.component';

@NgModule({
  declarations: [
    AppComponent,
    PaymentComponent,
    SuccessComponent,
    FailureComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Security and Compliance

PCI-DSS Compliance

The iframe implementation maintains full PCI-DSS compliance:

  • Credit card details are never processed on your domain
  • All sensitive data is handled securely within Tranzila's certified environment
  • Your website does not need PCI-DSS certification when using the iframe solution

SSL Certificate Requirements

  • Type: Valid SSL certificate (DV, OV, or EV)
  • Validation: Certificate must be properly installed and configured
  • Protocol: HTTPS is mandatory for both the parent page and domain verification

Testing

Production-Only Testing

Important: There is no sandbox or testing environment for Apple Pay integration. All testing must be performed in production after completing the integration.

Testing guidelines:

  1. Complete all implementation steps including domain verification
  2. Ensure Tranzila support has confirmed your domain registration
  3. Test with small amounts initially
  4. Verify successful transactions in your Tranzila dashboard

API Reference

Iframe Parameters

The following table lists the essential parameters for Apple Pay integration. For a complete list of all available iframe parameters, refer to the full iframe parameters documentation.

ParameterTypeRequiredDescription
sumdecimalYesTransaction amount
currencyintegerYesCurrency code: 1=ILS, 2=USD, 978=EUR
apple_payintegerYesEnable Apple Pay: 1=enabled
langstringNoInterface language: il=Hebrew, us=English
success_url_addressstringYesRedirect URL for successful transactions
fail_url_addressstringYesRedirect URL for failed transactions
contactstringNoCustomer email address
companystringNoCustomer name
pdescstringNoProduct or service description
tranmodestringNoTransaction mode: A=Standard, V=Verification

How It Works

  1. Automatic Detection: The Tranzila iframe automatically detects if Apple Pay is available on the user's device
  2. Button Display: If available, an Apple Pay button appears within the payment form inside the iframe
  3. User Interaction: The customer clicks the Apple Pay button and authenticates the payment on their device
  4. Session Management: The Tranzila script automatically handles the entire Apple Pay session
  5. Token Processing: Payment tokens are automatically processed without any merchant intervention
  6. Transaction Completion: After successful payment, users are redirected to success URL; on failure, to failure URL
  7. Notification: A server-side notification (NOTIFY) is also sent to your configured endpoint

Note: The payment process is initiated only when the customer clicks the Apple Pay button within the iframe. The parent page simply waits for the redirect after transaction completion.

Troubleshooting

Domain Verification Issues

Symptom

Apple Pay option does not appear in the iframe despite proper implementation.

Resolution

  1. Verify file accessibility:
Shell
curl -I https://your-domain.com/.well-known/apple-developer-merchantid-domain-association

Expected response: HTTP 200 OK

  1. Confirm HTTPS configuration:
Shell
openssl s_client -connect your-domain.com:443 -servername your-domain.com
  1. Validate file is served without extension and with correct MIME type:
  • Apache .htaccess:
APACHE
<Files "apple-developer-merchantid-domain-association">
    ForceType application/octet-stream
</Files>
  • Nginx configuration:
NGINX
location = /.well-known/apple-developer-merchantid-domain-association {
    default_type application/octet-stream;
}
  1. Contact Tranzila support to confirm domain registration completion

Script Loading Issues

Symptom

Console errors related to script loading.

Resolution

  1. Verify the script URL is accessible:
Shell
curl -I https://directng.tranzila.com/assets/js/tranzilanapple_v3.js
  1. Ensure no Content Security Policy blocks the script:
HTML
<meta http-equiv="Content-Security-Policy" 
      content="script-src 'self' https://direct.tranzila.com;">
  1. Confirm the script is loaded before the iframe:
JavaScript
// Ensure script loads first
const script = document.createElement('script');
script.src = 'https://directng.tranzila.com/assets/js/tranzilanapple_v3.js';
script.onload = () => {
    // Now safe to create iframe
    createPaymentIframe();
};
document.body.appendChild(script);

Apple Pay Not Appearing

Symptom

Apple Pay button does not appear in the iframe on supported devices.

Possible Causes and Solutions

  1. Browser Compatibility: Ensure using a supported browser (Safari, Chrome 78+, Edge 79+, Firefox 119+, Opera)
  2. Missing apple_pay Parameter: Ensure apple_pay=1 is included in iframe URL
  3. Terminal Not Configured: Contact Tranzila to verify Apple Pay is enabled for your terminal
  4. Device Not Supported: Verify device has Touch ID/Face ID capability
  5. No Cards in Wallet: User must have at least one card added to Apple Wallet

CORS or Security Errors

Symptom

Browser console shows CORS or security-related errors.

Resolution

Ensure the iframe includes the allowpaymentrequest attribute:

HTML
<iframe allowpaymentrequest="true" ...>

Important Notes

Security Considerations

  1. HTTPS Required: Both your domain and the page containing the iframe must use HTTPS
  2. Domain Verification: The verification file must remain accessible at all times
  3. No Additional Code: Do not attempt to manipulate or communicate with the iframe - all handling is automatic

Browser Compatibility

Apple Pay through iframe is supported on:

Mac:

  • Safari (all versions with Apple Pay support)
  • Chrome (version 78+)
  • Edge (version 79+)
  • Firefox (version 119+)
  • Opera

iOS devices (iPhone/iPad):

  • Safari
  • Chrome
  • Edge
  • Firefox
  • All other major browsers (all iOS browsers use WebKit engine)

Transaction Processing

  • Apple Pay transactions appear in Tranzila dashboard like regular credit card transactions
  • The last 4 digits shown are the Device Account Number, not the actual card number
  • Apple Pay tokens can be used for refunds (credits) and transaction cancellations, but cannot be used for new recurring payments
  • Supported Transaction Modes: Apple Pay only supports transaction modes A (Standard Transaction) and V (Verification/J5). Other transaction types such as pre-authorization or token creation are not supported

API Charging After J5 Verification

If you performed a J5 verification (tranmode=V) through Apple Pay in the iframe, you can charge the transaction later via API:

Step 1: J5 Verification (Done via iframe with Apple Pay)

The verification reserves the credit limit and returns:

  • Transaction ID
  • Authorization number
  • Token

Step 2: Force Charge via API

To obtain API credentials, contact Tranzila support at 073-222-4444.

For complete authentication documentation, see Tranzila API Authentication Guide.

JSON
POST https://api.tranzila.com/v1/transaction/credit_card/create

Headers:
Content-Type: application/json
X-tranzila-api-app-key: [your-app-key]
X-tranzila-api-request-time: [unix-timestamp]
X-tranzila-api-nonce: [40-byte-nonce]
X-tranzila-api-access-token: [hmac-hash]

Body:
{
  "terminal_name": "your-terminal",
  "txn_currency_code": "ILS",
  "txn_type": "force",
  "reference_txn_id": 148,  // Transaction ID from J5 verification
  "authorization_number": "0000393",  // Auth number from J5 verification
  "card_number": "token-from-verification",  // Token received from verification
  "expire_month": 3,
  "expire_year": 24,
  "payment_plan": 1,
  "items": [
    {
      "name": "Product",
      "unit_price": 100,
      "type": "I",
      "units_number": 1,
      "unit_type": 1,
      "price_type": "G",
      "currency_code": "ILS"
    }
  ]
}

Important: The force charge (J4) must include:

  • reference_txn_id: The transaction ID from the J5 verification
  • authorization_number: The authorization number from the J5 verification
  • card_number: The token received from the verification

For complete API documentation, see Tranzila API Documentation

Support

For technical assistance, contact Tranzila support:


Documentation Version: 3.0 | Last Updated: January 2026

Was this page helpful?