package com.cyksj.web.controller.payment; import cn.hutool.extra.qrcode.QrCodeUtil; import cn.hutool.extra.qrcode.QrConfig; import com.cyksj.common.EnvCommonService; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.util.IoKit; import com.cyksj.common.util.Xmls; import com.cyksj.config.zfb.BaseZfbConfig; import com.cyksj.config.zfb.ZfbProductCode; import com.cyksj.dto.Result; import com.cyksj.enums.GatewayResponse; import com.cyksj.model.dto.AliPayParams; import com.cyksj.model.dto.H5JsPayParams; import com.cyksj.model.entity.OrderDon; import com.cyksj.model.manage.views.OrderDonView; import com.cyksj.model.request.OrderPayRequest; import com.cyksj.model.response.AliPayTradeStatus; import com.cyksj.service.order.OrderDonService; import com.cyksj.web.util.StpUserUtil; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.SearchResult; import com.ejlchina.searcher.util.MapUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @author chan * @date 2021/10/11 下午3:50 */ @Slf4j @RequestMapping("/applets/order") @RestController public class OrderController { @Autowired private OrderDonService orderDonService; @Resource private BeanSearcher beanSearcher; @Resource private HttpServletRequest request; @Autowired private EnvCommonService envCommonService; /** * 支付 * @author chan * @date 2021-10-11 下午4:56 */ @PostMapping("/post/submit") public Result submit(@Validated @RequestBody OrderPayRequest payRequest) throws Exception { final String methodName = "吊起微信支付"; payRequest.setUserId(StpUserUtil.getLoginIdAsLong()); log.info("{}[start] params:{}",methodName,payRequest); OrderDon orderDon = orderDonService.submit(payRequest); return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon); } /** * 支付 * @author chan * @date 2021-10-11 下午4:56 */ @PostMapping("/post/pay/{orderId}") public Result pay(@PathVariable Long orderId) throws Exception { final String methodName = "吊起微信支付"; log.info("{}[start] orderId:{}",methodName,orderId); H5JsPayParams payParams = orderDonService.pay(orderId, "JSAPI"); return GatewayResponse.SUCCESS.newBuilder().toResult(payParams); } /** * 调用生成订单之后 * 微信网页预下单获取交易链接生成二维码 */ @PostMapping("/get/wx/orderQrCode/{orderId}") public Result createUnifiedOrderQr(@PathVariable Long orderId) throws Exception { //预下单 H5JsPayParams payParams = orderDonService.wxPcWebPay(orderId, "NATIVE"); //获取二维码链接code_url String codeUrl = payParams.getCodeUrl(); QrConfig qrConfig = new QrConfig(300, 300); return GatewayResponse.SUCCESS.newBuilder().toResult(QrCodeUtil.generateAsBase64(codeUrl, qrConfig, "png")); } /** * 微信支付回调 * @author chan * @date 2021-10-11 下午5:42 */ @PostMapping("/prepay/notify") public void prepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { String xml = IoKit.toString(request.getInputStream()); log.info("=== 基金会分发支付成功的回调: \n {}", xml); // 解析xml Map map = Xmls.toMap(xml); // 支付失败 if (!StringUtils.equals("SUCCESS", map.get("return_code")) || !StringUtils.equals("SUCCESS", map.get("result_code"))) { throw BusinessRuntimeException.getInstance("支付失败."); } orderDonService.prepayNotify(map); String toWeChatXmlResponse = ""; OutputStream out = null; try { out = response.getOutputStream(); IoKit.write(toWeChatXmlResponse, out); } catch (Exception e) { throw BusinessRuntimeException.getInstance(e,e.getMessage()); } finally { IoKit.close(out); } } /** * pc端微信支付回调 * @author chan * @date 2021-10-11 下午5:42 */ @PostMapping("/pc/prepay/notify") public void pcPrepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { String xml = IoKit.toString(request.getInputStream()); log.info("=== 微信pc端分发支付成功的回调: \n {}", xml); // 解析xml Map map = Xmls.toMap(xml); // 支付失败 if (!StringUtils.equals("SUCCESS", map.get("return_code")) || !StringUtils.equals("SUCCESS", map.get("result_code"))) { throw BusinessRuntimeException.getInstance("支付失败."); } orderDonService.prepayNotify(map); log.info("pc端微信支付回调修改订单状态成功"); String toWeChatXmlResponse = ""; OutputStream out = null; try { out = response.getOutputStream(); IoKit.write(toWeChatXmlResponse, out); } catch (Exception e) { throw BusinessRuntimeException.getInstance(e,e.getMessage()); } finally { IoKit.close(out); } } /** * 支付宝表单支付 * 支付宝调起支付宝表单 */ @PostMapping("/post/pay/zfb/{orderId}") @Deprecated public void aliPay(@PathVariable Long orderId,HttpServletResponse response) throws Exception { AliPayParams aliPayParams = orderDonService.aliPay(orderId, ZfbProductCode.MOBILE_WEB.getProductCode()); response.setContentType("text/html;charset=" + BaseZfbConfig.charset); //直接将完整的表单html输出到页面 response.getWriter().write(aliPayParams.getBody()); response.getWriter().flush(); response.getWriter().close(); // return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 支付宝web支付 * pc网页二维码 */ @PostMapping("/get/zfb/orderQrCode/{orderId}") public Result zfbWebQrCode(@PathVariable Long orderId, HttpServletResponse response) throws Exception { AliPayParams aliPayParams = orderDonService.aliPay(orderId, ZfbProductCode.PC_WEB.getProductCode()); // response.setContentType("text/html;charset=" + BaseZfbConfig.charset); // //直接将完整的表单html输出到页面 // response.getWriter().write(aliPayParams.getBody()); // response.getWriter().flush(); // response.getWriter().close(); return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody()); } /** * 支付宝回调 */ @PostMapping("/prepay/zfb/notify") public String aliPayNotify(HttpServletRequest request) throws Exception { ////将异步通知中收到的所有参数都存放到map中 Map params = convertRequestParamsToMap(request); String tradeStatus = params.get("trade_status"); if (AliPayTradeStatus.TRADE_SUCCESS.getStatus().equals(tradeStatus) || AliPayTradeStatus.TRADE_FINISHED.getStatus().equals(tradeStatus)) { orderDonService.aliPayNotify(params); } else { log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, params.get("out_trade_no")); return "fail"; } return "success"; } /** * 获取订单列表 */ @GetMapping("/get") public Result> list(){ long userId = StpUserUtil.getLoginIdAsLong(); SearchResult search = beanSearcher.search(OrderDonView.class, MapUtils.flatBuilder(request.getParameterMap()) .field(OrderDonView::getUserId,userId) .orderBy(OrderDonView::getId).desc() .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * 获取订单列表 */ @GetMapping("/get/{orderId}") public Result list(@PathVariable Long orderId){ long userId = StpUserUtil.getLoginIdAsLong(); OrderDonView detail = orderDonService.getDetail(orderId,userId); return GatewayResponse.SUCCESS.newBuilder().toResult(detail); } /** * 取消订单 */ @GetMapping("/get/close/{orderId}") public Result closeOrder(@PathVariable Long orderId){ orderDonService.closeOrder(orderId); return GatewayResponse.SUCCESS.newBuilder().toResult(); } @GetMapping("/get/order/status/{orderId}") public Result getOrderStatusById(@PathVariable Long orderId) { if (orderId < 1) { throw BusinessRuntimeException.getInstance("订单不存在"); } OrderDon orderDon = orderDonService.getById(orderId); if (orderDon == null) { throw BusinessRuntimeException.getInstance("订单不存在"); } return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon); } /** * 获取支付宝回调参数 */ private static Map convertRequestParamsToMap(HttpServletRequest request) { Map retMap = new HashMap<>(); Set> entrySet = request.getParameterMap().entrySet(); for (Map.Entry entry : entrySet) { String name = entry.getKey(); String[] values = entry.getValue(); int valLen = values.length; if (valLen == 1) { retMap.put(name, values[0]); } else if (valLen > 1) { StringBuilder sb = new StringBuilder(); for (String val : values) { sb.append(",").append(val); } retMap.put(name, sb.substring(1)); } else { retMap.put(name, ""); } } return retMap; } }