| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- package com.cyksj.service.paypal;
- import com.cyksj.common.exception.BusinessRuntimeException;
- import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
- import com.cyksj.common.util.Jsons;
- import com.cyksj.enums.GatewayApiCode;
- import com.cyksj.model.entity.OrderDon;
- import com.cyksj.model.entity.PaypalPayConfig;
- import com.cyksj.model.request.OrderRefundReq;
- import com.cyksj.redis.RedisService;
- import com.cyksj.service.order.OrderDonService;
- import com.paypal.api.payments.*;
- import com.paypal.api.payments.Currency;
- import com.paypal.base.rest.APIContext;
- import com.paypal.base.rest.OAuthTokenCredential;
- import com.paypal.base.rest.PayPalRESTException;
- import lombok.RequiredArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Service;
- import java.io.InputStream;
- import java.io.OutputStreamWriter;
- import java.math.BigDecimal;
- import java.math.RoundingMode;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.*;
- /**
- * @author chan
- * @date 2021/3/26 11:03 上午
- */
- @Service
- @Slf4j
- @RequiredArgsConstructor
- public class PayPalService{
- private static final GlobalThreadPoolTaskExecutor THREAD_POOL = GlobalThreadPoolTaskExecutor.getInstance();
- private final OrderDonService orderDonService;
- private final PaypalPayConfigService paypalPayConfigService;
- private final RedisService redisService;
- private static final String SANDBOX_URL = "https://api-m.sandbox.paypal.com";
- private static final String LIVE_URL = "https://api-m.paypal.com";
- public String successPayment(String paymentId, String payerId,PaypalPayConfig paypalPayConfig) throws Exception {
- log.info("paypal回调 paymentId:{},payerId:{}",paymentId,payerId);
- Payment payment = null;
- try {
- payment = this.executePayment(paymentId,payerId,paypalPayConfig.getClientId(),paypalPayConfig.getClientSecret(),paypalPayConfig.getMode());
- } catch (PayPalRESTException e) {
- log.error("支付回调失败",e);
- payment = Payment.get(getAPIContext(paypalPayConfig.getClientId(),paypalPayConfig.getClientSecret(),paypalPayConfig.getMode()), paymentId);
- }
- PayerInfo payerInfo = payment.getPayer().getPayerInfo();
- log.info("paypal 支付回调 用户信息:{}", payerInfo);
- //支付成功
- if("approved".equals(payment.getState())){
- //paypal 交易id
- Sale sale = payment.getTransactions().get(0).getRelatedResources().get(0).getSale();
- log.info("paypal 支付回调 订单信息:{}", sale);
- Currency transactionFee = sale.getTransactionFee();
- String transationId = sale.getId();
- String orderId = payment.getTransactions().get(0).getCustom();
- //更新订单支付状态
- OrderDon orderDon = orderDonService.getById(orderId);
- orderDon.setTransactionId(transationId);
- orderDon.setPayTime(new Date());
- orderDon.setAbroadTransactionFee(new BigDecimal(transactionFee.getValue()).multiply(BigDecimal.valueOf(100)));
- orderDonService.orderNotify(orderDon);
- log.info("支付成功订单:"+orderId+",支付交易号:"+transationId);
- log.info("支付成功订单:"+orderId+",返回参数:"+Jsons.toJson(payment));
- THREAD_POOL.execute(()->{
- try {
- APIContext apiContext = this.getAPIContext(paypalPayConfig.getClientId(), paypalPayConfig.getClientSecret(), paypalPayConfig.getMode());
- URL url = new URL("live".equals(paypalPayConfig.getMode()) ? LIVE_URL : SANDBOX_URL + "/v1/shipping/trackers-batch");
- HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
- httpConn.setRequestMethod("POST");
- httpConn.setRequestProperty("Content-Type", "application/json");
- httpConn.setRequestProperty("Authorization", apiContext.getAccessToken());
- httpConn.setDoOutput(true);
- OutputStreamWriter writer = new OutputStreamWriter(httpConn.getOutputStream());
- writer.write("{\"trackers\": [{ \"transaction_id\": \"" + transationId + "\", \"status\": \"SHIPPED\"}]}");
- writer.flush();
- writer.close();
- httpConn.getOutputStream().close();
- InputStream responseStream = httpConn.getResponseCode() / 100 == 2 ? httpConn.getInputStream() : httpConn.getErrorStream();
- Scanner s = new Scanner(responseStream).useDelimiter("\\A");
- String response = s.hasNext() ? s.next() : "";
- log.info("添加物流信息 response:{}",response);
- } catch (Exception e) {
- e.printStackTrace();
- }
- });
- return redisService.getStr(RedisService.key.ABROAD_SUCCESS_URL.getName() + orderId);
- }
- log.info("支付失败返回参数:"+ Jsons.toJson(payment));
- return paypalPayConfig.getCancelUrl();
- }
- public Payment createPayment(Long orderId,String successUrl) throws PayPalRESTException {
- OrderDon orderDon = orderDonService.getById(orderId);
- //paypal 不能购买奈飞月付账号 24-1-23
- if (orderDon.getSkuId() != null && orderDon.getSkuId() == 4) {
- throw BusinessRuntimeException.getInstance("暂不支持paypal购买该规格车票..");
- }
- redisService.set(RedisService.key.ABROAD_SUCCESS_URL.getName() + orderId,successUrl,RedisService.key.ABROAD_SUCCESS_URL.getTimeout());
- BigDecimal money = orderDon.getMoney().divide(new BigDecimal(7),2,RoundingMode.HALF_DOWN);
- orderDon.setAbroadMoney(money);
- orderDon.setType(OrderDon.Type.PAYPAL);
- orderDonService.updateById(orderDon);
- if (OrderDon.Status.hasPayment.equals(orderDon.getStatus())) {
- throw new BusinessRuntimeException(GatewayApiCode.METADATA_SYSTEM_ERROR.getCode(),"该捐款已支付");
- }
- PaypalPayConfig paypalPayConfig = paypalPayConfigService.getById(1);
- // Set payer details
- Payer payer = new Payer();
- payer.setPaymentMethod("paypal");
- // Set redirect URLs
- RedirectUrls redirectUrls = new RedirectUrls();
- redirectUrls.setCancelUrl(paypalPayConfig.getCancelUrl());
- String returnUrl = "https://" + paypalPayConfig.getHost() + "/8081/api/applets/order/paypal/notify";
- //成功回调地址(自己写的/pay/success)
- redirectUrls.setReturnUrl(returnUrl);
- Transaction transaction = new Transaction();
- transaction.setDescription("");
- transaction.setCustom(orderDon.getId().toString());
- //订单价格
- Amount amount = new Amount();
- amount.setCurrency("USD");
- // 支付的总价,paypal会校验 total = subTotal + tax + ...
- BigDecimal totalMoney = money.divide(new BigDecimal(100), 2, RoundingMode.HALF_DOWN);
- amount.setTotal(totalMoney.toString());
- // 设置各种费用
- Details details = new Details();
- //商品总价
- details.setSubtotal(totalMoney.toString());
- amount.setDetails(details);
- transaction.setAmount(amount);
- // Add transaction to a list
- List<Transaction> transactions = new ArrayList<Transaction>();
- transactions.add(transaction);
- // Add payment details
- Payment payment = new Payment();
- payment.setIntent("sale");
- payment.setPayer(payer);
- payment.setRedirectUrls(redirectUrls);
- payment.setTransactions(transactions);
- return payment.create(this.getAPIContext(paypalPayConfig.getClientId(),paypalPayConfig.getClientSecret(),paypalPayConfig.getMode()));
- }
- private APIContext getAPIContext(String clientId,String clientSecret,String mode) throws PayPalRESTException {
- Map<String, String> sdkConfig = new HashMap<>();
- sdkConfig.put("mode", mode);
- OAuthTokenCredential authTokenCredential = new OAuthTokenCredential(clientId,clientSecret,sdkConfig);
- APIContext apiContext = new APIContext(authTokenCredential.getAccessToken());
- apiContext.setConfigurationMap(sdkConfig);
- return apiContext;
- }
- /**
- * 执行支付
- */
- public Payment executePayment(String paymentId, String PayerID,String clientId,String clientSecret,String mode) throws PayPalRESTException {
- Payment payment = new Payment();
- payment.setId(paymentId);
- PaymentExecution paymentExecute = new PaymentExecution();
- paymentExecute.setPayerId(PayerID);
- return payment.execute(this.getAPIContext(clientId,clientSecret,mode), paymentExecute);
- }
- public Boolean refund(OrderRefundReq refundReq, OrderDon orderDon) throws PayPalRESTException {
- BigDecimal net = refundReq.getRefundMoney().divide(new BigDecimal(7),2,RoundingMode.HALF_DOWN).subtract(orderDon.getAbroadTransactionFee());;
- log.info("paypal return order:{},money:{}",orderDon.getId(),net);
- PaypalPayConfig paypalPayConfig = paypalPayConfigService.getById(1);
- APIContext apiContext = getAPIContext(paypalPayConfig.getClientId(), paypalPayConfig.getClientSecret(),paypalPayConfig.getMode());
- Sale sale = Sale.get(apiContext, orderDon.getTransactionId());
- Refund refund = new Refund();
- refund.setAmount(new Amount("USD", net.divide(new BigDecimal(100),2,RoundingMode.HALF_DOWN).toString()));
- refund = sale.refund(apiContext, refund);
- log.info("paypal return refund:{}",refund);
- if ("completed".equals(refund.getState())){
- orderDon.setStatus(OrderDon.Status.refund);
- orderDonService.updateById(orderDon);
- return true;
- }
- return false;
- }
- }
|