How to Override Apple Pay Domain Association Controller in Magento 2

Introduction
If you're implementing Apple Pay on your Magento 2 store, you'll need to serve the apple-developer-merchantid-domain-association file from the .well-known directory. While Magento's Payment Services PayPal module handles this automatically, you might need to customize the content without modifying the database or vendor files.
In this comprehensive guide, I'll show you how to override the controller using Magento's dependency injection system in a clean, maintainable way.
The Challenge
The Magento Payment Services PayPal module serves the domain association file through a controller that reads content from the database configuration. However, there are several reasons you might want to override this:
No database modifications: Keep your configuration clean
Version control: Track changes in your code repository
Easy updates: Simple file-based management
No vendor edits: Survives module updates
Solution Overview
We'll create a custom module that overrides the domain association controller to serve content from a static file instead of the database.
Directory Structure
app/code/
└── Company/
└── AppleDomain/
├── etc/
│ ├── module.xml
│ └── di.xml
├── Controller/
│ └── Index/
│ └── DomainAssociation.php
├── etc/
│ └── apple-developer-merchantid-domain-association
└── registration.php
Step-by-Step Implementation
Step 1: Create the Module Structure
First, create the necessary directories:
# Navigate to your Magento root directory
cd /path/to/your/magento
# Create the module directory structure
mkdir -p app/code/Company/AppleDomain/{etc,Controller/Index}
Step 2: Create the Registration File
Create app/code/Company/AppleDomain/registration.php:
<?php
/**
* Copyright © Company, Inc. All rights reserved.
*/
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Company_AppleDomain',
__DIR__
);
Step 3: Define the Module
Create app/code/Company/AppleDomain/etc/module.xml:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Company_AppleDomain" setup_version="1.0.0">
<sequence>
<module name="Magento_PaymentServicesPaypal"/>
</sequence>
</module>
</config>
Step 4: Configure Dependency Injection
Create app/code/Company/AppleDomain/etc/di.xml:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference
for="Magento\PaymentServicesPaypal\Controller\Index\DomainAssociation"
type="Company\AppleDomain\Controller\Index\DomainAssociation" />
</config>
Step 5: Create the Custom Controller
Create app/code/Company/AppleDomain/Controller/Index/DomainAssociation.php:
<?php
/**
* Copyright © Company, Inc. All rights reserved.
*/
namespace Company\AppleDomain\Controller\Index;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Filesystem\Driver\File;
use Magento\Framework\Exception\NotFoundException;
/**
* Custom controller for serving Apple Pay domain association file
*/
class DomainAssociation implements HttpGetActionInterface
{
/**
* @var ResultFactory
*/
private $resultFactory;
/**
* @var File
*/
private $fileDriver;
/**
* Custom domain association file path
*/
private const CUSTOM_DOMAIN_ASSOCIATION_FILE = 'app/code/Company/AppleDomain/etc/apple-developer-merchantid-domain-association';
/**
* @param ResultFactory $resultFactory
* @param File $fileDriver
*/
public function __construct(
ResultFactory $resultFactory,
File $fileDriver
) {
$this->resultFactory = $resultFactory;
$this->fileDriver = $fileDriver;
}
/**
* Serve custom domain association file
*
* @return ResultInterface
* @throws NotFoundException
*/
public function execute()
{
$content = $this->getCustomDomainAssociationContent();
if (empty($content)) {
throw new NotFoundException(__('Domain association file not found.'));
}
$result = $this->resultFactory->create(ResultFactory::TYPE_RAW);
$result->setHeader('Content-Type', 'text/plain');
$result->setContents($content);
return $result;
}
/**
* Get custom domain association content from file
*
* @return string
*/
private function getCustomDomainAssociationContent(): string
{
try {
$filePath = BP . '/' . self::CUSTOM_DOMAIN_ASSOCIATION_FILE;
if ($this->fileDriver->isExists($filePath)) {
return $this->fileDriver->fileGetContents($filePath);
}
return '';
} catch (\Exception $e) {
return '';
}
}
}
Step 6: Add Your Domain Association File
Create app/code/Company/AppleDomain/etc/apple-developer-merchantid-domain-association and add your content:
-----BEGIN MERCHANT ID-----
Your actual Apple domain association content goes here
This is provided by Apple Merchant Center
Typically starts with -----BEGIN MERCHANT ID-----
-----END MERCHANT ID-----
Step 7: Enable and Test the Module
Run the following commands to enable your module:
# Enable the module
bin/magento module:enable Company_AppleDomain
# Run setup upgrade
bin/magento setup:upgrade
# Clean cache
bin/magento cache:clean
bin/magento cache:flush
# Deploy static content (if needed)
bin/magento setup:static-content:deploy
Step 8: Verify the Implementation
Test that your custom domain association file is being served:
# Test the endpoint
curl -s https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association
# Check HTTP status
curl -I https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association
How It Works
The Magic of Dependency Injection
When Magento receives a request to /.well-known/apple-developer-merchantid-domain-association, here's what happens:
Request Routing: Magento's router identifies the request pattern
Dependency Injection: Our
di.xmlpreference tells Magento to use our custom controller instead of the originalCustom Controller: Our controller reads the content from the static file
Response: Returns the content with proper headers
Troubleshooting Common Issues
Module Not Working?
# Check if module is enabled
bin/magento module:status Company_AppleDomain
# Check for compilation issues
bin/magento setup:di:compile
# Verify file permissions
chmod 644 app/code/Company/AppleDomain/etc/apple-developer-merchantid-domain-association
Conclusion
Overriding the Apple Pay domain association controller in Magento 2 is a clean, maintainable solution that follows Magento best practices. By using dependency injection and custom controllers, you gain full control over the content while maintaining the integrity of your Magento installation.
This approach demonstrates the power of Magento's modular architecture and provides a pattern you can use for other controller overrides in your projects.
Happy coding!
Need help with your Magento project? Feel free to reach out in the comments below or contact me directly for consulting services.


