支付宝沙箱支付

支付介绍

支付: 支出,付出(转账)
    从自己账户上支出,付给别人
在中国这个大的环境下:
    中国人民银行: 发行人民币
    
同银行转账/支付:
    效率高,风险小
跨行转账/支付:
    银行与银行之间必须有合作关系
    效率低,风险高
程序接入支付:
    需要一家一家银行做对接,成本高
    最好对接第三方平台(第三方平台已经将大部分的银行进行了整合)

 

常见的支付方式

同银行转账/支付:
    效率高,风险小
跨行转账/支付:
    银行与银行之间必须有合作关系
    效率低,风险高
程序接入支付:
    需要一家一家银行做对接,成本高
    最好对接第三方平台(第三方平台已经将大部分的银行进行了整合)
常见的第三方支付平台:
    微信支付
    支付宝支付
    易宝支付
    ....

支付宝支付

https://nxf.github.io/11_%E6%94%AF%E4%BB%98%E4%B8%AD%E5%BF%83-%E4%B8%8A.html

支付环境

沙箱环境

在我们的学习,考试中主要使用这个环境的信息,包含appId,支付网关地址,签名等信息。

沙箱环境(登录 - 支付宝)

访问此地址生成自己的沙箱环境,我们需要使用到沙箱环境中相关的数据

 

 

文档中心

小程序文档 - 支付宝文档中心

 

 

测试支付

java代码集成支付宝支付

0.环境搭建

DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `out_trade_no` varchar(255) DEFAULT NULL COMMENT '订单编号',
  `created` datetime DEFAULT NULL COMMENT '创建时间',
  `over_time` datetime DEFAULT NULL COMMENT '有效支付时间',
  `status` varchar(255) DEFAULT NULL COMMENT '状态',
  `phone` varchar(255) DEFAULT NULL COMMENT '用户手机号',
  `price` decimal(10,2) DEFAULT NULL COMMENT '支付金额',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
/*Data for the table `orders` */
insert  into `orders`(`id`,`out_trade_no`,`created`,`over_time`,`status`,`phone`,`price`) values 
(1,'1678982070619193344','2023-07-12 12:18:14','2023-07-12 12:48:14','PAID','18748108828','26.00'),
(2,'1678982070703079424','2023-07-12 12:18:14','2023-07-12 12:19:14','CLOSE','18748108828','687.00'),
(3,'1678982070732439552','2023-07-12 12:18:14','2023-07-12 12:48:14','PAID','18748108828','764.00'),
(4,'1678982070745022464','2023-07-12 12:18:14','2023-07-12 12:48:14','PAID','1874810882','503.00'),
(5,'1678982070753411072','2023-07-12 12:18:14','2023-07-12 12:48:14','INIT','18748108828','520.00'),
(6,'1678982070765993984','2023-07-12 12:18:14','2023-07-12 12:48:14','INIT','18748108828','346.00'),
(7,'1678982070778576896','2023-07-12 12:18:14','2023-07-12 12:48:14','INIT','18748108828','347.00'),
(8,'1678982070795354112','2023-07-12 12:18:14','2023-07-12 12:48:14','INIT','18748108828','624.00'),
(9,'1678982070812131328','2023-07-12 12:18:14','2023-07-12 12:48:14','INIT','18748108828','234.00'),
(10,'1678982070828908544','2023-07-12 12:18:14','2023-07-12 12:48:14','PAID','18748108828','210.00');

1.创建支付服务

导入依赖

<dependencies>
    <dependency>
        <groupId>com.alipay.sdk</groupId>
        <artifactId>alipay-sdk-java</artifactId>
        <version>4.33.50.ALL</version>
    </dependency>
</dependencies>

2.创建AlipayClient对象

package com.linlinchen.pay.config;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: linlinchen
 * @name:MyAliPayConfig
 * @Date:2023/7/28 16:03
 */
@Configuration // 声明配置类
public class MyAliPayConfig2 {
    // shift + end
    // 应用私钥
    public static final String PRIVATE_KEY = "自己的应用私钥";
    // 支付宝公钥
    public static final String ALIPAY_PUBLIC_KEY = "自己的支付宝公钥";
    // 沙箱环境网关地址
    public static final String SERVER_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
    // 应用ID
    public static final String APP_ID = "自己的APPID";

    @Bean
    public AlipayClient createAlipayClient() throws AlipayApiException {
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl(SERVER_URL);
        alipayConfig.setAppId(APP_ID);
        alipayConfig.setPrivateKey(PRIVATE_KEY);
        alipayConfig.setFormat("json");
        alipayConfig.setAlipayPublicKey(ALIPAY_PUBLIC_KEY);
        alipayConfig.setCharset("UTF8");
        alipayConfig.setSignType("RSA2");
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
        return alipayClient;
    }
}

3.去支付

  /*
    * 去付款
    * */
    @RequestMapping("/toPay/{id}")
    public String toPay(@PathVariable String id) throws AlipayApiException {
        //拿到订单信息
        TbOrders orders = ordersService.getById(id);
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        model.setOutTradeNo(orders.getOutTradeNo());
        model.setTotalAmount(orders.getPrice()+"");
        model.setSubject(orders.getProduct());
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        request.setBizModel(model);

        //同步跳转地址,仅支持http/https   //回调  跳转到回调方法
        request.setReturnUrl("http://localhost:10010/ordersservice/orders/callback");

        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            System.out.println("调用成功");

            //此处可以通过MQ发送一个延迟消息

         

        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
        }
        return response.getBody();
    }

