Commit 5920f9b1 authored by Junling Bu's avatar Junling Bu
Browse files

采用乐观锁更新数据,需要处理更新失败的情况。

parent 4d1ec91b
...@@ -39,7 +39,7 @@ public class LitemallUserService { ...@@ -39,7 +39,7 @@ public class LitemallUserService {
userMapper.insertSelective(user); userMapper.insertSelective(user);
} }
public int update(LitemallUser user) { public int updateById(LitemallUser user) {
return userMapper.updateWithVersionByPrimaryKeySelective(user.getVersion(), user); return userMapper.updateWithVersionByPrimaryKeySelective(user.getVersion(), user);
} }
......
...@@ -160,7 +160,9 @@ public class WxAddressController { ...@@ -160,7 +160,9 @@ public class WxAddressController {
addressService.add(address); addressService.add(address);
} else { } else {
address.setUserId(userId); address.setUserId(userId);
addressService.update(address); if(addressService.updateId(address) == 0){
return ResponseUtil.updatedDateExpired();
}
} }
return ResponseUtil.ok(address.getId()); return ResponseUtil.ok(address.getId());
} }
......
...@@ -166,7 +166,9 @@ public class WxAuthController { ...@@ -166,7 +166,9 @@ public class WxAuthController {
} else { } else {
user.setLastLoginTime(LocalDateTime.now()); user.setLastLoginTime(LocalDateTime.now());
user.setLastLoginIp(IpUtil.client(request)); user.setLastLoginIp(IpUtil.client(request));
userService.update(user); if(userService.updateById(user) == 0){
return ResponseUtil.updatedDateExpired();
}
} }
// token // token
...@@ -333,7 +335,9 @@ public class WxAuthController { ...@@ -333,7 +335,9 @@ public class WxAuthController {
String encodedPassword = encoder.encode(password); String encodedPassword = encoder.encode(password);
user.setPassword(encodedPassword); user.setPassword(encodedPassword);
userService.update(user); if(userService.updateById(user) == 0){
return ResponseUtil.updatedDateExpired();
}
return ResponseUtil.ok(); return ResponseUtil.ok();
} }
...@@ -347,7 +351,9 @@ public class WxAuthController { ...@@ -347,7 +351,9 @@ public class WxAuthController {
String phone = phoneNumberInfo.getPhoneNumber(); String phone = phoneNumberInfo.getPhoneNumber();
LitemallUser user = userService.findById(userId); LitemallUser user = userService.findById(userId);
user.setMobile(phone); user.setMobile(phone);
userService.update(user); if(userService.updateById(user) == 0){
return ResponseUtil.updatedDateExpired();
}
return ResponseUtil.ok(); return ResponseUtil.ok();
} }
} }
...@@ -150,7 +150,9 @@ public class WxCartController { ...@@ -150,7 +150,9 @@ public class WxCartController {
return ResponseUtil.fail(400, "库存不足"); return ResponseUtil.fail(400, "库存不足");
} }
existCart.setNumber((short) num); existCart.setNumber((short) num);
cartService.update(existCart); if(cartService.updateById(existCart) == 0){
return ResponseUtil.updatedDateExpired();
}
} }
return goodscount(userId); return goodscount(userId);
...@@ -221,7 +223,9 @@ public class WxCartController { ...@@ -221,7 +223,9 @@ public class WxCartController {
return ResponseUtil.fail(400, "库存不足"); return ResponseUtil.fail(400, "库存不足");
} }
existCart.setNumber((short) num); existCart.setNumber((short) num);
cartService.update(existCart); if(cartService.updateById(existCart) == 0){
return ResponseUtil.updatedDateExpired();
}
} }
return ResponseUtil.ok(existCart != null ? existCart.getId() : cart.getId()); return ResponseUtil.ok(existCart != null ? existCart.getId() : cart.getId());
...@@ -281,7 +285,9 @@ public class WxCartController { ...@@ -281,7 +285,9 @@ public class WxCartController {
} }
existCart.setNumber(number.shortValue()); existCart.setNumber(number.shortValue());
cartService.update(existCart); if(cartService.updateById(existCart) == 0){
return ResponseUtil.updatedDateExpired();
}
return ResponseUtil.ok(); return ResponseUtil.ok();
} }
......
...@@ -5,6 +5,7 @@ import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; ...@@ -5,6 +5,7 @@ import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult; import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
...@@ -37,6 +38,7 @@ import org.springframework.web.bind.annotation.*; ...@@ -37,6 +38,7 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
...@@ -426,7 +428,9 @@ public class WxOrderController { ...@@ -426,7 +428,9 @@ public class WxOrderController {
throw new RuntimeException("下单的商品货品数量大于库存量"); throw new RuntimeException("下单的商品货品数量大于库存量");
} }
product.setNumber(remainNumber); product.setNumber(remainNumber);
productService.updateById(product); if(productService.updateById(product) == 0){
throw new Exception("更新数据已失效");
}
} }
//如果是团购项目,添加团购信息 //如果是团购项目,添加团购信息
...@@ -509,7 +513,9 @@ public class WxOrderController { ...@@ -509,7 +513,9 @@ public class WxOrderController {
// 设置订单已取消状态 // 设置订单已取消状态
order.setOrderStatus(OrderUtil.STATUS_CANCEL); order.setOrderStatus(OrderUtil.STATUS_CANCEL);
order.setEndTime(LocalDateTime.now()); order.setEndTime(LocalDateTime.now());
orderService.updateById(order); if(orderService.updateById(order) == 0){
throw new Exception("更新数据已失效");
}
// 商品货品数量增加 // 商品货品数量增加
List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId); List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
...@@ -518,7 +524,9 @@ public class WxOrderController { ...@@ -518,7 +524,9 @@ public class WxOrderController {
LitemallProduct product = productService.findById(productId); LitemallProduct product = productService.findById(productId);
Integer number = product.getNumber() + orderGoods.getNumber(); Integer number = product.getNumber() + orderGoods.getNumber();
product.setNumber(number); product.setNumber(number);
productService.updateById(product); if(productService.updateById(product) == 0){
throw new Exception("更新数据已失效");
}
} }
} catch (Exception ex) { } catch (Exception ex) {
txManager.rollback(status); txManager.rollback(status);
...@@ -603,7 +611,9 @@ public class WxOrderController { ...@@ -603,7 +611,9 @@ public class WxOrderController {
return ResponseUtil.fail(403, "订单不能支付"); return ResponseUtil.fail(403, "订单不能支付");
} }
orderService.updateById(order); if(orderService.updateById(order) == 0){
return ResponseUtil.updatedDateExpired();
}
return ResponseUtil.ok(result); return ResponseUtil.ok(result);
} }
...@@ -623,35 +633,67 @@ public class WxOrderController { ...@@ -623,35 +633,67 @@ public class WxOrderController {
*/ */
@PostMapping("pay-notify") @PostMapping("pay-notify")
public Object payNotify(HttpServletRequest request, HttpServletResponse response) { public Object payNotify(HttpServletRequest request, HttpServletResponse response) {
String xmlResult = null;
try { try {
String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding()); xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult); } catch (IOException e) {
e.printStackTrace();
return WxPayNotifyResponse.fail(e.getMessage());
}
WxPayOrderNotifyResult result = null;
try {
result = wxPayService.parseOrderNotifyResult(xmlResult);
} catch (WxPayException e) {
e.printStackTrace();
return WxPayNotifyResponse.fail(e.getMessage());
}
logger.info("处理腾讯支付平台的订单支付");
logger.info(result);
String orderSn = result.getOutTradeNo(); String orderSn = result.getOutTradeNo();
String payId = result.getTransactionId(); String payId = result.getTransactionId();
// 分转化成元 // 分转化成元
String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee()); String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
LitemallOrder order = orderService.findBySn(orderSn); LitemallOrder order = orderService.findBySn(orderSn);
if (order == null) { if (order == null) {
throw new Exception("订单不存在 sn=" + orderSn); return WxPayNotifyResponse.fail("订单不存在 sn=" + orderSn);
} }
// 检查这个订单是否已经处理过 // 检查这个订单是否已经处理过
if (OrderUtil.isPayStatus(order) && order.getPayId() != null) { if (OrderUtil.isPayStatus(order) && order.getPayId() != null) {
return WxPayNotifyResponse.success("处理成功!"); return WxPayNotifyResponse.success("订单已经处理成功!");
} }
// 检查支付订单金额 // 检查支付订单金额
if (!totalFee.equals(order.getActualPrice().toString())) { if (!totalFee.equals(order.getActualPrice().toString())) {
throw new Exception(order.getOrderSn() + " : 支付金额不符合 totalFee=" + totalFee); return WxPayNotifyResponse.fail(order.getOrderSn() + " : 支付金额不符合 totalFee=" + totalFee);
} }
order.setPayId(payId); order.setPayId(payId);
order.setPayTime(LocalDateTime.now()); order.setPayTime(LocalDateTime.now());
order.setOrderStatus(OrderUtil.STATUS_PAY); order.setOrderStatus(OrderUtil.STATUS_PAY);
orderService.updateById(order); if (orderService.updateById(order) == 0) {
// 这里可能存在这样一个问题,用户支付和系统自动取消订单发生在同时
// 如果数据库首先因为系统自动取消订单而更新了订单状态;
// 此时用户支付完成回调这里也要更新数据库,而由于乐观锁机制这里的更新会失败
// 因此,这里会重新读取数据库检查状态是否是订单自动取消,如果是则更新成支付状态。
order = orderService.findBySn(orderSn);
int updated = 0;
if(OrderUtil.isAutoCancelStatus(order)){
order.setPayId(payId);
order.setPayTime(LocalDateTime.now());
order.setOrderStatus(OrderUtil.STATUS_PAY);
updated = orderService.updateById(order);
}
// 如果updated是0,那么数据库更新失败
if(updated == 0) {
return WxPayNotifyResponse.fail("更新数据已失效");
}
}
// 支付成功,有团购信息,更新团购信息 // 支付成功,有团购信息,更新团购信息
LitemallGroupon groupon = grouponService.queryByOrderId(order.getId()); LitemallGroupon groupon = grouponService.queryByOrderId(order.getId());
...@@ -664,21 +706,18 @@ public class WxOrderController { ...@@ -664,21 +706,18 @@ public class WxOrderController {
groupon.setShareUrl(url); groupon.setShareUrl(url);
} }
groupon.setPayed(true); groupon.setPayed(true);
grouponService.update(groupon); if (grouponService.updateById(groupon) == 0) {
return WxPayNotifyResponse.fail("更新数据已失效");
}
} }
//TODO 发送邮件和短信通知,这里采用异步发送 //TODO 发送邮件和短信通知,这里采用异步发送
// 订单支付成功以后,会发送短信给用户,以及发送邮件给管理员 // 订单支付成功以后,会发送短信给用户,以及发送邮件给管理员
notifyService.notifyMail("新订单通知", order.toString()); notifyService.notifyMail("新订单通知", order.toString());
/** // 这里微信的短信平台对参数长度有限制,所以将订单号只截取后6位
* 这里微信的短信平台对参数长度有限制,所以将订单号只截取后6位
*
*/
notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED, new String[]{orderSn.substring(8, 14)}); notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED, new String[]{orderSn.substring(8, 14)});
/** // 请依据自己的模版消息配置更改参数
* 请依据自己的模版消息配置更改参数
*/
String[] parms = new String[]{ String[] parms = new String[]{
order.getOrderSn(), order.getOrderSn(),
order.getOrderPrice().toString(), order.getOrderPrice().toString(),
...@@ -691,10 +730,6 @@ public class WxOrderController { ...@@ -691,10 +730,6 @@ public class WxOrderController {
notifyService.notifyWxTemplate(result.getOpenid(), NotifyType.PAY_SUCCEED, parms, "pages/index/index?orderId=" + order.getId()); notifyService.notifyWxTemplate(result.getOpenid(), NotifyType.PAY_SUCCEED, parms, "pages/index/index?orderId=" + order.getId());
return WxPayNotifyResponse.success("处理成功!"); return WxPayNotifyResponse.success("处理成功!");
} catch (Exception e) {
logger.error("微信回调结果异常,异常原因 " + e.getMessage());
return WxPayNotifyResponse.fail(e.getMessage());
}
} }
/** /**
...@@ -733,7 +768,9 @@ public class WxOrderController { ...@@ -733,7 +768,9 @@ public class WxOrderController {
// 设置订单申请退款状态 // 设置订单申请退款状态
order.setOrderStatus(OrderUtil.STATUS_REFUND); order.setOrderStatus(OrderUtil.STATUS_REFUND);
orderService.updateById(order); if(orderService.updateById(order) == 0){
return ResponseUtil.updatedDateExpired();
}
//TODO 发送邮件和短信通知,这里采用异步发送 //TODO 发送邮件和短信通知,这里采用异步发送
// 有用户申请退款,邮件通知运营人员 // 有用户申请退款,邮件通知运营人员
...@@ -778,7 +815,9 @@ public class WxOrderController { ...@@ -778,7 +815,9 @@ public class WxOrderController {
order.setOrderStatus(OrderUtil.STATUS_CONFIRM); order.setOrderStatus(OrderUtil.STATUS_CONFIRM);
order.setConfirmTime(LocalDateTime.now()); order.setConfirmTime(LocalDateTime.now());
orderService.updateById(order); if(orderService.updateById(order) == 0){
return ResponseUtil.updatedDateExpired();
}
return ResponseUtil.ok(); return ResponseUtil.ok();
} }
......
...@@ -27,7 +27,7 @@ public class WxSearchController { ...@@ -27,7 +27,7 @@ public class WxSearchController {
/** /**
* 搜索页面信息 * 搜索页面信息
* * <p>
* 如果用户已登录,则给出用户历史搜索记录。 * 如果用户已登录,则给出用户历史搜索记录。
* *
* @param userId 用户ID * @param userId 用户ID
...@@ -53,11 +53,10 @@ public class WxSearchController { ...@@ -53,11 +53,10 @@ public class WxSearchController {
List<LitemallKeyword> hotKeywordList = keywordsService.queryHots(); List<LitemallKeyword> hotKeywordList = keywordsService.queryHots();
List<LitemallSearchHistory> historyList = null; List<LitemallSearchHistory> historyList = null;
if(userId != null) { if (userId != null) {
//取出用户历史关键字 //取出用户历史关键字
historyList = searchHistoryService.queryByUid(userId); historyList = searchHistoryService.queryByUid(userId);
} } else {
else {
historyList = new ArrayList<>(0); historyList = new ArrayList<>(0);
} }
...@@ -70,7 +69,7 @@ public class WxSearchController { ...@@ -70,7 +69,7 @@ public class WxSearchController {
/** /**
* 关键字提醒 * 关键字提醒
* * <p>
* 当用户输入关键字一部分时,可以推荐系统中合适的关键字。 * 当用户输入关键字一部分时,可以推荐系统中合适的关键字。
* *
* @param keyword 关键字 * @param keyword 关键字
...@@ -98,7 +97,7 @@ public class WxSearchController { ...@@ -98,7 +97,7 @@ public class WxSearchController {
/** /**
* 关键字清理 * 关键字清理
* * <p>
* 当用户输入关键字一部分时,可以推荐系统中合适的关键字。 * 当用户输入关键字一部分时,可以推荐系统中合适的关键字。
* *
* @param userId 用户ID * @param userId 用户ID
...@@ -108,7 +107,7 @@ public class WxSearchController { ...@@ -108,7 +107,7 @@ public class WxSearchController {
*/ */
@PostMapping("clearhistory") @PostMapping("clearhistory")
public Object clearhistory(@LoginUser Integer userId) { public Object clearhistory(@LoginUser Integer userId) {
if(userId == null){ if (userId == null) {
return ResponseUtil.unlogin(); return ResponseUtil.unlogin();
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment