springboot集成支付宝支付2.0

流程详解

相对于集成微信支付来说,支付宝相对简单些,支付宝对复杂的操作进行了高度封装
支付宝文档
在这里插入图片描述

创建应用

登录 支付宝开放平台,创建应用并提交审核,审核通过后会生成应用唯一标识 APPID,并且可以申请开通开放产品使用权限。通过 APPID 应用才能调用开放产品的接口能力(应用没上线也可以申请的,准备好相关的资料即可)
在这里插入图片描述

添加支付能力

应用创建完成后,系统会自动跳转到应用详情页面。开发者可以在 能力列表 中点击 添加能力 来添加 APP支付 功能。
在这里插入图片描述

接口加签

进入开发设置中完成接口加签方式、IP白名单、应用网关、接口内容加密方式开发信息设置。
在这里插入图片描述
接口加签方式:必填。用于保障商户应用和支付宝交互的安全性;
加签模式可分为:公钥证书模式和公钥模式,推荐使用证书模式,一劳永逸,因为支付宝很多开放功能想要使用,加签模式必须是证书模式,比如:转账到支付宝账户
在这里插入图片描述

获取证书

获取应用公私钥/公钥证书
最终获取证书结果:
在这里插入图片描述

集成支付到springboot项目

依赖

<!--easy版-->
<dependency>
   <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-easysdk</artifactId>
    <version>${alipay-easysdk.version}</version>
</dependency>
<!--通用版-->
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>${alipay-sdk-java.version}</version>
</dependency>

版本信息
在这里插入图片描述
加载证书信息:

 //应用私钥
    static String merchantPrivateKey;
    static String signType = "RSA2";
    static String appId = "202100xxxxxxxx";
    //应用私钥文件路径
    static String appPrivateKeyPath = "zfb/appPrivate_RSA2_PKCS8.txt";
    //应用公钥证书
    static String merchantCertPath = "zfb/appCertPublicKey_2021002151695893.crt";
    //支付宝公钥证书
    static String alipayCertPath = "zfb/alipayCertPublicKey_RSA2.crt";
    //支付宝根证书
    static String alipayRootCertPath = "zfb/alipayRootCert.crt";
    //支付异步通知接收服务地址(自己定义,支付宝异步调用,确保这个接口没有限制)
    static String payNotifyUrl = "http://(域名/IP)/thirdparty/payNotify/payed/zfbNotify";
    //退款异步通知接收服务地址
    //static String refundNotifyUrl = "http://(域名/IP)/PayNotify/refunded/zfbNotify";

    static {
        //读取应用私钥
        try {
            InputStream is = ZfbPayInfoConfig.class.getClassLoader().getResourceAsStream(appPrivateKeyPath);
            String str = IOUtils.toString(is, "utf-8");

            merchantPrivateKey = str;
            Config config = new Config();
            config.protocol = "https";
            config.gatewayHost = "openapi.alipay.com";
            config.signType = signType;

            config.appId = appId;
            // 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中,应用私钥
            config.merchantPrivateKey = merchantPrivateKey;

            //注:证书文件路径支持设置为文件系统中的路径或CLASS_PATH中的路径,优先从文件系统中加载,加载失败后会继续尝试从CLASS_PATH中加载
            //应用公钥证书
            config.merchantCertPath = merchantCertPath;
            //支付宝公钥证书
            config.alipayCertPath = alipayCertPath;
            //支付宝根证书
            config.alipayRootCertPath = alipayRootCertPath;

            //注:支付宝公钥,如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
            //config.alipayPublicKey = "<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->";

            //可设置异步通知接收服务地址(可选)
            config.notifyUrl = payNotifyUrl;

            //可设置AES密钥,调用AES加解密相关接口时需要(可选)
            //config.encryptKey = "<-- 请填写您的AES密钥,例如:aa4BtZ4tspm2wnXLb1ThQA== -->";

            // 1. 设置参数(全局只需设置一次)
            Factory.setOptions(config);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

使用,老规矩,看文档,文档最详细,找到文档位置是关键:
接入流程,入口
12
这里有通用版和easy版的详细介绍,下边都以easy做示例,easy进行了封装,使用起来更加方便。
参考这里的开放接口
订单支付:

 AlipayTradeAppPayResponse payResponse = Payment.App()
                        //设置15分钟未支付,则此次支付失败,因为订单过期了
                        .optional("timeout_express", "15m")
                        //passback_params 扩展参数,用于异步接收的时候根据这个参数写一些自定义逻辑,不用可以不加
                        .optional("passback_params", URLEncoder.encode(CommonConstant.pay_order, "utf-8"))
                        .pay("商品", totalOrderSn, totalPrice.toPlainString());

最重要的参数就是订单号和价格,看吧,就是如此简单。
简单看一下源码,可以看到sdk内部已经帮我们封装了前期的准备工作,签名逻辑也不用自己去封装啦,并且之后的异步通知验签一行代码就解决了,爽吧!!!
在这里插入图片描述
接收异步通知:

/**
     * 功能描述:支付宝异步回掉地址
     *
     * @param vo
     * @param request
     * @return java.lang.String
     * @author zhouwenjie
     * @date 2021/5/30 22:27
     */
    @ApiOperation(value = "支付宝异步通知", notes = "支付宝异步通知")
    @PostMapping("/payed/zfbNotify")
    public String handleAliPayed(ZfbPayAsyncVo vo, HttpServletRequest request) throws Exception {
        //获取支付宝POST过来反馈信息
        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 = iter.next();
            String[] values = 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);
        }
        //验签
        Boolean signVerified = Factory.Payment.Common().verifyNotify(params);
        if (signVerified){
        	//开始正常逻辑处理
        }
   }

