银联支付-代付功能
功能描述
我司使用场景:业务场景,为物业公司开发物业管理平台系统,包括APP,物业管理后台等。物业费、停车费等通过APP支付后,所缴费用首先是在我司所绑定的银行卡中,然后通过集成银联支付的代付功能来完成将这些费用分发至每个物业公司的银行卡账号中(这样做的目的前提:由于申请微信商户号,务必提供一个应用如app,所有的物业公司都是使用的我司提供的app,故每个物业公司不可能各自申请一个商户号)
接入银联代付流程
接入银联代付流程链接
代付业务都是从收单机构入网的,产品是收单机构的,通道是银联的!
接入银联支付产品,您需通过收单机构向您提供支付结算服务。收单机构审核后,会有专门人员和你联系有关入网申请提交资料的相关事宜,此时你可以先让对方提供测试版的商户号、sdk jar包、商户签名私钥、ChinaPay签名公钥和开发文档api等相关资料,可以边准备所需资料边进行开发(温馨提示:接入费用一次性5000元,后期每成交一笔收取2元手续费金额不限)。
商户需要提前将钱充值到银联所提供的备付金账号(可以线上或线下),在向物业公司付费时,实质是从备付金账号到物业公司,故转账前提需要保证备付金账号的余额充足!银联方会提供查询备付金余额的接口
注意事项
通过调银联接口进行转账基本一个小时左右就可以到账,如从向银联发起支付时间算起超过三天还未到账,则可被视为超时处理,建议开一个定时任务去处理这类逻辑
API文档
查询备付金余额
参数
MERID:商户号
MERKEY_PATH:商户签名私钥路径
PUBKEY_PATH:ChinaPay签名公钥路径
public String getAccountBalance() throws Exception{
String DataRequest = MERID + VERSION;
String plainDataReturn = new String(Base64.encode(DataRequest.getBytes()));
//签名
String chkValue = null;
int KeyUsage = 0;
PrivateKey key = new PrivateKey();
key.buildKey(MERID, KeyUsage, MERKEY_PATH);
SecureLink sl = new SecureLink(key);
chkValue = sl.Sign(plainDataReturn);
HttpClient httpClient = new HttpClient();
httpClient.getHttpConnectionManager().getParams()
.setConnectionTimeout(60000);
httpClient.getHttpConnectionManager().getParams().setSoTimeout(60000);
httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
PostMethod postMethod = new PostMethod(BALANCE_QUERY);
//填入各个表单域的值
NameValuePair[] data = {
new NameValuePair("merId", MERID),
new NameValuePair("version", VERSION),
new NameValuePair("chkValue",chkValue),
new NameValuePair("signFlag", SIGN_FLAG)
};
// 将表单的值放入postMethod中
postMethod.setRequestBody(data);
// 执行postMethod
try {
httpClient.executeMethod(postMethod);
} catch (Exception e) {
e.printStackTrace();
}
// 读取内容
InputStream resInputStream = null;
try {
resInputStream = postMethod.getResponseBodyAsStream();
} catch (IOException e) {
e.printStackTrace();
}
// 处理内容
BufferedReader reader = new BufferedReader(new InputStreamReader(resInputStream));
String tempBf = null;
StringBuffer html=new StringBuffer();
while((tempBf = reader.readLine()) != null){
html.append(tempBf);
}
String resMes = html.toString();
System.out.println("单笔查询返回报文:" + resMes);
int dex = resMes.lastIndexOf("|");
String Res_Code = resMes.substring(0,3);
//提取返回数据
if(Res_Code.equals("000")){
String Res_stat = resMes.substring(dex-2,dex-1);
String Res_chkValue = resMes.substring(dex+1);
System.out.println("Res_Code=" + Res_Code);
System.out.println("Res_stat=" + Res_stat);
System.out.println("Res_chkValue=" + Res_chkValue);
String plainData = resMes.substring(0,dex+1);
String accountBalance = plainData.substring(plainData.substring(0,dex).lastIndexOf("|")+1,dex);
System.out.println("查询账户余额:" + accountBalance);
System.out.println("需要验签的字段:" + plainData);
String Data = new String(Base64.encode(plainData.getBytes()));
System.out.println("转换成Base64后数据:" + Data);
//对收到的ChinaPay应答传回的域段进行验签
boolean buildOK = false;
boolean res = false;
try {
buildOK = key.buildKey("999999999999999", KeyUsage, PUBKEY_PATH);
} catch (Exception e) {
e.printStackTrace();
}
if (!buildOK) {
System.out.println("build error!");
return null;
}
res=sl.verifyAuthToken(Data,Res_chkValue);
System.out.println(res);
if (res){
System.out.println("验签数据正确!");
} else {
System.out.println("签名数据不匹配!");
}
return accountBalance;
} else {
String Res_chkValue = resMes.substring(dex+1);
String plainData = resMes.substring(0,dex+1);
System.out.println("需要验签的字段:" + plainData);
String Data = new String(Base64.encode(plainData.getBytes()));
System.out.println("转换成Base64后数据:" + Data);
//对收到的ChinaPay应答传回的域段进行验签
boolean buildOK = false;
boolean res = false;
try {
buildOK = key.buildKey("999999999999999", KeyUsage, PUBKEY_PATH);
} catch (Exception e) {
e.printStackTrace();
}
if (!buildOK) {
System.out.println("build error!");
return null;
}
res=sl.verifyAuthToken(Data,Res_chkValue);
System.out.println(res);
if (res){
System.out.prin