package com.app.service.order;

import com.app.Application;
import com.app.config.WXMPPayConfig;
import com.app.constant.SystemConstant;
import com.app.dto.wx.PrePayDto;
import com.app.entity.guardian.Guardian;
import com.app.entity.order.OpenCourseOrder;
import com.app.mapper.order.OpenCourseOrderMapper;
import com.app.service.guardian.GuardianService;
import com.app.util.DateUtil;
import com.app.util.HttpUtil;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)// 指定spring-boot的启动类
public class OpenCourseOrderServiceTest {

    @Autowired
    private OpenCourseOrderMapper mapper;

    @Autowired
    private OpenCourseOrderService openCourseOrderService;

    @Autowired
    private GuardianService guardianService;

    @Autowired
    private WXMPPayConfig wxmpPayConfig;

    @Autowired
    private HttpUtil httpUtil;

    /**
     * 功能描述：
     * 支付验收指引
     * https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=23_1&index=1
     */
    @Test
    public void testWXPrePay() {
        String accountId = SystemConstant.SYS_ACCOUNT_ID;
        String openId = SystemConstant.SYS_OPEN_ID;
        String orderId = "613799007247925248";
        PrePayDto prePayDto = openCourseOrderService.payToStart(accountId, openId, orderId);
        log.info("预支付：[{}]", prePayDto);
        Assert.assertTrue(!StringUtils.isEmpty(prePayDto.getPaySign()));
    }

    /**
     * 功能描述：
     * 微信支付仿真测试系统获取[密钥]
     * https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=23_1&index=1
     * 签名校验工具
     * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
     *
     * @return
     */
    @Test
    public void testGetSandboxKey() throws Exception {
        Map<String, String> sandboxKeyParam = new HashMap<>();
        sandboxKeyParam.put("mch_id", wxmpPayConfig.getMchID()); // 需要真实商户号
        sandboxKeyParam.put("nonce_str", WXPayUtil.generateNonceStr()); // 随机字符串
        String sign = WXPayUtil.generateSignature(sandboxKeyParam, wxmpPayConfig.getKey(), WXPayConstants.SignType.MD5); // 通过SDK生成签名其中API_KEY为商户对应的真实密钥
        sandboxKeyParam.put("sign", sign);

        String xml = WXPayUtil.mapToXml(sandboxKeyParam); // 将map转换为xml格式
        String sandboxKeyXml = httpUtil.post(wxmpPayConfig.getSandboxKeyUrl(), xml);
        log.info("[{}]", sandboxKeyXml);

        Map<String, String> sandboxKeyXmlParam = WXPayUtil.xmlToMap(sandboxKeyXml);
        log.info("[{}]", sandboxKeyXmlParam);
        log.info("返回状态码：[{}]", sandboxKeyXmlParam.get("return_code"));
        log.info("返回信息：[{}]", sandboxKeyXmlParam.get("return_msg"));
        log.info("商户号：[{}]", sandboxKeyXmlParam.get("mch_id"));
        log.info("沙箱密钥：[{}]", sandboxKeyXmlParam.get("sandbox_signkey"));
    }

    @Test
    public void wxNotify() throws Exception {
        String notityXml = "<xml>" +
                "<appid><![CDATA[wx2c9af1f91ac81be8]]></appid>" +
                "<bank_type><![CDATA[CMB_CREDIT]]></bank_type>" +
                "<cash_fee><![CDATA[100]]></cash_fee>" +
                "<fee_type><![CDATA[CNY]]></fee_type>" +
                "<is_subscribe><![CDATA[N]]></is_subscribe>" +
                "<mch_id><![CDATA[1546403921]]></mch_id>" +
                "<nonce_str><![CDATA[de5d586b2f0a4503b09007ecf54c8720]]></nonce_str>" +
                "<openid><![CDATA[oZrcK496Zuqdkm62Kf_iQeoqBcTk]]></openid>" +
                "<out_trade_no><![CDATA[657250491893284864]]></out_trade_no>" +
                "<result_code><![CDATA[SUCCESS]]></result_code>" +
                "<return_code><![CDATA[SUCCESS]]></return_code>" +
                "<sign><![CDATA[0A9ADDEB72D350A73F4F88BAF3D657A3]]></sign>" +
                "<time_end><![CDATA[20191217102649]]></time_end>" +
                "<total_fee>100</total_fee>" +
                "<trade_type><![CDATA[JSAPI]]></trade_type>" +
                "<transaction_id><![CDATA[4200000463201912176225868640]]></transaction_id>" +
                "</xml>";

        log.info("微信支付[回调] 参数：[{}]", notityXml);

        Map<String, String> notityParamMap = WXPayUtil.xmlToMap(notityXml);
        if (!"SUCCESS".equalsIgnoreCase(notityParamMap.get("return_code"))) {
            log.error("微信支付[回调] 错误：[{}]", notityParamMap.get("return_msg"));
        }

        String orderId = notityParamMap.get("out_trade_no"); // 获取商户订单号

        Optional<Guardian> optional = guardianService.findByOpenId(notityParamMap.get("openid"));
        if (optional.isPresent()) {
            Guardian _guardian = optional.get();

            String transactionId = notityParamMap.get("transaction_id"); // 微信支付订单号
            Date timeEnd = DateUtil.format(notityParamMap.get("time_end"), DateUtil.yyyyMMddHHmmss); // 支付完成时间
            Double paidPrice = BigDecimal.valueOf(Integer.parseInt(notityParamMap.get("total_fee"))).divide(new BigDecimal(100)).doubleValue(); // 订单金额(分转元)
            openCourseOrderService.payToEnd(orderId, _guardian.getId(), transactionId, paidPrice, timeEnd);
        }
    }

    /**
     * 功能描述：处理超时订单
     */
    @Test
    public void testHandleTimeoutOrder() {
        String orderId = "616416221792829440";
        Optional<OpenCourseOrder> optional = openCourseOrderService.findById(orderId);
        if (optional.isPresent()) {
            openCourseOrderService.handleTimeoutOrder(optional.get());
        }
    }

}
