歡迎使用拉卡拉開放平臺(tái)Java SDK
歡迎使用 拉卡拉開放平臺(tái)SDK for Java 。
拉卡拉開放平臺(tái)SDK for Java讓您不用復(fù)雜編程即可訪拉卡拉開放平臺(tái)開放的各項(xiàng)能力,SDK可以自動(dòng)幫您滿足能力調(diào)用過程中所需的證書校驗(yàn)、加簽、驗(yàn)簽、發(fā)送HTTP請(qǐng)求等非功能性要求。
資源下載
| 開發(fā)語言 | 資源下載 |
| JAVA | Java SDK |
環(huán)境要求
1.需要使用JDK 1.8或其以上版本;
2.SDK接入準(zhǔn)備:
●根據(jù)拉卡拉開放平臺(tái)接入指引,生成密鑰參見拉卡拉開放平臺(tái)-安全統(tǒng)一接入規(guī)范
●接入方生成密鑰對(duì)后,需要將公鑰證書提供給拉卡拉,同時(shí)獲取拉卡拉的公鑰證書并保存
●如接口需密文傳輸,需要先向拉卡拉進(jìn)行SM4秘鑰申請(qǐng)
●拉卡拉為接入方分配appId
●申請(qǐng)對(duì)應(yīng)接口訪問權(quán)限
3.準(zhǔn)備工作完成后,注意保存如下信息,后續(xù)將作為使用SDK的輸入。商戶的私鑰、商戶的公鑰、拉卡拉公鑰證書。
安裝依賴
方法一:
將拉卡拉sdk打包deploy到自己私服倉庫,通過maven管理項(xiàng)目
推薦通過Maven來管理項(xiàng)目依賴,您只需在項(xiàng)目的pom.xml文件中聲明如下依賴
<dependency> <groupId>com.lkl.laop.sdk</groupId> <artifactId>lkl-laop-java-sdk</artifactId> <version>1.0.x</version> </dependency>
方法二:
項(xiàng)目直接引入拉卡拉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.安裝好依賴庫保證運(yùn)行環(huán)境沒問題,可直接運(yùn)行SDK demo,如調(diào)用接口正常返回說明運(yùn)行環(huán)境配置成功;
2.更換接入配置(appId、序列化、私鑰、拉卡拉證書),看接口請(qǐng)求是否成功。如證書驗(yàn)證或加簽驗(yàn)簽失敗,請(qǐng)檢查相關(guān)配置;
3.拉卡拉開放平臺(tái)測(cè)試環(huán)境服務(wù)地址:https://test.wsmsd.cn/sit。生產(chǎn)環(huán)境服務(wù)地址:https://s2.lakala.com。
4.DEMO中提供兩種初始化接入配置參數(shù)的方式,可根據(jù)情況自行選擇。
以下這段代碼示例向您展示了使用拉卡拉SDK for Java調(diào)用一個(gè)API的4個(gè)主要步驟:
1.初始SDK接入?yún)?shù)。系統(tǒng)初始化時(shí)只需做一次;
2.創(chuàng)建API請(qǐng)求對(duì)象并設(shè)置請(qǐng)求參數(shù);
3.通過LKLSDK.httpPost()發(fā)起請(qǐng)求;
4.處理響應(yīng)或異常。
private static final String appId="拉卡拉開放平臺(tái)進(jìn)行配置開通"; private static final String serialNo="商戶證書序列號(hào),和商戶私鑰對(duì)應(yīng)"; private static final String priKeyPath="商戶私鑰地址,用于請(qǐng)求簽名"; private static final String lklCerPath=" 拉卡拉公鑰證書地址,用于驗(yàn)簽"; private static final String lklNotifyCerPath=" 拉卡拉支付平臺(tái)證書地址2(用于拉卡拉通知驗(yàn)簽,當(dāng)前同lklCerPath)";
private static final String serverUrl="拉卡拉開放平臺(tái)服務(wù)地址"; private static final String sm4Key = "如果需要密文傳輸請(qǐng)申請(qǐng)拉卡拉SM4密鑰"; private static final String priKeyStr="商戶私鑰字符串,用于請(qǐng)求簽名"; private static final String lklCerStr=" 拉卡拉公鑰證書字符串,用于驗(yàn)簽"; private static final String lklNotifyCerStr=" 拉卡拉支付平臺(tái)證書字符串2(用于拉卡拉通知驗(yàn)簽,當(dāng)前同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); //根據(jù)請(qǐng)求接口拼裝參數(shù)
V3LabsTradeQueryRequest v3LabsQueryTradequeryRequest=new V3LabsTradeQueryRequest();
v3LabsQueryTradequeryRequest.setMerchantNo("xxxx");
v3LabsQueryTradequeryRequest.setTermNo("xxx");
v3LabsQueryTradequeryRequest.setOutTradeNo("xxxx"); //發(fā)起請(qǐng)求-正常請(qǐng)求
String response=LKLSDK.httpPost(v3LabsQueryTradequeryRequest); //發(fā)起請(qǐng)求2(密文傳輸接口)-請(qǐng)求報(bào)文加密,響應(yīng)信息無需解密
String response2=LKLSDK.httpPost(v3LabsQueryTradequeryRequest,true,false); //發(fā)起請(qǐng)求3(密文傳輸接口)-請(qǐng)求報(bào)文加密,響應(yīng)信息需解密
String response3=LKLSDK.httpPost(v3LabsQueryTradequeryRequest,true,true); //發(fā)起請(qǐng)求4-自定義接口參數(shù)實(shí)體,直接發(fā)送接口地址
String response3=LKLSDK.httpPost("url","bodyJson");
//處理響應(yīng)
log.info(response);●以下代碼向您展示了使用拉卡拉SDK for Java接收回調(diào)通知的示例
//拉卡拉開放平臺(tái)采用數(shù)據(jù)流傳輸
public ResponseEntity<?> messageHandle(HttpServletRequest request) throws Exception {
// 1. 配置初始化-全局只需要初始化一次
doInit(); //驗(yàn)簽并解析請(qǐng)求
String body = LKLSDK.notificationHandle(request);
System.out.println("驗(yàn)簽成功,請(qǐng)求body:" + body);
//spring-boot 3.x 使用jakarta.servlet.http.HttpServletRequest接收,讀取內(nèi)容,LKLSDK提供驗(yàn)簽方法
LKLSDK.notificationHandle(getBody(request), getAuthorization(request)); //業(yè)務(wù)處理
return ResponseEntity.ok(body);
}/**
讀取請(qǐng)求頭
/
private String getAuthorization(HttpServletRequest request) {
return request.getHeader("Authorization");
}/**
讀取請(qǐng)求體
/
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失敗");
} }復(fù)制多APPID運(yùn)行
●如果你的應(yīng)用需要同時(shí)注冊(cè)多套APPID,請(qǐng)參考如下步驟
//1. 初始化全局配置 //注冊(cè)第一套 LKLSDK.init("第一套參數(shù)"); //注冊(cè)第二套 LKLSDK.init("第二套參數(shù)"); ... //2. 發(fā)起調(diào)用 //使用sdk封裝實(shí)體調(diào)用(如果不指定,則使用第一個(gè)初始化的appid) ... request.setLklAppId("指定發(fā)起的appid"); LKLSDK.httpPost(request); //調(diào)用sdk未封裝接口(如果不指定,則使用第一個(gè)初始化的appid) ... LKLSDK.httpPost("https://test.wsmsd.cn/sit/xxx", body,appId); //3. 回調(diào)(如果不指定,則使用第一個(gè)初始化的appid) String body = LKLSDK.notificationHandle(httpServletRequest,appid);其他
如果出現(xiàn)SDK版本無法自適應(yīng)接口新字段,以下兩種方案提供選擇。
1、聯(lián)系拉卡拉SDK管理人員,請(qǐng)求新的SDK版本。
2、可自行創(chuàng)建實(shí)體類并繼承V2CommRequest/V3CommRequest(和原封裝的接口實(shí)體保持一致即可),在自定義的實(shí)體類中增加新的參數(shù)。使用LKLSDK.httpPost()發(fā)起請(qǐng)求調(diào)用。
public class V3CcssCounterOrderSpecialCreateRequestExtendDemo extends BaseCommonDemo {
public static void main(String[] args) throws Exception {
// 1. 配置初始化
doInit();
//增加實(shí)體一級(jí)參數(shù)demo
extendFirstStruct();
//增加實(shí)體二級(jí)參數(shù)demo
extendSecondStruct();
//增加調(diào)用sdk未封裝接口demo
extendAllStruct();
} /**
增加實(shí)體最外層字段
> 重寫實(shí)體繼承原實(shí)體
*
@see V3CcssCounterOrderSpecialCreateRequestExtend 繼承
@see V3CcssCounterOrderSpecialCreateRequest
*/
private static void extendFirstStruct() throws SDKException {
// 創(chuàng)建自定義實(shí)體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("測(cè)試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("擴(kuò)展字段1");
//3. 發(fā)送請(qǐng)求
String response = LKLSDK.httpPost(req); //4. 響應(yīng)
System.out.println(response);
} /**
增加實(shí)體內(nèi)層嵌套實(shí)體字段
> 重寫嵌套實(shí)體繼承原實(shí)體
*
@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("測(cè)試12313131");
req.setTermNo("T12331234");
List<String> sgnInfos = new ArrayList<>();
sgnInfos.add("1");
req.setSgnInfo(sgnInfos); //創(chuàng)建自定義實(shí)體繼承 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"); //----- 增加內(nèi)部結(jié)構(gòu)字段
info.setSecondExtFiled1("內(nèi)部擴(kuò)展字段"); req.setOrderSceneField(info);
//3. 發(fā)送請(qǐng)求
String response = LKLSDK.httpPost(req); //4. 響應(yīng)
System.out.println(response);
} /**
增加自定義實(shí)體(sdk未封裝接口)
> v2接口繼承
*
@see com.lkl.laop.sdk.request.V2CommRequest
> v3接口繼承
@see com.lkl.laop.sdk.request.V3CommRequest
/
private static void extendAllStruct() throws SDKException {
//創(chuàng)建 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("測(cè)試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);
//========================== 發(fā)送請(qǐng)求使用此方法 ==========================
//參數(shù)需要加密時(shí) 使用 LKLSDK.sm4Encrypt(req.toBody(); 自行加密
String response = LKLSDK.httpPost("https://test.wsmsd.cn/sit/api/v3/ccss/counter/order/create",req.toBody());
//解密時(shí) 使用 LKLSDK.sm4Decrypt(response); 自行解密
//響應(yīng)
System.out.println(response);
}
} 

