电商平台接入手机支付宝支付(服务商授权模式,可直接付款给卖家)

前言

这段时间帮助一个电商平台做了手机支付宝支付的模块,过程中遇到了一些坑,也收获了一些经验,在此做一下记录,也希望能帮助到后来的人。

需求

我们的需求比较常规,就是下单的时候选择支付宝支付,支付给卖家即可。接入支付宝支付模块后应尽量让卖家操作简单,毕竟卖家不一定有开发能力,也不一定很懂电脑。为此,我们选择服务商授权第三方应用模式,卖家只需在蚂蚁金服务开放平台注册手机网站支付应用,然后在平台一键授权即可,非常简单。

支付宝手机支付

准备工作

首先,我们先看支付宝官方的文档以及官方demo,可以说基本所有问题都可以从文档里找到答案,实在找不到答案可以去问蚂蚁金服的人工客服。支付宝手机支付官方文档地址:https://docs.open.alipay.com/203/105288/ ,在文档里可以找到官方demo。我们先按照支付宝手机支付的官方文档完成支付宝支付功能。
可以使用沙箱账号,也可以直接使用真实账号,我们这里就不介绍沙箱账号配置方法,使用真实账号。需要提醒的是,沙箱账号有个坑:配置沙箱卖家账号之后,支付也只能使用沙箱买家账号,对于手机端,要下载沙箱版的支付宝app,登陆沙箱账号,而沙箱账号在我们用的支付宝app上是无法登陆的!
在蚂蚁金服开放平台使用支付宝账号密码登录,第一次登陆的时候要选择身份,可以选择系统服务商(ISV),也可以选择自主开发者,在后期可以扩展身份,这里选择系统服务商好了,对于注册应用似乎没什么影响。然后就需要注册应用,可以参考文档:https://docs.open.alipay.com/203/107084/ 即可,这里有一个授权回调地址,这是后来授权给第三方应用需要配置的项,现在可以不填或者随便填一个地址,支付宝网关是图里固定的一个url(对于沙箱是另一个url),支付宝公钥和应用公钥、应用私钥都可查看文档在本地生成,这些在代码里也要用到。
电商平台接入手机支付宝支付(服务商授权模式,可直接付款给卖家)_第1张图片
应用注册好,通过审核、上线之后,需要添加手机网站支付的功能,点击应用详情,进入应用详情页,点击添加功能,输入一系列必要的资料,等审核通过即可(对于个人账号貌似需要公司营业执照,公司支付宝账号似乎不需要,当时做的太快忘记了。。)。
电商平台接入手机支付宝支付(服务商授权模式,可直接付款给卖家)_第2张图片
电商平台接入手机支付宝支付(服务商授权模式,可直接付款给卖家)_第3张图片
电商平台接入手机支付宝支付(服务商授权模式,可直接付款给卖家)_第4张图片
电商平台接入手机支付宝支付(服务商授权模式,可直接付款给卖家)_第5张图片

正式写代码

准备工作做好之后,就要开始写代码。首先,因为在实现过程中需要调用支付宝的很多接口,我们需要导入alipay的jar包,在pom文件里添加依赖:

<dependency>
  <groupId>com.alipay.sdk</groupId>
  <artifactId>alipay-sdk-java</artifactId>
  <version>3.1.0</version>
</dependency>

然后,在application.yml文件里添加相关基本配置:

pay:
  alipay:
    gatewayUrl: https://openapi.alipay.com/gateway.do
    appid: 申请的应用id
    appPrivateKey: 生成的应用私钥
    alipayPublicKey: 支付宝公钥
    returnUrl: https://xxxxxx/alipay/returnurl
    notifyUrl: https://xxxxxx/alipay/notifyurl
    charset: UTF-8
    format: json
    signtype: RSA2

returnUrl和notifyUrl是两个接口地址,都需要是线上可访问的,因为是支付宝来调用这两个接口。
接下来新建AlipayController.java文件,在这个controller里写有关支付宝支付的所有接口,必要的接口包括创建支付宝订单接口、异步回调接口、同步回调接口和退款接口,其他一些辅助接口(比如交易查询接口、下载对账单接口等)可根据自己项目需要再加上。

创建支付宝订单接口

