Completed
Push — master ( aef9cc...ce2dfd )
by John
01:25
created

AuthnetWebhook   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 2
dl 0
loc 122
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 15 5
A __toString() 0 16 1
A __get() 0 4 1
A isValid() 0 5 2
A getRequestId() 0 4 2
A getAllHeaders() 0 15 4
1
<?php
2
3
/**
4
 * This file is part of the AuthnetJSON package.
5
 *
6
 * (c) John Conde <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace JohnConde\Authnet;
13
14
/**
15
 * Handles a Webhook notification from the Authorize.Net Webhooks API
16
 *
17
 * @package     AuthnetJSON
18
 * @author      John Conde <[email protected]>
19
 * @copyright   John Conde <[email protected]>
20
 * @license     http://www.apache.org/licenses/LICENSE-2.0.html Apache License, Version 2.0
21
 * @link        https://github.com/stymiee/authnetjson
22
 * @see         https://developer.authorize.net/api/reference/
23
 */
24
class AuthnetWebhook
25
{
26
    /**
27
     * @var     object  SimpleXML object representing the Webhook notification
28
     */
29
    private $webhook;
30
31
    /**
32
     * @var     string  JSON string that is the Webhook notification sent by Authorize.Net
33
     */
34
    private $webhookJson;
35
36
    /**
37
     * @var     array  HTTP headers sent with the notification
38
     */
39
    private $headers;
40
41
    /**
42
     * @var     string  Authorize.Net Signature Key
43
     */
44
    private $signature;
45
46
    /**
47
     * Creates the response object with the response json returned from the API call
48
     *
49
     * @param   string   $signature    Authorize.Net Signature Key
50
     * @param   string   $payload      Webhook Notification sent by Authorize.Net
51
     * @param   array    $headers      HTTP headers sent with the Webhook notification. Optional if PHP is run as an Apache module
52
     * @throws  \JohnConde\Authnet\AuthnetInvalidCredentialsException
53
     * @throws  \JohnConde\Authnet\AuthnetInvalidJsonException
54
     */
55
    public function __construct($signature, $payload, Array $headers = [])
56
    {
57
        $this->signature   = $signature;
58
        $this->webhookJson = $payload;
59
        $this->headers     = $headers;
60
        if (empty($this->headers) && function_exists('apache_request_headers')) {
61
            $this->headers = apache_request_headers();
62
        }
63
        if (empty($this->signature)) {
64
            throw new AuthnetInvalidCredentialsException('You have not configured your signature properly.');
65
        }
66
        if (($this->webhook = json_decode($this->webhookJson)) === null) {
67
            throw new AuthnetInvalidJsonException('Invalid JSON sent in the Webhook notification');
68
        }
69
    }
70
71
    /**
72
     * Outputs the response JSON in a human readable format
73
     *
74
     * @return  string  HTML table containing debugging information
75
     */
76
    public function __toString()
77
    {
78
        $output  = '';
79
        $output .= '<table summary="Authorize.Net Webhook" id="authnet-webhook">' . "\n";
80
        $output .= '<tr>' . "\n\t\t" . '<th colspan="2"><b>Response HTTP Headers</b></th>' . "\n" . '</tr>' . "\n";
81
        $output .= '<tr><td colspan="2"><pre>' . "\n";
82
        $output .= var_export($this->headers) . "\n";
83
        $output .= '</pre></td></tr>' . "\n";
84
        $output .= '<tr>' . "\n\t\t" . '<th colspan="2"><b>Response JSON</b></th>' . "\n" . '</tr>' . "\n";
85
        $output .= '<tr><td colspan="2"><pre>' . "\n";
86
        $output .= $this->webhookJson . "\n";
87
        $output .= '</pre></td></tr>' . "\n";
88
        $output .= '</table>';
89
90
        return $output;
91
    }
92
93
    /**
94
     * Gets a response variable from the Webhook notification
95
     *
96
     * @param   string  $var
97
     * @return  string          requested variable from the API call response
98
     */
99
    public function __get($var)
100
    {
101
        return $this->webhook->{$var};
102
    }
103
104
    /**
105
     * Validates a webhook signature to determine if the webhook is valid
106
     *
107
     * @return bool
108
     */
109
    public function isValid()
110
    {
111
        $hashedBody = strtoupper(hash_hmac('sha512', $this->webhookJson, $this->signature));
112
        return (isset($this->headers['X-ANET-Signature']) && strtoupper(explode('=', $this->headers['X-ANET-Signature'])[1]) === $hashedBody);
113
    }
114
115
    /**
116
     * Validates a webhook signature to determine if the webhook is valid
117
     *
118
     * @return string
119
     */
120
    public function getRequestId()
121
    {
122
        return (isset($this->headers['X-Request-Id'])) ? $this->headers['X-Request-Id'] : null;
123
    }
124
125
    /**
126
     * Retrieves all HTTP headers of a given request
127
     *
128
     * @return array
129
     */
130
    protected function getAllHeaders()
1 ignored issue
show
Coding Style introduced by
getAllHeaders uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
131
    {
132
        $headers = [];
133
        if (function_exists('apache_request_headers')) {
134
            $headers = apache_request_headers();
135
        }
136
        else {
137
            foreach ($_SERVER as $name => $value) {
138
                if (substr($name, 0, 5) == 'HTTP_') {
139
                    $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
140
                }
141
            }
142
        }
143
        return $headers;
144
    }
145
}