/* * Copyright 2015 Evgeny Dolganov (evgenij.dolganov@gmail.com). * * Licensed 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 och.comp.paypal; import static java.lang.System.*; import static och.api.model.BaseBean.*; import static och.api.model.PropKey.*; import static och.util.DateUtil.*; import static och.util.Util.*; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.concurrent.Callable; import och.api.model.user.User; import och.service.props.Props; import com.paypal.api.payments.Amount; import com.paypal.api.payments.Links; import com.paypal.api.payments.Payer; import com.paypal.api.payments.Payment; import com.paypal.api.payments.PaymentHistory; import com.paypal.api.payments.RedirectUrls; import com.paypal.api.payments.Transaction; import com.paypal.core.rest.APIContext; import com.paypal.core.rest.OAuthTokenCredential; import com.paypal.core.rest.PayPalRESTException; import com.paypal.core.rest.PayPalResource; public class PaypalRestClient { public static final String TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; public static final String ERROR_CODE_401 = "Error code : 401"; private Props sysProps; private Props conProps; private volatile String accessToken; private volatile long accessTokenLastUse; public PaypalRestClient(Props systemProps, Props connectProps) throws Exception { this.sysProps = systemProps; this.conProps = connectProps; Properties config = new Properties(); config.putAll(connectProps.toMap()); PayPalResource.initConfig(config); updateAccessToken(); } public String getAccessToken(){ return accessToken; } public String payWithPaypalAcc(User user, long val) throws Exception { validateState(val > 0, "val"); return invoke(()->{ Amount amount = new Amount(); amount.setCurrency("USD"); amount.setTotal(String.valueOf(val)); Transaction transaction = new Transaction(); transaction.setAmount(amount); transaction.setDescription("Online Chat Payment for User Account: "+user.login); List<Transaction> transactions = list(transaction); Payer payer = new Payer(); payer.setPaymentMethod("paypal"); Payment payment = new Payment(); payment.setIntent("sale"); payment.setPayer(payer); payment.setTransactions(transactions); RedirectUrls redirectUrls = new RedirectUrls(); redirectUrls.setReturnUrl(sysProps.findVal(httpsServerUrl) + sysProps.getStrVal(paypal_successUri)); redirectUrls.setCancelUrl(sysProps.findVal(httpsServerUrl) + sysProps.getStrVal(paypal_failUri)); payment.setRedirectUrls(redirectUrls); Payment createdPayment = payment.create(new APIContext(accessToken)); Iterator<Links> links = createdPayment.getLinks().iterator(); while (links.hasNext()) { Links link = links.next(); if (link.getRel().equalsIgnoreCase("approval_url")) { return link.getHref(); } } throw new IllegalStateException("No approval_url in payment resp: "+createdPayment.toJSON()); }); } public PaymentHistory getLastPaymentHistory() throws Exception{ return invoke(()->{ DateFormat dateFormat = new SimpleDateFormat(PaypalRestClient.TIME_FORMAT); String dayBefore = dateFormat.format(addDays(new Date(), -1)); PaymentHistory hist = Payment.list(accessToken, map( "start_time", dayBefore, "count", "10")); return hist; }); } private <T> T invoke(Callable<T> body) throws Exception{ try { updateAccessTokenIfNeed(); return body.call(); }catch(PayPalRESTException e){ String msg = e.getMessage(); if(hasText(msg) && msg.contains(ERROR_CODE_401)){ updateAccessToken(); return body.call(); } throw e; } } private void updateAccessTokenIfNeed() throws Exception{ long curLastTimeToUse = accessTokenLastUse; if(currentTimeMillis() < curLastTimeToUse) return; updateAccessToken(curLastTimeToUse); } private void updateAccessToken() throws Exception { updateAccessToken(accessTokenLastUse); } private synchronized void updateAccessToken(long oldLastTime) throws Exception { if(accessTokenLastUse != oldLastTime) return; accessToken = new OAuthTokenCredential( conProps.findVal("clientID"), conProps.findVal("clientSecret"), conProps.toMap()).getAccessToken(); accessTokenLastUse = currentTimeMillis() + sysProps.getLongVal(paypal_accessTokenLiveTime); } }