ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppGoodsController.java
@@ -1,7 +1,6 @@ package com.ruoyi.goods.controller.miniapp; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.goods.domain.dto.AppGoodsInfoGetDto; @@ -11,7 +10,6 @@ import com.ruoyi.goods.domain.vo.AppShoppingCartVo; import com.ruoyi.goods.service.goods.GoodsService; import com.ruoyi.goods.service.goods.ShoppingCartService; import com.ruoyi.system.api.constant.AppErrorConstant; import com.ruoyi.system.api.domain.dto.AppBaseBathDto; import com.ruoyi.system.api.domain.poji.member.Member; import com.ruoyi.system.api.service.RemoteMemberService; @@ -59,7 +57,8 @@ } } if(appGoodsInfoGetDto.getShopId()==null){ throw new ServiceException(AppErrorConstant.NO_POSITION); //throw new ServiceException(AppErrorConstant.NO_POSITION); appGoodsInfoGetDto.setShopId(1L); } AppGoodsInfoVo appGoodsInfoVo = goodsService.getGoodsInfo(appGoodsInfoGetDto); return R.ok(appGoodsInfoVo); ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppHomeController.java
@@ -59,7 +59,8 @@ shopId = appRecommendGoodsPageDto.getPositionShopId(); } if(shopId==null){ throw new ServiceException(AppErrorConstant.NO_POSITION); //throw new ServiceException(AppErrorConstant.NO_POSITION); shopId = 1L; } Page<AppSimpleGoodsVo> page = new Page<>(); page.setSize(appRecommendGoodsPageDto.getPageSize()); ruoyi-modules/ruoyi-order/pom.xml
@@ -104,7 +104,7 @@ <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> <version>0.2.7</version> <version>0.2.8</version> </dependency> </dependencies> ruoyi-modules/ruoyi-shop/pom.xml
@@ -102,7 +102,42 @@ <version>2.3.3</version> </dependency> <!-- 微信 --> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-apache-httpclient</artifactId> <version>0.4.9</version> </dependency> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> <version>0.2.8</version> </dependency> <dependency> <groupId>com.github.javen205</groupId> <artifactId>IJPay-WxPay</artifactId> <version>2.9.7-17</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>4.0.2</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>4.0.2</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>4.0.2</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-extension-providers</artifactId> <version>4.0.2</version> </dependency> </dependencies> <build> ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/controller/management/MgtShopController.java
@@ -169,7 +169,7 @@ } @RequestMapping(value = "/mgtAuditShopCertificate", method = RequestMethod.POST) @ApiOperation(value = "平台编辑会员建议标签") @ApiOperation(value = "平台审核商户证书") public R mgtAuditShopCertificate(@RequestBody MgtAuditShopCertificateDto mgtAuditShopCertificateDto) { Long userId = SecurityUtils.getUserId(); mgtAuditShopCertificateDto.setUserId(userId); @@ -196,4 +196,13 @@ List<MgtShopAuthPageVo> mgtShopAuthPageVoList = shopService.pageMgtShopAuth(page,mgtShopAuthPageDto); return R.ok(page.setRecords(mgtShopAuthPageVoList)); } @RequestMapping(value = "/mgtShopAuth", method = RequestMethod.POST) @ApiOperation(value = "平台商户进件") public R mgtShopAuth(@RequestBody MgtShopAuthDto mgtShopAuthDto) { Long userId = SecurityUtils.getUserId(); mgtShopAuthDto.setUserId(userId); shopService.mgtShopAuth(mgtShopAuthDto); return R.ok(); } } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/MgtShopAuthDto.java
New file @@ -0,0 +1,143 @@ package com.ruoyi.shop.domain.dto; import com.ruoyi.system.api.domain.dto.MgtBaseDto; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @ClassName Mgt * @Description TODO * @Author jqs * @Date 2023/6/19 10:57 * @Version 1.0 */ @Data public class MgtShopAuthDto extends MgtBaseDto { @ApiModelProperty(value = "审核id") private String authId; /** * 商户id */ @ApiModelProperty(value = "商户id") private Long shopId; @ApiModelProperty(value = "商户名称") private String shopName; @ApiModelProperty("店主姓名") private String shopownerName; @ApiModelProperty("店主联系方式") private String shopownerPhone; /** * 主题类型1个人2企业 */ @ApiModelProperty(value = "主题类型1个人2企业") private Integer mainType; /** * 营业执照商户名称 */ @ApiModelProperty(value = "营业执照商户名称") private String blShopName; /** * 营业执照编号 */ @ApiModelProperty(value = "营业执照编号") private String blNumber; /** * 营业执照法人姓名 */ @ApiModelProperty(value = "营业执照法人姓名") private String blCorporateName; /** * 营业执照注册地址 */ @ApiModelProperty(value = "营业执照注册地址") private String blRegisteredAddress; /** * 营业执照期限 */ @ApiModelProperty(value = "营业执照期限") private String blBusinessDeanline; /** * 营业执照图片 */ @ApiModelProperty(value = "营业执照图片") private String blImage; /** * 法人姓名 */ @ApiModelProperty(value = "法人姓名") private String lpCorporateName; /** * 法人身份证号 */ @ApiModelProperty(value = "法人身份证号") private String lpIdCard; /** * 法人身份证开始日期 */ @ApiModelProperty(value = "法人身份证开始日期") private String lpIcStartDate; /** * 法人身份证有效日期 */ @ApiModelProperty(value = "法人身份证有效日期") private String lpIcEndDate; /** * 法人身份证正面 */ @ApiModelProperty(value = "法人身份证正面") private String lpIcFront; /** * 法人身份证背面 */ @ApiModelProperty(value = "法人身份证背面") private String lpIcBack; /** * 结算账户类型1对公2对私 */ @ApiModelProperty(value = "结算账户类型1对公2对私") private String settlementAccountType; /** * 开户行 */ @ApiModelProperty(value = "开户行") private String saBank; /** * 开户名称 */ @ApiModelProperty(value = "开户名称") private String saAccountName; /** * 开户所在省 */ @ApiModelProperty(value = "开户所在省") private String saBankProvinceCode; /** * 开户所在市 */ @ApiModelProperty(value = "开户所在市") private String saBankCityCode; /** * 开户行全称 */ @ApiModelProperty(value = "开户行全称") private String saBankName; /** * 银行卡号 */ @ApiModelProperty(value = "银行卡号") private String saNumber; @ApiModelProperty(value = "补充资料") private String baPics; @ApiModelProperty(value = "补充说明") private String baDesc; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/pojo/shop/ShopAuthentication.java
@@ -242,9 +242,9 @@ private String adRejectReason; /** * 法人验证链接 1、当申请状态为 ACCOUNT_NEED_VERIFY,且通过系统校验的申请单,将返回链接。 2、建议将链接转为二维码展示,让商户法人用微信扫码打开,完成账户验证。 1、当申请状态为 ACCOUNT_NEED_VERIFY,且通过系统校验的申请单,将返回链接。 2、建议将链接转为二维码展示,让商户法人用微信扫码打开,完成账户验证。 */ @TableField("legal_validation_url") private String legalValidationUrl; @@ -252,7 +252,16 @@ private Date createTime; @TableField("update_time") private Date updateTime; /** * 补充资料 */ @TableField("ba_pics") private String baPics; /** * 补充说明 */ @TableField("ba_desc") private String baDesc; @Override protected Serializable pkVal() { ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/vo/MgtShopAuthGetVo.java
New file @@ -0,0 +1,152 @@ package com.ruoyi.shop.domain.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @ClassName MgtShopAuthDto * @Description TODO * @Author jqs * @Date 2023/6/19 10:21 * @Version 1.0 */ @Data public class MgtShopAuthGetVo { @ApiModelProperty(value = "审核id") private String authId; /** * 商户id */ @ApiModelProperty(value = "商户id") private Long shopId; @ApiModelProperty(value = "商户名称") private String shopName; @ApiModelProperty("店主姓名") private String shopownerName; @ApiModelProperty("店主联系方式") private String shopownerPhone; /** * 审核状态 1:CHECKING:资料校验中 2:ACCOUNT_NEED_VERIFY:待账户验证 3:AUDITING:审核中 4:REJECTED:已驳回 5:NEED_SIGN:待签约 6:FINISH:完成 7:FROZEN:已冻结 8:CANCELED:已作废 */ @ApiModelProperty(value = "审核状态") private Integer auditStatus; /** * 主题类型1个人2企业 */ @ApiModelProperty(value = "主题类型1个人2企业") private Integer mainType; /** * 营业执照商户名称 */ @ApiModelProperty(value = "营业执照商户名称") private String blShopName; /** * 营业执照编号 */ @ApiModelProperty(value = "营业执照编号") private String blNumber; /** * 营业执照法人姓名 */ @ApiModelProperty(value = "营业执照法人姓名") private String blCorporateName; /** * 营业执照注册地址 */ @ApiModelProperty(value = "营业执照注册地址") private String blRegisteredAddress; /** * 营业执照期限 */ @ApiModelProperty(value = "营业执照期限") private String blBusinessDeanline; /** * 营业执照图片 */ @ApiModelProperty(value = "营业执照图片") private String blImage; /** * 法人姓名 */ @ApiModelProperty(value = "法人姓名") private String lpCorporateName; /** * 法人身份证号 */ @ApiModelProperty(value = "法人身份证号") private String lpIdCard; /** * 法人身份证开始日期 */ @ApiModelProperty(value = "法人身份证开始日期") private String lpIcStartDate; /** * 法人身份证有效日期 */ @ApiModelProperty(value = "法人身份证有效日期") private String lpIcEndDate; /** * 法人身份证正面 */ @ApiModelProperty(value = "法人身份证正面") private String lpIcFront; /** * 法人身份证背面 */ @ApiModelProperty(value = "法人身份证背面") private String lpIcBack; /** * 结算账户类型1对公2对私 */ @ApiModelProperty(value = "结算账户类型1对公2对私") private String settlementAccountType; /** * 开户行 */ @ApiModelProperty(value = "开户行") private String saBank; /** * 开户名称 */ @ApiModelProperty(value = "开户名称") private String saAccountName; /** * 开户所在省 */ @ApiModelProperty(value = "开户所在省") private String saBankProvinceCode; /** * 开户所在市 */ @ApiModelProperty(value = "开户所在市") private String saBankCityCode; /** * 开户行全称 */ @ApiModelProperty(value = "开户行全称") private String saBankName; /** * 银行卡号 */ @ApiModelProperty(value = "银行卡号") private String saNumber; @ApiModelProperty(value = "补充资料") private String baPics; @ApiModelProperty(value = "补充说明") private String baDesc; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopServiceImpl.java
@@ -614,4 +614,19 @@ MgtBulletinBoardVo mgtBulletinBoardVoShop = shopMapper.shopTotal(); return mgtBulletinBoardVoShop; } /** * @description 商户进件 * @author jqs * @date 2023/6/19 11:02 * @param mgtShopAuthDto * @return void */ @Override public void mgtShopAuth(MgtShopAuthDto mgtShopAuthDto){ ShopAuthentication shopAuthentication = shopAuthenticationService.getById(mgtShopAuthDto.getAuthId()); BeanUtils.copyProperties(mgtShopAuthDto , shopAuthentication); shopAuthentication.setAuditStatus(3); shopAuthenticationService.saveOrUpdate(shopAuthentication); } } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopService.java
@@ -169,4 +169,13 @@ * @date 2023/6/18 17:01 */ MgtBulletinBoardVo boardShopTotal(); /** * @description 商户进件 * @author jqs * @date 2023/6/19 11:02 * @param mgtShopAuthDto * @return void */ void mgtShopAuth(MgtShopAuthDto mgtShopAuthDto); } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/Certificate.java
New file @@ -0,0 +1,162 @@ package com.ruoyi.shop.util; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.shop.util.dto.CertificateItem; import com.ruoyi.shop.util.dto.EncryptedCertificateItem; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; /** * @date 2020-03-18 15:06 * @description */ @Slf4j public class Certificate { private static final Logger logger = LoggerFactory.getLogger(Certificate.class); /** * 获取微信支付平台证书 * * @param merchantId * @param timeout * @param serialNo * @param mchPrivateKeyPath * @param APIv3Key * @param savePath * @return */ public static List<X509Certificate> getCertByAPI(String merchantId, int timeout, String serialNo, String mchPrivateKeyPath, String wechatPubKeyPath, String APIv3Key, String savePath) { String result = ""; //创建http请求 HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/certificates"); httpGet.addHeader("Content-Type", "application/json"); httpGet.addHeader("Accept", "application/json"); String authorization = SignUtils.authorization("GET", "/v3/certificates", merchantId, serialNo, "", mchPrivateKeyPath); //设置认证信息 httpGet.setHeader("Authorization", authorization); //设置请求器配置:如超时限制等 RequestConfig config = RequestConfig.custom().setSocketTimeout(timeout * 1000).setConnectTimeout(timeout * 1000).build(); httpGet.setConfig(config); List<X509Certificate> x509Certs = new ArrayList<X509Certificate>(); try { CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = httpClient.execute(httpGet); int statusCode = response.getStatusLine().getStatusCode(); HttpEntity httpEntity = response.getEntity(); result = EntityUtils.toString(httpEntity, "UTF-8"); if (statusCode == 200) { logger.info("下载平台证书返回结果:" + result); Header[] timestampHeader = response.getHeaders("Wechatpay-Timestamp"); Header[] nonceHeader = response.getHeaders("Wechatpay-Nonce"); Header[] signatureHeader = response.getHeaders("Wechatpay-Signature"); if (timestampHeader != null && timestampHeader.length > 0 && nonceHeader != null && nonceHeader.length > 0 && signatureHeader != null && signatureHeader.length > 0) { // 验证微信支付返回签名 String wTimestamp = timestampHeader[0].getValue(); String wNonce = nonceHeader[0].getValue(); String wSign = signatureHeader[0].getValue(); logger.info("wTimestamp:{},wNonce:{},wSign:{}", wTimestamp, wNonce, wSign); // 拼装待签名串 StringBuffer ss = new StringBuffer(); ss.append(wTimestamp).append("\n"); ss.append(wNonce).append("\n"); ss.append(result).append("\n"); // 验证签名 if (SignUtils.v3VerifyRSA(ss.toString(), Base64.decodeBase64(wSign.getBytes()), wechatPubKeyPath)) { List<CertificateItem> certList = new ArrayList<CertificateItem>(); JSONObject json = JSONObject.parseObject(result); logger.info("查询结果json字符串转证书List:" + json.get("data")); JSONArray jsonArray = (JSONArray) json.get("data"); for (int i = 0; i < jsonArray.size(); i++) { CertificateItem certificateItem = new CertificateItem(); EncryptedCertificateItem encryptCertificate = new EncryptedCertificateItem(); JSONObject bo = JSONObject.parseObject(jsonArray.get(i).toString()); certificateItem.setSerial_no(bo.get("serial_no").toString()); certificateItem.setEffective_time(bo.get("effective_time").toString()); certificateItem.setExpire_time(bo.get("expire_time").toString()); JSONObject encryptBo = JSONObject.parseObject(bo.get("encrypt_certificate").toString()); encryptCertificate.setAlgorithm(encryptBo.get("algorithm").toString()); encryptCertificate.setNonce(encryptBo.get("nonce").toString()); encryptCertificate.setAssociated_data(encryptBo.get("associated_data").toString()); encryptCertificate.setCiphertext(encryptBo.get("ciphertext").toString()); certificateItem.setEncrypt_certificate(encryptCertificate); certList.add(certificateItem); } logger.info("证书List:" + certList); /*List<PlainCertificateItem> plainList = decrypt(certList, APIv3Key); if (CollectionUtils.isNotEmpty(plainList)) { logger.info("平台证书开始保存"); x509Certs = saveCertificate(plainList, savePath); }*/ } } } response.close(); httpClient.close(); //throw return x509Certs; } catch (Exception e) { e.printStackTrace(); logger.error("下载平台证书返回结果:" + e); } return x509Certs; } /*private static List<PlainCertificateItem> decrypt(List<CertificateItem> certList,CloseableHttpResponse response) throws GeneralSecurityException, IOException { List<PlainCertificateItem> plainCertificateList = new ArrayList<PlainCertificateItem>(); AesUtil aesUtil = new AesUtil("".getBytes(StandardCharsets.UTF_8)); for(CertificateItem item:certList){ PlainCertificateItem bo = new PlainCertificateItem(); bo.setSerialNo(item.getSerial_no()); bo.setEffectiveTime(item.getEffective_time()); bo.setExpireTime(item.getExpire_time()); logger.info("平台证书密文解密"); bo.setPlainCertificate(aesUtil.decryptToString(item.getEncrypt_certificate().getAssociated_data().getBytes(StandardCharsets.UTF_8), item.getEncrypt_certificate().getNonce().getBytes(StandardCharsets.UTF_8), item.getEncrypt_certificate().getCiphertext())); logger.info("平台证书公钥明文:"+bo.getPlainCertificate()); plainCertificateList.add(bo); } return plainCertificateList; }*/ //证书保存 /*private static List<X509Certificate> saveCertificate(List<PlainCertificateItem> cert) throws IOException { List<X509Certificate> x509Certs = new ArrayList<X509Certificate>(); File file = new File("平台证书路径"); file.mkdirs(); for (PlainCertificateItem item : cert) { ByteArrayInputStream inputStream = new ByteArrayInputStream(item.getPlainCertificate().getBytes(StandardCharsets.UTF_8)); X509Certificate x509Cert = PemUtil.loadCertificate(inputStream); x509Certs.add(x509Cert); String outputAbsoluteFilename = file.getAbsolutePath() + File.separator + "wechatpay_" + item.getSerialNo() + ".pem"; try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputAbsoluteFilename), StandardCharsets.UTF_8))) { writer.write(item.getPlainCertificate()); } logger.info("输出证书文件目录:" + outputAbsoluteFilename); } return x509Certs; }*/ } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/CertificateUtils.java
New file @@ -0,0 +1,106 @@ package com.ruoyi.shop.util; import cn.hutool.core.codec.Base64; import cn.hutool.core.io.FileUtil; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; /** * @date 2020-03-18 11:25 * @description 证书相关 */ public class CertificateUtils { /** * 获取商户私钥 * @param priKeyPath 商户私钥证书路径 * @return */ public static String getPrivateKey(String priKeyPath) throws Exception { String originalKey = FileUtil.readUtf8String(priKeyPath); String privateKey = originalKey .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s+", ""); return getPrivateKeyStr(loadPrivateKey(privateKey)); } private static String getPrivateKeyStr(PrivateKey privateKey) { return Base64.encode(privateKey.getEncoded()); } /** * 从字符串中加载私钥 * @param privateKeyStr 私钥 * @return */ public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception { try { byte[] buffer = Base64.decode(privateKeyStr); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("私钥非法"); } catch (NullPointerException e) { throw new Exception("私钥数据为空"); } } /** * 获取证书 * @param fileName 证书文件路径 (required) * @return */ public static X509Certificate getCertificate(String fileName) throws IOException { InputStream fis = new FileInputStream(fileName); try (BufferedInputStream bis = new BufferedInputStream(fis)) { CertificateFactory cf = CertificateFactory.getInstance("X509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(bis); cert.checkValidity(); return cert; } catch (CertificateExpiredException e) { throw new RuntimeException("证书已过期", e); } catch (CertificateNotYetValidException e) { throw new RuntimeException("证书尚未生效", e); } catch (CertificateException e) { throw new RuntimeException("无效的证书文件", e); } } /** * 获取证书 * @param inputStream 证书文件 * @return */ public static X509Certificate getCertificate(InputStream inputStream) { try { CertificateFactory cf = CertificateFactory.getInstance("X509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream); cert.checkValidity(); return cert; } catch (CertificateExpiredException e) { throw new RuntimeException("证书已过期", e); } catch (CertificateNotYetValidException e) { throw new RuntimeException("证书尚未生效", e); } catch (CertificateException e) { throw new RuntimeException("无效的证书", e); } } } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/SignUtils.java
New file @@ -0,0 +1,160 @@ package com.ruoyi.shop.util; import cn.hutool.http.HttpResponse; import com.ruoyi.common.core.utils.uuid.IdUtils; import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.FileInputStream; import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.spec.PKCS8EncodedKeySpec; import java.util.List; import java.util.Map; /** * @date 2020-03-18 11:02 * @description 签名相关 */ public class SignUtils { private static final Logger logger = LoggerFactory.getLogger(SignUtils.class); /** * 签名生成 * @param method 请求方法 如POST * @param urlSuffix 请求地址后缀 如/v3/certificates * @param mchId 电商平台商户号 * @param serialNo 电商平台商户API证书序列号 * @param body 请求请求报文主体,如果没有,就传空字符串 * @param mchPrivateKeyPath 电商平台商户API私钥 * @return */ public static String authorization(String method,String urlSuffix,String mchId,String serialNo,String body,String mchPrivateKeyPath) { try { String mchPrivateKey = CertificateUtils.getPrivateKey(mchPrivateKeyPath); //时间戳 String timestamp = Long.toString(System.currentTimeMillis()/1000); //随机数 String nonceStr = IdUtils.randomUUID(); //拼签名串 StringBuilder sb = signMessage(method,urlSuffix,timestamp,nonceStr,body); logger.info("sign original string:{}",sb.toString()); //计算签名 String sign = new String(Base64.encodeBase64(v3signRSA(sb.toString(),mchPrivateKey))); logger.info("sign result:{}",sign); //拼装http头的Authorization内容 String authorization ="WECHATPAY2-SHA256-RSA2048 mchid=\""+mchId+"\",nonce_str=\""+nonceStr+"\",signature=\""+sign+"\",timestamp=\""+timestamp+"\",serial_no=\""+serialNo+"\""; logger.info("authorization result:{}",authorization); return authorization; } catch (Exception e) { logger.error("authorization Exception result:{}",e); e.printStackTrace(); return null; } } /** * Authorization 签名串 * @param method * @param urlSuffix * @param timestamp * @param nonceStr * @param body * @return */ private static StringBuilder signMessage(String method,String urlSuffix,String timestamp,String nonceStr,String body) { return new StringBuilder() .append(method) .append("\n") .append(urlSuffix) .append("\n") .append(timestamp) .append("\n") .append(nonceStr) .append("\n") .append(body) .append("\n"); } /** * 私钥签名 * @param data 需要加密的数据 * @param mchPriKey * @return * @throws Exception */ public static byte[] v3signRSA(String data, String mchPriKey) throws Exception { //签名的类型 Signature sign = Signature.getInstance("SHA256withRSA"); //读取商户私钥,该方法传入商户私钥证书的内容即可 byte[] keyBytes = Base64.decodeBase64(mchPriKey); PKCS8EncodedKeySpec keySpec =new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey priKey = keyFactory.generatePrivate(keySpec); sign.initSign(priKey); sign.update(data.getBytes(StandardCharsets.UTF_8)); return sign.sign(); } public static boolean v3VerifyRSA(HttpResponse response,String wechatPubKeyPath) { if (response == null || StringUtils.isEmpty(wechatPubKeyPath)) { return false; } Map<String, List<String>> headers = response.headers(); //验证微信支付返回签名 String headsTimestamp = headers.get("Wechatpay-Timestamp").get(0); String headsNonce = headers.get("Wechatpay-Nonce").get(0); String headsSign = headers.get("Wechatpay-Signature").get(0); String resContent = response.body(); //拼装待签名串 StringBuilder sb =new StringBuilder(); sb.append(headsTimestamp).append("\n"); sb.append(headsNonce).append("\n"); sb.append(resContent).append("\n"); try { //验证签名 return v3VerifyRSA(sb.toString(), Base64.decodeBase64(headsSign.getBytes()), wechatPubKeyPath); } catch (Exception e) { e.printStackTrace(); return false; } } public static boolean v3VerifyRSA(String data,byte[] sign, String wechatPubKeyPath) throws Exception{ if(data == null || sign == null || wechatPubKeyPath == null){ return false; } CertificateFactory cf = CertificateFactory.getInstance("X.509"); FileInputStream in =new FileInputStream(wechatPubKeyPath); Certificate c = cf.generateCertificate(in); in.close(); PublicKey publicKey = c.getPublicKey(); Signature signature = Signature.getInstance("SHA256WithRSA"); signature.initVerify(publicKey); signature.update(data.getBytes(StandardCharsets.UTF_8)); boolean result = signature.verify(sign); if (result) { logger.info("v3VerifyRSA result:{}","签名验证成功"); } else { logger.info("v3VerifyRSA result:{}","签名验证失败"); } return result; } } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/WxShopUtils.java
New file @@ -0,0 +1,211 @@ package com.ruoyi.shop.util; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.shop.util.dto.ContactInfo; import com.ruoyi.shop.util.dto.IdCardInfo; import com.ruoyi.shop.util.dto.SubmitInfo; import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder; import com.wechat.pay.contrib.apache.httpclient.auth.*; import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager; import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException; import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException; import com.wechat.pay.contrib.apache.httpclient.util.PemUtil; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import javax.crypto.Cipher; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Base64; /** * @ClassName WxShopUtils * @Description TODO * @Author jqs * @Date 2023/6/19 11:11 * @Version 1.0 */ public class WxShopUtils { public void ApplymentSubMch() throws Exception { // 初始化httpClient CloseableHttpClient httpClient = createHttpClient(); //请求URL HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/"); // 请求body参数 String reqdata = "{" + "\"business_info\": {" + "\"merchant_shortname\":\"上海XXX有限公司\"," + "\"service_phone\":\"139XXXX\"," + "\"sales_info\": {" + "\"mini_program_info\": {" + "\"mini_program_pics\": [" + "\"0\":\"F8O5MNAOlYZyxZcLnWXkyk72coZ3CVX3XobPZng-xepKPTrcH_XMfrGGYLi1XFogMG9P25LSUX6gjXU5iPI74YqiRUDfORyw2d76wK3vzuQ\"" + "]," + "\"mini_program_sub_appid\":\"wx76c3f74c108876c2\"" + "}," + "\"mp_info\": {" + "\"mp_pics\": [" + "\"0\":\"F8O5MNAOlYZyxZcLnWXkys5TBxf0dyfesnyfNuquBMArHRfgCq8hDRdscDpblCcEgvgV5MkVch9IBEX7aatZCmI8k5Wdb_M8a4bYcmlg6V8\"" + "]," + "\"mp_sub_appid\":\"wx85c88c63bd22651f\"" + "}," + "\"sales_scenes_type\": [" + "\"0\":\"SALES_SCENES_MP\"," + "\"1\":\"SALES_SCENES_MINI_PROGRAM\"" + "]" + "}" + "}," + "\"subject_info\": {" + "\"business_license_info\": {" + "\"legal_person\":\"江XX\"," + "\"license_copy\":\"F8O5MNAOlYZyxZcLnWXkysZ5xo8fE3SHJ1pHUe6OJKmNIWtqUVyv4aY2-JLTgjDOSovWaKkBu3AbkjGuQXhesDzREu2pT_Yf_hxlFKPJMwQ\"," + "\"merchant_name\":\"上海XXX有限公司\"," + "\"license_number\":\"91310118MA1JXXXX\"" + "}," + "\"subject_type\":\"SUBJECT_TYPE_ENTERPRISE\"," + "\"identity_info\": {" + "\"owner\":true," + "\"id_doc_type\":\"IDENTIFICATION_TYPE_IDCARD\"," + "\"id_card_info\": {" + "\"id_card_copy\":\"F8O5MNAOlYZyxZcLnWXkyvLpqoz7MNRULxju0NqUCtLGBl_vm8Bhj9uAyuLyDART9UsA10spF9gbT3DEoM85HxPQOhMuilK0zLtOxAjPx58\"," + "\"card_period_end\":\"2035-12-28\"," + "\"card_period_begin\":\"2015-12-28\"," + "\"id_card_name\":\"JRMJGA7B7oSVS+krFeaQn4AvYZE2LL9tTwA+XXa9lYJU4AhS+Qheb7fhgo+D+hfa0v+ykU1BVvVo7NpCfgOYQqmYDyYF27Q/p4hB7IoqZLhJUE+hTG45VNoa9ASaKG79Hg+eGz4YTIHFGMFm1ljyg4fd5lGJixCqn38/gCfwm5x6vDOMVkFpqbUdR7klQwReGoG7iSlEpr4gZPqzItcBHiuXidMToKZTX1Lol1Lx52DHk0blcdh1CMRhv+wxQzF0lJMy/WtVyjKuB8daDbLJKTEwDx5KfkTZGHmGiaJnWY0qFX03sXsufvfB0Wj6Z37+nJnV16fplPmdr1/KEHamLw==\"," + "\"id_card_national\":\"F8O5MNAOlYZyxZcLnWXkyvcmQrkBXCIo2vZGUoM6ER-skL5k6IOhzeJ34tNNUggQIPfJbM_pzdg9jM4pQbkIm84_bKfi2JKNn99xIurNgwI\"," + "\"id_card_number\":\"V0quwnIu/PLbdQQ3/nzMqjvHtChDqed4Jpc3Iy2lgnFoWVNXguRWBHMYKHaLgLvnxLvO6TciMnrSw13QzUJD4ZnEIiks8gGTd+OCzl5Jl3F+sneQ+Js4akBnCSBQso/SERvi6vUqCeRhX1vtiFsmKtqlL8r/ssrFev4FoJEka5gGME1osTgcpMMTIR8rolIO1oXbl3e8z5RDics5xKH2Ogjzis73yq9M18ap0uRRdLWoX/cxeG3tbU1bi5jZsAU9hGHXs4BKTaHfrslsKIkqXR0f2Jpk7H5qtwAyP8glcALN7gB5DIOmBEIZ5zx2PrDm38CsZHstu0hF8beXV/PG2w==\"" + "}" + "}" + "}," + "\"business_code\":\"20201126100507000003\"," + "\"contact_info\": {" + "\"contact_name\":\"AD2jwe8eYFYfeoSmBpyRYUawyQgQkUoAajOlHnQM/JzproDF7hikLDouMr5Mb1W5otvdJZYEipG0HzwLpG9NXbqP6SXSpzQFb8fY5cpuXZsIbDy70lAybF0bbxJiJw1PHSd7KpMbu0XHqwlicePLUOw7HCNV6euQsKEvtusiWsaVrNNdKXpj3ONhyAg2ws4ibc56GUVoNll3osmGLPi6/bIn3pD6sjNThgPE9UzRQax0XPwgIpafIewQiVy0GNtv5P33wqPa9pAsdEmaLXNtQr2Ddjw5SYMInen1qbVO8NP0VhuWmYiAjd1WbkNnR+gbwsilBCYYeRuFbKfqatASnA==\"," + "\"mobile_phone\":\"GLc5+TuqJbxLeQO+CrKeDWF+7lZq9IsidIU4zcMpus4qsE8r1qNyvVMjrZfWLrjOItiQhXqkiKZs0B4M0UWAviWwmBhNWW0BJrauBjZbGZU+pLHC/2eOetdDC4sQqHN7Xw0N4tizqeQNu49n+DbSiv0TL09EcmNUUV9rImfjpVyo77MxKhPvdg3ODwS+IVvY2Tc9q11iBgaPIQ+XwoBaJGth1wdw0GLgEFUmX02TWxjHxq7f5O1RU3LjBlt1O+56ZZYpA+zr+IjQ/TwrIDp+4nk9v1oW2wtHuwrdqKrlLyJ1/zdoqwSddLuGxp8PwSM8CKobQP8TXhJu0S9pwLbNyg==\"," + "\"contact_id_number\":\"iC35X6SaOx4A4BEJ4fmM2oOkYRO5rEzRh2QRdrxFD3+HwmNjxddsm1LoqfhSiV34DAO2x3Ded3q2c1LJ7NHqa3/IGCDss4FKlgIyiu5AmzQTTYwsobmvVFxeSUXA4PnH/tUTfatJOuj+9Emt7fmnpO9uWeCLIn5CXaaABrXpO4mUu8qPBaoF2jTfbwBm6QiYX58kATyRrIvBRs6VorHJydXkz3P1hCejh8sAYoJXlNHnoajI+NEwiWX9RhwUadYLbMwww68cc7Yzehp3s6an0NWuC76Y4e7FQ/i5D9ZpUvLKUoYfFsZMnHrv/PhLxmv5l8gQs9/IkmOdYfRujKZJwQ==\"," + "\"contact_email\":\"ggK2ABtJ8bBiBo1iM7I6R2yEvhD6WC96d07gthnPGajc4lBCKpIqXjyNX8B97vc0OilyLRNUcySbT/KUejPyu4x9W6Ok6iS4zcerfKfIQkKs+3JXIMo0bu+GyI5O0fzRrPg1Mek2okfIjVK9wiTNJTzoGyz9twMXEaqqrOTbysyhnkqfrol5dad/TPg8qNWaBO3+Ma/hr1Tr0xeHWkKX3mBySC3NW49HM51x0PvFAwnStHr/8hiGzGpqAA3yJuYdlEwey3Lv+/bMmbTq+AyrYq9xX3q+n0VHuiSnzgICPwQiP4zXsoivA0bm7DSgcP1Oa6MjpGqMOS7AU1dHyak2GQ==\"" + "}," + "\"bank_account_info\": {" + "\"account_number\":\"Bfu6CzrRWlVTLZwjEK2CCXG0KRfGoIsbYs9IYmtFcV9FTEVLCcVCRGW6DVE2hMMr7U9tSdo7QqsptXZ7Zhciandyx9kRkY/VmPywurySvCbqpOLbx3AgmQY7H6/Ye542R0uloi6Pdp5FjqY/TdnlDcTS4cqv9iqU0DqKAUt7q+L6jZ8lrSlGFPI/1RkXCGAhlTSZ/iAJYDWzcN/E0cno9BQPYCmEIWldzj7W3Tmhi1eaZYX5mlLWnTOuVmMsRXIehb4y6LCi6T0kS7/c3GOFwlTzHVaaUgFqZhOL00h2G4Cl94uZfuVNO7KTiFaWtV61muEN6JfaSnFwRDSHxhtsRg==\"," + "\"bank_address_code\":\"310101\"," + "\"account_name\":\"RVBRWZKlmzrjkDmz4uEkaLQLU5q5xErXGoWhzDNdnQjRlfn1NVHL2EtIE+B0BULFNOHrX61q13lcgo9CDal9YJ/LjZkzAAsivwJZpNSRZbAsNNjqbYiiVhdnxYpwMqtukVgZAFgx0XMovOeSGX1+Dosc2vKJSsxtUw6wJXcZbMjvsX5/xamFTvRIx1J2a/q3ODBJ9URO5O2FDhGwLx8LQnFIv7xUDM3JXw7c6+eNy1OYTVwlj3/MIDQVw2eiPjpG1vC6K6PRwCI4wFZk1QwH99Xa3Wwvf+ek54j7FQTh0N703dK6jjonL5L6Lh9ZsckLx45InkARlPnU0KQpoK5g9w==\"," + "\"bank_account_type\":\"BANK_ACCOUNT_TYPE_CORPORATE\"," + "\"account_bank\":\"招商银行\"" + "}," + "\"settlement_info\": {" + "\"settlement_id\":\"716\"," + "\"qualification_type\":\"零售批发/生活娱乐/网上商城/其他\"" + "}" + "}"; StringEntity entity = new StringEntity(reqdata,"utf-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); httpPost.setHeader("Accept", "application/json"); httpPost.setHeader("Wechatpay-Serial", "XXXXXXXXXXXXXX"); //完成签名并执行请求 CloseableHttpResponse response = httpClient.execute(httpPost); try { int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == 200) { //处理成功 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity())); } else if (statusCode == 204) { //处理成功,无返回Body System.out.println("success"); } else { System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity())); throw new IOException("request failed"); } } finally { response.close(); } httpClient.close(); } /** * @description 创建httpClient * @author jqs * @date 2023/6/19 12:50 * @param * @return CloseableHttpClient */ private CloseableHttpClient createHttpClient() throws NotFoundException, IOException, GeneralSecurityException, HttpCodeException { String merchantId = ""; PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey( new FileInputStream("/path/to/apiclient_key.pem")); String merchantSerialNumber = ""; String apiV3Key = ""; // 获取证书管理器实例 CertificatesManager certificatesManager = CertificatesManager.getInstance(); // 向证书管理器增加需要自动更新平台证书的商户信息 certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId, new PrivateKeySigner(merchantSerialNumber, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8)); // ... 若有多个商户号,可继续调用putMerchant添加商户信息 // 从证书管理器中获取verifier Verifier verifier = certificatesManager.getVerifier(merchantId); WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create() .withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey) .withValidator(new WechatPay2Validator(verifier)); CloseableHttpClient httpClient = builder.build(); return httpClient; } //提交申请 /*public static String apply(SubmitInfo submitInfo) throws Exception { String bodyStr=convertToStr(submitInfo); HttpResponse response = HttpUtils.v3HttpExecute("POST",EcommerceUrl.APPLYMENTS, "自己系统的应用名称","服务商商户号","商户API证书序列号","平台证书序列号",requestParam,"商户API证书位置.pem",null); }*/ //加密申请信息 private static String convertToStr(SubmitInfo submitInfo) throws Exception { rsaEncryptSubmitInfo(submitInfo); return JSONObject.toJSONString(submitInfo); } private static void rsaEncryptSubmitInfo(SubmitInfo submitInfo) throws Exception { IdCardInfo idCardInfo=submitInfo.getId_card_info(); if(idCardInfo!=null){ idCardInfo.setId_card_name(rsaEncryptByCert(idCardInfo.getId_card_name())); idCardInfo.setId_card_number(rsaEncryptByCert(idCardInfo.getId_card_number())); } ContactInfo contactInfo=submitInfo.getContact_info(); if(contactInfo!=null){ contactInfo.setContact_name(rsaEncryptByCert(contactInfo.getContact_name())); contactInfo.setContact_id_card_number(rsaEncryptByCert(contactInfo.getContact_id_card_number())); contactInfo.setMobile_phone(rsaEncryptByCert(contactInfo.getMobile_phone())); if(!StringUtils.isEmpty(contactInfo.getContact_email())){ contactInfo.setContact_email(rsaEncryptByCert(contactInfo.getContact_email())); } } } private static String rsaEncryptByCert(String content) throws Exception { String platPrivateKey = ""; InputStream inStream=new ByteArrayInputStream(platPrivateKey.getBytes(StandardCharsets.UTF_8)); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate certificate = (X509Certificate)cf.generateCertificate(inStream); PublicKey publicKey=certificate.getPublicKey(); Cipher ci= Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"); ci.init(Cipher.ENCRYPT_MODE,publicKey); return Base64.getEncoder().encodeToString(ci.doFinal(content.getBytes(StandardCharsets.UTF_8))); } } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/WxUploadUtils.java
New file @@ -0,0 +1,26 @@ package com.ruoyi.shop.util; /** * @ClassName WxUploadUtils * @Description TODO * @Author jqs * @Date 2023/6/19 11:55 * @Version 1.0 */ public class WxUploadUtils { /*String filePath = "/your/home/hellokitty.png"; URI uri = new URI("https://api.mch.weixin.qq.com/v3/merchant/media/upload"); File file = new File(filePath); FileInputStream ins1 = new FileInputStream(file)) { String sha256 = DigestUtils.sha256Hex(ins1); try (InputStream ins2 = new FileInputStream(file)) { HttpPost request = new WechatPayUploadHttpPost.Builder(uri) .withImage(file.getName(), sha256, ins2) .build(); CloseableHttpResponse response1 = httpClient.execute(request); } }*/ } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/AccountInfo.java
New file @@ -0,0 +1,35 @@ package com.ruoyi.shop.util.dto; /** * @ClassName AccountInfo * @Description TODO * @Author jqs * @Date 2023/6/19 12:55 * @Version 1.0 */ import lombok.Data; import java.io.Serializable; /** * 结算银行账户 */ @Data public class AccountInfo implements Serializable { private static final long serialVersionUID=1L; /**账户类型*/ private String bank_account_type; /**开户银行*/ private String account_bank; /**开户名称*/ private String account_name; /**开户银行省市编码*/ private String bank_address_code; /**开户银行联行号*/ private String bank_branch_id; /**开户银行全称 (含支行)*/ private String bank_name; /**银行帐号*/ private String account_number; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/BusinessLicenseInfo.java
New file @@ -0,0 +1,33 @@ package com.ruoyi.shop.util.dto; /** * @ClassName BusinessLicenseInfo * @Description TODO * @Author jqs * @Date 2023/6/19 12:54 * @Version 1.0 */ import lombok.Data; import java.io.Serializable; /** * 营业执照/登记证书信息 */ @Data public class BusinessLicenseInfo implements Serializable { private static final long serialVersionUID=1L; /**证件扫描件*/ private String business_license_copy; /**证件注册号*/ private String business_license_number; /**商户名称*/ private String merchant_name; /**经营者/法定代表人姓名*/ private String legal_person; /**注册地址*/ private String company_address; /**营业期限*/ private String business_time; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/CertificateItem.java
New file @@ -0,0 +1,22 @@ package com.ruoyi.shop.util.dto; import lombok.Data; //平台证书item @Data public class CertificateItem { //加密的平台证书序列号 private String serial_no; //加密的平台证书序列号 private String effective_time; //证书弃用时间 private String expire_time; //证书加密信息 private EncryptedCertificateItem encrypt_certificate; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/ContactInfo.java
New file @@ -0,0 +1,31 @@ package com.ruoyi.shop.util.dto; /** * @ClassName ContactInfo * @Description TODO * @Author jqs * @Date 2023/6/19 12:55 * @Version 1.0 */ import lombok.Data; import java.io.Serializable; /** * 超级管理员信息 */ @Data public class ContactInfo implements Serializable { private static final long serialVersionUID=1L; /**超级管理员类型*/ private String contact_type; /**超级管理员姓名*/ private String contact_name; /**超级管理员身份证件号码*/ private String contact_id_card_number; /**超级管理员手机*/ private String mobile_phone; /**超级管理员邮箱*/ private String contact_email; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/EncryptedCertificateItem.java
New file @@ -0,0 +1,26 @@ package com.ruoyi.shop.util.dto; import lombok.Data; /** * @ClassName EncryptedCertificateItem * @Description TODO * @Author jqs * @Date 2023/6/19 14:12 * @Version 1.0 */ @Data public class EncryptedCertificateItem { //加密的平台证书序列号 private String algorithm; //加密的平台证书序列号 private String nonce; //证书弃用时间 private String associated_data; //证书弃用时间 private String ciphertext; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/IdCardInfo.java
New file @@ -0,0 +1,31 @@ package com.ruoyi.shop.util.dto; /** * @ClassName IdCardInfo * @Description TODO * @Author jqs * @Date 2023/6/19 12:54 * @Version 1.0 */ import lombok.Data; import java.io.Serializable; /** * 经营者/法人身份证信息 */ @Data public class IdCardInfo implements Serializable { private static final long serialVersionUID=1L; /**身份证人像面照片*/ private String id_card_copy; /**身份证国徽面照片*/ private String id_card_national; /**身份证姓名*/ private String id_card_name; /**身份证号码*/ private String id_card_number; /**身份证有效期限*/ private String id_card_valid_time; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/IdDocInfo.java
New file @@ -0,0 +1,29 @@ package com.ruoyi.shop.util.dto; /** * @ClassName IdDocInfo * @Description TODO * @Author jqs * @Date 2023/6/19 12:55 * @Version 1.0 */ import lombok.Data; import java.io.Serializable; /** * 经营者/法人其他类型证件信息 */ @Data public class IdDocInfo implements Serializable { private static final long serialVersionUID=1L; /**证件姓名*/ private String id_doc_name; /**证件号码*/ private String id_doc_number; /**证件照片*/ private String id_doc_copy; /**证件结束日期*/ private String doc_period_end; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/OrganizationCertInfo.java
New file @@ -0,0 +1,27 @@ package com.ruoyi.shop.util.dto; /** * @ClassName OrganizationCertInfo * @Description TODO * @Author jqs * @Date 2023/6/19 12:54 * @Version 1.0 */ import lombok.Data; import java.io.Serializable; /** * 组织机构代码证信息 */ @Data public class OrganizationCertInfo implements Serializable { private static final long serialVersionUID=1L; /**组织机构代码证照片*/ private String organization_copy; /**组织机构代码*/ private String organization_number; /**组织机构代码有效期限*/ private String organization_time; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/PlainCertificateItem.java
New file @@ -0,0 +1,23 @@ package com.ruoyi.shop.util.dto; import lombok.Data; /** * @ClassName PlainCertificateItem * @Description TODO * @Author jqs * @Date 2023/6/19 14:14 * @Version 1.0 */ @Data public class PlainCertificateItem { private String serialNo; private String effectiveTime; private String expireTime; private String plainCertificate; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/SalesSceneInfo.java
New file @@ -0,0 +1,29 @@ package com.ruoyi.shop.util.dto; /** * @ClassName SalesSceneInfo * @Description TODO * @Author jqs * @Date 2023/6/19 12:56 * @Version 1.0 */ import lombok.Data; import java.io.Serializable; /** * 店铺信息 */ @Data public class SalesSceneInfo implements Serializable { private static final long serialVersionUID=1L; /**店铺名称*/ private String store_name; /**店铺链接*/ private String store_url; /**店铺二维码*/ private String store_qr_code; /**小程序AppID*/ private String mini_program_sub_appid; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/dto/SubmitInfo.java
New file @@ -0,0 +1,51 @@ package com.ruoyi.shop.util.dto; /** * @ClassName SubmitInfo * @Description TODO * @Author jqs * @Date 2023/6/19 12:53 * @Version 1.0 */ import lombok.Data; import java.io.Serializable; /** * 进件信息 */ @Data public class SubmitInfo implements Serializable { private static final long serialVersionUID=1L; /**业务申请编号*/ private String out_request_no; /**主体类型*/ private String organization_type; /**营业执照/登记证书信息*/ private BusinessLicenseInfo business_license_info; /**组织机构代码证信息*/ private OrganizationCertInfo organization_cert_info; /**经营者/法人证件类型*/ private String id_doc_type; /**经营者/法人身份证信息*/ private IdCardInfo id_card_info; /**经营者/法人其他类型证件信息*/ private IdDocInfo id_doc_info; /**是否填写结算银行账户*/ private Boolean need_account_info; /**结算银行账户*/ private AccountInfo account_info; /**超级管理员信息*/ private ContactInfo contact_info; /**店铺信息*/ private SalesSceneInfo sales_scene_info; /**商户简称*/ private String merchant_shortname; /**特殊资质*/ private String qualifications; /**补充材料*/ private String business_addition_pics; /**补充说明*/ private String business_addition_desc; }