提示:支付宝相对于微信支付更人性化,且细节做得更好。


Java对接第三方支付渠道之支付宝支付

  • 一、前期准备工作
  • 二、导入依赖
  • 三、书写配置类
  • 四、书写配置文件
  • 五、调用相关支付接口
  • 1.流程图
  • 2.创建支付
  • 3.支付通知
  • 4.查询支付
  • 5.取消支付
  • 总结



一、前期准备工作

支付宝支付分为正式环境和沙箱环境,我这里使用的是正式环境。 沙箱环境和正式环境差距不是很大,唯一的差距就是正式环境需要营业执照。沙箱环境就可以很好避免这个问题。

  1. 创建应用
  2. 绑定应⽤
  3. 配置秘钥
  4. 上线应⽤
  5. 签约功能

官方API文档地址: https://opendocs.alipay.com/open/270/01didh?ref=api


二、导入依赖

<!--支付宝sdk-->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.23.0.ALL</version>
        </dependency>

三、书写配置类

/**
 * description:支付宝支付配置类
 * author:maozl
 * date:2022/8/1
 */
@Configuration
@PropertySource("classpath:alipay.properties") //读取配置文件
@ConfigurationProperties(prefix="alipay") //读取wxpay节点
@Data //使用set方法将alipay节点中的值填充到当前类的属性中
@Slf4j
public class AliPayClientConfig {

    /**
     * APPID
     */
    private String appId;

    /**
     * 商户PID
     */
    private String sellerId;

    /**
     * 支付宝网关
     */
    private String gatewayUrl;

    /**
     * 商户私钥
     */
    private String merchantPrivateKey;

    /**
     * 支付宝公钥
     */
    private String aliPayPublicKey;

    /**
     * 接口加密秘钥
     */
    private String contentKey;

    /**
     * 页面跳转同步通知页面路径
     */
    private String returnUrl;

    /**
     * 回调地址
     */
    private String notifyUrl;

    @Bean
    public AlipayClient alipayClient() throws AlipayApiException {

        AlipayConfig alipayConfig=new AlipayConfig();
        //设置appId
        alipayConfig.setAppId(appId);
        //设置商户私钥
        alipayConfig.setPrivateKey(merchantPrivateKey);
        //设置支付宝公钥
        alipayConfig.setAlipayPublicKey(aliPayPublicKey);
        //设置支付宝网关
        alipayConfig.setServerUrl(gatewayUrl);
        //设置请求格式,固定值json.
        alipayConfig.setFormat(AlipayConstants.FORMAT_JSON);
        //设置字符集
        alipayConfig.setCharset(AlipayConstants.CHARSET_UTF8);
        //设置签名类型
        alipayConfig.setSignType(AlipayConstants.SIGN_TYPE_RSA2);
        //构造client
        AlipayClient alipayClient=new DefaultAlipayClient(alipayConfig);
        return alipayClient;
    }

}

四、书写配置文件

# 支付宝支付相关参数

# 应用ID,你的APPID
alipay.app-id=

# 商户PID
alipay.seller-id=

# 支付宝网关
alipay.gateway-url=

# 商户私钥
alipay.merchant-private-key=

# 支付宝公钥
aliPay.aliPay-public-key=

# 接口内容加密秘钥,对称秘钥
alipay.content-key=

# 页面跳转同步通知页面路径
alipay.return-url=

# 支付宝支付成功回调地址
alipay.notify-url=

五、调用相关支付接口

1.流程图

java 支付宝js请求支付宝 java接入支付宝_java 支付宝js请求支付宝

2.创建支付

https://opendocs.alipay.com/apis/028r8t?scene=22

/**
     * 发起支付
     * @param orderNo
     * @param uid
     * @return
     */
    @Override
    public String createPay(String orderNo, String uid) {

        //根据orderNo获取orderInfo
        OrderInfo orderInfo = orderInfoService.getOne(new LambdaQueryWrapper<OrderInfo>()
                .eq(OrderInfo::getOrderNo, orderNo)
                .eq(OrderInfo::getUid, uid));

        if (Objects.isNull(orderInfo)){
            throw new ServiceErrorException(ResultCode.ERROR, "发起支付请求失败 - 订单不存在");
        }

        //更新订单的支付类型
        orderInfoService.updatePayTypeByOrderNo(orderInfo.getOrderNo(), PayType.ALIPAY);

        //创建支付宝请求对象
        AlipayTradePagePayRequest request=new AlipayTradePagePayRequest();
        //数据
        AlipayTradePagePayModel bizModel=new AlipayTradePagePayModel();
        bizModel.setOutTradeNo(orderInfo.getOrderNo());
        //单位是元
        bizModel.setTotalAmount(orderInfo.getTotalFee().toString());
        bizModel.setSubject(orderInfo.getTitle());
        //默认的
        bizModel.setProductCode("FAST_INSTANT_TRADE_PAY");
        request.setBizModel(bizModel);

        request.setNotifyUrl(aliPayClientConfig.getNotifyUrl());
        //用户支付后支付宝会以GET方法请求returnUrl,并且携带out_trade_no,trade_no,total_amount等参数.
        request.setReturnUrl(aliPayClientConfig.getReturnUrl());

        AlipayTradePagePayResponse response=null;
        try{
            //完成签名并执行请求
            response=alipayClient.pageExecute(request);
            if(response.isSuccess()){
                log.debug("支付宝支付 - 调用成功");
                return response.getBody();
            }
            else{
                log.error("支付宝支付 - 调用失败");
                log.error(response.getMsg());
                return null;
            }
        }
        catch(AlipayApiException e){
            log.error("支付宝支付 - 创建支付交易失败");
            throw new ServiceErrorException(ResultCode.ERROR, "支付宝支付 - 创建支付交易失败");
        }
    }

