Java支付宝支付

目录

前言

代码实现

1、yaml配置

2、前端唤醒支付宝支付controller

3、前端唤醒支付宝支付controller传参

4、前端唤醒支付宝支付controller返回参数

5、前端唤醒微信支付service具体实现

6、常量配置

7、支付宝支付工具类

8、支付宝支付回调

9、解析回调参数


前言

支付宝开放平台

部分代码同Java微信支付_不如自成宇宙-CSDN博客 

代码实现

1、yaml配置


#支付宝配置
alipay:
  protocol: https
  gatewayHost: openapi.alipay.com
  signType: RSA2
  app-id: xxxxxxxxxxxx
  public-key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  private-key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  #订单支付回调地址
  orderPayNotifyUrl: https://xx.xxxxxxx.com/alipay/callback

2、前端唤醒支付宝支付controller

    @PostMapping(value = "/alipay")
    @ApiOperation("支付宝支付")
    @ApiImplicitParam(paramType = Constants.HEADER, dataType = Constants.STRING, name = Constants.AUTHORIZATION, value = "授权token", required = true)
    public Result<OrderAlipayPayVO> alipay(@Valid @RequestBody OrderPayDTO params) throws Exception {
        OrderAlipayPayVO orderAlipayPayVO = orderPayService.alipayPay(params);
        return Result.ok(orderAlipayPayVO);
    }

3、前端唤醒支付宝支付controller传参

@Data
@Accessors(chain = true)
@ApiModel("订单支付")
public class OrderPayDTO {

    @ApiModelProperty(value = "订单id", required = true)
    @NotNull(message = "订单id不能为空")
    private Long orderId;

    @ApiModelProperty(value = "下单用户终端 1.app 2.微信小程序", required = true)
    @NotNull(message = "下单用户终端不能为空")
    private Integer terminal;

    @ApiModelProperty(value = "是否部分支付", required = true)
    @NotNull(message = "是否部分支付不能为空")
    private Boolean partPay;

    @ApiModelProperty(value = "部分支付金额,部分支付时必传", required = false)
    private BigDecimal payPrice;

}

4、前端唤醒支付宝支付controller返回参数

@Data
@ApiModel(value = "订单支付宝支付返回")
public class OrderAlipayPayVO {

    @ApiModelProperty(value = "支付流水id")
    private Long id;

    @ApiModelProperty(value = "支付流水号")
    private String payNo;

    @ApiModelProperty(value = "支付金额")
    private BigDecimal payPrice;

    @ApiModelProperty(value = "支付唤醒参数")
    private String payData;

}

5、前端唤醒微信支付service具体实现

    /**
     * 支付宝支付
     *
     * @param params
     */
    @Transactional(rollbackFor = Exception.class)
    public OrderAlipayPayVO alipayPay(OrderPayDTO params) throws Exception{
        //自己的业务逻辑:创建支付流水
        OrderPay orderPay = createOrderPay(params, PayMethodCode.ALIPAY_PAY.getCode());
        
        String payResult = AlipayUtil.createAppOrder("购买", orderPay.getPayNo(), orderPay.getPayPrice(), alipayProperties.getCourseOrderPayNotifyUrl());

        OrderAlipayPayVO alipayPayVO = new OrderAlipayPayVO();
        alipayPayVO.setId(orderPay.getId());
        alipayPayVO.setPayNo(orderPay.getPayNo());
        alipayPayVO.setPayPrice(orderPay.getPayPrice());
        alipayPayVO.setPayData(payResult);
        return alipayPayVO;
    }

6、常量配置

/**
 * 支付宝配置
 *
 * @author: cyl
 * @date: 2021-04-19 15:47
 */
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "alipay")
public class AlipayProperties {

    private String protocol;

    private String gatewayHost;

    private String signType;

    private String appId;

    private String privateKey;

    private String publicKey;

    private String courseOrderPayNotifyUrl;

}

7、支付宝支付工具类

package com.lw.order.util;

import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.payment.app.Client;
import com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse;
import com.lw.order.constant.AlipayPayConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Map;

