diff --git a/dxhy-common/src/main/java/com/dxhy/common/enums/SNFplxEnum.java b/dxhy-common/src/main/java/com/dxhy/common/enums/SNFplxEnum.java index 8ac612da..21ee2bf4 100644 --- a/dxhy-common/src/main/java/com/dxhy/common/enums/SNFplxEnum.java +++ b/dxhy-common/src/main/java/com/dxhy/common/enums/SNFplxEnum.java @@ -140,7 +140,7 @@ public enum SNFplxEnum { return null; } - public String getFplxDm(String snFplxDm) { + public static String getFplxDm(String snFplxDm) { for (SNFplxEnum fplx : SNFplxEnum.values()) { if (fplx.getSnFplxDm() == snFplxDm) { return fplx.fplxDm; diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/controller/SDNYMainProcessController.java b/dxhy-erp/src/main/java/com/dxhy/erp/controller/SDNYMainProcessController.java index 770a7048..42cba771 100644 --- a/dxhy-erp/src/main/java/com/dxhy/erp/controller/SDNYMainProcessController.java +++ b/dxhy-erp/src/main/java/com/dxhy/erp/controller/SDNYMainProcessController.java @@ -1,13 +1,16 @@ package com.dxhy.erp.controller; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.dxhy.common.aspect.SysLog; import com.dxhy.common.constant.CommonConstants; import com.dxhy.common.controller.AbstractController; import com.dxhy.common.enums.FplxEnum; import com.dxhy.common.enums.SNFplxEnum; +import com.dxhy.common.jwt.IJWTInfo; import com.dxhy.common.util.InvoiceUtil; import com.dxhy.common.util.UserInfoUtil; +import com.dxhy.common.utils.BaseContextHandler; import com.dxhy.common.utils.R; import com.dxhy.erp.entity.sdny.*; import com.dxhy.erp.service.InvoiceQueryService; @@ -21,6 +24,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import javax.security.auth.message.config.AuthConfig; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; @@ -50,21 +54,22 @@ public class SDNYMainProcessController extends AbstractController { @ResponseBody @SysLog("发票查验") public ResponseEntity singleInvoiceCheck(@RequestBody Map pramsMap) { - // 入参统一在入口处理 - String userid = getLoginName(); - pramsMap.put("userid", userid); - String dbName = getUserInfo().getDbName(); - pramsMap.put("dbName", dbName); - pramsMap.put("saveHistory","Y"); - - pramsMap.put("company", getUserInfo().getCompany()); - List gfshAll = UserInfoUtil.getGfshAll(getUserInfo().getOrg()); - if (gfshAll.size() > 0) { - pramsMap.put("taxNo", gfshAll.get(0)); - - } - pramsMap.put("purchaserTaxNo", pramsMap.get("purchaserTaxNo")); +// // 入参统一在入口处理 +// String userid = getLoginName(); +// pramsMap.put("userid", userid); +// String dbName = getUserInfo().getDbName(); +// pramsMap.put("dbName", dbName); +// pramsMap.put("saveHistory","Y"); +// +// pramsMap.put("company", getUserInfo().getCompany()); +// +// List gfshAll = UserInfoUtil.getGfshAll(getUserInfo().getOrg()); +// if (gfshAll.size() > 0) { +// pramsMap.put("taxNo", gfshAll.get(0)); +// +// } +// pramsMap.put("purchaserTaxNo", pramsMap.get("purchaserTaxNo")); InvoiceUtil iu = new InvoiceUtil(pramsMap.get("invoiceCode")); @@ -74,7 +79,7 @@ public class SDNYMainProcessController extends AbstractController { return ResponseEntity.ok(R.error("发票代码不能为空!")); } - pramsMap.put("invoiceType", iu.getFplxdm()); +// pramsMap.put("invoiceType", iu.getFplxdm()); if (pramsMap.get("invoiceNumber").isEmpty()) { @@ -84,7 +89,7 @@ public class SDNYMainProcessController extends AbstractController { if (!pramsMap.get("billingDate").isEmpty()) { iu.setKprq(pramsMap.get("billingDate")); - pramsMap.put("invoiceDate", pramsMap.get("invoiceNumber")); + pramsMap.put("invoiceDate", pramsMap.get("billingDate")); if (!iu.kprqValid(null)) { pramsMap.put("invoiceDate", "开票日期格式错误!"); } @@ -92,12 +97,12 @@ public class SDNYMainProcessController extends AbstractController { return ResponseEntity.ok(R.error("开票日期不能为空!")); } - if (FplxEnum.ZP.getFplxDm().equals(pramsMap.get("invoiceType")) - || FplxEnum.JDC.getFplxDm().equals(pramsMap.get("invoiceType")) - || FplxEnum.DZZP.getFplxDm().equals(pramsMap.get("invoiceType")) - || FplxEnum.ESC.getFplxDm().equals(pramsMap.get("invoiceType")) - || FplxEnum.QDZZP.getFplxDm().equals(pramsMap.get("invoiceType")) - || FplxEnum.QDPP.getFplxDm().equals(pramsMap.get("invoiceType"))) { + if (SNFplxEnum.ZP.getSnFplxDm().equals(pramsMap.get("invoiceType")) + || SNFplxEnum.JDC.getSnFplxDm().equals(pramsMap.get("invoiceType")) + || SNFplxEnum.DZZP.getSnFplxDm().equals(pramsMap.get("invoiceType")) + || SNFplxEnum.ESC.getSnFplxDm().equals(pramsMap.get("invoiceType")) + || SNFplxEnum.QDZP.getSnFplxDm().equals(pramsMap.get("invoiceType")) + || SNFplxEnum.QDPP.getSnFplxDm().equals(pramsMap.get("invoiceType"))) { if (pramsMap.get("totalAmount").isEmpty()) { return ResponseEntity.ok(R.error("金额不能为空!")); } @@ -108,7 +113,7 @@ public class SDNYMainProcessController extends AbstractController { } String uuid = (StringUtils.isBlank(pramsMap.get("invoiceCode"))?"":pramsMap.get("invoiceCode"))+ pramsMap.get("invoiceNo"); - String notes = invoiceQueryService.checkingInvoiceInfo(dbName, uuid, getUserInfo()); + String notes = invoiceQueryService.checkingInvoiceInfo("business", uuid, getUserInfo()); if (notes != null) { return ResponseEntity.ok(R.error(notes)); } @@ -124,11 +129,13 @@ public class SDNYMainProcessController extends AbstractController { || SNFplxEnum.QDZP.getSnFplxDm().equals(pramsMap.get("invoiceType")) || SNFplxEnum.QDPP.getSnFplxDm().equals(pramsMap.get("invoiceType")) ) { + + pramsMap.put("invoiceType",fplxdm); //查验发票数据 checkInvoiceResult = snPushCheckRecordService.checkInvoice(pramsMap, getUserInfo()); }else{ //价税分离 - +// snPushCheckRecordService.valoremTaxCount(); } return ResponseEntity.ok(R.ok().put("data", checkInvoiceResult)); } diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/dao/OrgUserInfoDao.java b/dxhy-erp/src/main/java/com/dxhy/erp/dao/OrgUserInfoDao.java index f843e55b..f55a6006 100644 --- a/dxhy-erp/src/main/java/com/dxhy/erp/dao/OrgUserInfoDao.java +++ b/dxhy-erp/src/main/java/com/dxhy/erp/dao/OrgUserInfoDao.java @@ -4,6 +4,7 @@ import com.dxhy.erp.entity.sdny.BxwxEnterpriseUserEntity; import com.dxhy.erp.entity.sdny.OrgUserInfo; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiCheckInvoiceSingleRequest.java b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiCheckInvoiceSingleRequest.java new file mode 100644 index 00000000..7d02806a --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiCheckInvoiceSingleRequest.java @@ -0,0 +1,18 @@ +package com.dxhy.erp.entity.kfpt; + +import lombok.Data; + +/** + * Created by rei on 2021/8/26. + */ +@Data +public class ApiCheckInvoiceSingleRequest { + + private String fpdm; + private String fphm; + private String fpje; + private String jym; + private String kprq; + private String fpzl; + +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiRequest.java b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiRequest.java new file mode 100644 index 00000000..018ad86c --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiRequest.java @@ -0,0 +1,24 @@ +package com.dxhy.erp.entity.kfpt; + +import lombok.Data; + +import java.util.UUID; + +/** + * Created by rei on 2021/8/26. + */ +@Data +public class ApiRequest { + + private String zipCode; + private String encryptCode; + private String dataExchangeId; + private String entCode; + private String content; + + public ApiRequest() { + zipCode = "0"; + encryptCode = "0"; + dataExchangeId = UUID.randomUUID().toString().replace("-", ""); + } +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiResponse.java b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiResponse.java new file mode 100644 index 00000000..319f7957 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiResponse.java @@ -0,0 +1,22 @@ +package com.dxhy.erp.entity.kfpt; + +import lombok.Data; + +/** + * Created by rei on 2021/8/26. + */ +@Data +public class ApiResponse { + + private String zipCode; + private String encryptCode; + private String dataExchangeId; + private String entCode; + private String content; + private ApiReturnStateInfo returnStateInfo; + private String status; + private String error; + private String message; + private String timestamp; + +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiReturnStateInfo.java b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiReturnStateInfo.java new file mode 100644 index 00000000..1e7c36f0 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/ApiReturnStateInfo.java @@ -0,0 +1,14 @@ +package com.dxhy.erp.entity.kfpt; + +import lombok.Data; + +/** + * Created by rei on 2021/8/26. + */ +@Data +public class ApiReturnStateInfo { + + private String returnCode; + private String returnMessage; + +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/TokenRequest.java b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/TokenRequest.java new file mode 100644 index 00000000..7f25b477 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/TokenRequest.java @@ -0,0 +1,14 @@ +package com.dxhy.erp.entity.kfpt; + +import lombok.Data; + +/** + * Created by rei on 2021/8/26. + */ +@Data +public class TokenRequest { + + private String appKey; + private String appSecret; + +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/TokenResponse.java b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/TokenResponse.java new file mode 100644 index 00000000..b92588e4 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/entity/kfpt/TokenResponse.java @@ -0,0 +1,18 @@ +package com.dxhy.erp.entity.kfpt; + +import lombok.Data; + +/** + * Created by rei on 2021/8/26. + */ +@Data +public class TokenResponse { + + private String access_token; + private String token_type; + private String expires_in; + private String scope; + private String error; + private String error_description; + +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/service/SNPushCheckRecordService.java b/dxhy-erp/src/main/java/com/dxhy/erp/service/SNPushCheckRecordService.java index cdc87b90..0bc8dceb 100644 --- a/dxhy-erp/src/main/java/com/dxhy/erp/service/SNPushCheckRecordService.java +++ b/dxhy-erp/src/main/java/com/dxhy/erp/service/SNPushCheckRecordService.java @@ -6,6 +6,7 @@ import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSONObject; import com.dxhy.common.constant.DbConstant; import com.dxhy.common.datasource.config.DynamicContextHolder; +import com.dxhy.common.enums.SNFplxEnum; import com.dxhy.common.util.UserInfoUtil; import com.dxhy.common.vo.UserInfo; import com.dxhy.erp.dao.AreaDao; @@ -41,12 +42,13 @@ public class SNPushCheckRecordService extends AbstractServiceAdapter { @Value("${sdny.snYxUrl}") private String snYxUrl; + @Resource private InvoiceQueryUtil invoiceQueryUtil; - @Resource + @Autowired private AreaDao areaDao; - @Resource + @Autowired private OrgUserInfoDao orgUserInfoDao; public String pushCheckResultToSAP(JSONObject result) throws Exception { @@ -67,33 +69,38 @@ public class SNPushCheckRecordService extends AbstractServiceAdapter { // uuid = 发票代码+发票号码 String uuid = (org.apache.commons.lang.StringUtils.isBlank(pramsMap.get("invoiceCode"))?"":pramsMap.get("invoiceCode")) + pramsMap.get("invoiceNo"); - DynamicContextHolder.push(userInfo.getDbName() + DbConstant.BUSINESS_READ); + DynamicContextHolder.push("business" + DbConstant.BUSINESS_READ); - List gfshAll = UserInfoUtil.getGfshAll(userInfo.getOrg()); +// List gfshAll = UserInfoUtil.getGfshAll(userInfo.getOrg()); String gfsh = ""; - if (gfshAll.size() > 0) { - gfsh = gfshAll.get(0); - } +// if (gfshAll.size() > 0) { +// gfsh = gfshAll.get(0); +// } + + gfsh = "91370000166120002R"; + + + JSONObject queryInvoiceResult = invoiceQueryUtil.queryInvoice(pramsMap.get("invoiceCode"), - pramsMap.get("invoiceNo"), pramsMap.get("invoiceDate"), pramsMap.get("invoiceAmount"), pramsMap.get("checkCode"), - gfsh,"31"); + pramsMap.get("invoiceNumber"), pramsMap.get("billingDate"), pramsMap.get("totalAmount"), pramsMap.get("checkCode"), + gfsh,pramsMap.get("invoiceType")); String resultCode = queryInvoiceResult.getString("resultCode"); - DynamicContextHolder.push(userInfo.getDbName() + DbConstant.BUSINESS_WRITE); + DynamicContextHolder.push("business" + DbConstant.BUSINESS_WRITE); // 调用查验接口失败,将签收状态更新到扫描表中或者insert数据到扫描表,然后return; - if (queryInvoiceResult.containsKey("returnCode")) { - log.error("发票号码:" + pramsMap.get("invoiceNo") + "签收失败,失败原因:" + queryInvoiceResult.getString("returnMessage")); - return queryInvoiceResult; - } - if (!"0001".equals(resultCode)) { - // 接口通过但,调用返回失败 - log.error("发票号码:" + pramsMap.get("invoiceNo") + "签收失败,失败原因:" + queryInvoiceResult.getString("resultTip")); + if (queryInvoiceResult.containsKey("returnCode") && !"0001".equals(resultCode)) { + log.error("发票号码:" + pramsMap.get("invoiceNo") + "查验失败,失败原因:" + queryInvoiceResult.getString("returnMessage")); return queryInvoiceResult; } + + + return queryInvoiceResult; } + + /** * 客票价税计算 * @@ -213,7 +220,7 @@ public class SNPushCheckRecordService extends AbstractServiceAdapter { */ private ServiceResult checkIsDeduction(InvoiceInfo invoiceInfo, String enterpriseId) throws ParseException { try { - String result = verifyInfo( invoiceInfo); + String result = verifyInfo(invoiceInfo); if (!CommonEnum.RESPONSE_INTERFACE_STATUS_CODE_SUCCESS.equals(result)) { return fail(result); } diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/utils/ApiUtils.java b/dxhy-erp/src/main/java/com/dxhy/erp/utils/ApiUtils.java new file mode 100644 index 00000000..af4bdae4 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/utils/ApiUtils.java @@ -0,0 +1,86 @@ +package com.dxhy.erp.utils; + +import com.alibaba.fastjson.JSONObject; +import com.dxhy.erp.entity.kfpt.ApiRequest; +import com.dxhy.erp.entity.kfpt.ApiResponse; +import com.dxhy.erp.entity.kfpt.TokenRequest; +import com.dxhy.erp.entity.kfpt.TokenResponse; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.Duration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * 接口工具类 + * + * @author REI + */ +@Component +@Slf4j +public class ApiUtils { + + @Value("${params.api.tokenUrl}") + private String tokenUrl; + @Value("${params.api.loginUrl}") + private String loginUrl; + @Value("${params.api.connTimeout}") + private int connTimeout; + @Value("${params.api.readTimeout}") + private int readTimeout; + private String contentType = "application/json"; + private String charset = "UTF-8"; + + private TokenResponse callToken(String url, TokenRequest tokenRequest) { + final DateTime start = DateTime.now(); + String body = JSONObject.toJSONString(tokenRequest); + String result = null; + try { + result = HttpClientUtils.post(url, body, contentType, charset, connTimeout, readTimeout); + } catch (Exception e) { + log.error("<线程" + Thread.currentThread().getId() + ">调用开放平台获取token异常:", e); + } finally { + log.info("<线程{}>interface={}|param={}|result={}|responseTime={}", + Thread.currentThread().getId(), url, body, result, new Duration(start, DateTime.now()).getMillis()); + } + return JSONObject.parseObject(result, TokenResponse.class); + } + + + public ApiResponse callApi(String url, String entCode, Object content, String accessToken, String requestId) { + final DateTime start = DateTime.now(); + ApiRequest apiRequest = new ApiRequest(); + apiRequest.setContent(Base64.encode(JSONObject.toJSONBytes(content))); + apiRequest.setEntCode(entCode); + apiRequest.setDataExchangeId(requestId); + String body = JSONObject.toJSONString(apiRequest); + url = url + "?access_token=" + accessToken; + String result = null; + try { + result = HttpClientUtils.post(url, body, contentType, charset, connTimeout, readTimeout); + } catch (Exception e) { + log.error("<线程" + Thread.currentThread().getId() + ">调用开放平台业务接口异常:", e); + } finally { + log.info("<线程{}>interface={}|param={}|result={}|responseTime={}", + Thread.currentThread().getId(), url, body, result, new Duration(start, DateTime.now()).getMillis()); + } + ApiResponse apiResponse = JSONObject.parseObject(result, ApiResponse.class); + return apiResponse; + + } + + + public TokenResponse getToken(String appKey, String appSecret) { + TokenRequest tokenRequest = new TokenRequest(); + tokenRequest.setAppKey(appKey); + tokenRequest.setAppSecret(appSecret); + TokenResponse tokenResponse = callToken(tokenUrl, tokenRequest); + if (tokenResponse != null && StringUtils.isEmpty(tokenResponse.getError())) { + return tokenResponse; + } else { + return null; + } + } + +} diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/utils/Base64.java b/dxhy-erp/src/main/java/com/dxhy/erp/utils/Base64.java new file mode 100644 index 00000000..836740b2 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/utils/Base64.java @@ -0,0 +1,271 @@ +package com.dxhy.erp.utils; + +public final class Base64 { + + static private final int BASELENGTH = 128; + static private final int LOOKUPLENGTH = 64; + static private final int TWENTYFOURBITGROUP = 24; + static private final int EIGHTBIT = 8; + static private final int SIXTEENBIT = 16; + static private final int SIXBIT = 6; + static private final int FOURBYTE = 4; + static private final int SIGN = -128; + static private final char PAD = '='; + static private final boolean fDebug = false; + static final private byte [] base64Alphabet = new byte[BASELENGTH]; + static final private char [] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; + + static { + + for (int i = 0; i < BASELENGTH; ++i) { + base64Alphabet[i] = -1; + } + for (int i = 'Z'; i >= 'A'; i--) { + base64Alphabet[i] = (byte) (i-'A'); + } + for (int i = 'z'; i>= 'a'; i--) { + base64Alphabet[i] = (byte) ( i-'a' + 26); + } + + for (int i = '9'; i >= '0'; i--) { + base64Alphabet[i] = (byte) (i-'0' + 52); + } + + base64Alphabet['+'] = 62; + base64Alphabet['/'] = 63; + + for (int i = 0; i<=25; i++) + lookUpBase64Alphabet[i] = (char)('A'+i); + + for (int i = 26, j = 0; i<=51; i++, j++) + lookUpBase64Alphabet[i] = (char)('a'+ j); + + for (int i = 52, j = 0; i<=61; i++, j++) + lookUpBase64Alphabet[i] = (char)('0' + j); + lookUpBase64Alphabet[62] = (char)'+'; + lookUpBase64Alphabet[63] = (char)'/'; + + } + + protected static boolean isWhiteSpace(char octect) { + return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); + } + + protected static boolean isPad(char octect) { + return (octect == PAD); + } + + protected static boolean isData(char octect) { + return (octect < BASELENGTH && base64Alphabet[octect] != -1); + } + + protected static boolean isBase64(char octect) { + return (isWhiteSpace(octect) || isPad(octect) || isData(octect)); + } + + /** + * Encodes hex octects into Base64 + * + * @param binaryData Array containing binaryData + * @return Encoded Base64 array + */ + public static String encode(byte[] binaryData) { + + if (binaryData == null) + return null; + + int lengthDataBits = binaryData.length*EIGHTBIT; + if (lengthDataBits == 0) { + return ""; + } + + int fewerThan24bits = lengthDataBits%TWENTYFOURBITGROUP; + int numberTriplets = lengthDataBits/TWENTYFOURBITGROUP; + int numberQuartet = fewerThan24bits != 0 ? numberTriplets+1 : numberTriplets; + char encodedData[] = null; + + encodedData = new char[numberQuartet*4]; + + byte k=0, l=0, b1=0,b2=0,b3=0; + + int encodedIndex = 0; + int dataIndex = 0; + if (fDebug) { + System.out.println("number of triplets = " + numberTriplets ); + } + + for (int i=0; i>4 ) ; + decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); + decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); + } + + if (!isData( (d1 = base64Data[dataIndex++]) ) || + !isData( (d2 = base64Data[dataIndex++]) )) { + return null;//if found "no data" just return null + } + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + + d3 = base64Data[dataIndex++]; + d4 = base64Data[dataIndex++]; + if (!isData( (d3 ) ) || + !isData( (d4 ) )) {//Check if they are PAD characters + if (isPad( d3 ) && isPad( d4)) { //Two PAD e.g. 3c[Pad][Pad] + if ((b2 & 0xf) != 0)//last 4 bits should be zero + return null; + byte[] tmp = new byte[ i*3 + 1 ]; + System.arraycopy( decodedData, 0, tmp, 0, i*3 ); + tmp[encodedIndex] = (byte)( b1 <<2 | b2>>4 ) ; + return tmp; + } else if (!isPad( d3) && isPad(d4)) { //One PAD e.g. 3cQ[Pad] + b3 = base64Alphabet[ d3 ]; + if ((b3 & 0x3 ) != 0)//last 2 bits should be zero + return null; + byte[] tmp = new byte[ i*3 + 2 ]; + System.arraycopy( decodedData, 0, tmp, 0, i*3 ); + tmp[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ); + tmp[encodedIndex] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); + return tmp; + } else { + return null;//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data + } + } else { //No PAD e.g 3cQl + b3 = base64Alphabet[ d3 ]; + b4 = base64Alphabet[ d4 ]; + decodedData[encodedIndex++] = (byte)( b1 <<2 | b2>>4 ) ; + decodedData[encodedIndex++] = (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) ); + decodedData[encodedIndex++] = (byte)( b3<<6 | b4 ); + + } + + return decodedData; + } + + /** + * remove WhiteSpace from MIME containing encoded Base64 data. + * + * @param data the byte array of base64 data (with WS) + * @return the new length + */ + protected static int removeWhiteSpace(char[] data) { + if (data == null) + return 0; + + // count characters that's not whitespace + int newSize = 0; + int len = data.length; + for (int i = 0; i < len; i++) { + if (!isWhiteSpace(data[i])) + data[newSize++] = data[i]; + } + return newSize; + } +} + diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/utils/HttpClientUtils.java b/dxhy-erp/src/main/java/com/dxhy/erp/utils/HttpClientUtils.java new file mode 100644 index 00000000..1090a627 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/utils/HttpClientUtils.java @@ -0,0 +1,228 @@ +package com.dxhy.erp.utils; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.config.RequestConfig.Builder; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLContextBuilder; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.conn.ssl.X509HostnameVerifier; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import java.io.IOException; +import java.net.SocketTimeoutException; +import java.security.GeneralSecurityException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +public class HttpClientUtils { + + public static final int connTimeout = 10000; + public static final int readTimeout = 10000; + public static final String charset = "UTF-8"; + private static HttpClient client = null; + + static { + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); + cm.setMaxTotal(1000); + cm.setDefaultMaxPerRoute(500); + client = HttpClients.custom().setConnectionManager(cm).build(); + } + + public static String postParameters(String url, String parameterStr) throws ConnectTimeoutException, SocketTimeoutException, Exception { + return post(url, parameterStr, "application/json", charset, connTimeout, readTimeout); + } + + public static String get(String url) throws Exception { + return get(url, charset, null, null); + } + + public static String get(String url, String charset) throws Exception { + return get(url, charset, connTimeout, readTimeout); + } + + /** + * 发送一个 Post 请求, 使用指定的字符集编码. + * + * @param url + * @param body RequestBody + * @param mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3 + * @param charset 编码 + * @param connTimeout 建立链接超时时间,毫秒. + * @param readTimeout 响应超时时间,毫秒. + * @return ResponseBody, 使用指定的字符集编码. + * @throws ConnectTimeoutException 建立链接超时异常 + * @throws SocketTimeoutException 响应超时 + * @throws Exception + */ + public static String post(String url, String body, String mimeType, String charset, Integer connTimeout, Integer readTimeout) + throws ConnectTimeoutException, SocketTimeoutException, Exception { + HttpClient client = null; + HttpPost post = new HttpPost(url); + String result = ""; + try { + if (StringUtils.isNotBlank(body)) { + HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset)); + post.setEntity(entity); + } + // 设置参数 + Builder customReqConf = RequestConfig.custom(); + if (connTimeout != null) { + customReqConf.setConnectTimeout(connTimeout); + } + if (readTimeout != null) { + customReqConf.setSocketTimeout(readTimeout); + } + post.setConfig(customReqConf.build()); + + HttpResponse res; + if (url.startsWith("https")) { + // 执行 Https 请求. + client = createSSLInsecureClient(); + res = client.execute(post); + } else { + // 执行 Http 请求. + client = HttpClientUtils.client; + res = client.execute(post); + } + result = IOUtils.toString(res.getEntity().getContent(), charset); + } finally { + post.releaseConnection(); + if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) { + ((CloseableHttpClient) client).close(); + } + } + return result; + } + + /** + * 发送一个 GET 请求 + * + * @param url + * @param charset + * @param connTimeout 建立链接超时时间,毫秒. + * @param readTimeout 响应超时时间,毫秒. + * @return + * @throws ConnectTimeoutException 建立链接超时 + * @throws SocketTimeoutException 响应超时 + * @throws Exception + */ + public static String get(String url, String charset, Integer connTimeout, Integer readTimeout) + throws ConnectTimeoutException, SocketTimeoutException, Exception { + + HttpClient client = null; + HttpGet get = new HttpGet(url); + get.setHeader("Authorization", "pq8fTpZWeWv8"); + String result = ""; + try { + // 设置参数 + Builder customReqConf = RequestConfig.custom(); + if (connTimeout != null) { + customReqConf.setConnectTimeout(connTimeout); + } + if (readTimeout != null) { + customReqConf.setSocketTimeout(readTimeout); + } + get.setConfig(customReqConf.build()); + + HttpResponse res = null; + + if (url.startsWith("https")) { + // 执行 Https 请求. + client = createSSLInsecureClient(); + res = client.execute(get); + } else { + // 执行 Http 请求. + client = HttpClientUtils.client; + res = client.execute(get); + } + + result = IOUtils.toString(res.getEntity().getContent(), charset); + } finally { + get.releaseConnection(); + if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) { + ((CloseableHttpClient) client).close(); + } + } + return result; + } + + /** + * 从 response 里获取 charset + * + * @param ressponse + * @return + */ + @SuppressWarnings("unused") + private static String getCharsetFromResponse(HttpResponse ressponse) { + // Content-Type:text/html; charset=GBK + if (ressponse.getEntity() != null && ressponse.getEntity().getContentType() != null && ressponse.getEntity().getContentType().getValue() != null) { + String contentType = ressponse.getEntity().getContentType().getValue(); + if (contentType.contains("charset=")) { + return contentType.substring(contentType.indexOf("charset=") + 8); + } + } + return null; + } + + /** + * 创建 SSL连接 + * + * @return + * @throws GeneralSecurityException + */ + private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException { + try { + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { + public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { + return true; + } + }).build(); + + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() { + + @Override + public boolean verify(String arg0, SSLSession arg1) { + return true; + } + + @Override + public void verify(String host, SSLSocket ssl) + throws IOException { + } + + @Override + public void verify(String host, X509Certificate cert) + throws SSLException { + } + + @Override + public void verify(String host, String[] cns, + String[] subjectAlts) throws SSLException { + } + + }); + + return HttpClients.custom().setSSLSocketFactory(sslsf).build(); + + } catch (GeneralSecurityException e) { + throw e; + } + } + +} \ No newline at end of file diff --git a/dxhy-erp/src/main/java/com/dxhy/erp/utils/IcpUtils.java b/dxhy-erp/src/main/java/com/dxhy/erp/utils/IcpUtils.java new file mode 100644 index 00000000..cf7243e4 --- /dev/null +++ b/dxhy-erp/src/main/java/com/dxhy/erp/utils/IcpUtils.java @@ -0,0 +1,33 @@ +package com.dxhy.erp.utils; + +import com.dxhy.erp.entity.kfpt.ApiCheckInvoiceSingleRequest; +import com.dxhy.erp.entity.kfpt.ApiResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +public class IcpUtils { + + @Value("${params.api.invoiceCheckSingleUrl}") + private String invoiceCheckSingleUrl; + + @Autowired + private ApiUtils apiUtils; + + /** + * 调用开放平台单张发票查验 + * + * @param requestId + * @param singleInvoiceRequest + * @param taxpayerId + * @return InvoiceCheckResponse + */ + public ApiResponse callSingleCheck(String requestId, ApiCheckInvoiceSingleRequest singleInvoiceRequest, String taxpayerId, String access_token) { + ApiResponse apiResponse = apiUtils.callApi(invoiceCheckSingleUrl, taxpayerId, singleInvoiceRequest, access_token, requestId); + return apiResponse; + } + +}