微信提供
HttpClient.java 工具类
package cn.itcast.core.util; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.text.ParseException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContextBuilder; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.conn.ssl.X509HostnameVerifier; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; /** * 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; } }
BuyerCartServiceImpl
package cn.itcast.core.service; import cn.itcast.core.dao.item.ItemDao; import cn.itcast.core.pojo.entity.BuyerCart; import cn.itcast.core.pojo.item.Item; import cn.itcast.core.pojo.order.OrderItem; import cn.itcast.core.util.Constants; import com.alibaba.dubbo.config.annotation.Service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @Service public class BuyerCartServiceImpl implements BuyerCartService { @Autowired private RedisTemplate redisTemplate; @Autowired private ItemDao itemDao; @Override public List<BuyerCart> addItemToCartList(List<BuyerCart> cartList, Long itemId, Integer num) { //1. 根据商品SKU ID查询SKU商品信息 Item item = itemDao.selectByPrimaryKey(itemId); //2. 判断商品是否存在不存在, 抛异常 if (item == null) { throw new RuntimeException("您购买的商品不存在!"); } //3. 判断商品状态是否为1已审核, 状态不对抛异常 if (!"1".equals(item.getStatus())) { throw new RuntimeException("您购买的商品非法!"); } //4.获取商家ID String sellerId = item.getSellerId(); //5.根据商家ID查询购物车列表中是否存在该商家的购物车 BuyerCart buyerCart = findCartBySellerId(sellerId, cartList); //6.判断如果购物车列表中不存在该商家的购物车 if (buyerCart == null) { //6.a.1 新建购物车对象 buyerCart = new BuyerCart(); //向购物车中加入卖家id buyerCart.setSellerId(sellerId); //向购物车中加入卖家名称 buyerCart.setSellerName(item.getSeller()); //创建购物车中需要的购物项集合 List<OrderItem> orderItemList = new ArrayList<>(); //创建购物项对象 OrderItem orderItem = createOrderItem(item, num); //购物项加入购物项集合中 orderItemList.add(orderItem); //向购物车中加入购物项集合 buyerCart.setOrderItemList(orderItemList); //6.a.2 将新建的购物车对象添加到购物车列表 cartList.add(buyerCart); } else { //6.b.1如果购物车列表中存在该商家的购物车 (查询购物车明细列表中是否存在该商品) List<OrderItem> orderItemList = buyerCart.getOrderItemList(); OrderItem orderItem = findOrderItemByItemId(orderItemList, itemId); //6.b.2判断购物车明细是否为空 if (orderItem == null) { //6.b.3为空,新增购物车明细 orderItem = createOrderItem(item, num); //将新建的购物项对象放入购物项集合中 orderItemList.add(orderItem); } else { //6.b.4不为空,在原购物车明细上添加数量,更改金额 orderItem.setNum(orderItem.getNum() + num); orderItem.setTotalFee(orderItem.getPrice().multiply(new BigDecimal(orderItem.getNum()))); } //6.b.5如果购物车明细中数量操作后小于等于0,则移除 if (orderItem.getNum() <= 0) { orderItemList.remove(orderItem); } //6.b.6如果购物车中购物车明细列表为空,则移除 if (orderItemList.size() == 0) { cartList.remove(buyerCart); } } //7. 返回购物车列表对象 return cartList; } /** * 从购物项集合中找符合itemId的同款购物项 * @param orderItemList 购物项集合 * @param itemId 库存id * @return */ private OrderItem findOrderItemByItemId(List<OrderItem> orderItemList, Long itemId) { if (orderItemList != null) { for (OrderItem orderItem : orderItemList) { if (itemId.equals(orderItem.getItemId())) { return orderItem; } } } return null; } /** * 创建购物项对象 * @param item 库存对象 * @param num 购买商品数量 * @return */ private OrderItem createOrderItem(Item item, Integer num) { if (num == null || num <= 0) { throw new RuntimeException("您购买数量非法!"); } OrderItem orderItem = new OrderItem(); //库存标题 orderItem.setTitle(item.getTitle()); //购买数量 orderItem.setNum(num); //卖家id orderItem.setSellerId(item.getSellerId()); //商品单价 orderItem.setPrice(item.getPrice()); //示例图片地址 orderItem.setPicPath(item.getImage()); //库存id orderItem.setItemId(item.getId()); //商品id orderItem.setGoodsId(item.getGoodsId()); //总价 = 单价 * 购买数量 orderItem.setTotalFee(orderItem.getPrice().multiply(new BigDecimal(num))); return orderItem; } /** * 从购物车列表中获取这个卖家的购物车 * @param sellerId 卖家id * @param cartList 购物车列表 * @return */ private BuyerCart findCartBySellerId(String sellerId, List<BuyerCart> cartList) { if (cartList != null) { for (BuyerCart cart : cartList) { if (sellerId.equals(cart.getSellerId())) { return cart; } } } return null; } @Override public void setCartListToRedis(String userName, List<BuyerCart> cartList) { redisTemplate.boundHashOps(Constants.REDIS_CARTLIST).put(userName, cartList); } @Override public List<BuyerCart> getCartListFromRedis(String userName) { List<BuyerCart> cartList = (List<BuyerCart>)redisTemplate.boundHashOps(Constants.REDIS_CARTLIST).get(userName); if (cartList == null) { cartList = new ArrayList<BuyerCart>(); } return cartList; } @Override public List<BuyerCart> mergeCookieCartListToRedisCartList(List<BuyerCart> cookieCartList, List<BuyerCart> redisCartList) { if (cookieCartList != null) { //遍历cookie购物车集合 for (BuyerCart cart : cookieCartList) { List<OrderItem> orderItemList = cart.getOrderItemList(); if (orderItemList != null) { //遍历cookie中的购物项集合 for (OrderItem orderItem : orderItemList) { //向redis购物车集合中加入cookie中的购物项 redisCartList = addItemToCartList(redisCartList, orderItem.getItemId(), orderItem.getNum()); } } } } return redisCartList; } }
OrderServiceImpl
package cn.itcast.core.service; import cn.itcast.core.dao.log.PayLogDao; import cn.itcast.core.dao.order.OrderDao; import cn.itcast.core.dao.order.OrderItemDao; import cn.itcast.core.pojo.entity.BuyerCart; import cn.itcast.core.pojo.log.PayLog; import cn.itcast.core.pojo.order.Order; import cn.itcast.core.pojo.order.OrderItem; import cn.itcast.core.util.Constants; import cn.itcast.core.util.IdWorker; import com.alibaba.dubbo.config.annotation.Service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; @Service @Transactional public class OrderServiceImpl implements OrderService { @Autowired private IdWorker idWorker; @Autowired private PayLogDao payLogDao; @Autowired private OrderDao orderDao; @Autowired private OrderItemDao orderItemDao; @Autowired private RedisTemplate redisTemplate; @Override public void add(Order order, List<BuyerCart> cartList) { /** * 1. 遍历购物车集合 * 每一个购物车对象, 都保存一条order订单表数据 */ List<String> orderIdList=new ArrayList();//订单ID列表 double total_money=0;//总金额 (元) for(BuyerCart cart:cartList){ //生成一个id 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 /** * 2. 遍历购物项集合 * 每一个购物项对象, 都保存一条order_item订单详情表数据 */ double money=0; for(OrderItem orderItem :cart.getOrderItemList()){ 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;//累加到总金额 } /** * 3. 根据遍历过程中计算的总价钱, 保存一条支付日志数据 */ 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.insert(payLog);//插入到支付日志表 //将支付日志(未支付状态), 保存到redis中, 供支付使用 redisTemplate.boundHashOps(Constants.REDIS_PAYLOG).put(order.getUserId(), payLog);//放入缓存 } /** * 4. 保存支付日志, 订单集合, 订单详情集合完成后, 清空redis中的购物车 */ redisTemplate.boundHashOps(Constants.REDIS_CARTLIST).delete(order.getUserId()); } @Override public PayLog findPayLogFromRedis(String userName) { PayLog payLog = (PayLog)redisTemplate.boundHashOps(Constants.REDIS_PAYLOG).get(userName); if (payLog == null) { payLog = new PayLog(); } return payLog; } @Override public void updateOrderStatus(String out_trade_no, String transaction_id) { /** * 1.修改支付日志支付状态 */ PayLog payLog = payLogDao.selectByPrimaryKey(out_trade_no); //支付时间 payLog.setPayTime(new Date()); //支付状态改为1, 已支付 payLog.setTradeState("1"); //交易号, 微信给我们返回的 payLog.setTransactionId(transaction_id); //更新支付日志到数据库中 payLogDao.updateByPrimaryKeySelective(payLog); /** * 2.修改订单支付状态 */ String orderList = payLog.getOrderList();//获取订单号列表 String[] orderIds = orderList.split(",");//获取订单号数组 if (orderIds != null) { for (String orderId : orderIds) { Order order = new Order(); order.setStatus("2");//已付款 order.setOrderId(Long.parseLong(orderId)); orderDao.updateByPrimaryKeySelective(order); } } /** * 3. 清除redis缓存中的未支付日志数据 */ redisTemplate.boundHashOps(Constants.REDIS_PAYLOG).delete(payLog.getUserId()); } }
PayServiceImpl
package cn.itcast.core.service; import cn.itcast.core.util.HttpClient; import com.alibaba.dubbo.config.annotation.Service; import com.github.wxpay.sdk.WXPayUtil; import org.springframework.beans.factory.annotation.Value; import java.util.HashMap; import java.util.Map; @Service public class PayServiceImpl implements PayService { //微信公众账号或开放平台APP的唯一标识 @Value("${appid}") private String appid; //财付通平台的商户账号 @Value("${partner}") private String partner; //财付通平台的商户密钥 @Value("${partnerkey}") private String partnerkey; /** * 调用微信下单接口生成支付链接 * * @param tradeNo 支付单号 * @param totalFee 订单金额 * @return */ @Override public Map createNative(String tradeNo, 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", tradeNo);//商户订单号 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工具发送请求 HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder"); //使用https协议发送 client.setHttps(true); //发送的xml格式字符串数据 client.setXmlParam(xmlParam); //使用post请求发送 client.post(); //3.发送请求并获得结果 String result = client.getContent(); System.out.println(result); //调用微信工具类, 将返回的xml格式字符串转换成map格式 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", tradeNo);//订单号 return map; } catch (Exception e) { e.printStackTrace(); return new HashMap<>(); } } @Override public Map queryPayStatus(String tradeNo) { //封装发送的数据参数 Map param = new HashMap(); param.put("appid", appid);//公众账号ID param.put("mch_id", partner);//商户号 param.put("out_trade_no", tradeNo);//订单号 param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串 //发送的地址 String url = "https://api.mch.weixin.qq.com/pay/orderquery"; try { //调用微信工具类, 将封装的发送参数, 转换成xml格式字符串 String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey); //使用httpClient工具发送https请求, 到微信服务器 HttpClient client = new HttpClient(url); //设置使用https协议 client.setHttps(true); //设置发送的内容 client.setXmlParam(xmlParam); //设置post请求发送 client.post(); //发送并返回结果, 结果为xml格式字符串 String result = client.getContent(); //调用微信工具类, 将返回的xml格式字符串转换成Map Map<String, String> map = WXPayUtil.xmlToMap(result); System.out.println(map); return map; } catch (Exception e) { e.printStackTrace(); return null; } } }
PayController
package cn.itcast.core.controller; import cn.itcast.core.pojo.entity.Result; import cn.itcast.core.pojo.log.PayLog; import cn.itcast.core.service.OrderService; import cn.itcast.core.service.PayService; import com.alibaba.dubbo.config.annotation.Reference; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Map; /** * 支付流程 */ @RestController @RequestMapping("/pay") public class PayController { @Reference private OrderService orderService; @Reference private PayService payService; /** * 生成支付链接 */ @RequestMapping("/createNative") public Map createNative() { //1.获取当前登录用户的用户名 String userName = SecurityContextHolder.getContext().getAuthentication().getName(); //2.根据当前登录的用户的用户名到redis中获取未支付的日志记录 PayLog payLog = orderService.findPayLogFromRedis(userName); //3.根据日志对象中的支付单号和总金额调用,微信同意下单接口,生成支付链接返回 //"1"String.valueof(paylog.getTotalFee()) Map resultMap = payService.createNative(payLog.getOutTradeNo(), "1"); return resultMap; } @RequestMapping("/queryPayStatus") public Result queryPayStatus(String out_trade_no) { Result result = null; int flag = 1; //1.死循环 while (true) { //2.根据支付单号.调用微信的查询订单就扣查询支付状态 Map resultMap = payService.queryPayStatus(out_trade_no); //3.如果返回空的对象表示支付超时 if (resultMap == null) { result = new Result(false, "二维码超时"); break; } //4.如果返回数据中trade_state属性为SUCCESS代表支付成功 if ("SUCCESS".equals(resultMap.get("trade_state"))) { orderService.updateOrderStatus(out_trade_no, String.valueOf(resultMap.get("transaction_id"))); result = new Result(true, "支付成功"); break; } //超过20分钟未支付,这支付超时 if (flag >= 400) { result = new Result(false, "二维码超时"); break; } } try { Thread.sleep(3000); flag++; } catch (InterruptedException e) { e.printStackTrace(); result = new Result(false, "二维码超时"); } return result; } }
OrderController
package cn.itcast.core.controller; import cn.itcast.core.pojo.entity.BuyerCart; import cn.itcast.core.pojo.entity.Result; import cn.itcast.core.pojo.order.Order; import cn.itcast.core.service.BuyerCartService; import cn.itcast.core.service.OrderService; import com.alibaba.dubbo.config.annotation.Reference; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @RequestMapping("/order") public class OrderController { @Reference private OrderService orderService; @Reference private BuyerCartService buyerCartService; /** * 提交订单 * @param order 页面传入这个对象里面只有收货人地址, 联系人姓名, 手机号 * @return */ @RequestMapping("/add") public Result add(@RequestBody Order order) { try { //1. 获取当前登录用户的用户名 String userName = SecurityContextHolder.getContext().getAuthentication().getName(); //2. 将当前用户的用户名放入页面传进来的order对象中 order.setUserId(userName); //3. 通过登录用户的用户名获取这个人的购物车列表 List<BuyerCart> cartList = buyerCartService.getCartListFromRedis(userName); //3. 保存订单 orderService.add(order, cartList); return new Result(true, "保存订单成功!"); } catch (Exception e) { e.printStackTrace(); return new Result(false, "保存订单失败!"); } } }