Helius
2021-06-30 02b38bb7c08d68fffc6af25e4ba00a456d96e94e
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
package com.xzx.gc.pay.controller;
 
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.xzx.gc.common.constant.Constants;
import com.xzx.gc.common.request.BaseController;
import com.xzx.gc.model.admin.PayInfoModel;
import com.xzx.gc.model.admin.WeChatParams;
import com.xzx.gc.pay.service.PayService;
import com.xzx.gc.util.HttpUtil;
import com.xzx.gc.util.PayForUtil;
import com.xzx.gc.util.WeChatConfig;
import com.xzx.gc.util.XMLUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
 
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
 
@RestController
@Api(tags = "微信充值接口类")
@Slf4j
public class WeixinPayController extends BaseController {
 
 
    @Autowired
    private PayService payService;
    /**
     * 获取微信支付的二维码地址
     * @return
     * @author chenp
     * @throws Exception
     */
    public static String getCodeUrl(WeChatParams ps) throws Exception {
        /**
         * 账号信息
         */
        String appid = WeChatConfig.APPID;//微信服务号的appid
        String mch_id = WeChatConfig.MCHID; //微信支付商户号
        String key = WeChatConfig.APIKEY; // 微信支付的API密钥
        String notify_url = WeChatConfig.WECHAT_NOTIFY_URL_PC;//回调地址【注意,这里必须要使用外网的地址】
        String ufdoder_url=WeChatConfig.UFDODER_URL;//微信下单API地址
        String trade_type = "NATIVE"; //类型【网页扫码支付】
 
        /**
         * 时间字符串
         */
        String currTime = PayForUtil.getCurrTime();
        String strTime = currTime.substring(8, currTime.length());
        String strRandom = PayForUtil.buildRandom(4) + "";
        String nonce_str = strTime + strRandom;
 
        /**
         * 参数封装
         */
        SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);//随机字符串
        packageParams.put("body", ps.body);//支付的商品名称
        packageParams.put("out_trade_no", ps.out_trade_no+nonce_str);//商户订单号【备注:每次发起请求都需要随机的字符串,否则失败。】
        packageParams.put("total_fee", ps.total_fee);//支付金额
        packageParams.put("spbill_create_ip", PayForUtil.localIp());//客户端主机
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);
        packageParams.put("attach", ps.attach);//额外的参数【业务类型+会员ID+支付类型】
 
 
        String sign = PayForUtil.createSign("UTF-8", packageParams,key);  //获取签名
        packageParams.put("sign", sign);
 
        String requestXML = PayForUtil.getRequestXml(packageParams);//将请求参数转换成String类型
        log.info("微信支付请求参数的报文"+requestXML);
        String resXml = HttpUtil.postData(ufdoder_url,requestXML);  //解析请求之后的xml参数并且转换成String类型
        Map map = XMLUtil.doXMLParse(resXml);
        log.info("微信支付响应参数的报文"+resXml);
        String urlCode = (String) map.get("code_url");
 
        return urlCode;
    }
 
 
 
    //微信支付接口
    @PostMapping(Constants.ADMIN_VIEW_PREFIX + "/weixinPay/wxPay.json")
    @ResponseBody
    @ApiOperation(value="获取微信付款地址(该地址用于生成微信付款二维码)", notes="test: 仅0有正确返回")
    public String wxPay(@RequestBody WeChatParams ps) throws Exception {
        Snowflake snowflake = IdUtil.getSnowflake(0, 3);
        String payOrderId = "ZF"+snowflake.nextIdStr();
        ps.setOut_trade_no(payOrderId);
        ps.setTotal_fee(new BigDecimal(ps.getTotal_fee()).multiply(new BigDecimal("100")).toString());
        String urlCode =getCodeUrl(ps);
        System.out.println(urlCode);
 
        PayInfoModel model = new PayInfoModel();
        model.setPayOrderId(payOrderId);
        model.setMoney(ps.getTotal_fee());
        int num =payService.addPayInfo(model);
        return urlCode;
    }
 
    /**
     * pc端微信支付之后的回调方法
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(value="wechat_notify_url_pc",method= RequestMethod.POST)
    public void wechat_notify_url_pc(HttpServletRequest request, HttpServletResponse response) throws Exception{
 
        //读取参数
        InputStream inputStream ;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s ;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null){
            sb.append(s);
        }
        in.close();
        inputStream.close();
 
        //解析xml成map
        Map<String, String> m = new HashMap<String, String>();
        m = XMLUtil.doXMLParse(sb.toString());
 
        //过滤空 设置 TreeMap
        SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
        Iterator<String> it = m.keySet().iterator();
        while (it.hasNext()) {
            String parameter = it.next();
            String parameterValue = m.get(parameter);
 
            String v = "";
            if(null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }
        // 微信支付的API密钥
        String key = WeChatConfig.APIKEY; // key
        log.info("微信支付返回回来的参数:"+packageParams);
        //判断签名是否正确
        if(PayForUtil.isTenpaySign("UTF-8", packageParams,key)) {
            //------------------------------
            //处理业务开始
            //------------------------------
            String resXml = "";
            if("SUCCESS".equals((String)packageParams.get("result_code"))){
                // 这里是支付成功
 
                //执行自己的业务逻辑开始
                String app_id = (String)packageParams.get("appid");
                String mch_id = (String)packageParams.get("mch_id");
                String openid = (String)packageParams.get("openid");
                String is_subscribe = (String)packageParams.get("is_subscribe");//是否关注公众号
 
                //附加参数【商标申请_0bda32824db44d6f9611f1047829fa3b_15460】--【业务类型_会员ID_订单号】
                String attach = (String)packageParams.get("attach");
                //商户订单号
                String out_trade_no = (String)packageParams.get("out_trade_no");
                //付款金额【以分为单位】
                String total_fee = (String)packageParams.get("total_fee");
                //微信生成的交易订单号
                String transaction_id = (String)packageParams.get("transaction_id");//微信支付订单号
                //支付完成时间
                String time_end=(String)packageParams.get("time_end");
 
                //out_trade_no
 
                log.info("app_id:"+app_id);
                log.info("mch_id:"+mch_id);
                log.info("openid:"+openid);
                log.info("is_subscribe:"+is_subscribe);
                log.info("out_trade_no:"+out_trade_no);
                log.info("total_fee:"+total_fee);
                log.info("额外参数_attach:"+attach);
                log.info("time_end:"+time_end);
 
                //执行自己的业务逻辑结束
                log.info("支付成功");
                //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
 
            } else {
                log.info("支付失败,错误信息:" + packageParams.get("err_code"));
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
            }
            //------------------------------
            //处理业务完毕
            //------------------------------
            BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } else{
            log.info("通知签名验证失败");
        }
 
    }
}