• 230920_整合微信支付宝支付


    1. 支付中心表结构

    1.1 订单表orders

    表结构
    在这里插入图片描述
    sql脚本

    /*
     Navicat Premium Data Transfer
    
     Source Server         : 1本地数据
     Source Server Type    : MySQL
     Source Server Version : 80029
     Source Host           : localhost:3306
     Source Schema         : foodie-shop-dev
    
     Target Server Type    : MySQL
     Target Server Version : 80029
     File Encoding         : 65001
    
     Date: 20/09/2023 20:21:05
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for orders
    -- ----------------------------
    DROP TABLE IF EXISTS `orders`;
    CREATE TABLE `orders`  (
      `id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '订单主键',
      `merchant_order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商户订单号',
      `merchant_user_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商户方的发起用户的用户主键id',
      `amount` int(0) NOT NULL COMMENT '实际支付总金额(包含商户所支付的订单费邮费总额)',
      `pay_method` int(0) NOT NULL COMMENT '支付方式',
      `pay_status` int(0) NOT NULL COMMENT '支付状态 10:未支付 20:已支付 30:支付失败 40:已退款',
      `come_from` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '从哪一端来的,比如从天天吃货这门实战过来的',
      `return_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '支付成功后的通知地址,这个是开发者那一段的,不是第三方支付通知的地址',
      `is_delete` int(0) NOT NULL COMMENT '逻辑删除状态;1: 删除 0:未删除',
      `created_time` datetime(0) NOT NULL COMMENT '创建时间(成交时间)',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '订单表;' ROW_FORMAT = Dynamic;
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    oredrs实体类

    package com.imooc.pojo;
    import java.util.Date;
    
    @Data
    public class Orders {
        /**
         * 订单主键
         */
        private String id;
    
        /**
         * 商户订单号
         */
        private String merchantOrderId;
    
        /**
         * 商户方的发起用户的用户主键id
         */
        private String merchantUserId;
    
        /**
         * 实际支付总金额(包含商户所支付的订单费邮费总额)
         */
        private Integer amount;
    
        /**
         * 支付方式
         */
        private Integer payMethod;
    
        /**
         * 支付状态 10:未支付 20:已支付 30:支付失败 40:已退款
         */
        private Integer payStatus;
    
        /**
         * 从哪一端来的,比如从天天吃货这门实战过来的
         */
        private String comeFrom;
    
        /**
         * 支付成功后的通知地址,这个是开发者那一段的,不是第三方支付通知的地址
         */
        private String returnUrl;
    
        /**
         * 逻辑删除状态;1: 删除 0:未删除
         */
        private Integer isDelete;
    
        /**
         * 创建时间(成交时间)
         */
        private Date createdTime;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    1.2 订单状态表order_status

    在这里插入图片描述
    sql脚本

    /*
     Navicat Premium Data Transfer
    
     Source Server         : 1本地数据
     Source Server Type    : MySQL
     Source Server Version : 80029
     Source Host           : localhost:3306
     Source Schema         : foodie-shop-dev
    
     Target Server Type    : MySQL
     Target Server Version : 80029
     File Encoding         : 65001
    
     Date: 20/09/2023 20:27:05
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for order_status
    -- ----------------------------
    DROP TABLE IF EXISTS `order_status`;
    CREATE TABLE `order_status`  (
      `order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '订单ID;对应订单表的主键id',
      `order_status` int(0) NOT NULL COMMENT '订单状态',
      `created_time` datetime(0) NULL DEFAULT NULL COMMENT '订单创建时间;对应[10:待付款]状态',
      `pay_time` datetime(0) NULL DEFAULT NULL COMMENT '支付成功时间;对应[20:已付款,待发货]状态',
      `deliver_time` datetime(0) NULL DEFAULT NULL COMMENT '发货时间;对应[30:已发货,待收货]状态',
      `success_time` datetime(0) NULL DEFAULT NULL COMMENT '交易成功时间;对应[40:交易成功]状态',
      `close_time` datetime(0) NULL DEFAULT NULL COMMENT '交易关闭时间;对应[50:交易关闭]状态',
      `comment_time` datetime(0) NULL DEFAULT NULL COMMENT '留言时间;用户在交易成功后的留言时间',
      PRIMARY KEY (`order_id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '订单状态表;订单的每个状态更改都需要进行记录\n10:待付款  20:已付款,待发货  30:已发货,待收货(7天自动确认)  40:交易成功(此时可以评价)50:交易关闭(待付款时,用户取消 或 长时间未付款,系统识别后自动关闭)\n退货/退货,此分支流程不做,所以不加入' ROW_FORMAT = Dynamic;
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    OrderStatus实体类

    package com.imooc.pojo;
    
    import java.util.Date;
    
    @Data
    public class OrderStatus {
        /**
         * 订单ID;对应订单表的主键id
         */
        private String orderId;
    
        /**
         * 订单状态
         */
        private Integer orderStatus;
    
        /**
         * 订单创建时间;对应[10:待付款]状态
         */
        private Date createdTime;
    
        /**
         * 支付成功时间;对应[20:已付款,待发货]状态
         */
        private Date payTime;
    
        /**
         * 发货时间;对应[30:已发货,待收货]状态
         */
        private Date deliverTime;
    
        /**
         * 交易成功时间;对应[40:交易成功]状态
         */
        private Date successTime;
    
        /**
         * 交易关闭时间;对应[50:交易关闭]状态
         */
        private Date closeTime;
    
        /**
         * 留言时间;用户在交易成功后的留言时间
         */
        private Date commentTime;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    1.3 订单商品关联表 OrderItems

    在这里插入图片描述

    package com.imooc.pojo;
    
    /**
     * 订单商品关联表
     */
    public class OrderItems {
        /**
         * 主键id
         */
        private String id;
    
        /**
         * 归属订单id
         */
        private String orderId;
    
        /**
         * 商品id
         */
        private String itemId;
    
        /**
         * 商品图片
         */
        private String itemImg;
    
        /**
         * 商品名称
         */
        private String itemName;
    
        /**
         * 规格id
         */
        private String itemSpecId;
    
        /**
         * 规格名称
         */
        private String itemSpecName;
    
        /**
         * 成交价格
         */
        private Integer price;
    
        /**
         * 购买数量
         */
        private Integer buyCounts;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    sql脚本

    /*
     Navicat Premium Data Transfer
    
     Source Server         : 1本地数据
     Source Server Type    : MySQL
     Source Server Version : 80029
     Source Host           : localhost:3306
     Source Schema         : foodie-shop-dev
    
     Target Server Type    : MySQL
     Target Server Version : 80029
     File Encoding         : 65001
    
     Date: 20/09/2023 20:56:56
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for order_items
    -- ----------------------------
    DROP TABLE IF EXISTS `order_items`;
    CREATE TABLE `order_items`  (
      `id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键id',
      `order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '归属订单id',
      `item_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品id',
      `item_img` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品图片',
      `item_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '商品名称',
      `item_spec_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '规格id',
      `item_spec_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '规格名称',
      `price` int(0) NOT NULL COMMENT '成交价格',
      `buy_counts` int(0) NOT NULL COMMENT '购买数量',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '订单商品关联表 ' ROW_FORMAT = Dynamic;
    
    SET FOREIGN_KEY_CHECKS = 1;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2. 微信支付时序图

    2.1 参考文档

    2.2 二维码支付时序图

    在这里插入图片描述

    3. 时序图1=>生成订单环节

    3.1 用户下单

    1.电商平台保存订单信息=>2.订单信息发送到支付中心

    3.1.1 电商平台

    web接口

        @ApiOperation(value = "用户下单", notes = "用户下单", httpMethod = "POST")
        @PostMapping("/create")
        public IMOOCJSONResult create(
                @RequestBody SubmitOrderBO submitOrderBO,
                HttpServletRequest request,
                HttpServletResponse response) {
                
            if (submitOrderBO.getPayMethod() != PayMethod.WEIXIN.type
                && submitOrderBO.getPayMethod() != PayMethod.ALIPAY.type ) {
                return IMOOCJSONResult.errorMsg("支付方式不支持!");
            }
            
            // 1. 创建订单
            OrderVO orderVO = orderService.createOrder(submitOrderBO);
            String orderId = orderVO.getOrderId();
    
            // 2. 创建订单以后,移除购物车中已结算(已提交)的商品
            /**
             * 1001
             * 2002 -> 用户购买
             * 3003 -> 用户购买
             * 4004
             */
            // TODO 整合redis之后,完善购物车中的已结算商品清除,并且同步到前端的cookie
    //        CookieUtils.setCookie(request, response, FOODIE_SHOPCART, "", true);
    
            // 3. 向支付中心发送当前订单,用于保存支付中心的订单数据
            MerchantOrdersVO merchantOrdersVO = orderVO.getMerchantOrdersVO();
            merchantOrdersVO.setReturnUrl(payReturnUrl);
    
            // 为了方便测试购买,所以所有的支付金额都统一改为1分钱
            merchantOrdersVO.setAmount(1);
    
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.add("imoocUserId","imooc");
            headers.add("password","imooc");
    
            HttpEntity<MerchantOrdersVO> entity =
                    new HttpEntity<>(merchantOrdersVO, headers);
    
            ResponseEntity<IMOOCJSONResult> responseEntity =
                    restTemplate.postForEntity(paymentUrl,
                                                entity,
                                                IMOOCJSONResult.class);
            IMOOCJSONResult paymentResult = responseEntity.getBody();
            if (paymentResult.getStatus() != 200) {
                logger.error("发送错误:{}", paymentResult.getMsg());
                return IMOOCJSONResult.errorMsg("支付中心订单创建失败,请联系管理员!");
            }
    
            return IMOOCJSONResult.ok(orderId);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    业务层=>创建订单

        /**
         * 新增订单信息
         * 1. 新增订单信息
         * => 2. 新增订单状态信息 
         * => 3. 构建商户订单 用于传给支付中心
         * @param submitOrderBO
         * @return
         */
        @Transactional(propagation = Propagation.REQUIRED)
        @Override
        public OrderVO createOrder(SubmitOrderBO submitOrderBO) {
    
            String userId = submitOrderBO.getUserId();
            String addressId = submitOrderBO.getAddressId();
            String itemSpecIds = submitOrderBO.getItemSpecIds();
            Integer payMethod = submitOrderBO.getPayMethod();
            String leftMsg = submitOrderBO.getLeftMsg();
            // 包邮费用设置为0
            Integer postAmount = 0;
    
            String orderId = sid.nextShort();
    
            UserAddress address = addressService.queryUserAddres(userId, addressId);
    
            // 1. 新订单数据保存
            Orders newOrder = new Orders();
            newOrder.setId(orderId);
            newOrder.setUserId(userId);
            //收货信息
            newOrder.setReceiverName(address.getReceiver());
            newOrder.setReceiverMobile(address.getMobile());
            newOrder.setReceiverAddress(address.getProvince() + " "
                                        + address.getCity() + " "
                                        + address.getDistrict() + " "
                                        + address.getDetail());
    
    //        newOrder.setTotalAmount();
    //        newOrder.setRealPayAmount();
            newOrder.setPostAmount(postAmount);
    
            newOrder.setPayMethod(payMethod);
            newOrder.setLeftMsg(leftMsg);
    
            newOrder.setIsComment(YesOrNo.NO.type);
            newOrder.setIsDelete(YesOrNo.NO.type);
            newOrder.setCreatedTime(new Date());
            newOrder.setUpdatedTime(new Date());
    
    
            // 2. 循环根据itemSpecIds保存订单商品信息表
            String itemSpecIdArr[] = itemSpecIds.split(",");
            Integer totalAmount = 0;    // 商品原价累计
            Integer realPayAmount = 0;  // 优惠后的实际支付价格累计
            for (String itemSpecId : itemSpecIdArr) {
    
                // TODO 整合redis后,商品购买的数量重新从redis的购物车中获取
                int buyCounts = 1;
    
                // 2.1 根据规格id,查询规格的具体信息,主要获取价格
                ItemsSpec itemSpec = itemService.queryItemSpecById(itemSpecId);
                totalAmount += itemSpec.getPriceNormal() * buyCounts;
                realPayAmount += itemSpec.getPriceDiscount() * buyCounts;
    
                // 2.2 根据商品id,获得商品信息以及商品图片
                String itemId = itemSpec.getItemId();
                Items item = itemService.queryItemById(itemId);
                String imgUrl = itemService.queryItemMainImgById(itemId);
    
                // 2.3 循环保存子订单数据到数据库
                String subOrderId = sid.nextShort();
                OrderItems subOrderItem = new OrderItems();
                subOrderItem.setId(subOrderId);
                subOrderItem.setOrderId(orderId);
                subOrderItem.setItemId(itemId);
                subOrderItem.setItemName(item.getItemName());
                subOrderItem.setItemImg(imgUrl);
                subOrderItem.setBuyCounts(buyCounts);
                subOrderItem.setItemSpecId(itemSpecId);
                subOrderItem.setItemSpecName(itemSpec.getName());
                subOrderItem.setPrice(itemSpec.getPriceDiscount());
                orderItemsMapper.insert(subOrderItem);
    
                // 2.4 在用户提交订单以后,规格表中需要扣除库存
                itemService.decreaseItemSpecStock(itemSpecId, buyCounts);
            }
    
            newOrder.setTotalAmount(totalAmount);
            newOrder.setRealPayAmount(realPayAmount);
            ordersMapper.insert(newOrder);
    
            // 3. 保存订单状态表
            OrderStatus waitPayOrderStatus = new OrderStatus();
            waitPayOrderStatus.setOrderId(orderId);
            waitPayOrderStatus.setOrderStatus(OrderStatusEnum.WAIT_PAY.type);
            waitPayOrderStatus.setCreatedTime(new Date());
            orderStatusMapper.insert(waitPayOrderStatus);
    
            // 4. 构建商户订单,用于传给支付中心
            MerchantOrdersVO merchantOrdersVO = new MerchantOrdersVO();
            merchantOrdersVO.setMerchantOrderId(orderId);
            merchantOrdersVO.setMerchantUserId(userId);
            merchantOrdersVO.setAmount(realPayAmount + postAmount);
            merchantOrdersVO.setPayMethod(payMethod);
    
            // 5. 构建自定义订单vo
            OrderVO orderVO = new OrderVO();
            orderVO.setOrderId(orderId);
            orderVO.setMerchantOrdersVO(merchantOrdersVO);
    
            return orderVO;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111

    其他:1 整合RestTemplate

    package com.imooc.config;
    
    import org.springframework.boot.web.client.RestTemplateBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        // 实现静态资源的映射
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/**")
                    .addResourceLocations("classpath:/META-INF/resources/")  // 映射swagger2
                    .addResourceLocations("file:/workspaces/images/");  // 映射本地静态资源
        }
    
        @Bean
        public RestTemplate restTemplate(RestTemplateBuilder builder) {
            return builder.build();
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    其他2: OrderVO订单信息

    package com.imooc.pojo.vo;
    
    public class OrderVO {
    
        private String orderId;
        private MerchantOrdersVO merchantOrdersVO;
    
        public String getOrderId() {
            return orderId;
        }
    
        public void setOrderId(String orderId) {
            this.orderId = orderId;
        }
    
        public MerchantOrdersVO getMerchantOrdersVO() {
            return merchantOrdersVO;
        }
    
        public void setMerchantOrdersVO(MerchantOrdersVO merchantOrdersVO) {
            this.merchantOrdersVO = merchantOrdersVO;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    其他3: MerchantOrdersVO对象
    传递到支付中心的视图vo对象

    package com.imooc.pojo.vo;
    
    @Data
    public class MerchantOrdersVO {
        private String merchantOrderId;         // 商户订单号
        private String merchantUserId;          // 商户方的发起用户的用户主键id
        private Integer amount;                 // 实际支付总金额(包含商户所支付的订单费邮费总额)
        private Integer payMethod;              // 支付方式 1:微信   2:支付宝
        private String returnUrl;               // 支付成功后的回调地址(学生自定义)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.1.2 支付平台

    接受电商平台订单信息,保存到数据库中
    web接口

    	/**
    	 * 接受商户订单信息,保存到自己的数据库
    	 * @param merchantOrdersBO 商户订单信息
    	 * @param request
    	 * @param response
    	 * @return
    	 * @throws Exception
    	 */
    	@PostMapping("/createMerchantOrder")
    	public IMOOCJSONResult createMerchantOrder(@RequestBody MerchantOrdersBO merchantOrdersBO, HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    		String merchantOrderId = merchantOrdersBO.getMerchantOrderId();             	// 订单id
    		String merchantUserId = merchantOrdersBO.getMerchantUserId();     		// 用户id
    		Integer amount = merchantOrdersBO.getAmount();    // 实际支付订单金额
    		Integer payMethod = merchantOrdersBO.getPayMethod();          	// 支付方式
    		String returnUrl = merchantOrdersBO.getReturnUrl();           	// 支付成功后的回调地址(学生自定义)
    
    		if (StringUtils.isBlank(merchantOrderId)) {
    			return IMOOCJSONResult.errorMsg("参数[orderId]不能为空");
    		}
    		if (StringUtils.isBlank(merchantUserId)) {
    			return IMOOCJSONResult.errorMsg("参数[userId]不能为空");
    		}
    		if (amount == null || amount < 1) {
    			return IMOOCJSONResult.errorMsg("参数[realPayAmount]不能为空并且不能小于1");
    		}
    		if (payMethod == null) {
    			return IMOOCJSONResult.errorMsg("参数[payMethod]不能为空并且不能小于1");
    		}
    		if (payMethod != PayMethod.WEIXIN.type && payMethod != PayMethod.ALIPAY.type) {
    			return IMOOCJSONResult.errorMsg("参数[payMethod]目前只支持微信支付或支付宝支付");
    		}
    		if (StringUtils.isBlank(returnUrl)) {
    			return IMOOCJSONResult.errorMsg("参数[returnUrl]不能为空");
    		}
    
    		// 保存传来的商户订单信息
    		boolean isSuccess = false;
    		try {
    			isSuccess = paymentOrderService.createPaymentOrder(merchantOrdersBO);
    		} catch (Exception e) {
    			e.printStackTrace();
    			IMOOCJSONResult.errorException(e.getMessage());
    		}
    
    		if (isSuccess) {
    			return IMOOCJSONResult.ok("商户订单创建成功!");
    		} else {
    			return IMOOCJSONResult.errorMsg("商户订单创建失败,请重试...");
    		}
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    保存订单数据接口

    	@Transactional(propagation=Propagation.REQUIRED)
    	@Override
    	public boolean createPaymentOrder(MerchantOrdersBO merchantOrdersBO) {
    
    		String id = sid.nextShort();
    
    		Orders paymentOrder = new Orders();
    		BeanUtils.copyProperties(merchantOrdersBO, paymentOrder);
    
    		paymentOrder.setId(id);
    		paymentOrder.setPayStatus(PaymentStatus.WAIT_PAY.type);
    		paymentOrder.setComeFrom("天天吃货");
    		paymentOrder.setIsDelete(YesOrNo.NO.type);
    		paymentOrder.setCreatedTime(new Date());
    
    		int result = ordersMapper.insert(paymentOrder);
    		return result == 1 ? true : false;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    其他1: Orders对象

    package com.imooc.pojo;
    
    import java.util.Date;
    
    @Data
    public class Orders {
        /**
         * 订单主键
         */
        private String id;
    
        /**
         * 商户订单号
         */
        private String merchantOrderId;
    
        /**
         * 商户方的发起用户的用户主键id
         */
        private String merchantUserId;
    
        /**
         * 实际支付总金额(包含商户所支付的订单费邮费总额)
         */
        private Integer amount;
    
        /**
         * 支付方式
         */
        private Integer payMethod;
    
        /**
         * 支付状态 10:未支付 20:已支付 30:支付失败 40:已退款
         */
        private Integer payStatus;
    
        /**
         * 从哪一端来的,比如从天天吃货这门实战过来的
         */
        private String comeFrom;
    
        /**
         * 支付成功后的通知地址,这个是开发者那一段的,不是第三方支付通知的地址
         */
        private String returnUrl;
    
        /**
         * 逻辑删除状态;1: 删除 0:未删除
         */
        private Integer isDelete;
    
        /**
         * 创建时间(成交时间)
         */
        private Date createdTime;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    其他2: MerchantOrdersBO对象

    package com.imooc.pojo.bo;
    @Data
    public class MerchantOrdersBO {
    
        private String merchantOrderId;         // 商户订单号
        private String merchantUserId;          // 商户方的发起用户的用户主键id
        private Integer amount;                 // 实际支付总金额(包含商户所支付的订单费邮费总额)
        private Integer payMethod;              // 支付方式 1:微信   2:支付宝
        private String returnUrl;               // 支付成功后的回调地址(学生自定义)
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4. 时序图2=>调统一下单api

    前端直接调用支付平台的统一下单api
    在这里插入图片描述

    提交订单后,前端接收到支付链接,前端转化成二维码即可
    在这里插入图片描述
    支付中心:微信配置

    # 微信支付二维码key
    wxpay.qrcodeKey=wxpay_qrcode
    
    # 微信支付二维码过期时间为<2小时(微信二维码code_url有效期为2小时)
    wxpay.qrcodeExpire=7000
    
    # 微信异步通知频率为15/15/30/180/1800/1800/1800/1800/3600 秒
    
    # 公众账号ID
    wxpay.appId=wx10516asde1h8ki
    
    # 商户号
    wxpay.merchantId=3411210594
    
    # 商户秘钥
    wxpay.secrectKey=4fkbcKhMcSxSXYZQc369nP1SI
    
    # APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP, 即:服务器ip地址
    wxpay.spbillCreateIp=127.0.0.1
    
    # 接受微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数. (需配置)
    #	public static final String NOTIFY_URL = "http://1s7p978583.iok.la/pay/notice/wxpay.shtml";
    #wxpay.notifyUrl=http://micmcq.natappfree.cc/payment/notice/wxpay
    wxpay.notifyUrl=http://payment.t.mukewang.com/foodie-payment/payment/notice/wxpay
    
    # 支付方式,取值如下
    wxpay.tradeType=NATIVE
    
    # 微信支付统一下单地址
    wxpay.placeOrderUrl=https://api.mch.weixin.qq.com/pay/unifiedorder
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    package com.imooc.resource;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.stereotype.Component;
    
    //@Configuration
    @Component
    @ConfigurationProperties(prefix="wxpay")
    @PropertySource("classpath:wxpay.properties")
    @Data
    public class WXPayResource {
    
    	private String qrcodeKey;
    	private long qrcodeExpire;
    
    	private String appId;
    	private String merchantId;
    	private String secrectKey;
    
    	private String spbillCreateIp;
    	private String notifyUrl;
    
    	private String tradeType;
    	private String placeOrderUrl;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    web接口

    	/**
    	 * 获取微信扫码支付链接地址
    	 * @param merchantOrderId 订单Id
    	 * @param merchantUserId  用户Id
    	 * @return
    	 * @throws Exception
    	 */
    	@PostMapping(value="/getWXPayQRCode")
    	public IMOOCJSONResult getWXPayQRCode(String merchantOrderId, String merchantUserId) throws Exception{
    
    		// 根据订单ID和用户ID查询订单详情
        	Orders waitPayOrder = paymentOrderService.queryOrderByStatus(merchantUserId, merchantOrderId, PaymentStatus.WAIT_PAY.type);
    
        	// 商品描述
    		String body = "天天吃货-付款用户[" + merchantUserId + "]";
    		// 商户订单号
    		String out_trade_no = merchantOrderId;
    		// 从redis中去获得这笔订单的微信支付二维码,如果订单状态没有支付没有就放入,这样的做法防止用户频繁刷新而调用微信接口
    		if (waitPayOrder != null) {
    			String qrCodeUrl = redis.get(wxPayResource.getQrcodeKey() + ":" + merchantOrderId);
    
    			if (StringUtils.isEmpty(qrCodeUrl)) {
    				// 订单总金额,单位为分
    				String total_fee = String.valueOf(waitPayOrder.getAmount());
    
    				// 统一下单
    				PreOrderResult preOrderResult = wxOrderService.placeOrder(body, out_trade_no, total_fee);
    				qrCodeUrl = preOrderResult.getCode_url();
    			}
    
    			PaymentInfoVO paymentInfoVO = new PaymentInfoVO();
    			paymentInfoVO.setAmount(waitPayOrder.getAmount());
    			paymentInfoVO.setMerchantOrderId(merchantOrderId);
    			paymentInfoVO.setMerchantUserId(merchantUserId);
    			paymentInfoVO.setQrCodeUrl(qrCodeUrl);
    
    			redis.set(wxPayResource.getQrcodeKey() + ":" + merchantOrderId, qrCodeUrl, wxPayResource.getQrcodeExpire());
    
    			return IMOOCJSONResult.ok(paymentInfoVO);
    		} else {
    			return IMOOCJSONResult.errorMsg("该订单不存在,或已经支付");
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    统一下单
    官网:统一下单文档

    	@Autowired
    	private WXPayResource wxPayResource;
    	
    	/**
    	 * ==========================================
    	 * 微信预付单:指的是在自己的平台需要和微信进行支付交易生成的一个微信订单,称之为“预付单”
    	 * 订单:指的是自己的网站平台与用户之间交易生成的订单
    	 * 
    	 * 1. 用户购买产品 --> 生成网站订单
    	 * 2. 用户支付 --> 网站在微信平台生成预付单
    	 * 3. 最终实际根据预付单的信息进行支付
    	 * ==========================================
    	 */
    	
    	@Override
    	public PreOrderResult placeOrder(String body, String out_trade_no, String total_fee) throws Exception {
    		// 生成预付单对象
    		PreOrder o = new PreOrder();
    		// 生成随机字符串
    		String nonce_str = UUID.randomUUID().toString().trim().replaceAll("-", "");
    		o.setAppid(wxPayResource.getAppId());
    		o.setBody(body);
    		o.setMch_id(wxPayResource.getMerchantId());
    		o.setNotify_url(wxPayResource.getNotifyUrl());
    		o.setOut_trade_no(out_trade_no);
    		// 判断有没有输入订单总金额,没有输入默认1分钱
    		if (total_fee != null && !total_fee.equals("")) {
    			o.setTotal_fee(Integer.parseInt(total_fee));
    		} else {
    			o.setTotal_fee(1);
    		}
    		o.setNonce_str(nonce_str);
    		o.setTrade_type(wxPayResource.getTradeType());
    		o.setSpbill_create_ip(wxPayResource.getSpbillCreateIp());
    		SortedMap<Object, Object> p = new TreeMap<Object, Object>();
    		p.put("appid", wxPayResource.getAppId());
    		p.put("mch_id", wxPayResource.getMerchantId());
    		p.put("body", body);
    		p.put("nonce_str", nonce_str);
    		p.put("out_trade_no", out_trade_no);
    		p.put("total_fee", total_fee);
    		p.put("spbill_create_ip", wxPayResource.getSpbillCreateIp());
    		p.put("notify_url", wxPayResource.getNotifyUrl());
    		p.put("trade_type", wxPayResource.getTradeType());
    		// 获得签名
    		String sign = Sign.createSign("utf-8", p, wxPayResource.getSecrectKey());
    		o.setSign(sign);
    		// Object转换为XML
    		String xml = XmlUtil.object2Xml(o, PreOrder.class);
    		// 统一下单地址
    		String url = wxPayResource.getPlaceOrderUrl();
    		// 调用微信统一下单地址
    		String returnXml = HttpUtil.sendPost(url, xml);
    		
    		// XML转换为Object
    		PreOrderResult preOrderResult = (PreOrderResult) XmlUtil.xml2Object(returnXml, PreOrderResult.class);
    		
    		return preOrderResult;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    其他1: 微信支付对象PreOrderResult

    package com.imooc.wx.entity;
    
    /**
     * 
     * @Title: PreOrderResult.java
     * @Package com.itzixi.wx.entity
     * @Description: 微信支付 - 统一下单返回结果的封装entity
     * Copyright: Copyright (c) 2016
     * Company:FURUIBOKE.SCIENCE.AND.TECHNOLOGY
     * 
     * @author leechenxiang
     * @date 2017年8月31日 上午10:39:14
     * @version V1.0
     */
    public class PreOrderResult {
    	
    	private String return_code;				// 返回状态码
    	private String return_msg;				// 返回信息
    	private String appid;					// 公众账号ID
    	private String mch_id;					// 商户号
    	private String device_info;				// 设备号
    	private String nonce_str;				// 随机字符串
    	private String sign;					// 签名
    	private String result_code;				// 业务结果
    	private String err_code;				// 错误代码
    	private String err_code_des;			// 错误代码描述
    	private String trade_type;				// 交易类型
    	private String prepay_id;				// 预支付交易会话标识
    	private String code_url;				// 二维码链接
    	
    	public String getReturn_code() {
    		return return_code;
    	}
    	public void setReturn_code(String return_code) {
    		this.return_code = return_code;
    	}
    	public String getReturn_msg() {
    		return return_msg;
    	}
    	public void setReturn_msg(String return_msg) {
    		this.return_msg = return_msg;
    	}
    	public String getAppid() {
    		return appid;
    	}
    	public void setAppid(String appid) {
    		this.appid = appid;
    	}
    	public String getMch_id() {
    		return mch_id;
    	}
    	public void setMch_id(String mch_id) {
    		this.mch_id = mch_id;
    	}
    	public String getDevice_info() {
    		return device_info;
    	}
    	public void setDevice_info(String device_info) {
    		this.device_info = device_info;
    	}
    	public String getNonce_str() {
    		return nonce_str;
    	}
    	public void setNonce_str(String nonce_str) {
    		this.nonce_str = nonce_str;
    	}
    	public String getSign() {
    		return sign;
    	}
    	public void setSign(String sign) {
    		this.sign = sign;
    	}
    	public String getResult_code() {
    		return result_code;
    	}
    	public void setResult_code(String result_code) {
    		this.result_code = result_code;
    	}
    	public String getErr_code() {
    		return err_code;
    	}
    	public void setErr_code(String err_code) {
    		this.err_code = err_code;
    	}
    	public String getErr_code_des() {
    		return err_code_des;
    	}
    	public void setErr_code_des(String err_code_des) {
    		this.err_code_des = err_code_des;
    	}
    	public String getTrade_type() {
    		return trade_type;
    	}
    	public void setTrade_type(String trade_type) {
    		this.trade_type = trade_type;
    	}
    	public String getPrepay_id() {
    		return prepay_id;
    	}
    	public void setPrepay_id(String prepay_id) {
    		this.prepay_id = prepay_id;
    	}
    	public String getCode_url() {
    		return code_url;
    	}
    	public void setCode_url(String code_url) {
    		this.code_url = code_url;
    	}
    	
    	@Override
    	public String toString() {
    		return "OrderReturn [return_code=" + return_code + ", return_msg="
    				+ return_msg + ", appid=" + appid + ", mch_id=" + mch_id
    				+ ", device_info=" + device_info + ", nonce_str=" + nonce_str
    				+ ", sign=" + sign + ", result_code=" + result_code
    				+ ", err_code=" + err_code + ", err_code_des=" + err_code_des
    				+ ", trade_type=" + trade_type + ", prepay_id=" + prepay_id
    				+ ", code_url=" + code_url + "]";
    	}
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122

    5. 时序10=>支付成功后的微信支付异步通知

    	/**
    	 * 支付成功后的微信支付异步通知
    	 */
    	@RequestMapping(value="/wxpay")
    	public void wxpay(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    		log.info("支付成功后的微信支付异步通知");
    
    		// 获取微信支付结果
    		PayResult payResult = wxOrderService.getWxPayResult(request.getInputStream());
    
    		boolean isPaid = payResult.getReturn_code().equals("SUCCESS") ? true : false;
    		// 查询该笔订单在微信那边是否成功支付
    		// 支付成功,商户处理后同步返回给微信参数
    		PrintWriter writer = response.getWriter();
    		if (isPaid) {
    
    			String merchantOrderId = payResult.getOut_trade_no();			// 商户订单号
    			String wxFlowId = payResult.getTransaction_id();
    			Integer paidAmount = payResult.getTotal_fee();
    
    //			System.out.println("================================= 支付成功 =================================");
    
    			// ====================== 操作商户自己的业务,比如修改订单状态等 start ==========================
    			String merchantReturnUrl = paymentOrderService.updateOrderPaid(merchantOrderId, paidAmount);
    			// ============================================ 业务结束, end ==================================
    
    			log.info("************* 支付成功(微信支付异步通知) - 时间: {} *************", DateUtil.getCurrentDateString(DateUtil.DATETIME_PATTERN));
    			log.info("* 商户订单号: {}", merchantOrderId);
    			log.info("* 微信订单号: {}", wxFlowId);
    			log.info("* 实际支付金额: {}", paidAmount);
    			log.info("*****************************************************************************");
    
    
    			// 通知天天吃货服务端订单已支付
    //			String url = "http://192.168.1.2:8088/orders/notifyMerchantOrderPaid";
    
    			MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
    			requestEntity.add("merchantOrderId", merchantOrderId);
    			String httpStatus = restTemplate.postForObject(merchantReturnUrl, requestEntity, String.class);
    			log.info("*** 通知天天吃货后返回的状态码 httpStatus: {} ***", httpStatus);
    
    			// 通知微信已经收到消息,不要再给我发消息了,否则微信会10连击调用本接口
    			String noticeStr = setXML("SUCCESS", "");
    			writer.write(noticeStr);
    			writer.flush();
    
    		} else {
    			System.out.println("================================= 支付失败 =================================");
    
    			// 支付失败
    			String noticeStr = setXML("FAIL", "");
    			writer.write(noticeStr);
    			writer.flush();
    		}
    
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    解析HttpServletRequest的getInputStream

    	@Override
    	public PayResult getWxPayResult(InputStream inStream) throws Exception {
    		BufferedReader in = null;
    		String result = "";
    		in = new BufferedReader(
    				new InputStreamReader(inStream));
    		String line;
    		while ((line = in.readLine()) != null) {
    			result += line;
    		}
    		PayResult pr = (PayResult)XmlUtil.xml2Object(result, PayResult.class);
    //		System.out.println(pr.toString());
    		return pr;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    XmlUtil工具

    package com.imooc.wx.util;
    
    import com.thoughtworks.xstream.XStream;
    import com.thoughtworks.xstream.io.xml.DomDriver;
    import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
    
    import java.io.InputStream;
    
    public class XmlUtil {
    //	private static XStream xstream;
    //	static {
    //		xstream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
    //	}
    
    	/**
    	 * 
    	 * @Description: xml字符串转换为对象
    	 * @param inputXml
    	 * @param type
    	 * @return
    	 * @throws Exception
    	 * 
    	 * @author imooc
    	 * @date 2019年8月31日 下午4:52:13
    	 */
    	public static Object xml2Object(String inputXml, Class<?> type) throws Exception {
    		if (null == inputXml || "".equals(inputXml)) {
    			return null;
    		}
    		XStream xstream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
    		xstream.alias("xml", type);
    		return xstream.fromXML(inputXml);
    	}
    	
    	/**
    	 * 
    	 * @Description: 从inputStream中读取对象
    	 * @param inputStream
    	 * @param type
    	 * @return
    	 * @throws Exception
    	 * 
    	 * @author imooc
    	 * @date 2019年8月31日 下午4:52:29
    	 */
    	public static Object xml2Object(InputStream inputStream, Class<?> type) throws Exception {
    		if (null == inputStream) {
    			return null;
    		}
    		XStream xstream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
    		xstream.alias("xml", type);
    		return xstream.fromXML(inputStream, type);
    	}
    
    	/**
    	 * 
    	 * @Description: 对象转换为xml字符串
    	 * @param ro
    	 * @param types
    	 * @return
    	 * @throws Exception
    	 * 
    	 * @author imooc
    	 * @date 2019年8月31日 下午4:52:45
    	 */
    	public static String object2Xml(Object ro, Class<?> types) throws Exception {
    		if (null == ro) {
    			return null;
    		}
    		XStream xstream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
    		xstream.alias("xml", types);
    		return xstream.toXML(ro);
    	}
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    PayResult支付对象

    package com.imooc.wx.entity;
    
    /**
     * 
     * @Title: PayResult.java
     * @Package com.itzixi.wx.entity
     * @Description: 支付结果封装类
     * Copyright: Copyright (c) 2016
     * Company:FURUIBOKE.SCIENCE.AND.TECHNOLOGY
     * 
     * @author imooc
     * @date 2019年8月31日 下午4:26:14
     * @version V1.0
     */
    public class PayResult {
    	private String return_code;				// 返回状态码
    	private String appid;					// 公众账号ID
    	private String mch_id;					// 商户号
    	private String nonce_str;				// 随机字符串
    	private String sign;					// 签名
    	private String result_code;				// 业务结果
    	private String openid;					// 用户标识
    	private String trade_type;				// 交易类型
    	private String bank_type;				// 付款银行
    	private int total_fee;					// 总金额
    	private int cash_fee;					// 现金支付金额
    	private String transaction_id;			// 微信支付订单号
    	private String out_trade_no;			// 商户订单号
    	private String time_end;				// 支付完成时间
    	private String return_msg;				// 返回信息
    	private String device_info;				// 设备号
    	private String err_code;				// 错误代码
    	private String err_code_des;			// 错误代码描述
    	private String is_subscribe;			// 是否关注公众账号
    	private String fee_type;				// 货币种类
    	private String cash_fee_type;			// 现金支付货币类型
    	private String coupon_fee;				// 代金券或立减优惠金额
    	private String coupon_count;			// 代金券或立减优惠使用数量
    	private String coupon_id_$n;			// 代金券或立减优惠ID
    	private String coupon_fee_$n;			// 单个代金券或立减优惠支付金额
    	private String attach;					// 商家数据包
    
    	public String getReturn_code() {
    		return return_code;
    	}
    
    	public void setReturn_code(String return_code) {
    		this.return_code = return_code;
    	}
    
    	public String getAppid() {
    		return appid;
    	}
    
    	public void setAppid(String appid) {
    		this.appid = appid;
    	}
    
    	public String getMch_id() {
    		return mch_id;
    	}
    
    	public void setMch_id(String mch_id) {
    		this.mch_id = mch_id;
    	}
    
    	public String getNonce_str() {
    		return nonce_str;
    	}
    
    	public void setNonce_str(String nonce_str) {
    		this.nonce_str = nonce_str;
    	}
    
    	public String getSign() {
    		return sign;
    	}
    
    	public void setSign(String sign) {
    		this.sign = sign;
    	}
    
    	public String getResult_code() {
    		return result_code;
    	}
    
    	public void setResult_code(String result_code) {
    		this.result_code = result_code;
    	}
    
    	public String getOpenid() {
    		return openid;
    	}
    
    	public void setOpenid(String openid) {
    		this.openid = openid;
    	}
    
    	public String getTrade_type() {
    		return trade_type;
    	}
    
    	public void setTrade_type(String trade_type) {
    		this.trade_type = trade_type;
    	}
    
    	public String getBank_type() {
    		return bank_type;
    	}
    
    	public void setBank_type(String bank_type) {
    		this.bank_type = bank_type;
    	}
    
    	public int getTotal_fee() {
    		return total_fee;
    	}
    
    	public void setTotal_fee(int total_fee) {
    		this.total_fee = total_fee;
    	}
    
    	public int getCash_fee() {
    		return cash_fee;
    	}
    
    	public void setCash_fee(int cash_fee) {
    		this.cash_fee = cash_fee;
    	}
    
    	public String getTransaction_id() {
    		return transaction_id;
    	}
    
    	public void setTransaction_id(String transaction_id) {
    		this.transaction_id = transaction_id;
    	}
    
    	public String getOut_trade_no() {
    		return out_trade_no;
    	}
    
    	public void setOut_trade_no(String out_trade_no) {
    		this.out_trade_no = out_trade_no;
    	}
    
    	public String getTime_end() {
    		return time_end;
    	}
    
    	public void setTime_end(String time_end) {
    		this.time_end = time_end;
    	}
    
    	public String getReturn_msg() {
    		return return_msg;
    	}
    
    	public void setReturn_msg(String return_msg) {
    		this.return_msg = return_msg;
    	}
    
    	public String getDevice_info() {
    		return device_info;
    	}
    
    	public void setDevice_info(String device_info) {
    		this.device_info = device_info;
    	}
    
    	public String getErr_code() {
    		return err_code;
    	}
    
    	public void setErr_code(String err_code) {
    		this.err_code = err_code;
    	}
    
    	public String getErr_code_des() {
    		return err_code_des;
    	}
    
    	public void setErr_code_des(String err_code_des) {
    		this.err_code_des = err_code_des;
    	}
    
    	public String getIs_subscribe() {
    		return is_subscribe;
    	}
    
    	public void setIs_subscribe(String is_subscribe) {
    		this.is_subscribe = is_subscribe;
    	}
    
    	public String getFee_type() {
    		return fee_type;
    	}
    
    	public void setFee_type(String fee_type) {
    		this.fee_type = fee_type;
    	}
    
    	public String getCash_fee_type() {
    		return cash_fee_type;
    	}
    
    	public void setCash_fee_type(String cash_fee_type) {
    		this.cash_fee_type = cash_fee_type;
    	}
    
    	public String getCoupon_fee() {
    		return coupon_fee;
    	}
    
    	public void setCoupon_fee(String coupon_fee) {
    		this.coupon_fee = coupon_fee;
    	}
    
    	public String getCoupon_count() {
    		return coupon_count;
    	}
    
    	public void setCoupon_count(String coupon_count) {
    		this.coupon_count = coupon_count;
    	}
    
    	public String getCoupon_id_$n() {
    		return coupon_id_$n;
    	}
    
    	public void setCoupon_id_$n(String coupon_id_$n) {
    		this.coupon_id_$n = coupon_id_$n;
    	}
    
    	public String getCoupon_fee_$n() {
    		return coupon_fee_$n;
    	}
    
    	public void setCoupon_fee_$n(String coupon_fee_$n) {
    		this.coupon_fee_$n = coupon_fee_$n;
    	}
    
    	public String getAttach() {
    		return attach;
    	}
    
    	public void setAttach(String attach) {
    		this.attach = attach;
    	}
    
    	@Override
    	public String toString() {
    		return "OrderMessage [return_code=" + return_code + ", appid=" + appid
    				+ ", mch_id=" + mch_id + ", nonce_str=" + nonce_str + ", sign="
    				+ sign + ", result_code=" + result_code + ", openid=" + openid
    				+ ", trade_type=" + trade_type + ", bank_type=" + bank_type
    				+ ", total_fee=" + total_fee + ", cash_fee=" + cash_fee
    				+ ", transaction_id=" + transaction_id + ", out_trade_no="
    				+ out_trade_no + ", time_end=" + time_end + ", return_msg="
    				+ return_msg + ", device_info=" + device_info + ", err_code="
    				+ err_code + ", err_code_des=" + err_code_des
    				+ ", is_subscribe=" + is_subscribe + ", fee_type=" + fee_type
    				+ ", cash_fee_type=" + cash_fee_type + ", coupon_fee="
    				+ coupon_fee + ", coupon_count=" + coupon_count
    				+ ", coupon_id_$n=" + coupon_id_$n + ", coupon_fee_$n="
    				+ coupon_fee_$n + ", attach=" + attach + "]";
    	}
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
  • 相关阅读:
    力扣 -- 44. 通配符匹配
    中文版PyCharm改为英文版PyCharm
    Java创建对象的5种方式简介、语法、举例、对比
    1013 Battle Over Cities 甲级 xp_xht123
    Webmin--Webmin Configuration模块
    【1024程序员节特刊】算法题目易错之处干货总结
    宝宝蛋白过敏怎么办
    android.bp 使用
    leetcode-15.三数之和-20220821
    权限管理与jwt鉴权
  • 原文地址:https://blog.csdn.net/qq_44289784/article/details/133076740