package com.ibeetl.admin.console.api; import java.awt.image.BufferedImage; import java.io.*; import java.math.BigDecimal; import java.net.URLEncoder; import java.util.*; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.hutool.core.lang.Snowflake; import cn.hutool.core.util.IdUtil; import com.ibeetl.admin.console.model.PayInfoModel; import com.ibeetl.admin.console.model.WeChatParams; import com.ibeetl.admin.console.service.XzxCityPartnerService; import com.ibeetl.admin.console.service.XzxPartnerFenceService; import com.ibeetl.admin.console.util.HttpUtil; import com.ibeetl.admin.console.util.PayForUtil; import com.ibeetl.admin.console.util.WeChatConfig; import com.ibeetl.admin.console.util.XMLUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.google.zxing.BarcodeFormat; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @Api(value = "微信充值接口类") public class WeixinPay { public static Log log = LogFactory.getLog(WeixinPay.class); //public static Logger lg=Logger.getLogger(WeixinPay.class); private static final int BLACK = 0xff000000; private static final int WHITE = 0xFFFFFFFF; private static final String MODEL = "/admin/front/weixinPay"; @Autowired XzxCityPartnerService cpService; /** * 获取微信支付的二维码地址 * @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 packageParams = new TreeMap(); 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; } /** * 将路径生成二维码图片 * @author chenp * @param content * @param response */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static void encodeQrcode(String content,HttpServletResponse response){ if(StringUtils.isBlank(content)){ return; } MultiFormatWriter multiFormatWriter = new MultiFormatWriter(); Map hints = new HashMap(); BitMatrix bitMatrix = null; try { bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, 400, 400,hints); BufferedImage image = toBufferedImage(bitMatrix); //输出二维码图片流 try { ImageIO.write(image, "png", response.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } catch (WriterException e1) { e1.printStackTrace(); } } /** * 类型转换 * @author chenp * @param matrix * @return */ public static BufferedImage toBufferedImage(BitMatrix matrix) { int width = matrix.getWidth(); int height = matrix.getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, matrix.get(x, y) == true ? BLACK : WHITE); } } return image; } // 特殊字符处理 public static String UrlEncode(String src) throws UnsupportedEncodingException { return URLEncoder.encode(src, "UTF-8").replace("+", "%20"); } //微信支付接口 @PostMapping(MODEL + "/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 = WeixinPay.getCodeUrl(ps); System.out.println(urlCode); PayInfoModel model = new PayInfoModel(); model.setPayOrderId(payOrderId); model.setMoney(ps.getTotal_fee()); int num =cpService.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 m = new HashMap(); m = XMLUtil.doXMLParse(sb.toString()); //过滤空 设置 TreeMap SortedMap packageParams = new TreeMap(); Iterator 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 = "" + "" + "" + " "; } else { log.info("支付失败,错误信息:" + packageParams.get("err_code")); resXml = "" + "" + "" + " "; } //------------------------------ //处理业务完毕 //------------------------------ BufferedOutputStream out = new BufferedOutputStream( response.getOutputStream()); out.write(resXml.getBytes()); out.flush(); out.close(); } else{ log.info("通知签名验证失败"); } } }