├── README.md
├── includes
└── hooks
│ └── namecheapssl_sync.php
└── modules
├── addons
└── namecheap_ssl
│ ├── client_templates
│ └── notice.tpl
│ ├── namecheap_ssl.php
│ └── templates
│ ├── default.php
│ ├── list.php
│ ├── log.php
│ ├── settings.php
│ └── sync.php
└── servers
└── namecheapssl
├── lang
└── English.php
├── namecheapapi.php
├── namecheaplog.php
├── namecheapssl.php
├── no_approver.tpl
├── reissue_notice.tpl
├── show_validation_file_contents.tpl
└── viewdetails.tpl
/README.md:
--------------------------------------------------------------------------------
1 | ## Namecheap.com WHMCS SSL Module
2 |
3 | #### Update for WHMCS Namecheap SSL Plugin Users:
4 |
5 | The latest version is stable and works seamlessly with WHMCS 6.x.x, 7.x.x, 8.x.x.
6 | Further development of the WHMCS Namecheap SSL Plugin has stopped because user uptake is low.
7 | If you experience any problems with plugin performance, [Contact Us](https://www.namecheap.com/support/live-chat/ssl/).
8 | You can also find more user info [Here](https://www.namecheap.com/support/knowledgebase/subcategory.aspx/2196/whmcs-module-for-ssl).
9 |
10 | ##### Updated on May 18 2018 to version 1.6.7
11 | - Security changes: escaped all variables in SQL queries and templates
12 | - Fixed bug with duplicate configuration email after addon reactivation
13 | - Fixed bug with revoke function
14 |
15 | ##### Updated on September 7, 2017, to version 1.6.6 for WHMCS 7.x
16 | - Minor fixes according to changes in API
17 | - mysql_ functions removed, support of MySQLi extension added
18 |
19 | ##### Updated on March 28, 2016 to version 1.6.5 for WHMCS 6.x
20 |
21 | - Fixed bug with approver emails for Symantec OV and EV certificates
22 | - Added notification about latin characters to the first certificate activation page
23 | - Job/Title set as an obligatory field for Symantec certificates
24 |
25 | ##### Updated on November, 27 2015 to Version 1.6.4 for WHMCS 6.x
26 |
27 | - Removed email and HTTP validation for Symantec OV and EV certificates
28 | - Added product due date synchronization offset in settings section of addon
29 | - Simplified domain validation choice for Symantec DV certificates reissue
30 |
31 | ##### Updated on December 15, 2014 to Version 1.6.2 for WHMCS 5.
32 | **Important information:** Previous versions of WHMCS SSL Module contained a bug that could potentially affect clients that resell Multi-domain SSL certificates using WHMCS module. Please check details of the bug and how it might have affected you in the following [knowledgebase article](https://www.namecheap.com/support/knowledgebase/article.aspx/9444/2196/whmcs-ssl-module-bug).
33 |
34 | This bug has been fixed in version 1.6.2
35 |
36 | Other changes:
37 |
38 | - Fixed default number of addon domains for Comodo EV Multi Domain SSL and Multi Domain SSL to 3.
39 | - Fixed approver email resending for GeoTrust DV certificates
40 | - Fixed Organization fields for Comodo EV Multi Domain SSL.
41 | - Fixed issues with Job Title field: Added Job Title to Module Settings and made it required field for Thawte, Symantec and EV GeoTrust certificates.
42 | - Added 15 seconds timeout was implemented for uploading certificate types.
43 | - Added “SourceOfCall” parameter to API calls to Namecheap.
44 |
45 | [Release Notes](https://github.com/namecheap/ssl-whmcs/wiki/Changelog)
46 |
47 | ##### Addon version vs Module version
48 |
49 | Module version is the version of whole current release while "Addon version" is the version of addon file itself.
50 | The version specified in addon settings is version of addon file:
51 |
52 | 
53 |
54 | In order to check the version of module please open /modules/servers/namecheapssl/namecheapssl.php file on your server:
55 |
56 | 
57 |
58 | ##### Before you begin
59 |
60 | Namecheap.com SSL module for WHMCS is an open-source plugin that is distributed free of charge. This module allows you to automate SSL Certificate sales with the Namecheap platform.
61 |
62 | **Important:**
63 |
64 | If you have not previously performed the WHMCS "Further Security Steps," please follow the instructions from the WHMCS documentation at http://docs.whmcs.com/Further_Security_Steps to change your WHMCS admin folder name or password-protect the admin directory. These steps mitigate the risk of external cron file abuse from outside your server.
65 |
66 |
67 | ##### Pre-requisites
68 |
69 | - Access to WHMCS admin area.
70 | - An understanding of [Namecheap’s environments](https://www.namecheap.com/support/api/intro.aspx).
71 | - Namecheap account with API access enabled on the desired environment.
72 |
73 | ##### List of supported SSL certificates:
74 |
75 | You will be allowed to resell all of our SSL products:
76 |
77 | **RapidSSL Cerificates:**
78 |
79 | - RapidSSL
80 | - RapidSSL Wildcard
81 |
82 | **GeoTrust Cerificates:**
83 |
84 | - GeoTrust QuickSSL
85 | - GeoTrust QuickSSL Premium
86 | - GeoTrust True BusinessID with EV
87 | - GeoTrust TrueBusinessID
88 | - GeoTrust TrueBusinessID WildCard
89 | - GeoTrust TrueBusinessID Multi Domain
90 | - GeoTrust TrueBusinessID with EV Multi Domain
91 |
92 | **Comodo Certificates:**
93 |
94 | - Comodo PositiveSSL
95 | - Comodo PositiveSSL Wildcard
96 | - Comodo InstantSSL
97 | - Comodo InstantSSL Pro
98 | - Comodo PremiumSSL
99 | - Comodo PremiumSSL Wildcard
100 | - Comodo EssentialSSL
101 | - Comodo EssentialSSL Wildcard
102 | - Comodo EV SSL
103 | - Comodo EV SGC SSL
104 | - Comodo Unified Communications
105 | - Comodo PositiveSSL Multi Domain
106 |
107 | **Symantec Certificates:**
108 |
109 | - Symantec Secure Site
110 | - Symantec Secure Site Pro
111 | - Symantec Secure Site EV
112 | - Symantec Secure Site Pro EV
113 |
114 | **Thawte Certificates:**
115 |
116 | - SSL 123
117 | - Web Server
118 | - Web Server EV
119 | - Supercert
120 |
121 | ***
122 | **Important Note:** You may find ComodoSSL in the list of SSLs during setting up products in WHMCS. ComodoSSL is a test product, it is included in the list of products, but it is not fully supported yet. Please do not set up ComodoSSL Products.
123 | ***
124 |
125 | ##### Sandbox and Production Environments
126 |
127 | Namecheap has a production as well as a test server environment. The test server environment is called Sandbox. We urge you to test the module in our [sandbox environment](http://www.sandbox.namecheap.com), before pointing it to production. It uses same calls as our production environment except that you will not receive actual SSL product in the end of the process and will not be charged real money. Difference between setting product for Sandbox and for production will be described in "Setting up products and pricings" section.
128 |
129 | #####List of certificates supported in Sandbox:
130 |
131 | All of our certificates are supported in sandbox:
132 |
133 | **RapidSSL Cerificates:**
134 |
135 | - RapidSSL
136 | - RapidSSL Wildcard
137 |
138 | **GeoTrust Cerificates:**
139 |
140 | - GeoTrust QuickSSL
141 | - GeoTrust QuickSSL Premium
142 | - GeoTrust True BusinessID with EV
143 | - GeoTrust TrueBusinessID
144 | - GeoTrust TrueBusinessID WildCard
145 | - GeoTrust TrueBusinessID Multi Domain
146 | - GeoTrust TrueBusinessID with EV Multi Domain
147 |
148 | **Symantec Certificates:**
149 |
150 | - Symantec Secure Site
151 | - Symantec Secure Site Pro
152 | - Symantec Secure Site EV
153 | - Symantec Secure Site Pro EV
154 |
155 | **Thawte Certificates:**
156 |
157 | - SSL 123
158 | - Web Server
159 | - Web Server EV
160 |
161 | **Comodo Certificates:**
162 |
163 | - Comodo PositiveSSL
164 | - Comodo PositiveSSL Wildcard
165 | - Comodo InstantSSL
166 | - Comodo InstantSSL Pro
167 | - Comodo PremiumSSL
168 | - Comodo PremiumSSL Wildcard
169 | - Comodo EssentialSSL
170 | - Comodo EssentialSSL Wildcard
171 | - Comodo Unified Communications
172 | - Comodo PositiveSSL Multi Domain
173 |
174 | ***
175 | **Important Note:** Please note that activation of Comodo OV and EV certificates will not lead to receiving test certificate itself, only DCV email will be sent.
176 | ***
177 |
178 | ##### Download and installation
179 |
180 | Installation of our SSLmodule is very simple and takes just a few minutes:
181 |
182 | 1. Download and extract attached archive. It can be downloaded here: https://github.com/namecheap/ssl-whmcs/archive/master.zip. Copy the contents to the root folder of whmcs (folder structure will remain the same).
183 |
184 | 2. Go to 'Setup >Addon Modules' in your WHMCS Admin area and activate the addon. Then go here:
185 |
186 | 
187 |
188 | The SSL Module Addon installation is now complete.
189 |
190 | ***
191 | **Important Note:**
192 | If you receive any errors or cannot access addon please set up access permissions to addon for everyone as on screenshot:
193 |
194 | 
195 | ***
196 |
197 | ##### Setting up products and pricings
198 |
199 | To setup an SSL certificate product, please follow the steps below:
200 |
201 | 1. Create a new product within your WHMCS.
202 |
203 | 2. Ensure the welcome email is set to "None" in the dropdown menu on the Details tab, as the module sends its own email.
204 |
205 | 3. In this version, the module billing cycles and SSL validity period are configured via standard WHMCS “Products/Services” settings. To access this, go to the Pricing tab and select Payment Type to Recurring. Now disable “One Time/Monthly”, “Quarterly” and “Semi-Annualy” billing cycles since they are not applicable to SSL Certificates. Finally, specify prices for remaining billing cycles. “Annually” corresponds to 1 year of SSL certificate validity (i.e. the SSL will be registered for 1 year). Biennially and triennially refer to 2 and 3 years respectively.
206 |
207 | 
208 |
209 | 4. On the Module Settings tab, choose "Namecheapssl" from Module Name dropdown menu.
210 |
211 | 5. Enter your API credentials. If you wish to test this module in sandbox environment, make sure to enter your sandbox username, sandbox API key in the corresponding text fields. Also, be sure to check the “Test Mode” box.
212 |
213 | 6. Choose the certificate type from the drop-down menu.
214 |
215 | 7. If you have a special “Promotion Code”, type it into the corresponding text field.
216 |
217 | 8. If “Use existing SSL from account” option is checked we will try to use an existing SSL certificate of this type from your Namecheap account first. If there is no SSL available that can be used, a new certificate will be purchased.
218 |
219 | 9. The purpose of the next set of fields is to customize the Technical Contact Details for any purchased SSL Certificates (fields are shown on a screens shot below). By default, Namecheap Contact details are used (email address sslsupport@namecheap.com). Using a custom Technical Contact Details is useful for resellers who wish to appear as an independent business entity to their customers. Depending on whether you want to use custom Technical Contact Details or not, perform the corresponding action:
220 |
221 | - In order to use Default Technical Email leave ALL of the fields below empty.
222 | - If you wish to use Custom Technical Email fill in ALL of the fields below.
223 |
224 | 
225 |
226 | Note: Our ability to provide support to customers who use custom Technical Contact Fields is limited. In case custom technical contact details are used, we cannot perform reissues, resending of approver email/ certificate, or cancellation/revocation of GeoTrust and Symantec SSL Certificates. However, since you possess control over technical contact, you can access GeoTrust/Symantec Live Account and perform these required actions yourself.
227 |
228 | For control of GeoTrust SSLs, please visit: https://products.geotrust.com/orders/orderinformation/authentication.do
229 |
230 | For control of Thawte SSLs, please visit: https://products.thawte.com/orders/orderinformation/authentication.do
231 |
232 | For control of Symantec SSLs, please visit: https://products.verisign.com/orders/orderinformation/authentication.do
233 |
234 | ##### Order Process
235 |
236 | The product will appear in the order process as a regular product which can be added to the cart. No configuration is performed before purchase. Once a certificate is purchased, paid for, and activated, the user is sent an email containing a link which takes them to configure the certificate in the client area. Once all details have been provided, the configuration data is sent to the Certificate Authority for validation. No manual intervention is required from you.
237 |
238 | You have an option to resend an email containing a link to the certificate configuration page to the client. This page is also accessible from the client area (My Products & Services -> Product Details -> View Certificate Details). Options to resend approver email and email with the certificate issued are also available in the client area.
239 |
240 | ##### Welcome/Configuration Email
241 |
242 | On its first launch, Namecheap SSL module automatically creates a configuration email template (see “SSL Certificate Configuration Required” in section "Product Messages" of Email Templates in Setup). It contains link to activation process inside your client area for a specific SSL certificate.
243 |
244 | Sending of SSL Configuration Email is controlled by the following parameters:
245 |
246 | Type of product setup behavior in Module Settings tab:
247 |
248 | 
249 |
250 | 1. Configuration email is always sent for options “Automatically setup the product as soon as an order is placed” and “Automatically setup the product as soon as the first payment is received”. If you select “Automatically setup the product as soon as an order is placed”, a configuration email will only be sent if the order is placed from the client area. The module itself will run only if you place the order from client area as well.
251 |
252 | 2. If the options “Automatically setup the product when you manually accept a pending order” or “Do not automatically setup this product” are selected, then sending of the Configuration Email will depend on the box “Send Welcome Email”:
253 |
254 | 
255 |
256 | You can modify content of the configuration email at any time.
257 |
258 | ##### Activation from WHMCS
259 |
260 | In order to activate a certificate purchased from you, your client needs to access list of your services and click on ‘View Details’ button next to ordered certificate.
261 |
262 | 
263 |
264 | After that your client needs to click ‘View certificate details’ and ‘Configure certificate’.
265 |
266 | He will see window with SSL activation fields:
267 |
268 | 
269 |
270 | At this stage your client needs to input CSR code (obtained from web-server), select web-server type and fill in valid admin contact info.
271 |
272 | Basically admin contact info is to be pre-filled from user's WHMCS profile.
273 |
274 | Then your customer clicks 'Proceed' and gets to next step.
275 |
276 | In case CSR code is ok, your client will see the list of available DCV options on the next page.Those DCV options are basically HTTP-based validation or approval email. Your client may select any of emails there to receive Domain Control Validation email on that address or select HTTP-based DCV. In case HTTP-based DCV radiobutton is selected no email is to be sent for validation, however your customer will need to submit a specific file to root folder of his domain. Name and contents of file will be shown after he clicks ‘Submit’ and activation data gets transmitted to Certificate Authority. Also the file contents can be checked in customer’s area by viewing information of certificate that is being activated.
277 |
278 | Further activation process is between you or your customer and Certificate Authority. You are to receive approval email (for most certificates except Symantec OV and EV certs) and to approve it. After that certificate is to be sent to you (within 10-15 mins) or some docs request is to be sent to you for OV or EV certs.
279 |
280 | ***
281 | **Important Note:**
282 | Language variables containing strings with instructions to HTTP-based validation and with file contents are stored in /modules/servers/namecheapssl/lang/English.php. If you are using other language you need to create /modules/servers/namecheapssl/lang/%yourlanguage%.php and change values of the following variables to corresponding phrases in your language: $MOD_LANG['ncssl_http_based_validation'] ,$MOD_LANG['ncssl_show_validation_file_contents'] , $MOD_LANG['ncssl_custom_phrase_sslcertapproveremaildetails'],$MOD_LANG['ncssl_custom_phrase_sslconfigcompletedetails']
283 | ***
284 |
285 | ##### Debugging and Addon functions
286 |
287 | Our Namecheap SSL Module addon has the following functions:
288 |
289 | - Log
290 | - Link/Re-Link WHMCS cert ID to NC Cert ID
291 | - Certificate list
292 |
293 | Log
294 |
295 | During setting up product you may check ‘Debug mode’ box in order to have your actions with module logged :
296 |
297 | 
298 |
299 | This will allow you to check log of actions performed by module in addons section in WHMCS:
300 |
301 | There you will find all of the actions performed by your customer with namecheapssl products, all hook actions and all API calls and responses. This is very convenient for investigation of possible issues.
302 |
303 | Each action will have WHMCS service ID of certificate that was viewed/activated/reissued from WHMCS user area so you will be able to track actions of your customers.
304 |
305 | ** Link/Re-Link WHMCS Cert ID to NC Cert ID**
306 |
307 | This feature allows connecting WHMCS certificate record to existing Namecheap certificate.
308 |
309 | For this you will need to input WHMCS invoice ID given after order placement to corresponding box and then to input certID of an existing certificate within your NC account (can be found next to certificate in list of SSLs at Namecheap).
310 |
311 | After clicking ‘Sync’ details for specific certificate in your WHMCS will be taken from Namecheap.
312 |
313 | **Certificate List**
314 |
315 | In this section you may see all of the certificates ordered via this WHMCS from all of the NC accounts associated with it.
316 |
317 | You will see the following fields in the lists:
318 |
319 | 
320 |
321 | ##### Reissue and renewal
322 |
323 | Reissue and renewal are 2 different actions with SSL certificate.
324 |
325 | After the certificate gets issued, it's status becomes ‘active’ and you will see the following screen while viewing it’s info:
326 |
327 | 
328 |
329 | There you may download certificate in zip archive in corresponding format for your web-server or reissue the certificate.
330 |
331 | **Reissue**
332 |
333 | Reissue is the process of having certificate regenerated with Certificate Authority if needed. For example, if your client has lost your Private Key. For that he needs to view details of your certificate from list of certificates in WHMCS user area and click ‘Reissue Certificate’ button:
334 |
335 | Further process will be very similar to activation – your customer will need to paste CSR for the same domain name and select approval email. Reissuing a certificate will change its Namecheap Certificate ID. A new certificate record will be added to your Namecheap account.
336 |
337 | **Due date and reissue state synchronization**
338 |
339 | All changes done in WHMCS are synchronized with your Namecheap account automatically once a day (when WHMCS cron runs). Also you can perform manual synchronization any time by clicking ‘Synchronize with Namecheap’. This will set WHMCS due dates and reissue states in sync with Namecheap admin area when needed:
340 |
341 | 
342 |
343 | **Renewal** is pretty much the same as purchasing new certificate with Namecheap. Renewal functionality is fully integrated into the module. As long as you have “Payment Type” set to “Recurring” when creating a product, invoices for renewals will be generated automatically. Once paid, renewal SSLs will be created automatically as well. Please keep in mind that after the renewal SSL is created, it still requires activation using [CSR](http://namecheap.simplekb.com/kb.show?show=article&articleid=817&categoryid=71).
344 |
345 | ##### Multi-Domain Certificates
346 |
347 | **General information about product**
348 |
349 | Recently Multi-Domain Certificates were added to Namecheap’s product list. These certificates are quite popular among customers, but require some additional configurations. during Multidomain certificates can be divided into 2 categories – old single domain products that now support additional domains as a configurable addon, and new multi-domain products that come with a predefined number of domains included in the product by default (more domains can be included additionally as well). Therefore number of domains included by default differs across the products. See the table for details:
350 |
351 |
352 |
353 |
354 |
Provider
355 |
Product name
356 |
Default number of domains (domain from CSR is counted here)
357 |
Maximum number of domains
358 |
Maximum number of domains that should be used in configurable options
359 |
360 |
361 |
Comodo
362 |
PositiveSSL Multi-domain
363 |
3
364 |
100
365 |
97
366 |
367 |
368 |
Comodo
369 |
Multi Domain SSL
370 |
3
371 |
100
372 |
97
373 |
374 |
375 |
Comodo
376 |
EV Multi Domain
377 |
3
378 |
100
379 |
97
380 |
381 |
382 |
Comodo
383 |
Unified Communications
384 |
3
385 |
100
386 |
97
387 |
388 |
389 |
Geotrust
390 |
QuickSSL Premium
391 |
1
392 |
4
393 |
-
394 |
395 |
396 |
Geotrust
397 |
True Business ID with EV Multi-domain
398 |
5
399 |
25
400 |
20
401 |
402 |
403 |
Geotrust
404 |
True Business ID Multi-domain
405 |
5
406 |
25
407 |
20
408 |
409 |
410 |
Thawte
411 |
SSL Web Server
412 |
1
413 |
25
414 |
24
415 |
416 |
417 |
Thawte
418 |
SSL Web Server with EV
419 |
1
420 |
25
421 |
24
422 |
423 |
424 |
Thawte
425 |
SSGC Supercerts
426 |
1
427 |
25
428 |
24
429 |
430 |
431 |
Symantec
432 |
Secure Site Pro with EV
433 |
1
434 |
25
435 |
24
436 |
437 |
438 |
Symantec
439 |
Secure Site with EV
440 |
1
441 |
25
442 |
24
443 |
444 |
445 |
Symantec
446 |
Secure Site
447 |
1
448 |
25
449 |
24
450 |
451 |
452 |
Symantec
453 |
Secure Site Pro
454 |
1
455 |
25
456 |
24
457 |
458 |
459 |
460 |
461 | ##### Setting up Multi-Domain Certificates
462 |
463 | First of all, you need to set up product as described in ‘Setting up products and pricings’ section. After product is set up the default number of addon domains (from table above) will be available during activation. In order to give your customers ability to order additional domains you need to set up configurable options for each multi-domain certificate you set up. It would not take much time.
464 |
465 | 1. Go to configurable options and click on ‘Create a new group’ there.
466 |
467 | 
468 |
469 | 2. Fill in the name of your group (We recommend mentioning product name there) and select a product you wish to associate the configurable option with.
470 |
471 | 
472 |
473 | 3. Click ‘Add new configurable option’ button.
474 |
475 | 
476 |
477 | 4. Option Name. This field consists of two parts, the first one is internal and the other one is Visible to clients. Option name must contain ‘san|’ element. The text input after “|” will be displayed in your clients’ shopping cart. We recommend to specify default number of addon domains that are already included in certificate (For example – “san|Addon domains ( 3 domains are included by default)” for PositiveSSL MultiDomain.
478 |
479 | 5. Select ‘Quantity’ as Option Type from dropdown menu. Click ‘Save changes’.
480 |
481 | 6. Type 0 in ‘Minimum Quantity Required’ and the value from the last column of the table above as ‘Maximum Allowed’. For example, if you are setting up PositiveSSL Multi Domain, please input 97 as maximum.
482 |
483 | 7. Use any name (it will not be shown anywhere) in the box next to ‘Add Option:’ and click ‘Save changes’.
484 |
485 | 8. At this point you will see the table for pricing similar to one you’ve filled in during setting up product. Please fill in pricing for each additional domain for different terms.
486 |
487 | 9. Click ‘Save changes’
488 |
489 | 
490 |
491 | That’s it. Now if your customer orders a multi-domain certificate he will be able to add some additional domains to his order.
492 |
493 | ***
494 | **Important Note:** Please mention the default number of domains provided with Multi-Domain Certificates in product name or product description – this will guarantee your customers that even if they do not order any additional domains, they will have some of them added by default.
495 | ***
496 |
497 | ##### QuickSSL Premium multi-domain setup
498 | As you could see from the table above, QuickSSLs Premium are also multi-domain product from now on. However they have certain specifics.
499 |
500 | - You have 2 options during purchasing QuickSSL Premium – default single-domain option or option with 4 additional subdomains.
501 | - You may only add subdomains of different levels as addons – different domains will return error.
502 | - Price remains the same in case you activate QuickSSL Premium with 1 or 4 additional subdomains.
503 |
504 | Configurable option for QuickSSL Premium is a bit different. Please follow the next steps in order to configure it.
505 |
506 | 
507 |
508 | 1. Please select Option type as ‘Dropdown’.
509 |
510 | 2. Please set name as ‘san|Addon Subdomains’ (or, as for other Multi-Domain Certificates, any other phrase after ‘|’. 3. Fill the field below ‘Options’ with “0|No addon subdomains” (or any other phrase after ‘|’ on your demand. “0” is the keyword meaning that selecting this option will create no fields for client during activation.
511 |
512 | 4. Click ‘Save Changes’.
513 |
514 | 5. Fill the new field with ‘1|4 addon subdomains’ (or any other phrase after ‘|’ on your demand). “1” is the keyword meaning that selecting this option will create 4 fields for addon subdomains for client during activation.
515 |
516 | 6. Click ‘Save changes’.
517 |
518 | Example of configurable options table:
519 |
520 | 
521 |
522 | ##### Managing addon domains after purchase is made
523 |
524 | Your client as well as you will be able to add more domains to a certificate after order is complete.
525 |
526 | This can be done either from user and admin areas.
527 |
528 | In order to do that in admin area, your customer needs to mouse over ‘Management Actions’ and select ‘Upgrade/Downgrade Options’.
529 |
530 | 
531 |
532 | There your customer can increase number of addon domains. An attempt to decrease that number will cause error. A new hook was implemented in client area tracking attempts to decrease number of addon domains.
533 |
534 | ***
535 | **Important Note:** The number of addon domains can be changed from client area only after invoice for order is paid.
536 | ***
537 |
538 | In order to change number of addon domains in WHMCS admin area, you need to access product page and manually input the new number of addon domains.
539 |
540 | Please note that in case you decrease or increase this number here, you need to invoice/refund your client manually.
541 |
542 | 
543 |
544 | ***
545 | **Important Note:** In case you or your client increases number of addon domains for a certificate your Namecheap account will be charged for every extra addon domain used during activation/reissue.
546 | ***
547 |
548 | For example, if your customer has ordered 2 more domains before reissue or you have manually increased number of addon domains by 2, your Namecheap account will be charged for 2 addon domains after reissue is complete from WHMCS client area.
549 |
550 | ##### Activation of Multi-Domain Certificates
551 |
552 | Activation process is similar to activation of single-domain certificates. Below the CSR box you will see fields for additional domains (or subdomains in case of QuickSSL Premium).
553 |
554 | It is not strongly required to fill in all the Addon Domain field during the first activation. Duplicate records are not allowed (including duplicates in CSR’s common name and addon domain fields).
555 |
556 | Below is an example of first configuration page for PositiveSSL Multi Domain with 5 addon domains ordered (1 domain from CSR + 2 addon domains by default + 5 addon domains ordered separately).
557 |
558 | 
559 |
560 | For example, if he selects “admin@” as approver email having “domain.com” as common name in CSR and “secure.domain.com” and “domain2.com” as addon domains, the approvals will be sent to admin@domain.com, admin@secure.domain.com and admin@domain2.com.
561 |
562 | If your customer wishes to change email for one of the domains, he should contact you, and you in turn need to contact us via live chat or ticket system to have emails changed.
563 |
564 | Such approver email selection flow on second configuration page is caused by certain limitations in WHMCS core.
565 |
566 | **Revocation**
567 |
568 | In this version, revocation functionality has been added. WHMCS end users can request revocation of their reissued certificates. A new button appears on the Certificate Details page if there are any reissued certificates on record:
569 |
570 | 
571 |
572 | Also, this button will be shown in the admin area for specific services.
573 | With different Certificate Authorities, clicking this button will lead to different behaviors.
574 |
575 | **Comodo Case**
576 |
577 | Comodo certificates are revoked immedidately after the button is clicked. Once it has been clicked, the button will disappear from the client and admin areas, and certificate is marked ‘Revoked’ on the Namecheap side.
578 |
579 | **RapidSSL/GeoTrust/Symantec/Thawte Case**
580 |
581 | Revocation functionality for these Certificate Authorities is different from Comodo’s. Revocation approval via email is required. The revocation approval will be sent to the technical email address specified in the order. In addition, there are three groups of RapidSSL/ GeoTrust /Symantec/ Thawte certificates that show different behavior upon clicking the ‘Revoke old certificates’ button based on the issuance dates.
582 |
583 | **1. Certificates issued before 6/16/2014**
584 |
585 | These certificates cannot be revoked right away. Upon clicking the ‘Revoke Old Certificates’ button the following message will be shown:
586 | “Revocation of reissued certificates associated with this order is unavailable right away due to limitations from Symantec. Please contact support for revocation of your reissued certificates.”
587 | You, as WHMCS admin, will need to revoke the certificate from End User Portal.
588 |
589 | Please read the following article to learn how to revoke certificates using End User Portal: https://www.namecheap.com/support/knowledgebase/article.aspx/9346/38/revocation-of-symantecgeotrustthawterapidssl-certificates
590 |
591 | **2. Certificates issued after 6/16/2014 that have technical email unfilled in module settings of the product (therefore sslsupport@namecheap.com is used)**
592 |
593 | Upon clicking the ‘Revoke Old Certificates’ button the following message will be shown:
594 | “The revocation process has been initiated. The revocation will be processed manually between us and Symantec. It will be completed within 1-2 hours.“
595 |
596 | The revocation approval will be sent to our email address, and our team will process it for you within 1-2 hours if there are no unpredicted circumstances.
597 |
598 | **3. Certificates issued after 6/16/2014 that have your technical email specified in module settings of product**
599 |
600 | Upon clicking the ‘Revoke Old Certificates’ button the following message will be shown:
601 | “Your revocation request is being processed manually by admin. Revocation will be completed as soon as possible.”
602 |
603 | You, as WHMCS admin, will need to check your technical email and approve the revocation request manually. We recommend you check technical email inbox on a regular basis.
604 |
605 | **Important Note:** Due to limitations on Symantec’s side, the GeoTrust/RapidSSL/Symantec/Thawte certificates described in cases 2 and 3 can be revoked only if there is only one reissued certificate record for a specific certificate. Attempting to revoke certificates that have 2 or more reissued records will cause the following message upon clicking the ‘Revoke Old Certificates’ button:
606 | “Revocation of multiple instances of reissued certificates is temporarily unavailable due to technical restrictions on the Certificate Authority’s side. Please contact support for further assistance.”
607 |
608 | You will need to revoke the certificate using End User Home or to contact Namecheap SSL Support for revocation.
609 |
610 | ##### FAQ
611 |
612 | **Q:** I cancel certificate and nothing happens
613 |
614 | **A:** Cancellation is being performed only in your WHMCS, but not in our system. Please submit a cancellation request with our SSL support team for certificate to be revoked and refunded
615 |
616 | **Q:** Does your module have multi-language support?
617 |
618 | **A:** Yes, multi-language is fully integrated with WHMCS so you may change the default language of your WHMCS and language will be changed for fields used in module as well. Please note that you will need to create a custom %yourlanguage%.php file in lang directory at modules/servers/namecheapssl/lang for some fields to be translated as well. You may use default English.php as translation template.
619 |
620 | **Q:** Getting “ 2010167 Parameter Years is Missing” error while accepting order.
621 |
622 | **A:** This error usually occurs when Pricing is set up improperly for your SSL product. Please doublecheck that Payment type is set to ‘Recurring’ and there is ‘-1’ input in ‘Monhtly, Quarterly, and Semi-Anually’ fields to disable possibility of ordering SSL for terms less than a year as SSL certificates can only be ordered and issued for a whole number of years only.
623 |
624 | **Q:** I am receiving ''['" or any other strange characters instead or error messages while activation of my renewal certificate
625 |
626 | **A:** This is a known bug, our developers are currently investigating it. In case you face this issue please email details to sslsupport@namecheap.com and kindly purchase and activate renewal certificate manually from Namecheap if renewal is urgent. After purchasing certificate manually you will need to sync the IDs using ‘Link/Re-Link WHMCS Cert ID to NC Cert ID’ addon function.
627 |
628 |
629 |
630 |
631 |
--------------------------------------------------------------------------------
/includes/hooks/namecheapssl_sync.php:
--------------------------------------------------------------------------------
1 | 1, "PageSize" => $iPageSize);
45 |
46 | try{
47 | $response = $api->request("namecheap.ssl.getList", $requestParams);
48 | $result = $api->parseResponse($response);
49 | }catch(Exception $e){
50 | echo $e->getMessage();
51 | return;
52 | //exit();
53 | }
54 |
55 | if ($result){
56 | $iTotalPages = (int) ceil($result['Paging']['TotalItems']/$iPageSize);
57 | }
58 |
59 | for($i=1;$i<=$iTotalPages;$i++){
60 | if (1!=$i){
61 | try{
62 | $requestParams = array("Page" => $i, "PageSize" => $iPageSize);
63 | $response = $api->request("namecheap.ssl.getList", $requestParams);
64 | $result = $api->parseResponse($response);
65 | }catch(Exception $e){
66 | echo $e->getMessage();
67 | return;
68 | //exit();
69 | }
70 | }
71 |
72 |
73 | foreach ($result["SSLListResult"]["SSL"] as $aCertInfo){
74 |
75 | if ('active'==$aCertInfo['@attributes']['Status'] || 'replaced'==$aCertInfo['@attributes']['Status']){
76 |
77 |
78 | // synchronize expire date
79 | list($month, $day, $year) = explode("/", $aCertInfo['@attributes']['ExpireDate']);
80 |
81 | //
82 | $res = NcSql::q("SELECT h.id FROM `tblhosting` h INNER JOIN `tblsslorders` s ON s.serviceid=h.id WHERE s.remoteid='".(int)$aCertInfo['@attributes']['CertificateID']."' AND h.`nextduedate` != '".NcSql::e("$year-$month-$day")."'");
83 |
84 | if (NcSql::numRows($res)){
85 | $iHostingId = array_shift(NcSql::fetchArray($res));
86 |
87 | $duedate = "$year-$month-$day";
88 | if($sync_date_offset){
89 | $duedate = date('Y-m-d',strtotime($duedate . "-$sync_date_offset days"));
90 | }
91 |
92 | $sql = "update `tblhosting`
93 | set `nextduedate` = '".NcSql::e($duedate)."',
94 | `nextinvoicedate` = '". NcSql::e($duedate)."'
95 | where `id` = '".(int)$iHostingId."'";
96 | NcSql::q($sql);
97 | namecheapssl_log('hook.sync', 'sync_hook_updated_duedate', array("$duedate"),$iHostingId);
98 | }
99 |
100 | // sync domain
101 | if(!empty($aCertInfo['@attributes']['HostName']) && 'active'==$aCertInfo['@attributes']['Status']){
102 | $domain = NcSql::e($aCertInfo['@attributes']['HostName']);
103 | $res = NcSql::q("SELECT h.id FROM `tblhosting` h INNER JOIN `tblsslorders` s ON s.serviceid=h.id WHERE s.remoteid='{$aCertInfo['@attributes']['CertificateID']}' AND h.`domain` != '$domain'");
104 | if (NcSql::numRows($res)){
105 | $iHostingId = array_shift(NcSql::fetchArray($res));
106 | $sql = "update `tblhosting`
107 | set `domain` = '$domain'
108 | where `id` = '".(int)$iHostingId."'";
109 | NcSql::q($sql);
110 | namecheapssl_log('hook.sync', 'sync_hook_updated_domain', array($domain),$iHostingId);
111 | }
112 | }
113 |
114 |
115 | }
116 |
117 |
118 | if ('replaced'==$aCertInfo['@attributes']['Status']){
119 |
120 | // synchronize reissue state
121 | $sql ="SELECT * FROM tblsslorders WHERE remoteid='".(int)$aCertInfo['@attributes']['CertificateID']."'";
122 | $r = NcSql::q($sql);
123 | if (NcSql::numRows($r)){
124 | $aWhmcsCert = NcSql::fetchAssoc($r);
125 | // get replaced certificate info
126 | try{
127 | $replaced_cert_request_params = array('CertificateID' => (int)$aWhmcsCert['remoteid']);
128 | $replaced_cert_response = $api->request("namecheap.ssl.getInfo", $replaced_cert_request_params);
129 | $replaced_cert_result = $api->parseResponse($replaced_cert_response);
130 |
131 | if (!empty($replaced_cert_result["SSLGetInfoResult"]["@attributes"]["ReplacedBy"])){
132 |
133 | $replacedBy = (int)$replaced_cert_result["SSLGetInfoResult"]["@attributes"]["ReplacedBy"];
134 | if(0==$replacedBy){
135 | echo 'Wrong "replaced by" attribute: ' . $replaced_cert_result["SSLGetInfoResult"]["@attributes"]["ReplacedBy"];
136 | return;
137 | //exit();
138 | }
139 |
140 | $sql = "UPDATE tblsslorders SET remoteid='$replacedBy' WHERE remoteid='".(int)$aCertInfo['@attributes']['CertificateID']."'";
141 | NcSql::q($sql);
142 |
143 | $sql = "UPDATE mod_namecheapssl SET certificate_id='$replacedBy' WHERE certificate_id='".(int)$aCertInfo['@attributes']['CertificateID']."'";
144 | NcSql::q($sql);
145 |
146 | namecheapssl_log('hook.sync', 'sync_hook_updated_remoteid', array($aCertInfo['@attributes']['CertificateID'], $replacedBy),$aWhmcsCert['serviceid']);
147 |
148 | }
149 |
150 | }catch(Exception $e){
151 | echo $e->getMessage();
152 | return;
153 | }
154 |
155 | }
156 |
157 | }
158 |
159 |
160 | }
161 |
162 | }
163 |
164 |
165 | }
166 |
167 |
168 | function Namecheapssl_hook_report(){
169 |
170 | // create html for report
171 | $dateEnd = date('Y-m-d H:i:00');
172 | $dateStart = date('Y-m-d H:i:59', mktime(date('H'), date('i'), date('s'), date('n'), date('d')-1));
173 |
174 |
175 | $query = "SELECT log.*,c.email FROM mod_namecheapssl_log log LEFT JOIN tblclients AS c ON (log.userid=c.id AND user='client') WHERE log.date BETWEEN '". NcSql::e($dateStart)."' AND '". NcSql::e($dateEnd)."' AND `debug`=0 ";
176 |
177 | $r = NcSql::q($query);
178 |
179 | if(NcSql::numRows($r)){
180 |
181 | $html = "Namecheap SSL Module Cron Job Report for $dateStart-$dateEnd
A reissue request has been initiated by an administrator for the following: {\$ssl_certificate_id}. In order to reissue the certificate please go through a configuration process at the URL below.
{\$ssl_configuration_link}
Instructions are provided throughout the process but if you experience any problems or have any questions, please open a ticket for assistance.
and put it to the following location on your hosting server: http(s)://example.com/.well-known/pki-validation/. It may take some time for file to be automatically validated and cert to be issued by Certificate Authority';
163 | $_MOD_LANG['ncssl_download_certificate'] = "Download certificate";
164 |
165 |
166 | $_MOD_LANG['ncssl_custom_phrase_sslcertapproveremaildetails'] = 'Please select any of emails if you wish to proceed with email-based validation. An approval email will be sent to selected address by Certificate Authority after activation.';
167 | $_MOD_LANG['ncssl_custom_phrase_sslcertapproveremaildetails_http_based'] = '
If you select \'HTTP based validation\' option, you will need to place a certain file into a specific location of your server. Name and contents of the file will be provided at the last step of the activation process. No emails will be sent for Domain Control Validation.';
168 |
169 | $_MOD_LANG['ncssl_custom_phrase_sslcertapproveremaildetails_san'] = 'Please select local part of emails you wish to receive your approval emails to. This local part will be used to send approval emails for all domains and subdomains.
For example, if \'admin@\' is selected as approver having main domain specified as \'domain.com\' and addon domain is \'sub.domain1.com\' , the approver emails will be sent to admin@domain.com and admin@sub.domain1.com.';
170 |
171 | $_MOD_LANG['ncssl_custom_phrase_sslcertapproveremaildetails_san_http_based'] = '
If you select \'HTTP based validation\' option, you will need to place a certain file into a specific locations of servers for all of the domains specified while activation. Name and contents of the file will be provided at the last step of the activation process. No emails will be sent for Domain Control Validation.';
172 |
173 |
174 | $_MOD_LANG['ncssl_san_items_title'] = 'Enter additional domains';
175 |
176 | $_MOD_LANG['ncssl_san_items_item'] = 'Addon Domain ';
177 | $_MOD_LANG['ncssl_san_items_item_quick_ssl_premium'] = 'Addon Subdomain ';
178 |
179 | $_MOD_LANG['ncssl_san_csr_note'] = ' Domains included in SAN sections in CSR will be ignored! Please input addon domains in fields below the box for CSR. Please do not input main domain as addon domain. It is taken from CSR. Please make sure you do not use duplicates.';
180 |
181 | $_MOD_LANG['ncssl_reissue_notice_step1'] = 'The following contact information will be used for reissue of your certificate:';
182 | $_MOD_LANG['ncssl_reissue_notice_step2'] = 'The following information will be used for reissue of your certificate:';
183 |
184 | $_MOD_LANG['ncssl_revoke_confirmation_text'] = 'Are you sure that you want to revoke the old certificates associated with this order? This will not affect latest active certificate, only the old reissued certificates will be revoked.';
185 | $_MOD_LANG['ncssl_revoke_button'] = 'Revoke old certificates';
186 | $_MOD_LANG['ncssl_revoke_button_description'] = 'Recommended before new reissue';
187 |
188 | $_MOD_LANG['ncssl_error_2011166'] = 'Invalid domain name. Please use the domain name used during initial activation: ';
189 |
190 |
191 | $_MOD_LANG['ncssl_error_revoke_1'] = 'Revocation of reissued certificates associated with this order is unavailable right away due to limitations from Symantec. Please contact support for revocation of your reissued certificates';
192 | $_MOD_LANG['ncssl_error_revoke_2'] = 'Your revocation request is being processed manually by admin. Revocation will be completed as soon as possible';
193 | $_MOD_LANG['ncssl_error_revoke_3'] = 'Your revocation request is being processed manually. Revocation will be completed as soon as possible';
194 | $_MOD_LANG['ncssl_error_revoke_4'] = 'Revocation of multiple instances of reissued certificates is temporary unavailable due to technical restrictions at Certificate Authority’s side. Please contact support for further assistance.';
195 |
196 |
197 | $_MOD_LANG['ncssl_back_to_service'] = '« Back to the service';
198 |
199 | $_MOD_LANG['ncsssl_jobtitle_required_for_symantec'] = 'Job Title is required';
200 |
201 |
202 | $_MOD_LANG['ncssl_symantec_approver_email_notice'] = 'Approval email is not required for this type of certificate';
203 |
204 |
205 | $_MOD_LANG['ncssl_latin_characters_notice'] = 'Only Latin characters can be used in the Admin information';
206 |
--------------------------------------------------------------------------------
/modules/servers/namecheapssl/namecheapapi.php:
--------------------------------------------------------------------------------
1 | _apiUser = $apiUser;
49 | $this->_apiKey = $apiKey;
50 |
51 | $this->setTestMode($testMode);
52 |
53 | $this->_debugMode = (bool)$debugMode;
54 | }
55 |
56 | /**
57 | * parseResponse
58 | * @param string $response
59 | * @return array
60 | */
61 | public function parseResponse($response)
62 | {
63 |
64 | if (false === ($xml = simplexml_load_string($response))) {
65 | throw new NamecheapApiException("Unable to parse response");
66 | }
67 | $result = $this->_xml2Array($xml);
68 |
69 | if(empty($result['@attributes']['Status']) || !isset($result['Server'])){
70 | throw new NamecheapApiException("Response error. It is not look like normal api response. Please try again");
71 | }
72 |
73 |
74 | if ("ERROR" == $result['@attributes']['Status']) {
75 | $errors = isset($result['Errors']['Error'][0]) ? $result['Errors']['Error'] : array($result['Errors']['Error']);
76 |
77 | $err = $errors[count($errors) - 1];
78 | $err_msg = sprintf("[%s] %s", $err['@attributes']['Number'], $err['@value']) ;
79 | throw new NamecheapApiException($err_msg, $err['@attributes']['Number']);
80 | }
81 |
82 |
83 |
84 | return $result['CommandResponse'];
85 | }
86 |
87 | /**
88 | * request
89 | * @param string $command
90 | * @param array $params
91 | * @return string
92 | */
93 | public function request($command, array $params)
94 | {
95 | $result = false;
96 | $curl_error = false;
97 |
98 | $this->_requestUrl = $this->_getApiUrl($command, $params);
99 | $this->_requestParams = $this->_getApiParams($command, $params);
100 |
101 |
102 | if ($this->_debugMode){
103 | $logRequestParams = $this->_requestParams;
104 | if(!empty($logRequestParams['ApiKey'])){
105 | $logRequestParams['ApiKey'] = '***';
106 | }
107 | $this->_lastLogRecordId = namecheapssl_save_debug_info("REQUEST:\n".date('Y-m-d H:i:s')."\ncommand:".$command."\nparams:"."\n" . var_export($logRequestParams,true)."\n",$command);
108 | }
109 |
110 |
111 | if (extension_loaded("curl") && ($ch = curl_init()) !== false)
112 | {
113 | curl_setopt($ch, CURLOPT_URL, $this->_requestUrl);
114 | curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
115 |
116 | // we set peer verification of namecheap server to false - else the process will fail
117 | // if the host server doesnt have an accurate ca bundle.
118 | // Can turn this on, when you place an up to date ca bundle at your host server.
119 |
120 | if ($command == 'namecheap.ssl.activate' || strtolower($command) == 'namecheap.ssl.parsecsr' || strtolower($command) == 'namecheap.ssl.reissue') {
121 | curl_setopt($ch, CURLOPT_POST, 1);
122 | curl_setopt($ch, CURLOPT_POSTFIELDS, $this->_requestParams);
123 | }
124 |
125 |
126 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
127 | curl_setopt($ch, CURLOPT_HEADER, 0);
128 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
129 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
130 | $this->_response = curl_exec($ch);
131 | $curl_error = curl_error($ch);
132 | curl_close($ch);
133 |
134 | if($curl_error){
135 | if($this->_debugMode){
136 | namecheapssl_save_debug_info('Curl error: ' . $curl_error . ". Unable to request data from " . $this->_requestUrl,$command,true,$this->_lastLogRecordId);
137 | }
138 | throw new NamecheapApiException('Curl error: ' . $curl_error);
139 | }
140 |
141 | }else{
142 | $message = "Unable to request data, curl extention is not loaded";
143 | if($this->_debugMode){
144 | namecheapssl_save_debug_info($message,$command,true,$this->_lastLogRecordId);
145 | }
146 | throw new NamecheapApiException($message);
147 | }
148 | /*else{
149 | $this->_response = @file_get_contents($this->_requestUrl);
150 | if (!$this->_response) {
151 | $message = "Unable to request data from (file_get_contents used)" . $this->_requestUrl;
152 | if($this->_debugMode){
153 | namecheapssl_save_debug_info($message,$command,true,$this->_lastLogRecordId);
154 | }
155 | throw new NamecheapApiException($message);
156 | }
157 | }*/
158 |
159 |
160 | if ($this->_debugMode){
161 | namecheapssl_save_debug_info("RESPONSE:\n".date('Y-m-d H:i:s')."\n".$this->_response."\n",$command,true,$this->_lastLogRecordId);
162 | }
163 |
164 |
165 | return $this->_response;
166 | }
167 |
168 | /**
169 | * setTestMode
170 | * @param boolean $flag
171 | */
172 | public function setTestMode($flag)
173 | {
174 | $this->_testMode = (bool)$flag;
175 | }
176 |
177 | // private methods
178 |
179 | /**
180 | * formatPhone
181 | * @param string $phone
182 | * @return string
183 | */
184 | private function _formatPhone($phone)
185 | {
186 | /**
187 | * Namecheap API phone format requirement is +NNN.NNNNNNNNNN
188 | */
189 |
190 | $arg = $phone;
191 |
192 | // strip all non-digit characters
193 | $phone = preg_replace('/[^\d]/', '', $phone);
194 |
195 | // check country code
196 | $phone_code = "";
197 | foreach (self::$_phoneCountryCodes as $v) {
198 | if (preg_match("/^$v\d+$/", $phone)) {
199 | $phone_code = $v;
200 | break;
201 | }
202 | }
203 | if (!$phone_code) {
204 | return $arg;
205 | }
206 |
207 | // add '+' and dot to result phone number
208 | $phone = preg_replace("/^$phone_code/", "+{$phone_code}.", $phone);
209 | return $phone;
210 | }
211 |
212 | /**
213 | * _getApiUrl
214 | * @param string $command
215 | * @param array $params
216 | * @return string
217 | */
218 | private function _getApiUrl($command, array $params)
219 | {
220 |
221 | $isPost = false;
222 | if ($command == 'namecheap.ssl.activate' || strtolower($command) == 'namecheap.ssl.parsecsr' || strtolower($command) == 'namecheap.ssl.reissue') {
223 | $isPost = true;
224 | }
225 |
226 | if (!$isPost) {
227 | return ($this->_testMode ? self::$testUrl : self::$url) . '?' . 'SourceOfCall=WHMCS&' . http_build_query($this->_getApiParams($command, $params),'','&');
228 | } else {
229 | return ($this->_testMode ? self::$testUrl : self::$url) . '?SourceOfCall=WHMCS';
230 | }
231 | }
232 |
233 | /**
234 | * _getApiParams
235 | * @param string $command
236 | * @param array $params
237 | * @return string
238 | */
239 | private function _getApiParams($command, array $params)
240 | {
241 | $params['Command'] = $command;
242 | $params['ApiUser'] = $this->_apiUser;
243 | $params['ApiKey'] = $this->_apiKey;
244 |
245 | if (!array_key_exists('UserName', $params) || !strlen($params['UserName'])) {
246 | $params['UserName'] = $params['ApiUser'];
247 | }
248 | if (!array_key_exists('ClientIp', $params)) {
249 | $params['ClientIp'] = $this->_getClientIp();
250 | }
251 |
252 | // format phone/fax fields
253 | foreach ($params as $k => &$v) {
254 | if (preg_match('/(Phone|Fax)/i', $k)) {
255 | $v = trim($v);
256 | if(!empty($v)){
257 | $v = $this->_formatPhone($v);
258 | }
259 | }
260 | }
261 |
262 | return $params;
263 | }
264 |
265 | /**
266 | * _getClientIp
267 | * @return string
268 | */
269 | private function _getClientIp()
270 | {
271 | $clientip = $_SERVER['REMOTE_ADDR'];
272 | return $clientip ? $clientip : "10.11.12.13";
273 | }
274 |
275 | /**
276 | * _xml2Array
277 | * @param string $xml
278 | * @return array
279 | */
280 | private function _xml2Array($xml)
281 | {
282 | if (!($xml instanceof SimpleXMLElement)) {
283 | throw new NamecheapApiException("Not a SimpleXMLElement object");
284 | }
285 | $result = array();
286 | foreach ($xml->attributes() as $attrName => $attr) {
287 | $result['@attributes'][$attrName] = (string)$attr;
288 | }
289 | foreach ($xml->children() as $childName => $child) {
290 | if (array_key_exists($childName, $result)) {
291 | if (!is_array($result[$childName]) || !isset($result[$childName][1])) {
292 | $result[$childName] = array($result[$childName]);
293 | }
294 | $result[$childName][] = $this->_xml2Array($child);
295 | } else {
296 | $result[$childName] = $this->_xml2Array($child);
297 | }
298 | }
299 | $value = trim((string)$xml);
300 | if (array_keys($result)) {
301 | if ($value) {
302 | $result['@value'] = $value;
303 | }
304 | } else {
305 | $result = $value;
306 | }
307 | return $result;
308 | }
309 |
310 | /**
311 | *
312 | * @param string $xmlResponse
313 | * @return integer
314 | */
315 | public function getGmtTS($response)
316 | {
317 | $gmt = 0;
318 | if (preg_match("/(-|\+)+([0-9:]+)<\/GMTTimeDifference>/", $response, $matches)) {
319 | $gmt = $matches[2];
320 | $gmtsign = preg_replace("/-+/", "-", $matches[1]);
321 | $gmtsign = $gmtsign == '-' ? -1 : 1;
322 | list($gmth, $gmtm) = explode(":", $gmt);
323 | $gmt = $gmtsign*(($gmth*3600)+($gmtm*60));
324 | }
325 | return $gmt;
326 | }
327 |
328 | public function getLastUrl() {
329 | return $this->_requestUrl;
330 | }
331 | public function getLastParams() {
332 | return $this->_requestParams;
333 | }
334 | public function getLastResponse() {
335 | return $this->_response;
336 | }
337 | }
338 | }
339 |
340 |
341 | if (!class_exists('NcSql')){
342 | class NcSql{
343 |
344 | protected static $_link;
345 |
346 | public static function getLink(){
347 |
348 | $backtrace = debug_backtrace();
349 |
350 | if(!empty(self::$_link)) return self::$_link;
351 | include(dirname(__FILE__).'/../../../configuration.php');
352 | self::$_link = mysqli_connect($db_host, $db_username, $db_password, $db_name);
353 | return self::$_link;
354 | }
355 |
356 | public static function q($sql){
357 | //echo $sql.' ';
358 | $r = mysqli_query(self::getLink(), $sql);
359 | return $r;
360 | }
361 |
362 | public static function e($sql){
363 | return mysqli_escape_string(self::getLink(),$sql);
364 | }
365 |
366 | public static function fetchAssoc($r){
367 | return mysqli_fetch_assoc($r);
368 | }
369 |
370 | public static function fetchArray($r){
371 | return mysqli_fetch_array($r);
372 | }
373 |
374 | public static function numRows($r){
375 | return mysqli_num_rows($r);
376 | }
377 |
378 | public static function insertId(){
379 | return mysqli_insert_id(self::getLink());
380 | }
381 |
382 | public static function sql2set($sql){
383 | $r = self::q($sql);
384 | if(!$r){
385 | return false;
386 | }
387 | $row = array();
388 | while ($row=mysqli_fetch_assoc($r)){
389 | $result[]=$row;
390 | }
391 | return $result;
392 | }
393 |
394 | public static function sql2set_column($sql){
395 |
396 | $data = self::sql2set($sql);
397 | $set = array();
398 | if(!empty($data)){
399 |
400 | $aKey = array_slice(array_keys($data[0]), 0, 1);
401 | $columnName = $aKey[0];
402 |
403 | foreach($data as $v){
404 | $set[] = $v[$columnName];
405 | }
406 |
407 | }
408 | return $set;
409 | }
410 |
411 | public static function sql2row($sql){
412 | $r = self::q($sql);
413 | if(!$r){
414 | return false;
415 | }
416 | return mysqli_fetch_assoc($r);
417 | }
418 |
419 | public static function sqlNumRows($sql){
420 | $r = self::q($sql);
421 | if(!$r){
422 | return false;
423 | }
424 | return mysqli_num_rows($r);
425 | }
426 |
427 | public static function sql2set_keyval($sql){
428 | $data = self::sql2set($sql);
429 | $set = array();
430 | if(!empty($data)){
431 |
432 | list($firstKey,$secondKey) = array_slice(array_keys($data[0]), 0, 2);
433 | foreach($data as $v){
434 | $set[$v[$firstKey]] = $v[$secondKey];
435 | }
436 | }
437 | return $set;
438 | }
439 |
440 | public static function sql2cell($sql){
441 | $r = self::q($sql);
442 | if(!$r){
443 | return false;
444 | }
445 | $row = mysqli_fetch_assoc($r);
446 | return array_shift($row);
447 | }
448 |
449 | public static function insert($table,$array){
450 | self::q("INSERT INTO $table SET " . self::array2queryPart($array));
451 | return mysqli_insert_id(self::getLink());
452 | }
453 |
454 | public static function wrapInQuotes($string){
455 | $arr = explode(',',$string);
456 | foreach($arr as $k=>$v){
457 | $v = self::e($v);
458 | $arr[$k] = "'$v'";
459 | }
460 | return implode(',',$arr);
461 | }
462 |
463 | public static function array2queryPart($array,$delimiter=','){
464 | $s = '';
465 | foreach($array as $k=>$v){
466 | $s .= $k . "='".self::e($v)."'".$delimiter;
467 | }
468 | $s = substr_replace($s,'',strrpos($s,$delimiter));
469 | return $s;
470 | }
471 |
472 | }
473 | }
474 |
475 |
476 | if (!class_exists('NcRevokeManager')){
477 |
478 | class NcRevokeManager{
479 |
480 | protected $_localCertInfo;
481 | protected $_params;
482 |
483 | public function __construct(NcLocalCertInfo $localCertInfo, array $params) {
484 | $this->_localCertInfo = $localCertInfo;
485 | $this->_params = $params;
486 | }
487 |
488 | public function showButton(){
489 |
490 | if(!$this->_localCertInfo->getRemoteId()){
491 | return false;
492 | }
493 |
494 |
495 | if(!$this->_localCertInfo->loadServerTypes()){
496 | return false;
497 | }
498 |
499 |
500 | /*if('COMODO'!=$this->_localCertInfo->getProvider()){
501 | return false;
502 | }*/
503 |
504 |
505 | if(!$this->getRevokeInfoWasLoaded()){
506 |
507 |
508 | // load revoke info
509 | $certsFromList = $this->loadRevokeInfo();
510 | if(false===$certsFromList){
511 | return false;
512 | }
513 |
514 |
515 | foreach($certsFromList as $item){
516 | $this->addRemoteIdForRevocation($item['CertificateID']);
517 | }
518 |
519 | $this->setRevokeInfoWasLoaded();
520 |
521 | }
522 |
523 | return $this->hasRemoteIdForRevocation();
524 |
525 | }
526 |
527 |
528 | protected function loadRevokeInfo(){
529 |
530 | // 1.1. Get info
531 | $remoteCertInfo = _namecheapssl_getCertificateInfo($this->_params, $this->_localCertInfo->getRemoteId());
532 | if(!$remoteCertInfo){
533 | return false;
534 | }
535 |
536 |
537 | $providerOrderId = $remoteCertInfo['SSLGetInfoResult']['Provider']['OrderID'];
538 |
539 |
540 | // 1.2. Check list, search the same provider order id
541 | $certsFromList = _namecheapssl_searchCertificateInfoInList($this->_params,
542 | array(
543 | 'Status' => 'replaced',
544 | 'ProviderOrderID' => $providerOrderId
545 | ));
546 |
547 | if(false===$certsFromList){
548 | return false;
549 | }
550 |
551 | return $certsFromList;
552 |
553 | }
554 |
555 |
556 | public function hasRemoteIdForRevocation(){
557 | $revokeData = $this->_localCertInfo->getRevokeData();
558 |
559 | if(empty($revokeData['certs'])){
560 | return false;
561 | }
562 |
563 | foreach($revokeData['certs'] as $item){
564 | if(false===$item){
565 | return true;
566 | }
567 | }
568 |
569 | }
570 |
571 |
572 | protected function getRevokeInfoWasLoaded(){
573 | $revokeData = $this->_localCertInfo->getRevokeData();
574 | return isset($revokeData['loaded']);
575 | }
576 |
577 |
578 | protected function setRevokeInfoWasLoaded(){
579 | $revokeData = $this->_localCertInfo->getRevokeData();
580 | $revokeData['loaded'] = true;
581 | $this->_localCertInfo->setRevokeData($revokeData);
582 | }
583 |
584 |
585 | public function addRemoteIdForRevocation($remoteId){
586 | $revokeData = $this->_localCertInfo->getRevokeData();
587 | $revokeData['certs'][$remoteId] = false;
588 | $this->_localCertInfo->setRevokeData($revokeData);
589 | }
590 |
591 |
592 | public function setRemoteIdRevoked($remoteId){
593 | $revokeData = $this->_localCertInfo->getRevokeData();
594 | $revokeData['certs'][$remoteId] = true;
595 | $this->_localCertInfo->setRevokeData($revokeData);
596 | }
597 |
598 | public function getRemoteIdForRevocation(){
599 |
600 | $revokeData = $this->_localCertInfo->getRevokeData();
601 | $ids = array();
602 |
603 | if(empty($revokeData['certs'])){
604 | return $ids;
605 | }
606 |
607 | foreach($revokeData['certs'] as $remoteId=>$bRevoked){
608 | if(false===$bRevoked){
609 | $ids[] = $remoteId;
610 | }
611 | }
612 |
613 | return $ids;
614 |
615 | }
616 |
617 |
618 | }
619 |
620 |
621 |
622 | }
623 |
624 |
625 | if (!class_exists('NcLocalCertInfo')){
626 |
627 | class NcLocalCertInfo{
628 |
629 | const EXCEPTION_SSL_LIST_IS_EMPTY = 'SSL types list is empty';
630 |
631 | const CERTIFICATE_VALIDATION_TYPE_EV = 'ev';
632 | const CERTIFICATE_VALIDATION_TYPE_OV = 'ov';
633 | const CERTIFICATE_VALIDATION_TYPE_DOMAIN = 'domain';
634 |
635 |
636 | const PROVIDER_COMODO = 'COMODO';
637 | const PROVIDER_GEOTRUST = 'GEOTRUST';
638 | const PROVIDER_VERISIGN = 'VERISIGN';
639 | const PROVIDER_THAWTE = 'THAWTE';
640 |
641 |
642 | protected $_nativeRow;
643 | protected $_customRow;
644 |
645 | protected static $_namecheapSSLTypesAdvanced;
646 |
647 | public function __construct($serviceId) {
648 | $this->_nativeRow = NcSql::sql2row(" SELECT * FROM tblsslorders WHERE serviceid='".(int)$serviceId."' ");
649 | if($this->_nativeRow){
650 | $this->_customRow = NcSql::sql2row(" SELECT * FROM mod_namecheapssl WHERE id='" . (int)$this->_nativeRow['id'] . "' ");
651 | }
652 | }
653 |
654 | public function getType(){
655 | return $this->_nativeRow['certtype'];
656 | }
657 |
658 | public function getRemoteId(){
659 | return $this->_nativeRow['remoteid'];
660 | }
661 |
662 | public function inReissueState(){
663 | return (bool)$this->_customRow['reissue'];
664 | }
665 |
666 | public function hasFileName(){
667 | return !empty($this->_customRow['file_name']);
668 | }
669 |
670 | public function getConfigData($backuped=false){
671 |
672 | $configdata = $backuped ? $this->_customRow['configdata_copy'] : $this->_nativeRow['configdata'];
673 |
674 | $result = unserialize($configdata);
675 | if(false==$result){
676 | $result = unserialize(str_replace("\n", "\r\n", $configdata));
677 | }
678 | return $result;
679 |
680 | }
681 |
682 |
683 | public function getRevokeData(){
684 | $revokeData = array();
685 | if(!empty($this->_customRow['revoke_data'])){
686 | $revokeData = unserialize($this->_customRow['revoke_data']);
687 | }
688 | return $revokeData;
689 | }
690 |
691 | public function setRevokeData($revokeData){
692 |
693 | $serializedRevokeData = serialize($revokeData);
694 | $this->_customRow['revoke_data'] = $serializedRevokeData;
695 |
696 | $sql = "UPDATE mod_namecheapssl SET revoke_data='".NcSql::e($serializedRevokeData)."' WHERE id='" . (int)$this->_customRow['id'] . "'";
697 | NcSql::q($sql);
698 |
699 | }
700 |
701 |
702 | public function loadServerTypes(){
703 | self::$_namecheapSSLTypesAdvanced = namecheapssl_getSslTypes(true);
704 | if(!self::$_namecheapSSLTypesAdvanced){
705 | return false;
706 | }else{
707 | return true;
708 | }
709 | }
710 |
711 | public function getProvider(){
712 |
713 | if(empty(self::$_namecheapSSLTypesAdvanced)){
714 | throw new NamecheapApiException(self::EXCEPTION_SSL_LIST_IS_EMPTY);
715 | }
716 |
717 | foreach(self::$_namecheapSSLTypesAdvanced as $info){
718 | if( strtolower($info['Type']) == strtolower($this->_nativeRow['certtype']) ){
719 | return strtoupper($info['Provider']);
720 | }
721 | }
722 |
723 | }
724 |
725 |
726 | public function getValidationType(){
727 | if(empty(self::$_namecheapSSLTypesAdvanced)){
728 | throw new NamecheapApiException(self::EXCEPTION_SSL_LIST_IS_EMPTY);
729 | }
730 |
731 | foreach(self::$_namecheapSSLTypesAdvanced as $info){
732 | if( strtolower($info['Type']) == strtolower($this->_nativeRow['certtype']) ){
733 | $type = strtolower($info['ValidationType']);
734 | if('org'=== substr($type, 0,3)){
735 | return self::CERTIFICATE_VALIDATION_TYPE_OV;
736 | }
737 | if('ext'=== substr($type, 0,3)){
738 | return self::CERTIFICATE_VALIDATION_TYPE_EV;
739 | }
740 | return self::CERTIFICATE_VALIDATION_TYPE_DOMAIN;
741 | }
742 | }
743 | }
744 |
745 |
746 | public function backupConfigData(){
747 | if(empty($this->_customRow['configdata_copy'])){
748 | $sql = "UPDATE mod_namecheapssl SET configdata_copy='".NcSql::e($this->_nativeRow['configdata'])."' WHERE id='" . (int)$this->_customRow['id'] . "'";
749 | NcSql::q($sql);
750 | $this->_customRow['configdata_copy'] = $this->_nativeRow['configdata'];
751 | }
752 | }
753 |
754 | public function clearBackupedConfigData(){
755 | $sql = "UPDATE mod_namecheapssl SET configdata_copy='' WHERE id='" . (int)$this->_customRow['id'] . "'";
756 | NcSql::q($sql);
757 | }
758 |
759 |
760 |
761 | }
762 |
763 | }
764 |
765 |
766 | /**
767 | * NamecheapApiException
768 | */
769 | if (!class_exists("NamecheapApiException")) {
770 | class NamecheapApiException extends Exception {}
771 | }
772 |
773 |
--------------------------------------------------------------------------------
/modules/servers/namecheapssl/namecheaplog.php:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/modules/servers/namecheapssl/reissue_notice.tpl:
--------------------------------------------------------------------------------
1 |