3.支付通知

https://opendocs.alipay.com/open/270/105902

/**
     * 支付成功回调函数
     * @param params
     * @return
     */
    @PostMapping("/callback")
    public String callback(@RequestParam Map<String,String> params){

        log.debug("收到支付宝回调");

        try{
            //验签
            boolean signVerified = AlipaySignature.rsaCheckV1(params,
                    aliPayClientConfig.getAliPayPublicKey(),
                    AlipayConstants.CHARSET_UTF8,
                    AlipayConstants.SIGN_TYPE_RSA2) ; //调用SDK验证签名

            //验签成功
            if(signVerified){
                log.debug("验签成功");

                //1.商家需要验证该通知数据中的 out_trade_no 是否为商家系统中创建的订单号
                String orderNo = params.get("out_trade_no");
                OrderInfo orderInfo = orderInfoService.getOrderByOrderNo(orderNo);
                if (orderInfo == null){
                    log.error("订单不存在");
                    return "failure";
                }

                //2.判断 total_amount 是否确实为该订单的实际金额(即商家订单创建时的金额)
                String totalAmount = params.get("total_amount");
                if (!totalAmount.equals(orderInfo.getTotalFee().toString())){
                    log.error("金额校验失败");
                    return "failure";
                }

                //3.校验通知中的 seller_id(或者 seller_email ) 是否为 out_trade_no 这笔单据的对应的操作方
                String sellerId = params.get("seller_id");
                if (!aliPayClientConfig.getSellerId().equals(sellerId)){
                    log.error("商家PID校验失败");
                    return "failure";
                }

                //4.验证 app_id 是否为该商家本身
                String appId = params.get("app_id");
                if (!aliPayClientConfig.getAppId().equals(appId)){
                    log.error("应用APPID校验失败");
                    return "failure";
                }

                //5.在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,
                // 支付宝才会认定为买家付款成功。
                String tradeStatus = params.get("trade_status");
                if (!"TRADE_SUCCESS".equals(tradeStatus)){
                    log.error("支付未成功");
                    return "failure";
                }

                //支付成功后 - 处理订单
                aliPayService.processOrder(params);

                //除了success外其他返回均认为是失败
                return "success";
            }else{
                log.error("验签失败");
                return "failure";
            }
        }
        catch(AlipayApiException e){
            log.error("验签异常");
            e.printStackTrace();
            return "failure";
        }
    }

4.查询支付

https://opendocs.alipay.com/open/028woa

/**
     * 查询订单
     * @param orderNo
     * @return
     */
    @Override
    public boolean query(String orderNo) {

        //请求
        AlipayTradeQueryRequest request=new AlipayTradeQueryRequest();
        //数据
        AlipayTradeQueryModel bizModel=new AlipayTradeQueryModel();
        bizModel.setOutTradeNo(orderNo);
        request.setBizModel(bizModel);
        try{
            //完成签名并执行请求
            AlipayTradeQueryResponse response=alipayClient.execute(request);
            if(response.isSuccess()){
                log.debug("查询订单{}成功",orderNo);

                Gson gson = new Gson();
                HashMap<String,Object> resultMap=gson.fromJson(response.getBody(),HashMap.class);

                String tradeStatus = (String) resultMap.get("trade_status");

                if (tradeStatus.equals("TRADE_SUCCESS")){ //订单支付已完成
                    log.info("调用订单查询接口 - 订单已支付完成");
                    return true;
                }
                return false;
            }
            else{
                log.error("查询订单{}失败,响应数据是{}.",orderNo,response.getBody());
                return false;
            }
        }
        catch(AlipayApiException e){
            log.error("查询订单{}异常",orderNo);
            return false;
        }
    }

5.取消支付

https://opendocs.alipay.com/open/028wob

/**
     * 支付宝取消订单接口
     * @param orderNo
     */
    @Override
    public void closeOrder(String orderNo) {

        //请求
        AlipayTradeCloseRequest request=new AlipayTradeCloseRequest();
        //数据
        AlipayTradeCloseModel bizModel=new AlipayTradeCloseModel();
        bizModel.setOutTradeNo(orderNo);
        request.setBizModel(bizModel);
        try{
            //完成签名并执行请求
            AlipayTradeCloseResponse response=alipayClient.execute(request);
            if(response.isSuccess()){
                log.debug("订单:{}取消成功",orderNo);
            }
            else{
                log.debug("订单:{}未创建,因此也可认为本次取消成功.",orderNo);
            }
        }
        catch(AlipayApiException e){
            log.error("订单{}取消异常",orderNo);
            throw new ServiceErrorException(ResultCode.ERROR, "订单取消异常");
        }
    }

总结

支付回调中可能会存在验签一直失败的问题,出现这个问题的可能是公钥使用出错,验签使用的是支付宝公钥而不是应用公钥,如果开发者在开发过程中,出现验证一直不通过的问题可以尝试检查一下 以上就是就是全部内容,本文仅仅简单介绍了支付宝支付的部分API的使用,还有退款以及账单等相关操作后续使用到了会继续更新。