com.muk.services.api.impl.StripePaymentService.java Source code

Java tutorial

Introduction

Here is the source code for com.muk.services.api.impl.StripePaymentService.java

Source

/*******************************************************************************
 * Copyright (C)  2018  mizuuenikaze inc
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package com.muk.services.api.impl;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.inject.Inject;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.Cache;
import org.springframework.cache.Cache.ValueWrapper;
import org.springframework.cache.CacheManager;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.databind.JsonNode;
import com.muk.ext.security.KeystoreService;
import com.muk.ext.security.NonceService;
import com.muk.services.api.PaymentService;
import com.muk.services.api.SecurityConfigurationService;
import com.muk.services.exchange.ServiceConstants;

import net.thisptr.jackson.jq.JsonQuery;
import net.thisptr.jackson.jq.exception.JsonQueryException;

public class StripePaymentService implements PaymentService {
    private static final Logger LOG = LoggerFactory.getLogger(StripePaymentService.class);

    @Inject
    private CacheManager cacheManager;

    @Inject
    @Qualifier("genericRestTemplate")
    private RestTemplate restTemplate;

    @Inject
    @Qualifier("hashService")
    private NonceService nonceService;

    @Inject
    @Qualifier("securityConfigurationService")
    private SecurityConfigurationService securityCfgService;

    @Inject
    @Qualifier("generalKeystoreService")
    private KeystoreService keystoreService;

    @Override
    public Map<String, Object> startPayment(JsonNode payload) {
        final Map<String, Object> response = new HashMap<String, Object>();
        final ResponseEntity<JsonNode> paymentResponse = send("/charges", payload);

        try {
            final JsonQuery jqError = JsonQuery.compile(".failure_code, .failure_message");
            final List<JsonNode> errorNodes = jqError.apply(paymentResponse.getBody());

            if (errorNodes.get(0).isNull()) {
                final JsonQuery jq = JsonQuery.compile(
                        "{paymentId: .id, state: if .captured then \"created\" else \"not captured\" end }");
                final List<JsonNode> nodes = jq.apply(paymentResponse.getBody());
                response.put("json", nodes.get(0));
            } else {
                response.put("error", errorNodes.get(0).asText() + ": " + errorNodes.get(1).asText());
            }
        } catch (final JsonQueryException jsonEx) {
            LOG.error("failed jq", jsonEx);
            response.put("error", jsonEx.getMessage());
        }

        return response;
    }

    @Override
    public Map<String, Object> commitPayment(String paymentId, String payerId) {
        throw new UnsupportedOperationException();
    }

    private String getTokenHeader() {
        final Cache cache = cacheManager.getCache(ServiceConstants.CacheNames.paymentApiTokenCache);
        final String token = "stripe";
        ValueWrapper valueWrapper = cache.get(token);
        String cachedHeader = StringUtils.EMPTY;

        if (valueWrapper == null || valueWrapper.get() == null) {
            try {
                final String value = keystoreService.getPBEKey(securityCfgService.getStripeClientId());

                cache.put(token, value);
                valueWrapper = cache.get(token);
                cachedHeader = (String) valueWrapper.get();
            } catch (final IOException ioEx) {
                LOG.error("Failed read keystore", ioEx);
                cachedHeader = StringUtils.EMPTY;
            } catch (final GeneralSecurityException secEx) {
                LOG.error("Failed to get key", secEx);
                cachedHeader = StringUtils.EMPTY;
            }
        } else {
            cachedHeader = (String) valueWrapper.get();
        }

        return "Bearer " + cachedHeader;
    }

    private ResponseEntity<JsonNode> send(String path, JsonNode payload) {
        final HttpHeaders headers = new HttpHeaders();

        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add(HttpHeaders.AUTHORIZATION, getTokenHeader());

        final MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
        final Iterator<Entry<String, JsonNode>> nodes = payload.fields();

        while (nodes.hasNext()) {
            final Map.Entry<String, JsonNode> entry = nodes.next();

            if (entry.getValue().isObject()) {
                final String key = entry.getKey();
                final Iterator<Entry<String, JsonNode>> metadataNodes = entry.getValue().fields();

                while (metadataNodes.hasNext()) {
                    final Map.Entry<String, JsonNode> element = metadataNodes.next();
                    body.add(key + "[\"" + element.getKey() + "\"]", element.getValue().asText());
                }
            } else {
                body.add(entry.getKey(), entry.getValue().asText());
            }
        }

        return restTemplate.postForEntity(securityCfgService.getStripeUri() + path,
                new HttpEntity<MultiValueMap<String, String>>(body, headers), JsonNode.class);
    }

}