Springboot+MyBatisPlus+Mysql+vue实现支付宝支付

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Springboot+MyBatisPlus+Mysql+vue实现支付宝支付

文章目录

前言

一、支付宝沙箱环境准备

二、开发环境搭建

1.数据库脚本执行。

2 依赖添加

3 配置支付宝支付相关参数

4. 配置支付宝客户端类

三、支付宝支付api接口

1.下单接口

支付时序图

2 支付通知回调处理订单

3.支付失败关闭订单

4.订单退款

5、查询订单

6.对账

四.前端

1.下单页面

2.订单列表

3.对账页面

账单列表

总结

前言

本篇通过使用Springboot+MybatisPlus+Mysql+vue实现支付宝网页支付,下单,下单通知,查询订单,关闭订单,退款等功能,前端使用单页面的Vue+elementui+axiso发送请求后台。对账估计是沙箱环境的原因提示账单不存在

一、支付宝沙箱环境准备

1)注册支付宝开发者账号。

2)注册完成登录之后进入控制台->沙箱-》创建应用。

3)配置应用环境(支付宝公钥,应用私钥,应用公钥,支付宝网关地址,配置接口内容加密方式,查看APPID)。详细的配置过程这里就不多介绍。


二、开发环境搭建

1.数据库脚本执行。

-- test.`order` definition

