package com.cyksj.service.order.impl;

import cn.hutool.core.util.StrUtil;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyksj.common.exception.BusinessRuntimeException;
import com.cyksj.common.util.Codec;
import com.cyksj.config.WeChatConfig;
import com.cyksj.config.zfb.AliPayClientFactory;
import com.cyksj.mapper.*;
import com.cyksj.mapper.channel.ShopConfigMapper;
import com.cyksj.mapper.vip.VipOrderDonMapper;
import com.cyksj.model.entity.*;
import com.cyksj.model.request.OrderRefundReq;
import com.cyksj.service.order.OrderRefundService;
import com.cyksj.service.wechat.WeChatService;
import com.paypal.api.payments.Amount;
import com.paypal.api.payments.Refund;
import com.paypal.api.payments.Sale;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.OAuthTokenCredential;
import com.paypal.base.rest.PayPalRESTException;
import com.stripe.Stripe;
import com.stripe.exception.StripeException;
import com.stripe.param.RefundCreateParams;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 项目名: yhlxj
 * 文件名: OrderRefundServiceImpl
 * 创建者: JavaZou
 * 创建时间:2023/12/4 14:36
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class OrderRefundServiceImpl implements OrderRefundService {

	private final OrderDonMapper orderDonMapper;

	private final PaypalPayConfigMapper paypalPayConfigMapper;

	private final WeChatService weChatService;

	private final WeChatConfig weChatConfig;

	private final StripePayConfigMapper stripePayConfigMapper;

	private final ShopConfigMapper shopConfigMapper;

	private final RefundOrderDonMapper refundOrderDonMapper;

	private final RefundUpgradeOrderDonMapper refundUpgradeOrderDonMapper;

	private final SpotifyUserUpgradeOrderMapper spotifyUserUpgradeOrderMapper;

	private final VipOrderDonMapper vipOrderDonMapper;

	@Override
	public String centerRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
		OrderDon.Type type = orderDon.getType();
		String refundType = refundReq.getRefundType();
		if (type == OrderDon.Type.WeChat && !refundType.equals(OrderDon.Type.BALANCE.getType())) {
			return wxRefund(refundReq, orderDon.getId(), orderDon.getShopId(), orderDon.getTransactionId(), orderDon.getMoney());
		}
		if (type == OrderDon.Type.ALI_PAY && !refundType.equals(OrderDon.Type.BALANCE.getType())) {
			return zfbRefund(refundReq, orderDon.getId(), orderDon.getShopId(), orderDon.getTransactionId(), orderDon.getMoney());
		}
		if (type == OrderDon.Type.PAYPAL && !refundType.equals(OrderDon.Type.BALANCE.getType())) {
			if (!paypalRefund(refundReq, orderDon)) {
				throw BusinessRuntimeException.getInstance("paypal退款失败");
			}
		}
		if (type == OrderDon.Type.STRIPE && !refundType.equals(OrderDon.Type.BALANCE.getType())) {
			if (!stripeRefund(refundReq, orderDon)) {
				throw BusinessRuntimeException.getInstance("stripe退款失败");
			}
		}
		return StrUtil.EMPTY;
	}

	@Override
	public String centerUpgradeRefund(OrderRefundReq refundReq, UpgradeOrderDon orderDon) throws Exception {
		UpgradeOrderDon.Type type = orderDon.getType();
		String refundType = refundReq.getRefundType();
		if (type == UpgradeOrderDon.Type.ALI_PAY && !refundType.equals(OrderDon.Type.BALANCE.getType())) {
			return zfbUpgradeRefund(refundReq, orderDon);
		}
		return StrUtil.EMPTY;
	}

	@Override
	public void refundRecord(OrderDon orderDon, BigDecimal refundMoney, BigDecimal refundBalance, String operator, GoodsDon goodsDon, GoodsDonSku sku, String outRefundNo, String refundType, String chatImg) {
		RefundOrderDon refund = new RefundOrderDon();
		refund.setOrderId(orderDon.getId());
		refund.setOutRefundNo(outRefundNo);
		refund.setTotalFee(orderDon.getMoney());
		refund.setRefundDesc(orderDon.getRefundDesc());
		//退款金额
		refund.setRefundFee(refundMoney);
		refund.setUserId(orderDon.getUserId());
		refund.setGoodsId(orderDon.getGoodsId());
		refund.setGoodsTitle(goodsDon == null ? null : goodsDon.getTitle());
		refund.setSkuId(orderDon.getSkuId());
		refund.setSpecVal(sku == null ? null : String.format("%s%s", sku.getSpecVal(), sku.getPrice().divide(BigDecimal.valueOf(100))));
		refund.setRefundMethod(orderDon.getType().name());
		refund.setGoodsType(goodsDon == null ? 0 : goodsDon.getType());
		refund.setOperator(operator);
		refund.setChatImg(chatImg);
		//退款方式
		if (StrUtil.isNotBlank(refundType) && refundType.equals(OrderDon.Type.BALANCE.getType())) {
			refund.setRefundMethod(refundType);
			refund.setRefundFee(orderDon.getRefundBalance());
		}
		//余额现金退款
		if (OrderRefundReq.RefundType.bxj.name().equals(refundType)) {
			refund.setRefundMethod(OrderRefundReq.RefundType.bxj.name());
			refund.setRefundBalance(refundBalance);
		}
		refundOrderDonMapper.insert(refund);
	}

	@Override
	public void refundUpgradeRecord(UpgradeOrderDon orderDon, BigDecimal refundMoney, BigDecimal refundBalance, UpgradePackage upgradePackage, String operator, String outRefundNo, String refundType, String chatImg) {
		RefundUpgradeOrderDon refund = new RefundUpgradeOrderDon();
		refund.setOrderId(orderDon.getId());
		refund.setOutRefundNo(outRefundNo);
		refund.setTotalFee(orderDon.getMoney());
		refund.setRefundDesc(orderDon.getRefundDesc());
		//退款金额
		refund.setRefundFee(refundMoney);
		refund.setUserId(orderDon.getUserId());
		refund.setPackageId(orderDon.getPackageId());
		refund.setPackageName(upgradePackage == null ? null : upgradePackage.getName());
		refund.setRefundMethod(orderDon.getType().name());
		refund.setOperator(operator);
		refund.setChatImg(chatImg);
		//退款方式
		if (StrUtil.isNotBlank(refundType) && refundType.equals(OrderDon.Type.BALANCE.getType())) {
			refund.setRefundMethod(refundType);
			refund.setRefundFee(orderDon.getRefundBalance());
		}
		//余额现金退款
		if (OrderRefundReq.RefundType.bxj.name().equals(refundType)) {
			refund.setRefundMethod(OrderRefundReq.RefundType.bxj.name());
			refund.setRefundBalance(refundBalance);
		}
		refundUpgradeOrderDonMapper.insert(refund);
	}

	@Override
	public String refundWholesaleUserDeposit(GoodsWholesaleUserDeposit goodsWholesaleUserDeposit) throws Exception {
		GoodsWholesaleUserDeposit.Type type = goodsWholesaleUserDeposit.getType();
		if (type == GoodsWholesaleUserDeposit.Type.WeChat) {
			return wxRefundWholesaleUserDeposit(goodsWholesaleUserDeposit);
		}
		if (type == GoodsWholesaleUserDeposit.Type.ALI_PAY) {
			return zfbRefundWholesaleUserDeposit(goodsWholesaleUserDeposit);
		}
		return StrUtil.EMPTY;
	}

	private String wxRefundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception {
		BigDecimal money = orderDon.getRefundMoney();
		if (money.compareTo(BigDecimal.ZERO) <=0){
			return StrUtil.EMPTY;
		}
		long time = System.currentTimeMillis();
		//退款订单号
		String outRefundNo = Codec.DoDigest.custom()
				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
				.setStringData(time + String.valueOf(orderDon.getId()))
				.toHexString();
		log.info("退押金退款订单号:{}", outRefundNo);
		weChatService.refundWxOrder(weChatConfig.getAppid(),
				Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.WX_DEFAULT_APP_ID),
				orderDon.getTransactionId(),
				outRefundNo,
				money,
				money,
				weChatConfig.getDomain() + "manage/goods/whole/sale/deposit/refund/notify");
		//记录退款信息
		return outRefundNo;
	}

	private String zfbRefundWholesaleUserDeposit(GoodsWholesaleUserDeposit goodsWholesaleUserDeposit) throws Exception {
		BigDecimal money = goodsWholesaleUserDeposit.getMoney();
		if (money.compareTo(BigDecimal.ZERO) <=0){
			return StrUtil.EMPTY;
		}
		AlipayTradeRefundResponse response;
		//支付宝退款
		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(goodsWholesaleUserDeposit.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
		//支付宝交易号
		model.setTradeNo(goodsWholesaleUserDeposit.getTransactionId());
		model.setRefundAmount(money.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_EVEN).toString());
		model.setQueryOptions(List.of("gmt_refund_pay"));
		long time = System.currentTimeMillis();
		//退款订单号
		String outRefundNo = Codec.DoDigest.custom()
				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
				.setStringData(time + String.valueOf(goodsWholesaleUserDeposit.getId()))
				.toHexString();
		//退款请求号
		model.setOutRequestNo(outRefundNo);
		request.setBizModel(model);
		String shopId = goodsWholesaleUserDeposit.getShopId();
		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, goodsWholesaleUserDeposit.getShopId()));
		if (shopId != null && shopConfig != null && shopConfig.getIsCert()) {
			response = alipayClient.certificateExecute(request);
		} else {
			response = alipayClient.execute(request);
		}
		if (!response.isSuccess()) throw BusinessRuntimeException.getInstance("退款失败,e:{0}", response.getSubMsg());
		return outRefundNo;
	}

	private String wxRefundWholesaleUserDeposit(GoodsWholesaleUserDeposit goodsWholesaleUserDeposit) throws Exception {
		BigDecimal money = goodsWholesaleUserDeposit.getMoney();
		if (money.compareTo(BigDecimal.ZERO) <=0){
			return StrUtil.EMPTY;
		}
		long time = System.currentTimeMillis();
		//退款订单号
		String outRefundNo = Codec.DoDigest.custom()
				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
				.setStringData(time + String.valueOf(goodsWholesaleUserDeposit.getId()))
				.toHexString();
		log.info("退押金退款订单号:{}", outRefundNo);
		weChatService.refundWxOrder(weChatConfig.getAppid(),
				Optional.ofNullable(goodsWholesaleUserDeposit.getShopId()).orElse(ShopConfig.WX_DEFAULT_APP_ID),
				goodsWholesaleUserDeposit.getTransactionId(),
				outRefundNo,
				money,
				money,
				weChatConfig.getDomain() + "manage/goods/whole/sale/deposit/refund/notify");
		//记录退款信息
		return outRefundNo;
	}

	public String wxRefund(OrderRefundReq refundReq, Long orderId, String shopId, String transactionId, BigDecimal orderMoney) throws Exception {
		if (orderMoney.compareTo(BigDecimal.ZERO) <= 0) {
			return StrUtil.EMPTY;
		}
		long time = System.currentTimeMillis();
		//退款订单号
		String outRefundNo = Codec.DoDigest.custom()
				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
				.setStringData(time + String.valueOf(orderId))
				.toHexString();
		weChatService.refundWxOrder(weChatConfig.getAppid(),
				Optional.ofNullable(shopId).orElse(ShopConfig.WX_DEFAULT_APP_ID),
				transactionId,
				outRefundNo,
				orderMoney,
				refundReq.getRefundMoney(),
				weChatConfig.getNotifyDomain() + "manage/order/wx/refund/notify");
		//记录退款信息
		return outRefundNo;
	}

	public String zfbRefund(OrderRefundReq refundReq,  Long orderId, String shopId, String transactionId, BigDecimal orderMoney) throws Exception {
		if (orderMoney.compareTo(BigDecimal.ZERO) <=0){
			return StrUtil.EMPTY;
		}
		AlipayTradeRefundResponse response;
		//支付宝退款
		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(shopId).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
		//支付宝交易号
		model.setTradeNo(transactionId);
		model.setRefundAmount(refundReq.getRefundMoney().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_EVEN).toString());
		model.setQueryOptions(List.of("gmt_refund_pay"));
		long time = System.currentTimeMillis();
		//退款订单号
		String outRefundNo = Codec.DoDigest.custom()
				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
				.setStringData(time + String.valueOf(orderId))
				.toHexString();
		//退款请求号
		model.setOutRequestNo(outRefundNo);
		request.setBizModel(model);
		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, shopId));
		if (shopId != null && shopConfig != null && shopConfig.getIsCert()) {
			response = alipayClient.certificateExecute(request);
		} else {
			response = alipayClient.execute(request);
		}
		if (!response.isSuccess()) throw BusinessRuntimeException.getInstance("退款失败,e:{0}", response.getSubMsg());
