1.JAVA对接支付宝官网文档 ,下载支付宝开放平台开发助手
省略去平台注册开发者账号和产品信息过程~~~
官网文档给的太生疏,这边作者踩过的坑可以避免
生成应用公钥(public key)、应用私钥(private key)和公钥证书申请 CSR 文件,支持 RSA2 、RSA 三种签名算法。
说明:目前暂不支持国密的加签方式,即使获取后也无法设置加签。
签名 :使用商户应用私钥对请求参数做签名。
1.公钥证书说明
1.1开放平台在开发者配置应用公钥证书后,自动创建开放平台证书。
支付宝开放平台提供对 X.509 格式证书的支持,开发者上传证书后,后续在和支付宝开放平台交互过程中支付宝会尝试使用该证书进行报文验签。在报文签名场景下,报文接受方使用发送方的公钥进行报文验签即可。
1.2证书引入了 CA 机构对公钥持有者进行身份识别,保证该证书所属实体的真实性,以实现报文的抗抵赖。
只有 RSA2 签名算法支持证书。
1.3支持自签名证书,建议由权威 CA 机构签发。
1.4证书必须在有效期内。证书有效期是指证书能够实现其声明功能的期限,证书的功能可包括:签名、加密、身份鉴别。若开发者发现应用证书即将过期,请尽量在证书到期前的一个月前就开始准备证书替换。
对于签名用途的证书,其私钥只能在证书有效期内才可以用于数字签名,私钥的使用期限不能超过证书的有效期限。因此,证书有效期过后,其对应的私钥也相应失效,不能再用于签名,公钥验证也不能通过。当用户的证书过期后,接口中使用的证书验证方式将失效,导致 openapi 调用失败。但是为了保证在证书有效期内签名的信息可以验证,公钥的使用期限可以在证书的有限期限以外。
1.5对于身份鉴别用途的证书,其私钥和公钥只能在证书有效期内才可以使用。证书到期后,在保证安全的情况下,允许使用原密钥对对证书进行更新,但是密钥对不能无限期使用。
2支付宝开放平台开发助手配置
2.1生成证书
2.2生成3个文件
密钥文件
2.3点击接口加密证书点击证书(其实默认就是证书)
2.4下载证书
下载证书
2.5保存好证书
申请内网穿透
特点
支持协议:HTTP、HTTPS、TCP。
流量不限制:免费版不限制流量。
隧道数量:最多支持 2 条隧道连接。
实名认证:免实名认证
使用场景
小型开发项目:适合用于开发者将本地服务暴露给外部访问进行测试。
远程工作:适合需要远程访问公司内网的个人或团队。
优缺点
优点:免费流量不限制、简单易用、稳定性高。
缺点:免费带宽有限,适用于小流量应用。
上代码(重点来了) Maven依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>easysdk-kernel</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.10.209.ALL</version>
</dependency>
3封装配置信息
public class AlipayConfig {
//设置应用私钥
public static final String APP_PRIVATE_KEY = "(这里填 图一的 私钥)";
//设置应用公钥证书路径 线上
public static final String APP_CERT_PAHT = "/app/certificate/appCertPublicKey_2021001155653258.crt"; (这里是线上路径 注意看图六)
//设置支付宝公钥证书路径 线上
public static final String ALIPAY_CERT_PATH = "/app/certificate/alipayCertPublicKey_RSA2.crt";(这里是线上路径 注意看图六)
//设置支付宝根证书路径 线上
public static final String ALIPAY_ROOT_CERT_PATH = "/app/certificate/alipayRootCert.crt";(这里是线上路径 注意看图六)
//请求使用的编码格式,如utf-8,gbk,gb2312等 sign_type
public static final String CHARSET = "utf-8";
//商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2
public static final String SIGN_TYPE = "RSA2";
//设置请求格式,固定值json
public static final String FORMAT = "json";
//支付宝分配给开发者的应用ID
public static final String APP_ID = "(写自己的产品ID,在开发者平台看)";
public static CertAlipayRequest config() {
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
//设置网关地址
certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
//设置应用Id
certAlipayRequest.setAppId(AlipayConfig.APP_ID);
//设置应用私钥
certAlipayRequest.setPrivateKey(AlipayConfig.APP_PRIVATE_KEY);
//设置请求格式,固定值json
certAlipayRequest.setFormat(AlipayConfig.FORMAT);
//设置字符集
certAlipayRequest.setCharset(AlipayConfig.CHARSET);
//设置签名类型
certAlipayRequest.setSignType(AlipayConfig.SIGN_TYPE);
//设置应用公钥证书路径
certAlipayRequest.setCertPath(AlipayConfig.APP_CERT_PAHT);
//设置支付宝公钥证书路径
certAlipayRequest.setAlipayPublicCertPath(AlipayConfig.ALIPAY_CERT_PATH);
//设置支付宝根证书路径
certAlipayRequest.setRootCertPath(AlipayConfig.ALIPAY_ROOT_CERT_PATH);
return certAlipayRequest;
}
}
这里证书都是放在云服务器的需要 (重点)
图六
3.1写一个支付宝接口
//构造client
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.config());
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody("测试数据曾大大大");
model.setSubject(alipayDTO.getGoodsDescribe());
model.setOutTradeNo(orderNo);
model.setTimeoutExpress("30m");
model.setTotalAmount(alipayDTO.getTotalAmount());
model.setProductCode("QUICK_MSECURITY_PAY");
request.setBizModel(model);
request.setNotifyUrl(这里需要改成 支付成功之后回调接口的请求路径);
try {
Map<String, Object> data = new HashMap<>();
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
System.out.println(response.getBody()); //就是orderString 可以直接给客户端请求,无需再做处理。
data.put("orderString", response.getBody());
return ResponseResult.success(data);
} catch (Exception e) {
e.printStackTrace();
}
前端拿到response.getBody()就可以调起支付了
4.支付宝回调
图七
(value = "/自己命名", method = RequestMethod.POST)
(value = "支付回调", notes = "app")
public String alipayCallback(HttpServletRequest request) {
try {
Map<String, String> params = new HashMap<String, String>();
Map requestParams = request.getParameterMap();
for (Iterator 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] + ",";
}
System.out.println(">>>>>参数" + name + ":" + valueStr);
params.put(name, valueStr);
}
requestParams.get("trade_status");
//订单号
String outTradeNo = request.getParameter("out_trade_no");
String tradeStatus = request.getParameter("trade_status");
String subject = request.getParameter("subject");
String sellerId = request.getParameter("seller_id");
//支付宝流水
String tradeNo = request.getParameter("trade_no");
log.info("trade_status>>" + tradeStatus + ">>>>trade_no" + tradeNo + ">>>out_trade_no" + outTradeNo);
if ("TRADE_FINISHED".equals(tradeStatus) || "TRADE_SUCCESS".equals(tradeStatus)) {
//这里写业务逻辑
//操作成功
}
}
响应参数
参数 类型 是否必填 最大长度 描述 示例值
- out_trade_no 必选 64 商户网站唯一订单号 70501111111S001111119
- trade_no 必选 64 该交易在支付宝系统中的交易流水号 2014112400001000340011111118
- total_amount 必选 9 该笔订单的资金总额,单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位。 9.00
- seller_id 必选 16 收款支付宝账号对应的支付宝唯一用户号。 以2088开头的纯16位数字 2088111111116894
- merchant_order_no 必选 32 商户原始订单号,最大长度限制32位 20161008001
触发通知类型
通知类型 描述 默认开启
- tradeStatus.TRADE_CLOSED 交易关闭 1
- tradeStatus.TRADE_FINISHED 交易完结 1
- tradeStatus.TRADE_SUCCESS 支付成功 1
- tradeStatus.WAIT_BUYER_PAY 交易创建 0