微信支付超詳細教程(附商城訂單處理邏輯)

1、項目目錄結構
在這裏插入圖片描述
2、在pom.xml中引入相關依賴

<dependencies>
    <!--微信支付相關依賴-->
    <dependency>
        <groupId>com.github.wxpay</groupId>
        <artifactId>wxpay-sdk</artifactId>
        <version>0.0.3</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
    </dependency>
    
	//httpclient相關依賴
    <!--httpclient-->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
    </dependency>
    <!--commons-io-->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
    </dependency>
    <!--gson-->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
    </dependency>
</dependencies>

3、PayInfoController

@RestController
@RequestMapping("/mallservice/payInfo")
@CrossOrigin(allowCredentials = "true", allowedHeaders = "*")
@Slf4j
public class PayInfoController {
    @Autowired
    private PayInfoService payInfoService;

    /*生成微信支付二維碼接口*/
    @GetMapping("/createPayCode/{orderId}")
    public R createPayCode(@PathVariable String orderId) {
        Map map = this.payInfoService.createPayCode(orderId);
        log.info("生成二維碼" + map.toString());
        return R.ok().data(map);
    }

    //檢查訂單狀態

    @GetMapping(value = "/queryPayStatus/{orderId}")
    public R queryPayStatus(@PathVariable String orderId) {
        Map<String, String> map = this.payInfoService.queryPayStatus(orderId);
        if (map == null) {
            return R.error().message("支付出錯");
        }

        if (map.get("trade_state").equals("SUCCESS")) {
            log.info("檢查訂單狀態" + map.get("trade_state"));
            //更新訂單狀態
            //更改訂單狀態
            payInfoService.updateOrderStatus(map);
            return R.ok().message("支付成功");

        }
        //前端響應過濾器 25000被攔截
        return R.ok().code(25000).message("支付中。。。。。");
    }

}

4、PayInfoServiceImpl

@Service
@Slf4j
public class PayInfoServiceImpl extends ServiceImpl<PayInfoMapper, PayInfo> implements PayInfoService {

