Skip to content
Snippets Groups Projects
Commit 736f15c7 authored by srosse's avatar srosse
Browse files

OO-5059: automatically get or create a PayPal webhook

parent 3325b792
No related branches found
No related tags found
No related merge requests found
...@@ -2263,6 +2263,11 @@ ...@@ -2263,6 +2263,11 @@
<artifactId>checkout-sdk</artifactId> <artifactId>checkout-sdk</artifactId>
<version>1.0.2</version> <version>1.0.2</version>
</dependency> </dependency>
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>rest-api-sdk</artifactId>
<version>1.14.0</version>
</dependency>
<!-- end Paypal --> <!-- end Paypal -->
<!-- Start test dependencies --> <!-- Start test dependencies -->
...@@ -2347,7 +2352,6 @@ ...@@ -2347,7 +2352,6 @@
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.8.6</version> <version>2.8.6</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
......
...@@ -19,11 +19,16 @@ ...@@ -19,11 +19,16 @@
*/ */
package org.olat.resource.accesscontrol.provider.paypalcheckout; package org.olat.resource.accesscontrol.provider.paypalcheckout;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.apache.logging.log4j.Logger;
import org.olat.core.configuration.AbstractSpringModule; import org.olat.core.configuration.AbstractSpringModule;
import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper;
import org.olat.core.util.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.resource.accesscontrol.provider.paypalcheckout.manager.PaypalRESTWebhookProvider;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -37,10 +42,13 @@ import org.springframework.stereotype.Service; ...@@ -37,10 +42,13 @@ import org.springframework.stereotype.Service;
@Service @Service
public class PaypalCheckoutModule extends AbstractSpringModule { public class PaypalCheckoutModule extends AbstractSpringModule {
private static final Logger log = Tracing.createLoggerFor(PaypalCheckoutModule.class);
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 PAYPAL_SMART_BUTTONS = "paypal.checkout.v2.smart.buttons";
private static final String PAYPAL_WEBHOOK_ID = "paypal.webhhok.id";
private static final String[] currencies = new String[] { private static final String[] currencies = new String[] {
"AUD", "AUD",
...@@ -77,6 +85,11 @@ public class PaypalCheckoutModule extends AbstractSpringModule { ...@@ -77,6 +85,11 @@ public class PaypalCheckoutModule extends AbstractSpringModule {
private String paypalCurrency; private String paypalCurrency;
@Value("${paypal.checkout.v2.smart.buttons:true}") @Value("${paypal.checkout.v2.smart.buttons:true}")
private boolean smartButtons; private boolean smartButtons;
@Value("${paypal.webhhok.id:#{null}}")
private String webhookId;
@Autowired
private PaypalRESTWebhookProvider webhookProvider;
@Autowired @Autowired
public PaypalCheckoutModule(CoordinatorManager coordinatorManager) { public PaypalCheckoutModule(CoordinatorManager coordinatorManager) {
...@@ -93,7 +106,32 @@ public class PaypalCheckoutModule extends AbstractSpringModule { ...@@ -93,7 +106,32 @@ 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);
webhookId = getStringPropertyValue(PAYPAL_WEBHOOK_ID, webhookId);
smartButtons = "true".equals(getStringPropertyValue(PAYPAL_SMART_BUTTONS, Boolean.toString(smartButtons))); smartButtons = "true".equals(getStringPropertyValue(PAYPAL_SMART_BUTTONS, Boolean.toString(smartButtons)));
if(!StringHelper.containsNonWhitespace(webhookId) && StringHelper.containsNonWhitespace(clientId) && StringHelper.containsNonWhitespace(clientSecret)) {
updateWebhook(clientId, clientSecret);
}
}
public void updateWebhook() {
updateWebhook(clientId, clientSecret);
}
private void updateWebhook(String id, String secret) {
webhookId = webhookProvider.hasWebhook(id, secret, sandbox);
if(webhookId == null) {
List<String> eventNames = new ArrayList<>();
eventNames.add("PAYMENT.CAPTURE.COMPLETED");
eventNames.add("PAYMENT.CAPTURE.DENIED");
eventNames.add("PAYMENT.CAPTURE.PENDING");
webhookId = webhookProvider.createWebhook(id, secret, eventNames, sandbox);
if(StringHelper.containsNonWhitespace(webhookId)) {
setStringProperty(PAYPAL_WEBHOOK_ID, webhookId, true);
}
} else {
log.info("PayPal webhook successfully retrieved: {}", webhookId);
}
} }
public String getClientId() { public String getClientId() {
......
/**
* <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.ArrayList;
import java.util.List;
import org.apache.logging.log4j.Logger;
import org.olat.core.helpers.Settings;
import org.olat.core.logging.Tracing;
import org.springframework.stereotype.Service;
import com.paypal.api.payments.EventType;
import com.paypal.api.payments.Webhook;
import com.paypal.api.payments.WebhookList;
import com.paypal.base.Constants;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.PayPalRESTException;
/**
* Helper methods to manage PayPal Webhooks (deprecated but useful).
*
* Initial date: 12 nov. 2020<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
@Service
public class PaypalRESTWebhookProvider {
private static final Logger log = Tracing.createLoggerFor(PaypalRESTWebhookProvider.class);
public String hasWebhook(String clientId, String clientSecret, boolean sandbox) {
try {
String mode = sandbox ? Constants.SANDBOX : Constants.LIVE;
APIContext apiContext = new APIContext(clientId, clientSecret, mode);
WebhookList webhookList = new WebhookList();
webhookList = webhookList.getAll(apiContext);
List<Webhook> webhooks = webhookList.getWebhooks();
String webhookEndpoint = webhookEndpoint();
for(Webhook webhook:webhooks) {
String url = webhook.getUrl();
if(url.equals(webhookEndpoint)) {
return webhook.getId();
}
}
} catch (PayPalRESTException e) {
log.error("", e);
}
return null;
}
public String webhookEndpoint() {
String serverContext = Settings.getServerContextPathURI();
if(!serverContext.endsWith("/")) {
serverContext += "/";
}
return serverContext + "checkoutv2";
}
public String createWebhook(String clientId, String clientSecret, List<String> eventNames, boolean sandbox) {
List<EventType> eventTypes = new ArrayList<>();
for(String eventName:eventNames) {
EventType eventType = new EventType();
eventType.setName(eventName);
eventTypes.add(eventType);
}
String webhookEndpoint = webhookEndpoint();
Webhook webhook = new Webhook();
webhook.setUrl(webhookEndpoint);
webhook.setEventTypes(eventTypes);
try{
String mode = sandbox ? Constants.SANDBOX : Constants.LIVE;
APIContext apiContext = new APIContext(clientId, clientSecret, mode);
Webhook createdWebhook = webhook.create(apiContext, webhook);
String webhookId = createdWebhook.getId();
log.info(Tracing.M_AUDIT, "PayPal webhook created: {}", webhookId);
return webhookId;
} catch (PayPalRESTException e) {
log.error("", e);
return null;
}
}
}
...@@ -169,10 +169,19 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr ...@@ -169,10 +169,19 @@ public class PaypalCheckoutAccountConfigurationController extends FormBasicContr
paypalModule.setPaypalCurrency(currencyEl.getSelectedKey()); paypalModule.setPaypalCurrency(currencyEl.getSelectedKey());
} }
paypalModule.setSmartButtons(smartButtonsEl.isOneSelected() && smartButtonsEl.isSelected(0)); paypalModule.setSmartButtons(smartButtonsEl.isOneSelected() && smartButtonsEl.isSelected(0));
doUpdateWebhook();
} else { } else {
paypalModule.setClientId(null); paypalModule.setClientId(null);
paypalModule.setClientSecret(null); paypalModule.setClientSecret(null);
} }
showInfo("saved"); showInfo("saved");
} }
private void doUpdateWebhook() {
try {
paypalModule.updateWebhook();
} catch (Exception e) {
logError("", e);
}
}
} }
\ No newline at end of file
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