ZfbPayAsyncVo 实体类

@ToString
@Data
public class ZfbPayAsyncVo {

    /**
     * 交易创建时间
     */
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date gmt_create;
    /**
     * 交易付款时间
     */
    private String gmt_payment;
    /**
     * 交易退款时间
     */
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date gmt_refund;
    /**
     * 交易结束时间
     */
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date gmt_close;
    /**
     * 通知时间
     */
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date notify_time;
    /**
     * 编码格式utf-8
     */
    private String charset;
    /**
     * 支付宝分配给开发者的应用Id
     */
    private String app_id;
    /**
     * 买家支付宝用户号
     */
    private String buyer_id;
    /**
     * 买家支付宝账号
     */
    private String buyer_logon_id;
    /**
     * 卖家支付宝用户号
     */
    private String seller_id;
    /**
     * 卖家支付宝账号
     */
    private String seller_email;
    /**
     * 商户订单号
     */
    private String out_trade_no;
    /**
     * 商品描述,订单的信息
     */
    private String body;
    /**
     * 订单标题
     */
    private String subject;
    /**
     * 接口版本
     */
    private String version;
    /**
     * 通知校验ID
     */
    private String notify_id;
    /**
     * 通知类型:trade_status_sync
     */
    private String notify_type;
    /**
     * 支付金额信息,支付成功的各个渠道金额信息,详见下表 资金明细信息说明
     */
    private String fund_bill_list;
    /**
     * 订单金额,支付的总额
     */
    private BigDecimal total_amount;
    /**
     * 交易状态  TRADE_SUCCESS
     */
    private String trade_status;
    /**
     * 支付宝交易号,流水号
     */
    private String trade_no;
    /**
     * 用户在交易中支付的可开发票的金额
     */
    private BigDecimal invoice_amount;
    /**
     * 实收金额(商家收到的款)
     */
    private BigDecimal receipt_amount;
    /**
     * 集分宝金额
     */
    private BigDecimal point_amount;
    /**
     * 付款金额,最终支付的金额
     */
    private BigDecimal buyer_pay_amount;
    /**
     * 退款通知中,返回总退款金额,单位为元,支持两位小数
     */
    private BigDecimal refund_fee;
    /**
     * 签名
     */
    private String sign;
    /**
     * 签名类型
     */
    private String sign_type;
    /**
     * 公共回传参数,如果请求时传递了该参数,则返回给商户时会在异步通知时将该参数原样返回。
     * 本参数必须进行UrlEncode之后才可以发送给支付宝
     */
    private String passback_params;
}

退款:

  • 未发货退款
