U ovom blog postu možete saznati kako implementirati CorvusPay kartično plaćanje koristeći Node.js tj. Express.js i Angular Framework.
Kartično plaćanje provodi se kroz Corvus Form Service što znači da korisnik nakon odabira artikala bude preusmjeren na URL za autorizaciju kreditne kartice. Na tom URL-u ispunjava se obrazac s potrebnim podacima o kreditnoj kartici nakon čega korisnik ponovno bude preusmjeren na web shop gdje se najčešće prikazuje poruka o ne/uspješnoj kupovini.
Tijek transakcije kroz CorvusPay sustav odvija se na sljedeći način:
- Kupac u web trgovini odabire proizvod ili uslugu koju želi platiti karticom.
- Kupac se preusmjerava sa stranice trgovca na CorvusPay platnu formu (stranicu) gdje unosi podatke potrebne za realizaciju kartične transakcije.
- CorvusPay šalje banci zahtjev za autorizacijom.
- Banka šalje odgovor na zahtjev za autorizacijom na CorvusPay.
- CorvusPay preusmjerava kupca na cancel ili success url kojeg definira trgovac ovisno o ishodu transakcije.
Moguća je i integracija tog obrasca unutar web shopa, ali u tom slučaju trgovac mora imati PCI DSS certifikat.
Tijek implementacije
Proces se istovremeno odvija u dva smjera. Prvi se tiče administrativnih poslova u kojima Corvus od trgovca prikuplja potrebnu dokumentaciju za pokretanje procesa aktivacije kartičnog plaćanje koju prosljeđuje prema bankama/kartičnim kućama.
Paralelno trgovac (web shop) postavlja obavezan sadržaj na web trgovinu (uvjeti korištenja i plaćanja, logo CorvusPaya,…), vrši implementaciju prema dostupnim uputama i testira sustav pomoću razvojnog certifikata. Nakon obavljenih testova postavlja se produkcijski certifikat čime se proces implementacije završava.
Uvod
Komunikacija između trgovca i usluge CorvusPay vrši se putem HTTPS POST web zahtjeva.
Svaki web zahtjev prema Corvusu treba obavezno sadržavati tri parametra, a to su:
– Store ID
– Secret Key
– Client Certificate (.p12).
Dobiju se dva seta ovih podataka. Jedan set za testiranje, a drugi za produkciju.
Obavezni CorvusPay parametri
Obavezni parametri su: version, store_id, order_number, language, currency, amount, cart, signature i require_complete.
U slučaju greške pri kreiranju parametara prikazat će se sljedeći ekran:
order_number mora biti jedinstven jer sustav će provjeriti i odbiti svaki upit na Corvus API ako narudžba s istim brojem narudžbe već postoji.
signature se kreira koristeći HMAC-SHA256. On se sastoji od svih obaveznih i opcionalnih vrijednosti (key-value field pairs), poredanih abecedno i spojenih bez razmaka.
To onda izgleda ovako:
1 |
amount10.00cartkindlepaperwhitecurrencyHRKlanguagehrorder_number1537270065109require_completefalsestore_id2029version1.3 |
na osnovu čega se dobije signature
1 |
6cc62fa239555f790b5665d4b002faa5b1d90ded5e4caa3e70d37a4db88d6d51 |
signature = HMAC-256(key, key-value field pairs)
~ ključ: UNV3-i2otJw0rUWzA2lpcNRqTOYRWdAeTw
~ parametri:
– version : 1.3
– store_id : 2029
– order_number : 1537270065109
– amount : 10.00
– currency : HRK
– cart : kindle paperwhite
– require_complete : false
– language : hr
Neobavezni CorvusPay parametri
Osim obaveznih parametara moguće je koristiti i neobavezne. U ovom slučaju to će biti parametri vezani uz plaćanje na rate.
Tri su načina pokretanja transakcije na rate:
• Fiksni broj rata
• Fleksibilan broj rata
• Samostalan odabir rata za određenu karticu
Napomene:
• Ako se za određenu platnu karticu ne pošalje parametar payment_brandName kartica neće biti dostupna za odabir
• Prvi znak parametra payment_
• Posljednja četiri znaka određuju raspon broja rata. Kupac može odabrati broj rata u rasponu između prvog dvoznamenkastog broja i drugog dvoznamenkastog broja
Web aplikacija (Angular)
Unutar forme pomoću POST metode poziva se API za pokretanje kartičnog plaćanja.
Sve navedene vrijednosti su promjenjive tako da ih prilikom svake promjene unutar .ts datoteke treba osvježiti i unutar forme </form>.
Parametri signature i payment_ mogu se kreirati na frontendu i backendu. U ovom slučaju oni će se kreirati na frontendu i prosljeđivati kroz formu na API.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<form [action]="'https://localhost:3000/api/corvus/'" ngNoForm method="POST" target="_self"> <button [disabled]="disableSecondClick" class="btn-pay" type="submit">Plati karticom</button> <div hidden> <input name='order_number' value='{{orderNumber}}'> <input name='amount' value='{{paymentForm.value.amount}}'> <input name='cart' value='{{paymentForm.value.cart}}'> <input name='signature' value='{{paymentForm.value.signature}}'> <input name='payment_visa' value='{{paymentForm.value.payment_visa}}'> <input name='payment_master' value='{{paymentForm.value.payment_master}}'> <input name='payment_maestro' value='{{paymentForm.value.payment_maestro}}'> <input name='payment_diners' value='{{paymentForm.value.payment_diners}}'> </div> </form> |
Za potrebu kreiranja HmacSHA256 potpisa koristi se crypto-js. Uz to, unutar environment varijable nalaze se razvojni i produkcijski parametri secretKey i storeId.
1 2 3 4 5 6 |
import * as crypto from 'crypto-js'; import * as HmacSHA256 from 'crypto-js/hmac-sha256'; import { environment } from './../../environments/environment'; ... |
Glavna razlika u ovom dijelu tiče se ukupne cijene tj. ovisno o tome prelazi li iznos od 500kn plaćanje na rate biti će odobreno ili onemogućeno. U oba slučaja kreira se različit signature.
Za ukupan iznos veći ili jednak 500kn koristi se sljedeće:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
this.value_pairs="amount"+this.amountTotal.toFixed(2)+ "cart"+this.orderedItem+ "currencyHRK"+ "languagehr"+ "order_number"+this.orderNumber+ "payment_all_dynamictrue"+ "payment_dinersY0112"+ "payment_maestroY0112"+ "payment_masterY0112"+ "payment_visaY0112"+"require_completefalse"+ "store_id"+environment.storeId+ "version1.3"; this.signature = HmacSHA256(this.value_pairs,environment.secretKey).toString(crypto.enc.Hex); this.paymentForm.patchValue({ amount: this.amountTotal.toFixed(2), signature: this.signature, payment_visa: 'Y0112', payment_master: 'Y0112', payment_maestro: 'Y0112', payment_diners: 'Y0112' }); |
Dok se za iznose manje od 500kn koristi:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
this.value_pairs="amount"+this.amountTotal.toFixed(2)+ "cart"+this.orderedItem+ "currencyHRK"+ "languagehr"+ "order_number"+this.orderNumber+ "payment_all_dynamictrue"+ "payment_dinersY0000"+ "payment_maestroY0000"+ "payment_masterY0000"+ "payment_visaY0000"+ "require_completefalse"+ "store_id"+environment.storeId+ "version1.3"; this.signature = HmacSHA256(this.value_pairs,environment.secretKey).toString(crypto.enc.Hex); this.paymentForm.patchValue({ amount: this.amountTotal.toFixed(2), signature: this.signature, payment_visa: 'Y0000', payment_master: 'Y0000', payment_maestro: 'Y0000', payment_diners: 'Y0000' }); |
Backend API (Express.js)
Backend logika nalazit će se u server.js datoteci. Kako ju kreirati možete se vidjeti u blog postu “Izrada RESTful API-ja koristeći Node.js i Express.js“. Razlika između primjera iz tog blog posta i ovoga sada je što više nije potrebno koristiti body-parser.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var express = require('express'); var app = express(); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use('/api', apiRoutes); var port = process.env.PORT || 3000; var apiRoutes = express.Router(); apiRoutes.get('/', function(req, res) { res.json({ message: 'CorvusPay API je pokrenut!' }); }); ... app.listen(port); |
Ova će se datoteka sastojati od tri krajnje točke (API endpoints).
Prva krajnja točka, '/corvusPay', preusmjerit će korisnika na formu za plaćanje.
1 2 3 4 5 6 7 8 9 10 11 |
apiRoutes.post('/corvusPay', function(req, res) { if(req.body.order_number && req.body.amount){ res.status(301).redirect(307, 'https://test-wallet.corvuspay.com/checkout/?store_id=2029&order_number='+req.body.order_number+'&language=hr¤cy=HRK&amount='+req.body.amount+'&cart='+req.body.cart+'&signature='+req.body.signature+'&require_complete=false&version=1.3&payment_all_dynamic=true&payment_visa='+req.body.payment_visa+'&payment_master='+req.body.payment_master+'&payment_maestro='+req.body.payment_maestro+'&payment_diners='+req.body.payment_diners) } else { res.json({ success: false, status: 502, message: 'Greška, ne šaljete sve potrebne podatke za plaćanje!' }); } }); |
Nakon unosa i obrade podataka o kartici
korisnik je preusmjeren na dodatnu sigurnosnu autentifikaciju kartice.
Ako je sve prošlo uspješno korisniku će se prikazati obavijest
i na e-mail će dobiti obavijest o uspješnoj narudžbi.
Druga krajnja točka, '/corvusPaySuccess' , prihvaća odgovor od Corvusa kada je plaćanje uspješno provedeno.
1 2 3 4 |
apiRoutes.post('/corvusPaySuccess', function(req, res) { res.status(200).redirect(301, 'https://localhost/success/'+req.body.order_number) ... }); |
Treća krajnja točka, '/corvusPayCancel' , prihvaća odgovor od Corvusa kada je plaćanje neuspješno ili otkazano.
1 2 3 4 |
apiRoutes.post('/corvusPayCancel', function(req, res) { res.status(200).redirect(301, 'https://localhost/cancel/'+req.body.order_number) ... }); |