Completed
Push — whmcs-jetpack-partner-module ( 24f97f...6558f9 )
by
unknown
08:55
created

jetpack.php ➔ validate_required_fields()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 9
nop 1
dl 0
loc 30
rs 8.5066
c 0
b 0
f 0
1
<?php
2
3
use WHMCS\Database\Capsule;
4
5
6
if (!defined("WHMCS")) {
7
    die("This file cannot be accessed directly");
8
}
9
10
11
/**
12
 * A WHMCS module for use by Jetpack hosting partners to provision Jetpack plans.
13
 * The module provides functionality for partner hosts to be able to save their
14
 * client id and secret to request an access token for provisioning plans.
15
 *
16
 * Plans available for provisioning include free, personal, premium and professional
17
 *
18
 * A host has options to either provision(Create == WHMCS equivalent functional term)
19
 * or Cancel(Terminate == WHMCS equivalent functional term) from the WHMCS client area.
20
 *
21
 * Host setup for custom fields is currently required in order to use the module.
22
 *
23
 */
24
25
/**
26
 * Jetpack Meta Data for WHMCS module.
27
 * @return array
28
 */
29
function jetpack_MetaData()
30
{
31
    return array(
32
        'DisplayName' => 'Jetpack by Automattic',
33
        'Description' => 'Use this module to provision Jetpack plans with your Jetpack hosting partner account',
34
        'APIVersion' => '1.1',
35
        'RequiresServer' => false,
36
    );
37
}
38
39
40
/**
41
 * Basic configuration options required for a partner to get
42
 * a Jetpack plan provisioned. Currently a partner client id
43
 * and secret are the only host partner options needed to get
44
 * an access token to provision a Jetpack plan
45
 * @return array
46
 */
47
function jetpack_ConfigOptions()
48
{
49
    return array(
50
        'Jetpack Partner Client ID' => array(
51
            'Type' => 'text',
52
            'Size' => '256',
53
        ),
54
        'Jetpack Partner Client Secret' => array(
55
            'Type' => 'text',
56
            'Size' => '256',
57
        )
58
    );
59
}
60
61
62
/**
63
 * Equivalent to /provision. Create a Jetpack plan using
64
 * a Jetpack Hosting partner account.
65
 *
66
 *
67
 * @param array $params
68
 * @return string 'success'
69
 * @throws Exception
70
71
 */
72
function jetpack_CreateAccount(array $params)
73
{
74
    try {
75
        validate_required_fields($params);
76
77
        $access_token = get_access_token($params);
78
        $provisioning_url = "https://public-api.wordpress.com/rest/v1.3/jpphp/provision";
79
        $request_data = array (
80
            'plan' => strtolower($params['customfields']['Plan']),
81
            'siteurl' => $params['customfields']['Site URL'],
82
            'local_user' => $params['customfields']['Local User'],
83
            'force_register' => true,
84
        );
85
86
        $response = make_api_request($provisioning_url, $access_token, $request_data);
87
88
        if (isset($response->next_url)) {
89
            save_next_url($response->next_url, $params);
90
        }
91
92
        if ($response->success == true) {
93
            return 'success';
94
        }
95
    } catch(Exception $e) {
96
        logModuleCall('jetpack', __FUNCTION__, $params, $e->getMessage(), $e->getMessage());
97
        return $e->getMessage();
98
    }
99
100
}
101
102
/**
103
 * Equivalent to partner/cancel. Cancel a Jetpack plan using
104
 * using a Jetpack Hosting partner account.
105
 *
106
 * @param array $params
107
 * @return string
108
 * @throws Exception
109
 */
110
function jetpack_TerminateAccount(array $params)
111
{
112
    try {
113
        validate_required_fields($params);
114
115
        $access_token = get_access_token($params);
116
        $clean_url = str_replace('/', '::', $params['customfields']['Site URL']);
117
        $url = 'https://public-api.wordpress.com/rest/v1.3/jpphp/' . $clean_url .'/partner-cancel';
118
        $response = make_api_request($url, $access_token);
119
        if ($response->success == true) {
120
            return 'success';
121
        }
122
    }
123
    catch (Exception $e) {
124
        logModuleCall('jetpack', __FUNCTION__, $params, $e->getMessage(), $e->getMessage());
125
        return $e->getMessage();
126
    }
127
128
}
129
130
/**
131
 * Get a Jetpack partner access token using the client_id
132
 * and client secret stored when the product was created in
133
 * the WHMCS product settings.
134
 *
135
 *
136
 * @param $params
137
 * @return mixed
138
 * @throws Exception
139
 */
