WxOrderServiceImpl.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. package com.miaxis.wx.service.impl;
  2. import java.io.IOException;
  3. import java.text.SimpleDateFormat;
  4. import java.util.*;
  5. import java.util.stream.Collectors;
  6. import com.alibaba.fastjson.JSONArray;
  7. import com.alibaba.fastjson.JSONObject;
  8. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  9. import com.miaxis.activities.domain.ActivitiesTmall;
  10. import com.miaxis.activities.service.IActivitiesTmallService;
  11. import com.miaxis.common.enums.OrderStatusEnum;
  12. import com.miaxis.common.exception.CustomException;
  13. import com.miaxis.common.sms.MD5Utils;
  14. import com.miaxis.common.utils.StringUtils;
  15. import com.miaxis.feign.dto.FilmDTO;
  16. import com.miaxis.feign.dto.FilmMcpData;
  17. import com.miaxis.feign.dto.FilmXdResult;
  18. import com.miaxis.feign.dto.fulu.FuluCommonApiDTO;
  19. import com.miaxis.feign.dto.fulu.FuluDTO;
  20. import com.miaxis.feign.dto.fulu.FuluGoodsInfo;
  21. import com.miaxis.feign.dto.fulu.FuluResult;
  22. import com.miaxis.feign.service.IFuluService;
  23. import com.miaxis.wx.dto.*;
  24. import com.miaxis.system.service.ISysConfigService;
  25. import com.miaxis.wx.service.IRefundRecordService;
  26. import lombok.extern.slf4j.Slf4j;
  27. import org.apache.http.HttpResponse;
  28. import org.apache.http.HttpStatus;
  29. import org.apache.http.client.entity.UrlEncodedFormEntity;
  30. import org.apache.http.client.methods.HttpPost;
  31. import org.apache.http.impl.client.CloseableHttpClient;
  32. import org.apache.http.impl.client.HttpClientBuilder;
  33. import org.apache.http.message.BasicNameValuePair;
  34. import org.apache.http.util.EntityUtils;
  35. import org.springframework.beans.factory.annotation.Autowired;
  36. import org.springframework.beans.factory.annotation.Value;
  37. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  38. import org.springframework.stereotype.Service;
  39. import com.miaxis.wx.mapper.WxOrderMapper;
  40. import com.miaxis.wx.domain.WxOrder;
  41. import com.miaxis.wx.service.IWxOrderService;
  42. import javax.annotation.Resource;
  43. import static com.miaxis.common.utils.OrderCodeFactory.getOrderCode;
  44. /**
  45. * 电影订单Service业务层处理
  46. *
  47. * @author miaxis
  48. * @date 2021-05-07
  49. */
  50. @Service
  51. @Slf4j
  52. public class WxOrderServiceImpl extends ServiceImpl<WxOrderMapper, WxOrder> implements IWxOrderService {
  53. @Resource
  54. private WxOrderMapper wxOrderMapper;
  55. @Autowired
  56. private ISysConfigService configService;
  57. @Autowired
  58. private IRefundRecordService refundRecordService;
  59. @Autowired
  60. private IFuluService fuluService;
  61. @Autowired
  62. private IActivitiesTmallService activitiesTmallService;
  63. @Autowired
  64. private ThreadPoolTaskExecutor threadPoolTaskExecutor;
  65. @Value("${film.notifyUrl}")
  66. private String notifyUrl ;
  67. @Value("${app.appid}")
  68. private String appid;
  69. @Value("${film.appKey}")
  70. private String appKey ;
  71. @Value("${film.appSecret}")
  72. private String appSecret ;
  73. @Value("${film.v1Url}")
  74. private String v1Url ;
  75. @Value("${film.v2Url}")
  76. private String v2Url ;
  77. @Value("${fulu.appKey}")
  78. private String fuluAppKey ;
  79. @Value("${fulu.appSecret}")
  80. private String fuluAppSecret ;
  81. /**
  82. * 查询电影订单列表
  83. *
  84. * @param wxOrder 电影订单
  85. * @return 电影订单
  86. */
  87. @Override
  88. public List<WxOrder> selectWxOrderList(WxOrder wxOrder){
  89. return wxOrderMapper.selectWxOrderList(wxOrder);
  90. }
  91. @Override
  92. public WxOrder getByOutTradeNo(String outTradeNo) {
  93. return wxOrderMapper.getByOutTradeNo(outTradeNo);
  94. }
  95. @Override
  96. public String excuteFilmApi(FilmDTO filmDTO) {
  97. String resultData ="";
  98. // 创建一个http客户端
  99. CloseableHttpClient httpClient = HttpClientBuilder.create().build();
  100. try {
  101. HttpPost post = null;
  102. if ("api/automation/orderHandle".equals(filmDTO.getUrl())) {
  103. post = new HttpPost(v1Url+filmDTO.getUrl());
  104. }else{
  105. post = new HttpPost(v2Url+filmDTO.getUrl());
  106. }
  107. post.setHeader("Content-Type","application/x-www-form-urlencoded");
  108. Map<String, Object> sortMap = new TreeMap<String, Object>();
  109. String time = String.valueOf(System.currentTimeMillis()/1000);
  110. sortMap.put("appKey",appKey);
  111. sortMap.put("time",time);
  112. //1 将数据拆分成 treemap存储
  113. if (!StringUtils.isEmpty(filmDTO.getParamData())){
  114. String[] keyValueStr = filmDTO.getParamData().split("&");
  115. for(String keyValue : keyValueStr){
  116. String[] arr = keyValue.split("=");
  117. sortMap.put(arr[0],arr[1]) ;
  118. }
  119. }
  120. //2 读取treemap。按固定格式拼接,最后再拼接上 secret
  121. StringBuilder builder = new StringBuilder();
  122. for (Map.Entry<String, Object> s : sortMap.entrySet()) {
  123. String k = s.getKey();
  124. Object v = s.getValue();
  125. builder.append(k).append("=").append(v).append("&");
  126. }
  127. builder.append("appSecret="+appSecret);
  128. //3 将最后拼接出来的sign传 md5加密
  129. String sign = MD5Utils.MD5Encode(builder.toString());
  130. List<BasicNameValuePair> pairList = new ArrayList<BasicNameValuePair>();
  131. // 迭代Map-->取出key,value放到BasicNameValuePair对象中-->添加到list中
  132. for (Map.Entry entry : sortMap.entrySet()) {
  133. pairList.add(new BasicNameValuePair(String.valueOf(entry.getKey()) ,String.valueOf(entry.getValue())));
  134. }
  135. pairList.add(new BasicNameValuePair("sign",sign));
  136. UrlEncodedFormEntity uefe = new UrlEncodedFormEntity(pairList, "utf-8");
  137. post.setEntity(uefe);
  138. // 发送post请求
  139. HttpResponse response = httpClient.execute(post);
  140. // 状态码为:200
  141. if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
  142. // 返回数据:
  143. resultData = EntityUtils.toString(response.getEntity(),"UTF-8");
  144. return resultData;
  145. }else{
  146. throw new RuntimeException("接口连接失败!");
  147. }
  148. } catch (Exception e) {
  149. e.printStackTrace();
  150. throw new RuntimeException("接口连接失败!");
  151. } finally {
  152. try {
  153. httpClient.close();
  154. } catch (IOException e) {
  155. throw new RuntimeException("CloseableHttpClient 关闭失败!");
  156. }
  157. }
  158. }
  159. @Override
  160. public List<WxOrder> selectOrderList(WxOrderListDTO wxOrderListDTO) {
  161. return wxOrderMapper.selectOrderList(wxOrderListDTO);
  162. }
  163. @Override
  164. public Integer getPrice(String cinemaId, String showId, int ticketType, FilmWxOrderJsonData wxOrderJsonData) {
  165. FilmDTO filmDTO = new FilmDTO();
  166. filmDTO.setUrl("movieapi/movie-info/get-schedule-list");
  167. StringBuffer paramData = new StringBuffer();
  168. paramData.append("cinemaId="+cinemaId);
  169. filmDTO.setParamData(paramData.toString());
  170. String result = this.excuteFilmApi(filmDTO);
  171. JSONObject jsonObject = JSONObject.parseObject(result);
  172. JSONObject data = jsonObject.getJSONObject("data");
  173. JSONObject discountRule = data.getJSONObject("discountRule");
  174. JSONArray list = data.getJSONArray("list");
  175. log.info(list.toJSONString());
  176. List<CinemaData> cinemaData = list.toJavaList(CinemaData.class);
  177. List<CinemaData> listdata = cinemaData.stream().filter(a -> showId.equals(a.getShowId())).collect(Collectors.toList());
  178. CinemaData realCinemaData = listdata.get(0);
  179. wxOrderJsonData.setCinemaData(realCinemaData);
  180. Integer netPrice = realCinemaData.getNetPrice();
  181. Integer realValue =0;
  182. if (ticketType == 1){
  183. Double upDiscountRate = discountRule.getDouble("upDiscountRate");
  184. Double downDiscountRate = discountRule.getDouble("downDiscountRate");
  185. String film_discount = configService.selectConfigByKey("film_discount");
  186. Double chosenDiscount = netPrice >3900 ? upDiscountRate:downDiscountRate;
  187. Double aDouble = Double.valueOf(film_discount);
  188. Double dDouble = netPrice * chosenDiscount * aDouble;
  189. realValue = dDouble.intValue();
  190. }else if (ticketType == 2){
  191. realValue = netPrice;
  192. }
  193. return realValue;
  194. }
  195. @Override
  196. public void createFilmOrder(WxOrder order, WxOrderCreateDTO wxOrderCreateDTO) {
  197. FilmWxOrderJsonData filmWxOrderJsonData = new FilmWxOrderJsonData();
  198. wxOrderCreateDTO.setThirdOrderId(order.getOutTradeNo());
  199. filmWxOrderJsonData.setWxOrderCreateDTO(wxOrderCreateDTO);
  200. Integer price = getPrice(wxOrderCreateDTO.getCinemaId(),wxOrderCreateDTO.getShowId(),wxOrderCreateDTO.getTicketType(),filmWxOrderJsonData);
  201. int number = wxOrderCreateDTO.getSeat().split(",").length;
  202. order.setOrderDataJson(JSONObject.toJSONString(filmWxOrderJsonData));
  203. order.setTotal(price*number);
  204. }
  205. @Override
  206. public void createFuluOrder(WxOrder order, WxOrderCreateFuluDTO wxOrderCreateDTO) {
  207. FuluWxOrderJsonData fuluWxOrderJsonData = new FuluWxOrderJsonData();
  208. wxOrderCreateDTO.setCustomer_order_no(order.getOutTradeNo());
  209. fuluWxOrderJsonData.setWxOrderCreateDTO(wxOrderCreateDTO);
  210. order.setOrderDataJson(JSONObject.toJSONString(fuluWxOrderJsonData));
  211. //调用福禄接口 获取产品详情对象
  212. FuluDTO fuluDTO = new FuluDTO();
  213. FuluCommonApiDTO fuluCommonApiDTO = new FuluCommonApiDTO();
  214. fuluCommonApiDTO.setMethod("fulu.goods.info.get");
  215. JSONObject jsonObject = new JSONObject();
  216. jsonObject.put("product_id",wxOrderCreateDTO.getProduct_id());
  217. fuluCommonApiDTO.setBiz_content(jsonObject.toJSONString());
  218. init(fuluDTO,fuluCommonApiDTO);
  219. FuluResult fuluResult = fuluService.fuluCommonApi(fuluDTO);
  220. if (fuluResult.getCode()!= 0){
  221. throw new CustomException("福禄接口调用失败:"+fuluResult.getMessage());
  222. }
  223. FuluGoodsInfo fuluGoodsInfo = JSONObject.parseObject(fuluResult.getResult(), FuluGoodsInfo.class);
  224. fuluWxOrderJsonData.setFuluGoodsInfo(fuluGoodsInfo);
  225. String fuluVipDiscount = configService.selectConfigByKey("fulu_vip_discount");
  226. Double fuluVipDiscountDoubleValue = Double.valueOf(fuluVipDiscount);
  227. Double v =fuluGoodsInfo.getPurchase_price()* fuluVipDiscountDoubleValue * wxOrderCreateDTO.getBuy_num()* 100;
  228. order.setTotal(v.intValue());
  229. }
  230. @Override
  231. public void init(FuluDTO fuluDTO, FuluCommonApiDTO fuluCommonApiDTO) {
  232. fuluDTO.setApp_key(fuluAppKey);
  233. fuluDTO.setMethod(fuluCommonApiDTO.getMethod());
  234. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  235. fuluDTO.setTimestamp(simpleDateFormat.format(new Date()));
  236. fuluDTO.setVersion("2.0");
  237. fuluDTO.setFormat("json");
  238. fuluDTO.setCharset("utf-8");
  239. fuluDTO.setSign_type("md5");
  240. fuluDTO.setApp_auth_token("");
  241. fuluDTO.setBiz_content(fuluCommonApiDTO.getBiz_content());
  242. String str = JSONObject.toJSONString(fuluDTO);
  243. char[] s = str.toCharArray();
  244. Arrays.sort(s);
  245. String outputSignOriginalStr = new String(s) + fuluAppSecret;
  246. String sign = MD5Utils.MD5Encode(outputSignOriginalStr);
  247. fuluDTO.setSign(sign);
  248. }
  249. @Override
  250. public void buyFilmOrder(WxOrder wxOrder) {
  251. String orderDataJson = wxOrder.getOrderDataJson();
  252. FilmWxOrderJsonData wxOrderJsonData = JSONObject.parseObject(orderDataJson, FilmWxOrderJsonData.class);
  253. if (wxOrderJsonData != null && wxOrderJsonData.getWxOrderNotifyDTO() == null){
  254. threadPoolTaskExecutor.execute(new Runnable() {
  255. @Override
  256. public void run() {
  257. WxOrderCreateDTO wxOrderCreateDTO = wxOrderJsonData.getWxOrderCreateDTO();
  258. FilmDTO filmDTO = new FilmDTO();
  259. if (wxOrderCreateDTO.getTicketType() ==1){
  260. filmDTO.setUrl("api/order/create");
  261. }else if (wxOrderCreateDTO.getTicketType() ==2){
  262. filmDTO.setUrl("api/order/create-soon-order");
  263. }
  264. StringBuffer paramData = new StringBuffer();
  265. paramData.append("showId="+wxOrderCreateDTO.getShowId()+"&");
  266. paramData.append("seat="+wxOrderCreateDTO.getSeat()+"&");
  267. if (wxOrderCreateDTO.getReservedPhone() != null){
  268. paramData.append("reservedPhone="+wxOrderCreateDTO.getReservedPhone()+"&");
  269. }
  270. paramData.append("thirdOrderId="+wxOrderCreateDTO.getThirdOrderId()+"&");
  271. paramData.append("notifyUrl="+notifyUrl+"&");
  272. if (wxOrderCreateDTO.getSeatId() != null){
  273. paramData.append("seatId="+wxOrderCreateDTO.getSeatId()+"&");
  274. }
  275. if (wxOrderCreateDTO.getSeatNo() != null){
  276. paramData.append("seatNo="+wxOrderCreateDTO.getSeatNo()+"&");
  277. }
  278. paramData.append("acceptChangeSeat="+wxOrderCreateDTO.getAcceptChangeSeat());
  279. filmDTO.setParamData(paramData.toString());
  280. String s = excuteFilmApi(filmDTO);
  281. log.info("电影下单返回值:"+s);
  282. FilmXdResult filmXdResult = JSONObject.parseObject(s, FilmXdResult.class);
  283. //如果返回值不是200 ,则调用退款流程
  284. if (filmXdResult.getCode()!=200){
  285. String refundCode = getOrderCode(null);
  286. wxOrder.setOrderStatus(OrderStatusEnum.FAILD.getCode());
  287. wxOrder.setOutRefundNo(refundCode);
  288. try {
  289. refundRecordService.refund(wxOrder,refundCode,"电影购票失败,原因:"+filmXdResult.getMessage());
  290. } catch (Exception e) {
  291. throw new CustomException("退款失败");
  292. }
  293. }else {
  294. wxOrder.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
  295. if (filmXdResult.getData().getTicket()!= null){
  296. wxOrder.setOrderStatus(OrderStatusEnum.SUCCESS.getCode());
  297. FilmMcpData filmMcpData = filmXdResult.getData();
  298. wxOrderJsonData.setFilmMcpData(filmMcpData);
  299. wxOrder.setOrderDataJson(JSONObject.toJSONString(wxOrderJsonData));
  300. }
  301. }
  302. updateById(wxOrder);
  303. }
  304. });
  305. }
  306. }
  307. @Override
  308. public void buyFuluOrder(WxOrder wxOrder) {
  309. String orderDataJson = wxOrder.getOrderDataJson();
  310. FuluWxOrderJsonData wxOrderJsonData = JSONObject.parseObject(orderDataJson, FuluWxOrderJsonData.class);
  311. if (wxOrderJsonData != null && wxOrderJsonData.getWxFuluOrderDetailDTO()== null){
  312. threadPoolTaskExecutor.execute(new Runnable() {
  313. @Override
  314. public void run() {
  315. WxOrderCreateFuluDTO wxOrderCreateDTO = wxOrderJsonData.getWxOrderCreateDTO();
  316. //调用福禄下单接口
  317. FuluDTO fuluDTO = new FuluDTO();
  318. FuluCommonApiDTO fuluCommonApiDTO = new FuluCommonApiDTO();
  319. fuluCommonApiDTO.setMethod("fulu.order.direct.add");
  320. JSONObject jsonObject = new JSONObject();
  321. jsonObject.put("product_id",wxOrderCreateDTO.getProduct_id());
  322. jsonObject.put("customer_order_no",wxOrderCreateDTO.getCustomer_order_no());
  323. jsonObject.put("charge_account",wxOrderCreateDTO.getCharge_account());
  324. jsonObject.put("buy_num",wxOrderCreateDTO.getBuy_num());
  325. fuluCommonApiDTO.setBiz_content(jsonObject.toJSONString());
  326. init(fuluDTO,fuluCommonApiDTO);
  327. FuluResult fuluResult = fuluService.fuluCommonApi(fuluDTO);
  328. log.info("福禄下单返回值:"+JSONObject.toJSONString(fuluResult));
  329. //如果返回值不是0 ,则调用退款流程
  330. if (fuluResult.getCode() != 0){
  331. String refundCode = getOrderCode(null);
  332. wxOrder.setOrderStatus(OrderStatusEnum.FAILD.getCode());
  333. wxOrder.setOutRefundNo(refundCode);
  334. try {
  335. refundRecordService.refund(wxOrder,refundCode,"商品购买失败,原因:"+fuluResult.getMessage());
  336. } catch (Exception e) {
  337. throw new CustomException("退款失败");
  338. }
  339. }else {
  340. wxOrder.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
  341. }
  342. //返回成功,则保存返回福禄订单详情到微信订单json传中
  343. WxFuluOrderDetailDTO wxFuluOrderDetailDTO = JSONObject.parseObject(fuluResult.getResult(),WxFuluOrderDetailDTO.class);
  344. wxOrderJsonData.setWxFuluOrderDetailDTO(wxFuluOrderDetailDTO);
  345. wxOrder.setOrderDataJson(JSONObject.toJSONString(wxOrderJsonData));
  346. updateById(wxOrder);
  347. }
  348. });
  349. }
  350. }
  351. @Override
  352. public void createPhoneBillOrder(WxOrder wxOrder, WxOrderCreatePhoneBillDTO wxOrderCreatePhoneBillDTO) {
  353. ActivitiesTmall activitiesTmall= activitiesTmallService.getByTmallNoWithPhoneBill(wxOrderCreatePhoneBillDTO.getTmallNo() );
  354. if (activitiesTmall == null){
  355. throw new CustomException("天猫订单号不存在");
  356. }
  357. if (activitiesTmall.getIsExchange()==1){
  358. throw new CustomException("对不起,该天猫订单号已经充值过");
  359. }
  360. String price = configService.selectConfigByKey("activities_phone_bill");
  361. Double dprice = Double.valueOf(price);
  362. Double v =dprice* 100;
  363. wxOrder.setTotal(v.intValue());
  364. wxOrder.setOrderStatus(OrderStatusEnum.PROCESSING.getCode());
  365. wxOrder.setOrderDataJson(JSONObject.toJSONString(wxOrderCreatePhoneBillDTO));
  366. }
  367. @Override
  368. public void buyPhoneBillOrder(WxOrder wxOrder) {
  369. WxOrderCreatePhoneBillDTO wxOrderCreatePhoneBillDTO=JSONObject.parseObject(wxOrder.getOrderDataJson(),WxOrderCreatePhoneBillDTO.class);;
  370. ActivitiesTmall activitiesTmall= activitiesTmallService.getByTmallNoWithPhoneBill(wxOrderCreatePhoneBillDTO.getTmallNo() );
  371. activitiesTmall.setIsExchange(1);
  372. activitiesTmall.setExchangeTime(new Date());
  373. activitiesTmallService.updateById(activitiesTmall);
  374. // wxOrder.setOrderStatus(OrderStatusEnum.SUCCESS.getCode());
  375. updateById(wxOrder);
  376. }
  377. @Override
  378. public List<WxOrder> selectPcOrderList(PcWxOrderListDTO pcWxOrderListDTO) {
  379. return wxOrderMapper.selectPcOrderList(pcWxOrderListDTO);
  380. }
  381. }