ManagementOKTravel/guns-admin/pom.xml
@@ -27,6 +27,13 @@ <artifactId>aws-java-sdk-s3</artifactId> <version>1.11.24</version> </dependency> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.8.10.ALL</version> </dependency> <!--<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> ManagementOKTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/SysCouponRecordController.java
@@ -104,8 +104,11 @@ if(SinataUtil.isNotEmpty(couponType)){ wrapper.eq("couponType",couponType); } wrapper.eq("companyId",ShiroKit.getUser().getObjectId()); wrapper.eq("companyType",ShiroKit.getUser().getRoleType()); Integer roleType = ShiroKit.getUser().getRoleType(); if(roleType != 1){ wrapper.eq("companyId",ShiroKit.getUser().getObjectId()); wrapper.eq("companyType",ShiroKit.getUser().getRoleType()); } wrapper.orderBy("id",false); return super.packForBT(sysCouponRecordService.selectPage(page,wrapper)); } ManagementOKTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/general/TUserController.java
@@ -135,9 +135,15 @@ if(null != invite){ String inviteUser1 = ""; if(1 == invite.getUserType()){ inviteUser1 = tUserService.selectById(invite.getInviteUserId()).getPhone(); TUser tUser = tUserService.selectById(invite.getInviteUserId()); if(null != tUser){ inviteUser1 = tUser.getPhone(); } }else{ inviteUser1 = driverService.selectById(invite.getInviteUserId()).getPhone(); TDriver tDriver = driverService.selectById(invite.getInviteUserId()); if(null != tDriver){ inviteUser1 = tDriver.getPhone(); } } stringObjectMap.put("inviteUser", inviteUser1); } ManagementOKTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/controller/specialTrain/TReassignController.java
@@ -11,9 +11,7 @@ import com.stylefeng.guns.modular.system.dao.OrderCancelMapper; import com.stylefeng.guns.modular.system.model.*; import com.stylefeng.guns.modular.system.service.*; import com.stylefeng.guns.modular.system.util.HttpRequestUtil; import com.stylefeng.guns.modular.system.util.PushURL; import com.stylefeng.guns.modular.system.util.ResultUtil; import com.stylefeng.guns.modular.system.util.*; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @@ -26,6 +24,7 @@ import javax.annotation.Resource; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; /** @@ -356,8 +355,201 @@ @Autowired private ITPubTransactionDetailsService itPubTransactionDetailsService; @Autowired private PayMoneyUtil payMoneyUtil; /** * 操作跨城改派管理 * optType 1=拒绝 2=取消 */ @RequestMapping(value = "/optCross") @ResponseBody public Object optCross(@RequestParam Integer tReassignId,@RequestParam Integer optType) { try { TReassign tReassign = tReassignService.selectById(tReassignId); if(tReassign.getState() == 3){//已改派 return "不能重复操作"; } if(tReassign.getState() == 4){//已改派 return "不能重复操作"; } if(tReassign.getState() == 5){//已改派 return "不能重复操作"; } Integer state = tReassign.getState(); ShiroUser user = ShiroKit.getUser(); if (1 == optType){ tReassign.setState(5); tReassign.setReviewer(user.getId()); tReassign.setReviewerType(2); tReassignService.updateById(tReassign); TOrderCrossCity orderCrossCity = itOrderCrossCityService.selectById(tReassign.getOrderId()); orderCrossCity.setState(orderCrossCity.getOldState()); itOrderCrossCityService.updateById(orderCrossCity); }else if (2 == optType){ tReassign.setState(4); tReassign.setReviewer(user.getId()); tReassign.setReviewerType(2); tReassignService.updateById(tReassign); TOrderCrossCity orderCrossCity = itOrderCrossCityService.selectById(tReassign.getOrderId()); if(orderCrossCity.getState() > 5 && orderCrossCity.getState() != 11){ return ResultUtil.error("订单状态不在可取消范围内"); } orderCrossCity.setState(10); itOrderCrossCityService.updateById(orderCrossCity); //修改司机信息 LineShiftDriver lineShiftDriver = lineShiftDriverMapper.selectById(orderCrossCity.getLineShiftDriverId()); lineShiftDriver.setLaveSeat(lineShiftDriver.getLaveSeat() + orderCrossCity.getPeopleNumber() > lineShiftDriver.getTotalSeat() ? lineShiftDriver.getTotalSeat() : lineShiftDriver.getLaveSeat() + orderCrossCity.getPeopleNumber()); String seat = ""; String[] split = orderCrossCity.getSeatNumber().split(","); for(String s : split){ seat += s + ","; } seat = lineShiftDriver.getLaveSeatNumber() + "," + seat.substring(0, seat.length() - 1); //总和大于总座位数的情况 if(lineShiftDriver.getLaveSeat() + orderCrossCity.getPeopleNumber() > lineShiftDriver.getTotalSeat()){ seat = ""; for(int i = 1; i <= lineShiftDriver.getTotalSeat(); i++){ seat += i + ","; } seat = seat.substring(0, seat.length() - 1); } lineShiftDriver.setLaveSeatNumber(seat); lineShiftDriverMapper.updateById(lineShiftDriver); if(lineShiftDriver.getLaveSeat() >= lineShiftDriver.getTotalSeat()){ TDriver driver = itDriverService.selectById(tReassign.getOriginalDriverId()); driver.setState(2); itDriverService.updateById(driver); } //调用推送 Map<String,String> map = new HashMap<>(); map.put("id", orderCrossCity.getId().toString()); map.put("orderType", "3"); String result = HttpRequestUtil.postRequest(PushURL.cancel_order_url, map); System.out.println("跨城取消:【orderId="+orderCrossCity.getId().toString()+"】,调用接口:"+result); //已支付的情况下进行退款操作 if(null != orderCrossCity.getPayType() && null != orderCrossCity.getPayMoney()){ if(orderCrossCity.getPayType() == 3){//余额支付 TUser tUser = userService.selectById(orderCrossCity.getUserId()); tUser.setBalance(tUser.getBalance().add(orderCrossCity.getPayMoney())); userService.updateById(tUser); //添加交易明细 transactionDetailsService.saveData(orderCrossCity.getUserId(), "跨城改派取消退款", orderCrossCity.getPayMoney().doubleValue(), 1, 1, 1, 3, tReassign.getOrderId()); }else{ PaymentRecord query = paymentRecordService.query(1, null, null, tReassign.getOrderId(), 3, null, 2).get(0); if(null == query){ return ResultUtil.error("订单还未进行支付"); } if(query.getPayType() == 1){//微信 Map<String, String> map1 = payMoneyUtil.wxRefund(query.getCode(), orderCrossCity.getId() + "_3_" + UUIDUtil.getRandomCode(3), query.getAmount().toString(), query.getAmount().toString(), "/user/base/cancleOrderWXPay"); if(!"SUCCESS".equals(map1.get("return_code"))){ return ResultUtil.error(map1.get("return_msg")); } //添加交易明细 transactionDetailsService.saveData(query.getUserId(), "跨城改派取消退款", query.getAmount(), 1, 1, query.getType(), 3, orderCrossCity.getId()); }else{//支付宝 // Map<String, String> map1 = payMoneyUtil.aliRefund(query.getCode(), query.getAmount().toString()); // if(!"10000".equals(map1.get("code"))){ // return ResultUtil.error(map1.get("msg")); // } // //添加交易明细 // transactionDetailsService.saveData(query.getUserId(), "跨城改派取消退款", query.getAmount(), 1, 1, query.getType(), 3, orderCrossCity.getId()); } } //添加负的收入明细 List<Income> incomes = incomeService.selectList(new EntityWrapper<Income>().eq("type", 2).eq("incomeId", tReassign.getOrderId()).eq("orderType", 3)); for(Income income : incomes){ if(income.getUserType() == 2){//处理司机的收入 TDriver driver = itDriverService.selectById(income.getObjectId()); driver.setBalance(driver.getBalance().subtract(new BigDecimal(income.getMoney()))); driver.setLaveBusinessMoney(new BigDecimal(driver.getLaveBusinessMoney()).subtract(new BigDecimal(income.getMoney())).doubleValue()); itDriverService.updateById(driver); } Income income1 = new Income(); BeanUtils.copyProperties(income, income1); income1.setMoney(income.getMoney() * -1); income1.setId(null); income1.setInsertTime(new Date()); incomeService.insert(income1); } } //添加取消记录 OrderCancel orderCancel = new OrderCancel(); orderCancel.setOrderId(tReassign.getOrderId()); orderCancel.setOrderType(tReassign.getOrderType()); orderCancel.setReason("调度端取消订单"); orderCancel.setRemark("调度“" + user.getName() + "-" + user.getId() + "”执行取消操作"); orderCancel.setState(2); orderCancel.setInsertTime(new Date()); orderCancel.setUserType(3); orderCancel.setUserId(user.getId()); orderCancelMapper.insert(orderCancel); } if(state == 2){//退款操作 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); String out_refund_no = sdf.format(new Date()) + "_" + tReassign.getId(); Double money = tReassign.getMoney(); if(tReassign.getPayType() == 1){//微信 Map<String, String> map = payMoneyUtil.wxRefund(tReassign.getPayOrder(), out_refund_no, money.toString(), money.toString(), "/dispatch/base/order/reassignRefundCallback"); if(null == map || !"SUCCESS".equals(map.get("return_code"))){ System.err.println(map.get("return_msg")); return ResultUtil.error(map.get("return_msg")); } tReassign.setReviewer(ShiroKit.getUser().getId()); tReassign.setReviewerType(2); tReassignService.updateById(tReassign); //添加交易明细 transactionDetailsService.saveData(tReassign.getOriginalDriverId(), "跨城改派拒绝退款", money, 1, 1, 2, 3, tReassign.getOrderId()); } if(tReassign.getPayType() == 2){//支付宝 // Map<String, String> map = payMoneyUtil.aliRefund(tReassign.getPayOrder(), money.toString()); // if(null != map && "10000".equals(map.get("code"))){ // tReassign.setReviewer(ShiroKit.getUser().getId()); // tReassign.setReviewerType(2); // tReassignService.updateById(tReassign); // //添加交易明细 // transactionDetailsService.saveData(tReassign.getOriginalDriverId(), "跨城改派拒绝退款", money, 1, 1, 2, 3, tReassign.getOrderId()); // } // if(null == map || !"10000".equals(map.get("code"))){ // System.err.println(map.get("msg")); // return ResultUtil.error(map.get("msg")); // } } if(tReassign.getPayType() == 3){//余额 TDriver tDriver = itDriverService.selectById(tReassign.getOriginalDriverId()); tDriver.setBalance(tDriver.getBalance().add(new BigDecimal(money))); itDriverService.updateById(tDriver); } } //增加交易明细 TPubTransactionDetails details = new TPubTransactionDetails(); details.setUserId(tReassign.getOriginalDriverId()); details.setInsertTime(new Date()); details.setRemark("【跨城改派】:改派失败或订单取消"); details.setMoney(new BigDecimal(tReassign.getMoney())); details.setState(1); details.setType(1); details.setUserType(2); details.setOrderType(3); details.setOrderId(tReassign.getOrderId()); itPubTransactionDetailsService.insert(details); }catch (Exception e){ e.printStackTrace(); } return SUCCESS_TIP; } ManagementOKTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/HttpClientUtil.java
New file @@ -0,0 +1,343 @@ package com.stylefeng.guns.modular.system.util; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.http.NameValuePair; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 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 org.apache.http.message.BasicNameValuePair; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; import org.springframework.stereotype.Component; import javax.net.ssl.SSLContext; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.security.KeyStore; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; /** * http工具类 */ @Component public class HttpClientUtil { private CloseableHttpClient httpClient; private CloseableHttpResponse httpResponse; private RequestConfig requestConfig; /** * 创建一个httpClient对象 */ private void getHttpCline(){ //1.创建连接池管理器 PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(60000, TimeUnit.MILLISECONDS); connectionManager.setMaxTotal(1000); connectionManager.setDefaultMaxPerRoute(50); //2.创建httpclient对象 this.httpClient = HttpClients.custom() .setConnectionManager(connectionManager) .disableAutomaticRetries() .build(); } private RequestConfig getRequestConfig(){ return RequestConfig.custom() .setConnectTimeout(60000) .setSocketTimeout(60000) .build(); } /** * 创建一个POST请求实例 * @param url 请求地址 * @param params 请求参数 */ private void setPostHttpRequset(String url, Map<String, Object> params, Map<String, String> header, String contentType){ HttpPost httpPost = new HttpPost(url); httpPost.setConfig(this.getRequestConfig()); if(null != header){ for(String key : header.keySet()){ httpPost.setHeader(key, header.get(key)); } } List<NameValuePair> list = new ArrayList<>(); if(null != params){ Set<String> keys = params.keySet(); for(String key : keys){ list.add(new BasicNameValuePair(key, params.get(key).toString())); } } try { switch (contentType){ case "form": httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8")); break; case "json": ObjectMapper objectMapper = new ObjectMapper(); String s =objectMapper.writeValueAsString(params); System.err.println(s); httpPost.setEntity(new StringEntity(s, Charset.forName("UTF-8"))); break; } this.getHttpCline(); if(null == this.httpClient){ this.getHttpCline(); } httpResponse = this.httpClient.execute(httpPost); } catch (IOException e) { e.printStackTrace(); this.close(); } } /** * 获取get请求实例 * @param url 请求地址 * @param params 请求参数 */ private void setGetHttpRequset(String url, Map<String, Object> params, Map<String, String> header){ StringBuffer sb = new StringBuffer(); String p = ""; if(null != params){ Set<String> keys = params.keySet(); for(String key : keys){ sb.append(key + "=" + params.get(key) + "&"); } p = "?" + sb.substring(0, sb.length() - 1); } HttpGet httpGet = new HttpGet(url + p); if(null != header){ for(String key : header.keySet()){ httpGet.setHeader(key, header.get(key)); } } this.getHttpCline(); if(null == this.httpClient){ this.getHttpCline(); } try { httpResponse = this.httpClient.execute(httpGet); } catch (IOException e) { e.printStackTrace(); this.close(); } } /** * 发送http请求 * @param mothed "GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS" * @param url 请求地址 * @param params 请求参数 * @param header 请求头 * @param contentType 参数请求方式form/json * @return */ public String pushHttpRequset(String mothed, String url, Map<String, Object> params, Map<String, String> header, String contentType){ String content = null; switch (mothed){ case "GET": this.setGetHttpRequset(url, params, header); break; case "POST": this.setPostHttpRequset(url, params, header, contentType); break; } if(httpResponse.getStatusLine().getStatusCode() == 200){ try { content = EntityUtils.toString(httpResponse.getEntity()); this.close(); return content; } catch (IOException e) { e.printStackTrace(); this.close(); } } if(httpResponse.getStatusLine().getStatusCode() == 201){ content = "{\"status\":201}"; this.close(); return content; }else{ try { System.err.println("返回状态码:" + httpResponse.getStatusLine() + "。"); content = EntityUtils.toString(httpResponse.getEntity()); this.close(); return content; } catch (IOException e) { e.printStackTrace(); this.close(); } } this.close(); return content; } /** * 发送XML请求 * @param url 请求地址 * @param xml XML数据 * @param header 自定义请求头 * @return */ public String pushHttpRequsetXml(String url, String xml, Map<String, String> header){ HttpPost httpPost = new HttpPost(url); for(String key : header.keySet()){ httpPost.setHeader(key, header.get(key)); } httpPost.setHeader("Content-Type", "application/xml"); try { httpPost.setEntity(new StringEntity(xml, "UTF-8")); this.getHttpCline(); if(null == this.httpClient){ this.getHttpCline(); } httpResponse = this.httpClient.execute(httpPost); String content = null; if(httpResponse.getStatusLine().getStatusCode() == 200){ try { content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); this.close(); return content; } catch (IOException e) { e.printStackTrace(); this.close(); } }else{ try { content = "返回状态码:" + httpResponse.getStatusLine() + "。" + EntityUtils.toString(httpResponse.getEntity()); this.close(); return content; } catch (IOException e) { e.printStackTrace(); this.close(); } } this.close(); return content; } catch (IOException e) { e.printStackTrace(); this.close(); } return null; } /** * 请求https发送XML请求 * @param url 接口路径 * @param xml 内容 * @param header 请求头 * @param certPassword 证书密码 * @param certPath 证书路径 * @param certType 证书类型 * @return * @throws Exception */ public String pushHttpsRequsetXml(String url, String xml, Map<String, String> header, String certPassword, String certPath, String certType) throws Exception{ HttpPost httpPost = new HttpPost(url); for(String key : header.keySet()){ httpPost.setHeader(key, header.get(key)); } httpPost.setHeader("Content-Type", "application/xml"); try { httpPost.setEntity(new StringEntity(xml, "UTF-8")); this.getHttpCline(); this.initCert(certPassword, certPath, certType); httpResponse = this.httpClient.execute(httpPost); String content = null; if(httpResponse.getStatusLine().getStatusCode() == 200){ try { content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); } catch (IOException e) { e.printStackTrace(); this.close(); } }else{ try { content = "返回状态码:" + httpResponse.getStatusLine() + "。" + EntityUtils.toString(httpResponse.getEntity()); } catch (IOException e) { e.printStackTrace(); this.close(); } } this.close(); return content; } catch (IOException e) { e.printStackTrace(); this.close(); } return null; } /** * 初始化https对象(带证书) * @param key 证书密码 * @param certPath 证书路径 * @param certType 证书类型 * @throws Exception */ private void initCert(String key, String certPath, String certType) throws Exception { KeyStore keyStore = KeyStore.getInstance(certType); // ClassPathResource cp = new ClassPathResource(certPath); InputStream inputStream = new FileInputStream(new File(certPath)); // InputStream instream = cp.getInputStream(); try { keyStore.load(inputStream, key.toCharArray()); } finally { inputStream.close(); } SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] {"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); this.httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); } /** * 关闭资源 */ private void close(){ try { if(null != httpClient){ httpClient.close(); } if(null != httpResponse){ httpResponse.close(); } } catch (IOException e) { e.printStackTrace(); }finally { try { if(null != httpClient){ httpClient.close(); } if(null != httpResponse){ httpResponse.close(); } }catch (Exception e){ e.printStackTrace(); } } } } ManagementOKTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/MD5AndKL.java
New file @@ -0,0 +1,112 @@ package com.stylefeng.guns.modular.system.util; import java.security.MessageDigest; public class MD5AndKL { /** * MD5加码。32位 * * @param inStr * @return */ public static String MD5(String inStr) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); } catch (Exception e) { throw new RuntimeException(e.toString()); } byte[] md5Bytes = md5.digest(inStr.getBytes()); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++) { int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) { hexValue.append("0"); } hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } /** * 可逆的加密算法 * * @param inStr * @return */ public static String KL(String inStr) { char[] a = inStr.toCharArray(); for (int i = 0; i < a.length; i++) { a[i] = (char) (a[i] ^ 't'); } String s = new String(a); return s; } /** * 加密后解密 * * @param inStr * @return */ public static String JM(String inStr) { char[] a = inStr.toCharArray(); for (int i = 0; i < a.length; i++) { a[i] = (char) (a[i] ^ 't'); } String k = new String(a); return k; } private static String byteArrayToHexString(byte b[]) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) resultSb.append(byteToHexString(b[i])); return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) n += 256; int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } public static String MD5Encode(String origin, String charsetname) { String resultString = null; try { resultString = new String(origin); MessageDigest md = MessageDigest.getInstance("MD5"); if (charsetname == null || "".equals(charsetname)){ resultString = byteArrayToHexString(md.digest(resultString.getBytes())); }else{ resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); } } catch (Exception exception) { exception.printStackTrace(); } return resultString; } private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; public static void main(String args[]) { System.out.println("MD5后再加密:" + KL(MD5("123456"))); System.out.println(MD5("123456")); // System.out.println("加密:" + KL(MD5("123456"))); // s = KL(s); // System.out.println("解密:" + KL("81dc9bdb52d04dc20036dbd8313ed055")); // System.out.println("解密:" + JM(KL(s))); // System.out.println("解密为MD5后的:" + KL(KL(MD5(s)))); // System.out.println(JM("5d62957bb57d3e49dcf48a0df064be4c")); // System.out.println(MD5AndKL.KL(MD5AndKL.MD5("admin"+"87654321"))); } } ManagementOKTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/PayMoneyUtil.java
New file @@ -0,0 +1,648 @@ package com.stylefeng.guns.modular.system.util; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.apache.commons.collections.map.HashedMap; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.HttpServletRequest; import java.io.*; import java.math.BigDecimal; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.util.*; /** * 第三方支付工具类 */ @Component public class PayMoneyUtil { @Value("${wx.appid}") private String appid;//微信appid @Value("${wx.appletsAppid}") private String appletsAppid;//微信小程序appid @Value("${wx.mchId}") private String mchId;//微信商户号 @Value("${wx.key}") private String key;//微信商户号 @Value("${callbackPath}") private String callbackPath;//支付回调网关地址 @Autowired private HttpClientUtil httpClientUtil; /** * 微信统一下单 * @param body 商品描述 * @param attach 附加数据 * @param out_trade_no 商户订单号 * @param total_fee 标价金额 * @param notify_url 通知地址 * @param tradeType 交易类型 * @return */ public ResultUtil weixinpay(String body, String attach, String out_trade_no, String total_fee, String notify_url, String tradeType, String openId) throws Exception{ int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue(); String hostAddress = null; try { hostAddress = InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } String nonce_str = UUIDUtil.getRandomCode(16); Map<String, Object> map = new HashMap<>(); map.put("appid", "APP".equals(tradeType) ? appid : appletsAppid); map.put("mch_id", mchId); map.put("nonce_str", nonce_str); map.put("body", body); map.put("attach", attach);//存储订单id map.put("out_trade_no", out_trade_no);//存储的订单code map.put("total_fee", i); map.put("spbill_create_ip", hostAddress); map.put("notify_url", callbackPath + notify_url); map.put("trade_type", tradeType); if("JSAPI".equals(tradeType)){ map.put("openid", openId); } String s = this.weixinSignature(map); map.put("sign", s); String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; //设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_XML); StringBuffer xmlString = new StringBuffer(); Set<String> strings = map.keySet(); String[] keys = {}; keys = strings.toArray(keys); Arrays.sort(keys); xmlString.append("<xml>"); for(int l = 0; l < keys.length; l++){ xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">"); } xmlString.append("</xml>"); Map<String, String> map1 = null; String body1 = httpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()); //将结果xml解析成map body1 = body1.replaceAll("<!\\[CDATA\\[",""); body1 = body1.replaceAll("]]>", ""); try { map1 = this.xmlToMap(body1, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } String return_code = map1.get("return_code"); if("SUCCESS".equals(return_code)){ String result_code = map1.get("result_code"); if("SUCCESS".equals(result_code)){ String type = map1.get("trade_type"); String prepay_id = map1.get("prepay_id"); switch (type){ case "JSAPI": //重新进行签名后返回给前端 Map<String, Object> map2 = new HashMap<>(); map2.put("appId", map1.get("appid")); map2.put("nonceStr", map1.get("nonce_str")); map2.put("package", "prepay_id=" + prepay_id); map2.put("signType", "MD5"); map2.put("timeStamp", new Date().getTime() + ""); String s2 = this.weixinSignature(map2); map2.put("prepay_id", prepay_id); map2.put("mch_id", map1.get("mch_id")); map2.put("trade_type", map1.get("trade_type")); map2.put("sign", s2); return ResultUtil.success(map2); case "NATIVE": String code_url = map1.get("code_url"); return ResultUtil.success(code_url); case "APP": //重新进行签名后返回给前端 Map<String, Object> map3 = new HashMap<>(); map3.put("appid", appid); map3.put("noncestr", nonce_str); map3.put("package", "Sign=WXPay"); map3.put("partnerid", mchId); map3.put("prepayid", prepay_id); map3.put("timestamp", new Date().getTime() / 1000); String s1 = this.weixinSignature(map3); map3.put("sign", s1); System.err.println(map3); return ResultUtil.success(map3); } return null; }else{ System.err.println(map1.get("err_code_des")); return ResultUtil.error(map1.get("err_code_des")); } }else{ System.err.println(map1.get("return_msg") + appid + "----" + mchId); return ResultUtil.error(map1.get("return_msg"), new JSONObject()); } } /** * 微信支付成功后的回调处理 * @param request */ public Map<String, String> weixinpayCallback(HttpServletRequest request){ try { String param = this.getParam(request); param = param.replaceAll("<!\\[CDATA\\[",""); param = param.replaceAll("]]>", ""); Map<String, String> map = this.xmlToMap(param, "UTF-8"); String return_code = map.get("return_code"); if("SUCCESS".equals(return_code)){ String result_code = map.get("result_code"); if("SUCCESS".equals(result_code)){ Map<String, String> map1 = new HashedMap(); map1.put("nonce_str", map.get("nonce_str")); map1.put("out_trade_no", map.get("out_trade_no"));//存储的订单code map1.put("attach", map.get("attach"));//存储订单id map1.put("total_fee", map.get("total_fee")); map1.put("transaction_id", map.get("transaction_id"));//微信支付订单号 String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; map1.put("result", result); return map1; }else{ // System.err.println(map.get("err_code_des")); } }else{ // System.err.println(map.get("return_msg")); } } catch (IOException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } return null; } /** * 微信扫码收款 * @param body 商品描述 * @param attach 附加数据 * @param nonce_str 随机字符串 * @param out_trade_no 商户订单号 * @param total_fee 订单金额 * @param auth_code 授权码 扫码支付授权码,设备读取用户微信中的条码或者二维码信息(注:用户付款码条形码规则:18位纯数字,以10、11、12、13、14、15开头) * @return */ public ResultUtil wxScanQRCodePay(String body, String attach, String nonce_str, String out_trade_no, String total_fee, String auth_code){ int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue(); String hostAddress = null; try { InetAddress address = InetAddress.getLocalHost(); hostAddress = address.getHostAddress(); } catch (UnknownHostException e) { e.printStackTrace(); } String randomCode = null; try { randomCode = UUIDUtil.getRandomCode(10); } catch (Exception e) { e.printStackTrace(); } Map<String, Object> map = new HashMap<>(); map.put("appid", appid); map.put("mch_id", mchId); map.put("nonce_str", nonce_str);//存储的支付人员id,员工扫描二维码支付的时候存储的是收款员工id map.put("body", body); map.put("attach", attach);//存储的费用月份数据,员工扫描二维码支付的时候存储的是收费项id map.put("out_trade_no", randomCode + "_" + out_trade_no);//存储的房间id map.put("total_fee", i); map.put("spbill_create_ip", hostAddress); map.put("auth_code", auth_code); String s = this.weixinSignature(map); map.put("sign", s); String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; //设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_XML); StringBuffer xmlString = new StringBuffer(); Set<String> strings = map.keySet(); String[] keys = {}; keys = strings.toArray(keys); Arrays.sort(keys); xmlString.append("<xml>"); for(int l = 0; l < keys.length; l++){ xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">"); } xmlString.append("</xml>"); Map<String, String> map1 = null; String body1 = httpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()); //将结果xml解析成map body1 = body1.replaceAll("<!\\[CDATA\\[",""); body1 = body1.replaceAll("]]>", ""); try { map1 = this.xmlToMap(body1, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } String return_code = map1.get("return_code"); if("SUCCESS".equals(return_code)){ String result_code = map1.get("result_code"); if("SUCCESS".equals(result_code)){ String type = map1.get("trade_type"); switch (type){ case "JSAPI": break; case "NATIVE": String code_url = map1.get("code_url"); return ResultUtil.success(code_url); case "APP": String prepay_id = map1.get("prepay_id"); //重新进行签名后返回给前端 Map<String, Object> map2 = new HashMap<>(); map2.put("appid", appid); map2.put("noncestr", nonce_str); map2.put("package", "Sign=WXPay"); map2.put("partnerid", mchId); map2.put("prepayid", prepay_id); map2.put("timestamp", new Date().getTime() + ""); String s1 = this.weixinSignature(map2); map2.put("pac", "Sign=WXPay"); map2.put("sign", s1); // System.err.println(map2); return ResultUtil.success(map2); } return null; }else{ // System.err.println(map1.get("err_code_des")); return ResultUtil.error(map1.get("err_code_des")); } }else{ // System.err.println(map1.get("return_msg") + appid + "----" + mchId); return ResultUtil.error(map1.get("return_msg"), new JSONObject()); } } /** * 支付宝扫码收款 * @param data * @return */ public Object aliScanQRCodePay(String data){ return null; } /** * 微信退款申请 * @param transaction_id 微信订单号。微信生成的订单号,在支付通知中有返回 * @param out_refund_no 商户退款单号。商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。 * @param total_fee 订单金额。订单总金额,单位为分,只能为整数 * @param refund_fee 退款金额。退款总金额,订单总金额,单位为分,只能为整数 * @param notify_url 退款结果通知url。异步接收微信支付退款结果通知的回调地址,通知URL必须为外网可访问的url,不允许带参数 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效。 * @return */ public Map<String, String> wxRefund(String transaction_id, String out_refund_no, String total_fee, String refund_fee, String notify_url){ int tf = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue(); int rf = new BigDecimal(refund_fee).multiply(new BigDecimal("100")).intValue(); String nonce_str = UUIDUtil.getRandomCode(); Map<String, Object> map = new HashMap<>(); map.put("appid", appid); map.put("mch_id", mchId); map.put("nonce_str", nonce_str); map.put("transaction_id", transaction_id); map.put("out_refund_no", out_refund_no); map.put("total_fee", tf); map.put("refund_fee", rf); map.put("notify_url", callbackPath + notify_url); String s = this.weixinSignature(map); map.put("sign", s); String url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; //设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_XML); StringBuffer xmlString = new StringBuffer(); Set<String> strings = map.keySet(); String[] keys = {}; keys = strings.toArray(keys); Arrays.sort(keys); xmlString.append("<xml>"); for(int l = 0; l < keys.length; l++){ xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">"); } xmlString.append("</xml>"); Map<String, String> map1 = null; String body1 = null; try { String certPath = "D:\\xianning\\apiclient_cert.p12"; body1 = httpClientUtil.pushHttpsRequsetXml(url, xmlString.toString(), new HashMap<>(), "1680621323", certPath, "PKCS12"); } catch (Exception e) { e.printStackTrace(); } System.err.println("退款返回信息========"+body1); //将结果xml解析成map body1 = body1.replaceAll("<!\\[CDATA\\[",""); body1 = body1.replaceAll("]]>", ""); try { map1 = this.xmlToMap(body1, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } System.err.println("跨城推送取消====="+map1); String return_code = map1.get("return_code"); Map<String, String> map2 = new HashMap<>(); if("SUCCESS".equals(return_code)){ String result_code = map1.get("result_code"); if("SUCCESS".equals(result_code)){ map2.put("return_code", result_code); map2.put("refund_id", String.valueOf(map1.get("refund_id")));//微信退款订单号 map2.put("refund_fee", String.valueOf(map1.get("refund_fee")));//退款金额 return map2; }else{ map2.put("return_code", result_code); map2.put("return_msg", map1.get("err_code_des")); return map2; } }else{ map2.put("return_code", return_code); map2.put("return_msg", map1.get("return_msg")); return map2; } } /** * 微信退款成功后的回调处理 * @param request * @return */ public Map<String, String> wxRefundCallback(HttpServletRequest request){ try { String param = this.getParam(request); param = param.replaceAll("<!\\[CDATA\\[",""); param = param.replaceAll("]]>", ""); Map<String, String> map = this.xmlToMap(param, "UTF-8"); String return_code = map.get("return_code"); if("SUCCESS".equals(return_code)){ String req_info = map.get("req_info");//加密信息请用商户秘钥进行解密 String s = this.wxDecrypt(req_info); s = s.replaceAll("<!\\[CDATA\\[",""); s = s.replaceAll("]]>", ""); map = this.xmlToMap(s, "UTF-8"); Map<String, String> map1 = new HashMap<>(); map1.put("refund_id", map.get("refund_id")); map1.put("out_refund_no", map.get("out_refund_no")); return map1; }else{ // System.err.println(map.get("return_msg")); } } catch (IOException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (NoSuchProviderException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } return null; } /** * 查询微信支付订单 * @return * @throws Exception */ public ResultUtil queryWXOrder() throws Exception{ String url = "https://api.mch.weixin.qq.com/pay/orderquery"; String nonce_str = UUIDUtil.getRandomCode(16); Map<String, Object> map = new HashMap<>(); map.put("appid", appid); map.put("mch_id", mchId); map.put("transaction_id", nonce_str);//微信订单号 map.put("nonce_str", nonce_str);//随机字符串 String s = this.weixinSignature(map); map.put("sign", s); //设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_XML); StringBuffer xmlString = new StringBuffer(); Set<String> strings = map.keySet(); String[] keys = {}; keys = strings.toArray(keys); Arrays.sort(keys); xmlString.append("<xml>"); for(int l = 0; l < keys.length; l++){ xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">"); } xmlString.append("</xml>"); Map<String, String> map1 = null; String body1 = httpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()); //将结果xml解析成map body1 = body1.replaceAll("<!\\[CDATA\\[",""); body1 = body1.replaceAll("]]>", ""); try { map1 = this.xmlToMap(body1, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } String return_code = map1.get("return_code"); if("SUCCESS".equals(return_code)){ String result_code = map1.get("result_code"); if("SUCCESS".equals(result_code)){ String type = map1.get("trade_type"); switch (type){ case "JSAPI": break; case "NATIVE": String code_url = map1.get("code_url"); return ResultUtil.success(code_url); case "APP": String trade_state = map1.get("trade_state"); String time_end = map1.get("time_end"); Map<String, Object> map2 = new HashMap<>(); map2.put("trade_state", trade_state);//订单状态SUCCESS—支付成功,REFUND—转入退款,NOTPAY—未支付,CLOSED—已关闭,REVOKED—已撤销(刷卡支付),USERPAYING--用户支付中,PAYERROR--支付失败(其他原因,如银行返回失败) map2.put("time_end", time_end);//订单支付时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。 return ResultUtil.success(map2); } return null; }else{ System.err.println(map1.get("err_code_des")); return ResultUtil.error(map1.get("err_code_des")); } }else{ System.err.println(map1.get("return_msg") + appid + "----" + mchId); return ResultUtil.error(map1.get("return_msg"), new JSONObject()); } } /** * 获取请求内容 * @param request * @return * @throws IOException */ private String getParam(HttpServletRequest request) throws IOException { // 读取参数 InputStream inputStream; StringBuilder sb = new StringBuilder(); inputStream = request.getInputStream(); String s; BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); while ((s = in.readLine()) != null) { sb.append(s); } in.close(); inputStream.close(); return sb.toString(); } /** * 微信下单的签名算法 * @param map * @return */ private String weixinSignature(Map<String, Object> map){ try { Set<Map.Entry<String, Object>> entries = map.entrySet(); List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(entries); // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() { public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) { return (o1.getKey()).toString().compareTo(o2.getKey()); } }); // 构造签名键值对的格式 StringBuilder sb = new StringBuilder(); for (Map.Entry<String, Object> item : infoIds) { if (item.getKey() != null || item.getKey() != "") { String key = item.getKey(); Object val = item.getValue(); if (!(val == "" || val == null)) { sb.append(key + "=" + val + "&"); } } } sb.append("key=" + key); String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式 return sign; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 微信退款成功后的解密 * @param req_info * @return */ private String wxDecrypt(String req_info) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { byte[] decode = Base64.getDecoder().decode(req_info); String sign = MD5AndKL.MD5Encode(key, "UTF-8").toLowerCase(); if (Security.getProvider("BC") == null){ Security.addProvider(new BouncyCastleProvider()); } Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); SecretKeySpec secretKeySpec = new SecretKeySpec(sign.getBytes(), "AES"); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); return new String(cipher.doFinal(decode)); } public static void main(String[] ages){ // PayMoneyUtil payMoneyUtil = new PayMoneyUtil(); // payMoneyUtil.weixinpay("测试", "123", "12.5", ""); } /** * xml转map * @param xml * @param charset * @return * @throws UnsupportedEncodingException * @throws DocumentException */ public static Map<String, String> xmlToMap(String xml, String charset) throws UnsupportedEncodingException, DocumentException { Map<String, String> respMap = new HashMap<String, String>(); SAXReader reader = new SAXReader(); Document doc = reader.read(new ByteArrayInputStream(xml.getBytes(charset))); Element root = doc.getRootElement(); xmlToMap(root, respMap); return respMap; } public static Map<String, String> xmlToMap(Element tmpElement, Map<String, String> respMap){ if (tmpElement.isTextOnly()) { respMap.put(tmpElement.getName(), tmpElement.getText()); return respMap; } @SuppressWarnings("unchecked") Iterator<Element> eItor = tmpElement.elementIterator(); while (eItor.hasNext()) { Element element = eItor.next(); xmlToMap(element, respMap); } return respMap; } } ManagementOKTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/system/util/UUIDUtil.java
New file @@ -0,0 +1,78 @@ package com.stylefeng.guns.modular.system.util; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; /** * 定义生成随机码的工具类 */ public class UUIDUtil { private int i = 1; /** * 定义生成原生的UUID随机码 * @return */ public static String getNativeUUID(){ return UUID.randomUUID().toString(); } /** * 生成32位随机码 * @return */ public static String getRandomCode(){ return UUIDUtil.getNativeUUID().replaceAll("-", ""); } /** * 获取给定长度的随机码 * @param num * @return * @throws Exception */ public static String getRandomCode(Integer num) throws Exception{ String str = null; if(0 < num){ if(num % 32 > 0){ Integer s = num / 32; Integer l = num % 32; StringBuffer sb = new StringBuffer(); for(int i = 0; i < s; i++){ sb.append(UUIDUtil.getRandomCode()); } sb.append(UUIDUtil.getRandomCode().substring(0, l)); str = sb.toString(); }else if(num % 32 == 0){ Integer s = num / 32; StringBuffer sb = new StringBuffer(); for(int i = 0; i < s; i++){ sb.append(UUIDUtil.getRandomCode()); } str = sb.toString(); }else{ str = UUIDUtil.getRandomCode().substring(0, num); } }else{ throw new Exception("参数只能大于0"); } return str; } /** * 获取根据当前时间的字符串数据 * @return */ public synchronized static String getTimeStr(){ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmssS"); return simpleDateFormat.format(new Date()); } }