/**
     * 功能描述: 处理未发货退款
     *
     * @param refundInfo
     * @return boolean
     * @author zhouwenjie
     * @date 2021/6/30 15:03
     */
    private AlipayTradeRefundResponse refundByzfb(RefundInfo refundInfo) {
        AlipayTradeRefundResponse refundResponse = null;
        try {
            refundResponse = Factory.Payment.Common()
                    .refund(refundInfo.getOrderTotalSn(), refundInfo.getRefundFee().toPlainString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return refundResponse;
    }
  • 已发货退款
/**
     * 功能描述: 处理已发货退款
     *
     * @param apply
     * @return boolean
     * @author zhouwenjie
     * @date 2021/6/30 15:03
     */
    private boolean refundByzfb(OrderReturnApply apply) {
        boolean isSuccess = false;
        try {
            //已发货退款
            AlipayTradeRefundResponse refundResponse = Factory.Payment.Common()
                    //退款请求号,部分退款必填,防止重复退款
                    .optional("out_request_no", apply.getOutRequestNo())
                    .refund(apply.getOrderTotalSn(), apply.getReturnAmount().toPlainString());
            } catch (Exception e) {
            e.printStackTrace();
        }
        return isSuccess;

支付宝退款不同于微信,微信退款结果有三种结果,成功、失败、处理中(等待退款异步通知),而支付宝只有成功、失败,所以只在这个返回值中取结果处理逻辑即可;具体信息查看支付能力相关文档

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Springboot Cloud集成OAuth2.0可以让你的应用支持用户认证和授权,可以通过几个简单的步骤实现。 以下是基本的步骤: 1. 添加Spring Security和OAuth2依赖 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.0.0.RELEASE</version> </dependency> ``` 2. 创建Authorization Server配置 在Spring Boot应用程序中,您可以使用@EnableAuthorizationServer注释来启用OAuth2授权服务器。创建一个类,使用该注释,如下所示: ```java @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { // ... } ``` 在此类中,您需要实现以下方法: ```java @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("clientapp") .secret("123456") .authorizedGrantTypes("password", "refresh_token") .scopes("read", "write") .accessTokenValiditySeconds(1800) .refreshTokenValiditySeconds(3600 * 24); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); } ``` 这里我们已经实现了一个简单的ClientDetailsService,使用内存中的客户端信息。客户端名为“clientapp”,密码为“123456”,并且支持密码授权和刷新令牌。还设置了访问令牌和刷新令牌的有效期。 3. 配置Resource Server 现在,您需要配置Resource Server以保护您的REST API。在Spring Boot应用程序中,您可以使用@EnableResourceServer注释启用OAuth2资源服务器。 ```java @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { // ... } ``` 在这个配置类中,需要实现以下方法: ```java @Override public void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/api/**").authenticated() .and() .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); } ``` 这里我们将“/api/**”路径下的所有请求保护起来,只有经过授权的用户才能访问。如果用户未经授权尝试访问,我们将返回一个403 Forbidden响应。 4. 配置UserDetailsService 为了使资源服务器能够对用户进行身份验证,您需要提供一个UserDetailsService。这个类将使用用户名和密码对用户进行身份验证。 ```java @Service public class UserDetailsServiceImpl implements UserDetailsService { // ... } ``` 5. 配置WebSecurityConfigurerAdapter 为了使Spring Security能够使用UserDetailsService进行身份验证,您需要扩展WebSecurityConfigurerAdapter并将UserDetailsService注入其中。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { // ... @Autowired private UserDetailsService userDetailsService; // ... } ``` 在这个类中,你需要实现以下方法: ```java @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } ``` 这里我们使用BCryptPasswordEncoder作为密码编码器,以确保用户密码的安全性。 6. 测试OAuth2 现在您已经完成了OAuth2的所有配置,可以测试它是否正常工作。您可以使用cURL或Postman等工具发送HTTP请求来测试OAuth2。以下是一个使用cURL测试OAuth2的示例: ```bash curl -X POST \ http://localhost:8080/oauth/token \ -H 'Authorization: Basic Y2xpZW50YXBwOjEyMzQ1Ng==' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=password&username=user&password=pass' ``` 这里我们向Authorization Server发送密码授权请求,使用用户名“user”和密码“pass”进行身份验证。如果身份验证成功,将返回一个访问令牌和刷新令牌。 7. 使用访问令牌访问受保护的API 现在您已经获得了访问令牌,可以使用它来访问受保护的API。以下是一个使用cURL测试API的示例: ```bash curl -X GET \ http://localhost:8080/api/greeting \ -H 'Authorization: Bearer <access_token>' ``` 这里我们向Resource Server发送GET请求,使用访问令牌进行身份验证。如果身份验证成功,将返回一个响应。 这就是Springboot Cloud集成OAuth2.0的基本步骤。在实际项目中,您还需要做一些额外的工作,例如存储用户信息和客户端信息,实现授权码授权和客户端凭据授权等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值