Completed
Push — master ( 7a6150...2f2994 )
by Chad
10s
created

Service   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

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

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 3
A getHtml() 0 14 3
C checkAnswer() 0 46 8
A getSignupUrl() 0 4 1
1
<?php
2
/**
3
 * TraderInteractive\SolveMedia\Service class for accessing the Solve Media API service.
4
 * This component has been heavily modified from it's original form to
5
 * encapsulate the functionality in a class based structure that is
6
 * compatible with class autoloading functionality.
7
 *
8
 * @author Chris Ryan <[email protected]>
9
 */
10
namespace TraderInteractive\SolveMedia;
11
12
use Exception;
13
use GuzzleHttp\ClientInterface;
14
15
final class Service
16
{
17
    /**
18
     * The solvemedia server URL's
19
     */
20
    const ADCOPY_API_SERVER = 'http://api.solvemedia.com';
21
    const ADCOPY_API_SECURE_SERVER = 'https://api-secure.solvemedia.com';
22
    const ADCOPY_VERIFY_SERVER = 'http://verify.solvemedia.com/papi/verify';
23
    const ADCOPY_SIGNUP = 'http://api.solvemedia.com/public/signup';
24
25
    /**
26
     * @var ClientInterface
27
     */
28
    private $_client;
29
30
    /**
31
     * @var string
32
     */
33
    private $_pubkey;
34
35
    /**
36
     * @var string
37
     */
38
    private $_privkey;
39
40
    /**
41
     * @var string
42
     */
43
    private $_hashkey;
44
45
    /**
46
     * Construct a Service object with the required api key values.
47
     *
48
     * @param ClientInterface $client The guzzle client to send the requests over.
49
     * @param string $pubkey A public key for solvemedia
50
     * @param string $privkey A private key for solvemedia
51
     * @param string $hashkey An optional hash key for verification
52
     * @throws Exception
53
     */
54
    public function __construct(ClientInterface $client, string $pubkey, string $privkey, string $hashkey = '')
55
    {
56
        if (empty($pubkey) || empty($privkey)) {
57
            throw new Exception('To use solvemedia you must get an API key from ' . self::ADCOPY_SIGNUP);
58
        }
59
60
        $this->_client = $client;
61
        $this->_pubkey = $pubkey;
62
        $this->_privkey = $privkey;
63
        $this->_hashkey = $hashkey;
64
    }
65
66
    /**
67
     * Gets the challenge HTML (javascript and non-javascript version).
68
     * This is called from the browser, and the resulting solvemedia HTML widget
69
     * is embedded within the HTML form it was called from.
70
     *
71
     * @param string $error The error given by solvemedia (optional, default is null)
72
     * @param boolean $useSsl Should the request be made over ssl? (optional, default is false)
73
     * @return string The HTML to be embedded in the user's form.
74
     */
75
    public function getHtml(string $error = null, bool $useSsl = false) : string
76
    {
77
        $server = $useSsl ? self::ADCOPY_API_SECURE_SERVER : self::ADCOPY_API_SERVER;
78
        $errorpart = $error ? ';error=1' : '';
79
80
        return <<<EOS
81
<script type="text/javascript" src="{$server}/papi/challenge.script?k={$this->_pubkey}{$errorpart}"></script>
82
<noscript>
83
    <iframe src="{$server}/papi/challenge.noscript?k={$this->_pubkey}{$errorpart}" height="300" width="500" frameborder="0"></iframe><br/>
84
    <textarea name="adcopy_challenge" rows="3" cols="40"></textarea>
85
    <input type="hidden" name="adcopy_response" value="manual_challenge"/>
86
</noscript>
87
EOS;
88
    }
89
90
    /**
91
     * Calls an HTTP POST function to verify if the user's guess was correct
92
     *
93
     * @param string $remoteip
94
     * @param string $challenge
95
     * @param string $response
96
     * @throws Exception
97
     * @return Response
98
     */
99
    public function checkAnswer(string $remoteip, string $challenge = null, string $response = null) : Response
100
    {
101
        if (empty($remoteip)) {
102
            throw new Exception('For security reasons, you must pass the remote ip to solvemedia');
103
        }
104
105
        //discard spam submissions
106
        if (empty($challenge) || empty($response)) {
107
            return new Response(false, 'incorrect-solution');
108
        }
109
110
        $httpResponse = $this->_client->request(
111
            'POST',
112
            self::ADCOPY_VERIFY_SERVER,
113
            [
114
                'headers' => ['User-Agent' => 'solvemedia/PHP'],
115
                'form_params' => [
116
                    'privatekey' => $this->_privkey,
117
                    'remoteip' => $remoteip,
118
                    'challenge' => $challenge,
119
                    'response' => $response,
120
                ],
121
            ]
122
        );
123
124
        if ($httpResponse->getStatusCode() !== 200) {
125
            return new Response(false, $httpResponse->getReasonPhrase());
126
        }
127
128
        $answers = explode("\n", (string)$httpResponse->getBody());
129
130
        if (!empty($this->_hashkey)) {
131
            // validate message authenticator
132
            $hash = sha1($answers[0] . $challenge . $this->_hashkey);
133
134
            if ($hash !== $answers[2]) {
135
                return new Response(false, 'hash-fail');
136
            }
137
        }
138
139
        if (trim($answers[0]) !== 'true') {
140
            return new Response(false, $answers[1]);
141
        }
142
143
        return new Response(true);
144
    }
145
146
    /**
147
     * Gets a URL where the user can sign up for solvemedia. If your application
148
     * has a configuration page where you enter a key, you should provide a link
149
     * using this function.
150
     *
151
     * @param string $domain The domain where the page is hosted
152
     * @param string $appname The name of your application
153
     * @return string url for signup page
154
     */
155
    public function getSignupUrl(string $domain = null, string $appname = null) : string
156
    {
157
        return self::ADCOPY_SIGNUP . '?' . http_build_query(['domain' => $domain, 'app' => $appname]);
158
    }
159
}
160