/** * Copyright (C) 2010-2017 Structr GmbH * * This file is part of Structr <http://structr.org>. * * Structr is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * Structr 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Structr. If not, see <http://www.gnu.org/licenses/>. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.structr.payment.entity; import java.util.LinkedList; import java.util.List; import org.structr.common.View; import org.structr.common.error.ErrorBuffer; import org.structr.common.error.FrameworkException; import org.structr.core.Export; import org.structr.core.GraphObject; import org.structr.core.GraphObjectMap; import org.structr.core.entity.AbstractNode; import org.structr.core.property.EndNodes; import org.structr.core.property.EnumProperty; import org.structr.core.property.Property; import org.structr.core.property.StringProperty; import org.structr.payment.api.APIError; import org.structr.payment.api.APIResponse; import org.structr.payment.api.BeginCheckoutResponse; import org.structr.payment.api.CheckoutState; import org.structr.payment.api.ConfirmCheckoutResponse; import org.structr.payment.api.Payment; import org.structr.payment.api.PaymentItem; import org.structr.payment.api.PaymentProvider; import org.structr.payment.api.PaymentState; import org.structr.payment.impl.paypal.PayPalErrorToken; import org.structr.payment.impl.paypal.PayPalPaymentProvider; import org.structr.payment.impl.stripe.StripePaymentProvider; import org.structr.schema.SchemaService; /** * */ public class PaymentNode extends AbstractNode implements Payment { static { SchemaService.registerBuiltinTypeOverride("PaymentNode", PaymentNode.class.getName()); } public static final Property<List<PaymentItemNode>> items = new EndNodes<>("items", PaymentItems.class); public static final Property<PaymentState> stateProperty = new EnumProperty("state", PaymentState.class).indexed(); public static final Property<String> descriptionProperty = new StringProperty("description").indexed(); public static final Property<String> currencyProperty = new StringProperty("currency").indexed(); public static final Property<String> tokenProperty = new StringProperty("token").indexed(); public static final Property<String> billingAgreementId = new StringProperty("billingAgreementId"); public static final Property<String> note = new StringProperty("note"); public static final Property<String> billingAddressName = new StringProperty("billingAddressName"); public static final Property<String> billingAddressStreet1 = new StringProperty("billingAddressStreet1"); public static final Property<String> billingAddressStreet2 = new StringProperty("billingAddressStreet2"); public static final Property<String> billingAddressZip = new StringProperty("billingAddressZip"); public static final Property<String> billingAddressCity = new StringProperty("billingAddressCity"); public static final Property<String> billingAddressCountry = new StringProperty("billingAddressCountry"); public static final Property<String> invoiceId = new StringProperty("invoiceId"); public static final Property<String> payerAddressName = new StringProperty("payerAddressName"); public static final Property<String> payerAddressStreet1 = new StringProperty("payerAddressStreet1"); public static final Property<String> payerAddressStreet2 = new StringProperty("payerAddressStreet2"); public static final Property<String> payerAddressZip = new StringProperty("payerAddressZip"); public static final Property<String> payerAddressCity = new StringProperty("payerAddressCity"); public static final Property<String> payerAddressCountry = new StringProperty("payerAddressCountry"); public static final Property<String> payer = new StringProperty("payer"); public static final Property<String> payerBusiness = new StringProperty("payerBusiness"); public static final View publicView = new View(PaymentNode.class, "public", descriptionProperty, items, currencyProperty, tokenProperty, stateProperty, billingAgreementId, note, billingAddressName, billingAddressStreet1, billingAddressStreet2, billingAddressZip, billingAddressCity, billingAddressCountry, invoiceId, payerAddressName, payerAddressStreet1, payerAddressStreet2, payerAddressZip, payerAddressCity, payerAddressCountry, payer, payerBusiness ); public static final View uiView = new View(PaymentNode.class, "ui", descriptionProperty, items, currencyProperty, tokenProperty, stateProperty, billingAgreementId, note, billingAddressName, billingAddressStreet1, billingAddressStreet2, billingAddressZip, billingAddressCity, billingAddressCountry, invoiceId, payerAddressName, payerAddressStreet1, payerAddressStreet2, payerAddressZip, payerAddressCity, payerAddressCountry, payer, payerBusiness ); @Export public GraphObject beginCheckout(final String providerName, final String successUrl, final String cancelUrl) throws FrameworkException { final PaymentProvider provider = getPaymentProvider(providerName); if (provider != null) { final BeginCheckoutResponse response = provider.beginCheckout(this, successUrl, cancelUrl); if (CheckoutState.Success.equals(response.getCheckoutState())) { final GraphObjectMap data = new GraphObjectMap(); data.put(tokenProperty, response.getToken()); return data; } else { throwErrors("Unable to begin checkout.", response); } } else { throw new FrameworkException(422, "Payment provider " + providerName + " not found."); } return null; } @Export public void cancelCheckout(final String providerName, final String token) throws FrameworkException { final PaymentProvider provider = getPaymentProvider(providerName); if (provider != null) { provider.cancelCheckout(this); } else { throw new FrameworkException(422, "Payment provider " + providerName + " not found."); } } @Export public GraphObject confirmCheckout(final String providerName, final String notifyUrl, final String token, final String payerId) throws FrameworkException { final PaymentProvider provider = getPaymentProvider(providerName); if (provider != null) { final ConfirmCheckoutResponse response = provider.confirmCheckout(this, notifyUrl, token, payerId); if (CheckoutState.Success.equals(response.getCheckoutState())) { // no return value neccessary, will result in code 200 return null; } else { throwErrors("Unable to confirm checkout.", response); } } else { throw new FrameworkException(422, "Payment provider " + providerName + " not found."); } return null; } // ----- interface Payment ----- @Override public List<PaymentItem> getItems() { return new LinkedList<>(getProperty(items)); } @Override public int getTotal() { int total = 0; for (final PaymentItem item : getItems()) { total += item.getAmount() * item.getQuantity(); } return total; } @Override public String getCurrencyCode() { return getProperty(currencyProperty); } @Override public String getToken() { return getProperty(tokenProperty); } @Override public void setToken(String token) throws FrameworkException { setProperty(tokenProperty, token); } // ----- private methods ----- private PaymentProvider getPaymentProvider(final String providerName) { switch (providerName) { case "paypal": return new PayPalPaymentProvider(); case "stripe": return new StripePaymentProvider(); } return null; } private void throwErrors(final String cause, final APIResponse response) throws FrameworkException { final ErrorBuffer errorBuffer = new ErrorBuffer(); for (final APIError error : response.getErrors()) { errorBuffer.add(new PayPalErrorToken(PaymentNode.class.getSimpleName(), AbstractNode.base, error.getErrorCode(), error.getLongMessage())); } throw new FrameworkException(422, cause, errorBuffer); } @Override public String getDescription() { return getProperty(descriptionProperty); } @Override public void setDescription(final String description) throws FrameworkException { setProperty(descriptionProperty, description); } @Override public PaymentState getPaymentState() { return getProperty(stateProperty); } @Override public void setPaymentState(final PaymentState state) throws FrameworkException { setProperty(stateProperty, state); } @Override public String getBillingAddressName() { return getProperty(billingAddressName); } @Override public void setBillingAddressName(final String billingAddressName) throws FrameworkException { setProperty(PaymentNode.billingAddressName, billingAddressName); } @Override public String getBillingAddressStreet1() { return getProperty(PaymentNode.billingAddressStreet1); } @Override public void setBillingAddressStreet1(final String billingAddressStreet1) throws FrameworkException { setProperty(PaymentNode.billingAddressStreet1, billingAddressStreet1); } @Override public String getBillingAddressStreet2() { return getProperty(PaymentNode.billingAddressStreet2); } @Override public void setBillingAddressStreet2(final String billingAddressStreet2) throws FrameworkException { setProperty(PaymentNode.billingAddressStreet2, billingAddressStreet2); } @Override public String getBillingAddressZip() { return getProperty(PaymentNode.billingAddressZip); } @Override public void setBillingAddressZip(final String billingAddressZip) throws FrameworkException { setProperty(PaymentNode.billingAddressZip, billingAddressZip); } @Override public String getBillingAddressCity() { return getProperty(PaymentNode.billingAddressCity); } @Override public void setBillingAddressCity(final String billingAddressCity) throws FrameworkException { setProperty(PaymentNode.billingAddressCity, billingAddressCity); } @Override public String getBillingAddressCountry() { return getProperty(PaymentNode.billingAddressCountry); } @Override public void setBillingAddressCountry(final String billingAddressCountry) throws FrameworkException { setProperty(PaymentNode.billingAddressCountry, billingAddressCountry); } @Override public String getPayer() { return getProperty(PaymentNode.payer); } @Override public void setPayer(final String payer) throws FrameworkException { setProperty(PaymentNode.payer, payer); } @Override public String getPayerBusiness() { return getProperty(PaymentNode.payerBusiness); } @Override public void setPayerBusiness(final String payerBusiness) throws FrameworkException { setProperty(PaymentNode.payerBusiness, payerBusiness); } @Override public String getPayerAddressName() { return getProperty(PaymentNode.payerAddressName); } @Override public void setPayerAddressName(final String payerAddressName) throws FrameworkException { setProperty(PaymentNode.payerAddressName, payerAddressName); } @Override public String getPayerAddressStreet1() { return getProperty(PaymentNode.payerAddressStreet1); } @Override public void setPayerAddressStreet1(final String payerAddressStreet1) throws FrameworkException { setProperty(PaymentNode.payerAddressStreet1, payerAddressStreet1); } @Override public String getPayerAddressStreet2() { return getProperty(PaymentNode.payerAddressStreet2); } @Override public void setPayerAddressStreet2(final String payerAddressStreet2) throws FrameworkException { setProperty(PaymentNode.payerAddressStreet2, payerAddressStreet2); } @Override public String getPayerAddressZip() { return getProperty(PaymentNode.payerAddressZip); } @Override public void setPayerAddressZip(final String payerAddressZip) throws FrameworkException { setProperty(PaymentNode.payerAddressZip, payerAddressZip); } @Override public String getPayerAddressCity() { return getProperty(PaymentNode.payerAddressCity); } @Override public void setPayerAddressCity(final String payerAddressCity) throws FrameworkException { setProperty(PaymentNode.payerAddressCity, payerAddressCity); } @Override public String getPayerAddressCountry() { return getProperty(PaymentNode.payerAddressCountry); } @Override public void setPayerAddressCountry(final String payerAddressCountry) throws FrameworkException { setProperty(PaymentNode.payerAddressCountry, payerAddressCountry); } @Override public String getBillingAgreementId() { return getProperty(PaymentNode.billingAgreementId); } @Override public void setBillingAgreementId(final String billingAgreementId) throws FrameworkException { setProperty(PaymentNode.billingAgreementId, billingAgreementId); } @Override public String getNote() { return getProperty(PaymentNode.note); } @Override public void setNote(final String note) throws FrameworkException { setProperty(PaymentNode.note, note); } @Override public String getInvoiceId() { return getProperty(PaymentNode.invoiceId); } @Override public void setInvoiceId(final String invoiceId) throws FrameworkException { setProperty(PaymentNode.invoiceId, invoiceId); } }