CREATE TABLE `order` (

 `order_id` int NOT NULL AUTO_INCREMENT COMMENT '订单ID',

 `order_no` varchar(50) DEFAULT NULL COMMENT '订单号',

 `product_id` int DEFAULT NULL COMMENT '产品id',

 `user_id` int DEFAULT NULL COMMENT '用户ID',

 `order_num` int DEFAULT NULL COMMENT '订单产品数量',

 `order_amt` decimal(10,2) DEFAULT NULL COMMENT '订单金额',

 `order_status` varchar(10) DEFAULT NULL COMMENT '订单状态',

 `pay_status` varchar(10) DEFAULT NULL COMMENT '支付状态',

 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

 `update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',

 `create_user` varchar(10) DEFAULT NULL COMMENT '创建人',

 `update_user` varchar(10) DEFAULT NULL COMMENT '更新人',

 `code_url` varchar(100) DEFAULT NULL COMMENT '订单二维码连接',

 `pay_type` varchar(10) DEFAULT NULL COMMENT '支付类别',

 PRIMARY KEY (`order_id`)

) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单表';

-- test.payment_info definition

CREATE TABLE `payment_info` (

 `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '支付记录id',

 `order_no` varchar(50) DEFAULT NULL COMMENT '商户订单编号',

 `transaction_id` varchar(50) DEFAULT NULL COMMENT '支付系统交易编号',

 `payment_type` varchar(20) DEFAULT NULL COMMENT '支付类型',

 `trade_type` varchar(20) DEFAULT NULL COMMENT '交易类型',

 `trade_state` varchar(50) DEFAULT NULL COMMENT '交易状态',

 `payer_total` decimal(10,0) DEFAULT NULL COMMENT '支付金额(分)',

 `content` text COMMENT '通知参数',

 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

 `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

 PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- test.product definition

CREATE TABLE `product` (

 `product_id` int NOT NULL AUTO_INCREMENT COMMENT '商品ID',

 `product_name` varchar(100) DEFAULT NULL COMMENT '商品名称',

 `product_type` varchar(10) DEFAULT NULL,

 `product_price` decimal(10,2) DEFAULT NULL COMMENT '商品价格',

 `create_by` varchar(100) DEFAULT NULL COMMENT '创建人',

 `update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',

 `update_by` varchar(100) DEFAULT NULL COMMENT '更新人',

 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

 PRIMARY KEY (`product_id`),

 KEY `product_product_type_IDX` (`product_type`,`product_name`) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品表';

-- test.refund_info definition

CREATE TABLE `refund_info` (

 `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '退款单id',

 `order_no` varchar(50) DEFAULT NULL COMMENT '商户订单编号',

 `refund_no` varchar(50) DEFAULT NULL COMMENT '商户退款单编号',

 `refund_id` varchar(50) DEFAULT NULL COMMENT '支付系统退款单号',

 `total_fee` decimal(10,2) DEFAULT NULL COMMENT '原订单金额(分)',

 `refund` decimal(10,2) DEFAULT NULL COMMENT '退款金额(分)',

 `reason` varchar(50) DEFAULT NULL COMMENT '退款原因',

 `refund_status` varchar(10) DEFAULT NULL COMMENT '退款状态',

 `content_return` text COMMENT '申请退款返回参数',

 `content_notify` text COMMENT '退款结果通知参数',

 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

 `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

 PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- test.stock definition

CREATE TABLE `stock` (

 `stock_id` int NOT NULL AUTO_INCREMENT COMMENT '库存主键',

 `product_id` int NOT NULL COMMENT '商品ID',

 `stock_num` int DEFAULT NULL COMMENT '库存数量',

 `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

 `create_by` varchar(100) DEFAULT NULL COMMENT '创建人',

 `update_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',

 `update_by` varchar(100) DEFAULT NULL COMMENT '更新人',

 PRIMARY KEY (`stock_id`),

 KEY `stock_product_id_IDX` (`product_id`) USING BTREE,

 CONSTRAINT `stock_FK` FOREIGN KEY (`product_id`) REFERENCES `product` (`product_id`)

) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='库存表';

2 依赖添加

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

   <modelVersion>4.0.0</modelVersion>

   <parent>

       <groupId>org.springframework.boot</groupId>

       <artifactId>spring-boot-starter-parent</artifactId>

       <version>2.3.6.RELEASE</version>

       <relativePath/> <!-- lookup parent from repository -->

   </parent>

   <groupId>com.elite.springboot</groupId>

   <artifactId>Springboot16WechatAliPay</artifactId>

   <version>1.0-SNAPSHOT</version>

   <properties>

       <maven.compiler.source>8</maven.compiler.source>

       <maven.compiler.target>8</maven.compiler.target>

       <java.version>1.8</java.version>

   </properties>

   <dependencies>

       <!--web-->

       <dependency>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-web</artifactId>

       </dependency>

       <!--一引入alipay sdk-->

       <dependency>

           <groupId>com.alipay.sdk</groupId>

           <artifactId>alipay-sdk-java</artifactId>

           <version>4.22.0.ALL</version>

       </dependency>

       <!--引入微信支付api-->

       <dependency>

           <groupId>com.github.wechatpay-apiv3</groupId>

           <artifactId>wechatpay-apache-httpclient</artifactId>

           <version>0.3.0</version>

       </dependency>

       <dependency>

           <groupId>mysql</groupId>

           <artifactId>mysql-connector-java</artifactId>

       </dependency>

       <dependency>

           <groupId>com.baomidou</groupId>

           <artifactId>mybatis-plus-boot-starter</artifactId>

           <version>3.4.1</version>

       </dependency>

       <!--druid数据源-->

       <dependency>

           <groupId>com.alibaba</groupId>

           <artifactId>druid</artifactId>

           <version>1.2.8</version>

       </dependency>

       <dependency>

           <groupId>cn.hutool</groupId>

           <artifactId>hutool-all</artifactId>

           <version>5.1.4</version>

       </dependency>

       <dependency>

           <groupId>commons-lang</groupId>

           <artifactId>commons-lang</artifactId>

           <version>2.6</version>

       </dependency>

       <dependency>

           <groupId>com.alibaba</groupId>

           <artifactId>fastjson</artifactId>

           <version>1.2.76</version>

       </dependency>

       <dependency>

           <groupId>com.google.code.gson</groupId>

           <artifactId>gson</artifactId>

       </dependency>

       <!--lombok-->

       <dependency>

           <groupId>org.projectlombok</groupId>

           <artifactId>lombok</artifactId>

           <optional>true</optional>

       </dependency>

       <dependency>

           <groupId>junit</groupId>

           <artifactId>junit</artifactId>

           <version>4.12</version>

           <scope>test</scope>

       </dependency>

       <dependency>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-test</artifactId>

           <scope>test</scope>

       </dependency>

   </dependencies>

   <build>

       <!-- 项目打包时会将java目录中的*.xml文件也进行打包 -->

       <resources>

           <resource>

               <directory>src/main/java</directory>

               <includes>

                   <include>**/*.xml</include>

               </includes>

               <filtering>false</filtering>

           </resource>

       </resources>

       <plugins>

           <plugin>

               <groupId>org.springframework.boot</groupId>

               <artifactId>spring-boot-maven-plugin</artifactId>

               <configuration>

                   <excludes>

                       <exclude>

                           <groupId>org.projectlombok</groupId>

                           <artifactId>lombok</artifactId>

                       </exclude>

                   </excludes>

               </configuration>

           </plugin>

       </plugins>

   </build>

</project>

3 配置支付宝支付相关参数

##支付宝支付配置信息

alipayconfig:

 # 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号,开发时使用沙箱提供的APPID,生产环境改成自己的APPID

 app_id: APPID

 # 商户私钥,您的PKCS8格式RSA2私钥

 privateKey: 商户私钥

 # 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。

 publicKey: 支付宝公钥

 # 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问

 notify_url:  https://38bc-183-131-162-121.jp.ngrok.io/springboot/alipay/notify

 # 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问(其实就是支付成功后返回的页面)

 return_url:页面跳转同步通知页面路

 # 返回格式

 format: json

 #  签名方式

 sign_type: RSA2

 # 字符编码格式

 charset: utf-8

 # 支付宝网关,这是沙箱的网关

 gatewayUrl: https://openapi.alipaydev.com/gateway.do

 # 支付宝网关

 logPath: C:\\

4. 配置支付宝客户端类

package com.elite.springboot.config;

import com.alipay.api.AlipayClient;

import com.alipay.api.DefaultAlipayClient;

import lombok.Data;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.PropertySource;

/**

* 支付宝支付配置类

*/

@Configuration

@ConfigurationProperties(prefix = "alipayconfig")

@Data

public class AlipayConfig {

   // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号,开发时使用沙箱提供的APPID,生产环境改成自己的APPID

   private String app_id;

   // 商户私钥,您的PKCS8格式RSA2私钥

   private String privateKey;

   // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。

   private String publicKey;

   // 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问

   private String notify_url;

   // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问(其实就是支付成功后返回的页面)

   private String return_url;

   //返回格式

   private String format;

   // 签名方式

   private String sign_type;

   // 字符编码格式

   private String charset;

   // 支付宝网关,这是沙箱的网关

   private String gatewayUrl;

   // 支付宝网关

   private String logPath;

   /**

    * 获取alipayclient

    */

   @Bean(name="alipayClient")

   public AlipayClient getAlipayClient() {

       //调用RSA签名方式

       AlipayClient client = new DefaultAlipayClient(gatewayUrl, app_id,

               privateKey,format, charset, publicKey, sign_type);

//        AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

//

//        // 封装请求支付信息

//        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();

//        model.setOutTradeNo(out_trade_no);

//        model.setSubject(subject);

//        model.setTotalAmount(total_amount);

//        model.setBody(body);

//        model.setTimeoutExpress(timeout_express);

//        model.setProductCode(product_code);

//        alipay_request.setBizModel(model);

//        // 设置异步通知地址

//        alipay_request.setNotifyUrl(AlipayConfig.notify_url);

//        // 设置同步地址

//        alipay_request.setReturnUrl(AlipayConfig.return_url);

       return client;

   }

}

三、支付宝支付api接口

1.下单接口

支付时序图

ee0461d38b544613a99d6eac9121f2fe.png

下单请求代码示例:

@Transactional(rollbackFor = Exception.class)

   @Override

   public R createOrder(Integer product_id) {

       try{

           log.info("创建订单开始......");

           //创建订单

           Order orderInfo = orderService.createOrderByProductId(product_id, PayTypeEnum.ALIPAY.getPayType());

           log.info("创建订单结束:"+orderInfo.toString());

           log.info("调用支付开始.....");

           //调用支付宝接口

           AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();

           //配置需要的公共请求参数

           request.setNotifyUrl(alipayConfig.getNotify_url());

           //支付完成后配置returnUrl

           request.setReturnUrl(alipayConfig.getReturn_url());

           /**

            * out_trade_no String 必选 64 商户订单号。由商家自定义,64个字符以内,仅支持字母、数字、下划线且需保证在商户端不重复。 20150320010101001

            * total_amount Price 必选 11 订单总金额,单位为元,精确到小数点后两位,取值范围为 [0.01,100000000]。金额不能为0。 88.88

            * subject String 必选 256 订单标题。注意:不可使用特殊字符,如 /,=,& 等。 Iphone6 16G

            * product_code String 必选 64 销售产品码,与支付宝签约的产品码名称。注:目前电脑支付场景下仅支持FAST_INSTANT_TRADE_PAY FAST_INSTANT_TRADE_PAY

            */

           //组装当前业务方法的请求参数

           JSONObject bizContent = new JSONObject();

           bizContent.put("out_trade_no", orderInfo.getOrderNo());

           bizContent.put("total_amount", orderInfo.getOrderAmt());

           bizContent.put("subject", productService.getById(product_id).getProductName());

           bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");

           request.setBizContent(bizContent.toString());

           //执行请求,调用支付宝接口

           AlipayTradePagePayResponse response = alipayClient.pageExecute(request);

           log.info("调用支付结束:"+response.getBody());

           if(response.isSuccess()){

               log.info("调用成功,返回结果 ===> " + response.getBody());

               return R.ok(response.getBody());

           } else {

               log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());

               throw new RuntimeException("创建支付交易失败");

               //return R.fail(400,"创建支付交易失败:"+response.getMsg());

           }

       } catch (AlipayApiException e) {

           e.printStackTrace();

           throw new RuntimeException("创建支付交易失败");

           //return R.fail(400,"创建支付交易失败:"+e.getErrMsg());

       }

   }

2 支付通知回调处理订单

 /**

    * 支付通知

    */

   @PostMapping("/notify")

   public String notify(@RequestParam Map<String, String> params){

       String result = "failure";

       try {

           //异步通知验签

           boolean signVerified = AlipaySignature.rsaCheckV1(

                   params,

                   alipayConfig.getPublicKey(),

                   AlipayConstants.CHARSET_UTF8,

                   AlipayConstants.SIGN_TYPE_RSA2); //调用SDK验证签名

           if(!signVerified){

              //验签失败则记录异常日志,并在response中返回failure.

               log.error("支付成功异步通知验签失败!");

               return result;

           }

           // 验签成功后

           log.info("支付成功异步通知验签成功!");

           //按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,

           //1 商户需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号

           String outTradeNo = params.get("out_trade_no");

           Order order = orderService.getOrderByOrderNo(outTradeNo);

           if(order == null){

               log.error("订单不存在");

               return result;

           }

           //2 判断 total_amount 是否确实为该订单的实际金额(即商户订单创建时的金额)

           String totalAmount = params.get("total_amount");

           int totalAmountInt = new BigDecimal(totalAmount).intValue();

           int totalFeeInt = order.getOrderAmt().intValue();

           if(totalAmountInt != totalFeeInt){

               log.error("金额校验失败");

               return result;

           }

           //3 校验通知中的 seller_id(或者 seller_email) 是否为 out_trade_no 这笔单据的对应的操作方

           /*String sellerId = params.get("seller_id");

           String sellerIdProperty = config.getProperty("alipay.seller-id");

           if(!sellerId.equals(sellerIdProperty)){

               log.error("商家pid校验失败");

               return result;

           }*/

           //4 验证 app_id 是否为该商户本身

           String appId = params.get("app_id");

           String appIdProperty = alipayConfig.getApp_id();

           if(!appId.equals(appIdProperty)){

               log.error("appid校验失败");

               return result;

           }

           //在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS时,

           // 支付宝才会认定为买家付款成功。

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

           if(!"TRADE_SUCCESS".equals(tradeStatus)){

               log.error("支付未成功");

               return result;

           }

           //处理业务 修改订单状态 记录支付日志

           aliPayService.processOrder(params);

           //校验成功后在response中返回success并继续商户自身业务处理,校验失败返回failure

           result = "success";

       } catch (AlipayApiException e) {

           e.printStackTrace();

       }

       return result;

   }

3.支付失败关闭订单

 

   /**

    * 取消订单业务

    * @param orderNo

    */

   private boolean closeOrder(String orderNo) {

       /**

        * trade_no String 特殊可选 64 该交易在支付宝系统中的交易流水号。最短 16 位,最长 64 位。和out_trade_no不能同时为空,如果同时传了 out_trade_no和 trade_no,则以 trade_no为准。 2013112611001004680073956707

        * out_trade_no String 特殊可选 64 订单支付时传入的商户订单号,和支付宝交易号不能同时为空。 trade_no,out_trade_no如果同时存在优先取trade_no HZ0120131127001

        * operator_id String 可选 28 商家操作员编号 id,由商家自定义。 YX01

        */

       try {

           log.info("关单接口的调用,订单号 ===> {}", orderNo);

           AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();

           JSONObject bizContent = new JSONObject();

           bizContent.put("out_trade_no", orderNo);

           log.info("调用取消订单的的入参:"+bizContent.toString());

           request.setBizContent(bizContent.toString());

           AlipayTradeCloseResponse response = alipayClient.execute(request);

           if(response.isSuccess()){

               log.info("调用成功,返回结果 ===> " + response.getBody());

               return true;

           } else {

               log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());

               //throw new RuntimeException("关单接口的调用失败");

               return false;

           }

       } catch (AlipayApiException e) {

           e.printStackTrace();

           throw new RuntimeException("关单接口的调用失败");

       }

   }