创建支付宝订单接口包括两部分,一部分是和自己业务相关的,根据自己的订单获取支付金额、支付信息等,另一部分是调用alipay-sdk中的相关接口,由支付宝来处理支付信息,跳到支付宝支付界面进行支付。代码如下:

/**
     * 生成支付宝支付订单接口,传入参数为多个订单orderNo的数组,可多个订单一起支付
     * @param orderNoDTO
     * @return
     * @throws ServletException
     * @throws IOException
     */
    @PostMapping(value = "/createAlipayOrder")
    public Object createAlipayOrder(@RequestBody OrderNoDTO orderNoDTO) throws ServletException, IOException{
     
        Map<String, Object> map = new HashMap<>();
        if(orderNoDTO.getOrderNo().size()<=0){
     
            return ResponseJsonUtil.returnJson(map, BusinessConstants.GET_ORDER_LIST_ERROR, PsiInfo.ERROR.code);
        }//判断orderNoDTO里是否有订单,没有订单报错
        String firstOrderNo=orderNoDTO.getOrderNo().get(0);
        Long sellerId=orderService.selectSellerIdByOrderNo(firstOrderNo);//所有订单卖家相同,因此根据第一个订单编号即可获取卖家id
        double money=0.0;//支付金额初始值
        String subject="";//支付描述信息
        AlipayOrder alipayOrder=new AlipayOrder();//创建支付订单
        alipayOrder.setOut_trade_no(CreateOrderNo.createOrderNo("Alipay"));//创建由Alipay打头的支付订单号,多个订单号对应一个支付订单号
        for(String orderNo:orderNoDTO.getOrderNo()){
     
            try{
     
                Order order=orderService.getSingleOrderByOrderNo(orderNo);
                order.setAlipay_out_trade_no(alipayOrder.getOut_trade_no());
                orderService.updateOrderByExample(order);//获取原销售订单,将支付订单号传入并更新
                List<OrderEx> orderExlist=orderService.getOrderDetailByOrderNo(orderNo);//获取原支付订单包含的物品信息
                for(OrderEx orderEx:orderExlist){
     
                    subject+=orderEx.getGoodsName();//支付订单描述由所有物品信息组成
                    logger.info("subject:{}",subject);
                }
                money+=order.getMoney().doubleValue();//支付订单金额等于原订单金额之和
                logger.info("money:{}",money);
            }catch (Exception e){
     

            }
        }
       //以上是与自己业务相关的代码,可根据自己业务来,最重要的是要生成支付订单号,获取支付金额和支付描述信息
        alipayOrder.setStatus((byte)0);//0代表创建订单等待付款
        alipayOrder.setTotal_amount(new BigDecimal(Double.toString(money)));//支付订单金额
        alipayOrder.setReceipt_amount(new BigDecimal(Double.toString(0.00)));//实收金额
        alipayOrder.setInvoice_amount(new BigDecimal(Double.toString(0.00)));//开票金额
        alipayOrder.setBuyerpay_amount(new BigDecimal(Double.toString(0.00)));//买家付款金额
        alipayOrder.setRefund_fee(new BigDecimal(Double.toString(0.00)));//退款金额
        if(orderService.createAlipayOrder(alipayOrder)<=0) {
     
            return ResponseJsonUtil.returnJson(map, BusinessConstants.AliPay_ORDER_CREATE_FAIL, PsiInfo.ERROR.code);
        }//创建支付订单,插入数据库
        try{
     
            //String alipayToken=storeService.getAlipayTokenByMemberId(sellerId);
            //if(alipayToken==null){
     
                //return ResponseJsonUtil.returnJson(map, BusinessConstants.AliPay_TOKEN_NULL, PsiInfo.ERROR.code);
           // }
           //以上注释是和授权有关代码,以后再提,目前对于支付并无影响
            AlipayClient alipayClient=new DefaultAlipayClient(aliPayConfig.getGatewayUrl(),aliPayConfig.getAppid(),aliPayConfig.getAppPrivateKey(),"json",aliPayConfig.getCharset(),aliPayConfig.getAlipayPublicKey(),aliPayConfig.getSigntype());//初始化AlipayClient
            AlipayTradeWapPayRequest alipayRequest=new AlipayTradeWapPayRequest();//初始化AlipayTradeWapPayRequest,注意是手机网站支付
            AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
            model.setOutTradeNo(alipayOrder.getOut_trade_no());
            model.setSubject(subject);
            model.setTotalAmount(alipayOrder.getTotal_amount().toString());
            model.setProductCode("QUICK_WAP_WAY");
            alipayRequest.setBizModel(model);
            alipayRequest.setReturnUrl(aliPayConfig.getReturnUrl());
            alipayRequest.setNotifyUrl(aliPayConfig.getNotifyUrl());//给alipayRequest配置必要参数
            //alipayRequest.putOtherTextParam("app_auth_token", alipayToken);
            //以上注释掉的是和授权有关,暂时用不到
            logger.info("subject:{}",model.getSubject());
            logger.info("totalamount:{}",model.getTotalAmount());
            logger.info("outtradeno:{}",model.getOutTradeNo());
            String form="";
            try{
     
                form=alipayClient.pageExecute(alipayRequest).getBody();//执行请求
            }catch (AlipayApiException e){
     
                e.printStackTrace();
            }
            map.put("form",form);//返回的form还需要前端去请求,请求之后就可以跳到支付宝支付界面了,之后的事情就是在支付宝里进行的了
            return ResponseJsonUtil.returnJson(map, BusinessConstants.SERVICE_SUCCESS_MSG, PsiInfo.OK.code);
        }catch (Exception e){
     
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    BusinessConstants.AliPay_ORDER_CREATE_FAIL_CODE, BusinessConstants.AliPay_ORDER_CREATE_FAIL, e);
        }
        return ResponseJsonUtil.returnJson(map, BusinessConstants.AliPay_ORDER_CREATE_FAIL, PsiInfo.ERROR.code);
    }

