最近公司要做一个有关支付的相关项目,需要对接支付宝的支付接口,实现扫描二维码支付功能,为此研究了一下支付宝相关业务。
先看一下支付宝扫描二维码支付的业务流程,直接摘出来如下:
扫码支付(接入指引)
扫码支付,指用户打开支付宝钱包中的“扫一扫”功能,扫描商家展示在某收银场景下的二维码并进行支付的模式。该模式适用于线下实体店支付、面对面支付等场景。
业务流程:
使用步骤:
- 收银员在商家收银系统操作生成支付宝订单,并生成二维码;
- 用户登录支付宝钱包,点击首页“付款-扫码付”或直接点击“扫一扫”,进入扫一扫界面;
- 用户扫收银员提供的二维码,核对金额,确认支付;
- 用户付款后商家收银系统会拿到支付成功或者失败的结果。
产品特点:
- 用户仅出示手机扫码即可完成付款,方便快捷;
- 资金实时到账,无现金流压力。
基本上我们开发常用的也就是一个生成二维码的预创建订单接口,一个取消,一个退款,一个支付成功后的回调接口
接下来,我们开始准备环境进行开发,不管是运行官方的demo还是集成到项目中,我们都需要进行相应的环境准备,目前,网上的沙箱环境比较多,我就直接配置个人商家的真实环境来记录博客,沙箱环境本博主在公司里面搭建过,今天在家就用自己支付宝开发商家环境,更为真实的记录这个过程。
其实支付宝这块的api开发接口文档等还是写的比较明白的,如果真的是有搞不定的地方也是可以在线询问支付宝技术客服的,而且回复的速度也是挺快。现在支付宝的验签功能已经封装了,不需要我们在自己实现验签功能。挺方便
配置环境我们直接点击上面的连接接入指引按照步骤进行:
一、创建应用
创建完成就分配了appid,
红框设置步骤如下:
设置应用公钥
保存之后生成支付宝公钥
上述全部设置完成以后提交审核
接下来等待审核通过即可,
DEMO运行
下载demo地址-------> https://docs.open.alipay.com/194/105201/
解压后然后导入普通工程
导入后目录结构如下
然后根据demo进行
# 直接运行demo步骤如下(eclipse直接导入工程即可):
1、请先确认zfbinfo.properties配置文件是否已配置完成
2、运行Main.java中的main方法
我们主要修改的是zfbinfo.properties文件配置私钥,支付宝公钥,pid,appid等信息即可运行
1 # 支付宝网关名、partnerId和appId #注意区分沙箱环境和在线环境
2 open_api_domain = https://openapi.alipay.com/gateway.do(要填写)
3 mcloud_api_domain = http://mcloudmonitor.com/gateway.do
4 pid = 此处请填写你的PID
5 appid = 此处请填写你当面付的APPID
6
7 # RSA私钥、公钥和支付宝公钥
8 private_key = 此处请填写你的商户私钥且转PKCS8格式(要填写)
9 public_key = 此处请填写你的商户公钥(要填写)
10
11 #SHA1withRsa对应支付宝公钥(这是非java的形式要填写)
12 #alipay_public_key =
13
14 #SHA256withRsa对应支付宝公钥(java要填写)
15 alipay_public_key =
16
17 # 签名类型: RSA->SHA1withRsa,RSA2->SHA256withRsa
18 sign_type = RSA2
19 # 当面付最大查询次数和查询间隔(毫秒)
20 max_query_retry = 5
21 query_duration = 5000
22
23 # 当面付最大撤销次数和撤销间隔(毫秒)
24 max_cancel_retry = 3
25 cancel_duration = 2000
26
27 # 交易保障线程第一次调度延迟和调度间隔(秒)
28 heartbeat_delay = 5
29 heartbeat_duration = 900
View Code
只要填写正确就可以直接通过main方法测试运行。
接下来我们看看怎么集成到我们自己的项目中,作为一个接口提供出去给前端或者app调用,这个其实demo里面readme也说的很清楚,先把readme整个贴出来
DEMO里的readme
1 # DEMO仅供参考,实际开发中需要结合具体业务场景修改使用
2 #
3 # 运行环境:jdk1.6及以上
4 # 当面付2.0demo使用前必读
5
6 # 直接运行demo步骤如下(eclipse直接导入工程即可):
7 1、请先确认zfbinfo.properties配置文件是否已配置完成
8 2、运行Main.java中的main方法
9
10 # 集成至商户系统步骤如下(以maven工程结构为例):
11 1、拷贝java目录下的Main.java(和DemoHbRunner.java,如果需要集成交易保障接口)至系统商源代码目录
12 2、将lib目录下所有jar文件添加至系统商lib目录,如果没有alipay-trade-sdk.jar(此jar包集成了当面付交易逻辑和交易保障接口),则将TradePaySDK编译为该jar包
13 3、拷贝resources目录下的配置文件至系统商classpath根目录
14 4、在系统商项目中运行Main方法,确认集成无误
15 5、系统商使用main方法中的调用样例进行商户端系统开发
16
17 Q:扫码支付、统一下单+JSAPI唤起收银台支付后,支付成功异步通知如何处理?
18 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
19 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额)
20 3、校验通知中的seller_id(或者seller_email) 是否为该笔交易对应的操作方(一个商户可能有多个seller_id/seller_email)
21 4、验证接口调用方的app_id。。
22
23 # 交易保障接口常见问题
24 https://doc.open.alipay.com/doc2/detail.htm?spm=0.0.0.0.yzagzo&treeId=26&articleId=103903&docType=1
25
26 ### 当面付2.0demo代码结构TradePayDemo ###
27 src
28 └── main
29 ├── java
30 │ └── com
31 │ └── alipay
32 │ └── demo
33 │ └── trade
34 │ ├── DemoHbRunner.java # 交易保障数据收集器的范例实现,如果接入交易保障接口,参考此类实现,调用参考Main方法
35 │ └── Main.java ######## 当面付2.0调用范例 ########
36 ├── resources
37 │ └── zfbinfo.properties # 配置文件,调用Main方法之前请确认配置文件是否已正确配置
38 └── webapp
39 ├── WEB-INF
40 │ ├── lib # 依赖类库
41 │ │ ├── alipay-sdk-java20151021120052-source.jar
42 │ │ ├── alipay-sdk-java20151021120052.jar
43 │ │ ├── commons-codec-1.10.jar
44 │ │ ├── alipay-trade-sdk.jar # TradePaySDK模块创建生成的lib
45 │ │ ├── commons-configuration-1.10.jar
46 │ │ ├── commons-lang-2.6.jar
47 │ │ ├── commons-logging-1.1.1.jar
48 │ │ ├── core-2.1.jar
49 │ │ ├── gson-2.3.1.jar
50 │ │ └── hamcrest-core-1.3.jar
51 │ └── web.xml
52 ├── images
53 │ ├── alipay.gif
54 │ └── new-btn-fixed.png
55 ├── index.html # web方式调用当面付的首页
56 ├── trade_pay.jsp # 当面付2.0条码支付web界面,本质和Main方法中条码支付方法一致
57 ├── trade_precreate.jsp # 当面付2.0预下单web界面,本质和Main方法中预下单方法一致
58 ├── trade_query.jsp # 当面付2.0查询web界面,本质和Main方法中查询方法一致
59 └── trade_refund.jsp # 当面付2.0退货界面,本质和Main方法中退货方法一致
60
61 ### 当面付2.0sdk代码结构TradePaySDK ###
62 src
63 └── main
64 ├── java
65 │ └── com
66 │ └── alipay
67 │ └── demo
68 │ └── trade
69 │ ├── config
70 │ │ ├── Configs.java # 配置文件,解析properties文件
71 │ │ └── Constants.java # 常量定义
72 │ ├── model
73 │ │ ├── ExtendParams.java # 扩展参数
74 │ │ ├── GoodsDetail.java
75 │ │ ├── TradeStatus.java
76 │ │ ├── builder # 当面付2.0请求包
77 │ │ │ ├── AlipayHeartbeatSynContentBuilder.java # 服务保障接口请求bizContent结构体
78 │ │ │ ├── AlipayTradePayContentBuilder.java # 条码支付请求bizContent结构体
79 │ │ │ ├── AlipayTradePrecreateContentBuilder.java # 扫码支付(产生二维码)请求bizContent结构体
80 │ │ │ ├── AlipayTradeQueryCententBuilder.java # 当面付2.0查询请求bizContent结构体
81 │ │ │ ├── AlipayTradeRefundContentBuilder.java # 当面付2.0退款请求bizContent结构体
82 │ │ │ └── RequestBuilder.java # 请求抽象类
83 │ │ ├── hb # 服务保障接口数据模型
84 │ │ │ ├── EquipStatus.java # 发送心跳时的设备状态枚举
85 │ │ │ ├── EquipStatusAdapter.java
86 │ │ │ ├── ExceptionInfo.java # 异常信息枚举
87 │ │ │ ├── ExceptionInfoAdapter.java
88 │ │ │ ├── HbStatus.java # 交易状态
89 │ │ │ ├── PosTradeInfo.java # 机具商同步使用的交易结构体
90 │ │ │ ├── Product.java # 发送心跳的设备所依赖的支付宝产品
91 │ │ │ ├── SysTradeInfo.java # 系统商同步使用的交易结构体
92 │ │ │ ├── TradeInfo.java # 交易结构体接口,用于隐藏系统商交易结构体和机具商交易结构体的不同
93 │ │ │ ├── TradeInfoAdapter.java
94 │ │ │ └── Type.java # 发送心跳的设备类型枚举
95 │ │ └── result 当面付2.0应答包
96 │ │ ├── AlipayF2FPayResult.java # 当面付2.0支付应答
97 │ │ ├── AlipayF2FPrecreateResult.java # 当面付2.0预下单(产生二维码)应答
98 │ │ ├── AlipayF2FQueryResult.java # 当面付2.0查询应答
99 │ │ ├── AlipayF2FRefundResult.java # 当面付2.0退货应答
100 │ │ └── Result.java
101 │ ├── service
102 │ │ ├── AlipayMonitorService.java # 提供交易保障服务
103 │ │ ├── AlipayTradeService.java # 提供当面付2.0服务
104 │ │ └── impl
105 │ │ ├── AbsAlipayService.java # 服务实现类抽象类,所有的服务实现类的父类
106 │ │ ├── AbsAlipayTradeService.java # 当面付服务实现类抽象类,包含了当面付2.0预下单、查询、退货交易的封装
107 │ │ ├── AlipayMonitorServiceImpl.java # 交易保障服务具体实现
108 │ │ ├── AlipayTradeServiceImpl.java # 当面付2.0具体实现(不提供交易保障接口的集成)
109 │ │ ├── AlipayTradeWithHBServiceImpl.java # 当面付2.0具体实现(集成了交易保障逻辑)
110 │ │ └── hb # 交易保障逻辑相关代码
111 │ │ ├── AbsHbRunner.java # 抽象的交易保障数据收集器,系统商创建自己的子类用于自定义收集数据,参考DemoHbRunner
112 │ │ ├── HbListener.java # 交易保障监听器实现,每当交易完成后,将交易耗时写入队列
113 │ │ ├── HbQueue.java # 保存交易数据的队列,添加队列每次只加入1条交易,读取队列每次尽量读满30条交易
114 │ │ └── TradeListener.java # 交易监听接口,在当面付交易流程中加入监听逻辑
115 │ └── utils
116 │ ├── GsonFactory.java # 使用了gson序列化
117 │ ├── Utils.java # 杂物工具类
118 │ └── ZxingUtils.java # 使用了zxing库进行二维码的生成
119 └── lib # 依赖类库
120 ├── alipay-sdk-java20151021120052-source.jar # 支付宝底层api调用的sdk源码
121 ├── alipay-sdk-java20151021120052.jar
122 ├── commons-codec-1.10.jar
123 ├── commons-configuration-1.10.jar
124 ├── commons-lang-2.6.jar
125 ├── commons-logging-1.1.1.jar
126 ├── core-2.1.jar
127 ├── gson-2.3.1.jar
128 └── hamcrest-core-1.3.jar
129
130 # DEMO仅供参考,实际开发中需要结合具体业务场景修改使用
View Code
重点是:
# 集成至商户系统步骤如下(以maven工程结构为例):
1、拷贝java目录下的Main.java(和DemoHbRunner.java,如果需要集成交易保障接口)至系统商源代码目录
2、将lib目录下所有jar文件添加至系统商lib目录,如果没有alipay-trade-sdk.jar(此jar包集成了当面付交易逻辑和交易保障接口),则将TradePaySDK编译为该jar包
3、拷贝resources目录下的配置文件至系统商classpath根目录
4、在系统商项目中运行Main方法,确认集成无误
5、系统商使用main方法中的调用样例进行商户端系统开发
Q:扫码支付、统一下单+JSAPI唤起收银台支付后,支付成功异步通知如何处理?
1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额)
3、校验通知中的seller_id(或者seller_email) 是否为该笔交易对应的操作方(一个商户可能有多个seller_id/seller_email)
4、验证接口调用方的app_id。。
这里我们其实只需要alipay-sdk-java-3.3.0.jar个及相关的commons-logging-1.1.1.jar,生成二维码需要的包core-2.1.jar即可。然后新建springboot的maven项目
接下来就是大家都知道的
1.添加jar包
2.配置属性文件
3.编写支付相关代码(这个可以直接去官网拷贝即可https://docs.open.alipay.com/194/105203/,都有示例,拷贝后修改一下即可)
上代码
新建springboot项目,项目结构如下图:
pom
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.0.5.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>com.sharp</groupId>
12 <artifactId>alipay</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>alipay</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 </properties>
20
21 <dependencies>
22 <dependency>
23 <groupId>org.springframework.boot</groupId>
24 <artifactId>spring-boot-starter-web</artifactId>
25 </dependency>
26
27 <dependency>
28 <groupId>org.springframework.boot</groupId>
29 <artifactId>spring-boot-starter-test</artifactId>
30 <scope>test</scope>
31 </dependency>
32 <!-- 支付接口配置 -->
33 <dependency>
34 <groupId>com.alipay.sdk</groupId>
35 <artifactId>alipay-sdk-java</artifactId>
36 <version>3.4.49.ALL</version>
37 </dependency>
38 <!-- 支付接口需要依赖commons-logging:jar:1.1.1 -->
39 <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
40 <dependency>
41 <groupId>commons-logging</groupId>
42 <artifactId>commons-logging</artifactId>
43 <version>1.1.1</version>
44 </dependency>
45 <!-- 生成支付二维码需要jar -->
46 <!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
47 <dependency>
48 <groupId>com.google.zxing</groupId>
49 <artifactId>core</artifactId>
50 <version>3.3.3</version>
51 </dependency>
52
53 </dependencies>
54
55 <build>
56 <plugins>
57 <plugin>
58 <groupId>org.springframework.boot</groupId>
59 <artifactId>spring-boot-maven-plugin</artifactId>
60 </plugin>
61 </plugins>
62 </build>
63
64 </project>
View Code
zfbinfo属性文件
1 # 支付宝网关名、partnerId和appId
2 open_api_domain=https://openapi.alipaydev.com/gateway.do
3 mcloud_api_domain = http://mcloudmonitor.com/gateway.do
4 pid = ¥¥¥¥¥¥¥¥¥¥¥¥¥¥
5 appid = ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
6
7 # RSA私钥、公钥和支付宝公钥
8 private_key = &&&&&&&&&&&&&&&
9 public_key = ***************************
10 #SHA1withRsa对应支付宝公钥
11 #alipay_public_key = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB
12
13 #SHA256withRsa对应支付宝公钥
14 alipay_public_key = *******
15
16 # 签名类型: RSA->SHA1withRsa,RSA2->SHA256withRsa
17 sign_type = RSA2
18 # 当面付最大查询次数和查询间隔(毫秒)
19 max_query_retry = 5
20 query_duration = 5000
21
22 # 当面付最大撤销次数和撤销间隔(毫秒)
23 max_cancel_retry = 3
24 cancel_duration = 2000
25
26 # 交易保障线程第一次调度延迟和调度间隔(秒)
27 heartbeat_delay = 5
28 heartbeat_duration = 900
View Code
config类初始化zfbinfo的属性文件
1 /**
2 *
3 */
4 package com.sharp.alipay.config;
5
6 import org.springframework.beans.factory.annotation.Value;
7 import org.springframework.context.annotation.Configuration;
8 import org.springframework.context.annotation.ImportResource;
9
10 /**
11 * @Title zfbConfig.java
12 * @author 醉逍遥
13 * @date 2018年12月15日
14 * @version 1.0
15 */
16 @Configuration
17 @ImportResource(value="classpath:zfbinfo.properties")
18 public class zfbConfig {
19 // 以下配置可以写死,也可从属性文件中取出均可
20 // # 支付宝网关名、partnerId和appId
21 @Value("${open_api_domain}")
22 private static final String open_api_domain="https://openapi.alipaydev.com/gateway.do";
23 // private static final String mcloud_api_domain = "http://mcloudmonitor.com/gateway.do";
24 private static final String pid = "*****************";
25 private static final String appid = "*****************";
26
27 // # RSA私钥、公钥和支付宝公钥
28 private static final String private_key = "***************************************";
29 private static final String public_key = "*********************";
30 // #SHA1withRsa对应支付宝公钥
31 // #alipay_public_key = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB
32
33 // #SHA256withRsa对应支付宝公钥
34 private static final String alipay_public_key = "*****************";
35
36 // # 签名类型: RSA->SHA1withRsa,RSA2->SHA256withRsa
37 private static final String sign_type = "RSA2";
38 // ********************************************以下不用暂时注释掉*********************************************
39 // # 当面付最大查询次数和查询间隔(毫秒)
40 /*max_query_retry = 5
41 query_duration = 5000
42
43 # 当面付最大撤销次数和撤销间隔(毫秒)
44 max_cancel_retry = 3
45 cancel_duration = 2000
46
47 # 交易保障线程第一次调度延迟和调度间隔(秒)
48 heartbeat_delay = 5
49 heartbeat_duration = 900*/
50
51 }
View Code
controller均是支付宝api示例修改即可
1 /**
2 *
3 */
4 package com.sharp.alipay.controller;
5
6 import javax.servlet.http.HttpServletRequest;
7
8 import org.springframework.web.bind.annotation.PostMapping;
9 import org.springframework.web.bind.annotation.RequestMapping;
10 import org.springframework.web.bind.annotation.RestController;
11
12 import com.alipay.api.AlipayApiException;
13 import com.alipay.api.AlipayClient;
14 import com.alipay.api.DefaultAlipayClient;
15 import com.alipay.api.request.AlipayTradeCancelRequest;
16 import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
17 import com.alipay.api.request.AlipayTradePrecreateRequest;
18 import com.alipay.api.request.AlipayTradeQueryRequest;
19 import com.alipay.api.request.AlipayTradeRefundRequest;
20 import com.alipay.api.response.AlipayTradeCancelResponse;
21 import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
22 import com.alipay.api.response.AlipayTradePrecreateResponse;
23 import com.alipay.api.response.AlipayTradeQueryResponse;
24 import com.alipay.api.response.AlipayTradeRefundResponse;
25 import com.sharp.alipay.util.ZxingUtils;
26
27 /**
28 * @Title AlipayController.java
29 * @author 醉逍遥
30 * @date 2018年12月15日
31 * @version 1.0
32 */
33 @RestController
34 @RequestMapping("/alipay")
35 public class AlipayController {
36 @PostMapping("precreate")
37 public String precreate() {
38 AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
39 AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
40 // 设置支付成功后的回调地址,改地址必须外网可以访问到才行,所以调试该步骤必须要在外网环境,否则会出现支付成功但是却不能回调
41 request.setNotifyUrl("最下面一个方法notify_url的含域名的绝对路径,外网一定要可以访问哦");
42 request.setBizContent("{" +
43 "\"out_trade_no\":\"20150320010101001\"," +
44 "\"seller_id\":\"2088102146225135\"," +
45 "\"total_amount\":88.88," +
46 "\"discountable_amount\":8.88," +
47 "\"subject\":\"Iphone6 16G\"," +
48 " \"goods_detail\":[{" +
49 " \"goods_id\":\"apple-01\"," +
50 "\"goods_name\":\"ipad\"," +
51 "\"quantity\":1," +
52 "\"price\":2000," +
53 "\"goods_category\":\"34543238\"," +
54 "\"categories_tree\":\"124868003|126232002|126252004\"," +
55 "\"body\":\"特价手机\"," +
56 "\"show_url\":\"http://www.alipay.com/xxx.jpg\"" +
57 " }]," +
58 "\"body\":\"Iphone6 16G\"," +
59 "\"operator_id\":\"yx_001\"," +
60 "\"store_id\":\"NJ_001\"," +
61 "\"disable_pay_channels\":\"pcredit,moneyFund,debitCardExpress\"," +
62 "\"enable_pay_channels\":\"pcredit,moneyFund,debitCardExpress\"," +
63 "\"terminal_id\":\"NJ_T_001\"," +
64 "\"extend_params\":{" +
65 "\"sys_service_provider_id\":\"2088511833207846\"," +
66 "\"industry_reflux_info\":\"{\\\\\\\"scene_code\\\\\\\":\\\\\\\"metro_tradeorder\\\\\\\",\\\\\\\"channel\\\\\\\":\\\\\\\"xxxx\\\\\\\",\\\\\\\"scene_data\\\\\\\":{\\\\\\\"asset_name\\\\\\\":\\\\\\\"ALIPAY\\\\\\\"}}\"," +
67 "\"card_type\":\"S0JP0000\"" +
68 " }," +
69 "\"timeout_express\":\"90m\"," +
70 "\"settle_info\":{" +
71 " \"settle_detail_infos\":[{" +
72 " \"trans_in_type\":\"cardSerialNo\"," +
73 "\"trans_in\":\"A0001\"," +
74 "\"summary_dimension\":\"A0001\"," +
75 "\"settle_entity_id\":\"2088xxxxx;ST_0001\"," +
76 "\"settle_entity_type\":\"SecondMerchant、Store\"," +
77 "\"amount\":0.1" +
78 " }]" +
79 " }," +
80 "\"merchant_order_no\":\"20161008001\"," +
81 "\"business_params\":\"{\\\"data\\\":\\\"123\\\"}\"," +
82 "\"qr_code_timeout_express\":\"90m\"" +
83 " }");
84 AlipayTradePrecreateResponse response;
85 try {
86 response = alipayClient.execute(request);
87 if(response.isSuccess()){
88 System.out.println("调用成功");
89 String qr_code = response.getQrCode();
90 // 需要修改为运行机器上的路径
91 String filePath = String.format("d:/qr-%s.png",
92 response.getOutTradeNo());
93 System.out.println("filePath:" + filePath);
94 ZxingUtils.getQRCodeImge(response.getQrCode(), 256, filePath);
95 return qr_code;
96 } else {
97 System.out.println("调用失败");
98 return"调用失败";
99 }
100 } catch (AlipayApiException e) {
101 // TODO Auto-generated catch block
102 e.printStackTrace();
103 return"调用异常";
104 }
105
106 }
107 // 撤销
108 public String cancel() {
109 AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
110 AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
111 request.setBizContent("{" +
112 "\"out_trade_no\":\"20150320010101001\"," +
113 "\"trade_no\":\"2014112611001004680073956707\"" +
114 " }");
115 AlipayTradeCancelResponse response;
116 try {
117 response = alipayClient.execute(request);
118 if(response.isSuccess()){
119 System.out.println("调用成功");
120 return "success";
121 } else {
122 System.out.println("调用失败");
123 return "false";
124 }
125 } catch (AlipayApiException e) {
126 // TODO Auto-generated catch block
127 e.printStackTrace();
128 return "exception";
129 }
130
131 }
132 public void query() {
133 AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
134 AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
135 request.setBizContent("{" +
136 "\"out_trade_no\":\"20150320010101001\"," +
137 "\"trade_no\":\"2014112611001004680 073956707\"," +
138 "\"org_pid\":\"2088101117952222\"" +
139 " }");
140 AlipayTradeQueryResponse response;
141 try {
142 response = alipayClient.execute(request);
143 if(response.isSuccess()){
144 System.out.println("调用成功");
145 } else {
146 System.out.println("调用失败");
147 }
148 } catch (AlipayApiException e) {
149 // TODO Auto-generated catch block
150 e.printStackTrace();
151 }
152
153 }
154 // 退款
155 public void refund() {
156 AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
157 AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
158 request.setBizContent("{" +
159 "\"out_trade_no\":\"20150320010101001\"," +
160 "\"trade_no\":\"2014112611001004680073956707\"," +
161 "\"refund_amount\":200.12," +
162 "\"refund_currency\":\"USD\"," +
163 "\"refund_reason\":\"正常退款\"," +
164 "\"out_request_no\":\"HZ01RF001\"," +
165 "\"operator_id\":\"OP001\"," +
166 "\"store_id\":\"NJ_S_001\"," +
167 "\"terminal_id\":\"NJ_T_001\"," +
168 " \"goods_detail\":[{" +
169 " \"goods_id\":\"apple-01\"," +
170 "\"alipay_goods_id\":\"20010001\"," +
171 "\"goods_name\":\"ipad\"," +
172 "\"quantity\":1," +
173 "\"price\":2000," +
174 "\"goods_category\":\"34543238\"," +
175 "\"categories_tree\":\"124868003|126232002|126252004\"," +
176 "\"body\":\"特价手机\"," +
177 "\"show_url\":\"http://www.alipay.com/xxx.jpg\"" +
178 " }]," +
179 " \"refund_royalty_parameters\":[{" +
180 " \"royalty_type\":\"transfer\"," +
181 "\"trans_out\":\"2088101126765726\"," +
182 "\"trans_out_type\":\"userId\"," +
183 "\"trans_in_type\":\"userId\"," +
184 "\"trans_in\":\"2088101126708402\"," +
185 "\"amount\":0.1," +
186 "\"amount_percentage\":100," +
187 "\"desc\":\"分账给2088101126708402\"" +
188 " }]," +
189 "\"org_pid\":\"2088101117952222\"" +
190 " }");
191 AlipayTradeRefundResponse response;
192 try {
193 response = alipayClient.execute(request);
194 if(response.isSuccess()){
195 System.out.println("调用成功");
196 } else {
197 System.out.println("调用失败");
198 }
199 } catch (AlipayApiException e) {
200 // TODO Auto-generated catch block
201 e.printStackTrace();
202 }
203
204 }
205
206 public void refund_query() {
207 AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
208 AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
209 request.setBizContent("{" +
210 "\"trade_no\":\"20150320010101001\"," +
211 "\"out_trade_no\":\"2014112611001004680073956707\"," +
212 "\"out_request_no\":\"2014112611001004680073956707\"," +
213 "\"org_pid\":\"2088101117952222\"" +
214 " }");
215 AlipayTradeFastpayRefundQueryResponse response;
216 try {
217 response = alipayClient.execute(request);
218 if(response.isSuccess()){
219 System.out.println("调用成功");
220 } else {
221 System.out.println("调用失败");
222 }
223 } catch (AlipayApiException e) {
224 // TODO Auto-generated catch block
225 e.printStackTrace();
226 }
227
228 }
229
230
231 //异步通知
232 @PostMapping("notify_url")
233 public void notify_url(HttpServletRequest request) {
234 //写回调后的业务逻辑,按照相关api进行取值即可。
235 }
236 }
View Code
生成二维码的工具类
1 package com.sharp.alipay.util;
2
3 import com.google.zxing.BarcodeFormat;
4 import com.google.zxing.EncodeHintType;
5 import com.google.zxing.MultiFormatWriter;
6 import com.google.zxing.common.BitMatrix;
7 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10
11 import javax.imageio.ImageIO;
12 import java.awt.image.BufferedImage;
13 import java.io.File;
14 import java.io.IOException;
15 import java.util.Hashtable;
16 import java.util.Map;
17
18 /**
19 * Created by liuyangkly on 15/6/27.
20 * 使用了google zxing作为二维码生成工具
21 */
22 public class ZxingUtils {
23 private static Log log = LogFactory.getLog(ZxingUtils.class);
24
25 private static final int BLACK = 0xFF000000;
26 private static final int WHITE = 0xFFFFFFFF;
27
28 private static BufferedImage toBufferedImage(BitMatrix matrix) {
29 int width = matrix.getWidth();
30 int height = matrix.getHeight();
31 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
32 for (int x = 0; x < width; x++) {
33 for (int y = 0; y < height; y++) {
34 image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
35 }
36 }
37 return image;
38 }
39
40 private static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {
41 BufferedImage image = toBufferedImage(matrix);
42 if (!ImageIO.write(image, format, file)) {
43 throw new IOException("Could not write an image of format " + format + " to " + file);
44 }
45 }
46
47 /** 将内容contents生成长宽均为width的图片,图片路径由imgPath指定
48 */
49 public static File getQRCodeImge(String contents, int width, String imgPath) {
50 return getQRCodeImge(contents, width, width, imgPath);
51 }
52
53 /** 将内容contents生成长为width,宽为width的图片,图片路径由imgPath指定
54 */
55 public static File getQRCodeImge(String contents, int width, int height, String imgPath) {
56 try {
57 Map<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
58 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
59 hints.put(EncodeHintType.CHARACTER_SET, "UTF8");
60
61 BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);
62
63 File imageFile = new File(imgPath);
64 writeToFile(bitMatrix, "png", imageFile);
65
66 return imageFile;
67
68 } catch (Exception e) {
69 log.error("create QR code error!", e);
70 return null;
71 }
72 }
73 }
View Code
启动类没有任何变动还是生成项目的类
1 package com.sharp.alipay;
2
3 import org.springframework.boot.SpringApplication;
4 import org.springframework.boot.autoconfigure.SpringBootApplication;
5
6 @SpringBootApplication
7 public class AlipayApplication {
8
9 public static void main(String[] args) {
10 SpringApplication.run(AlipayApplication.class, args);
11 }
12
13 }
View Code
以上,就是整个支付宝整合的例子,本博主在工作上直接运行成功的,本篇博文,没有再去进行实际测试,仅仅记录一个对接支付宝的思路过程,总结记录以备后用。