    @Autowired
    private OrderService orderService;
    /*生成微信支付二維碼*/
    @Override
    public Map createPayCode(String orderId) {
        try {
            //根據訂單id獲取訂單信息
            QueryWrapper<Order> wrapper = new QueryWrapper<>();
            wrapper.eq("id", orderId);
            Order order = orderService.getOne(wrapper);

            Map m = new HashMap();
            //1、設置支付參數
            m.put("appid", "wx74862e954");
            m.put("mch_id", "15591"); //商戶號
            m.put("nonce_str", WXPayUtil.generateNonceStr());
            m.put("body", orderId);   //.......
            m.put("out_trade_no", orderId);
            m.put("total_fee", order.getPaymentPrice().multiply(new BigDecimal("100")).longValue() + "");
            m.put("spbill_create_ip", "127.0.0.1");
            m.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify"); //回調地址
            m.put("trade_type", "NATIVE");

            //2、HTTPClient來根據URL訪問第三方接口並且傳遞參數
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");

            //client設置參數
            client.setXmlParam(WXPayUtil.generateSignedXml(m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
            client.setHttps(true);  //允許https請求
            client.post();
            //3、返回第三方的數據
            String xml = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
            //4、封裝返回結果集

            Map map = new HashMap<>();
            map.put("out_trade_no", orderId);
            map.put("user_id", order.getUserId());
            map.put("total_fee", order.getPaymentPrice());
            map.put("result_code", resultMap.get("result_code"));  //返回二維碼操作狀態碼
            map.put("code_url", resultMap.get("code_url"));    //二維碼地址

            //微信支付二維碼2小時過期,可採取2小時未支付取消訂單
            //redisTemplate.opsForValue().set(orderNo, map, 120, TimeUnit.MINUTES);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            return new HashMap<>();
        }

    }

    //查詢訂單狀態
    @Override
    public Map queryPayStatus(String orderId) {
        try {
            //1、封裝參數
            Map m = new HashMap<>();
            m.put("appid", "wx74862e0dfc4");
            m.put("mch_id", "150191");
            m.put("out_trade_no", orderId);
            m.put("nonce_str", WXPayUtil.generateNonceStr());

            //2、設置請求
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            client.setXmlParam(WXPayUtil.generateSignedXml(m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
            client.setHttps(true);
            client.post();
            //3、返回第三方的數據
            String xml = client.getContent();
            //4、轉成Map並返回
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
            return resultMap;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    /*支付成功向支付表中添加記錄,同時更新訂單表中的支付狀態等信息*/
    @Override
    public void updateOrderStatus(Map<String, String> map) {
        log.info("修改訂單狀態" + "開始");
        //獲取訂單id
        String orderId = map.get("out_trade_no");
        //根據訂單id查詢訂單信息
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("id", orderId);
        Order order = orderService.getOne(wrapper);

        if (order.getStatus().intValue() == 1) return;
        order.setStatus(CONSTANT.ORDER_SATAUS.HAS_PAIED);
        order.setPaymentTime(new Date());
        order.setPaymentType(1);
        orderService.updateById(order);

        //記錄支付日誌
        PayInfo payInfo = new PayInfo();
        payInfo.setOrderId(order.getId());//支付訂單號
        payInfo.setPlatformStatus(CONSTANT.PLATFORM_STATUS.TRADE_SUCCESS);
        payInfo.setPayPlatform(1);//支付類型
        payInfo.setOrderId(order.getId());
        payInfo.setUserId(map.get("user_id"));

        payInfo.setTransactionId(map.get("transaction_id"));
//        payLog.setAttr(JSONObject.toJSONString(map));
        baseMapper.insert(payInfo);//插入到支付日誌表
        log.info("修改訂單狀態" + "完成");
    }

}

前端顯示支付二維碼:
(1)引入生成二維碼的js
在這裏插入圖片描述
(2)在HTML部分綁定一個id名爲QRCode的div
在這裏插入圖片描述
(3)在js中請求生成二維碼接口

				/*測試生成微信支付二維碼*/
            getCode(){
                CSU.http.get("/mallservice/payInfo/createPayCode/1492089528889").then(res => {
                    this.payObj = res.data.data;
                new QRCode("QRCode", {
                    text: this.payObj.code_url,
                    width: 128,
                    height: 128,
                    colorDark : "#000000",
                    colorLight : "#ffffff",
                    correctLevel : QRCode.CorrectLevel.H
                });
            })
            }

(4)使用定時器定時查詢訂單狀態
// 開啓定時任務,查詢付款狀態

          const taskId = setInterval(() => {
                 CSU.http.get("/mallservice/payInfo/queryPayStatus/" + this.orderId)
                 .then(res => {
                  if(res.data.code == 20000){
                 // 付款成功
                 clearInterval(taskId);
                 alert("支付成功")
                 // 跳轉到付款成功頁
                 location.href = "/paysuccess.html?orderId=" + this.orderId;
 			}   else if(res.data.code != 25000){  //code=25000說明正在支付中
                 // 付款失敗
                 clearInterval(taskId);
                 alert("支付失敗")
                 // 跳轉到付款成功頁
                 location.href = "/payfail.html?orderId=" + this.orderId;
 			}

         })
         }, 3000);
        },

(5)完整js代碼

<script type="text/javascript">
        var payVm = new Vue({
            el: "#payApp",
            data: {
                CSU: CSU,
                orderId: "1492091083720",
                payObj: {}
            },
            created() {
                // ly.verify().then(res=>{
                //     //已經登錄
                //     this.orderId = ly.getUrlParam("orderId");
                //     this.shouldPay = ly.getUrlParam("shouldPay");

                /*測試生成微信支付二維碼*/
                CSU.http.get("/mallservice/payInfo/createPayCode/1492091083720").then(res => {
                    this.payObj = res.data.data;
                new QRCode("QRCode", {
                    text: this.payObj.code_url,
                    width: 128,
                    height: 128,
                    colorDark: "#000000",
                    colorLight: "#ffffff",
                    correctLevel: QRCode.CorrectLevel.H
                });
            });

                // 開啓定時任務,查詢付款狀態
                const taskId = setInterval(() => {
                    CSU.http.get("/mallservice/payInfo/queryPayStatus/" + this.orderId)
                    .then(res => {
                     if(res.data.code == 20000){
                    // 付款成功
                    clearInterval(taskId);
                    alert("支付成功")
                    // 跳轉到付款成功頁
                    location.href = "/paysuccess.html?orderId=" + this.orderId;
				}   else if(res.data.code != 25000){  //code=25000說明正在支付中
                    // 付款失敗
                    clearInterval(taskId);
                    alert("支付失敗")
                    // 跳轉到付款成功頁
                    location.href = "/payfail.html?orderId=" + this.orderId;
				}
            })
            }, 3000);
           },
        })
        </script>

附訂單處理業務流程:

1、OrderController

@RestController
@RequestMapping("/mallservice/order")
@CrossOrigin
@Api("訂單服務接口")
public class OrderController {
    @Autowired
    private OrderService orderService;
//    @Autowired
//    private PayHelper payHelper;
    /**
     * 創建訂單
     *
     */
    @PostMapping("/createOrder")
    @ApiOperation(value = "創建訂單接口,返回訂單編號", notes = "創建訂單")
    public R createOrder(@RequestBody Order order, HttpSession session) {
        User user = (User)session.getAttribute(CONSTANT.LOGIN_USER);
        String id = this.orderService.createOrder(order,user);
        return R.ok().data("orderId",id).message("創建訂單成功");
    }

    /**
     * 根據訂單編號查詢訂單
     *
     */
    @GetMapping("selectOrderById/{orderId}")
    @ApiOperation(value = "根據訂單編號查詢訂單,返回訂單對象", notes = "查詢訂單")
    public R selectOrderById(@PathVariable("orderId") String orderId) {
        Order order = this.orderService.queryById(orderId);
        if (order == null) {
            return R.error().message("訂單號不存在");
        }
        return R.ok().data("order",order);
    }

    /**
     * 分頁查詢當前用戶訂單
     */
    @GetMapping("list")
    @ApiOperation(value = "分頁查詢當前用戶訂單,並且可以根據訂單狀態過濾", notes = "分頁查詢當前用戶訂單")
    public R queryUserOrderList(
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "limit", defaultValue = "5") Integer limit,
            @RequestParam(value = "status", required = false,defaultValue = "2") Integer status) {
        Map<String,Object> map = this.orderService.queryUserOrderList(page, limit, status);
        if(CollectionUtils.isEmpty(map)){
            return R.error().message("查詢用戶訂單失敗");
        }

        return R.ok().data("total",map.get("total")).data("orders",map.get("rows"));
    }

    /**
     * 更新訂單狀態
     *
     * @param id
     * @param status
     * @return
     */
    @PutMapping("/updateOrderStatus/{id}/{status}")
    @ApiOperation(value = "更新訂單狀態", notes = "更新訂單狀態")

    public R updateStatus(@PathVariable("id") Long id, @PathVariable("status") Integer status) {
        this.orderService.updateStatus(id, status);

        return R.ok();
    }
}

OrderServiceImpl

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private ShippingService shippingService;
    @Autowired
    private OrderItemService orderItemService;

    //創建訂單
    @Override
    public String createOrder(Order order, User user) {

        if(order == null){
            throw new XmallException(20001,"創建訂單失敗");
        }
        if(user == null){
            throw new XmallException(20001,"用戶未登錄");
        }

        //創建訂單編號
        String orderId = UUID.randomUUID().toString();
        order.setId(orderId);

        order.setUserId(user.getId());
        order.setStatus(CONSTANT.ORDER_SATAUS.NOT_PAY);

        //根據用戶查詢收貨地址
        QueryWrapper<Shipping> wrapper = new QueryWrapper<>();
        wrapper.eq("id",user.getId());
        Shipping shipping = shippingService.getOne(wrapper);
        order.setShippingId(shipping.getId());

        //設置支付類型
        order.setPaymentType(CONSTANT.PAYMENT_TYPE.ONLINE);
//        //設置訂單條目
//        order.setOrderItems();

        //插入訂單表
        int insert = baseMapper.insert(order);
        if(insert ==0 ){
            throw new XmallException(20001,"創建訂單失敗");
        }

        //order_item表中插入訂單id(批量更新)
        order.getOrderItems().forEach(orderItem -> {
            orderItem.setOrderId(orderId);
        });
        orderItemService.saveBatch(order.getOrderItems());

        return orderId;
    }

    //根據訂單編號查詢訂單
    @Override
    public Order queryById(String id) {
        if(StringUtils.isBlank(id)){
            throw new XmallException(20001,"訂單號有誤");
        }
        Order order = baseMapper.selectById(id);

        QueryWrapper<OrderItem> wrapper = new QueryWrapper<>();
        wrapper.eq("order_id",order.getId());
        List<OrderItem> orderItemList = orderItemService.list(wrapper);

        order.setOrderItems(orderItemList);

        return order;
    }

    //分頁查詢當前用戶訂單
    @Override
    public Map<String,Object> queryUserOrderList(Integer page, Integer limit, Integer status) {
        Page<Order> pageInfo = new Page<>(page,limit);
        /*構造查詢條件*/
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        if(status != 2){
            wrapper.eq("status",status);
        }else {
            wrapper = null;
        }

        baseMapper.selectPage(pageInfo,wrapper);

        List<Order> records = pageInfo.getRecords();
        long total = pageInfo.getTotal();
        Map<String,Object> map = new HashMap<>();
        map.put("total",total);
        map.put("rows",records);

        return map;
    }

    //更新訂單狀態
     @Transactional
        public void updateStatus(Long id, Integer status) {
         Order order = baseMapper.selectById(id);
         order.setStatus(status);

         // 根據狀態判斷要修改的時間
            switch (status) {
                case 20:
                    order.setPaymentTime(new Date());// 付款
                    break;
                case 30:
                    order.setSendTime(new Date());// 發貨
                    break;
                case 40:
                    order.setEndTime(new Date());// 確認收穫,訂單結束
                    break;
                case 50:
                    order.setCloseTime(new Date());// 交易失敗,訂單關閉
                    break;
            }
            int count = baseMapper.updateById(order);
            if(count == 0 ){
                throw new XmallException(20001,"更新訂單狀態失敗");
            }

        }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章