package ink.wgink.module.wechat.service.pay.v3.jsapi.impl;

import ink.wgink.common.base.DefaultBaseService;
import ink.wgink.module.wechat.enums.PayAuthorizationTypeEnum;
import ink.wgink.module.wechat.pojo.pay.v3.PaySign;
import ink.wgink.module.wechat.pojo.pay.v3.jsapi.pojo.PayPlaceOrder;
import ink.wgink.module.wechat.pojo.pay.v3.jsapi.pojo.PayPrepay;
import ink.wgink.module.wechat.request.pay.v3.jsapi.PlaceOrderPayRequestImpl;
import ink.wgink.module.wechat.service.pay.v3.jsapi.IJsapiService;
import ink.wgink.module.wechat.utils.pay.PayCertificateUtil;
import ink.wgink.module.wechat.utils.pay.PayPrivateKeyUtil;
import ink.wgink.properties.wechat.miniapp.MiniappProperties;
import ink.wgink.properties.wechat.pay.v3.PayProperties;
import ink.wgink.util.BeanPropertyCheckUtil;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.string.WStringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMethod;

import java.io.FileInputStream;
import java.security.cert.X509Certificate;

/**
 * @ClassName: JsapiServiceImpl
 * @Description: Jsapi业务
 * @Author: wanggeng
 * @Date: 2021/8/19 10:42 上午
 * @Version: 1.0
 */
@Service
public class JsapiServiceImpl extends DefaultBaseService implements IJsapiService {

    @Autowired
    private PayProperties payProperties;
    @Autowired
    private MiniappProperties miniappProperties;

    @Override
    public PaySign placeOrder(PayPlaceOrder payPlaceOrder) throws Exception {
        payPlaceOrder.setAppid(miniappProperties.getAppKey());
        payPlaceOrder.setMchid(payProperties.getMchid());
        BeanPropertyCheckUtil.checkField(payPlaceOrder);
        String urlSuffix = "/v3/pay/transactions/jsapi";
        String url = "https://api.mch.weixin.qq.com" + urlSuffix;

        LOG.debug("获得证书");
        X509Certificate certificate = PayCertificateUtil.getCertificate(new FileInputStream(payProperties.getCertificatePath()));
        String serialNumber = certificate.getSerialNumber().toString(16);

        LOG.debug("调用微信支付，发起预支付");
        PlaceOrderPayRequestImpl placeOrderPayRequest = new PlaceOrderPayRequestImpl();
        String body = placeOrderPayRequest.bodyJsonString(payPlaceOrder);
        String authorization = placeOrderPayRequest.getAuthorization(RequestMethod.POST, urlSuffix, serialNumber, payProperties, body, PayAuthorizationTypeEnum.WECHATPAY2_SHA256_RSA2048);
        LOG.debug("请求获得结果");
        PayPrepay payPrepay = placeOrderPayRequest.post(url, authorization, serialNumber, body);

        LOG.debug("生成返回结果");
        long timestamp = System.currentTimeMillis();
        String nonceStr = WStringUtil.randomSubStr(UUIDUtil.get32UUID(), 10).toUpperCase();

        PaySign paySign = new PaySign();
        paySign.setAppId(miniappProperties.getAppKey());
        paySign.setPrepayId(payPrepay.getPrepayId());
        paySign.setNonceStr(nonceStr);
        paySign.setTimestamp(String.valueOf(timestamp));
        paySign.setPaySign(getPaySign(timestamp, nonceStr, payPrepay.getPrepayId()));
        return paySign;
    }

    /**
     * 获得小程序签名
     *
     * @param timestamp
     * @param nonceStr
     * @param prepayId
     * @return
     * @throws Exception
     */
    private String getPaySign(long timestamp, String nonceStr, String prepayId) throws Exception {
        StringBuilder signBS = new StringBuilder();
        signBS.append(miniappProperties.getAppKey()).append("\n")
                .append(timestamp).append("\n")
                .append(nonceStr).append("\n")
                .append("prepay_id=").append(prepayId).append("\n");
        String key = PayPrivateKeyUtil.getPrivateKey(payProperties.getKeyPath());
        // 生成签名
        return PayPrivateKeyUtil.encryptByPrivateKey(signBS.toString(), key);
    }

}