//			AliPayRefundRep aliPayRefundRep = Jsons.parseObject(response.getBody(), AliPayRefundRep.class);
//			AliPayRefundRep.AlipayTradeRefundResponse res = aliPayRefundRep.getResponse();
//			orderDon.setRefundMoney(res.getRefundFee().multiply(BigDecimal.valueOf(100)));
		return outRefundNo;
	}


	public String zfbUpgradeRefund(OrderRefundReq refundReq, UpgradeOrderDon orderDon) throws Exception {
		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) <=0){
			return StrUtil.EMPTY;
		}
		AlipayTradeRefundResponse response;
		//支付宝退款
		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
		//支付宝交易号
		model.setTradeNo(orderDon.getTransactionId());
		model.setRefundAmount(refundReq.getRefundMoney().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_EVEN).toString());
		model.setQueryOptions(List.of("gmt_refund_pay"));
		long time = System.currentTimeMillis();
		//退款订单号
		String outRefundNo = Codec.DoDigest.custom()
				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
				.setStringData(time + String.valueOf(orderDon.getId()))
				.toHexString();
		//退款请求号
		model.setOutRequestNo(outRefundNo);
		request.setBizModel(model);
		String shopId = orderDon.getShopId();
		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, orderDon.getShopId()));
		if (shopId != null && shopConfig != null && shopConfig.getIsCert()) {
			response = alipayClient.certificateExecute(request);
		} else {
			response = alipayClient.execute(request);
		}
		if (!response.isSuccess()) throw BusinessRuntimeException.getInstance("退款失败,e:{0}", response.getSubMsg());
