WxService.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. package com.pj.api.wx.service;
  2. import cn.hutool.core.net.URLDecoder;
  3. import cn.hutool.core.util.NumberUtil;
  4. import cn.hutool.core.util.RandomUtil;
  5. import cn.hutool.core.util.StrUtil;
  6. import cn.hutool.core.util.XmlUtil;
  7. import cn.hutool.crypto.SecureUtil;
  8. import cn.hutool.http.HttpUtil;
  9. import cn.hutool.json.JSONObject;
  10. import cn.hutool.json.JSONUtil;
  11. import com.pj.api.wx.WxUtils;
  12. import com.pj.api.wx.bo.*;
  13. import com.pj.api.wx.vo.PrePayVO;
  14. import com.pj.current.config.MyConfig;
  15. import com.pj.current.config.WxConfig;
  16. import com.pj.project.tb_business.TbBusiness;
  17. import com.pj.project.tb_business.TbBusinessService;
  18. import com.pj.project.tb_business_car.TbBusinessCar;
  19. import com.pj.project.tb_business_car.TbBusinessCarService;
  20. import com.pj.project.tb_business_item.TbBusinessItem;
  21. import com.pj.project.tb_business_item.TbBusinessItemService;
  22. import com.pj.project.tb_costomer.TbCostomer;
  23. import com.pj.project.tb_costomer.TbCostomerService;
  24. import com.pj.project.tb_pay_record.TbPayRecord;
  25. import com.pj.project.tb_pay_record.TbPayRecordService;
  26. import com.pj.utils.cache.RedisUtil;
  27. import lombok.extern.slf4j.Slf4j;
  28. import org.springframework.context.annotation.Lazy;
  29. import org.springframework.scheduling.annotation.Async;
  30. import org.springframework.stereotype.Service;
  31. import org.springframework.transaction.annotation.Transactional;
  32. import javax.annotation.Resource;
  33. import javax.servlet.http.HttpServletRequest;
  34. import java.math.BigDecimal;
  35. import java.nio.charset.Charset;
  36. import java.util.*;
  37. import java.util.stream.Collectors;
  38. @Service
  39. @Transactional
  40. @Slf4j
  41. public class WxService {
  42. @Resource
  43. @Lazy
  44. private TbBusinessService tbBusinessService;
  45. @Resource
  46. WxConfig wxConfig;
  47. @Resource
  48. MyConfig myConfig;
  49. @Resource
  50. WxUtils wxUtils;
  51. @Resource
  52. TbPayRecordService tbPayRecordService;
  53. @Resource
  54. TbCostomerService tbCostomerService;
  55. @Resource
  56. TbBusinessCarService tbBusinessCarService;
  57. @Resource
  58. @Lazy
  59. TbBusinessItemService tbBusinessItemService;
  60. /**
  61. * 统一下单接口
  62. */
  63. public Map<String, String> prePay(HttpServletRequest request) throws Exception {
  64. String tradeType = request.getParameter("tradeType");
  65. String money = request.getParameter("money");
  66. String openid = request.getParameter("openid");
  67. String businessId = request.getParameter("b");
  68. String c = request.getParameter("c");
  69. String a = request.getParameter("a");
  70. Attach atchMap = new Attach();
  71. atchMap.setC(c).setB(businessId).setA(a);
  72. String out_trade_no = RandomUtil.randomString(32);
  73. Map<String, String> params = new HashMap<>();
  74. params.put("appid", wxConfig.getAppId());
  75. params.put("mch_id", wxConfig.getMachId());
  76. params.put("openid", openid);
  77. params.put("nonce_str", RandomUtil.randomString(32));
  78. params.put("body", "支付中心-业务订单支付");
  79. params.put("out_trade_no", out_trade_no);
  80. params.put("attach", JSONUtil.toJsonStr(atchMap));
  81. String total_free = NumberUtil.mul(money, 100 + "").intValue() + "";
  82. // String total_free = "1";
  83. log.info("pay free:{}", total_free);
  84. params.put("total_fee", total_free);
  85. // params.put("total_fee", "1");
  86. params.put("spbill_create_ip", getIpAddress(request));
  87. params.put("notify_url", myConfig.getDomain() + "/wx/notify");
  88. params.put("trade_type", tradeType);
  89. params.put("scene_info", SceneInfoBO.getSceneInfo(myConfig.getDomain(), wxConfig.getTitle()));
  90. String sign = wxUtils.sign(params, wxConfig.getKey());
  91. log.info("wx pay sign result:{}", sign);
  92. params.put("sign", sign);
  93. String prePayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
  94. String xmlParam = XmlUtil.mapToXmlStr(params);
  95. log.info("wx pay xml params:{}", xmlParam);
  96. String result = HttpUtil.createPost(prePayUrl).header("Content-Type", "text/xml").body(xmlParam)
  97. .execute().body();
  98. Map<String, Object> resultMap = XmlUtil.xmlToMap(result);
  99. log.info("request pre pay url result:{}", resultMap);
  100. PrePayVO vo = new PrePayVO();
  101. if ("SUCCESS".equals(resultMap.get("return_code")) && "SUCCESS".equals(resultMap.get("result_code"))) {
  102. log.info("生成预支付订单成功,mweb_url:{}", resultMap.get("mweb_url"));
  103. Object webUrl = resultMap.get("mweb_url");
  104. Object prePayId = resultMap.get("prepay_id");
  105. String preId = prePayId == null ? "" : prePayId.toString();
  106. vo.setPayUrl(webUrl == null ? "" : webUrl.toString())
  107. .setPrePayId(preId)
  108. .setTradeType(tradeType);
  109. return getPayParams(openid, preId);
  110. }
  111. throw new Exception("支付信息有误");
  112. }
  113. public Map<String, String> getPayParams(String openid, String prePayId) {
  114. Map<String, String> signMap = new HashMap<>(10);
  115. signMap.put("appId", wxConfig.getAppId());
  116. signMap.put("timeStamp", System.currentTimeMillis() / 1000 + "");
  117. signMap.put("nonceStr", RandomUtil.randomString(32));
  118. signMap.put("signType", "MD5");
  119. signMap.put("package", "prepay_id=" + prePayId);
  120. String sign = wxUtils.sign(signMap, wxConfig.getKey());
  121. signMap.put("paySign", sign);
  122. signMap.put("openId", openid);
  123. return signMap;
  124. }
  125. public static String getIpAddress(HttpServletRequest request) {
  126. String ip = request.getHeader("x-forwarded-for");
  127. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  128. ip = request.getHeader("Proxy-Client-IP");
  129. }
  130. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  131. ip = request.getHeader("WL-Proxy-Client-IP");
  132. }
  133. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  134. ip = request.getRemoteAddr();
  135. }
  136. if (ip.contains(",")) {
  137. return ip.split(",")[0];
  138. } else {
  139. return ip;
  140. }
  141. }
  142. @Async
  143. public void WxNotify(NotifyBO notifyBO) throws Exception {
  144. String total_fee = notifyBO.getTotalFee();
  145. BigDecimal money = new BigDecimal(total_fee).divide(new BigDecimal(100), 2, BigDecimal.ROUND_UP);
  146. log.info("wx pay notify;{}", JSONUtil.toJsonStr(notifyBO));
  147. String tradeNo = notifyBO.getOutTradeNo();
  148. tradeNo = StrUtil.subBefore(tradeNo, "_", true);
  149. String attachStr = notifyBO.getAttach();
  150. String transactionId = notifyBO.getTransactionId();
  151. Date now = new Date();
  152. if (StrUtil.isNotEmpty(attachStr)) {
  153. Attach attach = JSONUtil.toBean(attachStr, Attach.class);
  154. List<PriceBO> cars = JSONUtil.toList(attach.getC(), PriceBO.class);
  155. for (PriceBO bo1 : cars) {
  156. TbBusinessCar car = tbBusinessCarService.getById(bo1.getId());
  157. BigDecimal price = bo1.getP();
  158. car.setPay(1).setMoney(car.getMoney().add(price));
  159. tbBusinessCarService.updateById(car);
  160. TbBusiness business = tbBusinessService.getById(car.getBusinessId());
  161. business.setPayMoney(business.getPayMoney().add(price));
  162. business.setPayStatus(business.getPayMoney().add(price).equals(business.getTotalMoney()) ? 3 : 4);
  163. tbBusinessService.updateById(business);
  164. }
  165. String businessId = attach.getB();
  166. if (StrUtil.isNotEmpty(businessId)) {
  167. List<TbBusinessItem> items = tbBusinessItemService.findByBusinessId(businessId);
  168. items.forEach(tbBusinessItem -> tbBusinessItem.setPayStatus(1).setPayTime(now));
  169. double sum = items.stream().collect(Collectors.summarizingDouble(item -> item.getItemPrice().doubleValue())).getSum();
  170. BigDecimal itemPrice=new BigDecimal(sum);
  171. tbBusinessItemService.updateBatchById(items);
  172. TbBusiness tbBusiness = tbBusinessService.getById(businessId);
  173. tbBusiness.setPayStatus(tbBusiness.getPayMoney().add(itemPrice).equals(tbBusiness.getTotalMoney()) ? 3 : 4);
  174. tbBusiness.setPayTime(now).setPayType(3).setConfirmInput(1).setConfirmInputTime(now)
  175. .setPayMoney(tbBusiness.getPayMoney().add(itemPrice))
  176. .setPayNo(transactionId);
  177. tbBusinessService.updateById(tbBusiness);
  178. TbPayRecord payRecord = new TbPayRecord();
  179. TbCostomer tbCostomer = tbCostomerService.getById(tbBusiness.getCustomerId());
  180. payRecord.setCreateTime(now)
  181. .setOutTradeNo(tradeNo)
  182. .setTransactionId(transactionId)
  183. .setPayMoney(money)
  184. .setCustomerId(tbCostomer.getId()).setCustomerName(tbCostomer.getName());
  185. tbPayRecordService.save(payRecord);
  186. }
  187. }
  188. }
  189. public String getRedirectUrl(String path, String state) {
  190. String redirectUrl = myConfig.getWebDomain() + path;
  191. String encoderUrl = URLDecoder.decode(redirectUrl, Charset.forName("utf-8"));
  192. String url = wxConfig.getAuthLoginUrl().replace("REDIRECT_URI", encoderUrl);
  193. if (StrUtil.isNotEmpty(state)) {
  194. url = url.replace("STATE", state);
  195. }
  196. log.info("get redirect url:{}", url);
  197. return url;
  198. }
  199. public String getOpenidByCode(String code, String openid) {
  200. String openidUrl = wxConfig.getOpenidUrl().replace("CODE", code);
  201. String resp = HttpUtil.get(openidUrl);
  202. JSONObject result = JSONUtil.parseObj(resp);
  203. log.info("get openid result:{}", resp);
  204. String newOpenid = result.getStr("openid");
  205. if (StrUtil.isNotEmpty(newOpenid)) {
  206. return newOpenid;
  207. }
  208. return openid;
  209. }
  210. public SortedMap getWxConfig(String url) {
  211. Long nowTime = System.currentTimeMillis() / 1000;
  212. String jsTicket = RedisUtil.get(wxConfig.getJsApiTicketKey());
  213. SortedMap<String, Object> params = new TreeMap<>();
  214. params.put("noncestr", RandomUtil.randomString(32));
  215. params.put("jsapi_ticket", jsTicket);
  216. params.put("timestamp", nowTime);
  217. params.put("url", url);
  218. String sign = SecureUtil.sha1(params.toString().substring(1, params.toString().lastIndexOf("}")).replaceAll(", ", "&"));
  219. params.put("sign", sign);
  220. params.put("appId", wxConfig.getAppId());
  221. return params;
  222. }
  223. }