Completed
Pull Request — master (#10)
by Chad
05:48
created

Service::getHtml()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 4
nop 2
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
    private $_client;
26
    private $_pubkey;
27
    private $_privkey;
28
    private $_hashkey;
29
30
    /**
31
     * Construct a Service object with the required api key values.
32
     *
33
     * @param ClientInterface $client The guzzle client to send the requests over.
34
     * @param string $pubkey A public key for solvemedia
35
     * @param string $privkey A private key for solvemedia
36
     * @param string $hashkey An optional hash key for verification
37
     * @throws Exception
38
     */
39
    public function __construct(ClientInterface $client, $pubkey, $privkey, $hashkey = '')
40
    {
41
        if (empty($pubkey) || empty($privkey)) {
42
            throw new Exception('To use solvemedia you must get an API key from ' . self::ADCOPY_SIGNUP);
43
        }
44
45
        $this->_client = $client;
46
        $this->_pubkey = $pubkey;
47
        $this->_privkey = $privkey;
48
        $this->_hashkey = $hashkey;
49
    }
50
51
    /**
52
     * Gets the challenge HTML (javascript and non-javascript version).
53
     * This is called from the browser, and the resulting solvemedia HTML widget
54
     * is embedded within the HTML form it was called from.
55
     *
56
     * @param string $error The error given by solvemedia (optional, default is null)
57
     * @param boolean $useSsl Should the request be made over ssl? (optional, default is false)
58
     * @return string The HTML to be embedded in the user's form.
59
     */
60
    public function getHtml($error = null, $useSsl = false)
61
    {
62
        $server = $useSsl ? self::ADCOPY_API_SECURE_SERVER : self::ADCOPY_API_SERVER;
63
        $errorpart = $error ? ';error=1' : '';
64
65
        return <<<EOS
66
<script type="text/javascript" src="{$server}/papi/challenge.script?k={$this->_pubkey}{$errorpart}"></script>
67
<noscript>
68
    <iframe src="{$server}/papi/challenge.noscript?k={$this->_pubkey}{$errorpart}" height="300" width="500" frameborder="0"></iframe><br/>
69
    <textarea name="adcopy_challenge" rows="3" cols="40"></textarea>
70
    <input type="hidden" name="adcopy_response" value="manual_challenge"/>
71
</noscript>
72
EOS;
73
    }
74
75
    /**
76
     * Calls an HTTP POST function to verify if the user's guess was correct
77
     *
78
     * @param string $remoteip
79
     * @param string $challenge
80
     * @param string $response
81
     * @throws Exception
82
     * @return TraderInteractive\SolveMedia\Response
83
     */
84
    public function checkAnswer($remoteip, $challenge, $response)
85
    {
86
        if (empty($remoteip)) {
87
            throw new Exception('For security reasons, you must pass the remote ip to solvemedia');
88
        }
89
90
        //discard spam submissions
91
        if (empty($challenge) || empty($response)) {
92
            return new Response(false, 'incorrect-solution');
93
        }
94
95
        $httpResponse = $this->_client->request(
96
            'POST',
97
            self::ADCOPY_VERIFY_SERVER,
98
            [
99
                'headers' => ['User-Agent' => 'solvemedia/PHP'],
100
                'form_params' => [
101
                    'privatekey' => $this->_privkey,
102
                    'remoteip' => $remoteip,
103
                    'challenge' => $challenge,
104
                    'response' => $response,
105
                ],
106
            ]
107
        );
108
109
        if ($httpResponse->getStatusCode() !== 200) {
110
            return new Response(false, $httpResponse->getReasonPhrase());
111
        }
112
113
        $answers = explode("\n", (string)$httpResponse->getBody());
114
115
        if (!empty($this->_hashkey)) {
116
            // validate message authenticator
117
            $hash = sha1($answers[0] . $challenge . $this->_hashkey);
118
119
            if ($hash !== $answers[2]) {
120
                return new Response(false, 'hash-fail');
121
            }
122
        }
123
124
        if (trim($answers[0]) !== 'true') {
125
            return new Response(false, $answers[1]);
126
        }
127
128
        return new Response(true);
129
    }
130
131
    /**
132
     * Gets a URL where the user can sign up for solvemedia. If your application
133
     * has a configuration page where you enter a key, you should provide a link
134
     * using this function.
135
     *
136
     * @param string $domain The domain where the page is hosted
137
     * @param string $appname The name of your application
138
     * @return string url for signup page
139
     */
140
    public function getSignupUrl($domain = null, $appname = null)
141
    {
142
        return self::ADCOPY_SIGNUP . '?' . http_build_query(['domain' => $domain, 'app' => $appname]);
143
    }
144
}
145