支付宝支付之后,我们如何获取成功或者失败信息呢?这时候就需要支付宝回调,回调的两个接口已经在application.yml配置好了,现在需要写这两个接口。一个是异步通知接口,以它为准,在接口里修改订单状态等,另一个是同步回调地址,不以它为准,用来跳转到支付成功或失败的页面。

异步回调地址

/**
     * 支付宝支付成功后.异步请求该接口,修改订单状态,以这个接口为准
     * 不直接调用,支付宝调用
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping(value="/notifyurl",method=RequestMethod.POST)
    @ResponseBody
    public String notify(HttpServletRequest request,HttpServletResponse response) throws IOException{
     
        Map<String,String[]> aliParams=request.getParameterMap();
        Map<String,String> conversionParams=new HashMap<>();
        for(Iterator<String> iter=aliParams.keySet().iterator();iter.hasNext();){
     
            String key=iter.next();
            String[] values=aliParams.get(key);
            String valueStr="";
            for(int i=0;i<values.length;i++){
     
                valueStr=(i==values.length-1)?valueStr+values[i]:valueStr+values[i]+",";
            }
            conversionParams.put(key,valueStr);//参考了一些博客和官方文档的代码
        }
        String status=aliPayService.notify(conversionParams);
        return status;
    }

重点是aliPayService.notify方法

 @Override
    public String notify(Map<String,String> conversionParams){
     
        boolean signVerified=false;
        try{
     
            signVerified=AlipaySignature.rsaCheckV1(conversionParams,aliPayConfig.getAlipayPublicKey(),aliPayConfig.getCharset(),aliPayConfig.getSigntype());
        }catch (AlipayApiException e){
     
            e.printStackTrace();
        }
        if(signVerified){
     

            String appId=conversionParams.get("app_id");//支付宝分配给开发者的应用Id
            String notifyTime=conversionParams.get("notify_time");//通知时间:yyyy-MM-dd HH:mm:ss
            String gmtCreate=conversionParams.get("gmt_create");//交易创建时间:yyyy-MM-dd HH:mm:ss
            String gmtPayment=conversionParams.get("gmt_payment");//交易付款时间
            String gmtRefund=conversionParams.get("gmt_refund");//交易退款时间
            String gmtClose=conversionParams.get("gmt_close");//交易结束时间
            String tradeNo=conversionParams.get("trade_no");//支付宝的交易号
            String outTradeNo = conversionParams.get("out_trade_no");//获取商户之前传给支付宝的订单号(商户系统的唯一订单号)
            String outBizNo=conversionParams.get("out_biz_no");//商户业务号(商户业务ID,主要是退款通知中返回退款申请的流水号)
            String buyerLogonId=conversionParams.get("buyer_logon_id");//买家支付宝账号
            String sellerId=conversionParams.get("seller_id");//卖家支付宝用户号
            String sellerEmail=conversionParams.get("seller_email");//卖家支付宝账号
            String totalAmount=conversionParams.get("total_amount");//订单金额:本次交易支付的订单金额,单位为人民币(元)
            String receiptAmount=conversionParams.get("receipt_amount");//实收金额:商家在交易中实际收到的款项,单位为元
            String invoiceAmount=conversionParams.get("invoice_amount");//开票金额:用户在交易中支付的可开发票的金额
            String buyerPayAmount=conversionParams.get("buyer_pay_amount");//付款金额:用户在交易中支付的金额
            String tradeStatus = conversionParams.get("trade_status");// 获取交易状态

//            String outTradeNo=conversionParams.get("out_trade_no");
//            String tradeNo=conversionParams.get("trade_no");
//            String tradeStatus=conversionParams.get("trade_status");
//            String totalAmount=conversionParams.get("total_amount");
            AlipayOrder alipayOrder=orderService.selectAlipayOrderByOutTradeNo(outTradeNo);
            if(alipayOrder!=null&&totalAmount.equals(alipayOrder.getTotal_amount().toString())){
     
                if(appId!=null){
     
                    alipayOrder.setApp_id(appId);
                }
                if(notifyTime!=null){
     
                    alipayOrder.setNotify_time(notifyTime);
                }
                if(gmtClose!=null){
     
                    alipayOrder.setGmt_close_time(gmtClose);
                }
                if(gmtCreate!=null){
     
                    alipayOrder.setGmt_create_time(gmtCreate);
                }
                if(gmtPayment!=null){
     
                    alipayOrder.setGmt_payment_time(gmtPayment);
                }
                if(gmtRefund!=null){
     
                    alipayOrder.setGmt_refund_time(gmtRefund);
                }
                if(buyerLogonId!=null){
     
                    alipayOrder.setBuyer_logon_id(buyerLogonId);
                }
                if(outBizNo!=null){
     
                    alipayOrder.setOut_biz_no(outBizNo);
                }
                if(sellerId!=null){
     
                    alipayOrder.setSeller_id(sellerId);
                }
                if(sellerEmail!=null){
     
                    alipayOrder.setSeller_email(sellerEmail);
                }
                if(receiptAmount!=null){
     
                    alipayOrder.setReceipt_amount(new BigDecimal(Double.parseDouble(receiptAmount)));
                }
                if(invoiceAmount!=null){
     
                    alipayOrder.setInvoice_amount(new BigDecimal(Double.parseDouble(invoiceAmount)));
                }
                if(buyerPayAmount!=null){
     
                    alipayOrder.setBuyerpay_amount(new BigDecimal(Double.parseDouble(buyerPayAmount)));
                }
                if(totalAmount!=null){
     
                    alipayOrder.setTotal_amount(new BigDecimal(Double.parseDouble(totalAmount)));
                }
                if(tradeNo!=null){
     
                    alipayOrder.setTrade_no(tradeNo);
                }
                if(outTradeNo!=null){
     
                    alipayOrder.setOut_trade_no(outTradeNo);
                }

                switch (tradeStatus) // 判断交易结果
                {
     
                    case "TRADE_FINISHED": // 交易结束并不可退款
                        alipayOrder.setStatus((byte) 3);
                        break;
                    case "TRADE_SUCCESS": // 交易支付成功
                        alipayOrder.setStatus((byte) 2);
                        break;
                    case "TRADE_CLOSED": // 未付款交易超时关闭或支付完成后全额退款
                        alipayOrder.setStatus((byte) 1);
                        break;
                    case "WAIT_BUYER_PAY": // 交易创建并等待买家付款
                        alipayOrder.setStatus((byte) 0);
                        break;
                    default:
                        break;
                }
                int returnResult=orderService.updateByExample(alipayOrder);
                if(gmtRefund==null){
     //这里有一个小坑,在退款成功之后也会调用这个异步通知接口。支付成功后我们会将订单状态由待付款改为待发货,而退款成功之后订单状态不会再改变,改变的是退款单的状态,因此这里由gmtRefund即退款时间是否为空来判断是退款成功还是支付成功
                    if(tradeStatus.equals("TRADE_SUCCESS")&&returnResult>0){
     
                        if(orderService.updateOrderByOutTradeNo(outTradeNo, OrderConstants.PAY_TYPE_ALIPAY)>0){
     //修改订单状态,OrderConstants.PAY_TYPE_ALIPAY为支付方式
                            return "success";
                        }else{
     
                            return "fail";
                        }

                    }else{
     
                        return "fail";
                    }
                }else{
     
                    if(tradeStatus.equals("TRADE_SUCCESS")&&returnResult>0){
     
                        if(orderService.updateOrderModifyTime(outTradeNo)>0) {
     
                            return "success";
                        }
                    }else{
     
                        return "fail";
                    }
                }
            }else{
     
                return "fail";
            }
        }else{
     
            return "fail";
        }
        return "fail";
    }

同步通知接口

 /**
     * 支付宝支付成功之后,同步通知接口,跳转回支付成功或者支付失败页面,但不修改订单状态,不以这个为准
     * 不直接调用,支付宝调用
     * @param request
     * @param response
     * @param outTradeNo
     */
    @RequestMapping(value="/returnurl",method=RequestMethod.GET)
    public void returnUrl(HttpServletRequest request, HttpServletResponse response,String outTradeNo){
     
        Map<String,String> params = new HashMap<>();
        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] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        try{
     
            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");
            boolean verify_result = AlipaySignature.rsaCheckV1(params, aliPayConfig.getAlipayPublicKey(), aliPayConfig.getCharset(), "RSA2");
            if(verify_result){
     
                response.sendRedirect("https://xxxxxxxxxxx#/successPay");//跳到支付成功页面
            }else{
     
                response.sendRedirect("https://xxxxxxxxxxxxx/#/errorPay");//跳到支付失败页面
            }
        }catch (Exception e){
     

        }
    }

