package com.cyksj.service.stripe; import com.baomidou.mybatisplus.core.toolkit.Wrappers; 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.mapper.StripePayConfigMapper; import com.cyksj.model.entity.OrderDon; import com.cyksj.model.entity.OrderMasterDon; import com.cyksj.model.entity.StripePayConfig; import com.cyksj.model.request.OrderRefundReq; import com.cyksj.service.order.OrderDonService; import com.cyksj.service.order.OrderMasterDonService; import com.stripe.Stripe; import com.stripe.exception.StripeException; import com.stripe.model.*; import com.stripe.model.checkout.Session; import com.stripe.param.RefundCreateParams; import com.stripe.param.checkout.SessionCreateParams; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Date; import java.util.HashMap; import java.util.List; /** * @author zwhui * @date 2021/6/21 11:03 上午 */ @Service @Slf4j @RequiredArgsConstructor public class StripeService { private static final GlobalThreadPoolTaskExecutor THREAD_POOL = GlobalThreadPoolTaskExecutor.getInstance(); private final OrderDonService orderDonService; private final StripePayConfigMapper stripePayConfigMapper; private final OrderMasterDonService orderMasterDonService; public String checkOutStripe(Long mOid,String successUrl) throws Exception{ OrderMasterDon orderDon = orderMasterDonService.getById(mOid); BigDecimal money = orderDon.getMoney(); orderDon.setType(OrderMasterDon.Type.STRIPE); orderMasterDonService.updateById(orderDon); HashMap responseData = new HashMap(); if (!orderDon.getStatus().equals(OrderMasterDon.Status.noPayment) && !orderDon.getStatus().equals(OrderMasterDon.Status.close)) { throw new BusinessRuntimeException(GatewayApiCode.METADATA_SYSTEM_ERROR.getCode(),"The donation has been paid"); } StripePayConfig stripePayConfig = stripePayConfigMapper.selectById(1); try { Stripe.apiKey = stripePayConfig.getApiKey(); SessionCreateParams params = SessionCreateParams.builder() .setMode(SessionCreateParams.Mode.PAYMENT) .setSuccessUrl(successUrl) .setCancelUrl(stripePayConfig.getCancelUrl()) .setClientReferenceId(orderDon.getId().toString()) .addLineItem( SessionCreateParams.LineItem.builder() .setQuantity(1L) .setPriceData( SessionCreateParams.LineItem.PriceData.builder() .setCurrency("USD") .setUnitAmount(money.longValue()) .setProductData( SessionCreateParams.LineItem.PriceData.ProductData.builder() .setName("donation") .setDescription("donation") .build()).build()).build()).build(); Session session = Session.create(params); responseData.put("id", session.getId()); } catch (StripeException e) { e.printStackTrace(); } return Jsons.toJson(responseData); } public void fulfillOrder(Session session) throws Exception{ if (null == session){ log.error("支付回调失败"); return; } String mOid = session.getClientReferenceId(); if (!"paid".equals(session.getPaymentStatus())){ return; } OrderMasterDon masterDon = orderMasterDonService.getById(mOid); if (masterDon == null){ return; } if (!masterDon.getStatus().equals(OrderMasterDon.Status.noPayment) && !masterDon.getStatus().equals(OrderMasterDon.Status.close)) { log.info("支付宝已回调,重复修改状态 id:{}", masterDon.getId()); return; } String paymentIntentId = session.getPaymentIntent(); PaymentIntent paymentIntent = PaymentIntent.retrieve(paymentIntentId); String chargeId = paymentIntent.getLatestCharge(); BalanceTransaction balanceTransaction = BalanceTransaction.retrieve(Charge.retrieve(chargeId).getBalanceTransaction()); //更新订单支付状态 masterDon.setTransactionId(chargeId); masterDon.setAbroadTransactionFee(BigDecimal.valueOf(balanceTransaction.getFee())); masterDon.setPayTime(new Date()); masterDon.setStatus(OrderMasterDon.Status.hasPayment); log.info("支付成功订单:"+mOid+",支付交易号:"+chargeId); log.info("支付成功订单:"+mOid+",返回参数:"+Jsons.toJson(session)); //子订单 List orderDonList = orderDonService.list(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getMOid, mOid)); orderDonList.forEach(orderDon->{ if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) { orderDon.setType(OrderDon.Type.STRIPE); } orderDonService.orderNotify(orderDon); }); } public Boolean refund(OrderRefundReq refundReq, OrderDon orderDon) throws StripeException { BigDecimal net = refundReq.getRefundMoney().divide(new BigDecimal(7),2, RoundingMode.HALF_DOWN).subtract(orderDon.getAbroadTransactionFee()); log.info("stripe return order:{},money:{}",orderDon.getId(),net); StripePayConfig stripePayConfig = stripePayConfigMapper.selectById(1); Stripe.apiKey = stripePayConfig.getApiKey(); RefundCreateParams params = RefundCreateParams.builder() .setCharge(orderDon.getTransactionId()) .setAmount(net.longValue()) .build(); Refund refund = Refund.create(params); log.info("stripe return refund:{}",refund); if ("succeeded".equals(refund.getStatus())){ orderDon.setStatus(OrderDon.Status.refund); orderDonService.updateById(orderDon); return true; } return false; } }