diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/ApiFrom.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/ApiFrom.java index 8597f18c57..d63bebe671 100644 --- a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/ApiFrom.java +++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/ApiFrom.java @@ -7,7 +7,8 @@ import lombok.Getter; @Getter public enum ApiFrom { LianTong(1L,"联通Api"), - GuangZhouDX(2L,"广州电信Api");; + GuangZhouDX(2L,"广州电信Api"), + HaiNanDX(3L,"海南电信Api"); private final Long id; private final String name; } diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/ApiHaiNanDXService.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/ApiHaiNanDXService.java new file mode 100644 index 0000000000..e6da6d4768 --- /dev/null +++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/ApiHaiNanDXService.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.haoka.api; + +import cn.iocoder.yudao.module.haoka.api.hainandianxin.HaiNanDianXinApi; +import com.mashape.unirest.http.exceptions.UnirestException; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Service +public class ApiHaiNanDXService extends ApiConfigService { + + public static final String Key_url = "url"; + public static final String Key_appCode = "appCode"; + public static final String Key_abilityCod = "abilityCode"; + public static final String Key_md5Key = "md5Key"; + public static final String Key_publicKey = "publicKey"; + public static final String Key_privateKey = "privateKey"; + + private HaiNanDianXinApi.HaiNanDianXinApiConfig getConfig() { + Map devConfig = this.getDevConfig(ApiFrom.HaiNanDX); + + String url = devConfig.get(Key_url); + String appCode = devConfig.get(Key_appCode); + String abilityCode = devConfig.get(Key_abilityCod); + String md5Key = devConfig.get(Key_md5Key); + String publicKey = devConfig.get(Key_publicKey); + String privateKey = devConfig.get(Key_privateKey); + HaiNanDianXinApi.HaiNanDianXinApiConfig config = new HaiNanDianXinApi.HaiNanDianXinApiConfig(); + config.setUrl(url); + config.setAppCode(appCode); + config.setAbilityCode(abilityCode); + config.setMd5Key(md5Key); + config.setPublicKey(publicKey); + config.setPrivateKey(privateKey); + return config; + } + + public HaiNanDianXinApi.HaiNanResponseInfo + qryNbrList(HaiNanDianXinApi.QryNbrListRequest param) throws UnirestException { + return HaiNanDianXinApi.qryNbrList(this.getConfig(), param); + } + + public HaiNanDianXinApi.HaiNanResponseInfo + fraudCheck(HaiNanDianXinApi.FraudCheckRequest param) throws UnirestException { + return HaiNanDianXinApi.fraudCheck(this.getConfig(), param); + } + + public HaiNanDianXinApi.HaiNanResponseInfo + queryOrderInfo(HaiNanDianXinApi.QueryOrderInfoRequest param) throws UnirestException { + return HaiNanDianXinApi.queryOrderInfo(this.getConfig(), param); + } + + public HaiNanDianXinApi.HaiNanResponseInfo + getLogisticsTrajectory(HaiNanDianXinApi.GetLogisticsTrajectoryRequest param) throws UnirestException { + return HaiNanDianXinApi.getLogisticsTrajectory(this.getConfig(), param); + } + + public HaiNanDianXinApi.HaiNanResponseInfo + synOrderInfo(HaiNanDianXinApi.SynOrderInfoRequest param) throws UnirestException { + return HaiNanDianXinApi.synOrderInfo(this.getConfig(), param); + } +} diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/hainandianxin/HaiNanDianXinApi.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/hainandianxin/HaiNanDianXinApi.java new file mode 100644 index 0000000000..75a14f6d1f --- /dev/null +++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/hainandianxin/HaiNanDianXinApi.java @@ -0,0 +1,341 @@ +package cn.iocoder.yudao.module.haoka.api.hainandianxin; + +import cn.iocoder.yudao.module.haoka.api.liantong.util.StringUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.TypeReference; +import com.mashape.unirest.http.HttpResponse; +import com.mashape.unirest.http.Unirest; +import com.mashape.unirest.http.exceptions.UnirestException; +import lombok.Data; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + + +/** + * 海南电信互联网支撑平台号卡接口工具类 + */ +public class HaiNanDianXinApi { + + + @Data + public static class HaiNanDianXinApiConfig { + private String url = "https://openeop.dcoos.189.cn:8100/serviceAgent/rest/uop-web/executeEnhanced"; + private String appCode = "your_app_code"; // 合作商编码,由海南电信互联网支撑平台提供 + private String abilityCode = "your_ability_code"; // 能力编码,由海南电信互联网支撑平台提供 + private String md5Key = "your_md5_key"; // 平台分配的密钥 + private String publicKey = "your_rsa_public_key"; // RSA加密公钥 + private String privateKey = ""; // RSA 私钥 + } + + @Data + public static class HaiNanResponseInfo { + private T data; + private String biz; + private String code; + private String errMsg; + private String resTime; + } + + /** + * 生成 x-auth 请求头 + * + * @param abilityCode 能力编码 + * @param requestBody 请求体(未加密的原始 JSON 字符串) + * @return x-auth 请求头 + */ + private static String generateXAuthHeader(HaiNanDianXinApiConfig config, String abilityCode, String requestBody) { + SimpleDateFormat dtf = new SimpleDateFormat("yyyyMMddHHmmss"); + String reqTime = dtf.format(new Date()); + String transactionId = config.appCode + abilityCode + reqTime + UUID.randomUUID().toString().replace("-", ""); + String sign = UopMD5Utils.encryptByMD5_utf8(config.appCode + abilityCode + transactionId + config.md5Key + requestBody).toLowerCase(); + return config.appCode + ";" + abilityCode + ";" + transactionId + ";" + sign + ";" + reqTime; + } + + /** + * 防诈校验接口查询 + * + * @param request 防诈校验请求参数 + * @return 防诈校验返回结果 + * @throws UnirestException 请求异常 + */ + public static HaiNanResponseInfo fraudCheck(HaiNanDianXinApiConfig config, FraudCheckRequest request) throws UnirestException { + return doPost(config, "fraudCheck", request, FraudCheckResponse.class); + } + + /** + * 号码查询列表 + * + * @param request 号码查询列表请求参数 + * @return 号码查询列表返回结果 + * @throws UnirestException 请求异常 + */ + public static HaiNanResponseInfo qryNbrList(HaiNanDianXinApiConfig config, QryNbrListRequest request) throws UnirestException { + return doPost(config, "qryNbrList", request, QryNbrListResponse.class); + } + + /** + * 订单信息查询 + * + * @param request 订单信息查询请求参数 + * @return 订单信息查询返回结果 + * @throws UnirestException 请求异常 + */ + public static HaiNanResponseInfo queryOrderInfo(HaiNanDianXinApiConfig config, QueryOrderInfoRequest request) throws UnirestException { + return doPost(config, "queryOrderInfo", request, QueryOrderInfoResponse.class); + } + + /** + * 物流轨迹查询 + * + * @param request 物流轨迹查询请求参数 + * @return 物流轨迹查询返回结果 + * @throws UnirestException 请求异常 + */ + public static HaiNanResponseInfo getLogisticsTrajectory(HaiNanDianXinApiConfig config, GetLogisticsTrajectoryRequest request) throws UnirestException { + return doPost(config, "getLogisticsTrajectory", request, GetLogisticsTrajectoryResponse.class); + } + + /** + * 号卡订单收敛 + * + * @param request 号卡订单收敛请求参数 + * @return 号卡订单收敛返回结果 + * @throws UnirestException 请求异常 + */ + public static HaiNanResponseInfo synOrderInfo(HaiNanDianXinApiConfig config, SynOrderInfoRequest request) throws UnirestException { + return doPost(config, "synOrderInfo", request, SynOrderInfoResponse.class); + } + + /** + * 通用 POST 请求方法 + * + * @param method 接口方法名 + * @param param 请求参数 + * @param rClass 返回结果类型 + * @param 返回结果泛型 + * @param

请求参数泛型 + * @return 返回结果 + * @throws UnirestException 请求异常 + */ + private static HaiNanResponseInfo doPost(HaiNanDianXinApiConfig config, String method, P param, Class rClass) throws UnirestException { + String jsonString = JSON.toJSONString(param); + String encryptedBody = UopRSAUtils.encryptByPublicKey(jsonString, config.publicKey); + String xAuthHeader = generateXAuthHeader(config, method, jsonString); + HttpResponse response = Unirest.post(config.url) + .header("Content-Type", "application/json") + .header("x-auth", xAuthHeader) + .body(encryptedBody) + .asString(); + return dealResponse(response, rClass); + } + + /** + * 处理响应结果 + * + * @param response HTTP 响应 + * @param tClass 返回结果类型 + * @param 返回结果泛型 + * @return 返回结果 + */ + private static HaiNanResponseInfo dealResponse(HttpResponse response, Class tClass) { +// int status = response.getStatus(); +// if (status != 200) { +// return null; +// } + String body = response.getBody(); + + HaiNanResponseInfo haiNanResponseInfo = JSON.parseObject(body, new TypeReference>() { + }); + String biz = haiNanResponseInfo.getBiz(); + if (StringUtils.isNotEmpty(biz)) { + String bizDecrypt = UopRSAUtils.decryptByPrivateKey(body, biz); + // T t = JSON.parseObject(bizDecrypt, tClass); + T t = JSON.parseObject(body, new TypeReference() { + }); + haiNanResponseInfo.setData(t); + } + + + return haiNanResponseInfo; + } + + /** + * 防诈校验请求参数类 + */ + @Data + public static class FraudCheckRequest { + private String custName; // 客户名称 + private String custCertNo; // 身份证号 + private String province; // 省份(如:海南省) + private String city; // 市(如:海口市) + private String county; // 区县(如:龙华区) + private String street; // 街道(如:龙华街道) + private String detailedAddr; // 详细地址 + private String consignee; // 收货人 + private String receiContact; // 收货联系手机号 + private String scenarioCode; // 场景编码 + } + + /** + * 防诈校验返回结果类 + */ + @Data + public static class FraudCheckResponse { + private String code; // 状态编码:0:校验通过,可以下单;其他:校验不通过,不能下单 + private String errMsg; // 失败原因 + private String biz; // 成功返回报文 + private String resTime; // 请求返回时间 + } + + /** + * 号码查询列表请求参数类 + */ + @Data + public static class QryNbrListRequest { + private String goodsId; // 商品编码 + } + + /** + * 号码查询列表返回结果类 + */ + @Data + public static class QryNbrListResponse { + private String code; // 结果编码 2000 成功 1400 无效的销售品 id 9996 其他异常 + private String errMsg; // 相关信息说明 + private String biz; // 成功返回报文 + private String resTime; // 请求返回时间 + } + + /** + * 订单信息查询请求参数类 + */ + @Data + public static class QueryOrderInfoRequest { + private String queryType; // 查询类型(1:电渠业务订单号;2:接入方信息) + private String orderCode; // 电渠业务订单号 + private String openNo; // 第三方流水号(查询类型为2时必填) + private String devStaffCode; // 发展工号(查询类型为2时必填) + private String devMobile; // 发展手机号(查询类型为2时必填) + } + + /** + * 订单信息查询返回结果类 + */ + @Data + public static class QueryOrderInfoResponse { + private String code; // 状态编码:0:成功;-1:失败 + private String errMsg; // 失败原因 + private String biz; // 成功返回报文 + private String resTime; // 请求返回时间 + } + + /** + * 物流轨迹查询请求参数类 + */ + @Data + public static class GetLogisticsTrajectoryRequest { + private String orderCode; // 订单编码 + private String logisticNbr; // 物流单号 + } + + /** + * 物流轨迹查询返回结果类 + */ + @Data + public static class GetLogisticsTrajectoryResponse { + private String code; // 状态编码:0:成功,返回0既是代表有物流轨迹返回,否则无 + private String errMsg; // 失败原因 + private String biz; // 成功返回报文 + private String resTime; // 请求返回时间 + } + + /** + * 产品信息类 + */ + @Data + public static class OrderProdInst { + public String prodName; // 产品名称 + public String prodInstAct; // 产品动作:ADD/DEL/EDIT + } + + /** + * 物流信息类 + */ + @Data + public static class OrderLogisticInfo { + public String receiverName; // 收货人 + public String receiverAddr; // 收获地址(寄送地址) + public String receiverPhone; // 收获人电话(联系电话) + public String receiverType; // 收货方式(10:物流寄送;11:面对面;12:送货上门;13:京东到家;14:京东配送;不传默认为10) + public String provinceAddr; // 省级地址(收货方式为13、14时必填) + public String cityAddr; // 市级地址(收货方式为13、14时必填) + public String areaAddr; // 区县地址(收货方式为13、14时必填) + public String streetAddr; // 城镇/街道地址 + } + + /** + * 客户信息类 + */ + @Data + public static class OrderBusiInfo { + public String custName; // 入网姓名 + public String custCertType; // 入网证件类型:默认10 身份证号码 + public String custCertNo; // 入网证件号码 + public String custAddr; // 入网证件地址 + public String accNbr; // 入网号码(要送当前办理的业务号码),宽带新装无需该节点 + public String regionAddr; // 所在省 / 市 / 县 + public String detailAddr; // 详细地址(装机地址) + public String jthtNo; // 集团活体流水,接入方有能力接入集团情况,才需要提供 + public String openId; // 微信openId + public String addrId; // 地址Id(宽带新装实时单需传值,调用5.15、5.16接口获取) + public String exchId; // 支局Id(宽带新装实时单需传值,调用5.15、5.16接口获取) + public String measureId; // 测量室Id(宽带新装实时单需传值,调用5.15、5.16接口获取) + public String townFlag; // 城乡标识(宽带新装实时单需传值,调用5.15、5.16接口获取) + } + + /** + * 支付信息类 + */ + @Data + public static class OrderPayInfo { + public String ordPayType; // 支付类型 10、微信 11、支付宝 12、翼支付 13、银行卡 14、打入话费 + public String ordPayMethod; // 支付方法(宽带新装传11) 10、在线支付 11、先装后付 12、话费抵扣 + public String ordPayMoney; // 支付金额 + public String ordPayStatus; // 支付状态(1000:待支付 1100:已支付) + } + + /** + * 号卡订单收敛请求参数类 + */ + @Data + public static class SynOrderInfoRequest { + private String orderType; // 订单类型,28:新装天翼(实时),26:宽带新装(甩单) + private String orderAmount; // 订购金额(分) + private String openNo; // 第三方流水 + private String statusCd; // 流程环节(宽带新装预约单传1500,宽带新装实时单传3100) + private String orderDate; // 受理时间yyyy-mm-dd HH:mm:ss + private String orderArea; // 订单区域, 海南目前默认只有一个本地网460 + private OrderProdInst orderProdInst; // 订购的产品信息 + private OrderLogisticInfo orderLogisticInfo; // 物流信息 + private OrderBusiInfo orderBusiInfo; // 客户信息 + private OrderPayInfo orderPayInfo; // 支付信息 + private String busiScenarioCode; // 场景编码 + private String devStaffCode; // 发展工号 + private String devMobile; // 发展手机号 + private String remark; // 订单备注 + } + + /** + * 号卡订单收敛返回结果类 + */ + @Data + public static class SynOrderInfoResponse { + private String resultCode; // 1000:成功 其他值:失败 + private String codeMessage; // 原因(失败时返回) + private String orderCode; // 订单编码(成功时返回) + private String orderSerialNo; // 外系统单号(代理商不需要) + private String preOrderNo; // 外系统单号(代理商不需要) + } +} diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/hainandianxin/UopMD5Utils.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/hainandianxin/UopMD5Utils.java new file mode 100644 index 0000000000..73969ce6e8 --- /dev/null +++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/hainandianxin/UopMD5Utils.java @@ -0,0 +1,164 @@ +package cn.iocoder.yudao.module.haoka.api.hainandianxin; + +import java.security.MessageDigest; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.UUID; + +/** + * @author LAIYONGMIN@FFCS.CN + * @ClassName: UOPMD5Utils + * @Description: MD5工具类 + * @date 2017年9月4日 上午9:57:15 + */ +public class UopMD5Utils { + + /** + * MD5 加密 + * + * @param src + * @return + */ + public static String encryptByMD5(String src) { + if (src == null) { + return null; + } + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(src.getBytes()); + return byte2hex(md5.digest()); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 二进制转十六进制 + * + * @param b + * @return + */ + private static String byte2hex(byte[] b) { + String hs = ""; + String stmp = ""; + for (int n = 0; n < b.length; n++) { + stmp = (Integer.toHexString(b[n] & 0XFF)); + if (stmp.length() == 1) { + hs = hs + "0" + stmp; + } else { + hs = hs + stmp; + } + } + return hs.toUpperCase(); + } + + public static void main(String[] args) { + String appCode = "nblh"; + String abilityCode = "checkWaistOrder"; + SimpleDateFormat dtf = new SimpleDateFormat("yyyyMMddHHmmss"); + String transactionId = appCode + abilityCode + dtf.format(new Date()) + UUID.randomUUID(); + String md5Key = "密钥"; + String uri = "/agent/openapi/waist/check"; + String body = "{\"cityCode\": \"002034001\",\"contactNumber\": \"15858333480\",\"countyCode\": \"002034001005\",\"custCertNo\": \"113405196802181122\",\"custName\": \"华云\",\"detailAddr\": \"广州塔大厦llq04s6d\",\"provinceCode\": \"002034\",\"saleNo\": \"1043\",\"supplierCode\": \"nxdx\"}"; + String origin = appCode + abilityCode + transactionId + md5Key + uri + body; + System.out.println(origin); + String sign1 = UopMD5Utils.encryptByMD5_utf8(origin).toLowerCase(Locale.ROOT); + System.out.println(sign1); + } + + + /** + * MD5 加密 + * + * @param src + * @return + */ + public static String encryptByMD5_utf8(String src) { + if (src == null) { + return null; + } + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(src.getBytes("UTF-8")); + return byte2hex(md5.digest()); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 小程序支付生成MD5工具 + */ + private static class MD5Util { + private static String byteArrayToHexString(byte b[]) { + StringBuffer resultSb = new StringBuffer(); + for (int i = 0; i < b.length; i++) { + resultSb.append(byteToHexString(b[i])); + } + return resultSb.toString(); + } + + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) { + n += 256; + } + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String MD5Encode(String origin, String charsetname) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if (charsetname == null || "".equals(charsetname)) { + resultString = byteArrayToHexString(md.digest(resultString + .getBytes())); + } else { + resultString = byteArrayToHexString(md.digest(resultString + .getBytes(charsetname))); + } + } catch (Exception exception) { + } + return resultString; + } + + private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; + + } + + public static String MD5min(String str) { + String result = ""; + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update((str).getBytes("UTF-8")); + byte b[] = md5.digest(); + + int i; + StringBuffer buf = new StringBuffer(""); + + for (int offset = 0; offset < b.length; offset++) { + i = b[offset]; + if (i < 0) { + i += 256; + } + if (i < 16) { + buf.append("0"); + } + buf.append(Integer.toHexString(i)); + } + result = buf.toString(); + return result; + } catch (Exception e) { + return null; + } + + } + +} diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/hainandianxin/UopRSAUtils.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/hainandianxin/UopRSAUtils.java new file mode 100644 index 0000000000..6456684b68 --- /dev/null +++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/api/hainandianxin/UopRSAUtils.java @@ -0,0 +1,238 @@ +package cn.iocoder.yudao.module.haoka.api.hainandianxin; + + + +import javax.crypto.Cipher; +import java.io.ByteArrayOutputStream; +import java.security.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @Description: RSA加解密工具类 + * @Author: ffchenxiaodong + * @Date: 2023/1/27 10:12 + * @Vsersion: 1.0 + */ +public class UopRSAUtils { + + /** + * 定义加密方式 + */ + public static final String KEY_RSA = "RSA"; + + /** + * 定义公钥关键词 + */ + public static final String KEY_RSA_PUBLICKEY = "RSAPublicKey"; + + /** + * 定义私钥关键词 + */ + public static final String KEY_RSA_PRIVATEKEY = "RSAPrivateKey"; + + /** + * ** + * RSA最大加密大小 + */ + private final static int MAX_ENCRYPT_BLOCK = 117; + + /** + * ** + * RSA最大解密大小 + */ + private final static int MAX_DECRYPT_BLOCK = 128; + + + /** + * 公钥加密 + * + * @param encryptingStr + * @param publicKeyStr + * @return + */ + public static String encryptByPublicKey(String encryptingStr, String publicKeyStr) { + try { + // 将公钥由字符串转为UTF-8格式的字节数组 + byte[] publicKeyBytes = decryptBASE64(publicKeyStr); + // 获得公钥 + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes); + // 取得待加密数据 + byte[] data = encryptingStr.getBytes("UTF-8"); + KeyFactory factory; + factory = KeyFactory.getInstance(KEY_RSA); + PublicKey publicKey = factory.generatePublic(keySpec); + // 对数据加密 + Cipher cipher = Cipher.getInstance(factory.getAlgorithm()); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + // 返回加密后由Base64编码的加密信息 + int inputLen = data.length; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int offSet = 0; + byte[] cache; + int i = 0; + // 对数据分段解密 + while (inputLen - offSet > 0) { + if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { + cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); + } else { + cache = cipher.doFinal(data, offSet, inputLen - offSet); + } + out.write(cache, 0, cache.length); + i++; + offSet = i * MAX_ENCRYPT_BLOCK; + } + byte[] decryptedData = out.toByteArray(); + out.close(); + return replaceBlank(encryptBASE64(decryptedData)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 私钥解密 + * + * @param encryptedStr + * @param privateKeyStr + * @return + */ + public static String decryptByPrivateKey(String encryptedStr, String privateKeyStr) { + try { + // 对私钥解密 + byte[] privateKeyBytes = decryptBASE64(privateKeyStr); + // 获得私钥 + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); + // 获得待解密数据 + byte[] data = decryptBASE64(encryptedStr); + KeyFactory factory = KeyFactory.getInstance(KEY_RSA); + PrivateKey privateKey = factory.generatePrivate(keySpec); + // 对数据解密 + Cipher cipher = Cipher.getInstance(factory.getAlgorithm()); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + // 返回UTF-8编码的解密信息 + int inputLen = data.length; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int offSet = 0; + byte[] cache; + int i = 0; + // 对数据分段解密 + while (inputLen - offSet > 0) { + if (inputLen - offSet > MAX_DECRYPT_BLOCK) { + cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK); + } else { + cache = cipher.doFinal(data, offSet, inputLen - offSet); + } + out.write(cache, 0, cache.length); + i++; + offSet = i * MAX_DECRYPT_BLOCK; + } + byte[] decryptedData = out.toByteArray(); + out.close(); + return replaceBlank(new String(decryptedData, "UTF-8")); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + + /** + * 解决编码问题,去掉换行 + * @param str + * @return + */ + public static String replaceBlank(String str) { + String dest = ""; + if (str != null) { + Pattern p = Pattern.compile("\t|\r|\n"); + Matcher m = p.matcher(str); + dest = m.replaceAll(""); + } + return dest; + } + + /** + * 生成RSA公私钥对 + * @return + * @throws Exception + */ + public static Map generateRSAKeyPlain() throws Exception { + //获得对象 KeyPairGenerator 参数 RSA 1024个字节 + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_RSA); + keyPairGen.initialize(1024); + //通过对象 KeyPairGenerator 获取对象KeyPair + KeyPair keyPair = keyPairGen.generateKeyPair(); + //通过对象 KeyPair 获取RSA公私钥对象RSAPublicKey RSAPrivateKey + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); + //公私钥对象存入map中 + Map keyMap = new HashMap(2); + keyMap.put(KEY_RSA_PUBLICKEY, publicKey); + keyMap.put(KEY_RSA_PRIVATEKEY, privateKey); + return keyMap; + } + + /** + * 获取公钥 + * @param + * @return + * @throws Exception + */ + public static String getPublicKey(Map keyMap) throws Exception { + Key key = (Key) keyMap.get(KEY_RSA_PUBLICKEY); + return encryptBASE64(key.getEncoded()); + } + + /** + * 获取私钥 + * @param + * @return + * @throws Exception + */ + public static String getPrivateKey(Map keyMap) throws Exception { + Key key = (Key) keyMap.get(KEY_RSA_PRIVATEKEY); + return encryptBASE64(key.getEncoded()); + } + + /** + * 解码返回byte + * @param key + * @return + * @throws Exception + */ + public static byte[] decryptBASE64(String key) throws Exception { + return Base64.getDecoder().decode(key); + } + + /** + * 编码返回字符串 + * @param key + * @return + * @throws Exception + */ + public static String encryptBASE64(byte[] key) { + return Base64.getEncoder().encodeToString (key); + } + + public static void main(String[] args) { + try { + Map keyMap = generateRSAKeyPlain(); + + System.out.println("生成的公钥:" + getPublicKey(keyMap)); + System.out.println("生成的私钥:" + getPrivateKey(keyMap)); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaApiHaiNanDXController.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaApiHaiNanDXController.java new file mode 100644 index 0000000000..e452ab0b1d --- /dev/null +++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaApiHaiNanDXController.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.haoka.controller.admin.api; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.haoka.api.ApiHaiNanDXService; +import cn.iocoder.yudao.module.haoka.api.hainandianxin.HaiNanDianXinApi; +import com.mashape.unirest.http.exceptions.UnirestException; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "API----------上游接口-------海南电信") +@RestController +@RequestMapping("/haoka/api/hainan-dx") +@Validated +public class HaokaApiHaiNanDXController { + + @Resource + private ApiHaiNanDXService apiHaiNanDXService; + + @PostMapping("/qryNbrList") + @Operation(summary = "海南电信-选号接口") + public CommonResult> + lianTongSelectNumber(@RequestBody HaiNanDianXinApi.QryNbrListRequest param) throws UnirestException { + return success(apiHaiNanDXService.qryNbrList(param)); + } + + @PostMapping("/fraudCheck") + @Operation(summary = "海南电信-防诈校验接口") + public CommonResult> + fraudCheck(@RequestBody HaiNanDianXinApi.FraudCheckRequest param) throws UnirestException { + return success(apiHaiNanDXService.fraudCheck(param)); + } + + @PostMapping("/queryOrderInfo") + @Operation(summary = "海南电信-订单信息查询接口") + public CommonResult> + queryOrderInfo(@RequestBody HaiNanDianXinApi.QueryOrderInfoRequest param) throws UnirestException { + return success(apiHaiNanDXService.queryOrderInfo(param)); + } + + @PostMapping("/getLogisticsTrajectory") + @Operation(summary = "海南电信-物流轨迹查询接口") + public CommonResult> + getLogisticsTrajectory(@RequestBody HaiNanDianXinApi.GetLogisticsTrajectoryRequest param) throws UnirestException { + return success(apiHaiNanDXService.getLogisticsTrajectory(param)); + } + + @PostMapping("/synOrderInfo") + @Operation(summary = "海南电信-号卡订单收敛接口") + public CommonResult> + synOrderInfo(@RequestBody HaiNanDianXinApi.SynOrderInfoRequest param) throws UnirestException { + return success(apiHaiNanDXService.synOrderInfo(param)); + } +} diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaApiController.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaApiLianTongController.java similarity index 88% rename from yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaApiController.java rename to yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaApiLianTongController.java index 87846f361d..40910b3f60 100644 --- a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaApiController.java +++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaApiLianTongController.java @@ -18,79 +18,79 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -@Tag(name = "API----上游接口") +@Tag(name = "API----------上游接口-------联通-集团") @RestController -@RequestMapping("/haoka/api") +@RequestMapping("/haoka/api/lian-tong") @Validated -public class HaokaApiController { +public class HaokaApiLianTongController { @Resource private ApiLianTongService haokaAllSuperiorApiService; - @PostMapping("/lian-tong/select-number") + @PostMapping("/select-number") @Operation(summary = "联通选号接口") public CommonResult lianTongSelectNumber(@RequestBody KingNumSelectRequest kingNumSelectRequest) { KingNumSelectResponse zopResponse = haokaAllSuperiorApiService.lianTongSelectNumber(kingNumSelectRequest); return success(zopResponse); } - @PostMapping("/lian-tong/zhan-hao") + @PostMapping("/zhan-hao") @Operation(summary = "联通占号接口") public CommonResult lianTongZhanHao(@RequestBody KingNumStateChangeRequest request) { KingNumStateChangeResponse response = haokaAllSuperiorApiService.lianTongZhanHao(request); return success(response); } - @PostMapping("/lian-tong/submit-user-info") + @PostMapping("/submit-user-info") @Operation(summary = "联通资料提交接口") public CommonResult lianTongSubmitUserInfo(@RequestBody KingIdentityCustV2Request request) { KingIdentityCustV2Response response = haokaAllSuperiorApiService.lianTongSubmitUserInfo(request); return success(response); } - @PostMapping("/lian-tong/order-sync-v2") + @PostMapping("/order-sync-v2") @Operation(summary = "联通订单同步接口") public CommonResult lianTongOrderSyncV2(@RequestBody KingOrderSyncV2Request request) { KingOrderSyncResponse response = haokaAllSuperiorApiService.lianTongOrderSyncV2(request); return success(response); } - @GetMapping("/lian-tong/message-get") + @GetMapping("/message-get") @Operation(summary = "联通消息获取接口") public CommonResult lianTongMessageGet(@RequestParam String type) { KingMessageGetResponse response = haokaAllSuperiorApiService.lianTongMessageGet(type); return success(response); } - @PostMapping("/lian-tong/message-del") + @PostMapping("/message-del") @Operation(summary = "联通消息删除接口") public CommonResult lianTongMessageDel(@RequestParam String type, @RequestParam String megIds) { KingMessageDelResponse response = haokaAllSuperiorApiService.lianTongMessageDel(type, megIds); return success(response); } - @PostMapping("/lian-tong/pre-order-sync") + @PostMapping("/pre-order-sync") @Operation(summary = "联通意向单同步接口") public CommonResult lianTongPreOrderSync(@RequestBody KingPreOrderSyncRequest request) { KingPreOrderSyncResponse response = haokaAllSuperiorApiService.lianTongPreOrderSync(request); return success(response); } - @PostMapping("/lian-tong/post-info-query") + @PostMapping("/post-info-query") @Operation(summary = "联通收货地址和号码信息查询接口") public CommonResult lianTongPostInfoQuery(@RequestBody KingPostInfoRequest request) { KingPostInfoResponse response = haokaAllSuperiorApiService.lianTongPostInfoQuery(request); return success(response); } - @PostMapping("/lian-tong/token-select-number") + @PostMapping("/token-select-number") @Operation(summary = "联通token选号接口") public CommonResult lianTongTokenSelectNumber(@RequestBody KingNumTokenSelectRequest request) { KingNumSelectResponse response = haokaAllSuperiorApiService.lianTongTokenSelectNumber(request); return success(response); } - @PostMapping("/lian-tong/select-area") + @PostMapping("/select-area") @Operation(summary = "联通-地址-归属地查询") public CommonResult> lianTongAreaInfo(@RequestParam(required = false, defaultValue = "1") String code) { LianTongArea area = LianTongAreaUtils.getArea(code); diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaGuangZhouDXController.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaGuangZhouDXController.java new file mode 100644 index 0000000000..e03404ae0e --- /dev/null +++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/controller/admin/api/HaokaGuangZhouDXController.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.haoka.controller.admin.api; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.haoka.api.ApiGuangZhouDXService; +import cn.iocoder.yudao.module.haoka.api.guangdong.GdOrderCreateRequestParam; +import cn.iocoder.yudao.module.haoka.api.guangdong.inner.GdOrderQueryRequestParam; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "API----------上游接口-------广州电信") +@RestController +@RequestMapping("/haoka/api/guangzhou-dx") +@Validated +public class HaokaGuangZhouDXController { + + @Resource + private ApiGuangZhouDXService apiGuangZhouDXService; + + @PostMapping("/createOrder") + @Operation(summary = "广州电信-创建订单接口") + public CommonResult createOrder(@RequestBody GdOrderCreateRequestParam param) { + return success(apiGuangZhouDXService.createOrder(param)); + } + + @PostMapping("/queryOrder") + @Operation(summary = "广州电信-查询订单接口") + public CommonResult queryOrder(@RequestBody GdOrderQueryRequestParam param) { + return success(apiGuangZhouDXService.queryOrder(param)); + } +}