4.订单退款

 @Transactional(rollbackFor = Exception.class)

   @Override

   public void refund(String orderNo, String reason) {

       try {

           log.info("调用退款API");

           //创建退款单

           RefundInfo refundInfo = refundsInfoService.createRefundByOrderNoForAliPay(orderNo, reason);

           //调用统一收单交易退款接口

           AlipayTradeRefundRequest request = new AlipayTradeRefundRequest ();

           //组装当前业务方法的请求参数

           JSONObject bizContent = new JSONObject();

           bizContent.put("out_trade_no", orderNo);//订单编号

           BigDecimal refund = new

                   BigDecimal(refundInfo.getRefund().toString());

           //BigDecimal refund = new BigDecimal("2").divide(new BigDecimal("100"));

           bizContent.put("refund_amount", refund);//退款金额:不能大于支付金额

           bizContent.put("refund_reason", reason);//退款原因(可选)

           request.setBizContent(bizContent.toString());

           log.info("退款API的入参:"+bizContent.toString());

           //执行请求,调用支付宝接口

           AlipayTradeRefundResponse response = alipayClient.execute(request);

           if(response.isSuccess()){

               log.info("调用成功,返回结果 ===> " + response.getBody());

               //更新订单状态

               orderService.updateStatusByOrderNo(orderNo,OrderStatus.REFUND_SUCCESS);

               //更新退款单

               refundsInfoService.updateRefundForAliPay(

                       refundInfo.getRefundNo(),

                       response.getBody(),

                       OrderStatus.REFUND_SUCCESS.getType()); //退款成功

           } else {

                log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> "

                       + response.getMsg());

               //更新订单状态

               orderService.updateStatusByOrderNo(orderNo,

                       OrderStatus.REFUND_ABNORMAL);

               //更新退款单

               refundsInfoService.updateRefundForAliPay(

                       refundInfo.getRefundNo(),

                       response.getBody(),

                       OrderStatus.REFUND_ABNORMAL.getType()); //退款失败

           }

       } catch (AlipayApiException e) {

           e.printStackTrace();

           throw new RuntimeException("创建退款申请失败");

       }

   }