支付宝退款接口

/**
     * 支付宝退款接口
     * @param id,为退款单的id
     * @return
     */
    @PostMapping(value = "/refund")
    public String refund(@RequestParam Long id){
     
        Map<String, Object> map = new HashMap<>();
        AfterSale afterSale=afterSaleService.selectById(id);//跟自己业务有关,根据id获取退款单
        if(afterSale==null){
     
            return ResponseJsonUtil.returnJson(map, BusinessConstants.AFTER_SALE_IS_NULL, PsiInfo.ERROR.code);
        }
        BigDecimal totalAmount=afterSale.getTotal_amount();//退款金额
        String alipayOutTradeNo=orderService.selectAlipayOutTradeNoByOrderNo(afterSale.getOrderNo());//根据原订单号获取支付订单号
        String alipayTradeNo=orderService.selectAlipayTradeNoByOrderNo(afterSale.getOrderNo());//获取支付宝交易号
        try{
     
//            Long sellerId=afterSale.getSellerId();
//            String alipayToken=storeService.getAlipayTokenByMemberId(sellerId);
//            if(alipayToken==null){
     
//                return ResponseJsonUtil.returnJson(map, BusinessConstants.AliPay_TOKEN_NULL, PsiInfo.ERROR.code);
//            }
            //与授权有关代码
            AlipayClient alipayClient=new DefaultAlipayClient(aliPayConfig.getGatewayUrl(),aliPayConfig.getAppid(),aliPayConfig.getAppPrivateKey(),"json",aliPayConfig.getCharset(),aliPayConfig.getAlipayPublicKey(),aliPayConfig.getSigntype());
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            AlipayTradeRefundModel model=new AlipayTradeRefundModel();
            model.setOutTradeNo(alipayOutTradeNo);
            model.setTradeNo(alipayTradeNo);
            model.setRefundAmount(totalAmount.toString());
            model.setOutRequestNo(CreateOrderNo.createRefundNo());//随机退款流水号
            request.setBizModel(model);
//            request.putOtherTextParam("app_auth_token", alipayToken);授权相关代码
            try{
     
                AlipayTradeRefundResponse alipay_response =alipayClient.execute(request);
                logger.info("alipay_response的内容是:{}",alipay_response.getBody());
                if(alipay_response.getFundChange()==null){
     
                    map.put("result","退款失败,请重试!");
                }else if(alipay_response.getFundChange().equals("Y")){
     
                    map.put("result","退款成功!");
                }else{
     
                    map.put("result","退款失败,请重试!");
                }//退款成功与否根据alipay_response.getFundChange()是否为Y来判断
                map.put("form",alipay_response.getBody());
            }catch (AlipayApiException e){
     
                e.printStackTrace();
            }

            return ResponseJsonUtil.returnJson(map, BusinessConstants.SERVICE_SUCCESS_MSG, PsiInfo.OK.code);
        }catch (Exception e){
     
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    BusinessConstants.AliPay_ORDER_REFUND_FAIL_CODE, BusinessConstants.AliPay_ORDER_REFUND_FAIL, e);
        }
        return ResponseJsonUtil.returnJson(map, BusinessConstants.AliPay_ORDER_REFUND_FAIL, PsiInfo.ERROR.code);
    }

