package com.fs.wx.utils;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.http.*;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.HashMap;

@Slf4j
public class WxPayUtils {

    /**
     * 发起转账
     *
     * @param outBillNo 商户单号
     * @param openId    openId
     * @param userName  用户实名
     * @param amount    转账金额（单位：分）
     */
    public void createTransferBills(String outBillNo, String openId, String userName, Long amount) {
        OkHttpClient okHttpClient = new OkHttpClient();
        HttpClient httpClient = new DefaultHttpClientBuilder()
                .config(rsaAutoCertificateConfig())
                .okHttpClient(okHttpClient)
                .build();
        HttpHeaders headers = new HttpHeaders();
        headers.addHeader("Authorization","");
        headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Wechatpay-Serial", rsaEncryptOAEP("696D09084C2B091DF44A8CE31DF907BBC93196A7"));

        HashMap<Object, Object> map = new HashMap<>();
        // 商户AppID
        map.put("appid", "小程序APPID");
        // 商户单号
        map.put("out_bill_no", outBillNo);
        // 转账场景ID
        map.put("transfer_scene_id", "1001");
        // 收款用户OpenID
        map.put("openid", openId);
//        // 收款用户姓名（需要加密传入）
//        if (StringUtils.isNotBlank(userName)) {
//            map.put("user_name", rsaEncryptOAEP(userName));
//        }
        // 转账金额（单位：分）
        map.put("transfer_amount", amount);
        // 转账备注
        map.put("transfer_remark", "课堂答题奖励");
        // 回调通知地址
        map.put("notify_url", "https://h5api.ylrzcloud.com/app/wxpay/TransferNotify");
        // 用户收款感知
        map.put("user_recv_perception", "现金奖励");
        // 转账场景报备信息
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(new JSONObject().fluentPut("info_type", "活动名称").fluentPut("info_content", "答题有礼"));
        jsonArray.add(new JSONObject().fluentPut("info_type", "奖励说明").fluentPut("info_content", "答题成功奖励红包"));
        map.put("transfer_scene_report_infos", jsonArray);

        JsonRequestBody build = new JsonRequestBody.Builder()
                .body(JSONUtil.toJsonStr(map))
                .build();
        HttpRequest executeSendGetHttpRequest = new HttpRequest.Builder()
                .httpMethod(HttpMethod.POST)
                .url("https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills")
                .headers(headers)
                .body(build)
                .build();
        try {
            HttpResponse<Response> execute = httpClient.execute(executeSendGetHttpRequest, Response.class);
            ResponseBody responseBody = execute.getBody();
            JSONObject jsonObject = JSONObject.parseObject(responseBody.toString());
            log.info("发起转账返回：{}", jsonObject.toJSONString());
        } catch (ServiceException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * API安全加密配置
     */
    private RSAAutoCertificateConfig rsaAutoCertificateConfig() {
        return new RSAAutoCertificateConfig.Builder()
                // 商户号
                .merchantId("1708360153")
                // 商户API证书私钥的存放路径
                .privateKeyFromPath("C:\\cert\\apiclient_key.pem")
                // 商户API证书序列号
                .merchantSerialNumber("696D09084C2B091DF44A8CE31DF907BBC93196A7")
                // APIv3密钥
                .apiV3Key("g6cmfHZhY8njcfNX11TaC0eOAtgO6FjE")
                .build();
    }

    /**
     * 敏感信息加密
     */
    private String rsaEncryptOAEP(String message) {
        X509Certificate cert = getX509Certificate();
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, cert.getPublicKey());
            byte[] data = message.getBytes(StandardCharsets.UTF_8);
            byte[] cipherdata = cipher.doFinal(data);
            return Base64.getEncoder().encodeToString(cipherdata);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取 X509Certificate
     */
    private X509Certificate getX509Certificate() {
        ClassLoader classLoader = this.getClass().getClassLoader();
        try (InputStream in = classLoader.getResourceAsStream("v3/platform_cert.pem")) {
            if (in == null) {
                throw new IOException("Resource not found: v3/platform_cert.pem");
            }
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            return (X509Certificate) cf.generateCertificate(in);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

