官方使用说明文档
SDK & Demo(Eclipse+JDK 1.6 及以上+Tomcat 6.0 及以上)
开发工具包SDK下载
【推荐参考】电脑网站支付接入助手
通用版SDK
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.31.7.ALL</version>
</dependency>
新建springboot项目,引入相关依赖
<!-- 解决Spring Boot Configuration Annotation Processor not configured报错 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!-- 通用连接池-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--druid 连接池依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.9</version>
</dependency>
<!--mybatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<!--操作JSON字符串-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.80</version>
</dependency>
<!--语言包,处理字符串,日期等工具包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!--项目启动热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- 支付宝开发工具包-通用版 -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.31.7.ALL</version>
</dependency>
制作controller,根据官方提供的代码,进行改造一下,
先做支付的API接口
package com.tj.alipay.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.tj.alipay.domain.PayData;
import com.tj.alipay.service.BaseZhifubaoParamService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
@Slf4j
@RestController
@RequestMapping("/zhifubao")
public class ZhiFuBaoCtrl {
@Autowired(required = false)
private BaseZhifubaoParamService baseZhifubaoParamService;
@PostMapping
String getPayForm(@RequestBody PayData payData) {
/** 支付宝网关 **/
String URL = "https://openapi.alipaydev.com/gateway.do"; //沙箱地址
/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/
String APP_ID = baseZhifubaoParamService.getAppId();
/** 应用私钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/
String APP_PRIVATE_KEY = baseZhifubaoParamService.getAppPrivateKey();
/** 支付宝公钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/
String ALIPAY_PUBLIC_KEY = baseZhifubaoParamService.getAlipayPublicKey();
/** 初始化 **/
AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");
/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.page.pay(电脑网站支付) **/
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
/** 设置业务参数 **/
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
/** 商户订单号,商户自定义,需保证在商户端不重复,如:20200612000001 **/
model.setOutTradeNo(payData.getOutTradeNo());
/** 销售产品码,固定值:FAST_INSTANT_TRADE_PAY **/
model.setProductCode("FAST_INSTANT_TRADE_PAY");
/**
* PC扫码支付的方式。
* 支持前置模式和跳转模式。
* 前置模式是将二维码前置到商户的订单确认页的模式。需要商户在自己的页面中以 iframe 方式请求支付宝页面。具体支持的枚举值有以下几种:
* 0:订单码-简约前置模式,对应 iframe 宽度不能小于600px,高度不能小于300px;
* 1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于600px;
* 3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于75px;
* 4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小。
*
* 跳转模式下,用户的扫码界面是由支付宝生成的,不在商户的域名下。支持传入的枚举值有:
* 2:订单码-跳转模式
*/
model.setQrPayMode("0");
/**订单标题 **/
model.setSubject(payData.getSubject());
/** 订单金额,精确到小数点后两位 **/
model.setTotalAmount(payData.getTotalAmount());
/** 订单描述 **/
model.setBody(payData.getBody());
/** 业务扩展参数 **/
//ExtendParams extendParams = new ExtendParams();
/** 花呗分期参数传值前提:必须有该接口花呗收款准入条件,且需签约花呗分期 **/
/** 指定可选期数,只支持3/6/12期,还款期数越长手续费越高 **/
// extendParams.setHbFqNum("3");
/** 指定花呗分期手续费承担方式,手续费可以由用户全承担(该值为0),也可以商户全承担(该值为100),但不可以共同承担,即不可取0和100外的其他值。 **/
//extendParams.setHbFqSellerPercent("0");
//model.setExtendParams(extendParams);
/** 将业务参数传至request中 **/
alipayRequest.setBizModel(model);
/** 注:支付结果以异步通知为准,不能以同步返回为准,因为如果实际支付成功,但因为外力因素,如断网、断电等导致页面没有跳转,则无法接收到同步通知;**/
/** 同步通知地址,以http或者https开头,支付完成后跳转的地址,用于用户视觉感知支付已成功,传值外网可以访问的地址,如果同步未跳转可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602474937 **/
alipayRequest.setReturnUrl("");
/** 异步通知地址,以http或者https开头,商户外网可以post访问的异步地址,用于接收支付宝返回的支付结果,如果未收到该通知可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602475759 **/
alipayRequest.setNotifyUrl("");
/** 第三方调用(服务商模式),传值app_auth_token后,会收款至授权app_auth_token对应商家账号,如何获传值app_auth_token请参考文档:https://opensupport.alipay.com/support/helpcenter/79/201602494631 **/
//request.putOtherTextParam("app_auth_token", "传入获取到的app_auth_token值");
String form = null;
try {
/** 调用SDK生成表单form表单 **/
form = alipayClient.pageExecute(alipayRequest).getBody();
/** 调用SDK生成支付链接,可在浏览器打开链接进入支付页面 **/
//form = alipayClient.pageExecute(alipayRequest,"GET").getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/97 **/
System.out.println(form);
/** 直接将完整的表单html输出到页面 **/
return form;
}
@GetMapping
String queryResult(String outTradeNo) {
/** 支付宝网关 **/
String URL = "https://openapi.alipaydev.com/gateway.do";
/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/
String APP_ID = baseZhifubaoParamService.getAppId();
/** 应用私钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/
String APP_PRIVATE_KEY = baseZhifubaoParamService.getAppPrivateKey();
/** 支付宝公钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/
String ALIPAY_PUBLIC_KEY = baseZhifubaoParamService.getAlipayPublicKey();
/** 初始化 **/
AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");
/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.query(统一收单线下交易查询) **/
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
/** 设置业务参数 **/
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
/** 注:交易号(TradeNo)与订单号(OutTradeNo)二选一传入即可,如果2个同时传入,则以交易号为准 **/
/** 支付接口传入的商户订单号。如:2020061601290011200000140004 **/
model.setOutTradeNo(outTradeNo);
/** 异步通知/查询接口返回的支付宝交易号,如:2020061622001473951448314322 **/
//model.setTradeNo("2020061622001473951448314322");
/** 将业务参数传至request中 **/
request.setBizModel(model);
/** 第三方调用(服务商模式),必须传值与支付接口相同的app_auth_token **/
//request.putOtherTextParam("app_auth_token", "传入获取到的app_auth_token值");
AlipayTradeQueryResponse response = null;
try {
/** 通过alipayClient调用API,获得对应的response类 **/
response = alipayClient.execute(request);
log.info("返回结果:{}", response.getBody());
//参数处理
String tradeQueryResponse = JSON.parseObject(response.getBody()).getString("alipay_trade_query_response");
HashMap<String, String> map = new HashMap<>();
JSONObject jsonObject = JSON.parseObject(tradeQueryResponse);
map.put("out_trade_no", jsonObject.getString("out_trade_no"));
map.put("total_amount", jsonObject.getString("total_amount"));
map.put("trade_no", jsonObject.getString("trade_no"));
map.put("trade_status", jsonObject.getString("trade_status"));
map.put("send_pay_date", jsonObject.getString("send_pay_date"));
return JSON.toJSONString(map);
} catch (AlipayApiException e) {
e.printStackTrace();
}
/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101 **/
return null;
}
}
1、其中需要传入的参数,我们可以使用实体类进行定义,方便读取和调用
package com.tj.alipay.domain;
import lombok.Data;
import java.io.Serializable;
/**
* 支付信息
*/
@Data
public class PayData implements Serializable {
/**
* 商户订单号。
* 由商家自定义,64个字符以内,仅支持字母、数字、下划线且需保证在商户端不重复。
*/
private String outTradeNo;
/**
* 订单总金额,单位为元,精确到小数点后两位,取值范围为 [0.01,100000000]。金额不能为0。
*/
private String totalAmount;
/**
* 订单标题。
* 注意:不可使用特殊字符,如 /,=,& 等。
*/
private String subject;
/**
* 订单描述
**/
private String body;
private static final long serialVersionUID = 1L;
}
2、接口请求成功后,支付宝返回的是一个html格式的字符串,里面类似下面的代码
<form name="punchout_form" method="post" action="https://openapi.alipaydev.com/gateway.do?charset=UTF-8&method=alipay.trade.page.pay&sign=XZ%2BLINIxDqMW%2FxMgjIoXUrSk0uWuJGnxuRyYcqkxFCqubYULdBM1godWmH1S9Qgf2Eoz8TOdJXF1i%2FykDRbiNuEeOYZT8%2BJirKiBTSPfh%2Bl1pwxwDkx%2F5e5cwvzeVwyhKd6Yq3HsM3Eh7CZLfLq8ormpmCE4HEQgZvY1Bij%2FDS0AwecjzEwAtwyjh6mIP5ax48IlUwPIkWxdYpfoJ7aytfzK0cCX8H%2BYr%2B5YztGhozRUTaHwP74D5D6TXd%2BTS%2BIH%2Fm74XfcYuMRwkTZVhUyL31DyeRfur3TiOygs0U2ycsgw6dU8L4P1XRbidbQJkUXTmE9docbleDAB0drY2RbUBA%3D%3D&version=1.0&app_id=2021000120612546&sign_type=RSA2×tamp=2022-06-11+20%3A14%3A25&alipay_sdk=alipay-sdk-java-dynamicVersionNo&format=json">
<input type="hidden" name="biz_content" value="{"body":"海外批次付款:1004322060701","out_trade_no":"GWTEST2022061100002","product_code":"FAST_INSTANT_TRADE_PAY","qr_pay_mode":"0","subject":"海外批次付款:1004322060701","total_amount":"476.2"}">
<input type="submit" value="立即支付" style="display:none" >
</form>
<script>document.forms[0].submit();</script>
1、这个里面有关键参数“qr_pay_mode”,我们设置为0,我用ifranme窗口来现在返回的支付页面
这里可以参考:vue支付宝pc支付的扫码支付和跳转支付两种支付方式
PC扫码支付的方式。
支持前置模式和跳转模式。
前置模式是将二维码前置到商户的订单确认页的模式。需要商户在自己的页面中以 iframe 方式请求支付宝页面。具体支持的枚举值有以下几种:
0:订单码-简约前置模式,对应 iframe 宽度不能小于600px,高度不能小于300px;
1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于600px;
3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于75px;
4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小。
跳转模式下,用户的扫码界面是由支付宝生成的,不在商户的域名下。支持传入的枚举值有:
2:订单码-跳转模式
<iframe v-show="iframeShow" :srcdoc="alipayHtml" frameborder="no" border="0" marginwidth="0"
marginheight="0" scrolling="no" width="600" height="300" style="overflow:hidden;">
</iframe>
这样就做出这样一个界面,我个人不太喜欢“跳转模式”,体验不是很好,还是“前置模式”好点,这个qr_pay_mode如果不设置,就默认是“跳转模式”哦
再做一个支付结果查询的接口,根据这个接口,可以做支付完成后的一些逻辑
官方给出了3种方法来处理支付完成后的逻辑。分别是
- 同步接口(不推荐)
- 异步通知接口(这个接口必须是外网可放访问的接口,在本地调试的时候不太方便,但是尽量还是使用这个接口来处理支付成功后的逻辑)
查询接口(如果异步回调接口有问题,可以使用这个接口再次确认支付的状态)
查询接口JAVA代码
@GetMapping
String queryResult(String outTradeNo) {
/** 支付宝网关 **/
String URL = "https://openapi.alipaydev.com/gateway.do";
/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/
String APP_ID = baseZhifubaoParamService.getAppId();
/** 应用私钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/
String APP_PRIVATE_KEY = baseZhifubaoParamService.getAppPrivateKey();
/** 支付宝公钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/
String ALIPAY_PUBLIC_KEY = baseZhifubaoParamService.getAlipayPublicKey();
/** 初始化 **/
AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");
/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.query(统一收单线下交易查询) **/
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
/** 设置业务参数 **/
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
/** 注:交易号(TradeNo)与订单号(OutTradeNo)二选一传入即可,如果2个同时传入,则以交易号为准 **/
/** 支付接口传入的商户订单号。如:2020061601290011200000140004 **/
model.setOutTradeNo(outTradeNo);
/** 异步通知/查询接口返回的支付宝交易号,如:2020061622001473951448314322 **/
//model.setTradeNo("2020061622001473951448314322");
/** 将业务参数传至request中 **/
request.setBizModel(model);
/** 第三方调用(服务商模式),必须传值与支付接口相同的app_auth_token **/
//request.putOtherTextParam("app_auth_token", "传入获取到的app_auth_token值");
AlipayTradeQueryResponse response = null;
try {
/** 通过alipayClient调用API,获得对应的response类 **/
response = alipayClient.execute(request);
log.info("返回结果:{}", response.getBody());
//参数处理
String tradeQueryResponse = JSON.parseObject(response.getBody()).getString("alipay_trade_query_response");
HashMap<String, String> map = new HashMap<>();
JSONObject jsonObject = JSON.parseObject(tradeQueryResponse);
map.put("out_trade_no", jsonObject.getString("out_trade_no"));
map.put("total_amount", jsonObject.getString("total_amount"));
map.put("trade_no", jsonObject.getString("trade_no"));
map.put("trade_status", jsonObject.getString("trade_status"));
map.put("send_pay_date", jsonObject.getString("send_pay_date"));
return JSON.toJSONString(map);
} catch (AlipayApiException e) {
e.printStackTrace();
}
/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101 **/
return null;
}