到此,支付所必需的几个接口介绍完了。接下来,我们要做和第三方授权有关的事情。

支付宝授权

为什么要做这个第三方授权呢?根据刚才的代码,在代码里获取配置好的appid、appPrivateKey、alipayPublicKey,根据这些支付宝才能识别支付的收款方,也就是卖家。对于我们平台,需要将支付金额直接支付给卖家,那就不能直接获取配置的appid、appPrivateKey、alipayPublicKey,因为这些并不是卖家的。为了解决这个问题,开始考虑过每个卖家注册的时候填这些信息,存入数据库,在付款的时候根据sellerid获取这些,进而可以达到付款给卖家的目的,但是这个方法对于卖家操作比较复杂,并且appPrivateKey、alipayPublicKey都很长,存入数据库会让数据库十分臃肿,因而不可行。查找蚂蚁金服务开发文档,找到一种第三方授权的方式,可以让卖家支付宝授权给平台,平台即可代替第三方完成收账、退款等功能,卖家所做的只需要同意授权、生成授权码存入数据库,在支付、退款的时候提取出授权码即可识别要授权的第三方,对于卖家只需一键授权,十分方便。相关的文档如下:https://docs.open.alipay.com/20160728150111277227/intro 。

生成支付宝授权AppAuthCode接口

