支付宝实现当面付扫描支付退款及退款查询

发布时间:2018-11-23
 
技术:springboot1.5.6+jdk1.8+maven3.0.5
 

概述

封装了支付宝SDK,提供了支付、查询、退款(条码支付)等接口。

详细

 

概述

demo了介绍支付宝中当面付下属的条码支付、扫码支付、订单查询、退款申请等接口的集成开发过程。

 

 

详细

在移动支付行业中,支付宝一直占据龙头行业,市场占有率也遥遥领先。在聚合支付系统中,移动支付服务商一定将支付宝的支付接口接入。条码支付是支付宝在线下移动支付的一种收款方式。一般流程为消费者通过打开支付宝APP上的付款码,然后商家使用扫码枪或是扫码盒子等条码识别社保扫描消费者的条码/二维码,完成收款。消费者仅需要出示付款码,所有收款操作是有商户端完成。

 

业务的流程图为:

条码支付业务流程

消费者端流程:

blob.png

 

 

本例子主要基于支付宝的沙箱环境对怎么接入支付宝当面付的一个流程及使用springboot对支付宝sdk的下单、查询、退款等接口进行了一个封装。

 

一.准备工作

首先登录到支付宝蚂蚁金服的开发平台https://open.alipay.com/platform/home.htm,使用支付宝手机APP即可授权登录。登录进去效果如下:

blob.png

我们进入开发服务下面的研发服务,可以看到支付宝已经帮我们建好了沙箱应用,我们可以通过沙箱应用来模拟测试支付及查询、退款等接口,可以看到:

blob.png

 

应用公钥可以使用SHA2生成,也可以使用SHA1生成,SHA2是支付宝推荐的方式,本例也采取SHA2生成应用公钥,支付宝为我们提供了一个生成RSA密钥的工具,地址为https://docs.open.alipay.com/291/105971/,里面有介绍签名及验签的东西,如下图所示:

 

blob.png

接下来介绍一下支付提供的沙箱账号,我们可以在里面进行任意金额的充值进行模拟测试。

blob.png

我们可以使用安卓下载支付宝提供的沙箱支付宝应用进行账号登录。

blob.png

二、程序实现

1.首先创建springboot项目在pom.xml文件里面引入相关的依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <scope>test</scope>
   </dependency>
    
     <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
        
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
       </dependency>
        
       <dependency>
           <groupId>com.alipay.sdk</groupId>
           <artifactId>alipay-sdk-java</artifactId>
           <version>3.0.0</version>
       </dependency>
        
       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>fastjson</artifactId>
           <version>1.2.15</version>
      </dependency>

2.在application.yml文件添加如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server:
  port: 8080
 
 
alipay:
  app_id: xxxxx
  merchant_private_key: xxxxx
  alipay_public_key: xxxx
  notify_url: http://yourdomain:8080/notify_url
  return_url: http://yourdomain:8080/return_url
  sign_type: RSA2
  charset: utf-8
  gatewayUrl: https://openapi.alipaydev.com/gateway.do
  log_path: /tmp/

其中app_id为支付宝沙箱应用对应的app_id,merchant_private_key为商户私钥,alipay_public_key为支付宝公钥,主要用来验签

3.主要代码如下:

1)支付宝参数配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class AlipayConfig {
     
    @Value("${alipay.app_id}")
    public  String app_id;
 
    @Value("${alipay.merchant_private_key}")
    public String merchant_private_key;
 
    @Value("${alipay.alipay_public_key}")
    public String alipay_public_key;
 
    @Value("${alipay.notify_url}")
    public  String notify_url;
 
    @Value("${alipay.return_url}")
    public  String return_url;
 
    @Value("${alipay.sign_type}")
    public  String sign_type;
 
    @Value("${alipay.charset}")
    public  String charset;
 
    @Value("${alipay.gatewayUrl}")
    public String gatewayUrl;
 
    @Value("${alipay.log_path}")
    public String log_path;

 

2)生成二维码主要逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
QrCodeResponse qrCodeResponse = new QrCodeResponse();
        
        AlipayClient alipayClient =
                new DefaultAlipayClient(alipayConfig.getGatewayUrl(), alipayConfig.getApp_id(), alipayConfig.getMerchant_private_key(),
                        "JSON", alipayConfig.getCharset(), alipayConfig.getAlipay_public_key(), alipayConfig.getSign_type());
        
       AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
       request.setBizContent("{" +
               "\"out_trade_no\":\""+model.getOutTradeNo()+"\"," +
               "\"total_amount\":\""+model.getTotalAmount()+"\"," +
               "\"subject\":\""+model.getSubject()+"\"," +
               "\"timeout_express\":\"90m\"}");
        
       request.setNotifyUrl(alipayConfig.getNotify_url());
       AlipayTradePrecreateResponse alipayTradePrecreateResponse = null;
        
       try {
           alipayTradePrecreateResponse = alipayClient.execute(request);
       } catch (AlipayApiException e) {
           e.printStackTrace();
           qrCodeResponse.setCode("500");
           qrCodeResponse.setMsg("服务器内部错误");
           return qrCodeResponse;
       }
        
       QrResponse qrResponse = JSON.parseObject(alipayTradePrecreateResponse.getBody(),QrResponse.class);
        
       qrCodeResponse = qrResponse.getAlipay_trade_precreate_response();
       return qrCodeResponse;

