接入指南-扫码支付
接入设计
扫码支付适合有各类自助终端的商家,用户在自助终端通过扫码完成支付。当面付扫码支付采用 商家/系统服务商后台转发 方式接入,商家先预下单到商家后台,再请求到支付宝。
流程图
开发者可以点击下载 支付宝支付物料 或者直接进行 物料系统申请。
支付宝为了保证交易安全采取了一系列安全手段以保证交易安全。点击了解 更多安全设计指南。请商家务必注意:
采用 HTTPS 协议传输交易数据,防止数据被截获、解密。
采用 RSA/RSA2 非对称密钥,明确交易双方的身份,保证交易主体的正确性和唯一性。
调用接口
开发者需要确认自己的应用在审核通过后显示 已上线,同时完成当面付功能的签约后,才能顺利调用以下接口。否则会有缺少权限的报错。
调用流程
商户系统调用 alipay.trade.precreate(统一收单线下交易预创建)接口,获得该订单的二维码串 qr_code,开发者需要利用二维码生成工具获得最终的订单二维码图片;
发起轮询获得支付结果:等待 5 秒后调用 alipay.trade.query(统一收单线下交易查询)接口,通过支付时传入的商户订单号(out_trade_no)查询支付结果(返回参数 TRADE_STATUS),如果仍然返回等待用户付款(WAIT_BUYER_PAY),则再次等待 5 秒后继续查询,直到返回确切的支付结果(成功 TRADE_SUCCESS 或 已撤销关闭 TRADE_CLOSED),或是超出轮询时间。在最后一次查询仍然返回等待用户付款的情况下,必须立即调用 alipay.trade.cancel(统一收单交易撤销接口)将这笔交易撤销,避免用户继续支付;
除了主动轮询,当订单支付成功时,商户也可以通过设置异步通知(notify_url)来获得支付宝服务端返回的支付结果,详见 扫码异步通知,注意一定要对异步通知验签,确保通知是支付宝发出的。
注意:如商户由于客观原因(如无公网服务器接受支付宝请求等)无法接受异步支付通知,则忽略上图中的步骤 3.4 和 3.4.1。更多注意事项请参考 异常处理。
预下单
商家可调用 alipay.trade.precreate(统一收单线下交易预创建)接口,传入订单商品及金额的信息创建订单。支付宝将返回支付二维码信息用于用户扫码支付。
示例代码
AlipayClient alipayClient = new DefaultAlipayClient ( "https://openapi.alipay.com/gateway.do" , APP_ID , APP_PRIVATE_KEY , "json" , CHARSET , ALIPAY_PUBLIC_KEY , "RSA2" ); //获得初始化的AlipayClient
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest (); //创建API对应的request类
request . setBizContent ( "{" +
"\"out_trade_no\":\"20150320010101002\"," + //商户订单号
"\"total_amount\":\"88.88\"," +
"\"subject\":\"Iphone6 16G\"," +
"\"store_id\":\"NJ_001\"," +
"\"timeout_express\":\"90m\"}" ); //订单允许的最晚付款时间
AlipayTradePrecreateResponse response = alipayClient.execute (request);
System.out.print( response.getBody ());
//根据response中的结果继续业务逻辑处理
重要入参说明
out_trade_no:商户订单号,需要保证商家系统不重复。
total_amount:订单金额。
subject:商品的标题/交易标题/订单标题/订单关键字等。不可使用特殊字符,如 /,=,& 等。
store_id:商户门店编号。
timeout_express:交易超时时间。
重要出参说明
qr_code:订单二维码(有效时间 2 小时)以字符串的格式返回,开发者需要自己使用工具根据内容生成二维码图片。
查询交易
商家可调用 alipay.trade.query(统一收单线下交易查询)接口,通过商户网站唯一订单号 out_trade_no 或支付宝交易号 trade_no 查询对应订单支付情况。
示例代码
xxxxxxxxxx
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2"); //获得初始化的AlipayClient
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();//创建API对应的request类
request.setBizContent("{" +
"\"out_trade_no\":\"20150320010101001\"," +
"\"trade_no\":\"2014112611001004680073956707\"}"); //设置业务参数
AlipayTradeQueryResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类
System.out.print(response.getBody());
//根据response中的结果继续业务逻辑处理
重要入参说明
out_trade_no:支付时传入的商户订单号,与 trade_no 必填一个。
trade_no:支付时返回的支付宝交易号,与 out_trade_no 必填一个。
撤销交易
支付交易返回失败或支付系统超时,商家可调用 alipay.trade.cancel(统一收单交易撤销接口)通过商户网站唯一订单号 out_trade_no 或支付宝交易号 trade_no 撤销交易。
说明:
如果此订单用户支付失败,支付宝将关闭此订单。
如果此订单用户支付成功,支付宝将退还订单资金给用户。
仅发生支付系统超时或者支付结果未知时可调用本接口撤销交易,其他正常支付的单如需实现相同功能请调用 alipay.trade.refund(统一收单交易退款接口)。
示例代码
xxxxxxxxxx
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2"); //获得初始化的AlipayClient
AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();//创建API对应的request类
request.setBizContent("{" +
"\"out_trade_no\":\"20150320010101001\"," +
"\"trade_no\":\"2014112611001004680073956707\"}"); //设置业务参数
AlipayTradeCancelResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类
System.out.print(response.getBody());
//根据response中的结果继续业务逻辑处理
重要入参说明
out_trade_no:支付时传入的商户订单号,与 trade_no 必填一个。
trade_no:支付时返回的支付宝交易号,与 out_trade_no 必填一个。
重要出参说明
retry_flag:是否需要重试,Y/N。
action:本次撤销触发的交易动作。
close:关闭交易,无退款 。
refund:产生了退款。
退款
当交易发生之后一段时间内,由于业务原因(如金额错误,用户退款或者对账不平等等)需要退款时,商家可以调用 alipay.trade.refund(统一收单交易退款接口)通过商户网站唯一订单号 out_trade_no 或支付宝交易号 trade_no,将对应订单支付款退还给买家,支付宝将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。支持全额或部分退款。
调用流程
说明:
退款的途径按照支付途径原路返回。
支付渠道为花呗、余额等退款即时到账。
银行卡的退款时间以银行退款时间为准,一般情况下 2 小时内可到账。
开发者也可以在 商家中心 中退款。
退款是否成功可以根据同步响应的
fund_change
参数来判断,返回值为 Y 则表示退款成功。退款接口会根据外部请求号 out_request_no 幂等返回,因此同一笔交易需要多次部分退款时,必须使用不同的 out_request_no。
示例代码
xxxxxxxxxx
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2"); //获得初始化的AlipayClient
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();//创建API对应的request类
request.setBizContent("{" +
"\"out_trade_no\":\"20150320010101001\"," +
"\"trade_no\":\"2014112611001004680073956707\"," +
"\"out_request_no\":\"1000001\"," +
"\"refund_amount\":\"1.00\"}"); //设置业务参数
AlipayTradeRefundResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类
System.out.print(response.getBody());
//根据response中的结果继续业务逻辑处理
重要入参说明
out_trade_no:支付时传入的商户订单号,与 trade_no 必填一个。
trade_no:支付时返回的支付宝交易号,与 out_trade_no 必填一个。
out_request_no:本次退款请求流水号,部分退款时必传。
refund_amount:本次退款金额。
重要出参说明
refund_fee:该笔交易已退款的总金额。
退款到银行卡通知
退款存在退到银行卡场景下时,支付宝会调用 alipay.trade.refund.depositback.completed(收单退款冲退完成通知)接口根据银行回执消息发送退款完成信息至应用网关地址。
注意:开发者需登录 开放平台 进入对应应用详情页,在 消息服务 > FROM 蚂蚁 中订阅 alipay.trade.refund.depositback.completed(收单退款冲退完成通知)。更多 From 蚂蚁消息详情参见 From 蚂蚁消息服务使用。
消息示例
xxxxxxxxxx
ISV_GATEWAY_URL?charset=GBK&biz_content=
{
"trade_no":"2014112611001004680073956707","out_trade_no":"20150320010101001","out_request_no":"HZ01RF001","dback_status":"S","dback_amount":"1.01","bank_ack_time":"2020-06-02 14:03:48","est_bank_receipt_time":"2020-06-02 14:03:48"
}
&msg_method=alipay.trade.refund.depositback.completed&utc_timestamp=1516797622752&version=1.1&sign_type=RSA2¬ify_id=d275fec564e62af6bedbcee73f3f05fi5x&app_id=2013121700999429&sign=I+Y/lvqYUEEc10EPdpntRhFIQ==
重要参数说明
trade_no:支付宝交易订单号。
dback_status:银行卡冲退状态。
S - 成功。
F - 失败。银行卡冲退失败,资金自动转入用户支付宝余额。
dback_amount:银行卡冲退金额。
bank_ack_time:银行响应时间,格式为 yyyy-MM-dd HH:mm:ss。
est_bank_receipt_time:预估银行入账时间,格式为 yyyy-MM-dd HH:mm:ss。
对账
商家/服务商可通过接口下载指定日期(当天除外)的业务明细账单文件,并结合自身业务系统实现自动对账。
接口流程
商户系统调用 alipay.data.dataservice.bill.downloadurl.query(查询对账单下载地址),传入指定日期,获得该日期账单文件的下载地址。
商户系统通过 HTTP 方式后台访问账单下载链接,将账单 csv 文件下载到本地后自行处理。
注意:该下载链接仅 30 秒,在得到链接后系统需要立刻下载账单文件。
示例代码
xxxxxxxxxx
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");//获得初始化的AlipayClient
AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();//创建API对应的request类
request.setBizContent("{" +
"\"bill_type\":\"trade\"," +
"\"bill_date\":\"2016-04-05\"}"); //设置业务参数
AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类
System.out.print(response.getBody());
//根据response中的结果继续业务逻辑处理
重要入参说明
bill_type:固定传入 trade。
bill_date:需要下载的账单日期,最晚是当期日期的前一天。
重要出参说明
bill_download_url:账单文件下载地址,有效时长:30 秒。
下载账单文件示例代码
xxxxxxxxxx
//将接口返回的对账单下载地址传入urlStr
String urlStr = "http://dwbillcenter.alipay.com/downloadBillFile.resource?bizType=X&userId=X&fileType=X&bizDates=X&downloadFileName=X&fileId=X";
//指定希望保存的文件路径
String filePath = "/Users/fund_bill_20160405.csv.zip";
URL url = null;
HttpURLConnection httpUrlConnection = null;
InputStream fis = null;
FileOutputStream fos = null;
try {
url = new URL(urlStr);
httpUrlConnection = (HttpURLConnection) url.openConnection();
httpUrlConnection.setConnectTimeout(5 * 1000);
httpUrlConnection.setDoInput(true);
httpUrlConnection.setDoOutput(true);
httpUrlConnection.setUseCaches(false);
httpUrlConnection.setRequestMethod("GET");
httpUrlConnection.setRequestProperty("CHARSET", "UTF-8");
httpUrlConnection.connect();
fis = httpUrlConnection.getInputStream();
byte[] temp = new byte[1024];
int b;
fos = new FileOutputStream(new File(filePath));
while ((b = fis.read(temp)) != -1) {