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 -ie 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.
