controller
@RestController @RequestMapping("/order") public class OrderController { @Reference private OrderService orderService; @RequestMapping("/add") public Result add(@RequestBody Order order) { try { String userName = SecurityContextHolder.getContext().getAuthentication().getName(); order.setUserId(userName); orderService.add(order); return new Result(true, "保存成功!"); } catch (Exception e) { e.printStackTrace(); return new Result(false, "保存失败!"); } } }Service
@Service @Transactional public class OrderServiceImpl implements OrderService { @Autowired private PayLogDao payLogDao; @Autowired private OrderDao orderDao; @Autowired private OrderItemDao orderItemDao; @Autowired private RedisTemplate redisTemplate; @Autowired private IdWorker idWorker; @Override public void add(Order order) { //1. 从订单对象中获取当前登录用户用户名 String userId = order.getUserId(); //2. 根据用户名获取购物车集合 List<BuyerCart> cartList = (List<BuyerCart>) redisTemplate.boundHashOps(Constants.CART_LIST_REDIS).get(userId); List<String> orderIdList = new ArrayList();//订单ID列表 double total_money = 0;//总金额 (元) //3. 遍历购物车集合 if (cartList != null) { for (BuyerCart cart : cartList) { //TODO 4. 根据购物车对象保存订单数据 long orderId = idWorker.nextId(); System.out.println("sellerId:" + cart.getSellerId()); Order tborder = new Order();//新创建订单对象 tborder.setOrderId(orderId);//订单ID tborder.setUserId(order.getUserId());//用户名 tborder.setPaymentType(order.getPaymentType());//支付类型 tborder.setStatus("1");//状态:未付款 tborder.setCreateTime(new Date());//订单创建日期 tborder.setUpdateTime(new Date());//订单更新日期 tborder.setReceiverAreaName(order.getReceiverAreaName());//地址 tborder.setReceiverMobile(order.getReceiverMobile());//手机号 tborder.setReceiver(order.getReceiver());//收货人 tborder.setSourceType(order.getSourceType());//订单来源 tborder.setSellerId(cart.getSellerId());//商家ID //循环购物车明细 double money = 0; //5. 从购物车中获取购物项集合 List<OrderItem> orderItemList = cart.getOrderItemList(); //6. 遍历购物项集合 if (orderItemList != null) { for (OrderItem orderItem : orderItemList) { //TODO 7. 根据购物项对象保存订单详情数据 orderItem.setId(idWorker.nextId()); orderItem.setOrderId(orderId);//订单ID orderItem.setSellerId(cart.getSellerId()); money += orderItem.getTotalFee().doubleValue();//金额累加 orderItemDao.insertSelective(orderItem); } } tborder.setPayment(new BigDecimal(money)); orderDao.insertSelective(tborder); orderIdList.add(orderId + "");//添加到订单列表 total_money += money;//累加到总金额 } } //TODO 8. 计算总价钱保存支付日志数据 if ("1".equals(order.getPaymentType())) {//如果是微信支付 PayLog payLog = new PayLog(); String outTradeNo = idWorker.nextId() + "";//支付订单号 payLog.setOutTradeNo(outTradeNo);//支付订单号 payLog.setCreateTime(new Date());//创建时间 //订单号列表,逗号分隔 String ids = orderIdList.toString().replace("[", "").replace("]", "").replace(" ", ""); payLog.setOrderList(ids);//订单号列表,逗号分隔 payLog.setPayType("1");//支付类型 payLog.setTotalFee((long) (total_money * 100));//总金额(分) payLog.setTradeState("0");//支付状态 payLog.setUserId(order.getUserId());//用户ID payLogDao.insertSelective(payLog);//插入到支付日志表 //TODO 9. 使用当前登录用户的用户名作为key, 支付日志对象作为value存入redis中供支付使用 redisTemplate.boundHashOps("payLog").put(order.getUserId(), payLog);//放入缓存 } //TODO 10. 根据当前登录用户的用户名删除购物车 redisTemplate.boundHashOps(Constants.CART_LIST_REDIS).delete(order.getUserId()); } }二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。 二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理:它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。
信息容量大, 可以容纳多达1850个大写字母或2710个数字或500多个汉字 应用范围广, 支持文字,声音,图片,指纹等等… 容错能力强, 即使图片出现部分破损也能使用 成本低, 容易制作
容错级别也就是容错率, 相当于部分二维码被遮挡仍然可以被扫描出来. L级(低) 7%的码字可以被恢复。 M级(中) 的码字的15%可以被恢复。 Q级(四分)的码字的25%可以被恢复。 H级(高) 的码字的30%可以被恢复。
这是前端的二维码生成工具
<html> <head> <title>二维码入门小demo</title> </head> <body> <img id="qrious"> <script src="qrious.min.js"></script> <script> var qr = new QRious({ element:document.getElementById('qrious'), size:250, level:'H', value:'https://www.baidu.com' }); </script> </body> </html>红色部分为项目需要实现的部分
controller
/** * 支付业务 */ @RestController @RequestMapping("/pay") public class PayController { @Reference private OrderService orderService; @Reference private PayService payService; /** * 根据支付单号和总金额调用微信统一下单接口,生成支付链接返回 * @return */ @RequestMapping("/createNative") public Map createNative(){ //1.获取用户名 String username = SecurityContextHolder.getContext().getAuthentication().getName(); //2.获取支付日志对象 PayLog payLog = orderService.getPayLogByUsername(username); if (payLog!=null){ //3.调用统一下单接口,生成支付链接 Map map = payService.createNative(payLog.getOutTradeNo(), "1");//payLog.getTotalFee() return map; } return new HashMap(); } }service:注意需要发送https请求,所以要用到HttpClient工具类
@Service public class PayServiceImpl implements PayService { //公众号唯一标识 @Value("${appid}") private String appid; //财付通平台商户账号 @Value("${partner}") private String partner; //密钥 @Value("${partnerkey}") private String partnerkey; //回调地址 @Value("${notifyurl}") private String notifyurl; @Override public Map createNative(String outTradeNo, String totalFee) { //1.创建参数 Map<String,String> param=new HashMap();//创建参数 param.put("appid", appid);//公众号 param.put("mch_id", partner);//商户号 param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串 param.put("body", "品优购");//商品描述 param.put("out_trade_no", outTradeNo);//商户订单号 param.put("total_fee",totalFee);//总金额(分) param.put("spbill_create_ip", "127.0.0.1");//IP param.put("notify_url", "http://www.itcast.cn");//回调地址(随便写) param.put("trade_type", "NATIVE");//交易类型 try { //2.生成要发送的xml String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey); System.out.println(xmlParam); HttpClient client=new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder"); client.setHttps(true); client.setXmlParam(xmlParam); client.post(); //3.获得结果 String result = client.getContent(); System.out.println(result); Map<String, String> resultMap = WXPayUtil.xmlToMap(result); Map<String, String> map=new HashMap<>(); map.put("code_url", resultMap.get("code_url"));//支付地址 map.put("total_fee", totalFee);//总金额 map.put("out_trade_no",outTradeNo);//订单号 return map; } catch (Exception e) { e.printStackTrace(); return new HashMap<>(); } } }HttpClient
/** * http请求客户端 * * @author Administrator * */ public class HttpClient { private String url; private Map<String, String> param; private int statusCode; private String content; private String xmlParam; private boolean isHttps; public boolean isHttps() { return isHttps; } public void setHttps(boolean isHttps) { this.isHttps = isHttps; } public String getXmlParam() { return xmlParam; } public void setXmlParam(String xmlParam) { this.xmlParam = xmlParam; } public HttpClient(String url, Map<String, String> param) { this.url = url; this.param = param; } public HttpClient(String url) { this.url = url; } public void setParameter(Map<String, String> map) { param = map; } public void addParameter(String key, String value) { if (param == null) param = new HashMap<String, String>(); param.put(key, value); } public void post() throws ClientProtocolException, IOException { HttpPost http = new HttpPost(url); setEntity(http); execute(http); } public void put() throws ClientProtocolException, IOException { HttpPut http = new HttpPut(url); setEntity(http); execute(http); } public void get() throws ClientProtocolException, IOException { if (param != null) { StringBuilder url = new StringBuilder(this.url); boolean isFirst = true; for (String key : param.keySet()) { if (isFirst) url.append("?"); else url.append("&"); url.append(key).append("=").append(param.get(key)); } this.url = url.toString(); } HttpGet http = new HttpGet(url); execute(http); } /** * set http post,put param */ private void setEntity(HttpEntityEnclosingRequestBase http) { if (param != null) { List<NameValuePair> nvps = new LinkedList<NameValuePair>(); for (String key : param.keySet()) nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数 http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数 } if (xmlParam != null) { http.setEntity(new StringEntity(xmlParam, Consts.UTF_8)); } } private void execute(HttpUriRequest http) throws ClientProtocolException, IOException { CloseableHttpClient httpClient = null; try { if (isHttps) { SSLContext sslContext = new SSLContextBuilder() .loadTrustMaterial(null, new TrustStrategy() { // 信任所有 public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslContext); httpClient = HttpClients.custom().setSSLSocketFactory(sslsf) .build(); } else { httpClient = HttpClients.createDefault(); } CloseableHttpResponse response = httpClient.execute(http); try { if (response != null) { if (response.getStatusLine() != null) statusCode = response.getStatusLine().getStatusCode(); HttpEntity entity = response.getEntity(); // 响应内容 content = EntityUtils.toString(entity, Consts.UTF_8); } } finally { response.close(); } } catch (Exception e) { e.printStackTrace(); } finally { httpClient.close(); } } public int getStatusCode() { return statusCode; } public String getContent() throws ParseException, IOException { return content; } }controller
/** * 调用查询订单接口,查询是否支付成功 * @param out_trade_no * @return */ @RequestMapping("/queryPayStatus") public Result queryPayStatus(String out_trade_no){ String username = SecurityContextHolder.getContext().getAuthentication().getName(); Result result = null; int flag = 1; while (true){ //1.判断支付单号为空 if (out_trade_no == null){ result = new Result(false,"二维码超时"); break; } //2.调用查询接口 Map map = payService.queryPayStatus(out_trade_no); if ("SUCCESS".equals(map.get("trade_state"))){ result = new Result(true,"支付成功"); //3.如果支付成功,支付日志表和订单表的支付状态改为已支付,redis的支付日志对象删除 orderService.updatePayStatus(username); break; } try { Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } //如果5分钟没有支付,则支付超时 if (flag > 100){ result = new Result(false,"二维码超时"); break; } flag++; } return result; }service
@Override public Map queryPayStatus(String out_trade_no) { Map param=new HashMap(); param.put("appid", appid);//公众账号ID param.put("mch_id", partner);//商户号 param.put("out_trade_no", out_trade_no);//订单号 param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串 String url="https://api.mch.weixin.qq.com/pay/orderquery"; try { String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey); HttpClient client=new HttpClient(url); client.setHttps(true); client.setXmlParam(xmlParam); client.post(); String result = client.getContent(); Map<String, String> map = WXPayUtil.xmlToMap(result); System.out.println(map); return map; } catch (Exception e) { e.printStackTrace(); return null; } }