5、查询订单

/**

    * 查询订单

    * @param orderNo

    * @return 返回订单查询结果,如果返回null则表示支付宝端尚未创建订单

    */

   @Override

   public String queryOrder(String orderNo) {

       /**

        * out_trade_no String 特殊可选 64 订单支付时传入的商户订单号,和支付宝交易号不能同时为空。

        * trade_no,out_trade_no如果同时存在优先取trade_no 20150320010101001

        * trade_no String 特殊可选 64 支付宝交易号,和商户订单号不能同时为空 2014112611001004680 073956707

        * org_pid String 可选 16 银行间联模式下有用,其它场景请不要使用;

        * 双联通过该参数指定需要查询的交易所属收单机构的pid; 2088101117952222

        * query_options String[] 可选 1024 查询选项,商户传入该参数可定制本接口同步响应额外返回的信息字段,数组格式。支持枚举如下:trade_settle_info:返回的交易结算信息,包含分账、补差等信息;

        * fund_bill_list:交易支付使用的资金渠道;

        * voucher_detail_list:交易支付时使用的所有优惠券信息;

        * discount_goods_detail:交易支付所使用的单品券优惠的商品优惠信息;

        * mdiscount_amount:商家优惠金额; trade_settle_info

        */

       try {

           log.info("查单接口调用 ===> {}", orderNo);

           AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();

           JSONObject bizContent = new JSONObject();

           bizContent.put("out_trade_no", orderNo);

           request.setBizContent(bizContent.toString());

           AlipayTradeQueryResponse response = alipayClient.execute(request);

           if(response.isSuccess()){

               log.info("调用成功,返回结果 ===> " + response.getBody());

               return response.getBody();

           } else {

               log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> " + response.getMsg());

               //throw new RuntimeException("查单接口的调用失败");

               return null;//订单不存在

           }

       } catch (AlipayApiException e) {

           e.printStackTrace();

           throw new RuntimeException("查单接口的调用失败");

       }

   }