4.支付结果回调

示例代码下载

去官方网站上下载示例代码

验签

@RequestMapping("/callback")
    public void callback(HttpServletRequest request, HttpServletResponse response, String out_trade_no) throws IOException, AlipayApiException {
        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 = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用d
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        boolean signVerified = AlipaySignature.rsaCheckV1(params,
                "你的支付宝公钥",
                "UTF8",
                "RSA2");
        if(signVerified){
            //成功  修改订单状态
            LambdaQueryWrapper<TbOrders> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TbOrders::getOutTradeNo,out_trade_no);
            TbOrders orders = ordersService.getOne(wrapper);
            orders.setStatus("PAID");
            ordersService.updateById(orders);

    


            log.info("支付成功,订单号:"+orders.getOutTradeNo());

            //重定向 跳回前端页面
            response.sendRedirect("http://localhost:8080/order");
        }else {
            //失败 跳回失败页面
            response.sendRedirect("http://localhost:8080/error");
        }

5.防止掉单处理

// 防止掉单--->扫单
    // 查询订单状态
    @RequestMapping("/query/{orderId}")
    public void scanOrder(@PathVariable String orderId) throws Exception {
        // 根据订单ID查询订单详情
        Orders orders = ordersService.getById(orderId);
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        // 设置订单编号,根据订单编号查询订单状态
        model.setOutTradeNo(orders.getOutTradeNo());
        request.setBizModel(model);
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        ObjectMapper objectMapper = new ObjectMapper();
        Map map = objectMapper.readValue(response.getBody(), Map.class);
        Map query_response = (Map)map.get("alipay_trade_query_response");
        String code = (String)query_response.get("code");
        String trade_status = (String)query_response.get("trade_status");
        System.out.println("交易状态:"+trade_status);
        //((Map)(new ObjectMapper().readValue(response.getBody().toString(),Map.class).get("alipay_trade_query_response"))).get("trade_status");
        if (response.isSuccess()) {
            // 判断状态码
            if ("10000".equals(code)){
                // 判断订单状态
                if ("TRADE_SUCCESS".equals(trade_status)){
                    // 当前订单支付成功
                    orders.setStatus("PAID");
                }else if ("TRADE_CLOSED".equals(trade_status)){
                    // 当前订单关闭
                    orders.setStatus("CLOSED");
                }else if ("TRADE_FINISHED".equals(trade_status)){
                    // 交易结束,不可退款
                    orders.setStatus("FINISHED");
                }
                ordersService.updateById(orders);
            }
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
        }
    }

6.退款

@RequestMapping("/refund/{id}")
public String refund(@PathVariable String id) throws Exception {
    String result = null;
    Orders order = ordersService.getById(id);
    // 请求语义对象
    AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
    // 请求参数封装
    AlipayTradeRefundModel model = new AlipayTradeRefundModel();
    model.setOutTradeNo(order.getOutTradeNo());
    model.setRefundAmount(order.getPrice()+"");
    // 将请求参数封装到请求语义对象中
    request.setBizModel(model);
    // 发送请求给支付宝
    AlipayTradeRefundResponse response = alipayClient.execute(request);
    System.out.println(response.getBody());
    ObjectMapper objectMapper = new ObjectMapper();
    Map map = objectMapper.readValue(response.getBody(), Map.class);
    Map params = (Map)map.get("alipay_trade_refund_response");
    // 调用接口是否成功
    if (response.isSuccess()) {
        System.out.println("调用成功");
        // 退款金额是否变更
        if ("Y".equals(params.get("fund_change"))){
            // 变更订单状态
            order.setStatus("REFUND");
            ordersService.updateById(order);
            result = "退款成功";
        }else {
            result = "已退款";
        }
    } else {
        System.out.println("调用失败");
        result="调用失败";
        // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
        // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
        // System.out.println(diagnosisUrl);
    }
    return result;
}

7.退款查询

// todo: 查询退款信息
@RequestMapping("/refund/query/{id}")
public String queryRefund(@PathVariable String id) throws Exception {
    String result = null;
    Orders order = ordersService.getById(id);
    // 请求语义对象
    AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
    // 请求参数对象
    AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
    model.setOutTradeNo(order.getOutTradeNo());
    model.setOutRequestNo(order.getOutTradeNo());
    // 将请求参数封装到请求语义对象中
    request.setBizModel(model);
    // 发送请求
    AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
    System.out.println(response.getBody());
    ObjectMapper objectMapper = new ObjectMapper();
    Map map = objectMapper.readValue(response.getBody(), Map.class);
    Map params = (Map)map.get("alipay_trade_fastpay_refund_query_response");
    if (response.isSuccess()) {
        System.out.println("调用成功");
        Object refund_status = params.get("refund_status");
        if (refund_status!=null){
            result = "当前订单已退款";
        }else{
            result = "当前订单未退款";
        }
    } else {
        System.out.println("调用失败");
        result = "调用失败";
        // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
        // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
        // System.out.println(diagnosisUrl);
    }
    return result;
}

8.下载订单

@RequestMapping("/downloadpay/{date}")
    public String downloadPayOrder(@PathVariable("date") String date) throws AlipayApiException {
        AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
        AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel();
        model.setBillType("trade");
        model.setBillDate(date);
        request.setBizModel(model);
        AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            System.out.println("调用成功");
            String url = response.getBillDownloadUrl();
            return url;
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
            return null;
        }
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值