Bootstrap

Java接入支付宝扫码支付

一、适用场景:pc端拉起付款二维码 用户扫码付款(非证书模式下单)

在这里插入图片描述

二、接入准备

1:支付宝-appId
2:支付宝公钥-appPublicKey

(是支付宝公钥,不是应用公钥,拿错会无法拉起支付)

3:支付宝应用私钥-appPrivateKey

三、官方DEMO下载地址

支付宝sdk官方下载地址
https://opendocs.alipay.com/open/270/106291?ref=api

四、代码

1:maven依赖
		<!-- 支付宝支付SDK -->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.9.100.ALL</version>
        </dependency>
2:配置文件


介绍下其他参数

returnUrl:阿里同步通知接口地址—后边会有代码展示
notifyUrl:支付后阿里通知支付状态的接口地址—后边会有代码展示
requestUrl:主要用于支付成功后页面跳转的网站地址(支付宝支付前端会用阿里自己的页面,所以支付成功以后要跳转到自己的页面)

配置类

@ConfigurationProperties(prefix = "alipay")
@Component
@Data
public class AliPayProperties {

    private String appId;
    private String gatewayUrl;
    private String format;
    private String charset;
    private String signType;
    private String returnUrl;
    private String notifyUrl;
    private String appPrivateKey;
    private String appPublicKey;
    private String requestUrl;

    //支付宝支付页面超时时间
    private String overTime;
    }
3:下单接口
//支付宝拉起统一下单
    public Map<String, String> prePay(UserOrders order, String clientIP) {
        log.info("支付宝统一下单接收到请求,下单用户ip :{}", clientIP);
        Map<String, String> map = new HashMap<>();
        AlipayClient alipayClient=new DefaultAlipayClient(properties.getGatewayUrl(),
                properties.getAppId(),properties.getAppPrivateKey(),properties.getFormat(),
                properties.getCharset(),properties.getAppPublicKey(),properties.getSignType()
                );
        try {
            //商户订单号,商户网站订单系统中唯一订单号,必填
            String out_trade_no = new String(order.getOrderNum().getBytes("UTF-8"),"UTF-8");
            //付款金额,必填
            Double payPrice = order.getPayPrice();
            String total_amount = new String(payPrice.toString().getBytes("UTF-8"),"UTF-8");
            //订单名称,必填
            String subject = new String(order.getPackageName().getBytes("UTF-8"),"UTF-8");
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            String encode = URLEncoder.encode(order.getOperatorInfo(), "UTF-8");
            request.setNotifyUrl(properties.getNotifyUrl());
            request.setReturnUrl(properties.getReturnUrl());
            request.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                    + "\"total_amount\":\""+ total_amount +"\","
                    + "\"subject\":\""+ subject +"\","
                    + "\"passback_params\":\""+ encode +"\","
                    + "\"timeout_express\":\""+ properties.getOverTime()+"\","
                    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
            AlipayTradePagePayResponse response = null;
            response = alipayClient.pageExecute(request);


            map.put("success", "true");
            map.put("body", response.getBody());
            map.put("msg", response.getMsg());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return map;
    }
对当前返回的map进行校验返回前端
4:异步回调

controller

@RequestMapping("/ali/notify")
    public String notify(HttpServletRequest request){
        log.info("支付宝异步回调接收到请求!!!");
        Map<String,String> flag = aliPayService.aliPayNotify(request);
        if("success".equals(flag.get("status"))){
         //这块做自己的业务逻辑
      AsyncManager.me().execute(AsyncFactory.updateCourseSignNum(flag.get("courseId")));
        }
        return flag.get("status");
    }

service

public Map<String, String> aliPayNotify(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        try {
            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("UTF-8"), "UTF-8");
                params.put(name, valueStr);
            }
            log.info("alipay支付回调:" + JSON.toJSONString(params));
            boolean flag = AlipaySignature.rsaCertCheckV1(params, properties.getPublicKeyFilePath(), properties.getCharset(), properties.getSignType());
            if (flag) {
                log.info("支付宝回调签名通过");
                //商户订单号
                String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("UTF-8"), "UTF-8");
                //支付宝交易号
                String trade_no = new String(request.getParameter("trade_no").getBytes("UTF-8"), "UTF-8");
                //交易状态
                String trade_status = new String(request.getParameter("trade_status").getBytes("UTF-8"), "UTF-8");
                //订单的金额
                String total_amount = new String(request.getParameter("total_amount").getBytes("UTF-8"), "UTF-8");
                //商户id
                String sellerId = new String(request.getParameter("seller_id").getBytes("UTF-8"), "UTF-8");
                log.info("此次订单金额为==>> {}", total_amount);
                if ("TRADE_FINISHED".equals(trade_status)) {
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                    //如果有做过处理,不执行商户的业务程序
                    log.info("交易finish非success");
                    //注意:
                    //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
                } else if ("TRADE_SUCCESS".equals(trade_status)) {
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                    //如果有做过处理,不执行商户的业务程序
                    //注意:
                    //付款完成后,支付宝系统发送该交易状态通知
                    log.info("交易成功,更新订单状态");
                    OrderInfo orderInfo = orderInfoMapper.selectOrderInfoByOrderNum(out_trade_no);
                    BigDecimal aliPrice = new BigDecimal(total_amount);
                    if (aliPrice.compareTo(orderInfo.getPayPrice()) != 0) {
                        log.info("支付宝返回成交额与当前订单金额不符,返回fail");
                        map.put("status", "fail");
                        return map;
                    }
                    if ("1".equals(orderInfo.getPayStatus())) {
                        //首次回调成功更新订单状态,给学员开课
                        orderInfoService.updateOrderPayStatus(out_trade_no);
                    }
                    map.put("status", "success");
                    map.put("courseId", String.valueOf(orderInfo.getCourseId()));
                    return map;
                }

            } else {
                log.info("异步签名校验有误,返回fail");
                map.put("status", "fail");
                return map;
            }
        } catch (Exception e) {
            e.printStackTrace();
            map.put("status", "fail");
            return map;
        }
        map.put("status", "fail");
        return map;
    }
5:同步回调

controller

@RequestMapping("/ali/return")
    public void aliReturn(HttpServletRequest request, HttpServletResponse response){
        aliPayService.aliReturn(request,response);
    }

service

public void aliReturn(HttpServletRequest request, HttpServletResponse response) {
        try {
            log.info("支付宝同步回调接收到请求");
            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);
            }
            //调用SDK验证签名
            boolean flag = AlipaySignature.rsaCertCheckV1(params, properties.getPublicKeyFilePath(), properties.getCharset(), properties.getSignType());
            if (flag) {
                //商户订单号
                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_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");

                log.info("支付宝同步回调参数 out_trade_no: {} ,trade_no: {}, total_amount : {}", out_trade_no, trade_no, total_amount);
                response.sendRedirect(properties.getRequestUrl());
            } else {
                System.out.println("验签失败");
                response.sendRedirect(properties.getRequestUrl());
            }
        } catch (Exception e) {
            e.printStackTrace();
            try {
                response.sendRedirect(properties.getRequestUrl());
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
;