package cn.com.ty.lift.ud.pay.alipay;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeCloseModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayDataBillBalanceQueryRequest;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayDataBillBalanceQueryResponse;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;

/**
 * 支付宝服务类
 * 
 * @author sKing 2020年5月15日
 */
@Service
public class AlipaySupport {

    private static final Logger logger = LoggerFactory.getLogger(AlipaySupport.class);

    // private @Autowired AlipayConfig alipayConfig;
    private @Autowired AlipayClient alipayClient;

    /**
     * PC网站二维码支付接口
     * 
     * @param response
     * @param model
     * @param notifyUrl
     * @param returnUrl
     * @throws AlipayApiException
     * @throws IOException
     */
    public void tradePagePay(HttpServletResponse response, AlipayTradePagePayModel model, String notifyUrl,
        String returnUrl) throws AlipayApiException, IOException {
        AlipayTradePagePayRequest pagePayRequest = new AlipayTradePagePayRequest();
        /*
         * bizContent与bizModel两个参数是相同的效果，只设置其一即可。
         * bizModel：对象形式，更简洁，不容易出错。 
         * bizContent：json字符串形式，较麻烦，很容易出错。
         */
        pagePayRequest.setBizModel(model);
        pagePayRequest.setNotifyUrl(notifyUrl);
        pagePayRequest.setReturnUrl(returnUrl);

        // 调用SDK生成表单
        String form = alipayClient.pageExecute(pagePayRequest).getBody();
        // 直接将完整的表单html输出到页面
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write(form);
        response.getWriter().flush();
        response.getWriter().close();
    }

    /**
     * App支付接口 2.0
     * 
     * @param model
     *            model和biz_content同时存在的情况下取biz_content。
     * @param notifyUrl
     *            回调地址
     */
    public String tradeAppPay(AlipayTradeAppPayModel model, String notifyUrl) throws AlipayApiException {

        AlipayTradeAppPayRequest appPayRequest = new AlipayTradeAppPayRequest();
        appPayRequest.setBizModel(model);
        appPayRequest.setNotifyUrl(notifyUrl);
        // 直接返回body内容给APP端即可。
        return alipayClient.sdkExecute(appPayRequest).getBody();
    }

    /**
     * 交易查询接口。<br>
     * tradeNo和outTradeNo不能同时为空。
     * 
     * @param tradeNo
     * @param outTradeNo
     * @return 订单已支付返回true
     * @throws AlipayApiException
     */
    public boolean tradeQuery(String tradeNo, String outTradeNo) {
        // 不能同时为空。
        if (StringUtils.isBlank(tradeNo) && StringUtils.isBlank(outTradeNo)) {
            logger.error("====订单号和交易流水号不能同时为空====");
            return false;
        }

        // 构建订单查询参数。
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        model.setTradeNo(tradeNo);
        model.setOutTradeNo(outTradeNo);

        AlipayTradeQueryRequest tradeQueryRequest = new AlipayTradeQueryRequest();
        tradeQueryRequest.setBizModel(model);

        AlipayTradeQueryResponse tradeQueryResponse;
        try {
            // 证书签名类型时，需要调用certificateExecute查询交易状态。
            tradeQueryResponse = alipayClient.certificateExecute(tradeQueryRequest);
        } catch (AlipayApiException e) {
            logger.error("====查询订单支付状态时发生异常====");
            logger.error(e.getMessage());
            return false;
        }
        if (tradeQueryResponse.isSuccess()) {
            String tradeStatus = tradeQueryResponse.getTradeStatus();
            if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {
                return true;
            }
        }
        return false;
    }

    /**
     * Alipay转账
     * 
     * @param model
     *            model和biz_content同时存在的情况下取biz_content。
     */
    public AlipayFundTransUniTransferResponse transfer(AlipayFundTransUniTransferRequest appPayRequest)
        throws AlipayApiException {
        return alipayClient.certificateExecute(appPayRequest);
    }
    
    /**
     * Alipay查询商户余额
     * 
     * @param model
     *            model和biz_content同时存在的情况下取biz_content。
     */
    public AlipayDataBillBalanceQueryResponse  balanceQuery(AlipayDataBillBalanceQueryRequest  appPayRequest)
        throws AlipayApiException {
        return alipayClient.execute(appPayRequest);
    }

    /**
     * 交易关闭接口
     * 
     * @param tradeNo
     * @param outTradeNo
     */
    public void tradeClose(String tradeNo, String outTradeNo) {
        // 不能同时为空。
        if (StringUtils.isBlank(tradeNo) && StringUtils.isBlank(outTradeNo)) {
            logger.error("====订单号和交易流水号不能同时为空====");
            return;
        }

        // 构建交易关询参数。
        AlipayTradeCloseModel model = new AlipayTradeCloseModel();
        model.setTradeNo(tradeNo);
        model.setOutTradeNo(outTradeNo);

        AlipayTradeCloseRequest tradeCloseRequest = new AlipayTradeCloseRequest();
        tradeCloseRequest.setBizModel(model);

        AlipayTradeCloseResponse tradeCloseResponse;
        try {
            // 请求交易关闭接口
            tradeCloseResponse = alipayClient.certificateExecute(tradeCloseRequest);
        } catch (AlipayApiException e) {
            logger.error("====关闭支付宝交易时发生异常====");
            logger.error(e.getMessage());
            return;
        }
        if (tradeCloseResponse.isSuccess()) {
            logger.info("====关闭支付宝交易成功====");
        } else {
            logger.info("====关闭支付宝交易失败====");
            logger.info("code: {}", tradeCloseResponse.getCode());
            logger.info("msg: {}", tradeCloseResponse.getMsg());
            logger.info("sub_code: {}", tradeCloseResponse.getSubCode());
            logger.info("sub_msg: {}", tradeCloseResponse.getSubMsg());
        }
    }

}