/**
 * 支付宝支付,需初始化AlipayConfig
 *
 * @author: cyl
 * @date: 2021-04-19 21:03
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class AlipayUtil {



    /**
     * 创建app支付订单
     *
     * @param subject     订单描述
     * @param outTradeNo  订单编号
     * @param totalAmount 订单金额,字符串,单位元,精确到小数2位
     * @param notifyUrl   回调地址
     * @return 支付字符串
     * @throws Exception 创建订单异常
     */
    public static String createAppOrder(String subject, String outTradeNo, BigDecimal totalAmount, String notifyUrl)
            throws Exception {
        Client client = Factory.Payment.App().asyncNotify(notifyUrl);
        return client.pay(subject, outTradeNo, String.valueOf(totalAmount)).getBody();
    }

    /**
     * 创建PC支付订单
     *
     * @param subject     订单描述
     * @param outTradeNo  订单编号
     * @param totalAmount 订单金额,字符串,单位元,精确到小数2位
     * @param notifyUrl   回调地址
     * @return 支付字符串
     * @throws Exception 创建订单异常
     */
    public static String createPageOrder(String subject, String outTradeNo, double totalAmount, String notifyUrl)
            throws Exception {
        return Factory.Payment.Page().asyncNotify(notifyUrl).pay(subject, outTradeNo, String.valueOf(totalAmount), "").getBody();
    }

    /**
     * 创建PC二维码支付订单
     *
     * @param subject     订单描述
     * @param outTradeNo  订单编号
     * @param totalAmount 订单金额,字符串,单位元,精确到小数2位
     * @param notifyUrl   回调地址
     * @return 支付二维码链接
     * @throws Exception 创建订单异常
     */
    public static String createPageCodeOrder(String subject, String outTradeNo, double totalAmount, String notifyUrl)
            throws Exception {
        return Factory.Payment.FaceToFace().asyncNotify(notifyUrl).preCreate(subject, outTradeNo, String.valueOf(totalAmount)).getQrCode();
    }

    /**
     * 创建手机浏览器支付订单
     *
     * @param subject     订单描述
     * @param outTradeNo  订单编号
     * @param totalAmount 订单金额,字符串,单位元,精确到小数2位
     * @param notifyUrl   回调地址
     * @return 支付字符串
     * @throws Exception 创建订单异常
     */
    public static String createWapOrder(String subject, String outTradeNo, double totalAmount, String notifyUrl)
            throws Exception {
        return Factory.Payment.Wap().asyncNotify(notifyUrl).pay(subject, outTradeNo, String.valueOf(totalAmount), "", "").getBody();
    }

    /**
     * 订单申请退款
     *
     * @param outTradeNo   订单编号
     * @param refundAmount 退款金额,字符串,单位元,精确到小数2位
     * @throws Exception 退款异常
     */
    public static void refund(String outTradeNo, double refundAmount, String appId, String privateKey, String publicKey) throws Exception {
        try {
            AlipayTradeRefundResponse refund = Factory.Payment.Common().optional("appId", appId).optional("merchantPrivateKey", privateKey).optional("alipayPublicKey", publicKey)
                    .refund(outTradeNo, String.valueOf(refundAmount));
            if (!AlipayPayConstants.REFUND_CODE.equals(refund.getCode())) {
                throw new IllegalArgumentException(refund.getSubMsg());
            }
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            log.error("支付宝退款异常", e);
            throw e;
        }
    }

    /**
     * 查询订单支付状态
     *
     * @param outTradeNo 订单号
     * @throws Exception 查询异常
     */
    public static boolean tradeQuery(String outTradeNo) throws Exception {
        String status = Factory.Payment.Common().query(outTradeNo).getTradeStatus();
        return AlipayPayConstants.TRADE_SUCCESS.equals(status) || AlipayPayConstants.TRADE_FINISHED.equals(status);
    }

    /**
     * 异步通知校验
     *
     * @param parameters 响应参数
     * @throws Exception 校验异常
     */
    public static boolean verifyNotify(Map<String, String> parameters) throws Exception {
        return Factory.Payment.Common().verifyNotify(parameters);
    }


}

8、支付宝支付回调

@PostMapping(value = "/alipay/callback")
    @ApiOperation(value = "支付宝支付回调", hidden = true)
    public String alipayCallback(HttpServletRequest request) {
        RLock lock = null;
        try {
            Map<String, String> params = requestParam(request);
            boolean signVerified = AlipayUtil.verifyNotify(params);
            if (!signVerified) {
                log.error("支付宝签名验证不通过");
                return AlipayPayConstants.FAILURE;
            }

            log.info("支付宝异步通知参数:{}", params.toString());
            String tradeNo = params.get("out_trade_no");

            //使用redisson获取分布式锁
            lock = redissonClient.getLock(DLockConstants.ALIPAY_OUT_TRADE_NO + tradeNo);
            //尝试加锁,设置等待时间10秒,锁超时时间10秒
            boolean locked = lock.tryLock(10, 10, TimeUnit.SECONDS);
            if (locked) {
                OrderPay orderPay = orderPayService.findByPayNo(tradeNo);
                if (null == orderPay || orderPay.getStatus() != PayStatusCode.WAIT_PAY.getCode()) {
                    log.error("订单不存在或已支付:{}", tradeNo);
                    return AlipayPayConstants.FAILURE;
                }

                String tradeStatus = params.get("trade_status");
                if (!AlipayPayConstants.TRADE_SUCCESS.equals(tradeStatus) && !AlipayPayConstants.TRADE_FINISHED.equals(tradeStatus)) {
                    log.error("订单支付回调状态不通过:{}", tradeNo);
                    return AlipayPayConstants.FAILURE;
                }

                //重新调用支付宝接口查询订单状态
                if (AlipayUtil.tradeQuery(tradeNo)) {
                    orderPayService.paySuccess(orderPay, PayMethodCode.ALIPAY_PAY.getCode(), params.get("trade_no"));
                    return AlipayPayConstants.SUCCESS;
                }

                log.error("支付宝支付回调通知二次校验不通过:{}", tradeNo);
                return AlipayPayConstants.FAILURE;
            }

            log.error("支付宝支付回调通知排队中:{}", tradeNo);
            return AlipayPayConstants.FAILURE;
        } catch (Exception e) {
            log.error("支付宝支付回调处理异常", e);
            return AlipayPayConstants.FAILURE;
        } finally {
            if (null != lock && lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

9、解析回调参数

    /**
     * 解析回调参数
     *
     * @param request
     * @return
     */
    private static Map<String, String> requestParam(HttpServletRequest request) {
        Map<String, String> params = Maps.newHashMap();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
            String valueStr = String.join(",", entry.getValue());
            params.put(entry.getKey(), valueStr);
        }
        return params;
    }

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值