前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java app支付宝支付

java app支付宝支付

作者头像
jaychou
发布2022-12-26 14:53:13
8770
发布2022-12-26 14:53:13
举报
文章被收录于专栏:全栈开发笔记全栈开发笔记

一.准备

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);
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021年10月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.准备
  • 二.创建配置类
  • 3.具体实现
相关产品与服务
微服务引擎 TSE
微服务引擎(Tencent Cloud Service Engine)提供开箱即用的云上全场景微服务解决方案。支持开源增强的云原生注册配置中心(Zookeeper、Nacos 和 Apollo),北极星网格(腾讯自研并开源的 PolarisMesh)、云原生 API 网关(Kong)以及微服务应用托管的弹性微服务平台。微服务引擎完全兼容开源版本的使用方式,在功能、可用性和可运维性等多个方面进行增强。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档