140
function get_access_token($params)
141
{
142
143
    $oauthURL = "https://public-api.wordpress.com/oauth2/token";
144
145
    $credentials = array (
146
        'client_id' => $params['configoption1'],
147
        'client_secret' => $params['configoption2'],
148
        'grant_type' => 'client_credentials',
149
        'scope' => 'jetpack-partner'
150
    );
151
152
    $response = make_api_request($oauthURL, null, $credentials);
153
    if (isset($response->access_token)) {
154
        return $response->access_token;
155
    } else {
156
        throw new Exception('There was an issue authorizing your partner account for provisioning. Please contact
157
        us for assistance');
158
    }
159
}
160
161
162
/**
163
 * Make an API request for authenticating and provisioning or
164
 * cancelling a Jetpack plan
165
 *
166
 * @param $url
167
 * @param $data
168
 * @param string $auth
169
 * @return mixed
170
 * @throws Exception
171
 */
172
function make_api_request($url, $auth='', $data=[])
173
{
174
    if (isset($auth)) {
175
        $auth = "Authorization: Bearer " . $auth;
176
    }
177
178
    $curl = curl_init();
179
    curl_setopt_array($curl, array(
180
        CURLOPT_HTTPHEADER => array($auth),
181
        CURLOPT_URL => $url,
182
        CURLOPT_RETURNTRANSFER => true,
183
        CURLOPT_ENCODING => "",
184
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
185
        CURLOPT_POSTFIELDS => $data,
186
        CURLOPT_CUSTOMREQUEST => "POST"
187
    ));
188
189
    $response = curl_exec($curl);
190
    $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
191
192
    if ($http_code >= 400) {
193
        logModuleCall('jetpack', __FUNCTION__, $url, $data, $response);
194
        throw new Exception('Something Went wrong');
195
    } else if (curl_error($curl)) {
196
        throw new Exception('Unable to connect: ' . curl_errno($curl) . ' - ' . curl_error($curl));
197
    } elseif (empty($response)) {
198
        throw new Exception('Empty response');
199
    }
200
201
    curl_close($curl);
202
    return json_decode($response);
203
}
204
205
/**
206
 * Save the next_url for Jetpack activation/setup to the
207
 * order for the client
208
 *
209
 * @param $url
210
 * @param $orderId
211
 */
212
function save_next_url($url, $params)
213
{
214
    $jetpack_next_url_field = Capsule::table('tblcustomfields')
215
        ->where(array('fieldname' => 'jetpack_provisioning_details', 'type' => 'product'))->first();
216
217
    Capsule::table('tblcustomfieldsvalues')->insert(array(
218
        'fieldid' => $jetpack_next_url_field->id, 'relid' => $params['model']['orderId'], 'value' => $url));
219
}
220
221
/**
222
 * Validate that the module was correctly set up when the product was
223
 * created by the WHMCS user and that the required Fields/Options for
224
 * being able to provision a Jetpack plan are present. Fields validated are
225
 *  - Allowed Plans from Plan Custom Field
226
 *  - Required Custom Fields
227
 *  - Required Config Options
228
 *
229
 * @param array $params
230
 * @return bool
231
 * @throws Exception
232
 */
233
function validate_required_fields(array $params)
234
{
235
    $allowed_plans = array('free', 'personal', 'premium', 'professional');
236
    $required_custom_fields = array('Plan', 'Site URL', 'Local User');
237
238
    foreach ($required_custom_fields as $field)
239
        if (!isset($params['customfields'][$field])) {
240
            throw new Exception('The module does not appear to be setup correctly. The required custom field '
241
            . $field . ' was not setup when the product was created. Please see the module documentation for more information');
242
        }
243
244
    $jetpack_next_url_field = Capsule::table('tblcustomfields')
245
        ->where(array('fieldname' => 'jetpack_provisioning_details', 'type' => 'product'))->first();
246
247
    if (!$jetpack_next_url_field) {
248
        throw new Exception('The module does not appear to be setup correctly. The jetpack_provisioning_details field is missing');
249
    }
250
251
    if (!in_array(strtolower($params['customfields']['Plan']), $allowed_plans)) {
252
        throw new Exception('The module does not appear to be setup correctly. ' .
253
            $params['customfields']['Plan'] . ' is not an allowed plan');
254
    }
255
256
    if (!isset($params['configoption1']) || !isset($params['configoption2'])) {
257
        throw new Exception('Your credentials for provisioning are not complete. Please see the module documentation
258
        for more information');
259
    }
260
261
    return true;
262
}
263
264