package com.izouma.nineth;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.github.kevinsawicki.http.HttpRequest;
import com.izouma.nineth.utils.DateTimeUtils;
import com.izouma.nineth.utils.SnowflakeIdWorker;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class HMPayTest {
    private String appPrivateKey;
    private String appPublicKey;
    private String hmPublicKey;

    public HMPayTest() {
        try {
            this.appPrivateKey = new String(getClass().getClassLoader().getResourceAsStream("cert/hmpay_app_private_key.txt").readAllBytes()).trim();
            this.appPublicKey = new String(getClass().getClassLoader().getResourceAsStream("cert/hmpay_app_public_key.txt").readAllBytes()).trim();
            this.hmPublicKey = new String(getClass().getClassLoader().getResourceAsStream("cert/hmpay_public_key.txt").readAllBytes()).trim();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getSign(Map<String, String> params) {
        try {
            Map<String, String> m = new HashMap<>(params);
            m.remove("expire_time");
            m.remove("goods_name");
            m.remove("product_code");
            m.remove("clear_cycle");
            m.remove("jump_scheme");
            m.remove("meta_option");
            return AlipaySignature.rsaSign(m, appPrivateKey, "UTF-8");
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    private void encodeParams(Map<String, String> params) {
        List<String> arr = Arrays.asList("notify_url", "return_url", "goods_name", "meta_option", "sign", "pay_extra");
        params.forEach((k, v) -> {
            if (arr.contains(k)) {
                params.put(k, URLEncoder.encode(v, StandardCharsets.UTF_8));
            }
        });
    }

    @Test
    public void alih5() throws IOException, AlipayApiException {
        Map<String, String> params = new HashMap<>();
        params.put("version", "10");
        params.put("mer_no", "664403000025502");
        params.put("mer_order_no", new SnowflakeIdWorker(1, 1).nextId() + "");
        params.put("create_time", DateTimeUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss"));
        params.put("expire_time", DateTimeUtils.format(LocalDateTime.now().plusMinutes(3), "yyyyMMddHHmmss"));
        params.put("order_amt", "0.01");
        params.put("notify_url", "https://testorder.raex.vip/hmpay/notify/test/123");
        params.put("return_url", "https://test.raex.vip/9th/home");
        params.put("create_ip", "58_213_205_43");
        params.put("goods_name", "话费充值");
        params.put("store_id", "100001");
        params.put("product_code", "01020002");
        params.put("clear_cycle", "0"); //不参与签名
        params.put("meta_option", "[{\"s\":\"Android\",\"n\":\"绿洲宇宙\",\"id\":\"vip.raex.nft\",\"sc\":\"wzsc://\"},{\"s\":\"IOS\",\"n\":\"\",\"id\":\"\",\"sc\":\"\"}]"); //不参与签名
        params.put("jump_scheme", "hemacash://hmpay");
        params.put("sign_type", "RSA");
        params.put("accsplit_info", "N");
        params.put("sign", getSign(params));
        encodeParams(params);

//        String url = "https://cash.sandgate.cn/h5/?" +
//                params.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue())
//                        .collect(Collectors.joining("&")) + "#/hippoh5";
//        System.out.println(url);
        String url = "https://cash.sandgate.cn/h5/" +
                "?version=" + params.get("version") +
                "&mer_no=" + params.get("mer_no") +
                "&mer_order_no=" + params.get("mer_order_no") +
                "&create_time=" + params.get("create_time") +
                "&expire_time=" + params.get("expire_time") +
                "&order_amt=" + params.get("order_amt") +
                "&notify_url=" + params.get("notify_url") +
                "&return_url=" + params.get("return_url") +
                "&create_ip=" + params.get("create_ip") +
                "&goods_name=" + params.get("goods_name") +
                "&store_id=" + params.get("store_id") +
                "&product_code=" + params.get("product_code") +
                "&clear_cycle=" + params.get("clear_cycle") +
                "&meta_option=" + params.get("meta_option") +
                "&jump_scheme=" + params.get("jump_scheme") +
                "&accsplit_info=" + params.get("accsplit_info") +
                "&sign_type=" + params.get("sign_type") +
                "&sign=" + params.get("sign") +
                "#/hippoh5";
        System.out.println(url);

        String body = HttpRequest.post("https://cash.sandgate.cn/gateway/api")
                .contentType("application/json")
                .send(JSON.toJSONString(params)).body();
        System.out.println(JSON.toJSONString(JSON.parseObject(body), true));
    }

    @Test
    public void queryOrder() {
        Map<String, String> params = new HashMap<>();
        params.put("app_id", "664403000025502");
        params.put("method", "trade.query");
        params.put("timestamp", DateTimeUtils.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
        params.put("nonce", RandomStringUtils.randomAlphabetic(32));
        params.put("biz_content", "{\"out_order_no\":\"976535925569884160\"}");
        params.put("sign", getSign(params));
        String body = HttpRequest.post("https://hmpay.sandpay.com.cn/gateway/api")
                .contentType("application/json")
                .send(JSON.toJSONString(params)).body();
        JSONObject res = JSON.parseObject(body);
        System.out.println(JSON.toJSONString(res, true));

        JSONObject data = res.getJSONObject("data");
        System.out.println(JSON.toJSONString(data, true));
    }

    @Test
    public void refund() {
        Map<String, String> params = new HashMap<>();
        params.put("app_id", "664403000025502");
        params.put("method", "trade.refund");
        params.put("timestamp", DateTimeUtils.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
        params.put("nonce", RandomStringUtils.randomAlphabetic(32));

        Map<String, String> bizContent = new HashMap<>();
        bizContent.put("out_order_no", "975823871284482048");
        bizContent.put("refund_amount", "0.01");
        bizContent.put("refund_request_no", "975823871284482048");
        params.put("biz_content", JSON.toJSONString(bizContent));
        params.put("sign", getSign(params));
        String body = HttpRequest.post("https://hmpay.sandpay.com.cn/gateway/api")
                .contentType("application/json")
                .send(JSON.toJSONString(params)).body();
        JSONObject res = JSON.parseObject(body);
        System.out.println(JSON.toJSONString(res, true));

        JSONObject data = res.getJSONObject("data");
        System.out.println(JSON.toJSONString(data, true));
    }

    @Test
    public void queryRefund() {
        Map<String, String> params = new HashMap<>();
        params.put("app_id", "664403000025502");
        params.put("method", "trade.refund.query");
        params.put("timestamp", DateTimeUtils.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
        params.put("nonce", RandomStringUtils.randomAlphabetic(32));
        params.put("biz_content", "{\"out_order_no\":\"970096214148124672\",\"refund_request_no\":\"970096214148124672\"}");
        params.put("sign", getSign(params));
        String body = HttpRequest.post("https://hmpay.sandpay.com.cn/gateway/api")
                .contentType("application/json")
                .send(JSON.toJSONString(params)).body();
        JSONObject res = JSON.parseObject(body);
        System.out.println(JSON.toJSONString(res, true));

        JSONObject data = res.getJSONObject("data");
        System.out.println(JSON.toJSONString(data, true));
    }
}