/**
     * 集团、店主生成支付宝授权AppAuthCode的接口,调用之后调用生成支付宝授权码AppAuthToken的接口,一键生成授权码
     * @param httpRequest
     * @param httpResponse
     * @return
     */
    @GetMapping(value = "/createAppAuthCode")
    public Object quickCreateAppAuthToken(HttpServletRequest httpRequest, HttpServletResponse httpResponse){
     
        Map<String,Object> map = new HashMap<>();
        Member member = userService.checkToken(httpRequest);
        map.put("memberId",member.getId());
        map.put("url","https://openauth.alipay.com/oauth2/appToAppAuth.htm?app_id=服务商appid&redirect_uri=https://xxxxxxxxxxxxx/alipay/createAppAuthToken");
        return ResponseJsonUtil.returnJson(map, BusinessConstants.SERVICE_SUCCESS_MSG, PsiInfo.OK.code);
    }

还记得之前注册应用的时候有一项授权回调地址吗?
电商平台接入手机支付宝支付(服务商授权模式,可直接付款给卖家)_第6张图片
授权回调地址要和redirect_uri的值,也就是https://xxxxxxxxxxxxx/alipay/createAppAuthToken保持一致,这里直接设置为我们的接口,并且需要是一个外网可以访问的接口,接下来会介绍这个接口。这里获取了memberId,是需要在生成授权码时传这个参数,根据这个参数将授权码插入到数据库对应位置。这里需要前端拼接一下,将返回的结果拼接成一个url并请求,即为请求createAppAuthToken接口。

生成支付宝授权码AppAuthToken的接口

