In questo articolo vedremo come reperire il listato dei prodotti presenti in uno store WooCommerce utilizzando Node.js e le REST API di WooCommerce. Utilizzeremo Ubuntu Server 16.04 con nginx.
Il file package.json
I moduli fondamentali sono ExpressJS e WooCommerce. Gli altri servono unicamente ad implementare le funzioni accessorie della nostra app come ad esempio l'autenticazione.
{
"name": "WCNode",
"version": "1.0.0",
"description": "WCNode",
"author": "Nome Cognome <account@sito.com>",
"dependencies": {
"body-parser": "^1.17.2",
"cookie-parser": "^1.4.1",
"ejs": "^2.5.6",
"express": "^4.15.3",
"helmet": "^2.1.1",
"serve-favicon": "^2.4.3"
"woocommerce": "^2.4.0"
},
"license": "MIT"
}
A questo punto installiamo i moduli:
npm install
Impostazioni per SSL
Creiamo un nuovo set di regole per nginx dopo aver acquisito privilegi di root (sudo -i
e quindi nano /etc/nginx/sites-available/wcnode
):
upstream wcnode {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name wcnode.sito.com;
root /home/wcnode/www;
index index.html;
client_max_body_size 8m;
location / {
try_files $uri @wcnode;
}
location @wcnode {
proxy_pass https://wcnode;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
A questo punto abilitiamo il nuovo set di regole:
ln -s /etc/nginx/sites-available/wcnode /etc/nginx/sites-enabled/wcnode
Se non avete già installato il tool di Let's Encrypt potete farlo come segue: per prima cosa aggiungete la repository:
add-apt-repository ppa:certbot/certbot
Quindi aggiornate l'elenco dei pacchetti:
apt-get update
Infine installate Certbot:
apt-get install python-certbot-nginx
Prima di riavviare nginx, otteniamo un certificato SSL da Let's Encrypt:
certbot --nginx -d wcnode.sito.com
Scegliamo l'opzione 2 durante l'installazione in modo da avere il redirect SSL inserito nel nostro set di regole.
A questo punto copiamo i file del certificato nella directory della nostra app:
cp /etc/letsencrypt/live/wcnode.sito.com/fullchain.pem > /home/wcnode/app/fullchain.pem && chown wcnode:wcnode /home/wcnode/app/fullchain.pem
cp /etc/letsencrypt/live/wcnode.site.com/privkey.pem > /home/wcnode/app/privkey.pem && chown wcnode:wcnode /home/wcnode/app/privkey.pem
Ora dobbiamo creare un nuovo servizio per systemd in modo che l'applicazione sopravviva e sia live al reboot. Digitiamo nano /etc/systemd/system/wcnode.service
e inseriamo i seguenti contenuti:
[Service]
WorkingDirectory=/home/wcnode/app
ExecStart=/usr/local/bin/node app.js
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=wcnode
User=wcnode
Group=wcnode
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
A questo punto abilitiamo il servizio:
systemctl enable wcnode
E lo avviamo:
systemctl start wcnode
Solo ora testiamo la configurazione di nginx:
nginx -t
Se è tutto corretto, lo riavviamo:
systemctl restart nginx
Il codice dell'app
Sostanzialmente viene effettuata una richiesta GET al sito in WooCommerce utilizzando l'endpoint /wp-json/wc/v2/products
con le credenziali di accesso.
Lo scheletro della nostra app è il seguente:
'use strict';
const express = require('express');
const fs = require('fs');
const https = require('https');
const port = process.env.PORT || 3000;
const app = express();
const routes = require('./routes');
const API = require('./lib/API');
const sslOptions = {
key: fs.readFileSync('privkey.pem'),
cert: fs.readFileSync('fullchain.pem')
};
app.disable('x-powered-by');
app.set('view engine', 'ejs');
app.use( (req, res, next ) => {
req.API = API;
next();
});
// Qui le route
app.get('/products', routes.products);
https.createServer(sslOptions, app).listen(port);
La gestione delle chiamate alle API è affidata alla classe API
che abbiamo reso disponibile in tutte le route della nostra app tramite la funzione di middleware definita in .use()
. In questo modo ora l'oggetto request
ha un riferimento a tale classe visibile per tutto il ciclo di vita dell'applicazione.
La classe è molto semplice. Inizia richiedendo il modulo WooCommerce e definendo le opzioni di base:
'use strict';
const WC = require('woocommerce');
const WooCommerce = new WC({
url: 'https://ecommerce.com',
ssl: true,
consumerKey: 'ck_123456789abcd',
secret: 'cs_abcdefg12345'
});
Ora viene il corpo della classe:
class API {
static products() {
return WooCommerce.get('/products');
}
}
module.exports = API;
Il metodo statico products()
restituisce una Promise che può avere due risultati:
- La richiesta ha successo e la Promise si risolve con un array di prodotti in formato JSON.
- La richiesta fallisce e la Promise restituisce un errore generato dal modulo WooCommerce.
Lo usiamo in questo modo nella route specifica:
'use strict';
// routes/index.js
module.exports = {
products: (req, res) => {
req.API.products().then(data => {
res.render('products', {products: data.products});
}).catch(err => {
res.json(err);
});
}
};
Il risultato viene mostrato di seguito.