6.对账

@Override

   public String queryBill(String billDate, String type) {

       /**

        * bill_type String 必选 20 账单类型,商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型,支持:

        * trade:商户基于支付宝交易收单的业务账单;

        * signcustomer:基于商户支付宝余额收入及支出等资金变动的账务账单。 trade

        * bill_date String 必选 15 账单时间:

        * * 日账单格式为yyyy-MM-dd,最早可下载2016年1月1日开始的日账单。不支持下载当日账单,只能下载前一日24点前的账单数据(T+1),当日数据一般于次日 9 点前生成,特殊情况可能延迟。

        * * 月账单格式为yyyy-MM,最早可下载2016年1月开始的月账单。不支持下载当月账单,只能下载上一月账单数据,当月账单一般在次月 3 日生成,特殊情况可能延迟。 2016-04-05

        * smid String 可选 20 二级商户smid 2088123412341234

        * AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");

        * AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();

        * request.setBizContent("{" +

        * "  \"bill_type\":\"trade\"," +

        * "  \"bill_date\":\"2016-04-05\"," +

        * "  \"smid\":\"2088123412341234\"" +

        * "}");

        * AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);

        * if(response.isSuccess()){

        * System.out.println("调用成功");

        * } else {

        * System.out.println("调用失败");

        * }

        */

       try {

           log.info("账单类型:"+type+",日期:"+billDate);

           AlipayDataDataserviceBillDownloadurlQueryRequest request = new

                   AlipayDataDataserviceBillDownloadurlQueryRequest();

           JSONObject bizContent = new JSONObject();

           bizContent.put("bill_type", type);

           bizContent.put("bill_date", billDate);

           bizContent.put("smid","2088123412341234");

           request.setBizContent(bizContent.toString());

           AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);

           if(response.isSuccess()){

               log.info("调用成功,返回结果 ===> " + response.getBody());

               //获取账单下载地址

               Gson gson = new Gson();

               HashMap<String, LinkedTreeMap> resultMap =

                       gson.fromJson(response.getBody(), HashMap.class);

               LinkedTreeMap billDownloadurlResponse =

                       resultMap.get("alipay_data_dataservice_bill_downloadurl_query_response");

               String billDownloadUrl =

                       (String)billDownloadurlResponse.get("bill_download_url");

               return billDownloadUrl;

           } else {

               log.info("调用失败,返回码 ===> " + response.getCode() + ", 返回描述 ===> "

                       + response.getMsg());

               throw new RuntimeException("申请账单失败");

           }

       } catch (AlipayApiException e) {

           e.printStackTrace();

           throw new RuntimeException("申请账单失败");

       }

   }

