继微信收款码之后,迎来了又一个新的对接支付方式---工商银行收款码支付
准备工作:
1.获取工行API在线文档地址:https://open.icbc.com.cn/icbc/apip/api_list.html
2.拿到相应的业务参数,包括publicKey,privateKey,appId,merId,storeCode等参数
3.获取相应Demo开发包:https://open.icbc.com.cn/icbc/apip/docs_sdk&demo.html
4.根据自己的相应业务场景需要,打开相应的demo文件(开发包中有几百个业务场景,并且根据不同版本有不同的demo示例,需要我们找到自身的版本及业务场景获得正确的代码)
开发
1.工行二维码----生成二维码
package com.youfuli.vendor.utils.icbc;
import com.icbc.api.DefaultIcbcClient;
import com.icbc.api.IcbcApiException;
import com.icbc.api.IcbcConstants;
import com.icbc.api.request.QrcodeGenerateRequestV2;
import com.icbc.api.request.QrcodeGenerateRequestV2.QrcodeGenerateRequestV2Biz;
import com.icbc.api.response.QrcodeGenerateResponseV2;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 工银二维码生成接口
*
* 请商户配置SDK中的lib文件夹中的jar包后,根据备注1-6提示进行数据替换
*/
public class QrcodeGenerateTest {
//1、网关公钥
protected static final String APIGW_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwFgHddddD4kzEVPdOj03ctKM7KV+16bWZ5BMNgvEeuEQwfQYkRVwI9HFOGkwNTMn5hiJXHnlXYCX+zp5r6R52MY0O7BsTCLT7aHaxsANsvI9ABGx3OaTVlPB59M6GPbJh0uXvio0m1r/lTW3Z60RU6Q3oid/rNhP3CiNgg0W6O3AGqwIDAQAB";
//2、appid
protected static final String APP_ID = "1000000ddd0000000651001";
//3、密钥对认证方式,公钥在API平台登记,此处为私钥
protected static final String MY_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7HTTvUpWkNs9ShetLtmfVXOVAhwGu3wB88TBnp+xd5Du2hthidHwOIWMo6JV58r2trIuDhap7MPiubbeJy6W4IsHwtRxV4cZ5ZvRpIHKM005A4eIfHmr/Vwo9PNXCmFHictU0ggTtwNNNrFM4gdOn1W8qMmhLjorjWglcEPj8oZgO5BNih2LCylZtRpUhTmNGzNue+hxQjY48eGWZy+cKPf147oMTqKC87P5xDfCTF/aIpVyHNeZfW1kj6VmanPoZVZL9sI4rMwacznBW+EJyqoXw1uHXMiW/WW/Zfm3LQM4lkOPneMsY8IOTq9ypPEpaUZTnDPyfXpG87Zerk9EYtAgMBAAECggEAcK3T9NL8vlkrXHy9B2ke+kPo4oTqpI4yUwtDpQhgtOH+e5qUsCfhWJl1DP0BDQAxIE2gw09EoqusAtrnnrxdsdluAIcd14CZQbamuPEg+jXKBbgyBayBaU/+Cyo1Rk9eQsNLfFy+u9IYebyHAt1leD/mX8mOGhEk8WszhFnyDPlDl48MQat+qieuZgJJ+3s4XO6u6FFWhwRnJrRDFSpc14qzsjoBUdiDtgwVFtjXL9DubxifqoQTzXj8nwFUvBXPtOzl+0JimImzM90cB0mR+bkeJ8NgaEKVz5ln1OiXfOr3RBnytMyW1D7hjlwOjdm1hg8oAWQFeN8fGUx6dmx9UD8zzmQKBgQdasdD/s+MRQ+e7lWQfV/PjbxeFpVb23FsPaHtWpPUbgJBxxi6ajEjbybzhJlkqt6cz8JGC+Nq8rn3AEMCC0/GtwqsTVD2rZRx1HUMZskfT15zCGnP/9WXsSrYJVmqs4IafiBg4vJp//aJsuO1AiabM7maWZIpmiVfZs2TvfNNCB8VrLwKBgQC7VOdP+jPTNsbFOf6s1+2FZTL+qADMu3ZJp2NQPZ/sulazKsY5WmrOqYzZgA4THEILcCk7/P2YIW+rYdSZPmkeEYPsMVpnCjdPUMtb5LoxZzvn2JeGaGY1MB/TcwkSt/anpCLnsvDSolRU2qI9K6qjPY5rBJ9oOZHjFPSPhSdasdCdYwKBgQD2LMKkYaLdVuNQxcV5JgAYW+kQu28zs1xjO2b69liaILnHct3GNEAS52+bD7r651XAKUO1uaw5WCdvDQu1RSCc+FJzC2JNYkGyoJBEZGV3/i3FtAVPa1I8RSVokLUrK8ReAz4fkRlp4NQReTTMQY0kp2ETfJDGd87qPlvJS2AGYdsadwKBgEG2RbHDVZyYkV8ruc9Nqy7o0duMeUNX2uV5RxgllczHjJQqw//oXKEDzrmY9tbzSaOTg5NcamSMDgzzM01SHDOE917J7SlJ5x72e29Pq5Sa3uO0EWr/giLUL8XPi3Y6e9ZQeEIIffuVH7noO5Lzl1bNyAB4TaaU0zzx49vYWhl7AoGAPZhGcp33nKLUvmPh1yl+L4Ziqmb7b+jT72goj3IdCxSMHQWumNp11PQKJbS10rqbJsVY8JOeUW3Cj7ZMxFsF5aTkiH/OC5yPi5X4++pYIJKLj8WsAS+MTyQD0aCdoKe4O6hJWeZLRrqZ5YlyCkAdhBsre5WEYkPXtaAfte8oMYg=";
public static void main(String[] args) throws Exception {
//签名类型为RSA2时,需传入appid,私钥和网关公钥,签名类型使用定值IcbcConstants.SIGN_TYPE_RSA2,其他参数使用缺省值
DefaultIcbcClient client = new DefaultIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY, APIGW_PUBLIC_KEY);
QrcodeGenerateRequestV2 request = new QrcodeGenerateRequestV2();
//4、根据测试环境和生产环境替换相应ip和端口
request.setServiceUrl("https://gw.open.icbc.com.cn/api/qrcode/V2/generate");
//5、请对照接口文档用bizContent.setxxx()方法对业务上送数据进行赋值
QrcodeGenerateRequestV2Biz bizContent = new QrcodeGenerateRequestV2Biz();
Date date=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat sdf2=new SimpleDateFormat("HHmmss");
System.out.println(sdf2.format(date));
bizContent.setMerId("108787871409");
bizContent.setStoreCode("1007878778018138");
//商户系统订单号
bizContent.setOutTradeNo(System.currentTimeMillis()+"");
//订单总金额,单位:分
bizContent.setOrderAmt("1");
//商户订单生成日期
bizContent.setTradeDate(sdf.format(date));
//商户订单生成时间
bizContent.setTradeTime(sdf2.format(date));
//商户附加数据
bizContent.setAttach("abcdefg");//该字段非必输项
//二维码有效期 秒
bizContent.setPayExpire("1200");
bizContent.setNotifyUrl("127.0.0.1");//该字段非必输项
//商户订单生成的机器IP
bizContent.setTporderCreateIp("127.0.0.1");
//扫码后是否需要跳转分行,0:否,1:是;非1按0处理
bizContent.setSpFlag("0");//该字段非必输项
//商户是否开启通知接口 0-否;1-是;非1按0处理
bizContent.setNotifyFlag("1");
request.setBizContent(bizContent);
QrcodeGenerateResponseV2 response = new QrcodeGenerateResponseV2();
try {
//response = client.execute(request, "msgId");//msgId消息通讯唯一编号,要求每次调用独立生成,APP级唯一
response = client.execute(request, bizContent.getMerId());//msgId消息通讯唯一编号,要求每次调用独立生成,APP级唯一
if (response.isSuccess()) {
//6、业务成功处理,请根据接口文档用response.getxxx()获取同步返回的业务数据
System.out.println("ReturnCode:"+response.getReturnCode());
System.out.println("response:" + response);
System.out.println("工行二维码链接为:"+response.getQrcode());
} else {
//失败
System.out.println("ReturnCode:" + response.getReturnCode());
System.out.println("ReturnMsg:" + response.getReturnMsg());
}
} catch (IcbcApiException e) {
e.printStackTrace();
}
}
}
这个是工行提供的demo中的源代码,其中我们只需要修改相应的merId和storeCord,以及对相应的业务参数做出匹配修改即可,本文中的demo是我修改后的版本,大家替换自己的参数修改即可。
注意,跑通代码需要导入几个jar包,前者三个是必须的,最后一个根据自己电脑的条件进行添加,这些jar包都可以在工行提供的开发包中找到
2.接收工行支付回调
工行的支付回调,只需要在下单时传入notify_url字段即可,但是坑就坑在这里,既没有说回调参数是哪些,也没有说通过哪种方式传递参数,关键的关键是,工行就给你开放了一个80端口,但是它还就不告诉你,因为这个我是真的到处怀疑人生。所以,大家在接收回调的时候,以80端口接收,打印出所有传递参数,然后自己再做处理,这边我把打印返回参数的map贴一下
// 参数Map
Map properties = request.getParameterMap();
// 返回值Map
Map returnMap = new HashMap();
Iterator entries = properties.entrySet().iterator();
Map.Entry entry;
String name = "";
String value = "";
while (entries.hasNext()) {
entry = (Map.Entry) entries.next();
name = (String) entry.getKey();
Object valueObj = entry.getValue();
if(null == valueObj){
value = "";
}else if(valueObj instanceof String[]){
String[] values = (String[])valueObj;
for(int i=0;i<values.length;i++){
value = values[i] + ",";
}
value = value.substring(0, value.length()-1);
}else{
value = valueObj.toString();
}
log.info("回调参数:"+name+":"+ value);
returnMap.put(name,value);
}
由于返回参数涉及我们公司的一些信息,就不张贴了,大家可以根据此代码自己尝试。
工行的回调通知,不需要我们返回相应的响应信息,也不管我们有没有收到,宇宙第一大行是真的厉害!!!
3.工行退款
package com.youfuli.vendor.utils.icbc;
import com.icbc.api.DefaultIcbcClient;
import com.icbc.api.IcbcApiException;
import com.icbc.api.IcbcConstants;
import com.icbc.api.request.QrcodeRejectRequestV2;
import com.icbc.api.request.QrcodeRejectRequestV2.QrcodeRejectRequestV2Biz;
import com.icbc.api.response.QrcodeRejectResponseV2;
/**
* 工银二维码退款接口
*
* 请商户配置SDK中的lib文件夹中的jar包后,根据备注1-6提示进行数据替换
*/
public class QrcodeRejectTest {
//1、网关公钥
protected static final String APIGW_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBsiQKBgQCwFgHD4kzEVPdOj03ctKM7KV+1aaa6bWZ5BMNgvEeuEQwfQYkRVwI9HFOGkwNTMn5hiJXHnlXYCX+zprl5r6R52MY0O7BsTCLT7aHaxsANsvI9ABGddx3OaTVlPB59M6GPbJh0uXvio0m1r/lTW3Z60RU6Q3oid/rNhP3CiNgg0dW6O3AGqwIDAQAB";
//2、appid
protected static final String APP_ID = "10000000000000002156";
//3、密钥对认证方式,公钥在API平台登记,此处为私钥
protected static final String MY_PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIJBzZNaiobplRUgtJ4OzmUvZRK99ih/fUyDBOoFLtpJJCCRzp8T6V11YNlE7Xg5dt+EG7byQs2NImqg0eWEj/mBdZ7UmlAct7BNw2hyF2h4R5OEfXyjoH3wqGjKJayhaHTvLM1DYy/mDFBb0ShJYI1QMScQJZhsOhMMFhrrZwIZAgMBAAECgYAA2kdrOIOBoJPOQJmOE1C8jtPdjIrI9xSt5Imqsn/9A8dd+NuwacOfgkGXmZ0n6vc8jYa7f2uZ1AVTUtdd4IIO5bpq8s0Tw2BfWALYwr/JdUuNKSjHVQsh/Do+wl8BgOgB4RqsNXWNGtoMdsdsaC8lHKHmrVcpyJMfDc3cP07NZ1wG2zB0lQJBAM+dNZv2L/Z4RzvQcoVZEthYavZ4pkFfoWGYC4jwc5G8um76zoQyrtxWYrtTP0GS+xFFX2dDZHAkBGnZ8vfdYIUVeDbDrzWXvCEXXJqewbKwOT2KqnTKM9yj9IBatttJGgvrAKiyH4zCqZD9JaG23sKGeJ8QopL60dAkEAtc4tlKoj3XZzRUXboqz0EhkgkjzDj50zpCD1sJKZ2EZH+A/7tXwPug+RnuSmKpM2uv3msqw3prdS3K4En8+rog==";
public static void main(String[] args) throws Exception {
//签名类型为RSA2时,需传入appid,私钥和网关公钥,签名类型使用定值IcbcConstants.SIGN_TYPE_RSA2,其他参数使用缺省值
DefaultIcbcClient client = new DefaultIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY, APIGW_PUBLIC_KEY);
QrcodeRejectRequestV2 request = new QrcodeRejectRequestV2();
//4、根据测试环境和生产环境替换相应ip和端口
request.setServiceUrl("https://ip:port/api/qrcode/V2/reject");
//5、请对照接口文档用bizContent.setxxx()方法对业务上送数据进行赋值
QrcodeRejectRequestV2Biz bizContent = new QrcodeRejectRequestV2Biz();
bizContent.setMerId("02011101515151");
bizContent.setCustId("Ey0LsS39FwdE35TsSW1A2eeoIRMZrjSa");//该字段非必输项
bizContent.setOutTradeNo("X000000001");//该字段非必输项,out_trade_no和order_id选一项上送即可
bizContent.setOrderId("020001515151201701030000001");//该字段非必输项,out_trade_no和order_id选一项上送即可
bizContent.setRejectNo("X000000001");
bizContent.setRejectAmt("100");
bizContent.setOperId("X000000001");//该字段非必输项
request.setBizContent(bizContent);
QrcodeRejectResponseV2 response;
try {
response = client.execute(request, "msgId");//msgId消息通讯唯一编号,要求每次调用独立生成,APP级唯一
if (response.isSuccess()) {
// 6、业务成功处理,请根据接口文档用response.getxxx()获取同步返回的业务数据
System.out.println("ReturnCode:"+response.getReturnCode());
System.out.println("response:" + response);
} else {
// 失败
System.out.println("ReturnCode:"+response.getReturnCode());
System.out.println("ReturnMsg:"+response.getReturnMsg());
}
} catch (IcbcApiException e) {
e.printStackTrace();
}
}
}
换一个请求退款的url链接,相应装载参数的实体也需要变换,此处请见代码。
工行二维码支付,相比微信支付,银联支付而言,流程相对简单,规范也比较轻松,功能定位也比较明确,相应的代码都封装在sdk中,只可远观而不可亵玩焉。所以我们还得努力学习。