sunshine
2024-11-05 00b4581009af28098da4286a8ef9f4d72c7c5728
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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<String, String> generateParam(VipCardVo cardVo, String orderNo) {
        Map<String, String> 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<String, String> 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<String, String> 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<String, String> 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;
    }
 
}