歡迎使用拉卡拉開放平臺Java SDK

lakala 4個月前 ( 11-09 ) 354

歡迎使用 拉卡拉開放平臺SDK for Java 。

拉卡拉開放平臺SDK for Java讓您不用復雜編程即可訪拉卡拉開放平臺開放的各項能力,SDK可以自動幫您滿足能力調用過程中所需的證書校驗、加簽、驗簽、發送HTTP請求等非功能性要求。

image.png

資源下載

開發語言資源下載
JAVAJava 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("{&quot;pay_mode&quot;:&quot;ALIPAY&quot;}");
        req.setSupportCancel(0);
        req.setBusiTypeParam("[{&quot;busi_type&quot;:&quot;UPCARD&quot;,&quot;params&quot;:{&quot;crd_flg&quot;:&quot;CRDFLG_D|CRDFLG_C|CRDFLG_OTH&quot;}},{&quot;busi_type&quot;:&quot;SCPAY&quot;,&quot;params&quot;:{&quot;pay_mode&quot;:&quot;WECHAT&quot;,&quot;crd_flg&quot;:&quot;CRDFLG_D&quot;}}]");
        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("{&quot;pay_mode&quot;:&quot;ALIPAY&quot;}");
        req.setSupportCancel(0);
        req.setBusiTypeParam("[{&quot;busi_type&quot;:&quot;UPCARD&quot;,&quot;params&quot;:{&quot;crd_flg&quot;:&quot;CRDFLG_D|CRDFLG_C|CRDFLG_OTH&quot;}},{&quot;busi_type&quot;:&quot;SCPAY&quot;,&quot;params&quot;:{&quot;pay_mode&quot;:&quot;WECHAT&quot;,&quot;crd_flg&quot;:&quot;CRDFLG_D&quot;}}]");
        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("{&quot;pay_mode&quot;:&quot;ALIPAY&quot;}");
        req.setSupportCancel(0);
        req.setBusiTypeParam("[{&quot;busi_type&quot;:&quot;UPCARD&quot;,&quot;params&quot;:{&quot;crd_flg&quot;:&quot;CRDFLG_D|CRDFLG_C|CRDFLG_OTH&quot;}},{&quot;busi_type&quot;:&quot;SCPAY&quot;,&quot;params&quot;:{&quot;pay_mode&quot;:&quot;WECHAT&quot;,&quot;crd_flg&quot;:&quot;CRDFLG_D&quot;}}]");
        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);
    }
}

image.png

The End