3)回调通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Map<String, String> map = HttpRequestUtil.ParamstoMap(request);
       QrServiceModel qrServiceEntity = new QrServiceModel();
       qrServiceEntity.setIsreceive(false);
       for (String key :map.keySet()) {
           System.out.println("[ "+key + " = "+map.get(key)+" ]");
       }
       try {
           boolean flag = AlipaySignature.rsaCheckV1(map,alipayConfig.getAlipay_public_key() ,alipayConfig.getCharset(),
                   alipayConfig.getSign_type());
           String json = JSON.toJSONString(map);
           logger.info("Alipay notify===>"+json);
           if (flag) {
               qrServiceEntity.setTran_starus(map.get("trade_status"));
               return qrServiceEntity;
           }
           else {
               return qrServiceEntity;
           }
       } catch (AlipayApiException e) {
           e.printStackTrace();
           return qrServiceEntity;
       }

 

4)查询订单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
AlipayClient alipayClient =
                new DefaultAlipayClient(alipayConfig.getGatewayUrl(), alipayConfig.getApp_id(), alipayConfig.getMerchant_private_key(),
                        "JSON", alipayConfig.getCharset(), alipayConfig.getAlipay_public_key(), alipayConfig.getSign_type());
         
           AlipayTradeQueryRequest aliqueryRequest = new AlipayTradeQueryRequest();
           AlipayTradeQueryModel bizModel = new AlipayTradeQueryModel();
           bizModel.setOutTradeNo(queryRequest.getOutTradeNo());
           aliqueryRequest.setBizModel(bizModel);
            
           /*alipayTradeQueryRequest.setBizContent("{" +
                   "\"out_trade_no\":\""+queryRequest.getOutTradeNo()+"\"" +
 
                   "}");*/
           AlipayTradeQueryResponse response = new AlipayTradeQueryResponse();
               try {
                   response = alipayClient.execute(aliqueryRequest);
                   if(response.getCode().equals("10000")){
                       System.out.println("业务处理成功!");
                       switch (response.getTradeStatus()) {
                       case "WAIT_BUYER_PAY":
                           logger.info("交易创建,等待买家付款");
                           break;
                       case "TRADE_CLOSED":
                           logger.info("未付款交易超时关闭,或支付完成后全额退款");
                           break;
                       case "TRADE_SUCCESS":
                           logger.info("交易支付成功");
                           break;
                       case "TRADE_FINISHED":
                           logger.info("交易结束,不可退款");
                           break;
                       default:
                           break;
                       }
 
                   }else if(response.getCode().equals("40004")){
                       logger.info("业务处理失败!");
                   }else if(response.getCode().equals("20000")){
                       logger.info("系统异常!");
                   }
                   logger.info(response.getBody());
               } catch (AlipayApiException e) {
                   e.printStackTrace();
               }
                
       QueryResponse queryResponse  =  JSON.parseObject(response.getBody(),QueryResponse.class);
       return queryResponse.getAlipay_trade_query_response();

 

5)退款

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
AlipayClient alipayClient =
                new DefaultAlipayClient(alipayConfig.getGatewayUrl(), alipayConfig.getApp_id(), alipayConfig.getMerchant_private_key(),
                        "JSON", alipayConfig.getCharset(), alipayConfig.getAlipay_public_key(), alipayConfig.getSign_type());
            
            
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        
            request.setBizContent(JSON.toJSONString(requestRequest));
             
            AlipayTradeRefundResponse response = null;
             
            try {
                response = alipayClient.execute(request);
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }
             
            if(response.isSuccess()){
                RefundResponseSign refundResponseSign = JSON.parseObject(response.getBody(),RefundResponseSign.class);
                return refundResponseSign.getAlipay_trade_refund_response();
            }
             
            return null;

 

三、项目结构图

blob.png

 

四、运行效果图

本例子使用postman工具进行模拟测试。

1.生成二维码效果图:

blob.pngblob.png

2.退款接口效果图:

blob.png

3.退款查询效果图:

blob.png

4.订单查询结果效果图:

blob.png

 

五、补充

本例子使用支付宝的沙箱环境展示了如何从零开始,使用蚂蚁金服开放平台服务端SDK快速接入当面付产品,完成与支付宝对接的部分。测试回调可以使用花生壳工具进行一个内网穿透进行测试。在实际应用中,只要配置好appId,商户私钥以及支付宝公钥即可完成本例子上述的功能。关于RSA密钥工具可以从支付宝里下载,本例子demo里面也附带了。

 

 



注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

posted on   demo例子集  阅读(4249)  评论(0编辑  收藏  举报

(评论功能已被禁用)
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示