diff --git a/nursing-unit-admin/nu-admin-biz/pom.xml b/nursing-unit-admin/nu-admin-biz/pom.xml index d76ec65..d70c790 100644 --- a/nursing-unit-admin/nu-admin-biz/pom.xml +++ b/nursing-unit-admin/nu-admin-biz/pom.xml @@ -10,6 +10,24 @@ nu-admin-biz + + + com.github.wechatpay-apiv3 + wechatpay-apache-httpclient + 0.4.9 + + + + com.github.wechatpay-apiv3 + wechatpay-java + 0.2.17 + + + + com.github.wxpay + wxpay-sdk + 0.0.3 + com.nursingunit.boot nu-admin-local-api diff --git a/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/wechart/controller/WechatPayController.java b/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/wechart/controller/WechatPayController.java new file mode 100644 index 0000000..20e4d97 --- /dev/null +++ b/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/wechart/controller/WechatPayController.java @@ -0,0 +1,297 @@ +package com.nu.modules.wechart.controller; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.json.JSONObject; +import com.nu.modules.bizEmployeesInfo.entity.BizEmployeesInfo; +import com.nu.modules.wechart.entity.WechatpayConfig; +import com.wechat.pay.java.core.Config; +import com.wechat.pay.java.core.RSAAutoCertificateConfig; + +import com.wechat.pay.java.core.exception.ServiceException; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.NotificationParser; +import com.wechat.pay.java.service.payments.jsapi.JsapiService; +import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension; +import com.wechat.pay.java.service.payments.jsapi.model.*; +import com.wechat.pay.java.service.payments.model.Transaction; +import io.swagger.models.auth.In; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.apache.http.HttpEntity; +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.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; +import com.wechat.pay.java.core.notification.RequestParam; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +@RestController +@RequestMapping("/weiXinPay") +@Slf4j +public class WechatPayController { + @Autowired + public WechatpayConfig wechatpayConfig; + + + /** + * Native下单 + * 调用统一下单API,生成支付二维码 + */ + @PostMapping("/native") + public Map nativePay(@RequestBody Map params) throws Exception { + + Config config = + new RSAAutoCertificateConfig.Builder() + .merchantId(wechatpayConfig.getMchId()) + .privateKeyFromPath(wechatpayConfig.getPrivateKeyPath()) + .merchantSerialNumber(wechatpayConfig.getMchSerialNo()) + .apiV3Key(wechatpayConfig.getApiV3Key()) + .build(); + // 构建service + JsapiService service = new JsapiService.Builder().config(config).build(); + PrepayRequest request = new PrepayRequest(); + String title = params.get("title"); + String openId = params.get("openId"); + String amountPrice = params.get("amountPrice"); + + Amount amount = new Amount(); + amount.setTotal(Integer.parseInt(amountPrice)); + request.setAmount(amount); + request.setAppid(wechatpayConfig.getAppid()); + request.setMchid(wechatpayConfig.getMchId()); + request.setDescription(title); + request.setNotifyUrl(wechatpayConfig.getNotifyDomain()); + request.setOutTradeNo(IdUtil.simpleUUID()); + Payer payer = new Payer(); + payer.setOpenid(openId); + request.setPayer(payer); + // 调用下单方法,得到应答 + PrepayResponse response = service.prepay(request); + log.info("prepayId:" + response.getPrepayId()); + Map map = prepayWithRequestPayment(request,config); + return map; + } + + + /** + * 返回调起支付的参数 + * @return + */ + private Map prepayWithRequestPayment(PrepayRequest request,Config config){ + Map map = new HashMap<>(); + JsapiServiceExtension jse = new JsapiServiceExtension.Builder().config(config).build(); + PrepayWithRequestPaymentResponse response = jse.prepayWithRequestPayment(request); + map.put("appId",response.getAppId()); + map.put("timeStamp",response.getTimeStamp()); + map.put("nonceStr",response.getNonceStr()); + map.put("package",response.getPackageVal()); + map.put("signType",response.getSignType()); + map.put("paySign",response.getPaySign()); + return map; + } + @PostMapping("/callback") + public String courseNative(HttpServletRequest request, HttpServletResponse response) { + + System.out.println("11111111111111"); + NotificationConfig config = + new RSAAutoCertificateConfig.Builder() + .merchantId(wechatpayConfig.getMchId()) + .apiV3Key(wechatpayConfig.getApiV3Key()) + .merchantSerialNumber(wechatpayConfig.getMchSerialNo()) + .privateKeyFromPath(wechatpayConfig.getPrivateKeyPath()) + .build(); + System.out.println("222222222222222"+config); + // 从请求头中获取信息 + String timestamp = request.getHeader("Wechatpay-Timestamp"); + String nonce = request.getHeader("Wechatpay-Nonce"); + String signature = request.getHeader("Wechatpay-Signature"); + String singType = request.getHeader("Wechatpay-Signature-Type"); + String wechatPayCertificateSerialNumber = request.getHeader("Wechatpay-Serial"); + + System.out.println("333333333333333"); + String requestBody = getRequestBody(request); + + System.out.println("333333333333333"+requestBody); + // 初始化解析器 NotificationParser + NotificationParser parser = new NotificationParser(config); + System.out.println("444444444444444444444" + parser); + RequestParam requestParam = new RequestParam.Builder() + .serialNumber(wechatPayCertificateSerialNumber) + .nonce(nonce) + .signature(signature) + .timestamp(timestamp) + .signType(singType) + .body(requestBody) + .build(); + System.out.println("555555555555555555555" + requestParam); + try { + // 这个Transaction是微信包里面的 + Transaction decryptObject = parser.parse( requestParam, Transaction.class); + + System.out.println("666666666666666666:"+decryptObject); + return decryptObject.getTradeState().toString(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + + } + // 获取请求头里的数据 + private String getRequestBody(HttpServletRequest request) { + StringBuffer sb = new StringBuffer(); + try ( + ServletInputStream inputStream = request.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + ) { + String line; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + } catch (IOException e) { + System.out.println("读取数据流异常:"+e); + } + return sb.toString(); + } + /** + * 查询订单 + * @param params + * @return + */ + @PostMapping("/queryOrderById") + public Map queryOrderById(@RequestBody Map params) throws Exception { + + + + Config config = + new RSAAutoCertificateConfig.Builder() + .merchantId(wechatpayConfig.getMchId()) + .privateKeyFromPath(wechatpayConfig.getPrivateKeyPath()) + .merchantSerialNumber(wechatpayConfig.getMchSerialNo()) + .apiV3Key(wechatpayConfig.getApiV3Key()) + .build(); + String prepay_id = params.get("prepay_id"); + Map map = new HashMap<>(); + if(StringUtils.isEmpty(prepay_id)){ + map.put("code","400"); + map.put("msg","参数错误,prepay_id为空!"); + return map; + } + // 构建service + JsapiService service = new JsapiService.Builder().config(config).build(); + QueryOrderByIdRequest queryRequest = new QueryOrderByIdRequest(); + queryRequest.setMchid(wechatpayConfig.getMchId()); + queryRequest.setTransactionId(prepay_id); + + try { + Transaction result = service.queryOrderById(queryRequest); + System.out.println(result.getTradeState()); + map.put("code","200"); + map.put("msg",result); + } catch (ServiceException e) { + // API返回失败, 例如ORDER_NOT_EXISTS + System.out.printf("code=[%s], message=[%s]\n", e.getErrorCode(), e.getErrorMessage()); + System.out.printf("reponse body=[%s]\n", e.getResponseBody()); + } + return map; + } + + + + public static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";// 获取access + + // 获取token + public static String getToken(String apiurl, String appid, String secret) + { + String turl = String.format( + "%s?grant_type=client_credential&appid=%s&secret=%s", apiurl, + appid, secret); + System.out.println("turl:" + turl); + HttpClient client = new DefaultHttpClient(); + HttpGet get = new HttpGet(turl); + System.out.println("get:" + get); + JsonParser jsonparer = new JsonParser();// 初始化解析json格式的对象 + String result = null; + try + { + HttpResponse res = client.execute(get); + System.out.println("res:" + res); + String responseContent = null; // 响应内容 + HttpEntity entity = res.getEntity(); + System.out.println("entity:" + entity); + responseContent = EntityUtils.toString(entity, "UTF-8"); + JsonObject json = jsonparer.parse(responseContent) + .getAsJsonObject(); + System.out.println("json:" + json); + // 将json字符串转换为json对象 + if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) + { + if (json.get("errcode") != null) + {// 错误时微信会返回错误码等信息,{"errcode":40013,"errmsg":"invalid appid"} + } + else + {// 正常情况下{"access_token":"ACCESS_TOKEN","expires_in":7200} + result = json.get("access_token").getAsString(); + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + // 关闭连接 ,释放资源 + client.getConnectionManager().shutdown(); + return result; + } + } + + + @PostMapping("/getUserInfo") + public JSONObject getWxUserInfo(@RequestBody Map params) throws Exception { +// String accessToken = getToken(GET_TOKEN_URL, "wx8fc3e4305d2fbf0b", "3bf3dd4ec72f591432db6b28c2c044e5");// 获取token + String accessToken = params.get("access_token"); + String openid = params.get("openid"); + System.out.println("---------token-------"+accessToken); + // 构造请求URL + String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN"; + + // 发送HTTP请求,并获取返回结果 + HttpGet httpGet = new HttpGet(requestUrl); + System.out.println("---------httpGet-------"+httpGet); + CloseableHttpClient httpClient = HttpClients.createDefault(); + System.out.println("---------httpClient-------"+httpClient); + CloseableHttpResponse httpResponse = httpClient.execute(httpGet); + System.out.println("---------httpResponse-------"+httpResponse); + HttpEntity httpEntity = httpResponse.getEntity(); + System.out.println("---------httpEntity-------"+httpEntity); + String responseJson = EntityUtils.toString(httpEntity, "UTF-8"); + System.out.println("---------responseJson-------"+responseJson); + // 解析返回结果,获取手机号 + JSONObject jsonObject = new JSONObject(responseJson); + System.out.println("---------jsonObject-------"+jsonObject); + return jsonObject; + } +} diff --git a/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/wechart/entity/WXConfig.java b/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/wechart/entity/WXConfig.java new file mode 100644 index 0000000..06224b1 --- /dev/null +++ b/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/wechart/entity/WXConfig.java @@ -0,0 +1,89 @@ +package com.nu.modules.wechart.entity; + +import com.github.wxpay.sdk.WXPayConfig; +import lombok.Data; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * @author fang + * @date 2020/2/26 + */ +@Data +public class WXConfig implements WXPayConfig { + private byte[] certData; + + public String appId; + public String key; + public String mchId; + + /*public WXConfigUtil() throws Exception { + String certPath = ClassUtils.getDefaultClassLoader().getResource("").getPath()+"/weixin/apiclient_cert.p12";//从微信商户平台下载的安全证书存放的路径 + File file = new File(certPath); + InputStream certStream = new FileInputStream(file); + this.certData = new byte[(int) file.length()]; + certStream.read(this.certData); + certStream.close(); + }*/ + + public byte[] getCertData() { + return certData; + } + + public void setCertData(byte[] certData) { + this.certData = certData; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public void setKey(String key) { + this.key = key; + } + + public String getMchId() { + return mchId; + } + + public void setMchId(String mchId) { + this.mchId = mchId; + } + + @Override + public String getAppID() { + return this.appId; + } + + //parnerid,商户号 + @Override + public String getMchID() { + return this.mchId; + } + + @Override + public String getKey() { + return this.key; + } + + @Override + public InputStream getCertStream() { + ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData); + return certBis; + } + + @Override + public int getHttpConnectTimeoutMs() { + return 8000; + } + + @Override + public int getHttpReadTimeoutMs() { + return 10000; + } +} diff --git a/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/wechart/entity/WechatpayConfig.java b/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/wechart/entity/WechatpayConfig.java new file mode 100644 index 0000000..00bb7b0 --- /dev/null +++ b/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/wechart/entity/WechatpayConfig.java @@ -0,0 +1,38 @@ +package com.nu.modules.wechart.entity; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Slf4j +@Data +public class WechatpayConfig { + // 商户ID + @Value("${wxpay.mch-id}") + private String mchId; + + // 商户API证书序列号 + @Value("${wxpay.mch-serial-no}") + private String mchSerialNo; + + // 商户私钥文件 + @Value("${wxpay.private-key-path}") + private String privateKeyPath; + + // APIv3密钥 + @Value("${wxpay.api-v3-key}") + private String apiV3Key; + + // APPID + @Value("${wxpay.appid}") + private String appid; + + // 接收结果通知地址 + @Value("${wxpay.notify-domain}") + private String notifyDomain; + + + +} diff --git a/nursing-unit-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java b/nursing-unit-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java index 3961900..29db857 100644 --- a/nursing-unit-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java +++ b/nursing-unit-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java @@ -116,6 +116,8 @@ public class ShiroConfig { filterChainDefinitionMap.put("/sys/checkAuth", "anon"); //授权接口排除 filterChainDefinitionMap.put("/h5Api/nuBizAdvisoryInfo/**", "anon"); //授权接口排除 filterChainDefinitionMap.put("/h5Api/nuBaseInfo/**", "anon"); //授权接口排除 + filterChainDefinitionMap.put("/weiXinPay/**", "anon"); //微信支付接口 + filterChainDefinitionMap.put("/weiXinPay2/**", "anon"); //微信支付接口 //update-begin--Author:scott Date:20221116 for:排除静态资源后缀 filterChainDefinitionMap.put("/", "anon"); diff --git a/nursing-unit-invoicing/nu-invoicing-biz/src/main/java/com/nu/modules/ConfigMaterial/controller/ConfigMaterialCategoryController.java b/nursing-unit-invoicing/nu-invoicing-biz/src/main/java/com/nu/modules/ConfigMaterial/controller/ConfigMaterialCategoryController.java index d8670da..5b8b39d 100644 --- a/nursing-unit-invoicing/nu-invoicing-biz/src/main/java/com/nu/modules/ConfigMaterial/controller/ConfigMaterialCategoryController.java +++ b/nursing-unit-invoicing/nu-invoicing-biz/src/main/java/com/nu/modules/ConfigMaterial/controller/ConfigMaterialCategoryController.java @@ -10,6 +10,8 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; import org.jeecg.common.api.vo.Result; import org.jeecg.common.system.query.QueryGenerator; import org.jeecg.common.system.query.QueryRuleEnum; @@ -83,6 +85,8 @@ public class ConfigMaterialCategoryController extends JeecgController queryWrapper = QueryGenerator.initQueryWrapper(configMaterialCategory, req.getParameterMap()); + queryWrapper.eq(StringUtils.isNotBlank(configMaterialCategory.getCategoryId()),"category_id",configMaterialCategory.getCategoryId()); + queryWrapper.eq(StringUtils.isNotBlank(configMaterialCategory.getTypeId()),"type_id",configMaterialCategory.getTypeId()); Page page = new Page(pageNo, pageSize); IPage pageList = configMaterialCategoryService.selectMaterialList(page, queryWrapper); return Result.OK(pageList); @@ -171,7 +175,6 @@ public class ConfigMaterialCategoryController extends JeecgController selectMaterialList(Page page, QueryWrapper queryWrapper) { IPage pageList = baseMapper.selectMaterialList(page,queryWrapper); List list = pageList.getRecords(); - //按照list 的categoryId字段获取相同数据开始和结束标记 - String categoryId = list.get(0).getCategoryId(); - int outerStart = 0; // 一级分组起始索引 - for (int i = 0; i < list.size(); i++) { - ConfigMaterialCategory configMaterialCategory = list.get(i); - // 当遇到不同的categoryId时处理当前分组 - if (!configMaterialCategory.getCategoryId().equals(categoryId)) { - processAllGroups(list, outerStart, i - 1); // 处理完整个一级分组 - outerStart = i; // 重置一级起始位置 - categoryId = configMaterialCategory.getCategoryId(); + if(list.size()>0){ + //按照list 的categoryId字段获取相同数据开始和结束标记 + String categoryId = list.get(0).getCategoryId(); + int outerStart = 0; // 一级分组起始索引 + for (int i = 0; i < list.size(); i++) { + ConfigMaterialCategory configMaterialCategory = list.get(i); + // 当遇到不同的categoryId时处理当前分组 + if (!configMaterialCategory.getCategoryId().equals(categoryId)) { + processAllGroups(list, outerStart, i - 1); // 处理完整个一级分组 + outerStart = i; // 重置一级起始位置 + categoryId = configMaterialCategory.getCategoryId(); + } } + processAllGroups(list, outerStart, list.size() - 1); // 处理最后一组 } - processAllGroups(list, outerStart, list.size() - 1); // 处理最后一组 return pageList; } diff --git a/nursing-unit-system/nu-system-start/src/main/resources/cert/apiclient_key.pem b/nursing-unit-system/nu-system-start/src/main/resources/cert/apiclient_key.pem new file mode 100644 index 0000000..3ba51a7 --- /dev/null +++ b/nursing-unit-system/nu-system-start/src/main/resources/cert/apiclient_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQD9DP/vMUP0rTVZ +rvoOXgpTpyzptWTuMLUBHfY63kpZ7cYEekkznIuqt1XE3HezlwL4uOrzaMR59sGJ +MD2kvh0V7wxlWYtA1nTLkUi5jUW8DmoMR2wlVOm+jV9SpG2AH4w/coMDHCIuMbge +ZncsIN3wJrAwSRFCWM2La1Bjzrt7z9GR/LwhX60RN9UvKvhcnFvuJWYe2wd62NQa +NvdGlApt8MW/WBFNLBaPlCM1Tp5TLOapVna9a42cRhzWW/gJr5i02nGQX1kFC5h1 +On+DvUJGpXdLl/gr+f6Otr4TrvxOTVY4IU20UO/TkI1+cH9VXwY4VlNN1WrzVVtd +fN96ZCwVAgMBAAECggEAdZW103rL/gUCVmMlVMnD+K0lBJBCjx/Y6+T1RtOGLxV6 +vxfnrfDfQXuhgjGD+dKBEfwzSNn0+kt8EPh2nHeu4kNLOkkKmR1N9k3TQk1wCvuT +sZL6oLo9R0s/8RHww+lk7RKT6D0JcPeve4jXdYzsNCx2EGnTeEX1dQRvvYERw2yY +hbp6jgtE0XZztK4+54aPqBmVrQCzhJdXwNmfNhspjMCUGN9SQ+NPyKr6Q9mL78px ++WWnmCPktekPAiBV1P87uVCuc1BWG7n2J1dyiUicqQ4T2v5S7KFJPjOMwy+dB0Pd +WxWAv3V6f3bQHUGV2Vj5NjRm+2z2DXTYofvso5u53QKBgQD/bEayMuJhsSGqV56Q +W3sqKTwB+MgEISbeONXkfOppazUxuGmUi1Je9d+7IujMCf8eP26OudIdW2CLY/VP +7EzOpx4Y16B75GuSfdIfgCrmaVIePD1yiC9rzhsQ/UkgP/gAof8BiY6GbSQXkSg2 +W9MkeWFretgkuygYymI/y+rqLwKBgQD9n1oFHmYizu5abfKdXsGWQPIvqaO93FLF +nh3QM/VXAGC7R/oNqjlAD8ZJmaIOGDMwrfeZ4wDwdgs/DeIBDTpuuNG+KWSgP28X +NryIUyuu/4q0a4uIMhwdykKpPVVJ7bnPjihRY0HE3LdDqhnY5JLuGhGE9T7zD1KT +RwejCiRw+wKBgF8nmELEwB+C3LbYA4NmAUFYsTlO1DztmMxKwixn+PAi92M5f2PO +b3ZfBOVzgOSaiMdc/DQBt+wl4ZasO3R15LtL+ONqWSgulYCyjPgdSF4kOGp5KK8l +Wv0/gEfZBEgWbK7XqueItmcP+9Unx6JQnR1GduuSjTlJ3As4QlfgAPkTAoGABKjM +ypNIZRNQJbEnZ+S5wbzntiBztaU6kA7blVufAj4riMVFvsKF0rt3dRqxc3jWV+qa +ReV5uvEwO7RRlptbm3UhxVCVXKxNqiuDQy3j+48OSUpAgfwJsDJrDxjlXDpV045V +B0m/h5JWe5PAbc+lM2KfN8YZpfV+Gt6PMVuaV8kCgYBw+uhCANG+FHnFmNXR7E8m +HID8xorhnz6d9hwJKo2cE+DHQzjX03fiV9suq2QiYz50YX06CN/xPyPy+XRQh3Rj +xhd8jNnNUKJygXjGzlLVbO394ePcq9hNONds31m1wJILFAq3+LIrtWq3XUAyJpBp +w+xnruEDdBI/mm2Y76V8zg== +-----END PRIVATE KEY----- diff --git a/pom.xml b/pom.xml index 9447740..ef998d8 100644 --- a/pom.xml +++ b/pom.xml @@ -158,13 +158,13 @@ spring-cloud-starter-alibaba-nacos-discovery 2021.0.5.0 - + com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config 2021.0.5.0 - + org.springframework.boot spring-boot-starter-amqp