package com.uas.service.donate.controller; import com.alibaba.fastjson.JSONObject; import com.github.binarywang.utils.qrcode.QrcodeUtils; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult; import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; import com.github.binarywang.wxpay.constant.WxPayConstants; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.util.SignUtils; import com.uas.dfs.service.FileClient; import com.uas.platform.core.util.HttpUtil; import com.uas.service.donate.api.WxPayApi; import com.uas.service.donate.config.WxConfig; import com.uas.service.donate.core.support.SystemSession; import com.uas.service.donate.model.Project; import com.uas.service.donate.model.ProjectRecode; import com.uas.service.donate.model.User; import com.uas.service.donate.model.WechatOrder; import com.uas.service.donate.service.ProjectRecodeService; import com.uas.service.donate.service.ProjectService; import com.uas.service.donate.service.UserService; import com.uas.service.donate.service.WechatOrderService; import com.uas.service.donate.util.IpUtils; import com.uas.service.donate.util.StringUtils; import com.uas.service.donate.util.WechatConnector; import com.uas.service.donate.util.WxCheckoutUtil; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.net.URLEncoder; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * Created by 黄诚天 on 2017-10-27. */ @Controller @RequestMapping("/wxpay") public class WxpayController { @Autowired private FileClient fileClient; @Autowired protected WxPayApi wxPayApi; @Autowired protected WechatOrderService wechatOrderService; @Autowired private ProjectRecodeService projectRecodeService; @Autowired private ProjectService projectService; @Autowired private UserService userService; private Logger logger = LoggerFactory.getLogger(WxpayController.class); private static String redirectUrl = "http://lj.ubtob.com/wxpay/redirectUrl"; //private String orderNumber = NumberGenerator.generateId(); /** * 扫码支付 @RequestParam ProjectRecode projectRecode * 使用模式一 模式一,先扫码,再生成订单。模式二,先生成订单,再扫码。 * @param request * @param response * @throws Exception */ @ResponseBody @RequestMapping(value = "/pcPay", method = RequestMethod.POST) public ModelMap pcPay(@RequestParam("jsonStr") String jsonStr, HttpServletRequest request, HttpServletResponse response) throws Exception { ModelMap modelMap = new ModelMap(); ProjectRecode projectRecode= null; try { projectRecode = this.createProjectRecode(jsonStr); } catch (Exception e) { logger.error("生成商户订单错误,原因:{}", e.getMessage()); modelMap.put("error", "参数错误"); return modelMap; } WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = createWxPayUnifiedOrderRequest(request, projectRecode, WxPayConstants.TradeType.NATIVE); Map map = unifiedOrder(wxPayUnifiedOrderRequest); if ("FAIL".equals(map.get("status"))) { modelMap.put("error", map.get("message")); } else { modelMap.put("qrcodeUrl", map.get("qrcodeUrl")); modelMap.put("outTradeNo", projectRecode.getId()); } return modelMap; } /** * 公众号支付 网页支付JSAPI即公众号支付是用户在微信中打开商户的H5页面 * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 * @param request * @param response * @throws Exception */ @ResponseBody @RequestMapping(value = "/webPay", method = RequestMethod.POST) public ModelMap webPay(@RequestParam("jsonStr") String jsonStr, HttpServletRequest request, HttpServletResponse response) throws Exception { ModelMap modelMap = new ModelMap(); ProjectRecode projectRecode= null; try { projectRecode = this.createProjectRecode(jsonStr); } catch (Exception e) { logger.error("生成商户订单错误,原因:{}", e.getMessage()); modelMap.put("error", "参数错误"); return modelMap; } WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = createWxPayUnifiedOrderRequest(request, projectRecode, WxPayConstants.TradeType.JSAPI); String openId = null; Object openIdObj = request.getSession().getAttribute("openId"); /*User user =SystemSession.getUser(); if (user != null && user.getWxOpenId() != null) { logger.info("当前用户信息:" + user.toString()); openId = user.getWxOpenId(); } else { logger.info("公众号支付缺少openId:--需要用户授权"); String url = WechatConnector.createAuthorizeUrl(WxConfig.oauthUserScope, wxPayApi.getConfig().getAppId(), URLEncoder.encode("http://lj.ubtob.com", "UTF-8")); response.sendRedirect(url); }*/ if (openIdObj != null) { openId = (String) openIdObj; logger.info("当前微信用户信息:" + openId); } else { logger.info("公众号支付缺少openId:--需要用户授权"); String url = WechatConnector.createAuthorizeUrl(WxConfig.oauthUserScope, wxPayApi.getConfig().getAppId(), URLEncoder.encode("http://lj.ubtob.com", "UTF-8")); response.sendRedirect(url); return null; } logger.info("公众号支付处理:openId=" + openId); if (StringUtils.isEmpty(wxPayApi.getConfig().getSubAppId())) { wxPayUnifiedOrderRequest.setOpenid(openId);//否是 trade_type=JSAPI,此参数必传,用户在主商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。 } else { wxPayUnifiedOrderRequest.setSubOpenid(openId);//否是 trade_type=JSAPI,此参数必传,用户在子商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。 } Map map = unifiedOrder(wxPayUnifiedOrderRequest); if ("FAIL".equals(map.get("status"))) { modelMap.put("error", map.get("message")); } else { //modelMap.put("outTradeNo", projectRecode.getId()); //将prepayId返回给js String nonceStr = String.valueOf(System.currentTimeMillis()); String timeStamp = String.valueOf(Long.parseLong(nonceStr) / 1000); String appId = wxPayApi.getConfig().getAppId(); String packagePrepayId = "prepay_id=" + map.get("prepayId"); modelMap.put("appId", appId); modelMap.put("timeStamp", timeStamp); modelMap.put("nonceStr", nonceStr); modelMap.put("package", packagePrepayId); modelMap.put("signType", "MD5"); logger.info("参数--" + appId + "," + timeStamp + "," + nonceStr + "," + packagePrepayId); Map signMap = new HashMap<>(); signMap.put("appId", appId); signMap.put("timeStamp", timeStamp); signMap.put("nonceStr", nonceStr); signMap.put("package", packagePrepayId); signMap.put("signType", "MD5"); //预付订单再次签名 String packageSign = SignUtils.createSign(signMap, "MD5", wxPayApi.getConfig().getMchKey(), false); logger.info("预付订单再次签名验签--" + SignUtils.checkSign(signMap, "MD5", wxPayApi.getConfig().getMchKey())); modelMap.put("paySign", packageSign); } return modelMap; } /** * H5支付 商户在微信客户端外的移动端网页 * https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4 应让用户去点击按钮触发查单操作 * @param request * @param response * @throws Exception */ @ResponseBody @RequestMapping(value = "/wapPay", method = RequestMethod.POST) public ModelMap wapPay(@RequestParam("jsonStr") String jsonStr, HttpServletRequest request, HttpServletResponse response) throws Exception { ModelMap modelMap = new ModelMap(); ProjectRecode projectRecode= null; try { projectRecode = this.createProjectRecode(jsonStr); } catch (Exception e) { logger.error("生成商户订单错误,原因:{}", e.getMessage()); modelMap.put("error", "参数错误"); return modelMap; } WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = createWxPayUnifiedOrderRequest(request, projectRecode, WxPayConstants.TradeType.MWEB); Map map = unifiedOrder(wxPayUnifiedOrderRequest); if ("FAIL".equals(map.get("status"))) { modelMap.put("error", map.get("message")); } else { modelMap.put("mwebUrl", map.get("mwebUrl")); } return modelMap; } //通过统一下单接口发起请求,获得prepay_id(预支付交易会话标识),这个标示是微信提交支付的关键数据 public Map unifiedOrder(WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest) throws Exception { Map map = new HashMap(); WxPayUnifiedOrderResult wxPayUnifiedOrderResult = null; try { wxPayUnifiedOrderResult = wxPayApi.unifiedOrder(wxPayUnifiedOrderRequest); //map.put("status", "SUCCESS"); if (WxPayConstants.TradeType.MWEB.equals(wxPayUnifiedOrderRequest.getTradeType())) { /*H5支付开发步骤:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4*/ String mwebUrl = wxPayUnifiedOrderResult.getMwebUrl() + "&redirect_url=" + URLEncoder.encode(redirectUrl,"UTF-8"); map.put("mwebUrl", mwebUrl); } else if (WxPayConstants.TradeType.NATIVE.equals(wxPayUnifiedOrderRequest.getTradeType())) { //扫码支付 //QrcodeUtils.encode(wxPayUnifiedOrderResult.getCodeURL(),response.getOutputStream()); byte[] bytes = QrcodeUtils.createQrcode(wxPayUnifiedOrderResult.getCodeURL(), 400, null); String qrcodeUrl = fileClient.upload(bytes, bytes.length,"jpg",null); //保存图片地址 String outTradeNo = wxPayUnifiedOrderRequest.getOutTradeNo(); ProjectRecode projectRecode = projectRecodeService.findOne(Long.parseLong(outTradeNo)); projectRecode.setQrcodeUrl(qrcodeUrl); projectRecodeService.update(projectRecode); map.put("qrcodeUrl", qrcodeUrl); } else if (WxPayConstants.TradeType.JSAPI.equals(wxPayUnifiedOrderRequest.getTradeType())) { //公众号支付 String prepayId = wxPayUnifiedOrderResult.getPrepayId(); map.put("prepayId", prepayId); } //byte[] arr = wxPayApi.createScanPayQrcodeMode2(wxPayUnifiedOrderResult.getCodeURL(),null,null); } catch (WxPayException e) { logger.error("微信支付失败!订单号:{},原因:{}", wxPayUnifiedOrderRequest.getOutTradeNo(), e.getMessage()); e.printStackTrace(); map.put("status", e.getReturnCode()); map.put("message", e.getReturnMsg()); } return map; } /** * 查询订单支付状态 参数二选一 * @param transactionId * @param outTradeNo */ @ResponseBody @RequestMapping(value = "/queryTradeState", method = RequestMethod.POST) public String queryTradeState(@RequestParam(required = false) String transactionId, @RequestParam(required = false) String outTradeNo){ try { WxPayOrderQueryResult wxPayOrderQueryResult =wxPayApi.queryOrder(transactionId, outTradeNo); return wxPayOrderQueryResult.getTradeState(); } catch (WxPayException e) { return "ERROR"; } } /** * 推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过, * 如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前, * 要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。 * 特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致, * 防止数据泄漏导致出现“假通知”,造成资金损失。 * @param request * @param response * @return */ @ResponseBody @RequestMapping("/notifyUrl") public synchronized void payNotify(HttpServletRequest request, HttpServletResponse response) throws IOException { ModelMap map = new ModelMap(); String returnResult = null; try { String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding()); WxPayOrderNotifyResult result = wxPayApi.parseOrderNotifyResult(xmlResult); //商户系统订单默认支付状态 short projectRecodePayStatus = 1; if ("SUCCESS".equals(result.getReturnCode())) { if ("SUCCESS".equals(result.getResultCode())) { returnResult = setXml("SUCCESS", "OK"); WechatOrder wechatOrder = wechatOrderService.getByTransactionId(result.getTransactionId()); WxPayOrderQueryResult OrderQueryResult = null; if (wechatOrder != null) { OrderQueryResult = wxPayApi.queryOrder(result.getTransactionId(),null);//二选一填 } ProjectRecode projectRecode = projectRecodeService.findOne(Long.parseLong(result.getOutTradeNo())); //微信在数据库中订单存在且状态已处理 if (wechatOrder != null && wechatOrder.getStatus() == 1 && projectRecode != null && projectRecode.getStatus() != 1 && wechatOrder.getTradeState().equals(OrderQueryResult.getTradeState())) { logger.info("系统已对该笔交易进行处理,交易订单号" + wechatOrder.getOutTradeNo() + "微信交易号" + wechatOrder.getTransactionId()); returnResult = setXml("SUCCESS", "OK"); } else { // 自己处理订单的业务逻辑 //校验返回的订单金额是否与商户侧的订单金额一致 if (!(projectRecode != null && ((int) (projectRecode.getAmount()*100)) == result.getTotalFee().intValue())) { logger.warn("防止数据泄漏导致出现“假通知”,以免造成资金损失"); map.put("warning", "防止数据泄漏导致出现“假通知”,以免造成资金损失"); returnResult = setXml("FAIL", "商户侧的订单金额与返回的订单金额不一致"); projectRecodePayStatus = 3; projectRecode.setStatus(projectRecodePayStatus); projectRecode.setExceptionMsg("{'AmountMsg' : '支付宝返回金额(单位分)与订单金额不相等', 'notifyTotalFee' : " + result.getTotalFee().intValue() + "}"); } else { WxPayOrderQueryResult wxPayOrderQueryResult = wxPayApi.queryOrder(result.getTransactionId(),null);//二选一填 if (wxPayOrderQueryResult != null) { map.put("tradeState", wxPayOrderQueryResult.getTradeState());//微信订单状态 map.put("tradeStateDesc", wxPayOrderQueryResult.getTradeStateDesc());//微信订单状态详情 } if ("SUCCESS".equals(wxPayOrderQueryResult.getTradeState())) { logger.info("异步通知支付成功处理开始:商户订单状态:" + projectRecode.getStatus()); projectRecodePayStatus = 2; if (projectRecode.getStatus() == 1) { //如果当前数据库中商户订单还是待支付状态 更新项目参数人数和金额 Project project = projectService.findOne(projectRecode.getProId()); logger.info("查看项目,查看项目id为" + project.getId() + ",项目名称为" + project.getName() + ",当前参与人数为" + project.getJoinAmount() + ",当前已筹集的金额" + project.getTotalAmount()); project.setJoinAmount(project.getJoinAmount() + 1); project.setTotalAmount(project.getTotalAmount() + projectRecode.getAmount()); logger.info("此次用户捐款金额为" + projectRecode.getAmount() + "元"); projectService.save(project); logger.info("更新项目,更新了项目id为" + project.getId() + ",项目名称为" + project.getName()+ "的参数人数和金额" + ",当前参与人数为" + project.getJoinAmount() + ",当前已筹集的金额" + project.getTotalAmount()); } projectRecode.setStatus(projectRecodePayStatus); logger.info("异步通知支付成功处理结束:商户订单状态:" + projectRecode.getStatus()); } wechatOrderService.save(WechatOrder.WxPayOrderNotifyResultToConvert(result, (short) 1, wxPayOrderQueryResult)); returnResult = setXml("SUCCESS", "OK"); } //更新订单状态 projectRecodeService.update(projectRecode); } //String totalFee = WxPayBaseResult.feeToYuan(result.getTotalFee()); } else { logger.info("微信支付业务处理失败:" + result.getErrCodeDes()); returnResult = setXml("FAIL", "微信支付业务处理失败"); } } else { logger.info("微信支付返回错误状态码(通信错误),错误信息:" + result.getReturnMsg()); returnResult = setXml("FAIL", "微信支付返回错误状态码(通信错误)"); } } catch (WxPayException e) { logger.error("微信回调结果异常,异常原因{}", e.getMessage()); map.put("error", e.getMessage()); returnResult = setXml("FAIL", "签名失败"); } finally { //TODO map response.getWriter().write(returnResult); } } @ResponseBody @RequestMapping("/redirectUrl") public String redirectUrl(HttpServletRequest request) { /*由于设置redirect_url后,回跳指定页面的操作可能发生在:1,微信支付中间页调起微信收银台后超过5秒 2,用户点击“取消支付“或支付完成后点“完成”按钮。因此无法保证页面回跳时,支付流程已结束, 所以商户设置的redirect_url地址不能自动执行查单操作,应让用户去点击按钮触发查单操作。*/ //效果图可以参考: https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4 最下面 return "h5支付回调"; } /** * 判断是否是微信浏览器发起的请求,如果是返回true,反正返回false * @param req * @return */ @ResponseBody @RequestMapping("/isWechat") public boolean isWechatBrowser(HttpServletRequest req){ String ua = req.getHeader("user-agent").toLowerCase(); if (ua.indexOf("micromessenger") >= 0) {// 是微信浏览器 return true; } return false; } /** * 获取token 基础支持token 一日上限2000次 与用户网页授权无关 与支付无关 * @return * @throws Exception */ public String getAccessToken() throws Exception { String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + WxConfig.APPID + "&secret=" + WxConfig.APPSECRET; HttpUtil.Response response = HttpUtil.sendGetRequest(url,null); if (response.getStatusCode() == 200) { return response.getResponseText(); } return null; } @ResponseBody @RequestMapping(value = "/userAdvanced", method = RequestMethod.GET) public void userAdvanced(HttpServletRequest request, HttpServletResponse response) throws Exception { //配置网页授权url String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxPayApi.getConfig().getAppId() + "&redirect_uri=" + URLEncoder.encode("http://lj.ubtob.com/wxpay/getOpenId", "UTF-8") + "&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect"; response.sendRedirect(url); } /** * 获取用户基本信息 静默获取 无需用户同意 只有公众号模式需要 * https://mp.weixin.qq.com/advanced/advanced?action=table&token=719542712&lang=zh_CN * 网页授权添加url 需icp备案 * @param request * @return */ @ResponseBody @RequestMapping(value = "/getOpenId", method = RequestMethod.GET) public void getOpenId(HttpServletRequest request) throws IOException { try { //TODO 授权方式 是否需要电话号码 名字等信息 //TODO 获取code String code = request.getParameter("code"); String state = request.getParameter("state"); logger.info("公众号获取:authCode=" + code + ",state=" + state); //String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding()); String openId = wxPayApi.authcode2Openid(code); } catch (WxPayException e) { e.printStackTrace(); } } /** * 验证token * @param request * @param response */ @ResponseBody @RequestMapping("/checkToken") public void checkToken(HttpServletRequest request, HttpServletResponse response) { boolean isGet = request.getMethod().toLowerCase().equals("get"); boolean isPost = request.getMethod().toLowerCase().equals("post"); PrintWriter print; if (isGet) { // 微信加密签名 String signature = request.getParameter("signature"); // 时间戳 String timestamp = request.getParameter("timestamp"); // 随机数 String nonce = request.getParameter("nonce"); // 随机字符串 String echostr = request.getParameter("echostr"); // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if (signature != null && WxCheckoutUtil.checkSignature(signature, timestamp, nonce)) { try { print = response.getWriter(); print.write(echostr); print.flush(); } catch (IOException e) { e.printStackTrace(); } } } else if (isPost) { //核心逻辑 } } // private WxPayUnifiedOrderRequest createWxPayUnifiedOrderRequest(HttpServletRequest request, ProjectRecode projectRecode, String tradeType) { //Project project = projectRecode.getProject(); WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest(); wxPayUnifiedOrderRequest.setDeviceInfo("WEB");//否 终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB wxPayUnifiedOrderRequest.setNonceStr(String.valueOf(System.currentTimeMillis()));//是 随机字符串,不长于32位。 //wxPayUnifiedOrderRequest.setSign("xixihahxixhahaha");//是 签名 //wxPayUnifiedOrderRequest.setSignType(null);//否 签名类型,目前支持HMAC-SHA256和MD5,默认为MD5 //商品描述交易字段格式根据不同的应用场景按照以下格式:(1)PC网站——传入浏览器打开的网站主页title名-实际商品名称,例如:腾讯充值中心-QQ会员充值;(2) 公众号——传入公众号名称-实际商品名称,例如:腾讯形象店- image-QQ公仔;(3) H5——应用在浏览器网页上的场景,传入浏览器打开的移动网页的主页title名-实际商品名称,例如:腾讯充值中心-QQ会员充值;(4) 线下门店——门店品牌名-城市分店名-实际商品名称,例如: image形象店-深圳腾大- QQ公仔)(5) APP——需传入应用市场上的APP名字-实际商品名称,天天爱消除-游戏充值。 if (WxPayConstants.TradeType.MWEB.equals(tradeType)) { //H5——应用在浏览器网页上的场景,传入浏览器打开的移动网页的主页title名-实际商品名称,例如:腾讯充值中心-QQ会员充值; wxPayUnifiedOrderRequest.setBody("一元捐-" + projectService.findOne(projectRecode.getProId()).getName()); } else if (WxPayConstants.TradeType.JSAPI.equals(tradeType)) { if (StringUtils.isEmpty(wxPayApi.getConfig().getSubAppId())) { wxPayUnifiedOrderRequest.setOpenid(null);//TODO 否是 trade_type=JSAPI,此参数必传,用户在主商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。 } else { wxPayUnifiedOrderRequest.setSubOpenid(null);//否是 trade_type=JSAPI,此参数必传,用户在子商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。 } //公众号——传入公众号名称-实际商品名称,例如:腾讯形象店- image-QQ公仔; wxPayUnifiedOrderRequest.setBody("优软科技-" + projectService.findOne(projectRecode.getProId()).getName()); } else if (WxPayConstants.TradeType.NATIVE.equals(tradeType)) { //PC网站——传入浏览器打开的网站主页title名-实际商品名称,例如:腾讯充值中心-QQ会员充值; wxPayUnifiedOrderRequest.setBody("一元捐-" + projectService.findOne(projectRecode.getProId()).getName()); } //wxPayUnifiedOrderRequest.setDetail("");//否 商品详细描述,对于使用单品优惠的商户,改字段必须按照规范上传,详见“单品优惠参数说明” wxPayUnifiedOrderRequest.setAttach("这是附加数据");//否 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据 wxPayUnifiedOrderRequest.setOutTradeNo(projectRecode.getId().toString());//是 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。 //wxPayUnifiedOrderRequest.setFeeType("CNY");//否 符合ISO 4217标准的三位字母代码,默认人民币:CNY wxPayUnifiedOrderRequest.setTotalFee((int)(projectRecode.getAmount() * 100));//是 订单总金额,只能为整数 String spbillCreateIp = IpUtils.getIpFromRequest(request); if ("0:0:0:0:0:0:0:1".equals(spbillCreateIp)) { spbillCreateIp = "127.0.0.1"; } wxPayUnifiedOrderRequest.setSpbillCreateIp(spbillCreateIp);//是 APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP //wxPayUnifiedOrderRequest.setSpbillCreateIp(getIp(request)); //wxPayUnifiedOrderRequest.setSpbillCreateIp("10.10.100.200"); //wxPayUnifiedOrderRequest.setTimeStart(null);//否 订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。 //wxPayUnifiedOrderRequest.setTimeExpire(null);//否 订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。 //wxPayUnifiedOrderRequest.setGoodsTag(null);//否 订单优惠标记,代金券或立减优惠功能的参数 //wxPayUnifiedOrderRequest.setNotifyURL();//是 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。 wxPayUnifiedOrderRequest.setTradeType(tradeType); //是 取值如下:JSAPI,NATIVE,APP wxPayUnifiedOrderRequest.setProductId(projectRecode.getProId().toString());//否是 trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。 //wxPayUnifiedOrderRequest.setLimitPay(null);//否 指定支付方式 如:no_credit--指定不能使用信用卡支付 //wxPayUnifiedOrderRequest.setSceneInfo(null);//否 该字段用于上报场景信息,目前支持上报实际门店信息。该字段为JSON对象数据,对象格式为{"store_info":{"id": "门店ID","name": "名称","area_code": "编码","address": "地址" }} return wxPayUnifiedOrderRequest; } //通过xml 返回给给微信消息 public String setXml(String return_code, String return_msg) { return "" + ""; } private ProjectRecode createProjectRecode(String jsonStr) throws Exception { JSONObject jsonObject = JSONObject.parseObject(jsonStr); String imid = jsonObject.getString("imid"); logger.info("移动端imid=" + imid); Long uuid = null; User user = SystemSession.getUser(); if (user != null) { uuid = user.getUserUU(); } if (!StringUtils.isEmpty(imid)) { jsonObject.remove("imid"); //TODO 通过imid获取uuid Object uuidObj = userService.getUserByImId(Long.parseLong(imid)); if (uuidObj !=null) { uuid = (Long)uuidObj; logger.info("移动端imid转为uuid,uuid=" + uuid); } } ProjectRecode projectRecode= JSONObject.parseObject(jsonObject.toJSONString(),ProjectRecode.class); if (uuid != null) { projectRecode.setUuid(uuid); } projectRecode.setTime(new Date()); ProjectRecode newProjectRecode = projectRecodeService.join(projectRecode); return newProjectRecode; } public String getIp(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if(ip!=null && !"unKnown".equalsIgnoreCase(ip)){ int index = ip.indexOf(","); if(index != -1){ return ip.substring(0,index); }else{ return ip; } } ip = request.getHeader("X-Real-IP"); if(ip!=null && !"unKnown".equalsIgnoreCase(ip)){ return ip; } return request.getRemoteAddr(); } }