org.esupportail.papercut.services.PayBoxService.java Source code

Java tutorial

Introduction

Here is the source code for org.esupportail.papercut.services.PayBoxService.java

Source

/**
 * Licensed to EsupPortail under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 *
 * EsupPortail licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.esupportail.papercut.services;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.esupportail.papercut.domain.PayBoxForm;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Scheduled;

public class PayBoxService {

    private final Logger log = Logger.getLogger(getClass());

    private final static String retourVariables = "montant:M;reference:R;auto:A;erreur:E;idtrans:S;signature:K";

    private String numCommandePrefix = "EsupPaperCut-";

    private HashService hashService;

    private String site;

    private String rang;

    private String identifiant;

    // 978 = Euro
    private String devise;

    private List<String> payboxActionUrls;

    private List<String> payboxServersIP;

    private PublicKey payboxPublicKey;

    private String reponseServerUrl;

    private String payboxActionUrlOK = null;

    public String getNumCommandePrefix() {
        return numCommandePrefix;
    }

    public void setNumCommandePrefix(String numCommandePrefix) {
        this.numCommandePrefix = numCommandePrefix;
    }

    public void setHashService(HashService hashService) {
        this.hashService = hashService;
    }

    public void setSite(String site) {
        this.site = site;
    }

    public void setRang(String rang) {
        this.rang = rang;
    }

    public void setIdentifiant(String identifiant) {
        this.identifiant = identifiant;
    }

    public void setDevise(String devise) {
        this.devise = devise;
    }

    public void setPayboxActionUrls(List<String> payboxActionUrls) {
        this.payboxActionUrls = payboxActionUrls;
    }

    public void setPayboxServersIP(List<String> payboxServersIP) {
        this.payboxServersIP = payboxServersIP;
    }

    public void setDerPayboxPublicKeyFile(String derPayboxPublicKeyFile)
            throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
        org.springframework.core.io.Resource derPayboxPublicKeyRessource = new ClassPathResource(
                derPayboxPublicKeyFile);
        InputStream fis = derPayboxPublicKeyRessource.getInputStream();
        DataInputStream dis = new DataInputStream(fis);
        byte[] pubKeyBytes = new byte[fis.available()];
        dis.readFully(pubKeyBytes);
        fis.close();
        dis.close();
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(pubKeyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        this.payboxPublicKey = kf.generatePublic(x509EncodedKeySpec);
    }

    public void setReponseServerUrl(String reponseServerUrl) {
        this.reponseServerUrl = reponseServerUrl;
    }

    /**
     * @param uid
     * @param montant en 
     * @return
     */
    public PayBoxForm getPayBoxForm(String uid, String mail, double montant, String paperCutContext,
            String portletContextPath) {

        String montantAsCents = Integer.toString(new Double(montant * 100).intValue());

        PayBoxForm payBoxForm = new PayBoxForm();
        payBoxForm.setActionUrl(getPayBoxActionUrl());
        payBoxForm.setClientEmail(mail);
        payBoxForm.setCommande(getNumCommande(uid, montantAsCents, paperCutContext));
        payBoxForm.setDevise(devise);
        payBoxForm.setHash(hashService.getHash());
        payBoxForm.setIdentifiant(identifiant);
        payBoxForm.setRang(rang);
        payBoxForm.setRetourVariables(retourVariables);
        payBoxForm.setSite(site);
        payBoxForm.setTime(getCurrentTime());
        payBoxForm.setTotal(montantAsCents);

        String callbackUrl = reponseServerUrl + "/esup-papercut/servlet/payboxcallback";
        payBoxForm.setCallbackUrl(callbackUrl);

        String forwardUrl = reponseServerUrl + portletContextPath;
        payBoxForm.setForwardAnnuleUrl(forwardUrl);
        payBoxForm.setForwardEffectueUrl(forwardUrl);
        payBoxForm.setForwardRefuseUrl(forwardUrl);

        String hMac = hashService.getHMac(payBoxForm.getParamsAsString());
        payBoxForm.setHmac(hMac);

        return payBoxForm;
    }

    private String getNumCommande(String uid, String montantAsCents, String paperCutContext) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-S");
        return numCommandePrefix + uid + "@" + paperCutContext + "@" + montantAsCents + "-" + df.format(new Date());
    }

    protected String getPayBoxActionUrl() {
        if (payboxActionUrlOK == null) {
            updatePayBoxActionUrl();
        }
        return this.payboxActionUrlOK;
    }

    /**
     * @return current UTC Time - ISO 8601 format
     */
    protected String getCurrentTime() {
        TimeZone tz = TimeZone.getTimeZone("UTC");
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
        df.setTimeZone(tz);
        String nowAsISO = df.format(new Date());
        return nowAsISO;
    }

    public boolean isPayboxServer(String ip) {

        if (ip == null || !payboxServersIP.contains(ip)) {
            log.info(ip + " is not a paybox server");
            return false;
        } else {
            log.info(ip + " is a paybox server");
            return true;
        }
    }

    public boolean checkPayboxSignature(String queryString, String signature) {

        String sData = queryString.substring(0, queryString.lastIndexOf("&"));

        try {
            Signature sig = Signature.getInstance("SHA1WithRSA");
            byte[] sigBytes = Base64.decodeBase64(signature.getBytes());
            sig.initVerify(payboxPublicKey);
            sig.update(sData.getBytes());
            boolean signatureOk = sig.verify(sigBytes);
            if (!signatureOk) {
                log.error("Erreur lors de la vrification de la signature, les donnes ne correspondent pas.");
                log.error(sData);
                log.error(signature);
            }
            return signatureOk;
        } catch (Exception e) {
            log.warn("Pb when checking SSL signature of Paybox", e);
            return false;
        }
    }

    @Scheduled(fixedDelay = 3600000)
    public void flushPayboxActionUrlOK() {
        updatePayBoxActionUrl();
        log.info("Update Paybox Action Url: " + this.payboxActionUrlOK);
    }

    public void updatePayBoxActionUrl() {
        for (String payboxActionUrl : payboxActionUrls) {
            try {
                // on teste la connection, pour voir si le serveur est disponible
                URL url = new URL(payboxActionUrl);
                URLConnection connection = url.openConnection();
                connection.connect();
                connection.getInputStream().read();
                this.payboxActionUrlOK = payboxActionUrl;
            } catch (Exception e) {
                log.warn("Pb with " + payboxActionUrl, e);
            }
        }
        if (this.payboxActionUrlOK == null) {
            throw new RuntimeException("No paybox action url is available at the moment !");
        }
    }

}