接入指南
接口调用时序图

芝麻账单信用状态变化流程说明
out_trade_no
(同一个商户订单号)或者多笔交易单 out_trade_no
(不同的商户订单号,多次扣款)。out_trade_no
不变,尝试再次调支付或者关闭失败的交易订单。out_trade_no
不变,尝试再次支付,支付成功后子交易单(项)的逾期状态变为逾期已结清。逾期已结清不会再蔓延影响用户信用额度。
order_status
是 FINISH 或 CLOSED 且用户存在逾期记录,同时商家同意给用户消除这些逾期记录时,商家就可以调 alipay.trade.orderinfo.sync(支付宝订单信息同步接口)把冻结转失败的逾期交易单 trade_no
同步履约状态,履约状态支持 COMPLETE(用户已履约)、CLOSED(同步履约已取消)。接入芝麻免押
生成资金冻结订单
示例代码
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2");
AlipayFundAuthOrderAppFreezeRequest request = new AlipayFundAuthOrderAppFreezeRequest();
// 设置异步通知
request.setNotifyUrl("http://api.test.alipay.net/atinterface/receive_notify.htm");
JSONObject bizContent = new JSONObject();
bizContent.put("out_order_no","outOrderNo123");
bizContent.put("out_request_no","outRequestNo123");
bizContent.put("order_title","XX租车押金");
bizContent.put("amount",0.01);
bizContent.put("product_code","PRE_AUTH_ONLINE");
bizContent.put("payee_user_id","2088102000275795");
bizContent.put("timeout_express","30m");
//设置免押模式(POSTPAY、POSTPAY_UNCERTAIN、DEPOSIT_ONLY)
//bizContent.put("deposit_product_mode","DEPOSIT_ONLY");
//设置后付费项目开始
//JSONArray postPayments = new JSONArray();
//后付费项目
// JSONObject postPayment = new JSONObject();
// postPayment.put("name","租金");
// postPayment.put("amount","1");
// postPayment.put("description","1元/小时");
// postPayments.add(postPayment);
// bizContent.put("post_payments",postPayments);
//设置后付费项目结束
//JSONArray disablePayChannels = new JSONArray();
//// 禁用渠道添加信用卡快捷
//JSONObject disableChannel1 = new JSONObject();
//disableChannel1.put("payChannelType","OPTIMIZED_MOTO");
//disablePayChannels.add(disableChannel1);
//// 禁用渠道添加信用卡卡通
//JSONObject disableChannel2 = new JSONObject();
//disableChannel2.put("payChannelType","BIGAMOUNT_CREDIT_CARTOON");
//disablePayChannels.add(disableChannel2);
//// 设置禁用渠道(无特殊诉求请勿传入)
//bizContent.put("disable_pay_channels",disablePayChannels);
//// 买家实名信息(无特殊诉求请勿传入)
//JSONObject identityParams = new JSONObject();
//String identityHash = genHashCode("SHA-256","UTF-8","张三","4566498798498498498498");
//identityParams.put("identity_hash",identityHash);
//identityParams.put("alipay_user_id","2088345012230098");
//bizContent.put("identity_params",identityParams);
//// 设置扩展参数
//JSONObject extraParam = new JSONObject();
//extraParam.put("category","CHARGE_PILE_CAR");
//extraParam.put("serviceId","2020042800000000000001450466");
//bizContent.put("extra_param",extraParam);
// 设置整体请求参数
request.setBizContent(bizContent.toString());
// 使用sdkExecute方法发起请求
AlipayFundAuthOrderAppFreezeResponse response = alipayClient.sdkExecute(request);
if(response.isSuccess()){
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}
/*******以下为identity_hash生成加密串的方法示例,无实名校验诉求可忽略********/
/**
* 根据给定的一个或多个字符串获得摘要
* 使用SHA256摘要方式与UTF8编码,返回十六进制的字符串
*
* @param strsToBeDigest
* @return 十六进制的字符串
*/
private static String genHashCode(String algorithmType, String charset, String... strsToBeDigest) {
//拼接字符串,再hash
StringBuilder sb = new StringBuilder();
for (String str : strsToBeDigest) {
sb.append(str);
}
String identity = sb.toString();
MessageDigest messageDigest;
String hashResult = "";
try {
messageDigest = MessageDigest.getInstance(algorithmType);
byte[] bytes = messageDigest.digest(identity.getBytes(charset));
hashResult = convertByteToHexString(bytes);
} catch (NoSuchAlgorithmException e) {
System.out.println("获得实名hash值出错,无此hash算法");
} catch (UnsupportedEncodingException e) {
System.out.println("获得实名hash值出错,不支持此编码");
}
return hashResult;
}
/**
* 将字节数组转为十六进制字符串
*
* @param bytes
* @return
*/
private static String convertByteToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
String byteString;
for (byte aByte : bytes) {
//byte转为int时高位补零
byteString = Integer.toHexString(aByte & 0xFF);
if (byteString.length() == 1) {
//补齐2位
sb.append("0");
}
sb.append(byteString);
}
return sb.toString();
}
重要入参说明
参数名称 | 参数说明 |
---|---|
out_order_no | 商户授权资金订单号。 |
out_request_no | 商户本次资金操作的请求流水号。 |
order_title | 订单标题。 |
amount | 需要冻结的金额,由商户根据自身业务评估金额。 |
product_code | 产品码,根据开通支付产品传参;开通预授权支付产品传 PREAUTH_PAY,开通支付宝预授权产品传 PRE_AUTH_ONLINE |
extra_param | 业务扩展参数,用于商家的特定业务信息的传递,JSON 格式。 授权业务对应的类目:key 为 category 信用场景下必传,value 为业务分类,例如:充电桩业务传 CHARGE_PILE_CAR 。 信用服务ID:key 为 serviceId 信用场景下 必传。信用服务 ID 需要商家在 芝麻信用服务平台 创建信用服务获取,详情可查看 创建信用服务。在创建过程中如果有其它疑问,可以咨询芝麻客服小二(0571-88158055 转 2)。例如:{"category":"CHARGE_PILE_CAR","serviceId":"2019*********************300"} |
外部商户的门店编号:key 为 outStoreCode ,可选。 | |
外部商户的门店简称:key 为 outStoreAlias ,可选,将在用户端信用守护、支付信息、账单详情页展示。 | |
间联模式必须传入二级商户所属机构 ID,key 为 requestOrgId。 | |
notify_url | 异步通知地址,异步通知响应详情可查看文中 授权异步通知 章节,当用户授权成功时将触发异步通知返回 auth_no等授权结果信息。若未设置 notify_url 则需调用 alipay.fund.auth.operation.detail.query(资金授权操作查询接口)轮询用户授权结果,当接口返回 order_status = AUTHORIZED 时则用户授权成功 |
deposit_product_mode | 免押受理台模式,根据免押不同业务模式将开通受理台区分三种模式,商家可根据调用预授权冻结接口传入的参数决定该笔免押订单使用哪种受理台模式。不同受理台模式需要传入不同参数,其中:POSTPAY 表示后付金额已知,POSTPAY_UNCERTAIN 表示后付金额未知,DEPOSIT_ONLY 表示纯免押。具体规则参考文档:https://opendocs.alipay.com/b/08tf3t?pathHash=d67d7545 |
post_payments | 后付费项目, 有付费项目时需要传入该字段。不同受理台模式需要传入不同参数,后付费项目名称和计费说明需要通过校验规则,同时计费说明将展示在开通受理台上。具体规则参考文档:https://opendocs.alipay.com/b/08tf3t?pathHash=d67d7545 |
payee_user_id | 可选字段,收款账户的支付宝用户号,支付宝用户号可以登录 开放平台控制台 查看 账号 ID 获得。 |
payee_logon_id | 可选字段,收款账户的支付宝登录号(email 或手机号)。如果商户希望用户能够使用花呗,则用户号(payee_user_id)和登录号(payee_logon_id)两者必须传入其一。 |
enable_pay_channels | 可选字段,可以指定支付渠道,如果不传,默认为签约协议的支付渠道;若需要限制支付渠道,目前仅支持余额宝(MONEY_FUND)、花呗(PCREDIT_PAY)以及芝麻信用(CREDITZHIMA)。冻结用户花呗(PCREDIT_PAY)额度渠道升级中,暂不支持新用户申请接入,请关注后续通知。 |
**
唤起冻结页
APP 支付冻结
Android 样例代码
final String orderInfo = info; // 订单信息
Runnable payRunnable = new Runnable() {
@Override
public void run () {
PayTask alipay = new PayTask(DemoActivity. this );
Map<String,String> result = alipay.payV2(orderInfo, true );
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必须异步调用
Thread payThread = new Thread(payRunnable);
payThread.start();
入参说明
出参获取
private Handler mHandler = new Handler() {
public void handleMessage (Message msg) {
Result result = new Result((String) msg.obj);
Toast.makeText(DemoActivity. this , result.getResult(),
Toast.LENGTH_LONG).show();
};
};
iOS 样例代码
H5 支付冻结
示例代码
<script src= "https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.inc.min.js"></script>
<button id = "J_btn" class = "btn btn-default">支付</button>
<script>
var btn = document.querySelector('#J_btn');
btn.addEventListener('click', function(){
ap.tradePay({
orderStr : 'timestamp=2016-12-27%2018%3A00%3A00&method=alipay.trade.app.pay&app_id=2014073000007292......'
}, function( res ) {
ap.alert(res.resultCode);
});
});
</script>
使用介绍
OPTION.orderStr
参数。名称 | 类型 | 必填 | 描述 |
---|---|---|---|
tradeNO | String | 否 | 交易号,多个交易号请用英文分号 ; 分隔 |
partnerID | String | 否 | 商户 id |
bizType | String | 否 | 交易类型,默认为 trade |
bizSubType | String | 否 | 交易子类型 |
bizContext | String | 否 | 支付额外的参数,格式为 JSON 字符串 |
orderStr | String | 否 | 完整的支付参数拼接成的字符串,从服务端获取。 |
名称 | 类型 | 描述 |
---|---|---|
resultCode | String | 支付结果状态码,详情可查看下表。 |
resultCode | 描述 |
---|---|
9000 | 订单支付成功 |
8000 | 正在处理中 |
4000 | 订单支付失败 |
6001 | 用户中途取消 |
6002 | 网络连接出错 |
99 | 用户点击忘记密码导致快捷界面退出(only iOS) |
小程序支付唤起冻结
示例代码
my.tradePay({
orderStr: 'myOrderStr', // 完整的支付参数拼接成的字符串,从服务端获取
success: (res) => {
my.alert({
content: JSON.stringify(res),
});
},
fail: (res) => {
my.alert({
content: JSON.stringify(res),
});
}
});
唤起冻结注意事项
授权异步通知
用户授权成功异步通知样例
https://www.merchant.com/receive_notify.htm?gmt_create=2022-12-07 11%3A30%3A42&charset=utf-8&rest_credit_amount=0.01&operation_type=FREEZE&sign=$$$&rest_fund_amount=0.00&auth_no=20221207****************7851¬ify_id=20221207***************6835&total_freeze_credit_amount=0.01¬ify_type=fund_auth_freeze&gmt_trans=2022-12-07 11%3A31%3A43&operation_id=20221207*******1805&total_pay_fund_amount=0.00&out_request_no=20221207********0141&payer_user_id=2088********2180&app_id=20141********3222&sign_type=RSA2&amount=0.01&rest_amount=0.01¬ify_time=2022-12-07 11%3A31%3A43&fund_amount=0.00&total_pay_credit_amount=0.00&payee_user_id=2088*******0335&credit_amount=0.01&pre_auth_type=CREDIT_AUTH&out_order_no=20221207*******0141&total_freeze_fund_amount=0.00&payee_logon_id=ali***%40alipay.com&version=1.0&total_unfreeze_fund_amount=0.00&total_pay_amount=0.00&total_freeze_amount=0.01&total_unfreeze_credit_amount=0.00&auth_app_id=20141********3222&total_unfreeze_amount=0.00&status=SUCCESS&payer_logon_id=156****8305
参数说明
参数名 | 参数说明 |
---|---|
auth_no | 支付宝资金授权订单号 |
out_order_no | 商家的资金授权订单号 |
operation_id | 支付宝的资金操作流水号 |
out_request_no | 商家资金操作流水号 |
验签方法
异步通知接收代码规范
示例代码
资金信用冻结转支付场景
示例代码
package com.java.sdk.demo;
import com.alipay.v3.ApiException;
import com.alipay.v3.ApiClient;
import com.alipay.v3.util.model.AlipayConfig;
import com.alipay.v3.Configuration;
import com.alipay.v3.api.AlipayTradeApi;
import com.alipay.v3.model.*;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AlipayTradeApiPay {
public static void main(String[] args) throws ApiException {
ApiClient defaultClient = Configuration.getDefaultApiClient();
// 初始化alipay参数(全局设置一次)
AlipayConfig alipayConfig = new AlipayConfig();
alipayConfig.setServerUrl("https://openapi.alipay.com");
alipayConfig.setAppId("<-- 请填写您的AppId,例如:2019091767145019 -->");
alipayConfig.setPrivateKey("<-- 请填写您的应用私钥,例如:MIIEvQIBADANB ... ... -->");
alipayConfig.setAlipayPublicKey("<-- 请填写您的支付宝公钥,例如:MIIBIjANBg... -->");
defaultClient.setAlipayConfig(alipayConfig);
AlipayTradeApi api = new AlipayTradeApi();
AlipayTradePayModel data = new AlipayTradePayModel();
data.setAuthConfirmMode("COMPLETE");
PromoParam promoParams = new PromoParam();
promoParams.setActualOrderTime("2018-09-25 22:47:33");
data.setPromoParams(promoParams);
data.setProductCode("FACE_TO_FACE_PAYMENT");
data.setUndiscountableAmount("8.88");
data.setDiscountableAmount("80.00");
BkAgentReqInfo bkagentReqInfo = new BkAgentReqInfo();
bkagentReqInfo.setMerchCode("123412341234");
bkagentReqInfo.setLocation("+37.28/-121.268");
bkagentReqInfo.setDeviceType("02");
bkagentReqInfo.setAcqCode("12345678901234");
bkagentReqInfo.setSerialNum("123123123123");
data.setBkagentReqInfo(bkagentReqInfo);
data.setRequestOrgPid("2088201916734621");
List<GoodsDetail> goodsDetail = new ArrayList<GoodsDetail>();
GoodsDetail goodsDetail0 = new GoodsDetail();
goodsDetail0.setQuantity(1);
goodsDetail0.setPrice("2000");
goodsDetail0.setGoodsCategory("34543238");
goodsDetail0.setCategoriesTree("124868003|126232002|126252004");
goodsDetail0.setGoodsId("apple-01");
goodsDetail0.setShowUrl("http://www.alipay.com/xxx.jpg");
goodsDetail0.setGoodsName("ipad");
goodsDetail0.setOutItemId("outItem_01");
goodsDetail0.setOutSkuId("outSku_01");
goodsDetail.add(goodsDetail0);
data.setGoodsDetail(goodsDetail);
data.setTerminalId("NJ_T_001");
SubMerchant subMerchant = new SubMerchant();
subMerchant.setMerchantId("2088000603999128");
subMerchant.setMerchantType("alipay");
data.setSubMerchant(subMerchant);
SettleInfo settleInfo = new SettleInfo();
List<SettleDetailInfo> settleDetailInfos = new ArrayList<SettleDetailInfo>();
SettleDetailInfo settleDetailInfos0 = new SettleDetailInfo();
settleDetailInfos0.setTransInType("cardAliasNo");
settleDetailInfos0.setAmount("0.1");
settleDetailInfos0.setTransIn("A0001");
settleDetailInfos0.setActualAmount("0.1");
settleDetailInfos0.setSummaryDimension("A0001");
settleDetailInfos0.setSettleEntityType("SecondMerchant");
settleDetailInfos0.setSettleEntityId("2088xxxxx;ST_0001");
settleDetailInfos.add(settleDetailInfos0);
settleInfo.setSettleDetailInfos(settleDetailInfos);
settleInfo.setSettlePeriodTime("7d");
data.setSettleInfo(settleInfo);
data.setSellerId("2088102146225135");
data.setBody("Iphone6 16G");
data.setAuthCode("28763443825664394");
data.setScene("bar_code");
AgreementParams agreementParams = new AgreementParams();
agreementParams.setAgreementNo("20170322450983769228");
agreementParams.setDeductPermission("2021571176714791277815457854545");
agreementParams.setApplyToken("MDEDUCT0068292ca377d1d44b65fa24ec9cd89132f");
agreementParams.setAuthConfirmNo("423979");
data.setAgreementParams(agreementParams);
data.setAuthNo("2016110310002001760201905725");
data.setTimeoutExpress("90m");
data.setStoreId("NJ_001");
ExtendParams extendParams = new ExtendParams();
extendParams.setTradeComponentOrderId("2023060801502300000008810000005657");
extendParams.setSysServiceProviderId("2088511833207846");
extendParams.setIndustryRefluxInfo("{\"scene_code\":\"metro_tradeorder\",\"channel\":\"xxxx\",\"scene_data\":{\"asset_name\":\"ALIPAY\"}}");
extendParams.setSpecifiedSellerName("XXX的跨境小铺");
extendParams.setRoyaltyFreeze("true");
extendParams.setCardType("S0JP0000");
data.setExtendParams(extendParams);
PayParams payParams = new PayParams();
payParams.setAsyncType("NORMAL_ASYNC");
payParams.setRetryType("NONE");
data.setPayParams(payParams);
data.setBuyerId("2088202954065786");
data.setOutTradeNo("20150320010101001");
data.setAdvancePaymentType("ENJOY_PAY_V2");
data.setOperatorId("yx_001");
List<String> queryOptions = new ArrayList<String>();
queryOptions.add("voucher_detail_list");
data.setQueryOptions(queryOptions);
data.setSubject("Iphone6 16G");
data.setIsAsyncPay(false);
data.setTimeExpire("2021-12-31 10:05:00");
data.setTotalAmount("88.88");
try {
AlipayTradePayResponseModel response = api.pay(data);
} catch (ApiException e) {
AlipayTradePayDefaultResponse errorObject = (AlipayTradePayDefaultResponse) e.getErrorObject();
System.out.println("调用失败:" + errorObject);
}
}
}
重要入参说明
参数名称 | 参数说明 |
---|---|
notify_url | 非必填,支付成功异步接收地址。 |
extend_params | 如果需返佣接入时还需要传入 "extend_params":{"sys_service_provider_id":"ISV签约账户的PID"} 参数用于计算返佣。 |
auth_confirm_mode | 非必填,预授权确认模式。当 auth_confirm_mode = COMPLETE 时无需调用解冻接口,支付宝端在扣款成功后会自动解冻剩余金额,同时该笔授权订单完成。 |
当 auth_confirm_mode = NOT_COMPLETE 时,商家收到支付成功通知后需要自行调用 alipay.fund.auth.order.unfreeze(资金授权解冻接口)将余额进行解冻。 | |
如果需要从一笔授权中完成多笔订单支付,保持 auth_no 不变,不同订单根据 out_trade_no 进行标识,此时 auth_confirm_mode 不传或者传入 NOT_COMPLETE;进行到最后一笔转支付时,auth_confirm_mode 传入 COMPLETE 由支付宝完成剩余金额自动解冻,或者商家自行调用解冻接口将剩余金额解冻。 | |
deduction_subject | 必填,扣款原因,扣款原因是扣押金需传 入DEPOSIT ,扣后付服务费用(租金、房费等)需传入SERVICE_FEE 。扣款时需要满足校验规则,否则扣款将被拦截具体规则参考文档:https://opendocs.alipay.com/b/08tf3t?pathHash=d67d7545 |
出参处理
支付异步通知
资金授权转支付通知示例
gmt_create=2022-12-07 16:38:26&charset=utf-8&seller_email=$$$&subject=资金信用转支付&sign=$$$&buyer_id=2088********2180&invoice_amount=0.01¬ify_id=20221207*****************7576&fund_bill_list=[{"amount":"0.01","fundChannel":"ALIPAYACCOUNT"}]¬ify_type=trade_status_sync&trade_status=TRADE_SUCCESS&receipt_amount=0.01&app_id=2014********3222&buyer_pay_amount=0.01&sign_type=RSA2&seller_id=2088********0335&gmt_payment=2022-12-07 16:38:28¬ify_time=2022-12-07 16:38:29&version=1.0&out_trade_no=20221207********pay&total_amount=0.01&trade_no=20221207*****************0384&auth_app_id=2014********3222&buyer_logon_id=156****8305&point_amount=0.00
参数说明:
参数名称 | 参数说明 |
---|---|
out_trade_no | 商户外部交易号 |
trade_no | 支付宝交易号 |
trade_status | 交易状态 |
receipt_amount | 实收金额 |