//			AliPayRefundRep aliPayRefundRep = Jsons.parseObject(response.getBody(), AliPayRefundRep.class);
//			AliPayRefundRep.AlipayTradeRefundResponse res = aliPayRefundRep.getResponse();
//			orderDon.setRefundMoney(res.getRefundFee().multiply(BigDecimal.valueOf(100)));
		return outRefundNo;
	}


	public Boolean paypalRefund(OrderRefundReq refundReq, OrderDon orderDon) throws PayPalRESTException {
		BigDecimal net = refundReq.getRefundMoney().divide(new BigDecimal(7), 2, RoundingMode.HALF_DOWN);
		//非补差价 需要扣除手续费
		if (!refundReq.getIsDiffer()) {
			net = net.subtract(orderDon.getAbroadTransactionFee());
		}
		log.info("paypal return order:{},money:{}",orderDon.getId(),net);
		PaypalPayConfig paypalPayConfig = paypalPayConfigMapper.selectById(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);
			orderDonMapper.updateById(orderDon);
			return true;
		}
		return false;
	}

	public Boolean stripeRefund(OrderRefundReq refundReq, OrderDon orderDon) throws StripeException {
		BigDecimal net = refundReq.getRefundMoney().divide(new BigDecimal(7), 2, RoundingMode.HALF_DOWN);
		if (!refundReq.getIsDiffer()) {
			net = net.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();
		com.stripe.model.Refund refund = com.stripe.model.Refund.create(params);
		log.info("stripe return refund:{}",refund);
		if ("succeeded".equals(refund.getStatus())){
			orderDon.setStatus(OrderDon.Status.refund);
			orderDonMapper.updateById(orderDon);
			return true;
		}
		return false;
	}

	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;
	}

	@Override
	public String refundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception {
		GoodsWholesaleOrderDon.Type type = orderDon.getType();
		if (type == GoodsWholesaleOrderDon.Type.WeChat) {
			return wxRefundWholesaleOrder(orderDon);
		}
		if (type == GoodsWholesaleOrderDon.Type.ALI_PAY) {
			return zfbRefundWholesaleOrder(orderDon);
		}
		return StrUtil.EMPTY;
	}

	@Override
	public String refundUserMirrorShopFee(UserMirrorShopFeeOrderDon orderDon) throws Exception {
		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) <=0){
			return StrUtil.EMPTY;
		}
		AlipayTradeRefundResponse response;
		//支付宝退款
		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
		//支付宝交易号
		model.setTradeNo(orderDon.getTransactionId());
		model.setRefundAmount(orderDon.getMoney().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_EVEN).toString());
		model.setQueryOptions(List.of("gmt_refund_pay"));
		long time = System.currentTimeMillis();
		//退款订单号
		String outRefundNo = Codec.DoDigest.custom()
				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
				.setStringData(time + String.valueOf(orderDon.getId()))
				.toHexString();
		//退款请求号
		model.setOutRequestNo(outRefundNo);
		request.setBizModel(model);
		String shopId = orderDon.getShopId();
		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, orderDon.getShopId()));
		if (shopId != null && shopConfig != null && shopConfig.getIsCert()) {
			response = alipayClient.certificateExecute(request);
		} else {
			response = alipayClient.execute(request);
		}
		if (!response.isSuccess()) throw BusinessRuntimeException.getInstance("退款失败,e:{0}", response.getSubMsg());
		return outRefundNo;
	}

	@Override
	public void refundSpotifyUpgrade(Long orderId) throws Exception {
		SpotifyUserUpgradeOrder order = spotifyUserUpgradeOrderMapper.selectById(orderId);
		if (order == null) {
			throw BusinessRuntimeException.getInstance("订单不存在");
		}
		if (order.getStatus() != SpotifyUserUpgradeOrder.Status.hasPayment) {
			throw BusinessRuntimeException.getInstance("订单状态异常");
		}
		BigDecimal money = order.getMoney();
		if (money.compareTo(BigDecimal.ZERO) <=0){
			return;
		}
		AlipayTradeRefundResponse response;
		//支付宝退款
		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(order.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
		//支付宝交易号
		model.setTradeNo(order.getTransactionId());
		model.setRefundAmount(money.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_EVEN).toString());
		model.setQueryOptions(List.of("gmt_refund_pay"));
		long time = System.currentTimeMillis();
		//退款订单号
		String outRefundNo = Codec.DoDigest.custom()
				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
				.setStringData(time + String.valueOf(order.getId()))
				.toHexString();
		log.info("spotify升级订单oid:{}退款订单号：{}", orderId, outRefundNo);
		//退款请求号
		model.setOutRequestNo(outRefundNo);
		request.setBizModel(model);
		String shopId = order.getShopId();
		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, order.getShopId()));
		if (shopId != null && shopConfig != null && shopConfig.getIsCert()) {
			response = alipayClient.certificateExecute(request);
		} else {
			response = alipayClient.execute(request);
		}
		if (!response.isSuccess()) throw BusinessRuntimeException.getInstance("退款失败,e:{0}", response.getSubMsg());
		order.setStatus(SpotifyUserUpgradeOrder.Status.refund);
		spotifyUserUpgradeOrderMapper.updateById(order);
	}

	@Override
	public String vipCenterRefund(OrderRefundReq refundReq, VipOrderDon orderDon) throws Exception {
		VipOrderDon.Type type = orderDon.getType();
		String refundType = refundReq.getRefundType();
		if (type == VipOrderDon.Type.WeChat && !refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
			return wxRefund(refundReq, orderDon.getId(), orderDon.getShopId(), orderDon.getTransactionId(), orderDon.getMoney());
		}
		if (type == VipOrderDon.Type.ALI_PAY && !refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
			return zfbRefund(refundReq, orderDon.getId(), orderDon.getShopId(), orderDon.getTransactionId(), orderDon.getMoney());
		}
		if (type == VipOrderDon.Type.PAYPAL && !refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
			if (!paypalRefundVipOrder(refundReq, orderDon)) {
				throw BusinessRuntimeException.getInstance("paypal退款失败");
			}
		}
		if (type == VipOrderDon.Type.STRIPE && !refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
			if (!stripeRefundVipOrder(refundReq, orderDon)) {
				throw BusinessRuntimeException.getInstance("stripe退款失败");
			}
		}
		return StrUtil.EMPTY;
	}

	private String zfbRefundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception {
		BigDecimal money = orderDon.getRefundMoney();
		if (money.compareTo(BigDecimal.ZERO) <=0){
			return StrUtil.EMPTY;
		}
		AlipayTradeRefundResponse response;
		//支付宝退款
		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
		//支付宝交易号
		model.setTradeNo(orderDon.getTransactionId());
		model.setRefundAmount(money.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_EVEN).toString());
		model.setQueryOptions(List.of("gmt_refund_pay"));
		long time = System.currentTimeMillis();
		//退款订单号
		String outRefundNo = Codec.DoDigest.custom()
				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
				.setStringData(time + String.valueOf(orderDon.getId()))
				.toHexString();
		//退款请求号
		model.setOutRequestNo(outRefundNo);
		request.setBizModel(model);
		String shopId = orderDon.getShopId();
		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, orderDon.getShopId()));
		if (shopId != null && shopConfig != null && shopConfig.getIsCert()) {
			response = alipayClient.certificateExecute(request);
		} else {
			response = alipayClient.execute(request);
		}
		if (!response.isSuccess()) throw BusinessRuntimeException.getInstance("退款失败,e:{0}", response.getSubMsg());
		return outRefundNo;
	}

	private boolean stripeRefundVipOrder(OrderRefundReq refundReq, VipOrderDon orderDon) throws StripeException {
		BigDecimal net = refundReq.getRefundMoney().divide(new BigDecimal(7), 2, RoundingMode.HALF_DOWN);
		if (!refundReq.getIsDiffer()) {
			net = net.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();
		com.stripe.model.Refund refund = com.stripe.model.Refund.create(params);
		log.info("stripe return refund:{}",refund);
		if ("succeeded".equals(refund.getStatus())){
			orderDon.setStatus(VipOrderDon.Status.refund);
			vipOrderDonMapper.updateById(orderDon);
			return true;
		}
		return false;
	}

	private boolean paypalRefundVipOrder(OrderRefundReq refundReq, VipOrderDon orderDon) throws PayPalRESTException {
		BigDecimal net = refundReq.getRefundMoney().divide(new BigDecimal(7), 2, RoundingMode.HALF_DOWN);
		//非补差价 需要扣除手续费
		if (!refundReq.getIsDiffer()) {
			net = net.subtract(orderDon.getAbroadTransactionFee());
		}
		log.info("paypal return order:{},money:{}",orderDon.getId(),net);
		PaypalPayConfig paypalPayConfig = paypalPayConfigMapper.selectById(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(VipOrderDon.Status.refund);
			vipOrderDonMapper.updateById(orderDon);
			return true;
		}
		return false;
	}
}
