package com.nova.sankuai.domain.api.yinsheng; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; import com.nova.sankuai.domain.entity.VipCardOrder; import com.nova.sankuai.domain.vo.vipcard.VipCardVo; import com.nova.sankuai.infra.config.CommonException; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.util.codec.binary.Base64; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; /** * @author weikangdi * @create 2022/3/2 */ @Component @Slf4j public class YinShengUtil { @Value("${yinsheng.notify_url}") private String notify_url; @Value("${yinsheng.h5.partner_id}") private String partner_id; @Value("${yinsheng.h5.seller_id}") private String seller_id; @Value("${yinsheng.h5.seller_name}") private String seller_name; @Value("${yinsheng.h5.business_code}") private String business_code; @Value("${yinsheng.h5.password}") private String password; @Value("${yinsheng.h5.private_key_path}") private String privateKeyPath; @Value("${yinsheng.h5.public_key_path}") private String publicKeyPath; /** * wap支付,手机收银台 */ public final static String WAP_METHOD = "ysepay.online.wap.directpay.createbyuser"; public Map generateParam(VipCardVo cardVo, String orderNo) { Map mapData = new HashMap<>(); //组装请求参数报文 mapData.put("method", WAP_METHOD); mapData.put("partner_id", partner_id); mapData.put("timestamp", DateUtil.getDateNow()); mapData.put("charset", "utf-8"); mapData.put("sign_type", "SM"); mapData.put("notify_url", notify_url + "/api/v1/vipCardOrder/notifyByYinSheng"); //银盛支付处理完请求后,当前页面自动跳转到商户网站里指定页面的http路径。若不想回调,则需传入银盛指定地址 mapData.put("return_url", cardVo.getUrl()); mapData.put("version", "3.0"); mapData.put("out_trade_no", orderNo); mapData.put("shopdate", DateUtil.getDateNowYmd()); mapData.put("subject", cardVo.getName()); mapData.put("total_amount", cardVo.parseSellingPrice()); mapData.put("currency", "CNY"); mapData.put("seller_id", seller_id); mapData.put("seller_name", seller_name); mapData.put("timeout_express", "30m"); mapData.put("business_code", business_code); // mapData.put("pay_mode", "native"); // mapData.put("bank_type", "1903000"); try { log.info("待验签数据:" + CommonUtil.mapToString(mapData)); String sign = sign(mapData); mapData.put("sign", sign); } catch (Exception e) { log.error("签名异常:", e); throw new CommonException("参数异常"); } return mapData; } /** * 异步通知参数验签 */ public boolean asynVerifyYs(Map reqMap) throws Exception { //获取银盛公钥 GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(publicKeyPath); //验签 String sign = reqMap.get("sign"); System.out.println("签名原文:" + reqMap); String content = StringUtil.createLinkString(CommonUtil.paraFilter(reqMap)); System.out.println("验签数据" + content + "," + sign); byte[] srcData = content.getBytes("utf-8"); boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(sign.getBytes("utf-8")), srcData); return validateSignResult; } /** * 同步请求参数签名 */ public String sign(Map mapData) throws Exception { //商户私钥地址 //将所有外层报文参数(sign除外)进行字典排序,组成字符串得到待签名内容 String signContent = CommonUtil.mapToString(mapData); log.info("待签名内容:{}", signContent); //执行签名 String sign = GMSignUtils.signMsgSM2(privateKeyPath, password, signContent); return sign; } public JSONObject getOrderStatus(VipCardOrder order) { Map mapData = new HashMap<>(); //组装请求参数报文 mapData.put("method", "ysepay.online.trade.order.query"); mapData.put("partner_id", partner_id); mapData.put("timestamp", DateUtil.getDateNow()); mapData.put("charset", "utf-8"); mapData.put("sign_type", "SM"); mapData.put("version", "3.0"); JSONObject biz_content = new JSONObject(); biz_content.put("out_trade_no", order.getPartnerThirdOrderId()); biz_content.put("shopdate", cn.hutool.core.date.DateUtil.format(order.getCreationDate(), "yyyyMMdd")); mapData.put("biz_content", biz_content.toJSONString()); try { log.info("待验签数据:" + CommonUtil.mapToString(mapData)); String sign = sign(mapData); mapData.put("sign", sign); } catch (Exception e) { log.error("签名异常:", e); throw new CommonException("参数异常"); } //调用银盛接口查询状态 String result = HttpRequest.sendPost("https://search.ysepay.com/gateway.do", CommonUtil.mapToString(mapData)); try { JSONObject jsonObject = JSON.parseObject(result, Feature.OrderedField); log.info("银盛查询明细返回原始参数:jsonObject:" + jsonObject); JSONObject response = jsonObject.getJSONObject("ysepay_online_trade_order_query_response"); String content = response.toString(); String sign = jsonObject.get("sign").toString(); log.info("sign:" + sign); log.info("content:" + content); boolean verify = resultVerify(sign, content); log.info("同步请求验签结果:{}", verify); if (verify && "Success".equals(response.getString("msg"))) { return response; } } catch (Exception e) { e.printStackTrace(); log.error("同步请求验签异常" + result); throw new CommonException("同步请求验签异常"); } return null; } public boolean resultVerify(String sign, String content) throws Exception { //获取银盛公钥 GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(publicKeyPath); //验签 byte[] srcData = content.getBytes("utf-8"); boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo, Base64.decodeBase64(sign.getBytes("utf-8")), srcData); return validateSignResult; } }