java app支付宝支付

2022-12-26 14:53:13 浏览数 (2)

一.准备

java接入支付宝需要引入Maven

代码语言:javascript复制
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>${alipay.sdk.version}</version>
</dependency>

二.创建配置类

我是直接把配置放在nacos配置中心上面

代码语言:javascript复制
package com.jieyihua.pay.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * @program: JieYiHua-Cloud
 * @description: 支付宝配置
 * @author: LiYu
 * @create: 2021-08-16 09:35
 **/
@Component
@ConfigurationProperties(prefix = "alipay")
@Data
public class Alipay implements Serializable {
    private static final long serialVersionUID = -582917908416008697L;
    /**
     * 服务地址
     */
    private String serverUrl;
    /**
     * AppId
     */
    private String appId;
    /**
     * 应用私钥
     */
    private String privateKey;
    /**
     * 应用公钥
     */
    private String publicKey;
    /**
     * 支付宝公钥
     */
    private String alipayPublicKey;
    /**
     * 支付宝回调地址
     */
    private String alipayNoticeUrl;
    /**
     * 公钥证书文件路径
     */
    private String certPath;
    /**
     * 公钥证书文件路径
     */
    private String alipayPublicCertPath;
    /**
     * 支付宝根证书文件路径
     */
    private String rootCertPath;
    /**
     * 编码
     */
    private String charset = "UTF-8";
    /**
     * 返回格式
     */
    private String format = "json";
    /**
     * RSA2
     */
    private String signType = "RSA2";

}

3.具体实现

代码语言:javascript复制
package com.jieyihua.pay.model;

import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * @program: JieYiHua-Cloud
 * @description: 支付宝返回结果对应的参数类
 * @author: LiYu
 * @create: 2021-10-14 13:27
 **/
@Data
@Accessors(chain = true)
public class AlipayNotifyParam implements Serializable {
    private String appId;
    /**
     * 支付宝交易凭证号
     */
    private String tradeNo;
    /**
     *  原支付请求的商户订单号
     */
    private String outTradeNo;
    /**
     * 商户业务ID,主要是退款通知中返回退款申请的流水号
     */
    private String outBizNo;
    /**
     * 买家支付宝账号对应的支付宝唯一用户号。以2088开头的纯16位数字
     */
    private String buyerId;
    /**
     * 买家支付宝账号
     */
    private String buyerLogonId;
    /**
     * 卖家支付宝用户号
     */
    private String sellerId;
    /**
     * 卖家支付宝账号
     */
    private String sellerEmail;
    /**
     * 交易目前所处的状态,见交易状态说明
     */
    private String tradeStatus;
    /**
     * 本次交易支付的订单金额
     */
    private BigDecimal totalAmount;
    /**
     * 商家在交易中实际收到的款项
     */
    private BigDecimal receiptAmount;
    /**
     * 用户在交易中支付的金额
     */
    private BigDecimal buyerPayAmount;
    /**
     *  退款通知中,返回总退款金额,单位为元,支持两位小数
     */
    private BigDecimal refundFee;
    /**
     * 商品的标题/交易标题/订单标题/订单关键字等
     */
    private String subject;
    /**
     * 该订单的备注、描述、明细等。对应请求时的body参数,原样通知回来
     */
    private String body;
    /**
     * 该笔交易创建的时间。格式为yyyy-MM-dd HH:mm:ss
     */
    private LocalDateTime gmtCreate;
    /**
     * 该笔交易的买家付款时间。格式为yyyy-MM-dd HH:mm:ss
     */
    private LocalDateTime gmtPayment;
    /**
     * 该笔交易的退款时间。格式为yyyy-MM-dd HH:mm:ss.S
     */
    private LocalDateTime gmtRefund;
    /**
     * 该笔交易结束时间。格式为yyyy-MM-dd HH:mm:ss
     */
    private LocalDateTime gmtClose;
    /**
     * 支付成功的各个渠道金额信息,array
     */
    private String fundBillList;
    /**
     * 公共回传参数,如果请求时传递了该参数,则返回给商户时会在异步通知时将该参数原样返回。
     */
    private String passbackParams;

}
代码语言:javascript复制
/**
 * @program: JieYiHua-Cloud
 * @description: 支付宝接口
 * @author: LiYu
 * @create: 2021-08-16 10:08
 **/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/alipay")
public class AlipayController {
    private final AliPayService aliPayService;

    @ApiOperation("拉起支付")
    @PostMapping("/pullUpPayment")
    public AjaxResult pullUpPayment(@RequestBody PayMoneyReq payMoneyReq) throws AlipayApiException {
        return aliPayService.pullUpPayment(payMoneyReq);
    }

