0

I'm writing an extension that utilizes web services and I need a way for those web services to send information back to the extension over the internet.

Would I just use a controller like every other action? The URL would have to be fully public (no admin key in URL). Or would I trigger an event via an observer. I couldn't find an observer event that waits for the callback URL to be hit.

So far I've tried creating a folder with a file inside (myCompany/myModule/Notify/Notifications.php).

<?php
//Notifications.php
namespace myCompany\myModule\Notify;

class Notifications
{
    /**
    * Constructor
    */
    public function __construct(
        \myCompany\myModule\Api\Data\EntityInterface $entityModel
    ) {
        file_put_contents('/home/username/Desktop/test/log.txt', 'endpoint' . "\n", FILE_APPEND);
        $this->_entityModel = $entityModel;
    }
} 

Then I tried going to http://myMagento.com/myCompany/myModule/notify/notifications.php and my test doesn't print out.

As an example, here's how it's done in Drupal 8.

myCompany.notify:
  path: '/myCompany/notify'
  defaults:
    _controller: '\Drupal\myCompany\Controller\NotificationController::endpoint'
    _title: 'Notification Receiver'
  requirements:
    _access: 'TRUE'
0

Observers don't work like that due to the synchronous ways of how PHP works.

In your situation the main question is: how sensitive is the information? There is nothing wrong with having a publicly accessible URL for a 'behind the scenes' callback of some sort. But I would advise that you use some unique parameter that you can check your response against so you can still prevent someone from 'faking' the response from the 3rd party web service.

Now I don't know if your in control on the web service you're trying to connect to, but most PSP's work in a similar way. They have a secret key on the server, and use that to send a unique hash in the URL. Identically, the secret key is sent back in the response. An example:

  • Magento wants to let server X know that foo=42.
  • On the server, there is a secret key. It's value is ABC.
  • Magento creates a hash using the secret key and the value. Let's say: md_whatever('ABC' . '42') = 'qr92mc'. The request to server X could now for example be: http://serverx.org/?foo=42&hash=qr92mc.
  • Server X knows that foo is 42, and it also knows the secret key, so it can re-calculate the hash. If the hash matches, server X knows that the request is legit.
  • Now it's time for server X to send a response to your server, also using the secret key. Let's say server X created a transaction ID (100) and has a status (success). It now creates a new hash: md_whatever('ABC' . '100' . 'success') = 'f20mca'. The request back to Magento will be http://magento.org/?id=100&status=success&hash=f20mca.
  • The Magento store has the parameters and can recalculate the hash to determine if the response from server X is valid.

Note that in this example both parties use a secret key, but only communicate a hash to each other that needs to be revalidated. This way, it's very hard (note: not impossible, depends on how you create your hashes, but that's another story that involves decrypting) for somebody else to fake the response or the request.

For example, if I try to fool Magento by saying that my status is not complete, but pending I could edit the URL like so: http://magento.org/?id=100&status=pending&hash=f20mca. However, when Magento will recalculate the hash, it will find out that the hash of md_whatever('ABC' . '100' . 'pending') will not equal the hash that is sent (f20mca).

I hope this answer is helpful for you.

2
  • Thanks Giel Berkers for your answer. I'm actually using OAuth 2 tokens to make API calls to the web service, which I own as well. However the crux of my question is that I just don't know how to make a public endpoint in Magento 2. I'm familiar with Drupal 7, and I'm trying to do something similiar. – Joseph Hovik Mar 7 '17 at 19:12
  • Then once the endpoint is hit, I want to run some code. So far I've only made adminhtml controllers, and I'm wondering how to make a controller that fires regardless of if an admin user is logged into Magento. – Joseph Hovik Mar 7 '17 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.