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>二维码入门小demotitle>
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;
}
}