支付宝当面付扫码支付接口开发
最近公司要做一个有关支付的相关项目,需要对接支付宝的支付接口,实现扫描二维码支付功能,为此研究了一下支付宝相关业务。主要依据就是支付宝的相关接口文档:
https://docs.open.alipay.com/catalog,重点关注如下红色方框部分
先看一下支付宝扫描二维码支付的业务流程,直接摘出来如下:
扫码支付(接入指引)
扫码支付,指用户打开支付宝钱包中的“扫一扫”功能,扫描商家展示在某收银场景下的二维码并进行支付的模式。该模式适用于线下实体店支付、面对面支付等场景。
业务流程:
使用步骤:
- 收银员在商家收银系统操作生成支付宝订单,并生成二维码;
- 用户登录支付宝钱包,点击首页“付款-扫码付”或直接点击“扫一扫”,进入扫一扫界面;
- 用户扫收银员提供的二维码,核对金额,确认支付;
- 用户付款后商家收银系统会拿到支付成功或者失败的结果。
产品特点:
- 用户仅出示手机扫码即可完成付款,方便快捷;
- 资金实时到账,无现金流压力。
基本上我们开发常用的也就是一个生成二维码的预创建订单接口,一个取消,一个退款,一个支付成功后的回调接口
接下来,我们开始准备环境进行开发,不管是运行官方的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等信息即可运行
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
只要填写正确就可以直接通过main方法测试运行。
接下来我们看看怎么集成到我们自己的项目中,作为一个接口提供出去给前端或者app调用,这个其实demo里面readme也说的很清楚,先把readme整个贴出来
DEMO里的readme
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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仅供参考,实际开发中需要结合具体业务场景修改使用
重点是:
# 集成至商户系统步骤如下(以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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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>
zfbinfo属性文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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
config类初始化zfbinfo的属性文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
controller均是支付宝api示例修改即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
生成二维码的工具类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
启动类没有任何变动还是生成项目的类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
以上,就是整个支付宝整合的例子,本博主在工作上直接运行成功的,本篇博文,没有再去进行实际测试,仅仅记录一个对接支付宝的思路过程,总结记录以备后用。