zoukankan      html  css  js  c++  java
  • 尚筹网17订单、支付

    订单部分建模回顾

    实体类之间关系

    创建OrderVO实体类

    public class OrderVO implements Serializable {
        private static final long serialVersionUID = 1L;
    
        // 主键
        private Integer id;
        // 订单号
        private String orderNum;
        // 支付宝流水单号
        private String payOrderNum;
        // 订单金额
        private Double orderAmount;
        // 是否开发票
        private Integer invoice;
        // 发票抬头
        private String invoiceTitle;
        // 备注
        private String orderRemark;
    
        private String addressId;
    
        private OrderProjectVO orderProjectVO;
    
        public OrderVO() {
        }
    
        public OrderVO(Integer id, String orderNum, String payOrderNum, Double orderAmount, Integer invoice, String invoiceTitle, String orderRemark, String addressId, OrderProjectVO orderProjectVO) {
            this.id = id;
            this.orderNum = orderNum;
            this.payOrderNum = payOrderNum;
            this.orderAmount = orderAmount;
            this.invoice = invoice;
            this.invoiceTitle = invoiceTitle;
            this.orderRemark = orderRemark;
            this.addressId = addressId;
            this.orderProjectVO = orderProjectVO;
        }

    修改t_order

    增加address_id字段

    支付功能流程

    思路

    操作1:搭建环境

    基础环境

    参照order-consumer

    支付接口调用所需环境 

    <!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java --> <dependency> 
    <groupId>com.alipay.sdk</groupId> 
    <artifactId>alipay-sdk-java</artifactId>
     <version>3.3.49.ALL</version> 
    </dependency> 

    创建PayProperties类维护支付接口参数

    @Component
    @ConfigurationProperties(prefix = "ali.pay")
    public class PayProperties {
        private String appId;
        private String merchantPrivateKey;
        private String alipayPublicKey;
        private String notifyUrl;
        private String returnUrl;
        private String signType;
        private String charset;
        private String gatewayUrl;
    
        public PayProperties() {
        }
    
        public PayProperties(String appId, String merchantPrivateKey, String alipayPublicKey, String notifyUrl, String returnUrl, String signType, String charset, String gatewayUrl) {
            this.appId = appId;
            this.merchantPrivateKey = merchantPrivateKey;
            this.alipayPublicKey = alipayPublicKey;
            this.notifyUrl = notifyUrl;
            this.returnUrl = returnUrl;
            this.signType = signType;
            this.charset = charset;
            this.gatewayUrl = gatewayUrl;
        }

    配置支付参数

    操作2:提交订单表单

    构造页面不可见的表单

    <!-- 为了收集当前页面中的所有数据,构造空表单 -->
    <form id="summaryForm" action="pay/generate/order" method="post"></f

    立即付款按钮绑定单击响应函数

    $("#payButton").click(function(){
       
       // 1.收集所有要提交的表单项的数据
       var addressId = $("[name=addressId]:checked").val();
       var invoice = $("[name=invoiceRadio]:checked").val();
       var invoiceTitle = $.trim($("[name=invoiceTitle]").val());
       var remark = $.trim($("[name=remark]").val());
       
       // 2.将上面收集到的表单数据填充到空表单中并提交
       $("#summaryForm")
          .append("<input type='hidden' name='addressId' value='"+addressId+"'/>")
          .append("<input type='hidden' name='invoice' value='"+invoice+"'/>")
          .append("<input type='hidden' name='invoiceTitle' value='"+invoiceTitle+"'/>")
          .append("<input type='hidden' name='orderRemark' value='"+remark+"'/>")
          .submit();
       
    });

    操作3:生成订单号

    支付宝对订单号的要求

    格式设计

    当前时间(年月日小时分秒)+用户ID

    时间格式:yyyyMMddHHmmss

    用户ID:通过UUID生成

    Controller

    //让当前方法返回响应体,在浏览器页面上显示支付宝支付页面
    @ResponseBody
    @RequestMapping("/generate/order")
    public String generateOrder(HttpSession session, OrderVO orderVO) throws AlipayApiException {
        // 1.从session中获取orderProjectVO
        OrderProjectVO orderProjectVO= (OrderProjectVO) session.getAttribute("orderProjectVO");
        // 2.将orderProjectVO对象和orderVO对象封装到一起
        orderVO.setOrderProjectVO(orderProjectVO);
        // 3.生成订单并设置到orderVO对象中
        String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
    
        String user = UUID.randomUUID().toString().replace("-","").toUpperCase();
    
        String orderNum = time + user;
    
        orderVO.setOrderNum(orderNum);
        // 4.计算订单金额并设置到orderVO对象中
        Double orderAmount = (double) orderProjectVO.getSupportPrice() * orderProjectVO.getReturnCount() + orderProjectVO.getFreight();
        orderVO.setOrderAmount(orderAmount);
    
        // 将OrderVO对象存入Session域中
        session.setAttribute("orderVO",orderVO);
        // 5.调用支付宝封装方法
        return sendRequestToAliPay(orderNum,orderAmount,orderProjectVO.getProjectName(),orderProjectVO.getReturnContent());
    
    }

    调用支付宝接口的专门方法

    /**
         * 为了调用支付宝接口封装的方法
         * @param outTradeNo  外部订单号
         * @param totalAmount 订单金额
         * @param subject      订单标题
         * @param body          描述
         * @return              返回页面上显示的登录界面
         * @throws AlipayApiException
         */
        private String sendRequestToAliPay(
                String outTradeNo,
                Double totalAmount,
                String subject,
                String body) throws AlipayApiException {
            //获得初始化的AlipayClient
            AlipayClient alipayClient = new DefaultAlipayClient(
                    payProperties.getGatewayUrl(),
                    payProperties.getAppId(),
                    payProperties.getMerchantPrivateKey(),
                    "json",
                    payProperties.getCharset(),
                    payProperties.getAlipayPublicKey(),
                    payProperties.getSignType());
    
            //设置请求参数
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
            alipayRequest.setReturnUrl(payProperties.getReturnUrl());
            alipayRequest.setNotifyUrl(payProperties.getNotifyUrl());
    
            //商户订单号,商户网站订单系统中唯一订单号,必填
    //        String out_trade_no = new String(request.getParameter("WIDout_trade_no").getBytes("ISO-8859-1"),"UTF-8");
            //付款金额,必填
    //        String total_amount = new String(request.getParameter("WIDtotal_amount").getBytes("ISO-8859-1"),"UTF-8");
    //        //订单名称,必填
    //        String subject = new String(request.getParameter("WIDsubject").getBytes("ISO-8859-1"),"UTF-8");
    //        //商品描述,可空
    //        String body = new String(request.getParameter("WIDbody").getBytes("ISO-8859-1"),"UTF-8");
    
            alipayRequest.setBizContent("{"out_trade_no":""+ outTradeNo +"","
                    + ""total_amount":""+ totalAmount +"","
                    + ""subject":""+ subject +"","
                    + ""body":""+ body +"","
                    + ""product_code":"FAST_INSTANT_TRADE_PAY"}");
    
            //若想给BizContent增加其他可选请求参数,以增加自定义超时时间参数timeout_express来举例说明
            //alipayRequest.setBizContent("{"out_trade_no":""+ out_trade_no +"","
            //    + ""total_amount":""+ total_amount +"","
            //    + ""subject":""+ subject +"","
            //    + ""body":""+ body +"","
            //    + ""timeout_express":"10m","
            //    + ""product_code":"FAST_INSTANT_TRADE_PAY"}");
            //请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节
    
            //请求
            return alipayClient.pageExecute(alipayRequest).getBody();
        }

    操作4:returnUrl方法

    @ResponseBody
    @RequestMapping("/return")
    public String returnUrlMethod(
            HttpServletRequest request,
            HttpSession session) throws AlipayApiException, UnsupportedEncodingException {
        //获取支付宝GET过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
    
        boolean signVerified = AlipaySignature.rsaCheckV1(
                params,
                payProperties.getAlipayPublicKey(),
                payProperties.getCharset(),
                payProperties.getSignType()); //调用SDK验证签名
    
        //——请在这里编写您的程序(以下代码仅作参考)——
        if(signVerified) {
            //商户订单号
            String orderNum = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
    
            //支付宝交易号
            String payOrderNum = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
    
            //付款金额
            String orderAmount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
            // 保存到数据库
            // 从Session获取OrderVO对象
            OrderVO orderVO = (OrderVO) session.getAttribute("orderVO");
    
            orderVO.setPayOrderNum(payOrderNum);
            // 发送给mysql远程接口
            ResultEntity<String> resultEntity = mySQLRemoteService.saveOrderRemote(orderVO);
            logger.info("Order save result="+resultEntity.getResult());
            return "trade_no:"+payOrderNum+"<br/>out_trade_no:"+orderNum+"<br/>total_amount:"+orderAmount;
        }else {
            // 页面显示信息,验签失败
            return "验签失败";
        }
    }

    操作5:notifyUrl方法

     @RequestMapping("/notify")
        public void notifyUrlMethod(HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException {
    
            //获取支付宝POST过来反馈信息
            Map<String,String> params = new HashMap<String,String>();
            Map<String,String[]> requestParams = request.getParameterMap();
            for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
                String name = (String) iter.next();
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                //乱码解决,这段代码在出现乱码时使用
                valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
                params.put(name, valueStr);
            }
    
            boolean signVerified = AlipaySignature.rsaCheckV1(
                    params,
                    payProperties.getAlipayPublicKey(),
                    payProperties.getCharset(),
                    payProperties.getSignType()); //调用SDK验证签名
            //——请在这里编写您的程序(以下代码仅作参考)——
       /* 实际验证过程建议商户务必添加以下校验:
       1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
       2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
       3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
       4、验证app_id是否为该商户本身。
       */
            if(signVerified) {//验证成功
                //商户订单号
                String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
    
                //支付宝交易号
                String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
    
                //交易状态
                String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
                logger.info("trade_status="+trade_status);
                logger.info("out_trade_no="+out_trade_no);
                logger.info("trade_no="+trade_no);
    //            if(trade_status.equals("TRADE_FINISHED")){
    //                //判断该笔订单是否在商户网站中已经做过处理
    //                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
    //                //如果有做过处理,不执行商户的业务程序
    //
    //                //注意:
    //                //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
    //            }else if (trade_status.equals("TRADE_SUCCESS")){
    //                //判断该笔订单是否在商户网站中已经做过处理
    //                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
    //                //如果有做过处理,不执行商户的业务程序
    //
    //                //注意:
    //                //付款完成后,支付宝系统发送该交易状态通知
    //            }
    //
    //            out.println("success");
    //
    //        }else {//验证失败
    //            out.println("fail");
    //
    //            //调试用,写文本函数记录程序运行情况是否正常
    //            //String sWord = AlipaySignature.getSignCheckContentV1(params);
    //            //AlipayConfig.logResult(sWord);
            }else {
                logger.info("验证失败");
            }
        }

    订单信息保存到数据库

    思路

    SQL设置

    关键点:保存OrderPO时获取自增主键

    <insert id="insert" parameterType="com.example.entity.po.OrderPO" useGeneratedKeys="true" keyProperty="id">
      insert into t_order (id, order_num, pay_order_num, 
        order_amount, invoice, invoice_title, 
        order_remark, address_id)
      values (#{id,jdbcType=INTEGER}, #{orderNum,jdbcType=CHAR}, #{payOrderNum,jdbcType=CHAR}, 
        #{orderAmount,jdbcType=DOUBLE}, #{invoice,jdbcType=INTEGER}, #{invoiceTitle,jdbcType=CHAR}, 
        #{orderRemark,jdbcType=CHAR}, #{addressId,jdbcType=CHAR})
    </insert>
  • 相关阅读:
    Please verify that your alternate settings file is specified properly and exists in the workspace.
    史上最全最新微信小程序自动化教程
    Android的WebView调试工具(无需FanQ,可同时调试多个设备,永不过期)
    Android通过Chrome Inspect调试WebView的H5 App出现空白页面的解决方法(不需要FQ)
    appium+java(四)微信公众号自动化测试
    基于APPIUM测试微信公众号的UI自动化测试框架
    Appium测试微信公众号
    通过Debugx5在电脑端调试微信页面
    微信小程序自动化测试实践
    Rocketmq和Kafka区别
  • 原文地址:https://www.cnblogs.com/Adam-Ye/p/13423787.html
Copyright © 2011-2022 走看看