支付宝支付的实现

工程搭建

创建youxin_pay_interface的jar工程,依赖pojo
创建youxin_pay_service的war工程,除了项目依赖,需要加入支付的依赖
在这里插入图片描述

<!-- 支付宝支付所需类库包 -->
<dependency>
	<groupId>com.alipay.sdk</groupId>
	<artifactId>alipay-sdk-java</artifactId>
	<version>3.4.27.ALL</version>
</dependency>

配置sring-pay-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xmlns:tx="http://www.springframework.org/schema/tx"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans.xsd 
    		http://www.springframework.org/schema/context 
    		http://www.springframework.org/schema/context/spring-context.xsd
    		http://www.springframework.org/schema/aop
    		http://www.springframework.org/schema/aop/spring-aop.xsd
    		http://www.springframework.org/schema/tx
    		http://www.springframework.org/schema/tx/spring-tx.xsd">

	<context:component-scan base-package="com.youxin"/>

	<!-- 创建AlipayClient -->
	<bean id="payClient" class="com.alipay.api.DefaultAlipayClient">
		<constructor-arg name="serverUrl" value="${serverUrl}"/>
		<constructor-arg name="appId" value="${appId}"/>
		<constructor-arg name="privateKey" value="${privateKey}"/>
		<constructor-arg name="alipayPublicKey" value="${alipayPulicKey}"/>
		<constructor-arg name="format" value="${format}"/>
		<constructor-arg name="charset" value="${charset}"/>
		<constructor-arg name="signType" value="${signType}"/>
	</bean>
</beans>

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID" version="3.1">

  <!-- spring监听 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- spring配置文件初始化 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:spring-*.xml</param-value>
  </context-param>

</web-app>

配置alipay.properties

serverUrl=https://openapi.alipay.com/gateway.do
appId=*******
privateKey=生成的应用私钥
alipayPulicKey=支付宝公钥
format=json
charset=utf-8
signType=RSA2

注意
在spring的配置文件中加载alipay.properties(我们已经设置依赖了common层导入所有properties)

向支付宝发起预支付,前端接收预支付返回信息生成付款二维码

Map用来存储预支付响应信息,如果发起预支付成功,将订单号和支付总金额以及二维码码串返回给前端页面
在这里插入图片描述
响应结果示例
在这里插入图片描述
service层代码

@Autowired
private AlipayClient alipayClient;

public Map createNative(String out_trade_no, String total_fee) {
    Map<String, String> map = new HashMap<String, String>();
    // 创建预下单请求对象
    AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
    // 设置业务参数
    request.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
            + "\"total_amount\":\"" + total_fee + "\","
            + "\"subject\":\"在线支付\","
            + "\"timeout_express\":\"90m\"}");
    // 发出预下单业务请求
    try {
        AlipayTradePrecreateResponse response = alipayClient.execute(request);
        // 从相应对象读取相应结果
        String code = response.getCode();
        System.out.println("支付宝接口响应码:" + code);
        // 全部的响应结果
        String body = response.getBody();
        System.out.println("支付宝返回结果:" + body);

        if (code.equals("10000")) {
            map.put("qrcode", response.getQrCode());
            map.put("out_trade_no", response.getOutTradeNo());
            map.put("total_fee", total_fee);


            System.out.println("返回qrcode:" + response.getQrCode());
            System.out.println("返回out_trade_no:" + response.getOutTradeNo());
            System.out.println("返回total_fee:" + total_fee);
        } else {
            System.out.println("预下单接口调用失败:" + body);
        }
    } catch (AlipayApiException e) {
        e.printStackTrace();
    }
    return map;
}

检测支付状态

实现思路:
通过AlipayClient实现对交易查询接口(alipay.trade.query)的调用。阿里支付api
交易查询接口请求关键参数:
在这里插入图片描述
响应关键参数
在这里插入图片描述
service层

public Map queryPayStatus(String out_trade_no) {
    Map<String, String> map = new HashMap<String, String>();
    AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
    // 设置业务参数
    request.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
            + "\"trade_no\":\"\"}");

    // 发出请求
    try {
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        String code = response.getCode();

        System.out.println("查询交易状态--返回值1:" + code);
        System.out.println("查询交易状态--返回值2:" + response.getBody());

        if (code.equals("10000")) {
            map.put("out_trade_no", out_trade_no);
            map.put("tradestatus", response.getTradeStatus());
        }
    } catch (AlipayApiException e) {
        e.printStackTrace();
    }
    return map;
}

controller层
先调用service层的方法去查询支付状态,service层会将查询出来的结果封装进map集合返回,controller拿到集合中交易状态,怼它进行判断
支付状态的查询如果是等待买家付款就需要一直查询支付状态,通过循环的方式实现

/*
查询支付状态
 */
public Result queryPayStatus(String out_trade_no){
    Result result = null;
    int x = 0;
    while (true) {
        Map map = new HashMap();
        try {
            map = payService.queryPayStatus(out_trade_no);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String tradestatus = (String) map.get("tradestatus");
        if (tradestatus!=null && tradestatus.equals("TRADE_CLOSED") ){
            result = new Result(false,"未付款交易超时关闭,或支付完成后全额退款");
            break;
        }
        if (tradestatus!=null && tradestatus.equals("TRADE_SUCCESS")){
            result = new Result(true,"支付成功");
            break;
        }
        if (tradestatus!=null && tradestatus.equals("TRADE_FINISHED")){
            result = new Result(false,"交易结束,不可退款");
            break;
        }
        //时间间隔三秒再去循环校验支付状态
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 定义一个过期时间,可以参考登录信息的过期时间
        // 为了测试,可以设置30秒的过期时间,即 x 约 10次,实际时可以设置和用户登录过期时间
        x++;
        if(x>10){
            result = new Result(false,"二维码已失效!");
            break;
        }

    }
    return result;
}

支付日志

(1)系统中无法查询到支付记录
(2)支付后订单状态没有改变
实现思路:
(1)在用户下订单时就向支付日志表添加一条记录,信息包括支付总金额、订单ID(多个)、用户ID、下单时间等信息,支付状态为0(未支付)
(2)生成的支付日志对象放入redis中,以用户ID作为key,这样在生成支付二维码时就可以从redis中提取支付日志对象中的金额和订单号。
(3)当用户支付成功后,修改支付日志的支付状态为1(已支付),并记录支付宝传递给我们的交易流水号。根据订单ID(多个)修改订单的状态为2(已付款)。
在创建的订单同时创建支付日志
在这里插入图片描述
在这里插入图片描述
支付控制层从redis中获取订单号和总金额生成支付二维码
在这里插入图片描述
在这里插入图片描述
监听支付状态的同时,如果支付成功,更新支付日志和订单状态
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值