支付宝对接-java后端

作者: nickbi | 来源:发表于2017-09-05 23:12 被阅读73次
    前段时间,公司需要接入支付宝,现在腾出了一点时间,所以做一下总结,分享一些自己项目中遇到的坑,本文
    app支付为例。对于支付宝的对接,无疑官方文档是最全,最完善的,所以给大家一个传送 
    

    支付宝官方文档
    1.创建应用并获取APPID
    2.配置应用


    集成开发

    本文使用支付宝sdk进行支付宝对接,请到支付宝java demo进行下载

    1.参数说明

    FireShot Capture 2 - 开放平台文档中心 - https___docs.open.alipay.com_204_105465_.png

    2.APP客户端请求orderString的生成

     // 请求网关地址
        public static final String ALIPAY_URL = "https://openapi.alipay.com/gateway.do";
     // 异回调地址
        public static final String ALIPAY_NOTIFY_URL = "https://www.nickbi.com/alipay/notify";
     // 商户appid
        public static final String ALIPAY_APPID = "xxxxxx";
    // 私钥 pkcs8格式的(可用支付宝秘钥工具生成)
        public static final String ALIPAY_RSA_PRIVATE_KEY = “xxxxx”
     // 返回格式
        public static final String ALIPAY_ALI_FORMAT = "json";
     // 返回格式
        public static final String ALIPAY_ALI_FORMAT = "json";
    // 支付宝公钥(可在设置了公钥私钥后,在支付宝商户后台查看)
        public static final String ALI_PUBLIC_KEY = “xxxxx”
    // RSA2
        public static final String ALIPAY_SIGNTYPE = "RSA2";
    
     /**
      * 获得app端支付宝参数
      */
        public String getAlipayReqeustString(String orderNo, String totalAmount)
                throws AlipayApiException {
            //app Request
            AlipayClient alipayClient = new DefaultAlipayClient(ALIPAY_URL,
                    ALIPAY_APPID, ALIPAY_RSA_PRIVATE_KEY, ALIPAY_ALI_FORMAT,
                   ALIPAY_CHARSET,  ALI_PUBLIC_KEY,ALIPAY_SIGNTYPE);
            //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            //model.setBody(body);
            model.setSubject(“简书打赏”);
            model.setOutTradeNo(orderNo);
            //订单超时时间:取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天
            model.setTimeoutExpress(“30m”);
           //订单总支付金额
            model.setTotalAmount(totalAmount);
           //销售产品码:商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY
            model.setProductCode("QUICK_MSECURITY_PAY");
            request.setBizModel(model);
            request.setNotifyUrl(ALIPAY_NOTIFY_URL);
            //这里和普通的接口调用不同,使用的是sdkExecute
            AlipayTradeAppPayResponse response =  alipayClient.sdkExecute(request);
            return response.getBody();//就是orderString 可以直接给客户端请求,无需再做处理。
        }
    

    3.回调处理

        @ResponseBody
        @RequestMapping(value = "/alipay/notify", method = RequestMethod.POST)
        public String getPayNotify(HttpServletRequest request) throws Exception {
            Map<String, String> params = new HashMap<String, String>();
            Map requestParams = request.getParameterMap();
            for (Iterator 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] + ",";
                }
                //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转
                // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
                params.put(name, valueStr);
    }
            //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
            // 商户订单号
            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 total_fee = "0.00";
            if (request.getParameter("total_amount") != null) {
                total_fee = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),
                        "UTF-8");
            }
    
            //交易状态
            String trade_status = new String(
                    request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
    
            //异步通知ID
            String notify_id = request.getParameter("notify_id");
    
            if (notify_id != null && !"".equals(notify_id)) {
                boolean verify_result = AlipaySignature
                        .rsaCheckV1(params, ALI_PUBLIC_KEY, AppContents.ALI_CHARSET,
                                ALIPAY_SIGNTYPE);
                if (verify_result) {
                    //使用支付宝公钥验签
                    //订单支付成功
                    //if (trade_status.equals("TRADE_FINISHED") || trade_status.equals("TRADE_SUCCESS")) {
                    if (trade_status.equals("TRADE_SUCCESS")) {
                    //业务处理,使用自己的接口,进行订单处理
                        boolean result = orderService.getNotify(......)
                        if (result) {
                            return "success";
                        }
                    }
                    //订单超时关闭,修改订单
                    if (trade_status.equals("TRADE_CLOSED")) {
                        boolean result = orderService.getCloseNotify(......)
                        if (result) {
                            return "success";
                        }
                    }
                    return "fail";
                } else {
                    //验证签名失败
                    return "fail";
                }
    
            } else {
                return "fail";
            }
        }
    

    总结

    遇到的一些坑:

    在项目的前期,使用app端的同步回调去处理订单信息,但是由于用户操作的确定性,所以在回调过程中会出现很多
    意向不到的结果,所以订单处理异步回调更稳妥(老哥如果觉得想飙车,去试一把那我也是不拒绝的)。另外对于异步
    回调也会出现未知原因,所以关于订单的轮询查询,订单矫正请自行尝试,到时可以一起交流下。
    

    相关文章

      网友评论

        本文标题:支付宝对接-java后端

        本文链接:https://www.haomeiwen.com/subject/nxppjxtx.html