查看文档 支付宝文档地址:
小程序文档 - 支付宝文档中心
使用沙箱环境
沙箱登录地址
登录 - 支付宝
点击查看 才能看钥匙截图写错了。。 问号可以看默认加密方式
点击沙箱帐号 这里我们就具备所有条件了
实战开始
pom文件增加依赖
java"><dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.38.0.ALL</version>
</dependency>
创建配置文件,将沙箱内的信息填写到配置文件
java"># 支付宝网关名
open_api_domain = https://openapi-sandbox.dl.alipaydev.com/gateway.do#此处请填写你的PID
pid = 20887210111111
#此处请填写你当面付的APPID
appid = 902101111110# RSA私钥、公钥和支付宝公钥
#此处请填写你的应用私钥且转PKCS8格式
private_key = cpwVvks4h8PwdWDm13Jc207PvY5iy+8xMQd919ClW9H8lVBbpuyA+uyRmoPHp63SpmSnyXAye7ZvjDvuJ4kH9edbLnL
#此处请填写你的应用公钥
public_key = qRhLEXLU+LvD91mAs1iVCGx4bpfl2eLpwLMYvCePwijD6xdBPuRsNv3Chw4xUHfoqK6MKRLzXeqJPdEinhr/DZrAnSbkdH8BwIDAQAB#SHA256withRsa对应支付宝公钥
alipay_public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqGJldKdkvrx1WirZ4LGUP1DCELrb9Ci1qIdU1Y35z7v4V44BWv2QZoFVVjqVd7mAy7EtCM/cnTH5# 签名类型: RSA->SHA1withRsa,RSA2->SHA256withRsa
sign_type = RSA2
# 当面付最大查询次数和查询间隔(毫秒)
max_query_retry = 5
query_duration = 5000# 当面付最大撤销次数和撤销间隔(毫秒)
max_cancel_retry = 3
cancel_duration = 2000# 交易保障线程第一次调度延迟和调度间隔(秒)
heartbeat_delay = 5
heartbeat_duration = 900#异步通知url(注意拦截器是否拦截)
NotifyUrl=http://fpwquz.natappfree.cc/callbac
支付实体
java">package com.bjbr.controller;import com.alipay.api.domain.GoodsDetail;import java.util.List;/*** 支付宝当面付实体类**/
public class ZFBFaceToFaceModel {private String outTradeNo;// (必填) 商户网站订单系统中唯一订单号 ,64个字符以内,只能包含字母、数字、下划线, 需保证商户系统端不能重复,建议通过数据库sequence生成private String subject; // (必填) 订单标题,粗略描述用户的支付目的。如“喜士多(浦东店)消费”private String totalAmount;// (必填) 订单总金额单位为元,不能超过1亿元 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】private String undiscountableAmount;// (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】private String sellerId;// 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)// 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PIDprivate String body;// // 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"private String operatorId; // 商户操作员编号,添加此参数可以为商户操作员做销售统计private String storeId; // (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持private String timeoutExpress;//支付超时如:“120m”,定义为120分钟private List<GoodsDetail> goodsDetailList; //商品明细列表,需填写购买商品详细信息,private String NotifyUrl;// 支付成功之后 支付宝异步调用的接口地址;private String MoblieReturnUrl;//手机支付同步通知页面地址;private String refundReason;//退款原因,(退款使用)private String tradeNo;//支付宝订单号,(退款使用)public String getTradeNo() {return tradeNo;}public void setTradeNo(String tradeNo) {this.tradeNo = tradeNo;}public String getRefundReason() {return refundReason;}public void setRefundReason(String refundReason) {this.refundReason = refundReason;}/*** (必填) 商户网站订单系统中唯一订单号 ,64个字符以内,只能包含字母、数字、下划线, 需保证商户系统端不能重复,建议通过数据库sequence生成* @return*/public String getOutTradeNo() {return outTradeNo;}/*** (必填) 商户网站订单系统中唯一订单号 ,64个字符以内,只能包含字母、数字、下划线, 需保证商户系统端不能重复,建议通过数据库sequence生成* @param outTradeNo*/public void setOutTradeNo(String outTradeNo) {this.outTradeNo = outTradeNo;}/*** (必填) 订单标题,粗略描述用户的支付目的。如“喜士多(浦东店)消费”* @return*/public String getSubject() {return subject;}/*** (必填) 订单标题,粗略描述用户的支付目的。如“喜士多(浦东店)消费”* @param subject*/public void setSubject(String subject) {this.subject = subject;}/*** (必填) 订单总金额单位为元,不能超过1亿元 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】* @return*/public String getTotalAmount() {return totalAmount;}/*** (必填) 订单总金额单位为元,不能超过1亿元 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】* @param totalAmount*/public void setTotalAmount(String totalAmount) {this.totalAmount = totalAmount;}/*** (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】* @return*/public String getUndiscountableAmount() {return undiscountableAmount;}/*** (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】* @param undiscountableAmount*/public void setUndiscountableAmount(String undiscountableAmount) {this.undiscountableAmount = undiscountableAmount;}/*** // 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)// 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID* @return*/public String getSellerId() {return sellerId;}/*** // 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)// 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID* @param sellerId*/public void setSellerId(String sellerId) {this.sellerId = sellerId;}/*** 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"* @return*/public String getBody() {return body;}/*** 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"* @param body*/public void setBody(String body) {this.body = body;}/***商户操作员编号,添加此参数可以为商户操作员做销售统计* @return*/public String getOperatorId() {return operatorId;}/***商户操作员编号,添加此参数可以为商户操作员做销售统计* @param operatorId*/public void setOperatorId(String operatorId) {this.operatorId = operatorId;}/*** (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持* @return*/public String getStoreId() {return storeId;}/*** (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持* @param storeId*/public void setStoreId(String storeId) {this.storeId = storeId;}/***支付超时如:“120m”,定义为120分钟* @return*/public String getTimeoutExpress() {return timeoutExpress;}/***支付超时如:“120m”,定义为120分钟* @param timeoutExpress*/public void setTimeoutExpress(String timeoutExpress) {this.timeoutExpress = timeoutExpress;}/***商品明细列表,需填写购买商品详细信息,* @return*/public List<GoodsDetail> getGoodsDetailList() {return goodsDetailList;}/***商品明细列表,需填写购买商品详细信息,* @param goodsDetailList*/public void setGoodsDetailList(List<GoodsDetail> goodsDetailList) {this.goodsDetailList = goodsDetailList;}/***支付成功之后 支付宝异步调用的接口地址;* @return*/public String getNotifyUrl() {return NotifyUrl;}/***支付成功之后 支付宝异步调用的接口地址;* @param notifyUrl*/public void setNotifyUrl(String notifyUrl) {NotifyUrl = notifyUrl;}/*** 手机支付后跳转的页面地址* @return*/public String getMoblieReturnUrl() {return MoblieReturnUrl;}/*** 手机支付后跳转的页面地址* @return*/public void setMoblieReturnUrl(String moblieReturnUrl) {MoblieReturnUrl = moblieReturnUrl;}
}
根据键值获取配置文件内容方法
java">public static String getZFBinfoValue(String name){try(InputStream inputStream = CommonUtils.class.getClassLoader().getResourceAsStream("config/zfbinfo.properties")) {if(properties==null){properties = new Properties();properties.load(new InputStreamReader(inputStream, StandardCharsets.UTF_8));}return properties.getProperty(name,"");} catch (Exception e) {log.error(e.getMessage(),e);return "";}}
获取二维码接口
java">public static String getZFBPreorder(ZFBFaceToFaceModel zfbFaceToFaceModel) throws AlipayApiException {CommonUtils commonUtils = new CommonUtils();/** 支付宝网关 **/String URL = commonUtils.getZFBinfoValue("open_api_domain");/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/String APP_ID = commonUtils.getZFBinfoValue("appid");/** 应用私钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/String APP_PRIVATE_KEY = commonUtils.getZFBinfoValue("private_key");/** 支付宝公钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/String ALIPAY_PUBLIC_KEY = commonUtils.getZFBinfoValue("alipay_public_key");/** 初始化 **/AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.precreate(统一收单线下交易预创建(扫码支付)) **/AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();/** 设置业务参数 **/AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();/** 商户订单号,商户自定义,需保证在商户端不重复,如:20200612000001 **/model.setOutTradeNo(zfbFaceToFaceModel.getOutTradeNo());/**订单标题 **/model.setSubject(zfbFaceToFaceModel.getSubject());/** 订单金额,精确到小数点后两位 **/model.setTotalAmount(zfbFaceToFaceModel.getTotalAmount());/** 订单描述 **/model.setBody(zfbFaceToFaceModel.getBody());/** 将业务参数传至request中 **/request.setBizModel(model);/** 异步通知地址,以http或者https开头的,商户外网可以post访问的异步地址,用于接收支付宝返回的支付结果,如果未收到该通知可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602475759 **/request.setNotifyUrl(zfbFaceToFaceModel.getNotifyUrl());/** 通过alipayClient调用API,获得对应的response类 **/AlipayTradePrecreateResponse response = alipayClient.execute(request);/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101 **/System.out.println(response.getBody());return response.getBody();}
退款接口
java">public static String ZFBTradeRefund(ZFBFaceToFaceModel zfbFaceToFaceModel) throws AlipayApiException {CommonUtils commonUtils = new CommonUtils();/** 支付宝网关 **/String URL = commonUtils.getZFBinfoValue("open_api_domain");/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/String APP_ID = commonUtils.getZFBinfoValue("appid");/** 应用私钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/String APP_PRIVATE_KEY = commonUtils.getZFBinfoValue("private_key");/** 支付宝公钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/String ALIPAY_PUBLIC_KEY = commonUtils.getZFBinfoValue("alipay_public_key");/** 初始化 **/AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.refund(统一收单交易退款接口) **/AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();/** 设置业务参数 **/AlipayTradeRefundModel model = new AlipayTradeRefundModel ();/** 商户订单号,商户自定义,需保证在商户端不重复,如:20200612000001 **/model.setOutTradeNo(zfbFaceToFaceModel.getOutTradeNo());model.setTradeNo(zfbFaceToFaceModel.getTradeNo());// 设置退款金额model.setRefundAmount(zfbFaceToFaceModel.getTotalAmount());// 设置退款原因说明model.setRefundReason(zfbFaceToFaceModel.getRefundReason());// 设置退款请求号 退款请求号。 标识一次退款请求,需要保证在交易号下唯一model.setOutRequestNo(UUID.randomUUID().toString());/** 将业务参数传至request中 **/request.setBizModel(model);/** TODO暂时不用退款通知 异步通知地址,以http或者https开头的,商户外网可以post访问的异步地址,用于接收支付宝返回的支付结果,如果未收到该通知可参考该文档进行确认:https://opensupport.alipay.com/support/helpcenter/193/201602475759 **/request.setNotifyUrl("");AlipayTradeRefundResponse response = alipayClient.execute(request);/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101 **/System.out.println(response.getBody());if (response.isSuccess()) {System.out.println("调用成功");} else {System.out.println("调用失败");}return response.getBody();}
查询订单状态接口
java">public static String ZFBTradeQuery(ZFBFaceToFaceModel zfbFaceToFaceModel) throws AlipayApiException {CommonUtils commonUtils = new CommonUtils();/** 支付宝网关 **/String URL = commonUtils.getZFBinfoValue("open_api_domain");/** 应用id,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/190/201602493024 **/String APP_ID = commonUtils.getZFBinfoValue("appid");/** 应用私钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602469554 **/String APP_PRIVATE_KEY = commonUtils.getZFBinfoValue("private_key");/** 支付宝公钥,如何获取请参考:https://opensupport.alipay.com/support/helpcenter/207/201602487431 **/String ALIPAY_PUBLIC_KEY = commonUtils.getZFBinfoValue("alipay_public_key");/** 初始化 **/AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, "json", "UTF-8", ALIPAY_PUBLIC_KEY, "RSA2");/** 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.refund(统一收单交易退款接口) **/AlipayTradeQueryRequest request = new AlipayTradeQueryRequest ();/** 设置业务参数 **/AlipayTradeQueryModel model = new AlipayTradeQueryModel ();/** 商户订单号,商户自定义,需保证在商户端不重复,如:20200612000001 **/model.setOutTradeNo(zfbFaceToFaceModel.getOutTradeNo());model.setTradeNo(zfbFaceToFaceModel.getTradeNo());/** 将业务参数传至request中 **/request.setBizModel(model);AlipayTradeQueryResponse response = alipayClient.execute(request);/** 获取接口调用结果,如果调用失败,可根据返回错误信息到该文档寻找排查方案:https://opensupport.alipay.com/support/helpcenter/101 **///解析json数据JSONObject jsonObject=JSONObject.parseObject(response.getBody());//得到alipay_trade_query_response数据后再强转JSONObjectJSONObject jsonobj_two=(JSONObject)jsonObject.get("alipay_trade_query_response");//再通过jsonobj_two获取到二维码地址String code=jsonobj_two.get("code").toString();//交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)String trade_status=jsonobj_two.get("trade_status").toString();if (trade_status.equals("TRADE_SUCCESS")) {//用户已付款 直接调用回调return "yzf";}else {return "wzf";}}