Skip to content
Snippets Groups Projects
Commit 63f77f3f authored by srosse's avatar srosse
Browse files

OO-5059: implement an alternative Paypal payment with Smart Buttons

parent 3f2c2538
No related branches found
No related tags found
No related merge requests found
Showing
with 757 additions and 36 deletions
...@@ -50,6 +50,12 @@ public interface AccessMethodHandler { ...@@ -50,6 +50,12 @@ public interface AccessMethodHandler {
public boolean isPaymentMethod(); public boolean isPaymentMethod();
/**
*
* @return true if it is technically possible to have 2 methods overlap
*/
public boolean isOverlapAllowed(AccessMethodHandler handler);
public String getType(); public String getType();
public String getMethodName(Locale locale); public String getMethodName(Locale locale);
......
...@@ -58,6 +58,11 @@ public abstract class AutoAccessHandler implements AccessMethodHandler { ...@@ -58,6 +58,11 @@ public abstract class AutoAccessHandler implements AccessMethodHandler {
return false; return false;
} }
@Override
public boolean isOverlapAllowed(AccessMethodHandler handler) {
return true;
}
@Override @Override
public AccessMethodSecurityCallback getSecurityCallback(Identity identity, Roles roles) { public AccessMethodSecurityCallback getSecurityCallback(Identity identity, Roles roles) {
return SYSTEM_AC_SECURITY_CALLBACK; return SYSTEM_AC_SECURITY_CALLBACK;
......
...@@ -63,6 +63,11 @@ public class FreeAccessHandler implements AccessMethodHandler { ...@@ -63,6 +63,11 @@ public class FreeAccessHandler implements AccessMethodHandler {
return false; return false;
} }
@Override
public boolean isOverlapAllowed(AccessMethodHandler handler) {
return true;
}
@Override @Override
public String getType() { public String getType() {
return METHOD_TYPE; return METHOD_TYPE;
......
...@@ -65,6 +65,11 @@ public class PaypalAccessHandler implements AccessMethodHandler { ...@@ -65,6 +65,11 @@ public class PaypalAccessHandler implements AccessMethodHandler {
public boolean isPaymentMethod() { public boolean isPaymentMethod() {
return true; return true;
} }
@Override
public boolean isOverlapAllowed(AccessMethodHandler handler) {
return true;
}
@Override @Override
public String getType() { public String getType() {
......
...@@ -180,7 +180,7 @@ public class PaypalManagerImpl implements PaypalManager { ...@@ -180,7 +180,7 @@ public class PaypalManagerImpl implements PaypalManager {
private PaypalAccessMethod getMethodSecure(Long key) { private PaypalAccessMethod getMethodSecure(Long key) {
PaypalAccessMethod smethod = null; PaypalAccessMethod smethod = null;
List<PaypalAccessMethod> methods = getPaypalMethods(); List<PaypalAccessMethod> methods = getPaypalMethods();
if(methods.size() > 0) { if(!methods.isEmpty()) {
smethod = methods.get(0); smethod = methods.get(0);
} else { } else {
smethod = new PaypalAccessMethod(); smethod = new PaypalAccessMethod();
...@@ -199,11 +199,9 @@ public class PaypalManagerImpl implements PaypalManager { ...@@ -199,11 +199,9 @@ public class PaypalManagerImpl implements PaypalManager {
private List<PaypalAccessMethod> getPaypalMethods() { private List<PaypalAccessMethod> getPaypalMethods() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("select method from ").append(PaypalAccessMethod.class.getName()).append(" method"); sb.append("select method from ").append(PaypalAccessMethod.class.getName()).append(" method");
return dbInstance.getCurrentEntityManager()
List<PaypalAccessMethod> methods = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), PaypalAccessMethod.class) .createQuery(sb.toString(), PaypalAccessMethod.class)
.getResultList(); .getResultList();
return methods;
} }
@Override @Override
...@@ -284,8 +282,7 @@ public class PaypalManagerImpl implements PaypalManager { ...@@ -284,8 +282,7 @@ public class PaypalManagerImpl implements PaypalManager {
query.setParameter("transactionId", transactionId); query.setParameter("transactionId", transactionId);
} }
List<PaypalTransaction> transactions = query.getResultList(); return query.getResultList();
return transactions;
} }
private boolean appendAnd(StringBuilder sb, boolean where) { private boolean appendAnd(StringBuilder sb, boolean where) {
...@@ -643,6 +640,7 @@ public class PaypalManagerImpl implements PaypalManager { ...@@ -643,6 +640,7 @@ public class PaypalManagerImpl implements PaypalManager {
} }
} }
@Override
public PayResponse request(Identity delivery, OfferAccess offerAccess, String mapperUri, String sessionId) { public PayResponse request(Identity delivery, OfferAccess offerAccess, String mapperUri, String sessionId) {
StringBuilder url = new StringBuilder(); StringBuilder url = new StringBuilder();
url.append(Settings.createServerURI()).append(mapperUri); url.append(Settings.createServerURI()).append(mapperUri);
......
...@@ -41,6 +41,7 @@ import org.olat.resource.accesscontrol.model.PSPTransaction; ...@@ -41,6 +41,7 @@ import org.olat.resource.accesscontrol.model.PSPTransaction;
import org.olat.resource.accesscontrol.provider.paypalcheckout.ui.PaypalCheckoutAccessConfigurationController; import org.olat.resource.accesscontrol.provider.paypalcheckout.ui.PaypalCheckoutAccessConfigurationController;
import org.olat.resource.accesscontrol.provider.paypalcheckout.ui.PaypalCheckoutAccessController; import org.olat.resource.accesscontrol.provider.paypalcheckout.ui.PaypalCheckoutAccessController;
import org.olat.resource.accesscontrol.provider.paypalcheckout.ui.PaypalCheckoutTransactionDetailsController; import org.olat.resource.accesscontrol.provider.paypalcheckout.ui.PaypalCheckoutTransactionDetailsController;
import org.olat.resource.accesscontrol.provider.paypalcheckout.ui.PaypalSmartButtonAccessController;
import org.olat.resource.accesscontrol.ui.AbstractConfigurationMethodController; import org.olat.resource.accesscontrol.ui.AbstractConfigurationMethodController;
import org.olat.resource.accesscontrol.ui.FormController; import org.olat.resource.accesscontrol.ui.FormController;
...@@ -60,6 +61,15 @@ public class PaypalCheckoutAccessHandler implements AccessMethodHandler { ...@@ -60,6 +61,15 @@ public class PaypalCheckoutAccessHandler implements AccessMethodHandler {
public boolean isPaymentMethod() { public boolean isPaymentMethod() {
return true; return true;
} }
@Override
public boolean isOverlapAllowed(AccessMethodHandler handler) {
if(handler instanceof PaypalCheckoutAccessHandler) {
PaypalCheckoutModule paypalModule = CoreSpringFactory.getImpl(PaypalCheckoutModule.class);
return !paypalModule.isSmartButtons();
}
return true;
}
@Override @Override
public String getType() { public String getType() {
...@@ -79,7 +89,14 @@ public class PaypalCheckoutAccessHandler implements AccessMethodHandler { ...@@ -79,7 +89,14 @@ public class PaypalCheckoutAccessHandler implements AccessMethodHandler {
@Override @Override
public FormController createAccessController(UserRequest ureq, WindowControl wControl, OfferAccess link, Form form) { public FormController createAccessController(UserRequest ureq, WindowControl wControl, OfferAccess link, Form form) {
if(form == null) { PaypalCheckoutModule paypalModule = CoreSpringFactory.getImpl(PaypalCheckoutModule.class);
if(paypalModule.isSmartButtons()) {
if(form == null) {
return new PaypalSmartButtonAccessController(ureq, wControl, link);
} else {
return new PaypalSmartButtonAccessController(ureq, wControl, link, form);
}
} else if(form == null) {
return new PaypalCheckoutAccessController(ureq, wControl, link); return new PaypalCheckoutAccessController(ureq, wControl, link);
} else { } else {
return new PaypalCheckoutAccessController(ureq, wControl, link, form); return new PaypalCheckoutAccessController(ureq, wControl, link, form);
......
...@@ -27,6 +27,7 @@ import org.olat.resource.accesscontrol.Order; ...@@ -27,6 +27,7 @@ import org.olat.resource.accesscontrol.Order;
import org.olat.resource.accesscontrol.OrderPart; import org.olat.resource.accesscontrol.OrderPart;
import org.olat.resource.accesscontrol.model.PSPTransaction; import org.olat.resource.accesscontrol.model.PSPTransaction;
import org.olat.resource.accesscontrol.provider.paypalcheckout.model.CheckoutRequest; import org.olat.resource.accesscontrol.provider.paypalcheckout.model.CheckoutRequest;
import org.olat.resource.accesscontrol.provider.paypalcheckout.model.CreateSmartOrder;
/** /**
* *
...@@ -40,6 +41,34 @@ public interface PaypalCheckoutManager { ...@@ -40,6 +41,34 @@ public interface PaypalCheckoutManager {
public void updateTransaction(String uuid); public void updateTransaction(String uuid);
/**
* Create an order in OpenOlat and in Paypal, reserve the access
* if needed.
*
* @param delivery The identity which buy the access
* @param offerAccess The offer
* @return The order id or null if the reservation fails
*/
public CreateSmartOrder createOrder(Identity delivery, OfferAccess offerAccess);
/**
*
* @param paypalOrderId The order id of the Paypal order.
*/
public void approveTransaction(String paypalOrderId);
/**
*
* @param paypalOrderId The order id of the Paypal order.
*/
public void cancelTransaction(String paypalOrderId);
/**
*
* @param paypalOrderId The order id of the Paypal order.
*/
public void errorTransaction(String paypalOrderId);
public PaypalCheckoutTransaction loadTransaction(Order order, OrderPart part); public PaypalCheckoutTransaction loadTransaction(Order order, OrderPart part);
......
...@@ -40,6 +40,7 @@ public class PaypalCheckoutModule extends AbstractSpringModule { ...@@ -40,6 +40,7 @@ public class PaypalCheckoutModule extends AbstractSpringModule {
private static final String PAYPAL_CLIENT_ID = "paypal.checkout.v2.client.id"; private static final String PAYPAL_CLIENT_ID = "paypal.checkout.v2.client.id";
private static final String PAYPAL_CLIENT_SECRET = "paypal.checkout.v2.client.secret"; private static final String PAYPAL_CLIENT_SECRET = "paypal.checkout.v2.client.secret";
private static final String PAYPAL_CURRENCY = "paypal.checkout.v2.currency"; private static final String PAYPAL_CURRENCY = "paypal.checkout.v2.currency";
private static final String PAYPAL_SMART_BUTTONS = "paypal.checkout.v2.smart.buttons";
private static final String[] currencies = new String[] { private static final String[] currencies = new String[] {
"AUD", "AUD",
...@@ -74,6 +75,8 @@ public class PaypalCheckoutModule extends AbstractSpringModule { ...@@ -74,6 +75,8 @@ public class PaypalCheckoutModule extends AbstractSpringModule {
private boolean sandbox; private boolean sandbox;
@Value("${paypal.checkout.v2.currency:CHF}") @Value("${paypal.checkout.v2.currency:CHF}")
private String paypalCurrency; private String paypalCurrency;
@Value("${paypal.checkout.v2.smart.buttons:true}")
private boolean smartButtons;
@Autowired @Autowired
public PaypalCheckoutModule(CoordinatorManager coordinatorManager) { public PaypalCheckoutModule(CoordinatorManager coordinatorManager) {
...@@ -90,6 +93,7 @@ public class PaypalCheckoutModule extends AbstractSpringModule { ...@@ -90,6 +93,7 @@ public class PaypalCheckoutModule extends AbstractSpringModule {
clientId = getStringPropertyValue(PAYPAL_CLIENT_ID, clientId); clientId = getStringPropertyValue(PAYPAL_CLIENT_ID, clientId);
clientSecret = getStringPropertyValue(PAYPAL_CLIENT_SECRET, clientSecret); clientSecret = getStringPropertyValue(PAYPAL_CLIENT_SECRET, clientSecret);
paypalCurrency = getStringPropertyValue(PAYPAL_CURRENCY, paypalCurrency); paypalCurrency = getStringPropertyValue(PAYPAL_CURRENCY, paypalCurrency);
smartButtons = "true".equals(getStringPropertyValue(PAYPAL_SMART_BUTTONS, Boolean.toString(smartButtons)));
} }
public String getClientId() { public String getClientId() {
...@@ -122,7 +126,16 @@ public class PaypalCheckoutModule extends AbstractSpringModule { ...@@ -122,7 +126,16 @@ public class PaypalCheckoutModule extends AbstractSpringModule {
this.paypalCurrency = currency; this.paypalCurrency = currency;
setStringProperty(PAYPAL_CURRENCY, currency, true); setStringProperty(PAYPAL_CURRENCY, currency, true);
} }
public boolean isSmartButtons() {
return smartButtons;
}
public void setSmartButtons(boolean smartButtons) {
this.smartButtons = smartButtons;
setStringProperty(PAYPAL_SMART_BUTTONS, Boolean.toString(smartButtons), true);
}
public boolean isSandbox() { public boolean isSandbox() {
return sandbox; return sandbox;
} }
......
...@@ -77,33 +77,54 @@ public class CheckoutV2Provider { ...@@ -77,33 +77,54 @@ public class CheckoutV2Provider {
@Autowired @Autowired
private PaypalCheckoutTransactionDAO transactionDao; private PaypalCheckoutTransactionDAO transactionDao;
public PaypalCheckoutTransaction createOrder(org.olat.resource.accesscontrol.Order order, PaypalCheckoutTransaction trx) {
ApplicationContext applicationContext = new ApplicationContext();
OrderRequest orderRequest = buildOrderRequest(order, "AUTHORIZE", applicationContext);
OrdersCreateRequest request = buildOrdersCreateRequest(orderRequest);
try {
HttpResponse<Order> orderResponse = client().execute(request);
if (orderResponse.statusCode() == 201) {
Order paypalOrder = orderResponse.result();
trx.setPaypalOrderId(paypalOrder.id());
trx.setPaypalOrderStatus(paypalOrder.status());
trx.setStatus(PaypalCheckoutStatus.INPROCESS);
log.info(Tracing.M_AUDIT, "Create Paypal order: id:{} status:{}", paypalOrder.id(), paypalOrder.status());
for (LinkDescription link : orderResponse.result().links()) {
log.debug("Create Paypal link: rel:{} href:{}", link.rel(), link.href());
log.debug("Create Paypal link: rel:{} media:{} for schema:{}", link.rel(), link.mediaType(),
link.schema());
}
} else {
log.error(Tracing.M_AUDIT, "Create Paypal order status:{}", orderResponse.statusCode());
}
} catch (HttpException e) {
JSONObject message = new JSONObject(e.getMessage());
log.error(Tracing.M_AUDIT, prettyPrint(message, ""));
log.error(Tracing.M_AUDIT, "Create Paypal order", e);
trx.setStatus(PaypalCheckoutStatus.ERROR);
trx.setPaypalOrderStatus(PaypalCheckoutStatus.ERROR.name());
} catch (IOException e) {
log.error(Tracing.M_AUDIT, "Create Paypal order", e);
trx.setStatus(PaypalCheckoutStatus.ERROR);
trx.setPaypalOrderStatus(PaypalCheckoutStatus.ERROR.name());
}
trx = transactionDao.update(trx);
dbInstance.commit();
return trx;
}
public CheckoutRequest paymentUrl(String url, org.olat.resource.accesscontrol.Order order, PaypalCheckoutTransaction trx, String sessionId) { public CheckoutRequest paymentUrl(String url, org.olat.resource.accesscontrol.Order order, PaypalCheckoutTransaction trx, String sessionId) {
String returnURL = url + "/" + trx.getSecureSuccessUUID() + ".html;jsessionid=" + sessionId + "?status=success"; String returnURL = url + "/" + trx.getSecureSuccessUUID() + ".html;jsessionid=" + sessionId + "?status=success";
String cancelURL = url + "/" + trx.getSecureCancelUUID() + ".html;jsessionid=" + sessionId + "?status=cancel"; String cancelURL = url + "/" + trx.getSecureCancelUUID() + ".html;jsessionid=" + sessionId + "?status=cancel";
ApplicationContext applicationContext = new ApplicationContext()
.cancelUrl(cancelURL)
.returnUrl(returnURL);
OrderRequest orderRequest = new OrderRequest(); OrderRequest orderRequest = buildOrderRequest(order, "AUTHORIZE", applicationContext);
orderRequest.checkoutPaymentIntent("AUTHORIZE"); OrdersCreateRequest request = buildOrdersCreateRequest(orderRequest);
ApplicationContext applicationContext = new ApplicationContext().cancelUrl(cancelURL).returnUrl(returnURL);
orderRequest.applicationContext(applicationContext);
String price = PriceFormat.format(order.getTotal());
String currencyCode = order.getCurrencyCode();
AmountWithBreakdown amount = new AmountWithBreakdown()
.currencyCode(currencyCode).value(price)
.amountBreakdown(new AmountBreakdown().itemTotal(new com.paypal.orders.Money().currencyCode(currencyCode).value(price)));
List<PurchaseUnitRequest> purchaseUnitRequests = new ArrayList<>();
PurchaseUnitRequest purchaseUnitRequest = new PurchaseUnitRequest()
.amountWithBreakdown(amount);
purchaseUnitRequests.add(purchaseUnitRequest);
orderRequest.purchaseUnits(purchaseUnitRequests);
OrdersCreateRequest request = new OrdersCreateRequest();
request.header("prefer", "return=representation");
request.requestBody(orderRequest);
CheckoutRequest checkoutRequest = new CheckoutRequest(); CheckoutRequest checkoutRequest = new CheckoutRequest();
try { try {
HttpResponse<Order> orderResponse = client().execute(request); HttpResponse<Order> orderResponse = client().execute(request);
...@@ -144,6 +165,34 @@ public class CheckoutV2Provider { ...@@ -144,6 +165,34 @@ public class CheckoutV2Provider {
return checkoutRequest; return checkoutRequest;
} }
private OrdersCreateRequest buildOrdersCreateRequest(OrderRequest orderRequest) {
OrdersCreateRequest request = new OrdersCreateRequest();
request.header("prefer", "return=representation");
request.requestBody(orderRequest);
return request;
}
private OrderRequest buildOrderRequest(org.olat.resource.accesscontrol.Order order, String intent, ApplicationContext applicationContext) {
OrderRequest orderRequest = new OrderRequest();
orderRequest.checkoutPaymentIntent(intent);
orderRequest.applicationContext(applicationContext);
String price = PriceFormat.format(order.getTotal());
String currencyCode = order.getCurrencyCode();
AmountWithBreakdown amount = new AmountWithBreakdown()
.currencyCode(currencyCode).value(price)
.amountBreakdown(new AmountBreakdown().itemTotal(new com.paypal.orders.Money().currencyCode(currencyCode).value(price)));
List<PurchaseUnitRequest> purchaseUnitRequests = new ArrayList<>();
PurchaseUnitRequest purchaseUnitRequest = new PurchaseUnitRequest()
.amountWithBreakdown(amount);
purchaseUnitRequests.add(purchaseUnitRequest);
orderRequest.purchaseUnits(purchaseUnitRequests);
return orderRequest;
}
public PaypalCheckoutTransaction authorizeUrl(PaypalCheckoutTransaction trx) { public PaypalCheckoutTransaction authorizeUrl(PaypalCheckoutTransaction trx) {
OrdersAuthorizeRequest request = new OrdersAuthorizeRequest(trx.getPaypalOrderId()); OrdersAuthorizeRequest request = new OrdersAuthorizeRequest(trx.getPaypalOrderId());
request.requestBody(new OrderRequest()); request.requestBody(new OrderRequest());
......
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.resource.accesscontrol.provider.paypalcheckout.manager;
import java.util.Collection;
import java.util.List;
import org.olat.core.commons.services.csp.CSPDirectiveProvider;
import org.olat.resource.accesscontrol.AccessControlModule;
import org.olat.resource.accesscontrol.provider.paypalcheckout.PaypalCheckoutModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*
* Initial date: 9 nov. 2020<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
@Service
public class PaypalCSPDirectiveProvider implements CSPDirectiveProvider {
private static final List<String> sandboxedPaypal = List.of("https://www.paypal.com", "https://www.sandbox.paypal.com");
private static final List<String> productionPaypal = List.of("https://www.paypal.com");
@Autowired
private AccessControlModule acModule;
@Autowired
private PaypalCheckoutModule paypalCheckoutModule;
@Override
public Collection<String> getScriptSrcUrls() {
return urls();
}
@Override
public Collection<String> getImgSrcUrls() {
return null;
}
@Override
public Collection<String> getFontSrcUrls() {
return null;
}
@Override
public Collection<String> getConnectSrcUrls() {
return urls();
}
@Override
public Collection<String> getFrameSrcUrls() {
return urls();
}
@Override
public Collection<String> getMediaSrcUrls() {
return null;
}
private Collection<String> urls() {
if(acModule.isPaypalCheckoutEnabled()) {
return paypalCheckoutModule.isSandbox() ? sandboxedPaypal : productionPaypal;
}
return null;
}
}
...@@ -48,6 +48,7 @@ import org.olat.resource.accesscontrol.provider.paypalcheckout.PaypalCheckoutMan ...@@ -48,6 +48,7 @@ import org.olat.resource.accesscontrol.provider.paypalcheckout.PaypalCheckoutMan
import org.olat.resource.accesscontrol.provider.paypalcheckout.PaypalCheckoutStatus; import org.olat.resource.accesscontrol.provider.paypalcheckout.PaypalCheckoutStatus;
import org.olat.resource.accesscontrol.provider.paypalcheckout.PaypalCheckoutTransaction; import org.olat.resource.accesscontrol.provider.paypalcheckout.PaypalCheckoutTransaction;
import org.olat.resource.accesscontrol.provider.paypalcheckout.model.CheckoutRequest; import org.olat.resource.accesscontrol.provider.paypalcheckout.model.CheckoutRequest;
import org.olat.resource.accesscontrol.provider.paypalcheckout.model.CreateSmartOrder;
import org.olat.resource.accesscontrol.provider.paypalcheckout.model.PaypalCheckoutAccessMethod; import org.olat.resource.accesscontrol.provider.paypalcheckout.model.PaypalCheckoutAccessMethod;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -92,6 +93,35 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager { ...@@ -92,6 +93,35 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager {
return checkoutProvider.paymentUrl(url.toString(), order, trx, sessionId); return checkoutProvider.paymentUrl(url.toString(), order, trx, sessionId);
} }
@Override
public CreateSmartOrder createOrder(Identity delivery, OfferAccess offerAccess) {
Offer offer = offerAccess.getOffer();
Price amount = offer.getPrice();
if(acService.reserveAccessToResource(delivery, offerAccess)) {
Order order = orderManager.saveOneClick(delivery, offerAccess, OrderStatus.PREPAYMENT);
PaypalCheckoutTransaction trx = transactionDao.createTransaction(amount, order, order.getParts().get(0), offerAccess.getMethod());
trx = checkoutProvider.createOrder(order, trx);
return new CreateSmartOrder(trx.getPaypalOrderId(), true);
}
log.info(Tracing.M_AUDIT, "Can reserve: {}", delivery);
return new CreateSmartOrder(null, false);
}
public PaypalCheckoutTransaction approveOrder(PaypalCheckoutTransaction trx) {
try {
trx = checkoutProvider.captureOrder(trx);
if(PaypalCheckoutStatus.COMPLETED.name().equals(trx.getPaypalOrderStatus())) {
completeTransactionSucessfully(trx);
} else {
completeDeniedTransaction(trx);
}
} catch (IOException e) {
log.error("", e);
}
return trx;
}
@Override @Override
public void updateTransaction(String uuid) { public void updateTransaction(String uuid) {
PaypalCheckoutTransaction trx = loadTransactionByUUID(uuid); PaypalCheckoutTransaction trx = loadTransactionByUUID(uuid);
...@@ -106,6 +136,39 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager { ...@@ -106,6 +136,39 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager {
} }
} }
@Override
public void approveTransaction(String paypalOrderId) {
PaypalCheckoutTransaction trx = transactionDao.loadTransactionByPaypalOrderId(paypalOrderId);
if(trx != null) {
log.info(Tracing.M_AUDIT, "Paypal Checkout transaction approved: {}", trx);
completeTransaction(trx);
} else {
log.error("Paypal Checkout transaction not found for approval: {} (Paypal order id)", paypalOrderId);
}
}
@Override
public void cancelTransaction(String paypalOrderId) {
PaypalCheckoutTransaction trx = transactionDao.loadTransactionByPaypalOrderId(paypalOrderId);
if(trx != null) {
log.info(Tracing.M_AUDIT, "Paypal Checkout transaction cancelled: {}", trx);
cancelTransaction(trx);
} else {
log.error("Paypal Checkout transaction not found for cancellation: {} (Paypal order id)", paypalOrderId);
}
}
@Override
public void errorTransaction(String paypalOrderId) {
PaypalCheckoutTransaction trx = transactionDao.loadTransactionByPaypalOrderId(paypalOrderId);
if(trx != null) {
log.info(Tracing.M_AUDIT, "Paypal Checkout transaction error: {}", trx);
completeDeniedTransaction(trx);
} else {
log.error("Paypal Checkout transaction not found for error: {} (Paypal order id)", paypalOrderId);
}
}
private PaypalCheckoutTransaction completeTransaction(PaypalCheckoutTransaction trx) { private PaypalCheckoutTransaction completeTransaction(PaypalCheckoutTransaction trx) {
try { try {
trx = checkoutProvider.authorizeUrl(trx); trx = checkoutProvider.authorizeUrl(trx);
...@@ -150,7 +213,7 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager { ...@@ -150,7 +213,7 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager {
ResourceReservation reservation = acService.getReservation(identity, resource); ResourceReservation reservation = acService.getReservation(identity, resource);
if(reservation != null) { if(reservation != null) {
acService.removeReservation(identity, identity, reservation); acService.removeReservation(identity, identity, reservation);
log.info(Tracing.M_AUDIT, "Remove reservation after cancellation for: " + reservation + " to " + identity); log.info(Tracing.M_AUDIT, "Remove reservation after cancellation for: {} to {}", reservation, identity);
} }
} }
} }
...@@ -171,12 +234,12 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager { ...@@ -171,12 +234,12 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager {
transactionManager.update(transaction, AccessTransactionStatus.ERROR); transactionManager.update(transaction, AccessTransactionStatus.ERROR);
for(OrderLine line:part.getOrderLines()) { for(OrderLine line:part.getOrderLines()) {
acService.denyAccesToResource(identity, line.getOffer()); acService.denyAccesToResource(identity, line.getOffer());
log.info(Tracing.M_AUDIT, "Paypal payed access revoked for: " + buildLogMessage(line, method) + " to " + identity); log.info(Tracing.M_AUDIT, "Paypal payed access revoked for: {} to {}", buildLogMessage(line, method), identity);
ResourceReservation reservation = reservationDao.loadReservation(identity, line.getOffer().getResource()); ResourceReservation reservation = reservationDao.loadReservation(identity, line.getOffer().getResource());
if(reservation != null) { if(reservation != null) {
acService.removeReservation(identity, identity, reservation); acService.removeReservation(identity, identity, reservation);
log.info(Tracing.M_AUDIT, "Remove reservation after cancellation for: " + reservation + " to " + identity); log.info(Tracing.M_AUDIT, "Remove reservation after cancellation for: {} to {}", reservation, identity);
} }
} }
} }
...@@ -201,10 +264,10 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager { ...@@ -201,10 +264,10 @@ public class PaypalCheckoutManagerImpl implements PaypalCheckoutManager {
transactionManager.save(transaction); transactionManager.save(transaction);
for(OrderLine line:part.getOrderLines()) { for(OrderLine line:part.getOrderLines()) {
if(acService.allowAccesToResource(identity, line.getOffer())) { if(acService.allowAccesToResource(identity, line.getOffer())) {
log.info(Tracing.M_AUDIT, "Paypal Checkout payed access granted for: " + buildLogMessage(line, method) + " to " + identity); log.info(Tracing.M_AUDIT, "Paypal Checkout payed access granted for: {} to {}", buildLogMessage(line, method), identity);
transaction = transactionManager.update(transaction, AccessTransactionStatus.SUCCESS); transaction = transactionManager.update(transaction, AccessTransactionStatus.SUCCESS);
} else { } else {
log.error("Paypal Checkout payed access refused for: " + buildLogMessage(line, method) + " to " + identity); log.error("Paypal Checkout payed access refused for: {} to {}", buildLogMessage(line, method), identity);
transaction = transactionManager.update(transaction, AccessTransactionStatus.ERROR); transaction = transactionManager.update(transaction, AccessTransactionStatus.ERROR);
} }
} }
......
...@@ -95,6 +95,18 @@ public class PaypalCheckoutTransactionDAO { ...@@ -95,6 +95,18 @@ public class PaypalCheckoutTransactionDAO {
return transactions.isEmpty() ? null : transactions.get(0); return transactions.isEmpty() ? null : transactions.get(0);
} }
public PaypalCheckoutTransaction loadTransactionByPaypalOrderId(String paypalOrderId) {
StringBuilder sb = new StringBuilder(128);
sb.append("select trx from paypalcheckouttransaction as trx")
.append(" where trx.paypalOrderId=:paypalOrderId");
List<PaypalCheckoutTransaction> transactions = dbInstance.getCurrentEntityManager()
.createQuery(sb.toString(), PaypalCheckoutTransaction.class)
.setParameter("paypalOrderId", paypalOrderId)
.getResultList();
return transactions.isEmpty() ? null : transactions.get(0);
}
public List<PSPTransaction> loadTransactionBy(List<Order> orders) { public List<PSPTransaction> loadTransactionBy(List<Order> orders) {
if(orders == null || orders.isEmpty()) return new ArrayList<>(); if(orders == null || orders.isEmpty()) return new ArrayList<>();
......
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.resource.accesscontrol.provider.paypalcheckout.model;
/**
*
* Initial date: 9 nov. 2020<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class CreateSmartOrder {
private final String paypalOrderId;
private final boolean reservationOk;
public CreateSmartOrder(String paypalOrderId, boolean reservationOk) {
this.paypalOrderId = paypalOrderId;
this.reservationOk = reservationOk;
}
public boolean isReservationOk() {
return reservationOk;
}
public String getPaypalOrderId() {
return paypalOrderId;
}
}
...@@ -34,6 +34,7 @@ import javax.persistence.TemporalType; ...@@ -34,6 +34,7 @@ import javax.persistence.TemporalType;
import org.hibernate.annotations.Target; import org.hibernate.annotations.Target;
import org.olat.core.id.Persistable; import org.olat.core.id.Persistable;
import org.olat.core.util.StringHelper;
import org.olat.resource.accesscontrol.Price; import org.olat.resource.accesscontrol.Price;
import org.olat.resource.accesscontrol.model.PSPTransactionStatus; import org.olat.resource.accesscontrol.model.PSPTransactionStatus;
import org.olat.resource.accesscontrol.model.PriceImpl; import org.olat.resource.accesscontrol.model.PriceImpl;
...@@ -306,4 +307,37 @@ public class PaypalCheckoutTransactionImpl implements Persistable, PaypalCheckou ...@@ -306,4 +307,37 @@ public class PaypalCheckoutTransactionImpl implements Persistable, PaypalCheckou
public boolean equalsByPersistableKey(Persistable persistable) { public boolean equalsByPersistableKey(Persistable persistable) {
return equals(persistable); return equals(persistable);
} }
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("PaypalCheckoutTransaction[key=").append(getKey()).append("]")
.append("[price=").append(securePrice).append("]")
//order
.append("[orderId=").append(orderId).append("]")
.append("[orderPartId=").append(orderPartId).append("]")
.append("[methodId=").append(methodId).append("]");
if(StringHelper.containsNonWhitespace(paypalOrderId)) {
sb.append("[paypalOrderId=").append(paypalOrderId).append("]");
}
if(StringHelper.containsNonWhitespace(paypalOrderStatus)) {
sb.append("[paypalOrderStatus=").append(paypalOrderStatus).append("]");
}
if(StringHelper.containsNonWhitespace(paypalOrderStatusReason)) {
sb.append("[paypalOrderStatusReason=").append(paypalOrderStatusReason).append("]");
}
if(StringHelper.containsNonWhitespace(paypalAuthorizationId)) {
sb.append("[paypalAuthorizationId=").append(paypalAuthorizationId).append("]");
}
if(StringHelper.containsNonWhitespace(paypalCaptureId)) {
sb.append("[paypalCaptureId=").append(paypalCaptureId).append("]");
}
if(StringHelper.containsNonWhitespace(secureSuccessUUID)) {
sb.append("[successUUID=").append(secureSuccessUUID ).append("]");
}
if(StringHelper.containsNonWhitespace(secureCancelUUID)) {
sb.append("[cancelUUID=").append(secureCancelUUID).append("]");
}
return sb.toString();
}
} }
\ No newline at end of file
...@@ -48,10 +48,12 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -48,10 +48,12 @@ import org.springframework.beans.factory.annotation.Autowired;
public class PaypalCheckoutAccountConfigurationController extends FormBasicController { public class PaypalCheckoutAccountConfigurationController extends FormBasicController {
private static final String[] onKeys = new String[] { "on" }; private static final String[] onKeys = new String[] { "on" };
private static final String[] smartButtonsKeys = new String[] { "smartbuttons", "standard" };
private TextElement clientIdEl; private TextElement clientIdEl;
private TextElement clientSecretEl; private TextElement clientSecretEl;
private SingleSelection currencyEl; private SingleSelection currencyEl;
private SingleSelection smartButtonsEl;
private MultipleSelectionElement enableEl; private MultipleSelectionElement enableEl;
private final List<String> paypalCurrencies; private final List<String> paypalCurrencies;
...@@ -83,6 +85,16 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr ...@@ -83,6 +85,16 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr
enableEl.select(onKeys[0], acModule.isPaypalCheckoutEnabled()); enableEl.select(onKeys[0], acModule.isPaypalCheckoutEnabled());
enableEl.addActionListener(FormEvent.ONCHANGE); enableEl.addActionListener(FormEvent.ONCHANGE);
KeyValues smartButtons = new KeyValues();
smartButtons.add(KeyValues.entry(smartButtonsKeys[0], translate("checkout.smart.buttons.enabled")));
smartButtons.add(KeyValues.entry(smartButtonsKeys[1], translate("checkout.standard")));
smartButtonsEl = uifactory.addRadiosVertical("checkout.smart.buttons", "checkout.smart.buttons", formLayout, smartButtons.keys(), smartButtons.values());
if(paypalModule.isSmartButtons()) {
smartButtonsEl.select(smartButtonsKeys[0], true);
} else {
smartButtonsEl.select(smartButtonsKeys[1], true);
}
KeyValues currencies = new KeyValues(); KeyValues currencies = new KeyValues();
paypalCurrencies.forEach(currency -> currencies.add(KeyValues.entry(currency, currency))); paypalCurrencies.forEach(currency -> currencies.add(KeyValues.entry(currency, currency)));
currencyEl = uifactory.addDropdownSingleselect("currency", "currency", formLayout, currencies.keys(), currencies.values(), null); currencyEl = uifactory.addDropdownSingleselect("currency", "currency", formLayout, currencies.keys(), currencies.values(), null);
...@@ -99,7 +111,6 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr ...@@ -99,7 +111,6 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr
final FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonLayout", getTranslator()); final FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttonLayout", getTranslator());
formLayout.add(buttonGroupLayout); formLayout.add(buttonGroupLayout);
uifactory.addFormSubmitButton("save", buttonGroupLayout); uifactory.addFormSubmitButton("save", buttonGroupLayout);
} }
...@@ -108,6 +119,7 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr ...@@ -108,6 +119,7 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr
currencyEl.setVisible(enabled); currencyEl.setVisible(enabled);
clientIdEl.setVisible(enabled); clientIdEl.setVisible(enabled);
clientSecretEl.setVisible(enabled); clientSecretEl.setVisible(enabled);
smartButtonsEl.setVisible(enabled);
} }
@Override @Override
...@@ -133,7 +145,6 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr ...@@ -133,7 +145,6 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr
&& !StringHelper.containsNonWhitespace(element.getValue())) { && !StringHelper.containsNonWhitespace(element.getValue())) {
element.setErrorKey("form.legende.mandatory", null); element.setErrorKey("form.legende.mandatory", null);
allOk &= false; allOk &= false;
} }
return allOk; return allOk;
...@@ -157,6 +168,7 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr ...@@ -157,6 +168,7 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr
if(currencyEl.isOneSelected() && paypalCurrencies.contains(currencyEl.getSelectedKey())) { if(currencyEl.isOneSelected() && paypalCurrencies.contains(currencyEl.getSelectedKey())) {
paypalModule.setPaypalCurrency(currencyEl.getSelectedKey()); paypalModule.setPaypalCurrency(currencyEl.getSelectedKey());
} }
paypalModule.setSmartButtons(smartButtonsEl.isOneSelected() && smartButtonsEl.isSelected(0));
} else { } else {
paypalModule.setClientId(null); paypalModule.setClientId(null);
paypalModule.setClientSecret(null); paypalModule.setClientSecret(null);
......
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.resource.accesscontrol.provider.paypalcheckout.ui;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.impl.Form;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.htmlheader.jscss.JSAndCSSFormItem;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.util.StringHelper;
import org.olat.resource.accesscontrol.OfferAccess;
import org.olat.resource.accesscontrol.Price;
import org.olat.resource.accesscontrol.provider.paypalcheckout.PaypalCheckoutModule;
import org.olat.resource.accesscontrol.ui.FormController;
import org.olat.resource.accesscontrol.ui.PriceFormat;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* Initial date: 6 nov. 2020<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class PaypalSmartButtonAccessController extends FormBasicController implements FormController {
private OfferAccess link;
@Autowired
private PaypalCheckoutModule paypalModule;
public PaypalSmartButtonAccessController(UserRequest ureq, WindowControl wControl, OfferAccess link) {
super(ureq, wControl, "paypal_smart_buttons");
this.link = link;
initForm(ureq);
}
public PaypalSmartButtonAccessController(UserRequest ureq, WindowControl wControl, OfferAccess link, Form form) {
super(ureq, wControl, LAYOUT_CUSTOM, "paypal_smart_buttons", form);
this.link = link;
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
if(formLayout instanceof FormLayoutContainer) {
FormLayoutContainer layoutCont = (FormLayoutContainer)formLayout;
String appId = paypalModule.getClientId();
layoutCont.contextPut("clientId", appId);
String currency = link.getOffer().getPrice().getCurrencyCode();
layoutCont.contextPut("currency", currency);
String description = link.getOffer().getDescription();
if(StringHelper.containsNonWhitespace(description)) {
description = StringHelper.xssScan(description);
layoutCont.contextPut("description", description);
}
Price price = link.getOffer().getPrice();
String priceStr = PriceFormat.fullFormat(price);
layoutCont.contextPut("price", priceStr);
String mapperUri = registerMapper(ureq, new PaypalSmartButtonMapper(getIdentity(), link, this));
layoutCont.contextPut("mapperUri", mapperUri);
}
JSAndCSSFormItem js = new JSAndCSSFormItem("js", new String[] { "https://www.paypal.com/sdk/js?client-id=" + paypalModule.getClientId() + "&currency=CHF&intent=authorize" });
formLayout.add(js);
}
@Override
protected void fireEvent(UserRequest ureq, Event event) {
super.fireEvent(ureq, event);
}
@Override
protected void doDispose() {
//
}
@Override
protected void formOK(UserRequest ureq) {
//
}
}
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.resource.accesscontrol.provider.paypalcheckout.ui;
import javax.servlet.http.HttpServletRequest;
import org.json.JSONObject;
import org.olat.core.CoreSpringFactory;
import org.olat.core.dispatcher.mapper.Mapper;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.UserRequestImpl;
import org.olat.core.gui.media.JSONMediaResource;
import org.olat.core.gui.media.MediaResource;
import org.olat.core.id.Identity;
import org.olat.core.util.StringHelper;
import org.olat.resource.accesscontrol.OfferAccess;
import org.olat.resource.accesscontrol.provider.paypalcheckout.PaypalCheckoutManager;
import org.olat.resource.accesscontrol.provider.paypalcheckout.model.CreateSmartOrder;
import org.olat.resource.accesscontrol.ui.AccessEvent;
/**
*
* Initial date: 6 nov. 2020<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class PaypalSmartButtonMapper implements Mapper {
private CreateSmartOrder order;
private final OfferAccess link;
private final Identity identity;
private final PaypalCheckoutManager paypalManager;
private final PaypalSmartButtonAccessController controller;
public PaypalSmartButtonMapper(Identity identity, OfferAccess link, PaypalSmartButtonAccessController controller) {
this.link = link;
this.identity = identity;
this.controller = controller;
paypalManager = CoreSpringFactory.getImpl(PaypalCheckoutManager.class);
}
@Override
public MediaResource handle(String relPath, HttpServletRequest request) {
MediaResource resource = null;
if(relPath.contains("create-paypal-transaction")) {
resource = createPaypalTransaction();
} else if(relPath.contains("approve-paypal-transaction")) {
resource = approvePaypalTransaction(request);
} else if(relPath.contains("cancel-paypal-transaction")) {
resource = cancelPaypalTransaction();
} else if(relPath.contains("error-paypal-transaction")) {
resource = errorPaypalTransaction();
}
return resource;
}
private MediaResource createPaypalTransaction() {
if(order == null) {
order = paypalManager.createOrder(identity, link);
}
if(order != null) {
if(StringHelper.containsNonWhitespace(order.getPaypalOrderId())) {
return buildOrderResource(order.getPaypalOrderId());
} else if(!order.isReservationOk()) {
JSONObject obj = new JSONObject();
obj.put("reservation", false);
return new JSONMediaResource(obj, "UTF-8");
}
}
return null;
}
private MediaResource approvePaypalTransaction(HttpServletRequest request) {
if(order != null && StringHelper.containsNonWhitespace(order.getPaypalOrderId())) {
paypalManager.approveTransaction(order.getPaypalOrderId());
UserRequest ureq = new UserRequestImpl("m", request, null);
controller.fireEvent(ureq, AccessEvent.ACCESS_OK_EVENT);
return buildOrderResource(order.getPaypalOrderId());
}
return null;
}
private MediaResource cancelPaypalTransaction() {
if(order != null && StringHelper.containsNonWhitespace(order.getPaypalOrderId())) {
paypalManager.cancelTransaction(order.getPaypalOrderId());
return buildOrderResource(order.getPaypalOrderId());
}
return null;
}
private MediaResource errorPaypalTransaction() {
if(order != null && StringHelper.containsNonWhitespace(order.getPaypalOrderId())) {
paypalManager.errorTransaction(order.getPaypalOrderId());
return buildOrderResource(order.getPaypalOrderId());
}
return null;
}
private JSONMediaResource buildOrderResource(String paypalOrderId) {
JSONObject obj = new JSONObject();
obj.put("orderID", paypalOrderId);
obj.put("reservation", true);
return new JSONMediaResource(obj, "UTF-8");
}
}
<div class="o_paypal">
<fieldset class=" o_form form-horizontal clearfix">
<legend><i class="o_icon o_icon-fw o_ac_paypal_icon"> </i> $r.translate("access.paypal.title")</legend>
<div id="paypal_desc_${r.getCId()}" class="o_desc">$r.translate("access.paypal.desc.smart.buttons")</div>
<div id="paypal_processing_${r.getCId()}" class="o_desc" style="display: none;"><i class="o_icon o_icon-lg o_icon_pending o_icon-spin"> </i> $r.translate("paypal.process.transaction")</div>
<div id="paypal_wrapper_${r.getCId()}">
#if($r.isNotEmpty($description))
<div class="form-group clearfix">
<label class="control-label col-sm-3" for-id="paypal_desc_${r.getCId()}">$r.translate("offer.description")</label>
<div class="col-sm-9"><p id="paypal_desc_${r.getCId()}" class="form-control-static">$description</p></div>
</div>
#end
<div class="form-group clearfix">
<label class="control-label col-sm-3" for-id="paypal_price_${r.getCId()}">$r.translate("offer.price")</label>
<div class="col-sm-9"><p id="paypal_price_${r.getCId()}" class="form-control-static">$price</p></div>
</div>
<div id="paypal_buttons_${r.getCId()}">
<script defer>
jQuery(function() {
jQuery.ajax({
url: 'https://www.paypal.com/sdk/js?client-id=$clientId&currency=$currency&intent=authorize',
cache: true,
dataType: "script",
success: loadButtons
});
function loadButtons() {
paypal.Buttons({
createOrder: function(data, actions) {
return fetch('$mapperUri/create-paypal-transaction', {
method: 'post',
headers: { 'content-type': 'application/json' }
}).then(function(res) {
return res.json();
}).then(function(resData) {
// Use the same key name for order ID on the client and server
if(resData.reservation) {
return resData.orderID;
}
document.getElementById("paypal_wrapper_${r.getCId()}").style.display = "none";
document.getElementById("paypal_reservation_${r.getCId()}").style.display = "block";
return null;
});
},
onApprove: function(data, actions) {
document.getElementById("paypal_wrapper_${r.getCId()}").style.display = "none";
document.getElementById("paypal_processing_${r.getCId()}").style.display = "block";
return fetch('$mapperUri/approve-paypal-transaction', {
method: 'post',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
orderID: data.orderID
})
}).then(function(res) {
return res.json();
}).then(function(resData) {
setTimeout(function() {
location.reload();
}, 100);
});
},
onCancel: function (data, actions) {
return fetch('$mapperUri/cancel-paypal-transaction', {
method: 'post',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
orderID: data.orderID
})
}).then(function(res) {
document.getElementById("paypal_wrapper_${r.getCId()}").style.display = "none";
document.getElementById("paypal_cancel_${r.getCId()}").style.display = "block";
});
},
onError: function (err) {
return fetch('$mapperUri/error-paypal-transaction', {
method: 'post',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
orderID: data.orderID
})
}).then(function(res) {
document.getElementById("paypal_wrapper_${r.getCId()}").style.display = "none";
document.getElementById("paypal_error_${r.getCId()}").style.display = "block";
});
}
}).render('#paypal_buttons_${r.getCId()}');
}
});
</script>
</div>
</div>
</fieldset>
<div id="paypal_reservation_${r.getCId()}" class="o_error" style="display: none;" role="alert">$r.translate("paypal.reservation.failed") </div>
<div id="paypal_cancel_${r.getCId()}" class="o_warning" style="display: none;" role="alert">$r.translate("paypal.cancelled.transaction")</div>
<div id="paypal_error_${r.getCId()}" class="o_error" style="display: none;" role="alert">$r.translate("paypal.error.transaction")</div>
</div>
\ No newline at end of file
#Mon Aug 26 14:09:25 CEST 2019 #Mon Aug 26 14:09:25 CEST 2019
access.button=Zur Zahlung access.button=Zur Zahlung
access.paypal.desc=Diese Ressource kann mit einem PayPal Konto gekauft werden. Halten Sie Ihre PayPal Kontoinformationen und w\u00E4hlen Sie die Schaltfl\u00E4che "Kaufen" um sich f\u00FCr den Zugang zu registrieren. access.paypal.desc=Diese Ressource kann mit einem PayPal Konto gekauft werden. Halten Sie Ihre PayPal Kontoinformationen und w\u00E4hlen Sie die Schaltfl\u00E4che "Kaufen" um sich f\u00FCr den Zugang zu registrieren.
access.paypal.desc.smart.buttons=$\:access.paypal.desc
access.paypal.title=Bezahlen mit PayPal access.paypal.title=Bezahlen mit PayPal
checkout.client.id=Client ID checkout.client.id=Client ID
checkout.client.secret=Client secret checkout.client.secret=Client secret
checkout.config.description=Konfigurieren Sie die PayPal API-Berechtigung f\u00FCr den PayPal Zugang mit den Elementen Client ID und Client Secret. Diese zwei Sicherheitselemente m\u00FCssen Sie zuerst in Ihrem PayPal Businesskonto erstellen. <strong>OpenOlat unterst\u00FCtzt nicht nachtr\u00E4gliche Anderungen am Bestellungen von Ihrem Paypal Konto.</strong> checkout.config.description=Konfigurieren Sie die PayPal API-Berechtigung f\u00FCr den PayPal Zugang mit den Elementen Client ID und Client Secret. Diese zwei Sicherheitselemente m\u00FCssen Sie zuerst in Ihrem PayPal Businesskonto erstellen. <strong>OpenOlat unterst\u00FCtzt nicht nachtr\u00E4gliche Anderungen am Bestellungen von Ihrem Paypal Konto.</strong>
checkout.config.title=Paypal Checkout konfigurieren checkout.config.title=Paypal Checkout konfigurieren
checkout.smart.buttons=Integration
checkout.smart.buttons.enabled=Paypal Smart Buttons
checkout.standard=Standard (Paypal Konto erforderlich)
config.disabled.warning=Das PayPal Bezahlungsmodul ist f\u00FCr dieses System nicht freigeschaltet. Um Buchungen \u00FCber PayPal abwickeln zu k\u00F6nnen, nehmen Sie bitte Kontakt auf mit <a href="mailto:{0}">{0}</a>. config.disabled.warning=Das PayPal Bezahlungsmodul ist f\u00FCr dieses System nicht freigeschaltet. Um Buchungen \u00FCber PayPal abwickeln zu k\u00F6nnen, nehmen Sie bitte Kontakt auf mit <a href="mailto:{0}">{0}</a>.
currency=W\u00E4hrung currency=W\u00E4hrung
currency.error=Fehler in der W\u00E4hrungsauswahl currency.error=Fehler in der W\u00E4hrungsauswahl
...@@ -22,15 +26,19 @@ offer.description=$org.olat.resource.accesscontrol.ui\:offer.description ...@@ -22,15 +26,19 @@ offer.description=$org.olat.resource.accesscontrol.ui\:offer.description
offer.price=Preis offer.price=Preis
oo.order.nr=Bestellung ID (in OpenOlat) oo.order.nr=Bestellung ID (in OpenOlat)
paypal.before.redirect.error=Unerwarteter Fehler paypal.before.redirect.error=Unerwarteter Fehler
paypal.cancelled.transaction=Sie haben die Transaktion abgebrochen. Die Buchung ist nicht ausgef\u00FChrt worden und Ihre Kreditkarte wurde nicht belastet.
paypal.capture.id=Capture ID paypal.capture.id=Capture ID
paypal.checkout.method=Paypal Checkout v2 paypal.checkout.method=Paypal Checkout v2
paypal.enable=Paypal einschalten paypal.enable=Paypal einschalten
paypal.error.transaction=Ein Fehler ist aufgetreten.
paypal.invoice.id=Invoice ID paypal.invoice.id=Invoice ID
paypal.menu.title=Paypal paypal.menu.title=Paypal
paypal.menu.title.alt=Paypal Checkout konfigurieren paypal.menu.title.alt=Paypal Checkout konfigurieren
paypal.order.id=Bestellung ID (in Paypal) paypal.order.id=Bestellung ID (in Paypal)
paypal.order.status=Status paypal.order.status=Status
paypal.order.status.reason=Status Erkl\u00E4rung paypal.order.status.reason=Status Erkl\u00E4rung
paypal.process.transaction=Transkation ist erfolgreich und wird verarbeitet.
paypal.reservation.failed=Es gibt momentan keinen freien Platz.
paypal.segment.account=Konto paypal.segment.account=Konto
paypal.segment.transactions=Transactionen paypal.segment.transactions=Transactionen
paypal.transaction.amount=Preis (in Paypal) paypal.transaction.amount=Preis (in Paypal)
...@@ -39,7 +47,7 @@ paypal.transactions.empty=Keine Transaktion gefunden ...@@ -39,7 +47,7 @@ paypal.transactions.empty=Keine Transaktion gefunden
price=Preis price=Preis
price.error=Fehler in der Preisangabe price.error=Fehler in der Preisangabe
show.all=Show all show.all=Show all
status.canceled=Abgebrochenn status.canceled=Abgebrochen
status.error=Unerwartete Fehler status.error=Unerwartete Fehler
status.new=Neu, noch nicht abgeschlossen status.new=Neu, noch nicht abgeschlossen
status.success=Erfolgreich abgeschlossen status.success=Erfolgreich abgeschlossen
......
#Mon Aug 26 17:17:13 CEST 2019 #Mon Aug 26 17:17:13 CEST 2019
access.button=Go to Payment access.button=Go to Payment
access.paypal.desc=PayPal description access.paypal.desc=PayPal description
access.paypal.desc.smart.buttons=$\:access.paypal.desc
access.paypal.title=Pay with PayPal access.paypal.title=Pay with PayPal
checkout.client.id=Client ID checkout.client.id=Client ID
checkout.client.secret=Client secret checkout.client.secret=Client secret
checkout.config.description=Configure your authorisation to use your Paypal count with the Client ID and Client Secret. These two security elements must be created in your Paypal Business Account. <strong>OpenOlat doesn't support subsequent changes in order from your Paypal Account (yet).</strong> checkout.config.description=Configure your authorisation to use your Paypal count with the Client ID and Client Secret. These two security elements must be created in your Paypal Business Account. <strong>OpenOlat doesn't support subsequent changes in order from your Paypal Account (yet).</strong>
checkout.config.title=Configure Paypal Checkout checkout.config.title=Configure Paypal Checkout
checkout.smart.buttons=Integration
checkout.smart.buttons.enabled=Paypal Smart Buttons
checkout.standard=Standard (Paypal account mandatory)
config.disabled.warning=The PayPal payment module is not activated for this system. To handle bookings via PayPal can you please contact <a href="mailto:{0}">{0}</a>. config.disabled.warning=The PayPal payment module is not activated for this system. To handle bookings via PayPal can you please contact <a href="mailto:{0}">{0}</a>.
currency=Currency currency=Currency
currency.error=Currency error currency.error=Currency error
...@@ -22,15 +26,19 @@ offer.description=$org.olat.resource.accesscontrol.ui\:offer.description ...@@ -22,15 +26,19 @@ offer.description=$org.olat.resource.accesscontrol.ui\:offer.description
offer.price=Price offer.price=Price
oo.order.nr=Order ID (in OpenOlat) oo.order.nr=Order ID (in OpenOlat)
paypal.before.redirect.error=Unexpected error paypal.before.redirect.error=Unexpected error
paypal.cancelled.transaction=You have canceled a transaction.
paypal.capture.id=Capture ID paypal.capture.id=Capture ID
paypal.checkout.method=Paypal Checkout v2 paypal.checkout.method=Paypal Checkout v2
paypal.enable=Enable Paypal paypal.enable=Enable Paypal
paypal.error.transaction=An error occured.
paypal.invoice.id=Invoice ID paypal.invoice.id=Invoice ID
paypal.menu.title=Paypal paypal.menu.title=Paypal
paypal.menu.title.alt=Configure Paypal Checkout paypal.menu.title.alt=Configure Paypal Checkout
paypal.order.id=Order ID (in Paypal) paypal.order.id=Order ID (in Paypal)
paypal.order.status=Status paypal.order.status=Status
paypal.order.status.reason=Status reason paypal.order.status.reason=Status reason
paypal.process.transaction=Your transaction is approved and is currently processed.
paypal.reservation.failed=There isn't currently an available place.
paypal.segment.account=Account paypal.segment.account=Account
paypal.segment.transactions=Transactions paypal.segment.transactions=Transactions
paypal.transaction.amount=Price (Paypal) paypal.transaction.amount=Price (Paypal)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment