package com.softwarebr.nunu.service.pay.weixin.impl;

import com.alibaba.fastjson.JSON;
import com.brframework.commonweb.exception.HandleException;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import com.google.common.collect.Maps;
import com.softwarebr.nunu.util.ali.OrderInfoUtil2_0;
import com.softwarebr.nunu.domain.WxPayOrder;
import com.softwarebr.nunu.service.pay.weixin.WeiXinPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 微信支付
 *
 * @author lilin
 * @date 2019/12/26
 * @time 15:25
 */
@Service
@Slf4j
public class WeiXinPayServiceImpl implements WeiXinPayService {

    @Autowired(required = false)
    @Qualifier("wxPayService")
    WxPayService wxPayService;


    @Override
    public WxPayOrder tradeCreate(String payerUserId, String outTradeNo, Long totalAmount, String body, String client) {
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        WxPayConfig payConfig = wxPayService.getConfig();
        request.setBody(body);
        if(client.equals(WeiXinPayService.WEIXIN_TRADE_TYPE_APPLET)){
            request.setOpenid(payerUserId);
        }
        request.setOutTradeNo(outTradeNo);
        request.setSpbillCreateIp(SPBILL_CREATE_IP);
        request.setTotalFee(totalAmount.intValue());
        request.setNotifyUrl(payConfig.getNotifyUrl());
        request.setTradeType(client);
        WxPayOrder wxPayOrderResult = new WxPayOrder();
        payConfig.setTradeType(client);
        try {
            request.checkAndSign(payConfig);
            WxPayUnifiedOrderResult unifiedOrder = wxPayService.unifiedOrder(request);
            String timeStamp = String.valueOf(System.currentTimeMillis()/1000);
            String resultSign = resultSign(payConfig.getMchKey(), payConfig.getAppId(), unifiedOrder.getNonceStr(), unifiedOrder.getPrepayId(), timeStamp, unifiedOrder.getMchId());
            wxPayOrderResult.setSign(resultSign);
            wxPayOrderResult.setWxPayResult(JSON.toJSONString(unifiedOrder));
            wxPayOrderResult.setTimeStamp(timeStamp);
        } catch (WxPayException e) {
            log.error("微信支付出现异常：", e.getErrCodeDes());
            throw new HandleException("微信支付出现异常"+e.getErrCodeDes());
        }
        return wxPayOrderResult;
    }

    /**
     * 返回结果签名
     *
     * @param signKey   商户秘钥
     * @param appId     appId
     * @param nonceStr  随机码
     * @param prepayId  下单返回的支付交易会话ID
     * @param timeStamp 时间戳
     * @param mchId     商户号
     * @return
     */
    private String resultSign(String signKey, String appId, String nonceStr, String prepayId, String timeStamp, String mchId) {
        Map<String, String> params = Maps.newHashMap();
        params.put("appid", appId);
        params.put("partnerid", mchId);
        params.put("prepayid", prepayId);
        params.put("package", "Sign=WXPay");
        params.put("noncestr", nonceStr);
        params.put("timestamp", timeStamp);
        return SignUtils.createSign(params, WxPayConstants.SignType.MD5, signKey, new String[0]);
    }

    @Override
    public WxPayRefundResult tradeRefund(String outTradeNo, Long totalAmount, Long refundAmount, String client, String body) {
        WxPayRefundRequest request = new WxPayRefundRequest();
        WxPayConfig payConfig = wxPayService.getConfig();
        request.setOpUserId(payConfig.getMchId());
        request.setOutTradeNo(outTradeNo);
        request.setRefundFee(refundAmount.intValue());
        request.setTotalFee(totalAmount.intValue());
        request.setOutRefundNo(OrderInfoUtil2_0.getOutTradeNo());
        request.setRefundDesc(body);
        WxPayRefundResult refund ;
        try {
            request.checkAndSign(payConfig);
            refund = wxPayService.refund(request);
        } catch (Exception e) {
            log.error("微信退款出现异常：{}", e.getMessage());
            throw new HandleException("微信退款出现异常"+e.getMessage());
        }
        return refund;
    }

}