    @ApiOperation("支付宝回调")
    @PostMapping("/notifyParam")
    public String notifyParam(HttpServletRequest request){
        return aliPayService.notifyParam(request);
    }
}
代码语言:javascript复制
public interface AliPayService {
    /**
     * 拉起支付
     * @param payMoneyReq 请求参数
     * @return 签名
     * @throws  AlipayApiException 异常
     */
    AjaxResult pullUpPayment(@RequestBody PayMoneyReq payMoneyReq) throws AlipayApiException;

    /**
     * 回调接口
     * <pre>
     * 第一步:验证签名,签名通过后进行第二步
     * 第二步:按一下步骤进行验证
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
     * 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
     * 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
     * </pre>
     * @param request 请求头
     * @return 结果
     */
    String notifyParam(HttpServletRequest request);
}
代码语言:javascript复制
/**
 * @author liyu
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AliPayServiceImpl implements AliPayService {
    private final Alipay alipay;
    private static final Logger logger = LoggerFactory.getLogger(AlipayController.class);
    private final ExecutorService executorService = Executors.newFixedThreadPool(20);

    public AlipayClient getAlipayClient() {
        return new DefaultAlipayClient(alipay.getServerUrl(),
                alipay.getAppId(),
                alipay.getPrivateKey(), JSON, CHARSET,
                alipay.getPublicKey(), SIGN_TYPE);
    }
  
    @Override
    public AjaxResult pullUpPayment(PayMoneyReq payMoneyReq) throws AlipayApiException {
        //实例化客户端
        AlipayClient alipayClient = getAlipayClient();
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        SnowflakeIdWorkerUtils snowflakeIdWorkerUtils = new SnowflakeIdWorkerUtils(0,0);
        request.setNotifyUrl(alipay.getAlipayNoticeUrl());
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", snowflakeIdWorkerUtils.nextId());
        bizContent.put("subject", "戒易花会员开通");
        bizContent.put("product_code", ValueConstants.QUICK_MSECURITY_PAY);
        bizContent.put("charset",alipay.getCharset());
        bizContent.put("sign_type",alipay.getSignType());
        bizContent.put("total_amount", "0.01");
        //自定义参数携带 有需要携带的参数自己填入
        JSONObject jsonObject = new JSONObject();
        bizContent.put("passback_params",jsonObject);
        request.setBizContent(bizContent.toString());
        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
        log.info("拉起支付宝调用返回路径{}",response.getBody());
        String result = response.getBody();
        if(response.isSuccess()){
          //把result返回给app则可以调用支付宝
            return AjaxResult.success("请求成功",result);
        } else {
            return AjaxResult.error("拉取支付宝失败!");
        }
    }

    @Override
    public String notifyParam(HttpServletRequest request){
        // 将异步通知中收到的待验证所有参数都存放到map中
        Map<String, String> params = convertRequestParamsToMap(request);
        String paramsJson = JSONObject.toJSONString(params);
        log.info("支付宝回调,{}", paramsJson);
        try {
            //验签
            boolean signVerify = AlipaySignature.rsaCheckV1(params, alipay.getAlipayPublicKey(), alipay.getCharset(), alipay.getSignType());
            if (signVerify) {
                // 另起线程处理业务
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        AlipayNotifyParam param = buildAlipayNotifyParam(params);
                        log.info("返回参数,{}",param);
                        String tradeStatus = param.getTradeStatus();
                        // 支付成功
                        if (ValueConstants.TRADE_SUCCESS.equals(tradeStatus)
                                || ValueConstants.TRADE_FINISHED.equals(tradeStatus)) {
                            	log.info("支付成功,处理业务")
                            } catch (Exception e) {
                                logger.error("支付宝回调业务处理报错,params:"   paramsJson, e);
                            }
                        } else {
                            logger.error("没有处理支付宝回调业务,支付宝交易状态:{},params:{}",tradeStatus,paramsJson);
                        }
                    }
                });
                // 如果签名验证正确,立即返回success,后续业务另起线程单独处理
                // 业务处理失败,可查看日志进行补偿,跟支付宝已经没多大关系。
                return "success";
            }
        }catch (Exception ex) {
            ex.printStackTrace();
            return "fail";
        }

        return "fail";
    }
  
    public AlipayFundTransOrderQueryResponse transferQueryToResponse(AlipayFundTransOrderQueryModel model) throws AlipayApiException{
        AlipayFundTransOrderQueryRequest request = new AlipayFundTransOrderQueryRequest();
        request.setBizModel(model);
        //实例化客户端
        AlipayClient alipayClient = getAlipayClient();
        return alipayClient.execute(request);
    }

    private static Map<String, String> getStringStringMap(HttpServletRequest request, Map<String, String> retMap) {
        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;

            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.toString().substring(1));
            } else {
                retMap.put(name, "");
            }
        }

        return retMap;
    }

    private AlipayNotifyParam buildAlipayNotifyParam(Map<String, String> params) {
        String json = JSONObject.toJSONString(params);
        return JSONObject.parseObject(json, AlipayNotifyParam.class);
    }
}

0 人点赞