四.前端

1.下单页面

db95987d034c424caaea5d7421a15fc7.png

2.订单列表

订单列表可以操作退款

a8c8a5364b87401eabcda29c2174d5a7.png

3.对账页面

2fc801aff68049c2bd22003b48ba4d03.png

总结

本篇通过一个简单简单的前端页面+springboot+mybatisplus实现支付宝支付,了解支付宝api接口的调用以及简单的下单业务逻辑。

注意:支付宝的回调地址必须外网可以访问,需要使用ngrok进行外网映射,这个工具比较简单。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4天前
|
算法 Java 数据库连接
Spring+MySQL+数据结构+集合,Alibaba珍藏版mybatis手写文档
Spring+MySQL+数据结构+集合,Alibaba珍藏版mybatis手写文档
|
5天前
|
XML JavaScript 前端开发
springboot配合Freemark模板生成word,前台vue接收并下载【步骤详解并奉上源码】
springboot配合Freemark模板生成word,前台vue接收并下载【步骤详解并奉上源码】
|
6天前
|
Java 关系型数据库 MySQL
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口(下)
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口
44 0
|
1天前
|
监控 NoSQL Java
java云MES 系统源码Java+ springboot+ mysql 一款基于云计算技术的企业级生产管理系统
MES系统是生产企业对制造执行系统实施的重点在智能制造执行管理领域,而MES系统特点中的可伸缩、信息精确、开放、承接、安全等也传递出:MES在此管理领域中无可替代的“王者之尊”。MES制造执行系统特点集可伸缩性、精确性、开放性、承接性、经济性与安全性于一体,帮助企业解决生产中遇到的实际问题,降低运营成本,快速适应企业不断的制造执行管理需求,使得企业已有基础设施与一切可用资源实现高度集成,提升企业投资的有效性。
27 5
|
3天前
|
监控 安全 NoSQL
采用java+springboot+vue.js+uniapp开发的一整套云MES系统源码 MES制造管理系统源码
MES系统是一套具备实时管理能力,建立一个全面的、集成的、稳定的制造物流质量控制体系;对生产线、工艺、人员、品质、效率等多方位的监控、分析、改进,满足精细化、透明化、自动化、实时化、数据化、一体化管理,实现企业柔性化制造管理。
24 3
|
3天前
|
前端开发 JavaScript Java
Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)五(前端页面
Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)五(前端页面
Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)五(前端页面
|
4天前
|
存储 数据可视化 前端开发
Echarts+vue+java+mysql实现数据可视化
Echarts+vue+java+mysql实现数据可视化
|
5天前
|
JavaScript Java 关系型数据库
基于springboot+vue+Mysql的交流互动系统
简化操作,便于维护和使用。
16 2
|
5天前
|
前端开发 关系型数据库 MySQL
SpringBoot-----从前端更新数据到MySql数据库
SpringBoot-----从前端更新数据到MySql数据库
14 1
|
6天前
|
前端开发 关系型数据库 MySQL
【MySQL × SpringBoot 突发奇想】全面实现流程 · 数据库导出Excel表格文件的接口
【MySQL × SpringBoot 突发奇想】全面实现流程 · 数据库导出Excel表格文件的接口
38 0