欢迎使用拉卡拉开放平台Java SDK
欢迎使用 拉卡拉开放平台SDK for Java 。
拉卡拉开放平台SDK for Java让您不用复杂编程即可访拉卡拉开放平台开放的各项能力,SDK可以自动帮您满足能力调用过程中所需的证书校验、加签、验签、发送HTTP请求等非功能性要求。
资源下载
| 开发语言 | 资源下载 |
| JAVA | Java SDK |
环境要求
1.需要使用JDK 1.8或其以上版本;
2.SDK接入准备:
●根据拉卡拉开放平台接入指引,生成密钥参见拉卡拉开放平台-安全统一接入规范
●接入方生成密钥对后,需要将公钥证书提供给拉卡拉,同时获取拉卡拉的公钥证书并保存
●如接口需密文传输,需要先向拉卡拉进行SM4秘钥申请
●拉卡拉为接入方分配appId
●申请对应接口访问权限
3.准备工作完成后,注意保存如下信息,后续将作为使用SDK的输入。商户的私钥、商户的公钥、拉卡拉公钥证书。
安装依赖
方法一:
将拉卡拉sdk打包deploy到自己私服仓库,通过maven管理项目
推荐通过Maven来管理项目依赖,您只需在项目的pom.xml文件中声明如下依赖
<dependency> <groupId>com.lkl.laop.sdk</groupId> <artifactId>lkl-laop-java-sdk</artifactId> <version>1.0.x</version> </dependency>
方法二:
项目直接引入拉卡拉sdk jar包,并增加所需依赖
<dependency> <groupId>com.lkl.laop.sdk</groupId> <artifactId>lkl-laop-java-sdk</artifactId> <version>1.0.x</version> <systemPath>${project.basedir}/src/main/resources/lib/lkl-java-sdk-1.0.x.jar</systemPath> <scope>system</scope> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.30</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.13.3</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.68</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.68</version> </dependency>快速使用
1.安装好依赖库保证运行环境没问题,可直接运行SDK demo,如调用接口正常返回说明运行环境配置成功;
2.更换接入配置(appId、序列化、私钥、拉卡拉证书),看接口请求是否成功。如证书验证或加签验签失败,请检查相关配置;
3.拉卡拉开放平台测试环境服务地址:https://test.wsmsd.cn/sit。生产环境服务地址:https://s2.lakala.com。
4.DEMO中提供两种初始化接入配置参数的方式,可根据情况自行选择。
以下这段代码示例向您展示了使用拉卡拉SDK for Java调用一个API的4个主要步骤:
1.初始SDK接入参数。系统初始化时只需做一次;
2.创建API请求对象并设置请求参数;
3.通过LKLSDK.httpPost()发起请求;
4.处理响应或异常。
private static final String appId="拉卡拉开放平台进行配置开通"; private static final String serialNo="商户证书序列号,和商户私钥对应"; private static final String priKeyPath="商户私钥地址,用于请求签名"; private static final String lklCerPath=" 拉卡拉公钥证书地址,用于验签"; private static final String lklNotifyCerPath=" 拉卡拉支付平台证书地址2(用于拉卡拉通知验签,当前同lklCerPath)";
private static final String serverUrl="拉卡拉开放平台服务地址"; private static final String sm4Key = "如果需要密文传输请申请拉卡拉SM4密钥"; private static final String priKeyStr="商户私钥字符串,用于请求签名"; private static final String lklCerStr=" 拉卡拉公钥证书字符串,用于验签"; private static final String lklNotifyCerStr=" 拉卡拉支付平台证书字符串2(用于拉卡拉通知验签,当前同lklCerStr)";
//初始化配置(全局只需配置一次)
//方式1:
LKLSDK.init(new Config(appId,serialNo,priKeyPath,lklCerPath,lklNotifyCerPath,serverUrl));
//方式2:
LKLSDK.init(new Config(appId,serialNo,priKeyPath,lklCerPath,lklNotifyCerPath,sm4Key,serverUrl));
//方式3:
Config config = new Config();
config.setAppId(appId);
config.setSerialNo(serialNo);
config.setPriKeyPath(priKeyPath);
config.setLklCerPath(lklCerPath);
config.setLklNotifyCerPath(lklNotifyCerPath);
config.setServerUrl(serverUrl);
config.setSm4Key(sm4Key);
return LKLSDK.init(config);
//方式4:
Config2 config = new Config2();
config.setAppId(appId);
config.setSerialNo(serialNo);
config.setPriKey(priKeyStr);
config.setLklCer(lklCerStr);
config.setLklNotifyCer(lklNotifyCerStr);
config.setServerUrl(serverUrl);
config.setSm4Key(sm4Key);
return LKLSDK.init(config); //根据请求接口拼装参数
V3LabsTradeQueryRequest v3LabsQueryTradequeryRequest=new V3LabsTradeQueryRequest();
v3LabsQueryTradequeryRequest.setMerchantNo("xxxx");
v3LabsQueryTradequeryRequest.setTermNo("xxx");
v3LabsQueryTradequeryRequest.setOutTradeNo("xxxx"); //发起请求-正常请求
String response=LKLSDK.httpPost(v3LabsQueryTradequeryRequest); //发起请求2(密文传输接口)-请求报文加密,响应信息无需解密
String response2=LKLSDK.httpPost(v3LabsQueryTradequeryRequest,true,false); //发起请求3(密文传输接口)-请求报文加密,响应信息需解密
String response3=LKLSDK.httpPost(v3LabsQueryTradequeryRequest,true,true); //发起请求4-自定义接口参数实体,直接发送接口地址
String response3=LKLSDK.httpPost("url","bodyJson");
//处理响应
log.info(response);●以下代码向您展示了使用拉卡拉SDK for Java接收回调通知的示例
//拉卡拉开放平台采用数据流传输
public ResponseEntity<?> messageHandle(HttpServletRequest request) throws Exception {
// 1. 配置初始化-全局只需要初始化一次
doInit(); //验签并解析请求
String body = LKLSDK.notificationHandle(request);
System.out.println("验签成功,请求body:" + body);
//spring-boot 3.x 使用jakarta.servlet.http.HttpServletRequest接收,读取内容,LKLSDK提供验签方法
LKLSDK.notificationHandle(getBody(request), getAuthorization(request)); //业务处理
return ResponseEntity.ok(body);
}/**
读取请求头
/
private String getAuthorization(HttpServletRequest request) {
return request.getHeader("Authorization");
}/**
读取请求体
/
private final String getBody(HttpServletRequest request) {
try (InputStreamReader in = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8)) {
StringBuilder bf = new StringBuilder();
int len;
char[] chs = new char[1024];
while ((len = in.read(chs)) != -1) {
bf.append(new String(chs, 0, len));
}
return bf.toString();
} catch (Exception e) {
throw new RuntimeException("读取body失败");
} }复制多APPID运行
●如果你的应用需要同时注册多套APPID,请参考如下步骤
//1. 初始化全局配置 //注册第一套 LKLSDK.init("第一套参数"); //注册第二套 LKLSDK.init("第二套参数"); ... //2. 发起调用 //使用sdk封装实体调用(如果不指定,则使用第一个初始化的appid) ... request.setLklAppId("指定发起的appid"); LKLSDK.httpPost(request); //调用sdk未封装接口(如果不指定,则使用第一个初始化的appid) ... LKLSDK.httpPost("https://test.wsmsd.cn/sit/xxx", body,appId); //3. 回调(如果不指定,则使用第一个初始化的appid) String body = LKLSDK.notificationHandle(httpServletRequest,appid);其他
如果出现SDK版本无法自适应接口新字段,以下两种方案提供选择。
1、联系拉卡拉SDK管理人员,请求新的SDK版本。
2、可自行创建实体类并继承V2CommRequest/V3CommRequest(和原封装的接口实体保持一致即可),在自定义的实体类中增加新的参数。使用LKLSDK.httpPost()发起请求调用。
public class V3CcssCounterOrderSpecialCreateRequestExtendDemo extends BaseCommonDemo {
public static void main(String[] args) throws Exception {
// 1. 配置初始化
doInit();
//增加实体一级参数demo
extendFirstStruct();
//增加实体二级参数demo
extendSecondStruct();
//增加调用sdk未封装接口demo
extendAllStruct();
} /**
增加实体最外层字段
> 重写实体继承原实体
*
@see V3CcssCounterOrderSpecialCreateRequestExtend 继承
@see V3CcssCounterOrderSpecialCreateRequest
*/
private static void extendFirstStruct() throws SDKException {
// 创建自定义实体V3CcssCounterOrderSpecialCreateRequestExtend 继承V3CcssCounterOrderSpecialCreateRequest
V3CcssCounterOrderSpecialCreateRequestExtend req = new V3CcssCounterOrderSpecialCreateRequestExtend();
req.setOutOrderNo("8221210594300JY" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
req.setMerchantNo("8221210594300JY");
req.setTotalAmount(10L);
req.setOrderEfficientTime("20230824155923");
req.setNotifyUrl("http://run.mocky.io/v3/b02c9448-20a2-4ff6-a678-38ecab30161d");
req.setSupportRefund(1);
req.setSupportRepeatPay(1);
req.setCounterParam("{"pay_mode":"ALIPAY"}");
req.setSupportCancel(0);
req.setBusiTypeParam("[{"busi_type":"UPCARD","params":{"crd_flg":"CRDFLG_D|CRDFLG_C|CRDFLG_OTH"}},{"busi_type":"SCPAY","params":{"pay_mode":"WECHAT","crd_flg":"CRDFLG_D"}}]");
req.setOrderInfo("测试12313131");
req.setTermNo("T12331234");
List<String> sgnInfos = new ArrayList<>();
sgnInfos.add("1");
req.setSgnInfo(sgnInfos); V3CcssOrderSceneFieldInfo info = new V3CcssOrderSceneFieldInfo();
V3CcssOrderSceneFieldInfo.HbFqSceneInfo hbFqSceneInfo = new V3CcssOrderSceneFieldInfo.HbFqSceneInfo();
hbFqSceneInfo.setHbFqNum("3");
hbFqSceneInfo.setHbFqSellerPercent("0");
info.setSceneInfo(JsonUtils.toJSONString(hbFqSceneInfo));
info.setOrderSceneType("HB_FQ");
req.setOrderSceneField(info); //====================== 增加下面字段 ===============
req.setExtFiled1("扩展字段1");
//3. 发送请求
String response = LKLSDK.httpPost(req); //4. 响应
System.out.println(response);
} /**
增加实体内层嵌套实体字段
> 重写嵌套实体继承原实体
*
@see V3CcssOrderSceneFieldInfoExtend 继承
@see V3CcssOrderSceneFieldInfo
*/
private static void extendSecondStruct() throws SDKException {
V3CcssCounterOrderSpecialCreateRequest req = new V3CcssCounterOrderSpecialCreateRequest();
req.setOutOrderNo("8221210594300JY" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
req.setMerchantNo("8221210594300JY");
req.setTotalAmount(10L);
req.setOrderEfficientTime("20230824155923");
req.setNotifyUrl("http://run.mocky.io/v3/b02c9448-20a2-4ff6-a678-38ecab30161d");
req.setSupportRefund(1);
req.setSupportRepeatPay(1);
req.setCounterParam("{"pay_mode":"ALIPAY"}");
req.setSupportCancel(0);
req.setBusiTypeParam("[{"busi_type":"UPCARD","params":{"crd_flg":"CRDFLG_D|CRDFLG_C|CRDFLG_OTH"}},{"busi_type":"SCPAY","params":{"pay_mode":"WECHAT","crd_flg":"CRDFLG_D"}}]");
req.setOrderInfo("测试12313131");
req.setTermNo("T12331234");
List<String> sgnInfos = new ArrayList<>();
sgnInfos.add("1");
req.setSgnInfo(sgnInfos); //创建自定义实体继承 V3CcssOrderSceneFieldInfo
V3CcssOrderSceneFieldInfoExtend info = new V3CcssOrderSceneFieldInfoExtend();
V3CcssOrderSceneFieldInfo.HbFqSceneInfo hbFqSceneInfo = new V3CcssOrderSceneFieldInfo.HbFqSceneInfo();
hbFqSceneInfo.setHbFqNum("3");
hbFqSceneInfo.setHbFqSellerPercent("0");
info.setSceneInfo(JsonUtils.toJSONString(hbFqSceneInfo));
info.setOrderSceneType("HB_FQ"); //----- 增加内部结构字段
info.setSecondExtFiled1("内部扩展字段"); req.setOrderSceneField(info);
//3. 发送请求
String response = LKLSDK.httpPost(req); //4. 响应
System.out.println(response);
} /**
增加自定义实体(sdk未封装接口)
> v2接口继承
*
@see com.lkl.laop.sdk.request.V2CommRequest
> v3接口继承
@see com.lkl.laop.sdk.request.V3CommRequest
/
private static void extendAllStruct() throws SDKException {
//创建 V3ExtendRequest 继承 V3CommRequest
V3ExtendRequest req = new V3ExtendRequest();
req.setOutOrderNo("8221210594300JY" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
req.setMerchantNo("8221210594300JY");
req.setTotalAmount(10L);
req.setOrderEfficientTime("20230824155923");
req.setNotifyUrl("http://run.mocky.io/v3/b02c9448-20a2-4ff6-a678-38ecab30161d");
req.setSupportRefund(1);
req.setSupportRepeatPay(1);
req.setCounterParam("{"pay_mode":"ALIPAY"}");
req.setSupportCancel(0);
req.setBusiTypeParam("[{"busi_type":"UPCARD","params":{"crd_flg":"CRDFLG_D|CRDFLG_C|CRDFLG_OTH"}},{"busi_type":"SCPAY","params":{"pay_mode":"WECHAT","crd_flg":"CRDFLG_D"}}]");
req.setOrderInfo("测试12313131");
req.setTermNo("T12331234");
List<String> sgnInfos = new ArrayList<>();
sgnInfos.add("1");
req.setSgnInfo(sgnInfos); V3CcssOrderSceneFieldInfo info = new V3CcssOrderSceneFieldInfo();
V3CcssOrderSceneFieldInfo.HbFqSceneInfo hbFqSceneInfo = new V3CcssOrderSceneFieldInfo.HbFqSceneInfo();
hbFqSceneInfo.setHbFqNum("3");
hbFqSceneInfo.setHbFqSellerPercent("0");
info.setSceneInfo(JsonUtils.toJSONString(hbFqSceneInfo));
info.setOrderSceneType("HB_FQ");
req.setOrderSceneField(info);
//========================== 发送请求使用此方法 ==========================
//参数需要加密时 使用 LKLSDK.sm4Encrypt(req.toBody(); 自行加密
String response = LKLSDK.httpPost("https://test.wsmsd.cn/sit/api/v3/ccss/counter/order/create",req.toBody());
//解密时 使用 LKLSDK.sm4Decrypt(response); 自行解密
//响应
System.out.println(response);
}
} 