/**
     * 生成支付宝授权码AppAuthToken的接口,在生成AppAuthCode的接口/alipay/createAppAuthCode已经被调用,无需再次调用,调用之后重定向回授权界面
     * @param memberId
     * @param app_id
     * @param source
     * @param app_auth_code
     * @param httprequest
     * @param httpResponse
     */
    @GetMapping(value = "/createAppAuthToken")
    public void createAppAuthToken(@Param("memberId") Long memberId,
                                   @Param("app_id") String app_id,
                                   @Param("source") String source,
                                   @Param("app_auth_code") String app_auth_code,
                                   HttpServletRequest httprequest,
                                   HttpServletResponse httpResponse){
     
        Map<String, Object> map = new HashMap<>();
        AlipayClient alipayClient=new DefaultAlipayClient(aliPayConfig.getGatewayUrl(),aliPayConfig.getAppid(),aliPayConfig.getAppPrivateKey(),"json",aliPayConfig.getCharset(),aliPayConfig.getAlipayPublicKey(),aliPayConfig.getSigntype());
        AlipayOpenAuthTokenAppRequest request = new AlipayOpenAuthTokenAppRequest();
        request.setBizContent("{" +
                "    \"grant_type\":\"authorization_code\"," +
                "    \"code\":"+"\""+app_auth_code+"\""+
                "  }");
        try{
     
            AlipayOpenAuthTokenAppResponse response = alipayClient.execute(request);
            JSONObject jsonObject=(JSONObject)(new JSONParser().parse(response.getBody()));
            Object token_app_response=jsonObject.get("alipay_open_auth_token_app_response");
            JSONObject token_app_response_jsonObject=(JSONObject)(new JSONParser().parse(token_app_response.toString()));
            Object final_app_auth_token=token_app_response_jsonObject.get("app_auth_token");
            Member member=userService.getUserById(memberId);
            Store store=storeService.getStoresById(member.getStoreId());
            if(store.getAlipayToken()!=null){
     
                throw new RuntimeException("已经授权,无需再次授权!");
            }
            store.setAlipayToken(final_app_auth_token.toString());
            String token = member.getPhone();
            Cookie cookie = new Cookie(BusinessConstants.TOKEN,  token);
            cookie.setPath("/");
            cookie.setMaxAge(BusinessConstants.COOKIE_MAX_AGE);
            httpResponse.addCookie(cookie);//将登陆cookie存入httpresponse,可以在重定向的时候回到原界面,否则要重新登陆
            if(storeService.updateStoreInfo(store)>0){
     
                httpResponse.sendRedirect("https:///xxxxxxxxxxxx//#/weixinaliPay");
            }else{
     
                httpResponse.sendRedirect("https://xxxxxxxxxxxx/#/weixinaliPay");//无论授权成功与否都跳回到原授权界面
            }
        }catch (Exception e){
     
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    BusinessConstants.AliPay_TOKEN_CREATE_FAIL_CODE, BusinessConstants.AliPay_TOKEN_CREATE_FAIL, e);
        }
    }

判断是否授权接口

/**
     * 判断支付宝是否已经授权的接口
     * @param httprequest
     * @return
     */
    @GetMapping(value = "/ifAuthorized")
    public Object ifAuthorized(HttpServletRequest httprequest){
     
        Map<String, Object> map = new HashMap<>();
        Member member = userService.checkToken(httprequest);
        if(member==null){
     
            return ResponseJsonUtil.returnJson(map, BusinessConstants.NON_LOGIN_STATUS_ERROR, PsiInfo.ERROR.code);
        }
        Long storeId=member.getStoreId();
        Store store=storeService.getStoresById(storeId);
        if(store.getAlipayToken()!=null){
     
            map.put("result","Y");
        }else{
     
            map.put("result","N");
        }
        return ResponseJsonUtil.returnJson(map, BusinessConstants.SERVICE_SUCCESS_MSG, PsiInfo.OK.code);
    }

每次到授权界面,即调用这个接口,根据这个接口判断是否授权,前端根据此显示授权健暴露与否。如果授权成功返回,即显示已授权。授权成功之后,之前的代码

request.putOtherTextParam("app_auth_token", alipayToken);

就有了意义,授权之后,将直接支付给被授权的第三方,appid、appPrivateKey、alipayPublicKey还使用原先配置的服务商的。

后记

大功告成,写的略有点乱。。希望读者能看懂吧哈哈,有什么不懂的可以给我留言。

你可能感兴趣的:(java)