This commit is contained in:
2025-08-30 15:02:10 +08:00
commit b26620cdf0
42 changed files with 4478 additions and 0 deletions

41
.gitignore vendored Normal file
View File

@@ -0,0 +1,41 @@
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
#*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.vscode
.idea
*.iml
.DS_Store
.env
target
build
dist
node_modules

102
pom.xml Normal file
View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lakala.moss</groupId>
<artifactId>moss-sdk</artifactId>
<version>1.0.0</version>
<name>moss-sdk</name>
<description>moss-sdk</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.64</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.7</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,52 @@
package com.lakala.moss.api;
/**
* @author Stephen yu
* @description: 请求消息-消息公共参数
* @date 2025-02-21
*/
public class ApiReq<T> {
// 请求消息头
private ApiReqHead head;
// 请求消息体
private T request;
// 请求消息体密文
private String requestEncrypted;
// 请求签名
private String sign;
public ApiReqHead getHead() {
return head;
}
public void setHead(ApiReqHead head) {
this.head = head;
}
public T getRequest() {
return request;
}
public void setRequest(T request) {
this.request = request;
}
public String getRequestEncrypted() {
return requestEncrypted;
}
public void setRequestEncrypted(String requestEncrypted) {
this.requestEncrypted = requestEncrypted;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
}

View File

@@ -0,0 +1,98 @@
package com.lakala.moss.api;
/**
* @author Stephen yu
* @description: 请求消息-消息头
* @date 2025-02-21
*/
public class ApiReqHead {
// 版本号值为1.0
private String versionId;
// 交易服务码
private String serviceId;
// 技术渠道号值为API
private String channelId;
// 请求时间格式yyyyMMddHHmmss
private String requestTime;
// 交易流水号请求方生成建议使用32位UUID
private String serviceSn;
// 业务渠道号即为MOSS为客户生成的唯一客户编号同为开发应用Appid在工作台-开发者中心获取)
private String businessChannel;
private String sid;
private String org;
private String accessToken;
public String getVersionId() {
return versionId;
}
public void setVersionId(String versionId) {
this.versionId = versionId;
}
public String getServiceId() {
return serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getRequestTime() {
return requestTime;
}
public void setRequestTime(String requestTime) {
this.requestTime = requestTime;
}
public String getServiceSn() {
return serviceSn;
}
public void setServiceSn(String serviceSn) {
this.serviceSn = serviceSn;
}
public String getBusinessChannel() {
return businessChannel;
}
public void setBusinessChannel(String businessChannel) {
this.businessChannel = businessChannel;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getOrg() {
return org;
}
public void setOrg(String org) {
this.org = org;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}

View File

@@ -0,0 +1,50 @@
package com.lakala.moss.api;
/**
* @author Stephen yu
* @description: 消息消息-消息公共参数
* @date @date 2025-02-21
*/
public class ApiRes<T> {
// 响应消息头
private ApiResHead head;
// 响应消息体
private T response;
// 响应消息体密文
private String responseEncrypted;
// 响应签名
private String sign;
public ApiResHead getHead() {
return head;
}
public void setHead(ApiResHead head) {
this.head = head;
}
public T getResponse() {
return response;
}
public void setResponse(T response) {
this.response = response;
}
public String getResponseEncrypted() {
return responseEncrypted;
}
public void setResponseEncrypted(String responseEncrypted) {
this.responseEncrypted = responseEncrypted;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
}

View File

@@ -0,0 +1,33 @@
package com.lakala.moss.api;
/**
* @author Stephen yu
* @description: 接口结果码定义
* @date 2025-02-21
*/
public enum ApiResCode {
SUCCESS("000000", "交易成功"),
PA_INSIDE_ERROR("MOSS0001", "交易处理失败"),
PA_TIMEOUT_ERROR("MOSS0002", "交易通讯异常"),
PA_UNKNOWN_ERROR("MOSS0003", "交易处理异常"),
PA_PARAM_ERROR("MOSS0004", "参数校验错误"),
PA_REPEAT_ERROR("MOSS0005", "订单重复"),
PA_NOEXIST_ERROR("MOSS0006", "订单不存在")
;
private String code;
private String desc;
ApiResCode(final String code, final String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return this.code;
}
public String getDesc() {
return this.desc;
}
}

View File

@@ -0,0 +1,70 @@
package com.lakala.moss.api;
/**
* @author Stephen yu
* @description: 响应消息-消息头
* @date 2025-02-21
*/
public class ApiResHead {
// 响应码8位字符000000为成功其他为失败
private String code;
// 响应码描述
private String desc;
// 响应时间
private String serviceTime;
// 响应流水号,原值返回
private String serviceSn;
// 交易服务码
private String serviceId;
// 全局流水
private String sid;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getServiceTime() {
return serviceTime;
}
public void setServiceTime(String serviceTime) {
this.serviceTime = serviceTime;
}
public String getServiceSn() {
return serviceSn;
}
public void setServiceSn(String serviceSn) {
this.serviceSn = serviceSn;
}
public String getServiceId() {
return serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
}

View File

@@ -0,0 +1,175 @@
package com.lakala.moss.api.params;
import javax.xml.soap.Detail;
/**
* 请求参数-账户端业务信息域
*
* @author Stephen yu
* @date 2025-02-21
*/
public class AccBusiFields {
// 业务扩展参数
private ExtendParams extend_params;
// 商品详情
private GoodsDetail goods_detail;
// 商户门店编号
private String store_id;
// 支付宝禁用支付渠道 credit_group 表示禁用信用支付类(包含信用卡,花呗,花呗分期) pcredit 表示禁用花呗”
// pcreditpayInstallment 表示禁用花呗分期 creditCard 表示禁用信用卡 如果想禁用多个可在枚举间加,隔开
private String disable_pay_channels;
// 商户传入业务信息,应用于安全,营销等参数直传场景,格式为 json 格式。
// 示例:{“enable_thirdparty_subsidy”:”N”,”source”:”xxxx”},source送值与吱口令生成接口中上送的source对应
// 值内容为“inderict_wx_吱口令申领接口中source值”
private String business_params;
// 微信分配的子商户公众账号ID即微信小程序支付-71、公众号支付-51、此参数必传
private String sub_appid;
// 商品详情
private Detail detail;
// 附加域,该字段主要用于商户携带订单的自定义数据。商户定制字段,直接送到账户端。
private String attach;
// 终端设备号(门店号或收银设备ID)注意PC网页或JSAPI支付请传”WEB”
private String device_info;
// 指定支付方式,no_credit指定不能使用信用卡支付
private String limit_pay;
// 场景信息
private String scene_info;
// 银联单品营销订单信息
private AcqAddnDataOrderInfo acq_addn_data_order_info;
// 银联单品营销商品信息
private AcqAddnDataGoodsInfo acq_addn_data_goods_info;
// 银联前台通知地址
private String front_url;
// 银联失败交易前台通知地址
private String front_fail_url;
// 用户信息的临时授权码
private String user_auth_code;
public ExtendParams getExtend_params() {
return extend_params;
}
public void setExtend_params(ExtendParams extend_params) {
this.extend_params = extend_params;
}
public GoodsDetail getGoods_detail() {
return goods_detail;
}
public void setGoods_detail(GoodsDetail goods_detail) {
this.goods_detail = goods_detail;
}
public String getStore_id() {
return store_id;
}
public void setStore_id(String store_id) {
this.store_id = store_id;
}
public String getDisable_pay_channels() {
return disable_pay_channels;
}
public void setDisable_pay_channels(String disable_pay_channels) {
this.disable_pay_channels = disable_pay_channels;
}
public String getBusiness_params() {
return business_params;
}
public void setBusiness_params(String business_params) {
this.business_params = business_params;
}
public String getSub_appid() {
return sub_appid;
}
public void setSub_appid(String sub_appid) {
this.sub_appid = sub_appid;
}
public Detail getDetail() {
return detail;
}
public void setDetail(Detail detail) {
this.detail = detail;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getDevice_info() {
return device_info;
}
public void setDevice_info(String device_info) {
this.device_info = device_info;
}
public String getLimit_pay() {
return limit_pay;
}
public void setLimit_pay(String limit_pay) {
this.limit_pay = limit_pay;
}
public String getScene_info() {
return scene_info;
}
public void setScene_info(String scene_info) {
this.scene_info = scene_info;
}
public AcqAddnDataOrderInfo getAcq_addn_data_order_info() {
return acq_addn_data_order_info;
}
public void setAcq_addn_data_order_info(AcqAddnDataOrderInfo acq_addn_data_order_info) {
this.acq_addn_data_order_info = acq_addn_data_order_info;
}
public AcqAddnDataGoodsInfo getAcq_addn_data_goods_info() {
return acq_addn_data_goods_info;
}
public void setAcq_addn_data_goods_info(AcqAddnDataGoodsInfo acq_addn_data_goods_info) {
this.acq_addn_data_goods_info = acq_addn_data_goods_info;
}
public String getFront_url() {
return front_url;
}
public void setFront_url(String front_url) {
this.front_url = front_url;
}
public String getFront_fail_url() {
return front_fail_url;
}
public void setFront_fail_url(String front_fail_url) {
this.front_fail_url = front_fail_url;
}
public String getUser_auth_code() {
return user_auth_code;
}
public void setUser_auth_code(String user_auth_code) {
this.user_auth_code = user_auth_code;
}
}

View File

@@ -0,0 +1,165 @@
package com.lakala.moss.api.params;
import com.google.gson.annotations.SerializedName;
/**
* 请求参数-账户端返回信息域
*
* @author Stephen yu
* @date 2024-12-17
*/
public class AccRespFields {
// 商户可用此参数自定义去生成二维码后展示出来进行扫码支付;支付宝(41-NATIVE)场景下返回
private String code;
// 商户收款二维码图片。Base64编码暂无支付宝(41-NATIVE)场景下返回
private String code_image;
// 支付签名信息;微信(71-小程序)微信(51-JSAPI)场景下返回
private String pay_sign;
// 小程序id微信(71-小程序)微信(51-JSAPI)场景下返回
private String app_id;
// 时间戳;微信(71-小程序)微信(51-JSAPI)场景下返回
private String time_stamp;
// 随机字符串;微信(71-小程序)微信(51-JSAPI)场景下返回
private String nonce_str;
// 订单详情扩展字符串;微信(71-小程序)微信(51-JSAPI)场景下返回
@SerializedName("package")
private String spackage;
// 签名方式;微信(71-小程序)微信(51-JSAPI)场景下返回
private String sign_type;
// 银联JS支付返回重定向地址银联二维码(51-JSAPI)场景下返回
private String redirect_url;
// 订单查询特有
// [支付宝]商户门店编号
private String store_id;
// [支付宝]交易支付使用的资金渠道
private String fund_bill_list;
// [微信]活动 ID,在账户端商户后台配置的批次 ID
private String acc_activity_id;
// [微信]优惠功能信息
private String promotion_detail;
// [云闪付]银联单品营销 附加数据,参与单品营销优惠时返回
private String up_iss_addn_data;
// [云闪付]银联优惠信息/出资方信息,参与单品营销优惠时返回
private String up_coupon_info;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCode_image() {
return code_image;
}
public void setCode_image(String code_image) {
this.code_image = code_image;
}
public String getPay_sign() {
return pay_sign;
}
public void setPay_sign(String pay_sign) {
this.pay_sign = pay_sign;
}
public String getApp_id() {
return app_id;
}
public void setApp_id(String app_id) {
this.app_id = app_id;
}
public String getTime_stamp() {
return time_stamp;
}
public void setTime_stamp(String time_stamp) {
this.time_stamp = time_stamp;
}
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getSpackage() {
return spackage;
}
public void setSpackage(String spackage) {
this.spackage = spackage;
}
public String getSign_type() {
return sign_type;
}
public void setSign_type(String sign_type) {
this.sign_type = sign_type;
}
public String getRedirect_url() {
return redirect_url;
}
public void setRedirect_url(String redirect_url) {
this.redirect_url = redirect_url;
}
public String getStore_id() {
return store_id;
}
public void setStore_id(String store_id) {
this.store_id = store_id;
}
public String getFund_bill_list() {
return fund_bill_list;
}
public void setFund_bill_list(String fund_bill_list) {
this.fund_bill_list = fund_bill_list;
}
public String getAcc_activity_id() {
return acc_activity_id;
}
public void setAcc_activity_id(String acc_activity_id) {
this.acc_activity_id = acc_activity_id;
}
public String getPromotion_detail() {
return promotion_detail;
}
public void setPromotion_detail(String promotion_detail) {
this.promotion_detail = promotion_detail;
}
public String getUp_iss_addn_data() {
return up_iss_addn_data;
}
public void setUp_iss_addn_data(String up_iss_addn_data) {
this.up_iss_addn_data = up_iss_addn_data;
}
public String getUp_coupon_info() {
return up_coupon_info;
}
public void setUp_coupon_info(String up_coupon_info) {
this.up_coupon_info = up_coupon_info;
}
}

View File

@@ -0,0 +1,69 @@
package com.lakala.moss.api.params;
/**
* 请求参数-银联单品营销商品信息
*
* @author Stephen yu
* @date 2025-02-21
*/
public class AcqAddnDataGoodsInfo {
// 商品编号
private String id;
// 商品名称
private String name;
// 商品单价 单位元
private String price;
// 商品数量
private String quantity;
// 商品类目
private String category;
// 附加信息
private String addninfo;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getAddninfo() {
return addninfo;
}
public void setAddninfo(String addninfo) {
this.addninfo = addninfo;
}
}

View File

@@ -0,0 +1,29 @@
package com.lakala.moss.api.params;
/**
* 请求参数-银联单品营销订单信息
*
* @author Stephen yu
* @date 2025-02-21
*/
public class AcqAddnDataOrderInfo {
// 标题
private String title;
// 金额
private String dctAmount;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDctAmount() {
return dctAmount;
}
public void setDctAmount(String dctAmount) {
this.dctAmount = dctAmount;
}
}

View File

@@ -0,0 +1,29 @@
package com.lakala.moss.api.params;
/**
* 请求参数-支付宝业务扩展参数
*
* @author Stephen yu
* @date 2025-02-21
*/
public class ExtendParams {
// 系统商编号,该参数作为系统商返佣数据提取的依据,请填写系统商签约协议的 PID
private String sys_service_provider_id;
// 点餐场景类型qr_order店内扫码点餐pre_order预点到店自提home_delivery 外送到家direct_payment直接付款other其它
private String food_order_type;
public String getSys_service_provider_id() {
return sys_service_provider_id;
}
public void setSys_service_provider_id(String sys_service_provider_id) {
this.sys_service_provider_id = sys_service_provider_id;
}
public String getFood_order_type() {
return food_order_type;
}
public void setFood_order_type(String food_order_type) {
this.food_order_type = food_order_type;
}
}

View File

@@ -0,0 +1,109 @@
package com.lakala.moss.api.params;
/**
* 请求参数-商品详情
*
* @author Stephen yu
* @date 2025-02-21
*/
public class GoodsDetail {
// 商品的编号
private String goods_id;
// 支付宝定义的统一商品编号
private String alipay_goods_id;
// 商品名称
private String goods_name;
// 商品数量
private String quantity;
// 商品价格 单位元
private String price;
// 商品类目
private String goods_category;
// 商品类目树,从商品类目根节点到叶子节点的类目 id 组成,类目 id 值使用|分割
private String categories_tree;
// 商品描述信息
private String body;
// 商品的展示地址
private String show_url;
// 微信支付定义的统一商品编号
private String wxpay_goods_id;
public String getGoods_id() {
return goods_id;
}
public void setGoods_id(String goods_id) {
this.goods_id = goods_id;
}
public String getAlipay_goods_id() {
return alipay_goods_id;
}
public void setAlipay_goods_id(String alipay_goods_id) {
this.alipay_goods_id = alipay_goods_id;
}
public String getGoods_name() {
return goods_name;
}
public void setGoods_name(String goods_name) {
this.goods_name = goods_name;
}
public String getQuantity() {
return quantity;
}
public void setQuantity(String quantity) {
this.quantity = quantity;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getGoods_category() {
return goods_category;
}
public void setGoods_category(String goods_category) {
this.goods_category = goods_category;
}
public String getCategories_tree() {
return categories_tree;
}
public void setCategories_tree(String categories_tree) {
this.categories_tree = categories_tree;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getShow_url() {
return show_url;
}
public void setShow_url(String show_url) {
this.show_url = show_url;
}
public String getWxpay_goods_id() {
return wxpay_goods_id;
}
public void setWxpay_goods_id(String wxpay_goods_id) {
this.wxpay_goods_id = wxpay_goods_id;
}
}

View File

@@ -0,0 +1,42 @@
package com.lakala.moss.api.params;
/**
* 请求参数-地址位置信息
*
* @author Stephen yu
* @date 2025-02-21
*/
public class LocationInfo {
// 请求方的IP地址存在必填格式如36.45.36.95
private String request_ip;
// 客户端设备的基站信息
private String base_station;
// 商户终端的地理位置,整体格式:纬度,经度,+表示北纬、东经,-表示南纬、 西经。
// 经度格式1位正负号+3位整数+1位小数点+5位小数 纬度格式1位正负号+2位整数+1位小数点+6位小数
// 举例:+31.221345,+121.12345
private String location;
public String getRequest_ip() {
return request_ip;
}
public void setRequest_ip(String request_ip) {
this.request_ip = request_ip;
}
public String getBase_station() {
return base_station;
}
public void setBase_station(String base_station) {
this.base_station = base_station;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}

View File

@@ -0,0 +1,210 @@
package com.lakala.moss.api.params;
/**
* 请求参数-支付信息
*
* @author Stephen yu
* @date 2025-02-21
*/
public class PayInfo {
// 支付流水号仅交易类型为PAY-支付时存在。
private String pay_serial;
// 对账单流水号,根据交易类型不同,或为支付对账单流水号 或为退款对账单流水号
private String log_no;
// 账户端交易订单号,根据交易类型不同,或为支付账户端交易订单号 或为退款账户端交易订单号
private String acc_trade_no;
// 支付交易完成时间或退款交易完成时间。格式yyyyMMddHHmmss
private String trade_time;
// 原支付流水号trade_main_type=REFUND时存在该字段
private String origin_pay_serial;
// 申请退款订单金额单位分trade_main_type=REFUND时存在该字段
private String refund_amount;
// 钱包类型微信WECHAT 支付宝ALIPAY 银联云闪付UQRCODEPAY
private String account_type;
// 交易状态
//INIT-初始化
//CREATE-待支付
//SUCCESS-交易成功
//FAIL-交易失败
//DEAL-交易处理中
//CLOSE-订单关闭
//PART_REFUND-部分退款
//REFUND-全部退款
//EXPIRE-已过期
//UNKNOWN-未知状态
private String trade_state;
// 付款银行
private String bank_type;
// 银行卡类型,00借记 01贷记 02微信零钱 03支付宝花呗 04支付宝其他 05数字货币 06拉卡拉支付账户 99未知
private String card_type;
// 付款人实付金额,单位分
private String payer_amount;
// 账户端应结订单金额,单位分
private String acc_settle_amount;
// 商户优惠金额,单位分
private String acc_mdiscount_amount;
// 账户端优惠金额,单位分
private String acc_discount_amount;
// 账户端其它优惠金额,单位分
private String acc_other_discount_amount;
// 备注信息
private String remark;
// 用户标识1,微信sub_open_id 支付宝buyer_logon_id买家支付宝账号
private String user_id1;
// 用户标识2,微信openId支付宝buyer_user_id 银联user_id
private String user_id2;
// 账户端子商户号
private String sub_mch_id;
public String getPay_serial() {
return pay_serial;
}
public void setPay_serial(String pay_serial) {
this.pay_serial = pay_serial;
}
public String getLog_no() {
return log_no;
}
public void setLog_no(String log_no) {
this.log_no = log_no;
}
public String getAcc_trade_no() {
return acc_trade_no;
}
public void setAcc_trade_no(String acc_trade_no) {
this.acc_trade_no = acc_trade_no;
}
public String getTrade_time() {
return trade_time;
}
public void setTrade_time(String trade_time) {
this.trade_time = trade_time;
}
public String getOrigin_pay_serial() {
return origin_pay_serial;
}
public void setOrigin_pay_serial(String origin_pay_serial) {
this.origin_pay_serial = origin_pay_serial;
}
public String getRefund_amount() {
return refund_amount;
}
public void setRefund_amount(String refund_amount) {
this.refund_amount = refund_amount;
}
public String getAccount_type() {
return account_type;
}
public void setAccount_type(String account_type) {
this.account_type = account_type;
}
public String getTrade_state() {
return trade_state;
}
public void setTrade_state(String trade_state) {
this.trade_state = trade_state;
}
public String getBank_type() {
return bank_type;
}
public void setBank_type(String bank_type) {
this.bank_type = bank_type;
}
public String getCard_type() {
return card_type;
}
public void setCard_type(String card_type) {
this.card_type = card_type;
}
public String getPayer_amount() {
return payer_amount;
}
public void setPayer_amount(String payer_amount) {
this.payer_amount = payer_amount;
}
public String getAcc_settle_amount() {
return acc_settle_amount;
}
public void setAcc_settle_amount(String acc_settle_amount) {
this.acc_settle_amount = acc_settle_amount;
}
public String getAcc_mdiscount_amount() {
return acc_mdiscount_amount;
}
public void setAcc_mdiscount_amount(String acc_mdiscount_amount) {
this.acc_mdiscount_amount = acc_mdiscount_amount;
}
public String getAcc_discount_amount() {
return acc_discount_amount;
}
public void setAcc_discount_amount(String acc_discount_amount) {
this.acc_discount_amount = acc_discount_amount;
}
public String getAcc_other_discount_amount() {
return acc_other_discount_amount;
}
public void setAcc_other_discount_amount(String acc_other_discount_amount) {
this.acc_other_discount_amount = acc_other_discount_amount;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getUser_id1() {
return user_id1;
}
public void setUser_id1(String user_id1) {
this.user_id1 = user_id1;
}
public String getUser_id2() {
return user_id2;
}
public void setUser_id2(String user_id2) {
this.user_id2 = user_id2;
}
public String getSub_mch_id() {
return sub_mch_id;
}
public void setSub_mch_id(String sub_mch_id) {
this.sub_mch_id = sub_mch_id;
}
}

View File

@@ -0,0 +1,81 @@
package com.lakala.moss.api.params;
/**
* 请求参数-拆单信息
*
* @author Stephen yu
* @date 2025-04-11
*/
public class SplitInfo {
// 子单支付流水号
private String sub_pay_serial;
// 商户号
private String mer_no;
// 金额,单位分
private String amount;
// 子单对账单流水号
private String sub_log_no;
// 以下为合单退款特有字段
// 申请退款金额,单位分
private String refund_amount;
// 原子单支付流水号
private String origin_sub_pay_serial;
// 仅交易类型为PREFUND-退款时存在。表示子单退货状态 SUCCESS-交易成功
private String sub_trade_state;
public String getSub_pay_serial() {
return sub_pay_serial;
}
public void setSub_pay_serial(String sub_pay_serial) {
this.sub_pay_serial = sub_pay_serial;
}
public String getMer_no() {
return mer_no;
}
public void setMer_no(String mer_no) {
this.mer_no = mer_no;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String getSub_log_no() {
return sub_log_no;
}
public void setSub_log_no(String sub_log_no) {
this.sub_log_no = sub_log_no;
}
public String getRefund_amount() {
return refund_amount;
}
public void setRefund_amount(String refund_amount) {
this.refund_amount = refund_amount;
}
public String getOrigin_sub_pay_serial() {
return origin_sub_pay_serial;
}
public void setOrigin_sub_pay_serial(String origin_sub_pay_serial) {
this.origin_sub_pay_serial = origin_sub_pay_serial;
}
public String getSub_trade_state() {
return sub_trade_state;
}
public void setSub_trade_state(String sub_trade_state) {
this.sub_trade_state = sub_trade_state;
}
}

View File

@@ -0,0 +1,31 @@
package com.lakala.moss.api.request;
/**
* 请求参数-申请对账单
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderChkApplyReq {
// 账单日期格式yyyyMMdd仅支持三个月内的账单下载申请
private String tran_date;
// 申请订单号
private String apply_order_no;
public String getTran_date() {
return tran_date;
}
public void setTran_date(String tran_date) {
this.tran_date = tran_date;
}
public String getApply_order_no() {
return apply_order_no;
}
public void setApply_order_no(String apply_order_no) {
this.apply_order_no = apply_order_no;
}
}

View File

@@ -0,0 +1,34 @@
package com.lakala.moss.api.request;
import com.lakala.moss.api.params.LocationInfo;
/**
* 请求参数-关单交易
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderClsReq {
// 原商户支付订单号
private String origin_order_no;
// 地址位置信息,风控要求必送
private LocationInfo location_info;
public String getOrigin_order_no() {
return origin_order_no;
}
public void setOrigin_order_no(String origin_order_no) {
this.origin_order_no = origin_order_no;
}
public LocationInfo getLocation_info() {
return location_info;
}
public void setLocation_info(LocationInfo location_info) {
this.location_info = location_info;
}
}

View File

@@ -0,0 +1,304 @@
package com.lakala.moss.api.request;
/**
* 请求参数-订单通知
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderNoticeReq {
// 交易类型。PAY-支付REFUND-退款
private String trade_main_type;
// 商户订单号,根据交易类型不同,或为支付订单号 或为退款订单号
private String order_no;
// 商户号
private String mer_no;
// 订单金额,单位分
private String total_amount;
// 订单标题用于简单描述订单或商品主题。最多42个字符如不送默认显示商户简称
private String subject;
// 订单创建时间格式yyyyMMddHHmmss
private String order_create_time;
// 订单有效时间,分钟
private String order_eff_time;
// 订单层状态:
// SUCCESS-已支付
// PART_REFUND-部分退款 (当商户订单号下存在未全额退款成功的支付流水号时)
// REFUND-全部退款(当商户订单号下资金全部退完,为全部退款)
private String order_status;
// 支付流水号仅交易类型为PAY-支付时存在。
private String pay_serial;
// 对账单流水号,根据交易类型不同,或为支付对账单流水号 或为退款对账单流水号
private String log_no;
// 账户端交易订单号,根据交易类型不同,或为支付账户端交易订单号 或为退款账户端交易订单号
private String acc_trade_no;
// 支付交易完成时间或退款交易完成时间。格式yyyyMMddHHmmss
private String trade_time;
// 原商户支付订单号trade_main_type=REFUND时存在该字段
private String origin_order_no;
// 原支付流水号trade_main_type=REFUND时存在该字段
private String origin_pay_serial;
// 申请退款订单金额单位分trade_main_type=REFUND时存在该字段
private String refund_amount;
// 钱包类型微信WECHAT 支付宝ALIPAY 银联云闪付UQRCODEPAY
private String account_type;
// 接入方式41:NATIVEALIPAY云闪付支持51:JSAPI微信公众号支付支付宝服务窗支付银联JS支付71:微信小程序支付
private String trans_type;
// 交易状态SUCCESS-交易成功
private String trade_state;
// 付款银行
private String bank_type;
// 银行卡类型,00借记 01贷记 02微信零钱 03支付宝花呗 04支付宝其他 05数字货币 06拉卡拉支付账户 99未知
private String card_type;
// 付款人实付金额,单位分
private String payer_amount;
// 账户端应结订单金额,单位分
private String acc_settle_amount;
// 商户优惠金额,单位分
private String acc_mdiscount_amount;
// 账户端优惠金额,单位分
private String acc_discount_amount;
// 账户端其它优惠金额,单位分
private String acc_other_discount_amount;
// 备注信息
private String remark;
// 用户标识1,微信sub_open_id 支付宝buyer_logon_id买家支付宝账号
private String user_id1;
// 用户标识2,微信openId支付宝buyer_user_id 银联user_id
private String user_id2;
// 账户端子商户号
private String sub_mch_id;
public String getTrade_main_type() {
return trade_main_type;
}
public void setTrade_main_type(String trade_main_type) {
this.trade_main_type = trade_main_type;
}
public String getOrder_no() {
return order_no;
}
public void setOrder_no(String order_no) {
this.order_no = order_no;
}
public String getMer_no() {
return mer_no;
}
public void setMer_no(String mer_no) {
this.mer_no = mer_no;
}
public String getTotal_amount() {
return total_amount;
}
public void setTotal_amount(String total_amount) {
this.total_amount = total_amount;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getOrder_create_time() {
return order_create_time;
}
public void setOrder_create_time(String order_create_time) {
this.order_create_time = order_create_time;
}
public String getOrder_eff_time() {
return order_eff_time;
}
public void setOrder_eff_time(String order_eff_time) {
this.order_eff_time = order_eff_time;
}
public String getOrder_status() {
return order_status;
}
public void setOrder_status(String order_status) {
this.order_status = order_status;
}
public String getPay_serial() {
return pay_serial;
}
public void setPay_serial(String pay_serial) {
this.pay_serial = pay_serial;
}
public String getLog_no() {
return log_no;
}
public void setLog_no(String log_no) {
this.log_no = log_no;
}
public String getAcc_trade_no() {
return acc_trade_no;
}
public void setAcc_trade_no(String acc_trade_no) {
this.acc_trade_no = acc_trade_no;
}
public String getTrade_time() {
return trade_time;
}
public void setTrade_time(String trade_time) {
this.trade_time = trade_time;
}
public String getOrigin_order_no() {
return origin_order_no;
}
public void setOrigin_order_no(String origin_order_no) {
this.origin_order_no = origin_order_no;
}
public String getOrigin_pay_serial() {
return origin_pay_serial;
}
public void setOrigin_pay_serial(String origin_pay_serial) {
this.origin_pay_serial = origin_pay_serial;
}
public String getRefund_amount() {
return refund_amount;
}
public void setRefund_amount(String refund_amount) {
this.refund_amount = refund_amount;
}
public String getAccount_type() {
return account_type;
}
public void setAccount_type(String account_type) {
this.account_type = account_type;
}
public String getTrans_type() {
return trans_type;
}
public void setTrans_type(String trans_type) {
this.trans_type = trans_type;
}
public String getTrade_state() {
return trade_state;
}
public void setTrade_state(String trade_state) {
this.trade_state = trade_state;
}
public String getBank_type() {
return bank_type;
}
public void setBank_type(String bank_type) {
this.bank_type = bank_type;
}
public String getCard_type() {
return card_type;
}
public void setCard_type(String card_type) {
this.card_type = card_type;
}
public String getPayer_amount() {
return payer_amount;
}
public void setPayer_amount(String payer_amount) {
this.payer_amount = payer_amount;
}
public String getAcc_settle_amount() {
return acc_settle_amount;
}
public void setAcc_settle_amount(String acc_settle_amount) {
this.acc_settle_amount = acc_settle_amount;
}
public String getAcc_mdiscount_amount() {
return acc_mdiscount_amount;
}
public void setAcc_mdiscount_amount(String acc_mdiscount_amount) {
this.acc_mdiscount_amount = acc_mdiscount_amount;
}
public String getAcc_discount_amount() {
return acc_discount_amount;
}
public void setAcc_discount_amount(String acc_discount_amount) {
this.acc_discount_amount = acc_discount_amount;
}
public String getAcc_other_discount_amount() {
return acc_other_discount_amount;
}
public void setAcc_other_discount_amount(String acc_other_discount_amount) {
this.acc_other_discount_amount = acc_other_discount_amount;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getUser_id1() {
return user_id1;
}
public void setUser_id1(String user_id1) {
this.user_id1 = user_id1;
}
public String getUser_id2() {
return user_id2;
}
public void setUser_id2(String user_id2) {
this.user_id2 = user_id2;
}
public String getSub_mch_id() {
return sub_mch_id;
}
public void setSub_mch_id(String sub_mch_id) {
this.sub_mch_id = sub_mch_id;
}
}

View File

@@ -0,0 +1,162 @@
package com.lakala.moss.api.request;
import com.lakala.moss.api.params.AccBusiFields;
import com.lakala.moss.api.params.LocationInfo;
/**
* 请求参数-订单支付
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderPayReq {
// 商户订单号32位全局唯一建议规则businessChannel+日期时间+序列流水号
private String order_no;
// 订单总金额分为单位整数。示例1元应填写 100
private String total_amount;
// 商户号平台客户下所发展的商户通过MOSS平台新增商户产生M+8位数字
private String mer_no;
// 订单备注信息
private String remark;
// 后端支付结果通知url支付结果通知的平台后台回调地址通知url必须为外网可访问的url不能携带参数
private String notify_url;
// 支付场景 0-标准收银台 1-独立支付API
private String pay_scene;
// 钱包类型:
//pay_scene=0为非必传可多传表示为指定收银台内展示的支付方式当pay_scene=1模式时必传单个支付方式。
//ALIPAY支付宝
//WECHAT微信
//UQRCODEPAY银联云闪付
private String account_type;
// 订单标题用于简单描述订单或商品主题。最多42个字符如不送默认显示商户简称
private String subject;
// 订单有效期,格式yyyyMMddHHmmss,建议不超过15分钟。不传值则默认5分钟。
private String order_eff_time;
// 当客户微信公众号/支付宝生活号/云闪付H5支付场景时拉起MOSS-H5收银台支付成功后跳转至客户指定的URL页面地址
private String callback_url;
// 接入方式:
//41:NATIVEALIPAY云闪付支持
//51:JSAPI微信公众号支付支付宝服务窗支付银联JS支付
//71:微信小程序支付
private String trans_type;
// 地址位置信息,风控要求必送
private LocationInfo location_info;
// 用户在钱包侧唯一标识微信支付宝侧为openid云闪付为userid。trans_type为51情况下传入。
private String user_id;
// 账户端业务信息域不同类型的account_type对应不同的账户端需要填写以下不同的信息
private AccBusiFields acc_busi_fields;
public String getOrder_no() {
return order_no;
}
public void setOrder_no(String order_no) {
this.order_no = order_no;
}
public String getTotal_amount() {
return total_amount;
}
public void setTotal_amount(String total_amount) {
this.total_amount = total_amount;
}
public String getMer_no() {
return mer_no;
}
public void setMer_no(String mer_no) {
this.mer_no = mer_no;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getNotify_url() {
return notify_url;
}
public void setNotify_url(String notify_url) {
this.notify_url = notify_url;
}
public String getPay_scene() {
return pay_scene;
}
public void setPay_scene(String pay_scene) {
this.pay_scene = pay_scene;
}
public String getAccount_type() {
return account_type;
}
public void setAccount_type(String account_type) {
this.account_type = account_type;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getOrder_eff_time() {
return order_eff_time;
}
public void setOrder_eff_time(String order_eff_time) {
this.order_eff_time = order_eff_time;
}
public String getCallback_url() {
return callback_url;
}
public void setCallback_url(String callback_url) {
this.callback_url = callback_url;
}
public String getTrans_type() {
return trans_type;
}
public void setTrans_type(String trans_type) {
this.trans_type = trans_type;
}
public LocationInfo getLocation_info() {
return location_info;
}
public void setLocation_info(LocationInfo location_info) {
this.location_info = location_info;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public AccBusiFields getAcc_busi_fields() {
return acc_busi_fields;
}
public void setAcc_busi_fields(AccBusiFields acc_busi_fields) {
this.acc_busi_fields = acc_busi_fields;
}
}

View File

@@ -0,0 +1,32 @@
package com.lakala.moss.api.request;
/**
* 请求参数-订单查询列表
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderQryListReq {
// 商户订单号/退款订单号32位全局唯一建议规则businessChannel+日期时间+序列流水号
private String order_no;
// 支付流水号,上送则查账指定的支付流水号
private String pay_serial;
public String getOrder_no() {
return order_no;
}
public void setOrder_no(String order_no) {
this.order_no = order_no;
}
public String getPay_serial() {
return pay_serial;
}
public void setPay_serial(String pay_serial) {
this.pay_serial = pay_serial;
}
}

View File

@@ -0,0 +1,74 @@
package com.lakala.moss.api.request;
import com.lakala.moss.api.params.LocationInfo;
/**
* 请求参数-退款交易
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderRefundReq {
// 退款订单号
private String order_no;
// 原商户支付订单号
private String origin_order_no;
// 原支付流水号(可指定需要退款的支付流水号)
private String origin_pay_serial;
// 退款金额,以分为单位
private String refund_amount;
// 退款原因描述
private String refund_reason;
// 地址位置信息,风控要求必送
private LocationInfo location_info;
public String getOrder_no() {
return order_no;
}
public void setOrder_no(String order_no) {
this.order_no = order_no;
}
public String getOrigin_order_no() {
return origin_order_no;
}
public void setOrigin_order_no(String origin_order_no) {
this.origin_order_no = origin_order_no;
}
public String getOrigin_pay_serial() {
return origin_pay_serial;
}
public void setOrigin_pay_serial(String origin_pay_serial) {
this.origin_pay_serial = origin_pay_serial;
}
public String getRefund_amount() {
return refund_amount;
}
public void setRefund_amount(String refund_amount) {
this.refund_amount = refund_amount;
}
public String getRefund_reason() {
return refund_reason;
}
public void setRefund_reason(String refund_reason) {
this.refund_reason = refund_reason;
}
public LocationInfo getLocation_info() {
return location_info;
}
public void setLocation_info(LocationInfo location_info) {
this.location_info = location_info;
}
}

View File

@@ -0,0 +1,43 @@
package com.lakala.moss.api.request;
/**
* 请求参数-用户标识查询
*
* @author Stephen yu
* @date 2025-02-21
*/
public class UseridQryReq {
// 商户号平台客户下所发展的商户通过MOSS平台新增商户产生M+8位数字
private String mer_no;
// 付款方返回的临时授权码,一次有效。
//银联云闪付APP访问收单商户H5页面收款方返回302重定向地址。
//具体格式如下: “ https://qr.95516.com/qrcGtwWeb-web/api/userAuth?version=1.0.0&redirectUrl=收单商户接收处理结果的地址需进行URLEncode”成功后返回临时授权码
private String auth_code;
// 银联支付标识.收款方识别HTTP请求User Agent中包含银联支付标识格式为“UnionPay/<版本号> <App标识>”注意APP标识仅支持字母和数字,例UnionPay/1.0 ICBCeLife
private String app_up_identifier;
public String getMer_no() {
return mer_no;
}
public void setMer_no(String mer_no) {
this.mer_no = mer_no;
}
public String getAuth_code() {
return auth_code;
}
public void setAuth_code(String auth_code) {
this.auth_code = auth_code;
}
public String getApp_up_identifier() {
return app_up_identifier;
}
public void setApp_up_identifier(String app_up_identifier) {
this.app_up_identifier = app_up_identifier;
}
}

View File

@@ -0,0 +1,31 @@
package com.lakala.moss.api.response;
/**
* 响应参数-申请对账单
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderChkApplyRes {
// 文件下载地址供下一步请求账单文件的下载地址该地址5min内有效。
private String down_load_url;
// 申请订单号
private String apply_order_no;
public String getDown_load_url() {
return down_load_url;
}
public void setDown_load_url(String down_load_url) {
this.down_load_url = down_load_url;
}
public String getApply_order_no() {
return apply_order_no;
}
public void setApply_order_no(String apply_order_no) {
this.apply_order_no = apply_order_no;
}
}

View File

@@ -0,0 +1,32 @@
package com.lakala.moss.api.response;
/**
* 响应参数-关单交易
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderClsRes {
// 原商户支付订单号
private String origin_order_no;
// 交易时间格式yyyyMMddHHmmss
private String trade_time;
public String getOrigin_order_no() {
return origin_order_no;
}
public void setOrigin_order_no(String origin_order_no) {
this.origin_order_no = origin_order_no;
}
public String getTrade_time() {
return trade_time;
}
public void setTrade_time(String trade_time) {
this.trade_time = trade_time;
}
}

View File

@@ -0,0 +1,13 @@
package com.lakala.moss.api.response;
/**
* 响应参数-订单通知
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderNoticeRes {
}

View File

@@ -0,0 +1,103 @@
package com.lakala.moss.api.response;
import com.lakala.moss.api.params.AccRespFields;
/**
* 响应参数-订单支付
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderPayRes {
// 商户订单号
private String order_no;
// 支付流水号
private String pay_serial;
// 账户端的商户单号
private String trade_no;
// 对账单流水号
private String log_no;
// 支付场景 0-拉起收银台 1-独立支付API
private String pay_scene;
// 账户端子商户号
private String sub_mch_id;
// [微信小程序/微信公众号/支付宝生活号]支付时返回,预下单IdJSAPI支付方式时返回
private String prepay_id;
// 账户端返回信息域
private AccRespFields acc_resp_fields;
// 收银台地址url可嵌入至H5、PC或集成小程序场景中
private String counter_url;
public String getOrder_no() {
return order_no;
}
public void setOrder_no(String order_no) {
this.order_no = order_no;
}
public String getPay_serial() {
return pay_serial;
}
public void setPay_serial(String pay_serial) {
this.pay_serial = pay_serial;
}
public String getTrade_no() {
return trade_no;
}
public void setTrade_no(String trade_no) {
this.trade_no = trade_no;
}
public String getLog_no() {
return log_no;
}
public void setLog_no(String log_no) {
this.log_no = log_no;
}
public String getPay_scene() {
return pay_scene;
}
public void setPay_scene(String pay_scene) {
this.pay_scene = pay_scene;
}
public String getSub_mch_id() {
return sub_mch_id;
}
public void setSub_mch_id(String sub_mch_id) {
this.sub_mch_id = sub_mch_id;
}
public String getPrepay_id() {
return prepay_id;
}
public void setPrepay_id(String prepay_id) {
this.prepay_id = prepay_id;
}
public AccRespFields getAcc_resp_fields() {
return acc_resp_fields;
}
public void setAcc_resp_fields(AccRespFields acc_resp_fields) {
this.acc_resp_fields = acc_resp_fields;
}
public String getCounter_url() {
return counter_url;
}
public void setCounter_url(String counter_url) {
this.counter_url = counter_url;
}
}

View File

@@ -0,0 +1,130 @@
package com.lakala.moss.api.response;
import com.lakala.moss.api.params.PayInfo;
import java.util.List;
/**
* 响应参数-订单查询列表
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderQryListRes {
// 交易类型。PAY-支付REFUND-退款
private String trade_main_type;
// 商户订单号,根据交易类型不同,或为支付订单号 或为退款订单号
private String order_no;
// 原商户支付订单号trade_main_type=REFUND时存在该字段
private String origin_order_no;
// 商户号
private String mer_no;
// 订单金额,单位分
private String total_amount;
// 订单标题用于简单描述订单或商品主题。最多42个字符如不送默认显示商户简称
private String subject;
// 订单创建时间格式yyyyMMddHHmmss
private String order_create_time;
// 订单有效时间,分钟
private String order_eff_time;
// 订单层状态:
//INIT-初始化
//CREATE-待支付
//SUCCESS-已支付
//CLOSE-订单关闭
//PART_REFUND-部分退款 (当商户订单号下存在未全额退款成功的支付流水号时)
//REFUND-全部退款(当商户订单号下资金全部退完,为全部退款)
private String order_status;
// 接入方式41:NATIVEALIPAY云闪付支持51:JSAPI微信公众号支付支付宝服务窗支付银联JS支付71:微信小程序支付
private String trans_type;
// 支付信息列表
private List<PayInfo> pay_info_list;
public String getTrade_main_type() {
return trade_main_type;
}
public void setTrade_main_type(String trade_main_type) {
this.trade_main_type = trade_main_type;
}
public String getOrder_no() {
return order_no;
}
public void setOrder_no(String order_no) {
this.order_no = order_no;
}
public String getOrigin_order_no() {
return origin_order_no;
}
public void setOrigin_order_no(String origin_order_no) {
this.origin_order_no = origin_order_no;
}
public String getMer_no() {
return mer_no;
}
public void setMer_no(String mer_no) {
this.mer_no = mer_no;
}
public String getTotal_amount() {
return total_amount;
}
public void setTotal_amount(String total_amount) {
this.total_amount = total_amount;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getOrder_create_time() {
return order_create_time;
}
public void setOrder_create_time(String order_create_time) {
this.order_create_time = order_create_time;
}
public String getOrder_eff_time() {
return order_eff_time;
}
public void setOrder_eff_time(String order_eff_time) {
this.order_eff_time = order_eff_time;
}
public String getOrder_status() {
return order_status;
}
public void setOrder_status(String order_status) {
this.order_status = order_status;
}
public String getTrans_type() {
return trans_type;
}
public void setTrans_type(String trans_type) {
this.trans_type = trans_type;
}
public List<PayInfo> getPay_info_list() {
return pay_info_list;
}
public void setPay_info_list(List<PayInfo> pay_info_list) {
this.pay_info_list = pay_info_list;
}
}

View File

@@ -0,0 +1,127 @@
package com.lakala.moss.api.response;
/**
* 响应参数-退款交易
*
* @author Stephen yu
* @date 2025-02-21
*/
public class OrderRefundRes {
// 商户退款订单号
private String order_no;
// 原商户支付订单号
private String origin_order_no;
// 原支付流水号
private String origin_pay_serial;
// 对账单流水号
private String log_no;
// 账户端交易订单号
private String acc_trade_no;
// 商户号
private String mer_no;
// 交易金额,单位分
private String total_amount;
// 申请退款金额,单位分
private String refund_amount;
// 实际退款金额,单位分
private String payer_amount;
// 退款时间,yyyyMMddHHmmss
private String trade_time;
// 交易状态
//INIT-初始化;
//SUCCESS-交易成功;
//FAIL-交易失败;
//DEAL-交易处理中/未知;
//TIMEOUT-超时未知;
//EXCEPTION-异常;
private String trade_state;
public String getOrder_no() {
return order_no;
}
public void setOrder_no(String order_no) {
this.order_no = order_no;
}
public String getOrigin_order_no() {
return origin_order_no;
}
public void setOrigin_order_no(String origin_order_no) {
this.origin_order_no = origin_order_no;
}
public String getOrigin_pay_serial() {
return origin_pay_serial;
}
public void setOrigin_pay_serial(String origin_pay_serial) {
this.origin_pay_serial = origin_pay_serial;
}
public String getLog_no() {
return log_no;
}
public void setLog_no(String log_no) {
this.log_no = log_no;
}
public String getAcc_trade_no() {
return acc_trade_no;
}
public void setAcc_trade_no(String acc_trade_no) {
this.acc_trade_no = acc_trade_no;
}
public String getMer_no() {
return mer_no;
}
public void setMer_no(String mer_no) {
this.mer_no = mer_no;
}
public String getTotal_amount() {
return total_amount;
}
public void setTotal_amount(String total_amount) {
this.total_amount = total_amount;
}
public String getRefund_amount() {
return refund_amount;
}
public void setRefund_amount(String refund_amount) {
this.refund_amount = refund_amount;
}
public String getPayer_amount() {
return payer_amount;
}
public void setPayer_amount(String payer_amount) {
this.payer_amount = payer_amount;
}
public String getTrade_time() {
return trade_time;
}
public void setTrade_time(String trade_time) {
this.trade_time = trade_time;
}
public String getTrade_state() {
return trade_state;
}
public void setTrade_state(String trade_state) {
this.trade_state = trade_state;
}
}

View File

@@ -0,0 +1,21 @@
package com.lakala.moss.api.response;
/**
* 响应参数-用户标识查询
*
* @author Stephen yu
* @date 2025-02-21
*/
public class UseridQryRes {
// 银联钱包的userId
private String user_id;
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
}

View File

@@ -0,0 +1,47 @@
package com.lakala.moss.service;
import com.lakala.moss.api.ApiReq;
import com.lakala.moss.api.ApiRes;
import com.lakala.moss.api.request.*;
import com.lakala.moss.api.response.*;
/**
* @author Stephen yu
* @description: api服务接口
* @date 2025-02-21
*/
public interface IMossApiService {
/**
* 订单支付
*/
ApiRes<OrderPayRes> OrderPay(OrderPayReq req);
/**
* 订单查询
*/
ApiRes<OrderQryListRes> OrderQryList(OrderQryListReq req);
/**
* 订单关单
*/
ApiRes<OrderClsRes> OrderCls(OrderClsReq req);
/**
* 订单退款
*/
ApiRes<OrderRefundRes> OrderRefund(OrderRefundReq req);
/**
* 申请对账单
*/
ApiRes<OrderChkApplyRes> OrderChkApply(OrderChkApplyReq req);
/**
* 用户标识查询
*/
ApiRes<UseridQryRes> UseridQry(UseridQryReq req);
/**
* 对账单下载
*/
boolean ChkDownload(String urlPath,String localDir,String localFileName);
/**
* 订单通知
*/
ApiRes<OrderNoticeRes> OrderNotice(ApiReq<OrderNoticeReq> request);
}

View File

@@ -0,0 +1,174 @@
package com.lakala.moss.service.impl;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.lakala.moss.api.*;
import com.lakala.moss.api.request.OrderNoticeReq;
import com.lakala.moss.api.response.OrderNoticeRes;
import com.lakala.moss.util.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* @author Stephen yu
* @description: 基础服务
* @date 2025-02-21
*/
public abstract class BaseService {
private static Logger logger = LoggerFactory.getLogger(BaseService.class);
protected ApiReqHead BuildApiRequestHead(String serivceId) {
ApiReqHead head = new ApiReqHead();
head.setVersionId(PropertiesUtil.getStringByKey("api.versionId"));
head.setServiceId(serivceId);
head.setChannelId(PropertiesUtil.getStringByKey("api.channelId"));
head.setRequestTime(DateUtil.getSystemDateLongStr());
head.setServiceSn(UUID.randomUUID().toString().replaceAll("-", ""));
head.setBusinessChannel(PropertiesUtil.getStringByKey("api.businessChannel"));
return head;
}
public <T, E> ApiRes<E> postService(T requestObj, Class<E> responseClass, String serivceId) {
return invokApiByEncrypt(requestObj, responseClass, serivceId);
}
private <T, E> ApiRes<E> invokApiByEncrypt(T requestObj, Class<E> responseClass, String serivceId) {
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
ApiRes<E> responseBean = new ApiRes<>();
// 组装请求消息头对象
ApiReqHead reqHead = BuildApiRequestHead(serivceId);
ApiResHead resHead = new ApiResHead();
resHead.setServiceId(reqHead.getServiceId());
resHead.setServiceSn(reqHead.getServiceSn());
resHead.setServiceTime(DateUtil.getSystemDateLongStr());
try {
Map<String,String> headMap = ObjectToMapUtils.toMap(reqHead);
TreeMap<String,String> headTreeMap = new TreeMap<>();
headTreeMap.putAll(headMap);
// 组装请求消息体对象
// 生成加密报文,用moss公钥加密
String reqParams = gson.toJson(requestObj);
logger.info("data=" + reqParams);
String mossPublicKey = PropertiesUtil.getStringByKey("moss.pub.key");
String requestEncrypted = SecurityUtil.encryptInStringOutBase64(reqParams, mossPublicKey);
logger.info("encData=" + requestEncrypted);
// 组装请求消息签名
// 签名前字段先按key自然排序用TreeMap实现
Map<String, String> signMap = new TreeMap<>();
signMap.put("head", gson.toJson(headTreeMap));
signMap.put("requestEncrypted", requestEncrypted);
// 拼接参与签名的字符串,用商户私钥加签
String signStr = SecurityUtil.getSignSrcSkipNull(signMap, true, "&");
String merPrivateKey = PropertiesUtil.getStringByKey("mer.pri.key");
String sign = SecurityUtil.sign(signStr, merPrivateKey);
// 组装请求消息对象
Map<String, Object> request = new LinkedHashMap<>();
request.put("head", headTreeMap);
request.put("requestEncrypted", requestEncrypted);
request.put("sign", sign);
// 最后生成的报文是这样的
String encReq = gson.toJson(request);
// 发送post消息
String url = PropertiesUtil.getStringByKey("api.order.url");
String encRes = HttpsUtil.doPost(url, encReq);
if(StringUtils.isBlank(encRes)){
resHead.setCode(ApiResCode.PA_INSIDE_ERROR.getCode());
resHead.setDesc(ApiResCode.PA_INSIDE_ERROR.getDesc() + ",响应消息为空");
responseBean.setHead(resHead);
return responseBean;
}
Map<String, Object> response = gson.fromJson(encRes,Map.class);
String resSign = (String)response.get("sign");
String responseEncrypted = (String)response.get("responseEncrypted");
Map<String,String> resHeadMap = (Map<String,String>)response.get("head");
if(resHeadMap == null || StringUtils.isBlank(resHeadMap.get("code")) ){
resHead.setCode(ApiResCode.PA_INSIDE_ERROR.getCode());
resHead.setDesc(ApiResCode.PA_INSIDE_ERROR.getDesc() + ",响应消息头为空");
responseBean.setHead(resHead);
return responseBean;
}
responseBean.setHead(gson.fromJson(gson.toJson(resHeadMap), ApiResHead.class));
if(!ApiResCode.SUCCESS.getCode().equals(resHeadMap.get("code"))){
return responseBean;
}
TreeMap<String,String> resHeadTreeMap = new TreeMap<>();
resHeadTreeMap.putAll(resHeadMap);
// 组装响应消息签名
// 签名前字段先按key自然排序用TreeMap实现
Map<String, String> resSignMap = new TreeMap<>();
resSignMap.put("head", gson.toJson(resHeadTreeMap));
resSignMap.put("responseEncrypted", responseEncrypted);
// 拼接参与签名的字符串
String resSignStr = SecurityUtil.getSignSrcSkipNull(resSignMap, true, "&");
boolean verifySign = SecurityUtil.verify(resSignStr, resSign, mossPublicKey);
if(!verifySign){
resHead.setCode(ApiResCode.PA_INSIDE_ERROR.getCode());
resHead.setDesc(ApiResCode.PA_INSIDE_ERROR.getDesc() + ",响应消息验签失败");
responseBean.setHead(resHead);
return responseBean;
}
// 用商户的私要解密数据
if(StringUtils.isNotBlank(responseEncrypted)){
String decData = SecurityUtil.decryptInBase64OutString(responseEncrypted, merPrivateKey);
logger.info("decData={}",decData);
responseBean.setResponse(gson.fromJson(decData, responseClass));
}
} catch (Exception e) {
logger.error("invokApi error,e={}", e);
resHead.setCode(ApiResCode.PA_UNKNOWN_ERROR.getCode());
resHead.setDesc(ApiResCode.PA_UNKNOWN_ERROR.getDesc()+ ",e=" + e.getMessage());
responseBean.setHead(resHead);
}
return responseBean;
}
public <T, E> ApiRes<E> notifyServiceByDecrypt(ApiReq<T> request, Class<E> responseClass) {
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
ApiRes<E> res = new ApiRes<>();
ApiResHead resHead = new ApiResHead();
resHead.setServiceId(request.getHead().getServiceId());
resHead.setServiceSn(request.getHead().getServiceSn());
resHead.setServiceTime(DateUtil.getSystemDateLongStr());
try {
Map<String,String> headMap = ObjectToMapUtils.toMap(request.getHead());
TreeMap<String,String> headTreeMap = new TreeMap<>();
headTreeMap.putAll(headMap);
// 组装响应消息签名
// 签名前字段先按key自然排序用TreeMap实现
Map<String, String> signMap = new TreeMap<>();
signMap.put("head", gson.toJson(headTreeMap));
signMap.put("requestEncrypted", request.getRequestEncrypted());
// 拼接参与签名的字符串
String mossPublicKey = PropertiesUtil.getStringByKey("moss.pub.key");
String signStr = SecurityUtil.getSignSrcSkipNull(signMap, true, "&");
logger.info("signStr={}", signStr);
boolean verifySign = SecurityUtil.verify(signStr, request.getSign(), mossPublicKey);
if(!verifySign){
resHead.setCode(ApiResCode.PA_INSIDE_ERROR.getCode());
resHead.setDesc(ApiResCode.PA_INSIDE_ERROR.getDesc() + ",请求消息验签失败");
res.setHead(resHead);
return res;
}
// 用商户的私要解密数据
if(StringUtils.isNotBlank(request.getRequestEncrypted())){
String merPrivateKey = PropertiesUtil.getStringByKey("mer.pri.key");
String decData = SecurityUtil.decryptInBase64OutString(request.getRequestEncrypted(), merPrivateKey);
logger.info("decData={}",decData);
}
resHead.setCode(ApiResCode.SUCCESS.getCode());
resHead.setDesc(ApiResCode.SUCCESS.getDesc());
res.setHead(resHead);
} catch (Exception e) {
logger.error("invokApi error,e={}", e);
resHead.setCode(ApiResCode.PA_UNKNOWN_ERROR.getCode());
resHead.setDesc(ApiResCode.PA_UNKNOWN_ERROR.getDesc()+ ",e=" + e.getMessage());
res.setHead(resHead);
} finally {
}
return res;
}
}

View File

@@ -0,0 +1,49 @@
package com.lakala.moss.service.impl;
import com.lakala.moss.api.*;
import com.lakala.moss.api.request.*;
import com.lakala.moss.api.response.*;
import com.lakala.moss.service.IMossApiService;
import com.lakala.moss.util.CustomUrlUtil;
/**
* @author Stephen yu
* @description: api服务接口实现
* @date 2025-02-21
*/
public class MossApiServiceImpl extends BaseService implements IMossApiService {
@Override
public ApiRes<OrderPayRes> OrderPay(OrderPayReq req) {
return super.postService(req,OrderPayRes.class,"lfops.moss.order.pay");
}
@Override
public ApiRes<OrderQryListRes> OrderQryList(OrderQryListReq req) {
return super.postService(req,OrderQryListRes.class,"lfops.moss.order.qry");
}
@Override
public ApiRes<OrderClsRes> OrderCls(OrderClsReq req) {
return super.postService(req,OrderClsRes.class,"lfops.moss.order.cls");
}
@Override
public ApiRes<OrderRefundRes> OrderRefund(OrderRefundReq req) {
return super.postService(req,OrderRefundRes.class,"lfops.moss.order.ref");
}
@Override
public ApiRes<OrderChkApplyRes> OrderChkApply(OrderChkApplyReq req) {
return super.postService(req,OrderChkApplyRes.class,"lfops.moss.order.chk.apply");
}
@Override
public ApiRes<UseridQryRes> UseridQry(UseridQryReq req) {
return super.postService(req,UseridQryRes.class,"lfops.moss.userid.qry");
}
@Override
public boolean ChkDownload(String urlPath, String localDir, String localFileName) {
return CustomUrlUtil.download(urlPath,localDir,localFileName);
}
@Override
public ApiRes<OrderNoticeRes> OrderNotice(ApiReq<OrderNoticeReq> request) {
return super.notifyServiceByDecrypt(request,OrderNoticeRes.class);
}
}

View File

@@ -0,0 +1,82 @@
package com.lakala.moss.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
* 工具类 - url下载或上传文件
*
* @author Stephen yu
* @date 2025-02-26
*/
public class CustomUrlUtil {
private static final Logger logger = LoggerFactory.getLogger(CustomUrlUtil.class);
/**
*
* @param urlPath url链接字符串
*/
private static URLConnection connectUrlServer(String urlPath){
logger.info("connect params [urlPath="+urlPath+"]");
URLConnection conn = null;
try {
URL url = new URL(urlPath);
conn = url.openConnection();
} catch (MalformedURLException e) {
logger.error("connect failed,err msg = {}",e.getMessage());
} catch (IOException e) {
logger.error("connect failed,err msg = {}",e.getMessage());
}
return conn;
}
/**
* 文件下载
* @param urlPath urlPath地址
* @param localDir 本地路径
* @param localFileName 本地文件名称
*/
public static boolean download(String urlPath,String localDir,String localFileName){
URLConnection conn = connectUrlServer(urlPath);
if (conn == null){
return false;
}
InputStream is = null;
FileOutputStream os = null;
try {
is = conn.getInputStream();
byte[] bs = new byte[1024];
int len;
File file = new File(localDir+localFileName);
os = new FileOutputStream(file);
while ((len = is.read(bs)) != -1){
os.write(bs,0,len);
}
logger.info("从Url[{}]读取文件到[{}]成功", urlPath, localDir+localFileName);
} catch (IOException e) {
logger.error("处理文件流失败.err msg = {}",e.getMessage());
return false;
} finally {
try {
os.close();
is.close();
} catch (IOException e) {
logger.error("关闭文件流失败.err msg = {}",e.getMessage());
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,669 @@
package com.lakala.moss.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import static java.util.Calendar.*;
/**
* @author Stephen yu
* @description: 日期工具类
* @date 2025-02-21
*/
public class DateUtil {
private static Logger logger = LoggerFactory.getLogger(DateUtil.class);
private static final Calendar CAL = getInstance();
private static final Calendar TMP = getInstance();
public static final String FORMAT1 = "yyyyMMdd";
public static final String FORMAT2 = "yyyy-MM-dd";
public static final String FORMAT3 = "yyyyMMddHHmmss";
public static final String FORMAT4 = "yyyy-MM-dd HH:mm:ss";
public static final String FORMAT5 = "MMddHHmmss";
public static final String FORMAT6 = "yyMMddHHmmss";
public static final int YEAR = Calendar.YEAR;
public static final int MONTH = Calendar.MONTH;
public static final int DAY_OF_MONTH = Calendar.DAY_OF_MONTH;
public static final int HOUR = Calendar.HOUR;
public static final int MINUTE = Calendar.MINUTE;
public static final int SECOND = Calendar.SECOND;
// 静态工具类,防误生成
private DateUtil() {
throw new UnsupportedOperationException();
}
/**
* <p>Title: isThisMonth</p>
* <p>Description: 判断给定日期date是否在当前月内</p>
*
* @param date 给定日期
* @return boolean
*/
public static boolean isThisMonth(Date date) {
return isInRange(date, MONTH);
}
/**
* <p>Title: getDateByDayOfMonth</p>
* <p>Description: 查找指定日期的下一个提醒日</p>
*
* @param date 指定日期
* @param day 提醒日
* @return Date
*/
public static Date getDateByDayOfMonth(Date date, int day) {
synchronized (CAL) {
CAL.setTime(date);
int today = CAL.get(DAY_OF_MONTH);
if (day < today) {
CAL.add(MONTH, 1);
}
CAL.set(DAY_OF_MONTH, day);
return CAL.getTime();
}
}
/**
* <p>Title: getDateByDayOfMonth</p>
* <p>Description: 查找当前日期的下一个提醒日</p>
*
* @param day 提醒日
* @return Date
*/
public static Date getDateByDayOfMonth(int day) {
return getDateByDayOfMonth(new Date(), day);
}
/**
* <p>Title: getTheAppointedDayOfTheMonth</p>
* <p>Description: 根据指定日期和月份换回当月的提醒日期当提醒日期day大于本月最大天数时取最大天数。</p>
*
* @param month 指定的月份0-11
* @param day 指定的提醒日1-31
* @return int 1-31
*/
public static int getTheAppointedDayOfTheMonth(int month, int day) {
synchronized (CAL) {
CAL.set(MONTH, month);
int lastDay = CAL.getActualMaximum(DAY_OF_MONTH);
return day > lastDay ? lastDay : day;
}
}
/**
* <p>Title: getTheAppointedDayOfTheMonth</p>
* <p>Description: 根据指定日期返回当前月份的提醒日期当提醒日期day大于本月最大天数时取最大天数。</p>
*
* @param day 指定的提醒日1-31
* @return int 1-31
*/
public static int getTheAppointedDayOfTheMonth(int day) {
synchronized (CAL) {
resetCalendarWithNowTime();
int lastDay = CAL.getActualMaximum(DAY_OF_MONTH);
return day > lastDay ? lastDay : day;
}
}
/**
* <p>Title: getDayOfMonthOfToday</p>
* <p>Description: 获取当前日期在本月中是第几天</p>
*
* @return int 1-31
*/
public static int getDayOfMonthOfToday() {
synchronized (CAL) {
resetCalendarWithNowTime();
return CAL.get(DAY_OF_MONTH);
}
}
/**
* <p>Title: getFate</p>
* <p>Description: 根据提醒日和指定日期返回提醒日和指定日期间隔天数提醒日当天返回0。</p>
*
* @param day 提醒日
* @param date 指定日期
* @return int 0-30
*/
public static int getFate(int day, Date date) {
day = getTheAppointedDayOfTheMonth(day);
synchronized (CAL) {
CAL.setTime(date);
int today = CAL.get(DAY_OF_MONTH);
int max = CAL.getActualMaximum(DAY_OF_MONTH);
return (day - today + max) % max;
}
}
/**
* <p>Title: getFate</p>
* <p>Description: 根据提醒日返回下次提醒日距今的天数提醒日当天返回0。</p>
*
* @param day 提醒日
* @return int 0-30
*/
public static int getFate(int day) {
return getFate(day, new Date());
}
/**
* <p>Title: resetCalendarWithNowTime</p>
* <p>Description: 将cal重置为当前时间。</p>
*/
private static void resetCalendarWithNowTime() {
synchronized (CAL) {
CAL.setTime(new Date());
}
}
/**
* <p>Title: getFormatDate</p>
* <p>Description: 把指定日期date转换为指定格式format的日期字符串</p>
*
* @param date 指定日期
* @param pattern 指定格式,可从静态常量中获取
* @return String
*/
public static String getFormatDateStr(Date date, String pattern) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
return simpleDateFormat.format(date);
}
/**
* <p>Title: getFormatDateStr</p>
* <p>Description: 将传入的fm1格式的时间字符串date转换为fm2格式的字符串类型</p>
*
* @param date 指定日期
* @param fm1 fm1格式
* @param fm2 fm2格式
* @return String
*/
public static String getFormatDateStr(String date, String fm1, String fm2) {
String oDate = null;
SimpleDateFormat fmt = new SimpleDateFormat(fm1);
try {
Date outDate = fmt.parse(date);
fmt.applyPattern(fm2);
oDate = fmt.format(outDate);
} catch (ParseException e) {
logger.error("{}", e);
}
return oDate;
}
/**
* <p>Title: getSystemDateLongStr</p>
* <p>Description: 获取当前日期长字符串格式</p>
*
* @return String yyyyMMddHHmmss
*/
public static String getSystemDateLongStr() {
Date sysDate = new Date();
return getFormat3DateStr(sysDate);
}
/**
* <p>Title: getSystemDateStr</p>
* <p>Description: 获取当前日期字符串格式</p>
*
* @return String yyyyMMdd
*/
public static String getSystemDateStr() {
Date sysDate = new Date();
return getFormat1DateStr(sysDate);
}
/**
* <p>Title: getSystemDateStr</p>
* <p>Description: 获取当前日期指定字符串格式</p>
*
* @param pattern 指定字符串格式
* @return String
*/
public static String getSystemDateStr(String pattern) {
return getFormatDateStr(new Date(), pattern);
}
/**
* <p>Title: getFormat1DateStr</p>
* <p>Description: 获取指定日期date字符串格式</p>
*
* @param date 指定日期
* @return String yyyyMMdd
*/
public static String getFormat1DateStr(Date date) {
return getFormatDateStr(date, FORMAT1);
}
/**
* <p>Title: getFormat2DateStr</p>
* <p>Description: 将日期类型date转换为yyyy-MM-dd字符串</p>
*
* @param date 目标日期
* @return String yyyy-MM-dd
*/
public static String getFormat2DateStr(Date date) {
return getFormatDateStr(date, FORMAT2);
}
/**
* <p>Title: getFormat3DateStr</p>
* <p>Description: 将日期类型date转换为yyyyMMddHHmmss字符串</p>
*
* @param date 目标日期
* @return String yyyyMMddHHmmss
*/
public static String getFormat3DateStr(Date date) {
return getFormatDateStr(date, FORMAT3);
}
/**
* <p>Title: getFormat4DateStr</p>
* <p>Description: 将日期类型date转换为yyyy-MM-dd HH:mm:ss字符串</p>
*
* @param date 目标日期
* @return String yyyy-MM-dd HH:mm:ss
*/
public static String getFormat4DateStr(Date date) {
return getFormatDateStr(date, FORMAT4);
}
/**
* <p>Title: getFormat5DateStr</p>
* <p>Description: 将日期类型date转换为MMddHHmmss字符串</p>
*
* @param date 目标日期
* @return String MMddHHmmss
*/
public static String getFormat5DateStr(Date date) {
return getFormatDateStr(date, FORMAT5);
}
/**
* <p>Title: getFormat6DateStr</p>
* <p>Description: 将日期类型date转换为yyMMddHHmmss字符串</p>
*
* @param date 目标日期
* @return String MMddHHmmss
*/
public static String getFormat6DateStr(Date date) {
return getFormatDateStr(date, FORMAT6);
}
/**
* <p>Title: getDiffBetweenTwoDate</p>
* <p>Description: 计算两个日期差几天,也可比较两个日期谁在前,谁在后</p>
*
* @param firstDate 第一个日期
* @param secondDate 第二个日期
* @return int 天数。如果secondDate在firstDate之前返回一个负整数反之返回正整数
*/
public static int getDiffBetweenTwoDate(Date firstDate, Date secondDate) {
long seconds = secondDate.getTime() - firstDate.getTime();// 终止日期-起始日期=毫秒
int diff = (int) (seconds / (24 * 60 * 60 * 1000));// 再除以每天多少毫秒(24*60*60*1000)=差几天
return diff;
}
/**
* <p>Title: getDiffBetweenTwoDate</p>
* <p>Description: 计算两个日期差几天,也可比较两个日期谁在前,谁在后</p>
*
* @param firstDate 第一个日期 yyyyMMdd
* @param secondDate 第二个日期 yyyyMMdd
* @return int 天数。如果secondDate在firstDate之前返回一个负整数反之返回正整数
*/
public static int getDiffBetweenTwoDate(String firstDate, String secondDate) {
return getDiffBetweenTwoDate(firstDate, secondDate, FORMAT1);
}
/**
* <p>Title: getDiffBetweenTwoDate</p>
* <p>Description: 计算两个日期差几天,也可比较两个日期谁在前,谁在后</p>
*
* @param firstDate 第一个日期
* @param secondDate 第二个日期
* @param format 日期样式
* @return int 如果secondDate在firstDate之前返回一个负整数反之返回正整数
*/
public static int getDiffBetweenTwoDate(String firstDate, String secondDate, String format) {
SimpleDateFormat myFormatter = new SimpleDateFormat(format);// 计算两天之差
Date date1 = null;
Date date2 = null;
int diff = 0;
try {
date1 = myFormatter.parse(firstDate);// 起始日期
date2 = myFormatter.parse(secondDate);// 终止日期
diff = getDiffBetweenTwoDate(date1, date2);
} catch (ParseException e) {
logger.error("{}", e);
}// 起始日期
return diff;
}
/**
* <p>Title: isLeapYear</p>
* <p>Description: 判断目标日期所在年是否为闰年</p>
*
* @param date 目标日期
* @return boolean
*/
public static boolean isLeapYear(Date date) {
synchronized (CAL) {
CAL.setTime(date);
int year = CAL.get(YEAR);
if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
return true;
}
return false;
}
}
/**
* <p>Title: getDifferMonth</p>
* <p>Description: 计算两个日期相差的月份</p>
*
* @param startDate 起始日期
* @param endDate 结束日期
* @return int 正值startDate先于endDate负值startDate后于endDate
*/
public static int getDifferMonth(Date startDate, Date endDate) {
synchronized (CAL) {
CAL.setTime(startDate);
TMP.setTime(endDate);
int differYear = TMP.get(YEAR) - CAL.get(YEAR);
int differMonth = TMP.get(MONTH) - CAL.get(MONTH);
return differYear * 12 + differMonth;
}
}
/**
* <p>Title: getDateByAddYear</p>
* <p>Description: 指定日期date加year年</p>
*
* @param date 指定日期
* @param year 指定年份
* @return Date
*/
public static Date getDateByAddYear(Date date, int year) {
return getNextRangeDate(date, YEAR, year);
}
/**
* <p>Title: getDateByAddYear</p>
* <p>Description: 当前日期加year年</p>
*
* @param year 指定年份
* @return Date
*/
public static Date getDateByAddYear(int year) {
return getDateByAddYear(new Date(), year);
}
/**
* <p>Title: getDateBeforeXDay</p>
* <p>Description: 获取指定日期前n日的日期时间</p>
*
* @param date 指定日期
* @param n 提前天数
* @param format 格式化日期字符串
* @return String
*/
public static String getDateBeforeXDay(Date date, int n, String format) {
Date d = getNextRangeDate(date, DAY_OF_MONTH, -n);
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(d);
}
/**
* <p>Title: getDate</p>
* <p>Description: 日期字符串转换为日期</p>
*
* @param dateStr 日期字符串
* @param format 转换格式字符串
* @return Date
*/
public static Date getDate(String dateStr, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date date = null;
try {
date = sdf.parse(dateStr);
} catch (ParseException e) {
logger.error("{}", e);
}
return date;
}
/**
* <p>Title: getBeforeXDay</p>
* <p>Description: 返回当月指定日期的前X天的值</p>
*
* @param target 指定天数
* @param x 提前天数
* @return int
*/
public static int getBeforeXDay(int target, int x) {
synchronized (CAL) {
resetCalendarWithNowTime();
CAL.set(DAY_OF_MONTH, target);
CAL.add(DAY_OF_MONTH, -x);
return CAL.get(DAY_OF_MONTH);
}
}
/**
* <p>Title: dateCompare</p>
* <p>Description: 比较两个日期是否在某个时间范围内</p>
*
* @param date1 日期一
* @param date2 日期二
* @param range 范围Calendar常量或本类常量
* @param val 范围值
* @return boolean
*/
public static boolean dateCompare(Date date1, Date date2, int range, int val) {
synchronized (CAL) {
CAL.setTime(date1);
TMP.setTime(date2);
if (CAL.before(TMP)) {
CAL.add(range, val);
return CAL.after(TMP);
} else if (CAL.after(TMP)) {
TMP.add(range, val);
return CAL.before(TMP);
} else {
return true;
}
}
}
/**
* <p>Title: dateCompare</p>
* <p>Description: 判断指定日期与当前日期是否在某个时间范围内</p>
*
* @param date 指定日期
* @param range 范围Calendar常量或本类常量
* @param val 范围值
* @return boolean
*/
public static boolean dateCompare(Date date, int range, int val) {
return dateCompare(date, new Date(), range, val);
}
/**
* <p>Title: isInRange</p>
* <p>Description: 判断指定日期与当前日期是否在指定范围内,当前日期取极值。</p>
*
* @param date 指定日期
* @param range 范围Calendar常量或本类常量
* @param val 范围值
* @return boolean
*/
public static boolean isInRange(Date date, int range, int val) {
synchronized (CAL) {
boolean res = false;
TMP.setTime(date);
resetCalendarWithNowTime();
resetCalendarByRange(CAL, range);
res = TMP.after(CAL);
CAL.add(range, val);
res = res && TMP.before(CAL);
return res;
}
}
/**
* <p>Title: resetCalendarByRange</p>
* <p>Description: 按指定范围range重置cal时间值</p>
*
* @param cal 时间类
* @param range 范围Calendar常量或本类常量
*/
public static void resetCalendarByRange(Calendar cal, int range) {
switch (range) {
case YEAR:
cal.set(MONTH, CAL.getActualMinimum(MONTH));
case MONTH:
cal.set(DAY_OF_MONTH, CAL.getActualMinimum(DAY_OF_MONTH));
case DAY_OF_MONTH:
cal.set(HOUR_OF_DAY, CAL.getActualMinimum(HOUR_OF_DAY));
case HOUR_OF_DAY:
cal.set(MINUTE, CAL.getActualMinimum(MINUTE));
case MINUTE:
cal.set(SECOND, CAL.getActualMinimum(SECOND));
case SECOND:
cal.set(MILLISECOND, CAL.getActualMinimum(MILLISECOND));
}
}
/**
* <p>Title: isInRange</p>
* <p>Description: 判断指定日期与当前日期是否在1个单位的范围内当前日期取极值。</p>
*
* @param date 指定日期
* @param range 范围Calendar常量或本类常量
* @return boolean
*/
public static boolean isInRange(Date date, int range) {
return isInRange(date, range, 1);
}
/**
* <p>Title: isSameDay</p>
* <p>Description: 判断指定日期与当前日期是否在同一天内。</p>
*
* @param date 指定日期
* @return boolean
*/
public static boolean isSameDay(Date date) {
return isInRange(date, DAY_OF_MONTH);
}
/**
* <p>Title: getNextDate</p>
* <p>Description: 获取指定日期下一天的日期</p>
*
* @param start 指定日期
* @return Date
*/
public static Date getNextDate(Date start) {
return getNextDate(start, 1);
}
/**
* <p>Title: getNextDate</p>
* <p>Description: 获取指定日期下days天的日期</p>
*
* @param start 指定日期
* @param days 天数
* @return Date
*/
public static Date getNextDate(Date start, int days) {
synchronized (CAL) {
CAL.setTime(start);
CAL.add(DAY_OF_MONTH, days);
return CAL.getTime();
}
}
/**
* <p>Title: getNextRangeDate</p>
* <p>Description: 获取指定日期下val个单位指定范围range的日期</p>
*
* @param start 指定日期
* @param range 范围Calendar常量或本类常量
* @param val 范围值
* @return Date
*/
public static Date getNextRangeDate(Date start, int range, int val) {
synchronized (CAL) {
CAL.setTime(start);
CAL.add(range, val);
return CAL.getTime();
}
}
/**
* <p>Title: getDateStrFormatPlusHour</p>
* <p>Description: 把日期转换为指定格式的日期字符串</p>
*
* @param date 指定日期
* @param format 格式化字符串
* @param hour 添加时间
* @return String
*/
public static String getDateStrFormatPlusHour(Date date, String format,
int hour) {
Date nextDate = getNextRangeDate(date, HOUR_OF_DAY, hour);
return getFormatDateStr(nextDate, format);
}
public static String getDateMinu() {//获取当前时间与当日23:59:59的相差分钟数
Date lastDay = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(lastDay);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 50);
calendar.set(Calendar.SECOND, 00);
Date d = calendar.getTime();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long currentTime = 0;
try {
currentTime = df.parse(df.format(new Date())).getTime();
long createTime = df.parse(df.format(d)).getTime();
long diff = (createTime - currentTime) / 1000 / 60;
if (diff > 999) {
diff = 999;
}
String minu = String.valueOf(diff);
return minu;
} catch (ParseException e) {
e.printStackTrace();
return "10";
}
}
public static void main(String[] args) throws ParseException {
Date lastDay = new Date();
// Calendar calendar = Calendar.getInstance();
// calendar.setTime(lastDay);
// calendar.set(Calendar.HOUR_OF_DAY, 23);
// calendar.set(Calendar.MINUTE, 59);
// calendar.set(Calendar.SECOND, 59);
// Date d = calendar.getTime();
// System.out.println(""+ d);
// SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// System.out.println(""+ df.format(new Date()));
// long currentTime = df.parse(df.format(new Date())).getTime();
// //从对象中拿到时间
// long createTime = df.parse(df.format(d)).getTime();
// long diff = (createTime-currentTime)/1000/60;
// System.out.println("当前系统时间为:"+currentTime+"下单时间为:"+createTime+"两个时间差为:"+diff);
System.out.println(getNextDate(lastDay, -1));
System.out.println(getDateMinu());
}
}

View File

@@ -0,0 +1,120 @@
package com.lakala.moss.util;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Stephen yu
* @description: HTTPS工具类
* @date 2025-02-21
*/
public class HttpsUtil {
private static Logger logger = LoggerFactory.getLogger(HttpsUtil.class);
private HttpsUtil(){}
/**
* post请求
* @param url
* @param jsonStrParams
* @return
* @throws Exception
*/
public static String doPost(String url, String jsonStrParams) throws Exception {
logger.info("url=" + url);
logger.info("request message=" + jsonStrParams);
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
HttpResponse response = null;
httpClient = new SSLClient();
httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json");
StringEntity se = new StringEntity(jsonStrParams, "UTF-8");
se.setContentType("text/json");
se.setContentEncoding(new BasicHeader("Content-Type", "application/json"));
httpPost.setEntity(se);
response = httpClient.execute(httpPost);
if (response != null) {
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
result = EntityUtils.toString(resEntity, "UTF-8");
}
}
logger.info("response message=" + result);
return result;
}
/**
* post请求
* @param url
* @param jsonStrParams
* @return
* @throws Exception
*/
public static String doPost2(String url, String jsonStrParams) throws Exception {
logger.info("request" + jsonStrParams);
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
HttpResponse response = null;
httpClient = new SSLClient();
httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json");
httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36");
StringEntity se = new StringEntity(jsonStrParams, "UTF-8");
se.setContentType("text/json");
se.setContentEncoding(new BasicHeader("Content-Type", "application/json"));
httpPost.setEntity(se);
response = httpClient.execute(httpPost);
if (response != null) {
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
result = EntityUtils.toString(resEntity, "UTF-8");
}
}
logger.info("response" + result);
return result;
}
/**
* get请求
* @param url
* @return
* @throws Exception
*/
public static String doGet(String url) throws Exception {
logger.info("对账文件Url : " + url);
HttpClient httpClient = null;
HttpGet httpGet = null;
String result = null;
HttpResponse response = null;
httpClient = new SSLClient();
httpGet = new HttpGet(url);
response = httpClient.execute(httpGet);
if (response != null) {
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
result = EntityUtils.toString(resEntity, "GBK");
}
}
logger.info("对账文件内容 : " + result);
return result;
}
}

View File

@@ -0,0 +1,167 @@
package com.lakala.moss.util;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Stephen yu
* @description: 对象转成Map工具类
* @date 2025-02-21
*/
public class ObjectToMapUtils {
/**
* 将目标对象的所有属性转换成Map对象
*
* @param target 目标对象
* @return Map
*/
public static <T> Map<String, T> toMap(Object target) {
return toMap(target, false);
}
/**
* 将目标对象的所有属性转换成Map对象
*
* @param target 目标对象
* @param ignoreParent 是否忽略父类的属性
* @return Map
*/
public static <T> Map<String, T> toMap(Object target, boolean ignoreParent) {
return toMap(target, ignoreParent, false);
}
/**
* 将目标对象的所有属性转换成Map对象
*
* @param target 目标对象
* @param ignoreParent 是否忽略父类的属性
* @param ignoreEmptyValue 是否不把空值添加到Map中
* @return Map
*/
public static <T> Map<String, T> toMap(Object target, boolean ignoreParent, boolean ignoreEmptyValue) {
return toMap(target, ignoreParent, ignoreEmptyValue, new String[0]);
}
/**
* 将目标对象的所有属性转换成Map对象
*
* @param target 目标对象
* @param ignoreParent 是否忽略父类的属性
* @param ignoreEmptyValue 是否不把空值添加到Map中
* @param ignoreProperties 不需要添加到Map的属性名
* @return Map
*/
public static <T> Map<String, T> toMap(Object target, boolean ignoreParent, boolean ignoreEmptyValue,
String... ignoreProperties) {
final Map<String, T> map = new HashMap<String, T>();
if (target == null) {
return map;
}
final Map<String, String> ignoreMap = getIgnorePropertiesMap(ignoreProperties);
final List<Field> fields = getClassFields(ignoreParent, target.getClass());
for (Field field : fields) {
T value = getFieldsValue(target, field);
if (isIgnoreEmpty(value, ignoreEmptyValue) || isIgnoreProperty(field.getName(), ignoreMap)) {
continue;
}
map.put(field.getName(), value);
}
return map;
}
/**
* 获得忽略的属性Map条件
*
* @param ignoreProperties 待忽略的属性
* @return
*/
private static Map<String, String> getIgnorePropertiesMap(final String[] ignoreProperties) {
final Map<String, String> resultMap = new HashMap<String, String>();
for (String ignoreProperty : ignoreProperties) {
resultMap.put(ignoreProperty, null);
}
return resultMap;
}
/**
* 获取类实例的属性
*
* @param ignoreParent 是否忽略父类属性
* @param clazz 类名
* @return
*/
private static List<Field> getClassFields(boolean ignoreParent, Class<?> clazz) {
final List<Field> fields = new ArrayList<Field>();
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (!ignoreParent) {
fields.addAll(getParentClassFields(fields, clazz.getSuperclass()));
}
return fields;
}
/**
* 获取类实例的父类的属性
*
* @param fields 类实例的属性
* @param clazz 类名
* @return
*/
private static List<Field> getParentClassFields(List<Field> fields, Class<?> clazz) {
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (clazz.getSuperclass() == null) {
return fields;
}
return getParentClassFields(fields, clazz.getSuperclass());
}
/**
* 获取类实例的属性值
*
* @param target 目标对象
* @param field 目标对象属性
* @return
*/
@SuppressWarnings("unchecked")
private static <T> T getFieldsValue(Object target, Field field) {
field.setAccessible(true);
T value = null;
try {
value = (T) field.get(target);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
/**
* 是否忽略属性
*
* @param fieldName 属性字段名
* @param ignoreMap 忽略属性MAP
* @return
*/
private static <T> boolean isIgnoreProperty(String fieldName, final Map<String, String> ignoreMap) {
return ignoreMap.containsKey(fieldName);
}
/**
* 是否忽略空值
*
* @param value 属性值
* @param ignoreEmptyValue 是否不把空值添加到Map中
* @return
*/
private static <T> boolean isIgnoreEmpty(T value, boolean ignoreEmptyValue) {
boolean isEmpty = (value == null || value.toString().equals(""));
boolean isCollectionEmpty = (value instanceof Collection && ((Collection<?>) value).isEmpty());
boolean isMapEmpty = (value instanceof Map && ((Map<?, ?>) value).isEmpty());
return ignoreEmptyValue && (isEmpty || isCollectionEmpty || isMapEmpty);
}
}

View File

@@ -0,0 +1,183 @@
package com.lakala.moss.util;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
/**
* @author Stephen yu
* @description: 配置文件util
* @date 2025-02-21
*/
public class PropertiesUtil {
/**
* 私有化构造函数,防止类被实例化
*/
private PropertiesUtil(String filePath, String encode) {
File file = new File(filePath);
File[] array = file.listFiles();
for(File childfile : array) {
String childFileName = childfile.getName();
if(!childFileName.endsWith("properties")) continue;
loadConfigProperties(childFileName, encode);
}
}
/**
* 存放配置文件的所有的key-value
* 以这种方式存储是为了防止多个配置文件间存在key冲突
*/
private Map<String, HashMap<String,String>> allParam = new HashMap<String, HashMap<String, String>>();
/**
* 默认的properties文件名
*/
private static final String DEFAULT_PROPERTIES_NAME = "moss-sdk.properties";
/**
* 解析properties文件默认编码
*/
private static final String DEFAULT_ENCODE = "UTF-8";
/**
* 解析properties文件编码
*/
private static String fileEncode = null;
/**
* properties文件所在的地址
*/
private static String propertiesParentPath = null;
/**
* 根据文件名称-key返回相应key的值
* 文件名默认为config.properties文件编码默认为UTF-8
*/
public static Integer getIntegerByKey(String key) {
return Integer.parseInt(getStringByKey(DEFAULT_PROPERTIES_NAME, key, DEFAULT_ENCODE));
}
/**
* 根据文件名称-key返回相应key的值文件编码默认为UTF-8
* @param fileName 文件名
* @param key properties文件中key的名称
*/
public static Integer getIntegerByKey(String fileName, String key) {
return Integer.parseInt(getStringByKey(fileName, key, DEFAULT_ENCODE));
}
/**
* 根据文件名称-key返回相应key的值
* @param fileName 文件名
* @param key properties文件中key的名称
* @param encode 文件编码
*/
public static Integer getIntegerByKey(String fileName, String key, String encode) {
return Integer.parseInt(getStringByKey(fileName, key, encode));
}
/**
* 根据文件名称-key返回相应key的值
* 文件名默认为config.properties文件编码默认为UTF-8
*/
public static Boolean getBooleanByKey(String key) {
return Boolean.parseBoolean(getStringByKey(DEFAULT_PROPERTIES_NAME, key, DEFAULT_ENCODE));
}
/**
* 根据文件名称-key返回相应key的值文件编码默认为UTF-8
* @param fileName 文件名
* @param key properties文件中key的名称
*/
public static Boolean getBooleanByKey(String fileName, String key) {
return Boolean.parseBoolean(getStringByKey(fileName, key, DEFAULT_ENCODE));
}
/**
* 根据文件名称-key返回相应key的值
* @param fileName 文件名
* @param key properties文件中key的名称
* @param encode 文件编码
*/
public static Boolean getBooleanByKey(String fileName, String key, String encode) {
return Boolean.parseBoolean(getStringByKey(fileName, key, encode));
}
/**
* 根据文件名称-key返回相应key的值
* 文件名默认为config.properties文件编码默认为UTF-8
*/
public static Long getLongByKey(String key) {
return Long.parseLong(getStringByKey(DEFAULT_PROPERTIES_NAME, key, DEFAULT_ENCODE));
}
/**
* 根据文件名称-key返回相应key的值文件编码默认为UTF-8
* @param fileName 文件名
* @param key properties文件中key的名称
*/
public static Long getLongByKey(String fileName, String key) {
return Long.parseLong(getStringByKey(fileName, key, DEFAULT_ENCODE));
}
/**
* 根据文件名称-key返回相应key的值
* @param fileName 文件名
* @param key properties文件中key的名称
* @param encode 文件编码
*/
public static Long getLongByKey(String fileName, String key, String encode) {
return Long.parseLong(getStringByKey(fileName, key, encode));
}
/**
* 根据文件名称-key返回相应key的值
* 文件名默认为config.properties文件编码默认为UTF-8
*/
public static String getStringByKey(String key){
return getStringByKey(DEFAULT_PROPERTIES_NAME, key, DEFAULT_ENCODE);
}
/**
* 根据文件名key返回value值文件编码默认为UTF-8
*/
public static String getStringByKey(String fileName, String key) {
return getStringByKey(fileName, key, DEFAULT_ENCODE);
}
/**
* 根据文件名key编码返回value值
*/
public static String getStringByKey(String fileName, String key, String encode) {
String propertiesPath = PropertiesUtil.class.getClassLoader()
.getResource(fileName).getPath().replace(fileName, "");
propertiesParentPath = propertiesPath;
fileEncode = encode;
return PropertiesUtilHolder.instance.allParam.get(fileName).get(key);
}
/**
* 静态内部类,单例模式,保证只有一个实例变量
*/
private static class PropertiesUtilHolder {
private static PropertiesUtil instance = new PropertiesUtil(propertiesParentPath, fileEncode);
}
/**
* 加载配置文件,需要进行加锁
*/
private void loadConfigProperties(String fileName, String encode) {
InputStream in = null;
try {
Properties p = new Properties();
File file = new File(fileName);
if(file.exists()) {
p.load(new FileInputStream(file));
} else {
in = PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName);
// 解决中文乱码
BufferedReader bf = new BufferedReader(new InputStreamReader(in, encode));
p.load(bf);
}
Set<Entry<Object, Object>> allKey = p.entrySet();
HashMap<String, String> paramMap = new HashMap<String, String>();
for (Entry<Object, Object> entry : allKey) {
paramMap.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
}
allParam.put(fileName, paramMap);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(in != null) in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,42 @@
package com.lakala.moss.util;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* @author Stephen yu
* @description: SSL处理类
* @date 2025-02-21
*/
public class SSLClient extends DefaultHttpClient {
public SSLClient() throws Exception {
super();
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = this.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
}
}

View File

@@ -0,0 +1,272 @@
package com.lakala.moss.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.ArrayUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author Stephen yu
* @description: 密钥工具类
* @date 2025-02-21
*/
public class SecurityUtil {
private static final Logger logger = LoggerFactory.getLogger(SecurityUtil.class);
private static final String SOLT = "0123456789ABCDEF";
private static final Provider PROVIDER = new BouncyCastleProvider();
private static final String SIGN_VERIFY_ALGORITHM = "SHA1withRSA";
private static final String ENCRYPTD_ECRYPT_ALGORITHM = "RSA/None/PKCS1Padding";
private static final int RSA_KEY_LENGHTH = 1024;
private static final String ALGORITHM = "RSA";
private SecurityUtil() {
throw new IllegalStateException("Utility class");
}
/**
* 从字符串中加载公钥
*
* @param publicKeyStr 公钥数据字符串
* @throws Exception 加载公钥时产生的异常
*/
private static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
try {
byte[] buffer = Base64.decodeBase64(publicKeyStr.getBytes(StandardCharsets.UTF_8));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
return keyFactory.generatePublic(keySpec);
} catch (Exception ex) {
logger.warn("load public key exception:", ex);
throw ex;
}
}
private static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception {
try {
byte[] buffer = Base64.decodeBase64(privateKeyStr.getBytes(StandardCharsets.UTF_8));
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
return keyFactory.generatePrivate(keySpec);
} catch (Exception ex) {
logger.warn("load private key exception:", ex);
throw ex;
}
}
/** * 用公钥验证签名的正确性 * * @param message * @param signStr * @return * @throws Exception */
public static boolean verify(String message, String signStr, String publicKeyStr) {
if (message == null || signStr == null || publicKeyStr == null) {
return false;
}
try {
PublicKey key = loadPublicKey(publicKeyStr);
Signature signetcheck = Signature.getInstance(SIGN_VERIFY_ALGORITHM);
signetcheck.initVerify(key);
signetcheck.update(message.getBytes(StandardCharsets.UTF_8));
return signetcheck
.verify(Base64.decodeBase64(signStr.getBytes(StandardCharsets.UTF_8)));
} catch (Exception ex) {
logger.warn("verify [{}] sign [{}] exception:", message, signStr, ex);
return false;
}
}
public static String sign(String message, String privateKeyStr) {
try {
PrivateKey key = loadPrivateKey(privateKeyStr);
Signature signetcheck = Signature.getInstance(SIGN_VERIFY_ALGORITHM);
signetcheck.initSign(key);
signetcheck.update(message.getBytes(StandardCharsets.UTF_8));
return new String(Base64.encodeBase64(signetcheck.sign()), StandardCharsets.UTF_8);
} catch (Exception ex) {
logger.warn("sign message [{}] exception:", message, ex);
return "";
}
}
public static String encryptBase64(String messageBase64, String publicKeyStr) {
byte[] message = Base64.decodeBase64(messageBase64.getBytes(StandardCharsets.UTF_8));
byte[] encrypted = encrypt(message, publicKeyStr);
byte[] encryptBase64 = Base64.encodeBase64(encrypted);
return new String(encryptBase64, StandardCharsets.UTF_8);
}
public static String encryptInBytesOutBase64(byte[] message, String publicKeyStr) {
byte[] encrypted = encrypt(message, publicKeyStr);
byte[] encryptBase64 = Base64.encodeBase64(encrypted);
return new String(encryptBase64, StandardCharsets.UTF_8);
}
public static String encryptInStringOutBase64(String message, String publicKeyStr) {
byte[] encrypted = encrypt(message.getBytes(StandardCharsets.UTF_8), publicKeyStr);
byte[] encryptBase64 = Base64.encodeBase64(encrypted);
return new String(encryptBase64, StandardCharsets.UTF_8);
}
public static String decryptBase64(String messageBase64, String privateKeyStr) {
byte[] message = Base64.decodeBase64(messageBase64.getBytes(StandardCharsets.UTF_8));
byte[] decrypted = decrypt(message, privateKeyStr);
byte[] decryptBase64 = Base64.encodeBase64(decrypted);
return new String(decryptBase64, StandardCharsets.UTF_8);
}
public static byte[] decryptInBase64OutBytes(String messageBase64, String privateKeyStr) {
byte[] message = Base64.decodeBase64(messageBase64.getBytes(StandardCharsets.UTF_8));
return decrypt(message, privateKeyStr);
}
public static String decryptInBase64OutString(String messageBase64, String privateKeyStr) {
byte[] message = Base64.decodeBase64(messageBase64.getBytes(StandardCharsets.UTF_8));
return new String(decrypt(message, privateKeyStr), StandardCharsets.UTF_8);
}
// ref: https://blog.csdn.net/taoxin52/article/details/53782470
public static byte[] encrypt(byte[] message, String publicKeyStr) {
if (message == null || publicKeyStr == null || message.length == 0) {
return new byte[0];
}
try {
PublicKey key = loadPublicKey(publicKeyStr);
Cipher cipher = Cipher.getInstance(ENCRYPTD_ECRYPT_ALGORITHM, PROVIDER);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptBS = null;
int plaintextLen = RSA_KEY_LENGHTH / 8 - 11;
for (int i = 0; i < message.length; i += plaintextLen) {
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(message, i, i + plaintextLen));
encryptBS = ArrayUtils.addAll(encryptBS, doFinal);
}
return encryptBS;
} catch (Exception ex) {
logger.info("encrypt message [{}] exception:", byteArrayToHexString(message), ex);
return new byte[0];
}
}
public static byte[] decrypt(byte[] message, String privateKeyStr) {
if (message == null || privateKeyStr == null || message.length == 0) {
return new byte[0];
}
try {
PrivateKey key = loadPrivateKey(privateKeyStr);
Cipher cipher = Cipher.getInstance(ENCRYPTD_ECRYPT_ALGORITHM, PROVIDER);
cipher.init(Cipher.DECRYPT_MODE, key);
int cipherTextLen = RSA_KEY_LENGHTH / 8;
byte[] decryptBS = null;
for (int i = 0; i < message.length; i += cipherTextLen) {
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(message, i, i + cipherTextLen));
decryptBS = ArrayUtils.addAll(decryptBS, doFinal);
}
return decryptBS;
} catch (Exception ex) {
logger.info("decrypt message [{}] exception:", byteArrayToHexString(message), ex);
return new byte[0];
}
}
private static String byteArrayToHexString(byte[] b) {
StringBuilder sb = new StringBuilder(64);
for (int i = 0; i < b.length; i++) {
sb.append(SOLT.charAt(b[i] >>> 4 & 0x0F));
sb.append(SOLT.charAt(b[i] & 0x0F));
}
return sb.toString();
}
/**
* 哈希函数
*
* @param algorithm String MD5/SHA
* @param b byte[]
* @return byte[]
*/
private static byte[] hashData(String algorithm, byte[] b) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(b);
return md.digest();
}
/**
* 制作MD5
*
* @param source String
* @return byte[]
*/
public static String md5(String source) {
return md5(source.getBytes(StandardCharsets.UTF_8));
}
public static String md5(byte[] b) {
try {
byte[] a = hashData("MD5", b);
return byteArrayToHexString(a);
} catch (NoSuchAlgorithmException ex) {
logger.warn("calculate [{}] md5 exception:", byteArrayToHexString(b));
return "";
}
}
public static String getSignSrc(Map<String, String> secMap, boolean isUseKey, String split) {
StringBuilder content = new StringBuilder(512);
List<String> keys = new ArrayList<>(secMap.keySet());
Collections.sort(keys);
for (int i = 0; i < keys.size(); i++) {
Object key = keys.get(i);
if ("sign".equals(key)) {
continue;
}
Object value = secMap.get(key);
if (value instanceof String) {
if (isUseKey) {
content.append((i == 0 ? "" : split) + key + "=" + (String) value);
} else {
content.append((i == 0 ? "" : split) + (String) value);
}
}
}
return content.toString();
}
public static String getSignSrcSkipNull(Map<String, String> secMap, boolean isUseKey,
String split) {
StringBuilder content = new StringBuilder(512);
List<String> keys = new ArrayList<>(secMap.keySet());
Collections.sort(keys);
for (int i = 0; i < keys.size(); i++) {
Object key = keys.get(i);
if ("sign".equals(key)) {
continue;
}
Object value = secMap.get(key);
if (value instanceof String) {
if ("".equals(value)) {
continue;
}
if (isUseKey) {
content.append((i == 0 ? "" : split) + key + "=" + (String) value);
} else {
content.append((i == 0 ? "" : split) + (String) value);
}
}
}
return content.toString();
}
}

View File

@@ -0,0 +1,8 @@
api.versionId = 1.0
api.businessChannel = C00000001
api.channelId = API
api.order.url = https://moss.wsmsd.cn/ord-api/unified/v3
mer.pub.key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC/g7kWVjxMV1f0CTqp4GxCwRCB6zIWOeclSvqycRUa2YjYYd92bQn+KtpogYLuzaKT0ns24wCWVar+pVx7cokG2mJsQfe4epZQcq+tBgZcIE6nSVBp9dfWMX8w6AtT3QLURqzP9tMFXrysisKbdy54kNOUPcGWC0rg11oK6BvXbwIDAQAB
mer.pri.key=MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL+DuRZWPExXV/QJOqngbELBEIHrMhY55yVK+rJxFRrZiNhh33ZtCf4q2miBgu7NopPSezbjAJZVqv6lXHtyiQbaYmxB97h6llByr60GBlwgTqdJUGn119YxfzDoC1PdAtRGrM/20wVevKyKwpt3LniQ05Q9wZYLSuDXWgroG9dvAgMBAAECgYBh8o6A3A3uxWUYTHgSVdNIuNEmgRGWyHptWlGpXah7mPIiKLxPJylLMsONW1+JnuYdUDLwOV0dhib0IcKQ6F0nnq7CYqyPr6nL32pu0bGQbxjl6PgtYD0qc85AMHOJ5/NYujSKzW+HxByDNa6u7+m1LXDIgVm2qhiy/xYaKX58wQJBAPKPeStpZn2hzMjhmL6X0A1Xvvr+LaUgZHVOC/AA1eoGcGCPmmGHETMU1e7+ZW1Ti/JErABOqrI7bQTVHascdLECQQDKIDRJqP0CbXvJh5ThpinwpVRJ4BxTUxRs+9lCQDZ23SmFE0HhSgUZL4EMsrdPNzmdH2W56TYy3Ivpyl/SapYfAkEA5b9FuvvDiz3FFYSxQ93Rv8Gb8Gru2xgabw20uuhftaHRsXRzeusPPH4AwLWPZoUa6idnb4cToWwuL8SYrGlwkQJADtwDPA8SWqVV3mD7TwN6PdjJs4yoSG/pJoH1XOt/lYl4zfG2fCuG6G0Xnald1JMIx0ZRojNE6sRP/OYF2WBAnQJBAMIAdErHJLrKNo2ZSuJj9hrg51f540J95BjOYkXct25vX4ih3W2981gH08K+D4sk/kOLyTe1FOozJZLjjgSHfCs=
moss.pub.key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI/54uIovSxoDNwK+RkdXSnIwjlKPZBFcv6kYyPV9A8iyCgwcIfydXpA2ueCecyg/xPfLbFfiZpQsOUJvebtoOzAKGK9F48G7yGOG/ZhfS1ZM5LOWSVpy8sqMj8YgAhK42ZlIEivBwSdlwKkFsjDw02P57McfC0VvyVUsd/68cvwIDAQAB

View File

@@ -0,0 +1,173 @@
package com.lakala.moss;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.lakala.moss.api.ApiReq;
import com.lakala.moss.api.ApiRes;
import com.lakala.moss.api.params.LocationInfo;
import com.lakala.moss.api.request.*;
import com.lakala.moss.api.response.*;
import com.lakala.moss.service.IMossApiService;
import com.lakala.moss.service.impl.MossApiServiceImpl;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Type;
/**
* @author Stephen yu
* @description: 测试类
* @date 2025-02-21
*/
public class MossApiTest {
private static final Logger logger = LoggerFactory.getLogger(MossApiTest.class);
// 订单支付-拉起收银台
@Test
public void testOrderPayCounter(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
IMossApiService mossApi = new MossApiServiceImpl();
OrderPayReq req = new OrderPayReq();
req.setOrder_no("DemoMOSS20250225000001");
req.setTotal_amount("1");
req.setMer_no("M00000036");
req.setRemark("测试");
req.setNotify_url("");
req.setPay_scene("0");
req.setAccount_type("ALIPAY,WECHAT,UQRCODEPAY");
req.setSubject("测试标题");
req.setOrder_eff_time("300");
req.setCallback_url("https://www.baidu.com/");
ApiRes<OrderPayRes> res = mossApi.OrderPay(req);
logger.info("res={}",gson.toJson(res));
}
// 订单支付-独立支付
@Test
public void testOrderPay(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
IMossApiService mossApi = new MossApiServiceImpl();
OrderPayReq req = new OrderPayReq();
req.setOrder_no("DemoMOSS202502250000012");
req.setTotal_amount("1");
req.setMer_no("M00000036");
req.setRemark("测试");
req.setNotify_url("");
req.setPay_scene("1");
req.setAccount_type("UQRCODEPAY");
req.setSubject("测试标题");
req.setOrder_eff_time("15");
req.setTrans_type("51");
req.setUser_id("olpr-0sYaDrxaT5GmLUgUenVcDPo");
LocationInfo location_info = new LocationInfo();
location_info.setRequest_ip("36.45.36.95");
location_info.setBase_station("00 6361 58130");
location_info.setLocation("+37.123456789,-121.123456789");
req.setLocation_info(location_info);
ApiRes<OrderPayRes> res = mossApi.OrderPay(req);
logger.info("res={}",gson.toJson(res));
}
// 订单查询
@Test
public void testOrderQryList(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
IMossApiService mossApi = new MossApiServiceImpl();
OrderQryListReq req = new OrderQryListReq();
req.setOrder_no("DemoMOSS20250225000001");
req.setPay_serial("0bf31ad8e73e4e548960599b70d9b591");
ApiRes<OrderQryListRes> res = mossApi.OrderQryList(req);
logger.info("res={}",gson.toJson(res));
}
// 订单关单
@Test
public void testOrderCls(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
IMossApiService mossApi = new MossApiServiceImpl();
OrderClsReq req = new OrderClsReq();
req.setOrigin_order_no("DemoMOSS20250225000001");
LocationInfo location_info = new LocationInfo();
location_info.setRequest_ip("36.45.36.95");
location_info.setBase_station("00 6361 58130");
location_info.setLocation("+37.123456789,-121.123456789");
req.setLocation_info(location_info);
ApiRes<OrderClsRes> res = mossApi.OrderCls(req);
logger.info("res={}",gson.toJson(res));
}
// 订单退款
@Test
public void testOrderRefund(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
IMossApiService mossApi = new MossApiServiceImpl();
OrderRefundReq req = new OrderRefundReq();
req.setOrder_no("RefundMOSS20250225000001");
req.setOrigin_order_no("DemoMOSS20250225000001");
req.setOrigin_pay_serial("0bf31ad8e73e4e548960599b70d9b591");
req.setRefund_amount("1");
req.setRefund_reason("测试退款");
LocationInfo location_info = new LocationInfo();
location_info.setRequest_ip("36.45.36.95");
location_info.setBase_station("00 6361 58130");
location_info.setLocation("+37.123456789,-121.123456789");
req.setLocation_info(location_info);
ApiRes<OrderRefundRes> res = mossApi.OrderRefund(req);
logger.info("res={}",gson.toJson(res));
}
// 订单查询-退款
@Test
public void testOrderQryRefund(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
IMossApiService mossApi = new MossApiServiceImpl();
OrderQryListReq req = new OrderQryListReq();
req.setOrder_no("RefundMOSS20250225000001");
ApiRes<OrderQryListRes> res = mossApi.OrderQryList(req);
logger.info("res={}",gson.toJson(res));
}
// 订单通知
@Test
public void testOrderNotice(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
Type type = new TypeToken<ApiReq<OrderNoticeReq>>() {}.getType();
IMossApiService mossApi = new MossApiServiceImpl();
String request = "{\"head\":{\"requestTime\":\"20250227161640\",\"versionId\":\"1.0\",\"org\":\"000000000001\",\"serviceSn\":\"94452612AAB545149ED020431DE5C5F3\",\"serviceId\":\"lfops.moss.order.ntc\",\"channelId\":\"01\",\"businessChannel\":\"C00000001\",\"sid\":\"94452612AAB545149ED020431DE5C5F3\",\"accessToken\":\"\"},\"sign\":\"iZu2qma07bCjelm5jMuhtoXXG5/uqPSE/TgCGU6YerVpt7fwIqX9Y+wBTdZr8EXZF4CiU79usuVOi18SxvbXORXMsDUUlLL8E5eIvjh/xuaiYC/IXeOMC1CM+IbD9ql9n4/2E3f/wn5+OOtOgZM/HeVME7lsyndGvx6Iqof+kn0=\",\"requestEncrypted\":\"l+ULAxGYu3FFUIxAvY5h8f3qMoolXISOzdKp80zR2Jc016IQtVfKikWq6BPAaqzzLgL4rIWrQfr316iQVRQcN3OhIQS7ViRseeE7S1NVXSPWhypVWwnas6tfiURYqm+yydIiQ0e0FvLPIR6Hf909d3QdiDWoRQFXyzIVwjTnPbARk01NccPOLk/0HtEqoIPbmI/hOQYoxzY22Dj+WetAcRNdzaOL8vbFByTpHYSKu2teg+irEKLbs4VYpi0husKAT6eqyrX8ZTxMCeGhwsiLku68BOz7ddeA7aV/JJDOXDtd/qGjOhQIZL8anMbaN9CGY3xodCweGXRcYInc6frV0DhHu7FKO60//Q6zMwVwPp4qcA9mLpvclC37uE3CD5JJaOdyfVV2f4NgFa5lnFBYRXIicWTTQlPaNgZw4n9j61M7eWhFFzPqwvcGxcYxCcYrVmVZNr/KGHV4hGWuvjI9tiPJ1Uu5ZpHwkL75H+921uJLDmoshmD6VlgfPW4mmXY1QeeUTnQVHiIRN3BQ/c4ZjiAcxLEpQV4a26Vh5PDviQM0C6kZdLSGFmbMsMawcHV7LfzMbi2PbGGwWs/+sXKbb6m9bW1yH7sUsT9ScA0oJCDeRtpAO4yfnejU4b9Jj11vD9Wi7hilF1SMKAHKl3zzzmtRaN74oAYDCz5Zuo9bqZxJ/0ktBFfnIZ5aCUAiW6IFeaRsmQ2jXTO7JbDSfX5LfgA0lE1F7OV/Q7KC4TaVyz2XQ3FNztB9xDPY2uaNdetRIYk+71/cXmYcUIJPeqt0FcP7DXDzAKBkWbZh7MvC/7pDwBm6oW06HKDWiK2qJjRYi8k9Xzo+Q2T0nBpLLdMVKIDmEo1hJm13PC8ovl68kSvXEMSqs0D6snXxI+Op9QvkVjr3Q6fEbl3gKofPnssTzkmYLqK5hQ4AamiMNh5tC7fyd9T+w88iz6uuxQ/WcJ/q+FA6nLcjbkAouWiubU1ZCdYux9QkRaG4iZUJZ0Vo7b/7s1yg86+GjoJ2nsETU8fX\"}";
ApiReq<OrderNoticeReq> req = gson.fromJson(request, type);
ApiRes<OrderNoticeRes> res = mossApi.OrderNotice(req);
logger.info("res={}",gson.toJson(res));
}
// 申请对账单
@Test
public void testOrderChkApply(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
IMossApiService mossApi = new MossApiServiceImpl();
OrderChkApplyReq req = new OrderChkApplyReq();
req.setTran_date("20250225");
req.setApply_order_no("AONMOSS20250226000003");
ApiRes<OrderChkApplyRes> res = mossApi.OrderChkApply(req);
logger.info("res={}",gson.toJson(res));
}
// 用户标识查询
@Test
public void testUseridQry(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
IMossApiService mossApi = new MossApiServiceImpl();
UseridQryReq req = new UseridQryReq();
req.setMer_no("M00000036");
req.setAuth_code("5oqA5pyv5pSv5oyB5Zui6Zif6Ze16Z2S");
req.setApp_up_identifier("UnionPay/1.0 ICBCeLife");
ApiRes<UseridQryRes> res = mossApi.UseridQry(req);
logger.info("res={}",gson.toJson(res));
}
// 对账单下载
@Test
public void testChkDownload(){
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
IMossApiService mossApi = new MossApiServiceImpl();
String downUrl = "https://jrt.wsmsd.cn/lfpf-sch/chkfile/download?apply_order_no=AONMOSS20250226000003&file_name=F20250225_TRAN_CHECK_C00000001_01.xls";
String localDir = "d:/localpath/data/";
String localFileName = "F20250225_TRAN_CHECK_C00000001_01.xls";
boolean res = mossApi.ChkDownload(downUrl,localDir,localFileName);
logger.info("res={}",res);
}
}