|
|
@@ -0,0 +1,378 @@
|
|
|
+package com.izouma.weixin.web;
|
|
|
+
|
|
|
+import com.github.kevinsawicki.http.HttpRequest;
|
|
|
+import com.izouma.awesomeadmin.constant.AppConstant;
|
|
|
+import com.izouma.awesomeadmin.dto.Result;
|
|
|
+import com.izouma.awesomeadmin.model.MemberTicket;
|
|
|
+import com.izouma.awesomeadmin.model.ProductInfo;
|
|
|
+import com.izouma.awesomeadmin.service.MemberTicketService;
|
|
|
+import com.izouma.awesomeadmin.service.ProductInfoService;
|
|
|
+import com.izouma.awesomeadmin.util.DateTimeTool;
|
|
|
+import com.izouma.awesomeadmin.util.MbappUtil;
|
|
|
+import com.izouma.awesomeadmin.util.PropertiesFileLoader;
|
|
|
+import com.izouma.weixin.dao.WxpayTempMapper;
|
|
|
+import com.izouma.weixin.model.WxpayTemp;
|
|
|
+import org.apache.commons.codec.digest.DigestUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.log4j.Logger;
|
|
|
+import org.json.JSONObject;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Controller;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestMethod;
|
|
|
+import org.springframework.web.bind.annotation.RequestParam;
|
|
|
+import org.springframework.web.bind.annotation.ResponseBody;
|
|
|
+import org.springframework.web.servlet.ModelAndView;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import javax.servlet.http.HttpSession;
|
|
|
+import java.io.BufferedOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+@Controller
|
|
|
+@RequestMapping("/apay")
|
|
|
+public class ApayController {
|
|
|
+
|
|
|
+ private static Logger logger = Logger.getLogger(ApayController.class);
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private MemberTicketService memberTicketService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WxpayTempMapper wxpayTempMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ProductInfoService productInfoService;
|
|
|
+
|
|
|
+
|
|
|
+ @RequestMapping(value = "/notify", method = RequestMethod.POST)
|
|
|
+ @ResponseBody
|
|
|
+ public String notify(HttpServletRequest request, HttpServletResponse response) {
|
|
|
+ logger.error("apay:notify");
|
|
|
+ try {
|
|
|
+ Map<String, String> m = notifyMap(request, response);
|
|
|
+ autoCheckPayResult();
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("微信支付回调异常", e);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return "SUCCESS";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 支付结果
|
|
|
+ *
|
|
|
+ * @param m
|
|
|
+ */
|
|
|
+ public void payResultChange(Map<String, String> m) {
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ if (m != null && "00".equals(m.get("returncode"))
|
|
|
+ && !"NOTPAY".equals(m.get("trade_state"))) {//支付成功
|
|
|
+
|
|
|
+ WxpayTemp checkTemp = new WxpayTemp();
|
|
|
+ checkTemp.setOutTradeNo(m.get("orderid"));
|
|
|
+
|
|
|
+
|
|
|
+ checkTemp = wxpayTempMapper.queryWxpayTemp(checkTemp);
|
|
|
+
|
|
|
+ if (checkTemp != null && "NOT_PAY".equals(checkTemp.getResultCode())) {
|
|
|
+
|
|
|
+
|
|
|
+ WxpayTemp wxpayTemp = new WxpayTemp();
|
|
|
+ wxpayTemp.setOutTradeNo(m.get("orderid"));
|
|
|
+ wxpayTemp.setUserId(checkTemp.getUserId());
|
|
|
+ wxpayTemp.setOrderId(checkTemp.getOrderId());
|
|
|
+ wxpayTemp.setCash(checkTemp.getCash());
|
|
|
+ wxpayTemp.setTotalAmount(checkTemp.getTotalAmount());
|
|
|
+ wxpayTemp.setTransactionId(m.get("transaction_id"));
|
|
|
+ wxpayTemp.setResultCode(m.get("trade_state"));
|
|
|
+ wxpayTempMapper.updateByOutTradeNo(wxpayTemp);
|
|
|
+
|
|
|
+ if ("SUCCESS".equals(m.get("trade_state"))) {
|
|
|
+
|
|
|
+ logger.info("buyProductInfo");
|
|
|
+ try {
|
|
|
+ ProductInfo productInfo = productInfoService.getProductInfoById(checkTemp.getOrderId());
|
|
|
+ if (productInfo != null) {
|
|
|
+ if (AppConstant.ProductType.RECHARGE == productInfo.getTypeFlag()) {//如果是充值类型
|
|
|
+
|
|
|
+ MemberTicket memberTicket = new MemberTicket();
|
|
|
+ memberTicket.setMoney(productInfo.getCoin());
|
|
|
+ memberTicket.setUserId(Integer.valueOf(checkTemp.getUserId()));
|
|
|
+ memberTicket.setRemark("购买" + productInfo.getProductName() + "套餐,充值");
|
|
|
+ memberTicket.setRechargeType(AppConstant.RechargeType.APAY);
|
|
|
+
|
|
|
+ memberTicketService.recharge(memberTicket);
|
|
|
+
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //TODO 购买VIP
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("buyProductInfo", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("支付结果转换异常", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @RequestMapping(value = "/unifiedOrder", method = RequestMethod.GET)
|
|
|
+ @ResponseBody
|
|
|
+ public ModelAndView unifiedOrder(@RequestParam(required = true, value = "userId") String userId,
|
|
|
+ @RequestParam(required = true, value = "productId") String productId,
|
|
|
+ @RequestParam(required = true, value = "bankcode") String bankcode) {
|
|
|
+ try {
|
|
|
+
|
|
|
+ double cash = 1;
|
|
|
+
|
|
|
+ ProductInfo productInfo = productInfoService.getProductInfoById(productId);
|
|
|
+
|
|
|
+ cash = productInfo.getMoney().doubleValue();
|
|
|
+
|
|
|
+ int total = 0;
|
|
|
+
|
|
|
+
|
|
|
+ total = (int) (cash * 100);
|
|
|
+
|
|
|
+ //测试为一分
|
|
|
+ total = 1;
|
|
|
+
|
|
|
+ JSONObject attach = new JSONObject();
|
|
|
+ attach.put("productId", productId);
|
|
|
+ attach.put("userId", userId);
|
|
|
+ attach.put("cash", cash);
|
|
|
+ attach.put("total", total);
|
|
|
+
|
|
|
+
|
|
|
+ String out_trade_no = MbappUtil.create_out_trade_no();
|
|
|
+
|
|
|
+
|
|
|
+ Map<String, String> params = new TreeMap<>();
|
|
|
+ params.put("pay_memberid", PropertiesFileLoader.getProperties("apay_memberid")); //商户号
|
|
|
+ params.put("pay_orderid", out_trade_no); //商户系统内部的订单号
|
|
|
+ params.put("pay_applydate", DateTimeTool.dateTimeToTimeMMddHHmmssStr(new Date())); //提交时间
|
|
|
+ params.put("pay_bankcode", bankcode); //银行编码
|
|
|
+ params.put("pay_notifyurl", PropertiesFileLoader.getProperties("apay_return_url")); //接收支付结果异步通知回调地址
|
|
|
+ params.put("pay_callbackurl", PropertiesFileLoader.getProperties("apay_notify_url")); //页面回调地址
|
|
|
+ params.put("pay_amount", String.valueOf(total / 100.0)); //金额 单位元
|
|
|
+
|
|
|
+
|
|
|
+ String signSrc = getSignSrc(params);
|
|
|
+ String sign = DigestUtils.md5Hex(signSrc + "&key=" + PropertiesFileLoader.getProperties("apay_key")).toUpperCase();
|
|
|
+ params.put("pay_md5sign", sign); //签名
|
|
|
+ params.put("pay_productname", productInfo.getProductName()); //商品或支付单简要描述
|
|
|
+ params.put("pay_attach", attach.toString()); //附加数据
|
|
|
+
|
|
|
+ WxpayTemp wxpayTemp = new WxpayTemp();
|
|
|
+ wxpayTemp.setOrderId(productId);
|
|
|
+ wxpayTemp.setUserId(userId);
|
|
|
+ wxpayTemp.setCash(BigDecimal.valueOf(cash));
|
|
|
+ wxpayTemp.setTotalAmount(BigDecimal.valueOf(total / 100.0));
|
|
|
+ wxpayTemp.setOutTradeNo(out_trade_no);
|
|
|
+ wxpayTemp.setTypeFlag(AppConstant.Aliapi.BUY);
|
|
|
+ wxpayTemp.setResultCode("NOT_PAY");
|
|
|
+ wxpayTemp.setCreateUser("apay");
|
|
|
+ wxpayTempMapper.insertSelective(wxpayTemp);
|
|
|
+
|
|
|
+ params.put("AuthorizationURL", PropertiesFileLoader.getProperties("apay_pay_url"));
|
|
|
+ ModelAndView mv = new ModelAndView("jsp/pay.jsp");
|
|
|
+ mv.addAllObjects(params);
|
|
|
+ return mv;
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("apay下单失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @RequestMapping(value = "/orderquery", method = RequestMethod.GET)
|
|
|
+ @ResponseBody
|
|
|
+ public String orderquery(@RequestParam(required = true, value = "pay_orderid") String pay_orderid) {
|
|
|
+ try {
|
|
|
+
|
|
|
+
|
|
|
+ Map<String, String> params = new TreeMap<>();
|
|
|
+ params.put("pay_memberid", PropertiesFileLoader.getProperties("apay_memberid")); //商户号
|
|
|
+ params.put("pay_orderid", pay_orderid); //商户系统内部的订单号
|
|
|
+
|
|
|
+
|
|
|
+ String signSrc = getSignSrc(params);
|
|
|
+ String sign = DigestUtils.md5Hex(signSrc + "&key=" + PropertiesFileLoader.getProperties("apay_key")).toUpperCase();
|
|
|
+ params.put("pay_md5sign", sign); //签名
|
|
|
+
|
|
|
+ String response = HttpRequest.post(PropertiesFileLoader.getProperties("apay_query_url"))
|
|
|
+ .form(params).body();
|
|
|
+
|
|
|
+
|
|
|
+ return response;
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("apay查询订单失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @RequestMapping(value = "/autoCheckPayResult", method = RequestMethod.GET)
|
|
|
+ @ResponseBody
|
|
|
+ public Result autoCheckPayResult() {
|
|
|
+ try {
|
|
|
+
|
|
|
+ WxpayTemp param = new WxpayTemp();
|
|
|
+ param.setCreateUser("apay");
|
|
|
+ param.setResultCode("NOT_PAY");
|
|
|
+ List<WxpayTemp> wxpayTempList = wxpayTempMapper.queryAutoCheckPayWxpayTemp(param);
|
|
|
+
|
|
|
+ for (WxpayTemp wxpayTemp : wxpayTempList) {
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+
|
|
|
+ Map<String, String> params = new TreeMap<>();
|
|
|
+ params.put("pay_memberid", PropertiesFileLoader.getProperties("apay_memberid")); //商户号
|
|
|
+ params.put("pay_orderid", wxpayTemp.getOutTradeNo()); //商户系统内部的订单号
|
|
|
+
|
|
|
+
|
|
|
+ String signSrc = getSignSrc(params);
|
|
|
+ String sign = DigestUtils.md5Hex(signSrc + "&key=" + PropertiesFileLoader.getProperties("apay_key")).toUpperCase();
|
|
|
+ params.put("pay_md5sign", sign); //签名
|
|
|
+
|
|
|
+ String response = HttpRequest.post(PropertiesFileLoader.getProperties("apay_query_url"))
|
|
|
+ .form(params).body();
|
|
|
+
|
|
|
+ JSONObject responseJson = new JSONObject(response);
|
|
|
+
|
|
|
+ if ("NOTPAY".equals(responseJson.getString("trade_state")) && DateTimeTool.dateTimeAddMinutes(wxpayTemp.getCreateTime(), 120).before(new Date())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Map<String, String> notifyMap = new HashMap<>();
|
|
|
+
|
|
|
+ notifyMap.put("memberid", responseJson.getString("memberid"));
|
|
|
+ notifyMap.put("orderid", responseJson.getString("orderid"));
|
|
|
+ notifyMap.put("amount", responseJson.getString("amount"));
|
|
|
+ notifyMap.put("time_end", responseJson.getString("time_end"));
|
|
|
+ notifyMap.put("transaction_id", responseJson.getString("transaction_id"));
|
|
|
+ notifyMap.put("returncode", responseJson.getString("returncode"));
|
|
|
+ notifyMap.put("trade_state", responseJson.getString("trade_state"));
|
|
|
+ notifyMap.put("sign", responseJson.getString("sign"));
|
|
|
+
|
|
|
+
|
|
|
+ payResultChange(notifyMap);
|
|
|
+
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("查询支付结果异常", e);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return new Result(true, "自动检测支付结果成功");
|
|
|
+
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("apay查询订单失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析微信支付回调结果
|
|
|
+ *
|
|
|
+ * @param request
|
|
|
+ * @param response
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public Map<String, String> notifyMap(HttpServletRequest request, HttpServletResponse response) {
|
|
|
+
|
|
|
+ logger.info("payOrder:支付订单");
|
|
|
+ Map<String, String> notifyMap = new HashMap<>();
|
|
|
+ String resXml = "OK";
|
|
|
+ try {
|
|
|
+
|
|
|
+
|
|
|
+ notifyMap.put("memberid", request.getParameter("memberid"));
|
|
|
+ notifyMap.put("orderid", request.getParameter("orderid"));
|
|
|
+ notifyMap.put("amount", request.getParameter("amount"));
|
|
|
+ notifyMap.put("transaction_id", request.getParameter("transaction_id"));
|
|
|
+ notifyMap.put("datetime", request.getParameter("datetime"));
|
|
|
+ notifyMap.put("returncode", request.getParameter("returncode"));
|
|
|
+ notifyMap.put("attach", request.getParameter("attach"));
|
|
|
+ notifyMap.put("sign", request.getParameter("sign"));
|
|
|
+
|
|
|
+ System.out.println("notifyMap:" + notifyMap.toString());
|
|
|
+
|
|
|
+ // 签名正确
|
|
|
+ // 进行处理。
|
|
|
+ // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
|
|
|
+ if ("00".equals(notifyMap.get("returncode"))) {
|
|
|
+ //支付成功
|
|
|
+ resXml = "OK";
|
|
|
+ } else {
|
|
|
+ resXml = "OK";
|
|
|
+ }
|
|
|
+ System.out.println("支付回调数据结束");
|
|
|
+
|
|
|
+ HttpSession seesion = request.getSession();
|
|
|
+ seesion.setAttribute("notify", "支付回调");
|
|
|
+ try {
|
|
|
+ BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
|
|
|
+ out.write(resXml.getBytes());
|
|
|
+ out.flush();
|
|
|
+ out.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ // TODO Auto-generated catch block
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("payOrder:支付订单异常", e);
|
|
|
+ }
|
|
|
+ return notifyMap;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private String getSignSrc(Map<String, ?> paramMap) {
|
|
|
+ StringJoiner signSrc = new StringJoiner("&");
|
|
|
+ paramMap.forEach((key, value) -> {
|
|
|
+ if (!"sign".equals(key) && value != null && StringUtils.isNotBlank(value.toString())) {
|
|
|
+ signSrc.add(key + "=" + value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return signSrc.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|