Commit f4d4a093 by yangjiarong

1.0.1版本交付_v1.0.1_8_05

parent 907aaa19
No preview for this file type
No preview for this file type
......@@ -203,8 +203,9 @@
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.17.9.ALL</version>
<version>4.31.72.ALL</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
......@@ -255,6 +256,12 @@
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<dependency>
<groupId>org.scalaj</groupId>
<artifactId>scalaj-http_2.13</artifactId>
<version>2.4.2</version>
</dependency>
<!-- 不兼容-->
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<!-- <dependency>-->
......
#Generated by Maven
#Fri Jul 29 19:03:45 CST 2022
version=1.0.2-snapshot
groupId=com.icloud.boot
artifactId=icloud-common
/Users/yang/方卡/pay/ocloud-api/ocloud-api_v2-7_22/icloud-framework/icloud-common/src/main/java/com/icloud/framework/common/package-info.java
......@@ -111,7 +111,12 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- <dependency>-->
<dependency>
<groupId>org.scalaj</groupId>
<artifactId>scalaj-http_2.13</artifactId>
</dependency>
<!-- <dependency>-->
<!--这个包的版本有问题,会报错-->
<!-- <groupId>org.redisson</groupId>-->
<!-- <artifactId>redisson-spring-boot-starter</artifactId>-->
......
......@@ -36,29 +36,14 @@ public class PayService {
}
}
public CommonResult CreatePayClient_ALIPAY_WAP(PayEntiy pe) {
String privateKey="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDbrl+dSmi0sTHKebUL0n1ySETbbQQYZJ2lgMPmGG1mnAaGBUNQpb0pcnseMyv6swnVCBfH7nFJEOeLoVpkx5j2/gYMIx5i5fFPsdu8dDyPh3FyCSjmDmkMmhiNiPk//1+P99UPnNiN1xW8noOZRhphd8Bh0XM+sIRU/O6FDr+ymKSdySHPlF7tAKXMDILahkHN5SB8jyKNCDeZj3gYNzcD0Zyl2HYYr5haDtfr0NE0XI8c8yD4czs7FuuP51tEB37GFN0TAGz4chKfz9Mc8xZ/aBUlIa6wUk0LJEbjujP3tf+I797R4yyYJ8GhwDN9YkDspPIrw3N+a2chhpT5WzitAgMBAAECggEBALggVT+uqEga5JLCo/5+tGpfLGeF3hLb8k5PuOJYwwln6QfXzW4BHKVqsMrFNS1xduI5YEVRE16cbpZX7T3fFdSfYU42+TcHZ9TWTEiOXFwot+tOxhrdJStM1Rt8HP2I+/3dSZVGbzOjfTKU4dRML7xV9MeIGEIJDUF2piycCgyT2ovT0vbBNkKdfCfFjUNPkJmItLa3wuPs6+9CQdd6hwomPNHNVUFgfOLP7OLGSZuzKjjo6pul+oU3ZfpND3V3TZ+lD8i1Qps/EKfHN8fMt38lJcbRvQAso7DsqT7ZNzfaD8SpXY7ulBPVe+f7aoRAlqQXizIBhOK+TfYiQ2CIUoECgYEA7jD+YrRfFj31052HRykvmIY5YZTb6Emk6eiqTpbgkWbbC1KsWRuHR1854AvQ1aRk82BxtrxZxuwF2sEVQeGiaDxSK0KnLDMLMNmVe/Jr4NGhbcvVZuzU7L+ZM8e8XcIFy2nljWQQ5x50AZDoGY70eQkNFAxg8TVWmhzNZ9rWpj0CgYEA7BsXk1BRcBMtr+cYZ/2/cqUNKsw9BWVwL4lwTNn9A6PHt06+gNKD6+NUevYtp09xqENryIXc26dt/9OWk6BPd7kp6H3c1xGyByW9hC58vHhC6pcgSUiJ6diwVsqD0z2dTW7/3kbLPRpvSf/waHPfLOWkmnkkavtbiynzP4F4czECgYA/Dd85t+/4Dlz2MRxvnRqJcPbduy9f1ab/eOUkutImC6lu3OrdB+mO3kmO4vHcrJFA0EYqDsBhZXfDShvbfeSlXVqPMyzYCYcr3l2xGyKtuDDYxP3wKj/PkIT47SYTV9p618S54kSLOkeRZo/avDpBlEDPDtvW3rzXPUqu9IKgLQKBgQCLiYdpXLKElhEOQHnAG8slqj4Z6RK3ObgPoB5qjPpnSEgkIbmc0M1+f5/R++QHWYBGfXIZ1GMuvcjYxOfc34WXsCsAaEI4KREaAEf88qxthnWlxyMhrGk1dwbghFdcZLGurccySoya1CCpj0U5tiFTm3SohqfrQhpcKLLF+XKCQQKBgGSYZZ65F+WSDUrP1DfIkHzJcpVj4rFGLretIi3PJItFazq8pahWh3EllogUxMuntknOPwdbfptP/LCN/pTLCCYiwINgeCSZaEIlsSiUEJTmO5NE4YwEpSpbEWNuEDS1JRZrxRAFkh1WlL629vsV9jkS93nkDpc1OS7Cdp8ILsDE";
String APP_PUBLIC_KEY ="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA265fnUpotLExynm1C9J9ckhE220EGGSdpYDD5hhtZpwGhgVDUKW9KXJ7HjMr+rMJ1QgXx+5xSRDni6FaZMeY9v4GDCMeYuXxT7HbvHQ8j4dxcgko5g5pDJoYjYj5P/9fj/fVD5zYjdcVvJ6DmUYaYXfAYdFzPrCEVPzuhQ6/spiknckhz5Re7QClzAyC2oZBzeUgfI8ijQg3mY94GDc3A9Gcpdh2GK+YWg7X69DRNFyPHPMg+HM7Oxbrj+dbRAd+xhTdEwBs+HISn8/THPMWf2gVJSGusFJNCyRG47oz97X/iO/e0eMsmCfBocAzfWJA7KTyK8NzfmtnIYaU+Vs4rQIDAQAB";
String notify_url = "http://127.0.0.1:8080";
String alipayPublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAghBg+LB71Ivm+3v50LWhAmU69vZqcnWq9nNvIbp/PrDMpp+bfc8vwkEWEEkstF5Jo/kIhFPYWbECAJw8UJsJ7usTjfIZvasXv2KxRUnrsCV94Azn8jV7meHgxpE4LTpBiIqrN+AVf6SLjLlBmwCiQ78g7RbF/pIvsjtKiEPVhB7NAMttNorPVib/mIPbMjzWGXJf/GR6s1oaTs9vNcFbyjMBYd8h9KelyIQFvLaDeB1ffWxWJJ1o52wmgeoGlAhlHaF1dHdf3X9MXCKNpyZtDw9akwqJPAaG+vxKdSVUS9YDVhzBU3fSI05hb5waYeMsxAi6JAPHEluvRT03HzgDnwIDAQAB";
// 创建配置
// 创建配置
AlipayPayClientConfig config = new AlipayPayClientConfig();
config.setAppId(pe.getAppid());
config.setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD);
// config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX);
config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT);
config.setPrivateKey(pe.getPrivateKey());
config.setAlipayPublicKey(pe.getAlipayPublicKey());
// 创建客户端
// Long channelId = RandomUtil.randomLong();
payClientFactory.createOrUpdatePayClient(pe.getChannelId() ,PayChannelEnum.ALIPAY_WAP.getCode(), config);
PayClient client = payClientFactory.getPayClient(pe.getChannelId());
// 发起支付
PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(pe);
CommonResult<?> result = client.unifiedOrder(reqDTO);
System.out.println(JsonUtils.toJsonString(result));
String s = JsonUtils.toJsonString(result);
// public CommonResult CreatePayClient_ALIPAY_WAP(PayEntiy pe) {
// String privateKey="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDbrl+dSmi0sTHKebUL0n1ySETbbQQYZJ2lgMPmGG1mnAaGBUNQpb0pcnseMyv6swnVCBfH7nFJEOeLoVpkx5j2/gYMIx5i5fFPsdu8dDyPh3FyCSjmDmkMmhiNiPk//1+P99UPnNiN1xW8noOZRhphd8Bh0XM+sIRU/O6FDr+ymKSdySHPlF7tAKXMDILahkHN5SB8jyKNCDeZj3gYNzcD0Zyl2HYYr5haDtfr0NE0XI8c8yD4czs7FuuP51tEB37GFN0TAGz4chKfz9Mc8xZ/aBUlIa6wUk0LJEbjujP3tf+I797R4yyYJ8GhwDN9YkDspPIrw3N+a2chhpT5WzitAgMBAAECggEBALggVT+uqEga5JLCo/5+tGpfLGeF3hLb8k5PuOJYwwln6QfXzW4BHKVqsMrFNS1xduI5YEVRE16cbpZX7T3fFdSfYU42+TcHZ9TWTEiOXFwot+tOxhrdJStM1Rt8HP2I+/3dSZVGbzOjfTKU4dRML7xV9MeIGEIJDUF2piycCgyT2ovT0vbBNkKdfCfFjUNPkJmItLa3wuPs6+9CQdd6hwomPNHNVUFgfOLP7OLGSZuzKjjo6pul+oU3ZfpND3V3TZ+lD8i1Qps/EKfHN8fMt38lJcbRvQAso7DsqT7ZNzfaD8SpXY7ulBPVe+f7aoRAlqQXizIBhOK+TfYiQ2CIUoECgYEA7jD+YrRfFj31052HRykvmIY5YZTb6Emk6eiqTpbgkWbbC1KsWRuHR1854AvQ1aRk82BxtrxZxuwF2sEVQeGiaDxSK0KnLDMLMNmVe/Jr4NGhbcvVZuzU7L+ZM8e8XcIFy2nljWQQ5x50AZDoGY70eQkNFAxg8TVWmhzNZ9rWpj0CgYEA7BsXk1BRcBMtr+cYZ/2/cqUNKsw9BWVwL4lwTNn9A6PHt06+gNKD6+NUevYtp09xqENryIXc26dt/9OWk6BPd7kp6H3c1xGyByW9hC58vHhC6pcgSUiJ6diwVsqD0z2dTW7/3kbLPRpvSf/waHPfLOWkmnkkavtbiynzP4F4czECgYA/Dd85t+/4Dlz2MRxvnRqJcPbduy9f1ab/eOUkutImC6lu3OrdB+mO3kmO4vHcrJFA0EYqDsBhZXfDShvbfeSlXVqPMyzYCYcr3l2xGyKtuDDYxP3wKj/PkIT47SYTV9p618S54kSLOkeRZo/avDpBlEDPDtvW3rzXPUqu9IKgLQKBgQCLiYdpXLKElhEOQHnAG8slqj4Z6RK3ObgPoB5qjPpnSEgkIbmc0M1+f5/R++QHWYBGfXIZ1GMuvcjYxOfc34WXsCsAaEI4KREaAEf88qxthnWlxyMhrGk1dwbghFdcZLGurccySoya1CCpj0U5tiFTm3SohqfrQhpcKLLF+XKCQQKBgGSYZZ65F+WSDUrP1DfIkHzJcpVj4rFGLretIi3PJItFazq8pahWh3EllogUxMuntknOPwdbfptP/LCN/pTLCCYiwINgeCSZaEIlsSiUEJTmO5NE4YwEpSpbEWNuEDS1JRZrxRAFkh1WlL629vsV9jkS93nkDpc1OS7Cdp8ILsDE";
// String APP_PUBLIC_KEY ="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA265fnUpotLExynm1C9J9ckhE220EGGSdpYDD5hhtZpwGhgVDUKW9KXJ7HjMr+rMJ1QgXx+5xSRDni6FaZMeY9v4GDCMeYuXxT7HbvHQ8j4dxcgko5g5pDJoYjYj5P/9fj/fVD5zYjdcVvJ6DmUYaYXfAYdFzPrCEVPzuhQ6/spiknckhz5Re7QClzAyC2oZBzeUgfI8ijQg3mY94GDc3A9Gcpdh2GK+YWg7X69DRNFyPHPMg+HM7Oxbrj+dbRAd+xhTdEwBs+HISn8/THPMWf2gVJSGusFJNCyRG47oz97X/iO/e0eMsmCfBocAzfWJA7KTyK8NzfmtnIYaU+Vs4rQIDAQAB";
// String notify_url = "http://127.0.0.1:8080";
// String alipayPublicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAghBg+LB71Ivm+3v50LWhAmU69vZqcnWq9nNvIbp/PrDMpp+bfc8vwkEWEEkstF5Jo/kIhFPYWbECAJw8UJsJ7usTjfIZvasXv2KxRUnrsCV94Azn8jV7meHgxpE4LTpBiIqrN+AVf6SLjLlBmwCiQ78g7RbF/pIvsjtKiEPVhB7NAMttNorPVib/mIPbMjzWGXJf/GR6s1oaTs9vNcFbyjMBYd8h9KelyIQFvLaDeB1ffWxWJJ1o52wmgeoGlAhlHaF1dHdf3X9MXCKNpyZtDw9akwqJPAaG+vxKdSVUS9YDVhzBU3fSI05hb5waYeMsxAi6JAPHEluvRT03HzgDnwIDAQAB";
// result.getData()
......@@ -76,12 +61,30 @@ public class PayService {
// PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO();
// CommonResult<?> result = client.unifiedOrder(reqDTO);
// System.out.println(JsonUtils.toJsonString(result));
// return result;
// }
public CommonResult CreatePayClient_ALIPAY_WAP(PayEntiy pe) {
// 创建配置
AlipayPayClientConfig config = new AlipayPayClientConfig();
config.setAppId(pe.getAppid());
config.setServerUrl(AlipayPayClientConfig.SERVER_URL_PROD);
// config.setServerUrl(AlipayPayClientConfig.SERVER_URL_SANDBOX);
config.setSignType(AlipayPayClientConfig.SIGN_TYPE_DEFAULT);
config.setPrivateKey(pe.getPrivateKey());
config.setAlipayPublicKey(pe.getAlipayPublicKey());
// 创建客户端
// Long channelId = RandomUtil.randomLong();
payClientFactory.createOrUpdatePayClient(pe.getChannelId() ,PayChannelEnum.ALIPAY_WAP.getCode(), config);
PayClient client = payClientFactory.getPayClient(pe.getChannelId());
// 发起支付
PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(pe);
CommonResult<?> result = client.unifiedOrder(reqDTO);
String s = JsonUtils.toJsonString(result);
System.out.println(JsonUtils.toJsonString(s));
return result;
}
......@@ -178,13 +181,11 @@ public class PayService {
reqDTO.setMerchantOrderId(pe.getMerchantOrderId());
reqDTO.setUserIp(pe.getUserIp());
reqDTO.setNotifyUrl(pe.getNotifyUrl());
reqDTO.setReturnUrl(pe.getReturnUrl());
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("attach",pe.getOutTradeNo());
if(pe.getPayType()==1){
hm.put("trade_type","MWEB");
}
if(pe.getOpenid()!=null){
hm.put("openid",pe.getOpenid());
......
package com.icloud.server.payutils.ali.config;
/* *
*类名:AlipayConfig
*功能:基础配置类
*详细:设置帐户有关信息及返回路径
*版本:3.4
*修改日期:2016-03-08
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public class AlipayConfig {
//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
public static String partner = "";
// 收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号
public static String seller_id = partner;
// MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
public static String key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgk0caRPeLrONJf8IcCU5VCpFXww15MmDAiLto0c6QwMBfeF5oK47EzhzNuFCuXAlKSWSKffxdfBRLUWt2HRART+aINTfqUl6Bo0gTSiBBitYKDwKFLttN+Q4Oer6r1ozitCq9W/iaiTHhrDaLeCEyi2NSDKIc0YX4LG/yasfgwgM+lUjHWFZQ2zcsm6hkX97Q2eSYLLyx1Z1FWf4FsmJBcqZtZ0ZbCJAYAEZkZ4rVht9LKJLkqqoEX8FtGZaXlE9YbqBNi0JC12k/17bcE2HCbTd0QUIeKEY39loElLXNp6unpxvQUG+0hGDSl2U9Jf6X2ArtLyhoGWSdWQDtR3qiQIDAQAB";
// 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String notify_url = "";
// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String return_url = "";
// 签名方式
public static String sign_type = "MD5";
// 调试用,创建TXT日志文件夹路径,见AlipayCore.java类中的logResult(String sWord)打印方法。
public static String log_path = "";
// 字符编码格式 目前支持utf-8
public static String input_charset = "utf-8";
// 支付类型 ,无需修改
public static String payment_type = "1";
// 调用的接口名,无需修改
public static String service = "alipay.wap.create.direct.pay.by.user";
//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
}
package com.icloud.server.payutils.ali.sign;
import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
import org.apache.commons.codec.digest.DigestUtils;
/**
* 功能:支付宝MD5签名处理核心文件,不需要修改
* 版本:3.3
* 修改日期:2012-08-17
* 说明:
* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
* 该代码仅供学习和研究支付宝接口使用,只是提供一个
* */
public class MD5 {
/**
* 签名字符串
* @param text 需要签名的字符串
* @param key 密钥
* @param input_charset 编码格式
* @return 签名结果
*/
public static String sign(String text, String key, String input_charset) {
text = text + key;
return DigestUtils.md5Hex(getContentBytes(text, input_charset));
}
/**
* 签名字符串
* @param text 需要签名的字符串
* @param sign 签名结果
* @param key 密钥
* @param input_charset 编码格式
* @return 签名结果
*/
public static boolean verify(String text, String sign, String key, String input_charset) {
text = text + key;
String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));
if(mysign.equals(sign)) {
return true;
}
else {
return false;
}
}
/**
* @param content
* @param charset
* @return
* @throws SignatureException
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
}
\ No newline at end of file
package com.icloud.server.payutils.ali.util;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.icloud.server.payutils.ali.config.AlipayConfig;
/* *
*类名:AlipayFunction
*功能:支付宝接口公用函数类
*详细:该类是请求、通知返回两个文件所调用的公用函数核心处理文件,不需要修改
*版本:3.3
*日期:2012-08-14
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public class AlipayCore {
/**
* 除去数组中的空值和签名参数
* @param sArray 签名参数组
* @return 去掉空值与签名参数后的新签名参数组
*/
public static Map<String, String> paraFilter(Map<String, String> sArray) {
Map<String, String> result = new HashMap<String, String>();
if (sArray == null || sArray.size() <= 0) {
return result;
}
for (String key : sArray.keySet()) {
String value = sArray.get(key);
if (value == null || value.equals("") || key.equalsIgnoreCase("sign")
|| key.equalsIgnoreCase("sign_type")) {
continue;
}
result.put(key, value);
}
return result;
}
/**
* 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
* @param params 需要排序并参与字符拼接的参数组
* @return 拼接后字符串
*/
public static String createLinkString(Map<String, String> params) {
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
/**
* 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
* @param sWord 要写入日志里的文本内容
*/
public static void logResult(String sWord) {
FileWriter writer = null;
try {
writer = new FileWriter(AlipayConfig.log_path + "alipay_log_" + System.currentTimeMillis()+".txt");
writer.write(sWord);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.icloud.server.payutils.ali.util;
import com.icloud.server.payutils.ali.config.AlipayConfig;
import com.icloud.server.payutils.ali.sign.MD5;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
/* *
*类名:AlipayNotify
*功能:支付宝通知处理类
*详细:处理支付宝各接口通知返回
*版本:3.3
*日期:2012-08-17
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考
*************************注意*************************
*调试通知返回时,可查看或改写log日志的写入TXT里的数据,来检查通知返回是否正常
*/
public class AlipayNotify {
/**
* 支付宝消息验证地址
*/
private static final String HTTPS_VERIFY_URL = "https://mapi.alipay.com/gateway.do?service=notify_verify&";
/**
* 验证消息是否是支付宝发出的合法消息
* @param params 通知返回来的参数数组
* @return 验证结果
*/
public static boolean verify(Map<String, String> params,String sign) {
//判断responsetTxt是否为true,isSign是否为true
//responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
//isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
String responseTxt = "false";
// if(params.get("notify_id") != null) {
// String notify_id = params.get("notify_id");
// responseTxt = verifyResponse(notify_id);
// }
// String sign = "";
// if(params.get("sign") != null) {sign = params.get("sign");}
boolean isSign = getSignVeryfy(params, sign);
return isSign;
//写日志记录(若要调试,请取消下面两行注释)
//String sWord = "responseTxt=" + responseTxt + "\n isSign=" + isSign + "\n 返回回来的参数:" + AlipayCore.createLinkString(params);
//AlipayCore.logResult(sWord);
// if (isSign && responseTxt.equals("true")) {
// return true;
// } else {
// return false;
// }
}
/**
* 根据反馈回来的信息,生成签名结果
* @param Params 通知返回来的参数数组
* @param sign 比对的签名结果
* @return 生成的签名结果
*/
private static boolean getSignVeryfy(Map<String, String> Params, String sign) {
//过滤空值、sign与sign_type参数
Map<String, String> sParaNew = AlipayCore.paraFilter(Params);
//获取待签名字符串
String preSignStr = AlipayCore.createLinkString(sParaNew);
//获得签名验证结果
boolean isSign = false;
if(AlipayConfig.sign_type.equals("MD5") ) {
isSign = MD5.verify(preSignStr, sign, AlipayConfig.key, AlipayConfig.input_charset);
}
return isSign;
}
/**
* 获取远程服务器ATN结果,验证返回URL
* @param notify_id 通知校验ID
* @return 服务器ATN结果
* 验证结果集:
* invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空
* true 返回正确信息
* false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟
*/
private static String verifyResponse(String notify_id) {
//获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求
String partner = AlipayConfig.partner;
String veryfy_url = HTTPS_VERIFY_URL + "partner=" + partner + "&notify_id=" + notify_id;
return checkUrl(veryfy_url);
}
/**
* 获取远程服务器ATN结果
* @param urlvalue 指定URL路径地址
* @return 服务器ATN结果
* 验证结果集:
* invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空
* true 返回正确信息
* false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟
*/
private static String checkUrl(String urlvalue) {
String inputLine = "";
try {
URL url = new URL(urlvalue);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection
.getInputStream()));
inputLine = in.readLine().toString();
} catch (Exception e) {
e.printStackTrace();
inputLine = "";
}
return inputLine;
}
}
package com.icloud.server.payutils.ali.util;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.icloud.server.payutils.ali.config.AlipayConfig;
import com.icloud.server.payutils.ali.sign.MD5;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
/* *
*类名:AlipaySubmit
*功能:支付宝各接口请求提交类
*详细:构造支付宝各接口表单HTML文本,获取远程HTTP数据
*版本:3.3
*日期:2012-08-13
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public class AlipaySubmit {
/**
* 支付宝提供给商户的服务接入网关URL(新)
*/
private static final String ALIPAY_GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?";
/**
* 生成签名结果
* @param sPara 要签名的数组
* @return 签名结果字符串
*/
public static String buildRequestMysign(Map<String, String> sPara) {
String prestr = AlipayCore.createLinkString(sPara); //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
String mysign = "";
if(AlipayConfig.sign_type.equals("MD5") ) {
mysign = MD5.sign(prestr, AlipayConfig.key, AlipayConfig.input_charset);
}
return mysign;
}
/**
* 生成要请求给支付宝的参数数组
* @param sParaTemp 请求前的参数数组
* @return 要请求的参数数组
*/
private static Map<String, String> buildRequestPara(Map<String, String> sParaTemp) {
//除去数组中的空值和签名参数
Map<String, String> sPara = AlipayCore.paraFilter(sParaTemp);
//生成签名结果
String mysign = buildRequestMysign(sPara);
//签名结果与签名方式加入请求提交参数组中
sPara.put("sign", mysign);
sPara.put("sign_type", AlipayConfig.sign_type);
return sPara;
}
/**
* 建立请求,以表单HTML形式构造(默认)
* @param sParaTemp 请求参数数组
* @param strMethod 提交方式。两个值可选:post、get
* @param strButtonName 确认按钮显示文字
* @return 提交表单HTML文本
*/
public static String buildRequest(Map<String, String> sParaTemp, String strMethod, String strButtonName) {
//待请求参数数组
Map<String, String> sPara = buildRequestPara(sParaTemp);
List<String> keys = new ArrayList<String>(sPara.keySet());
StringBuffer sbHtml = new StringBuffer();
sbHtml.append("<form id=\"alipaysubmit\" name=\"alipaysubmit\" action=\"" + ALIPAY_GATEWAY_NEW
+ "_input_charset=" + AlipayConfig.input_charset + "\" method=\"" + strMethod
+ "\">");
for (int i = 0; i < keys.size(); i++) {
String name = (String) keys.get(i);
String value = (String) sPara.get(name);
sbHtml.append("<input type=\"hidden\" name=\"" + name + "\" value=\"" + value + "\"/>");
}
//submit按钮控件请不要含有name属性
sbHtml.append("<input type=\"submit\" value=\"" + strButtonName + "\" style=\"display:none;\"></form>");
sbHtml.append("<script>document.forms['alipaysubmit'].submit();</script>");
return sbHtml.toString();
}
/**
* 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数
* 注意:远程解析XML出错,与服务器是否支持SSL等配置有关
* @return 时间戳字符串
* @throws IOException
* @throws DocumentException
* @throws MalformedURLException
*/
public static String query_timestamp() throws MalformedURLException,
DocumentException, IOException {
//构造访问query_timestamp接口的URL串
String strUrl = ALIPAY_GATEWAY_NEW + "service=query_timestamp&partner=" + AlipayConfig.partner + "&_input_charset" +AlipayConfig.input_charset;
StringBuffer result = new StringBuffer();
SAXReader reader = new SAXReader();
Document doc = reader.read(new URL(strUrl).openStream());
List<Node> nodeList = doc.selectNodes("//alipay/*");
for (Node node : nodeList) {
// 截取部分不需要解析的信息
if (node.getName().equals("is_success") && node.getText().equals("T")) {
// 判断是否有成功标示
List<Node> nodeList1 = doc.selectNodes("//response/timestamp/*");
for (Node node1 : nodeList1) {
result.append(node1.getText());
}
}
}
return result.toString();
}
}
package com.icloud.server.payutils.ali.util;
import java.util.Date;
import java.util.Random;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
/* *
*类名:UtilDate
*功能:自定义订单类
*详细:工具类,可以用作获取系统日期、订单编号等
*版本:3.3
*日期:2012-08-17
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public class UtilDate {
/** 年月日时分秒(无下划线) yyyyMMddHHmmss */
public static final String dtLong = "yyyyMMddHHmmss";
/** 完整时间 yyyy-MM-dd HH:mm:ss */
public static final String simple = "yyyy-MM-dd HH:mm:ss";
/** 年月日(无下划线) yyyyMMdd */
public static final String dtShort = "yyyyMMdd";
/**
* 返回系统当前时间(精确到毫秒),作为一个唯一的订单编号
* @return
* 以yyyyMMddHHmmss为格式的当前系统时间
*/
public static String getOrderNum(){
Date date=new Date();
DateFormat df=new SimpleDateFormat(dtLong);
return df.format(date);
}
/**
* 获取系统当前日期(精确到毫秒),格式:yyyy-MM-dd HH:mm:ss
* @return
*/
public static String getDateFormatter(){
Date date=new Date();
DateFormat df=new SimpleDateFormat(simple);
return df.format(date);
}
/**
* 获取系统当期年月日(精确到天),格式:yyyyMMdd
* @return
*/
public static String getDate(){
Date date=new Date();
DateFormat df=new SimpleDateFormat(dtShort);
return df.format(date);
}
/**
* 产生随机的三位数
* @return
*/
public static String getThree(){
Random rad=new Random();
return rad.nextInt(1000)+"";
}
}
/*
* Alipay.com Inc.
* Copyright (c) 2004-2005 All Rights Reserved.
*/
package com.icloud.server.payutils.ali.util.httpClient;
/* *
*类名:HttpResultType
*功能:表示Http返回的结果字符方式
*详细:表示Http返回的结果字符方式
*版本:3.3
*日期:2012-08-17
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public enum HttpResultType {
/**
* 字符串方式
*/
STRING,
/**
* 字节数组方式
*/
BYTES
}
......@@ -3,8 +3,13 @@ package com.icloud.server.payutils.alipay;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.icloud.server.payutils.AbstractPayCodeMapping;
import com.icloud.server.payutils.PayCommonResult;
......@@ -13,6 +18,8 @@ import com.icloud.server.utils.JsonUtils;
import com.icloud.server.web.err.pay.PayChannelEnum;
import lombok.extern.slf4j.Slf4j;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Objects;
......@@ -38,6 +45,137 @@ public class AlipayWapPayClient extends AbstractAlipayClient {
super(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), config, new AlipayPayCodeMapping());
}
public PayCommonResult<AlipayTradeWapPayResponse> doUnifiedOrder1(PayOrderUnifiedReqDTO reqDTO) {
// 构建 AlipayTradeWapPayModel 请求
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(reqDTO.getMerchantOrderId());
model.setSubject(reqDTO.getSubject());
model.setBody(reqDTO.getBody());
// HashMap<String, String> map = new HashMap<>();
// map.put("attach",reqDTO.getChannelExtras().get("attach"));
// String attach = JsonUtils.toJsonString(map);
// model.setBusinessParams(attach);
model.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString());
model.setProductCode("QUICK_WAP_PAY"); //
model.setQuitUrl(reqDTO.getReturnUrl());
// https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay
//model.setSellerId("2088102147948060");
model.setTimeoutExpress("30m");
// model.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(),"yyyy-MM-dd HH:mm:ss"));
// TODO :userIp
// 构建 AlipayTradeWapPayRequest
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setBizModel(model);
System.out.println("最后计算的回调地址:"+reqDTO.getNotifyUrl());
String r_url="";
try {
r_url=URLEncoder.encode(reqDTO.getNotifyUrl(),"UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
request.setNotifyUrl(r_url);
// request.setReturnUrl(reqDTO.getReturnUrl());
System.out.println("最后计算的返回地址:"+reqDTO.getReturnUrl());
try {
r_url=URLEncoder.encode(reqDTO.getReturnUrl(),"UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
request.setReturnUrl(r_url);
// 执行请求
AlipayTradeWapPayResponse response;
try {
response = client.pageExecute(request);
} catch (AlipayApiException e) {
return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping);
}
// TODO :sub Code
if(response.isSuccess() && Objects.isNull(response.getCode()) && Objects.nonNull(response.getBody())){
//成功alipay wap 成功 code 为 null , body 为form 表单
return PayCommonResult.build("-9999", "Success", response, codeMapping);
}else {
return PayCommonResult.build(response.getCode(), response.getMsg(), response, codeMapping);
}
//实例化客户端
// AlipayClient alipayClient1 = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", "","", "json","", "RSA2");
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
// AlipayTradeWapPayRequest request1 = new AlipayTradeWapPayRequest();
////SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
// AlipayTradeWapPayModel model1 = new AlipayTradeWapPayModel();
// model1.setBody(reqDTO.getBody());
// model1.setSubject(reqDTO.getSubject());
// model1.setOutTradeNo(reqDTO.getMerchantOrderId());
// model1.setTimeoutExpress("30m");
// model1.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString());
// model1.setProductCode("QUICK_WAP_PAY");
// request1.setBizModel(model1);
// request1.setNotifyUrl(reqDTO.getNotifyUrl());
// request1.setReturnUrl("https://www.baidu.com");
// AlipayTradeWapPayResponse response1 = null;
// try {
// //这里和普通的接口调用不同,使用的是sdkExecute AlipayTradeWapPayResponse
// response1 = client.sdkExecute(request1);
// return PayCommonResult.build(response1.getCode(), response1.getMsg(), response1, codeMapping);
//// System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
//// return response1;
// } catch (AlipayApiException e) {
// return PayCommonResult.build("-9999", "Success", response1, codeMapping);
// }
}
public PayCommonResult<AlipayTradeWapPayResponse> doUnifiedOrder2(PayOrderUnifiedReqDTO reqDTO) {
// 构建 AlipayTradeWapPayModel 请求
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(reqDTO.getMerchantOrderId());
model.setSubject(reqDTO.getSubject());
model.setBody(reqDTO.getBody());
HashMap<String, String> map = new HashMap<>();
map.put("attach",reqDTO.getChannelExtras().get("attach"));
String attach = JsonUtils.toJsonString(map);
model.setBusinessParams(attach);
model.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString());
model.setProductCode("QUICK_WAP_PAY"); //
model.setQuitUrl(reqDTO.getReturnUrl());
// https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay
//model.setSellerId("2088102147948060");
model.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(),"yyyy-MM-dd HH:mm:ss"));
// TODO :userIp
// 构建 AlipayTradeWapPayRequest
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setBizModel(model);
request.setNotifyUrl(reqDTO.getNotifyUrl());
request.setReturnUrl("www.baidu.com");
// 执行请求
AlipayTradeWapPayResponse response;
try {
response = client.pageExecute(request);
} catch (AlipayApiException e) {
return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping);
}
// TODO :sub Code
if(response.isSuccess() && Objects.isNull(response.getCode()) && Objects.nonNull(response.getBody())){
//成功alipay wap 成功 code 为 null , body 为form 表单
return PayCommonResult.build("-9999", "Success", response, codeMapping);
}else {
return PayCommonResult.build(response.getCode(), response.getMsg(), response, codeMapping);
}
}
@Override
public PayCommonResult<AlipayTradeWapPayResponse> doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
// 构建 AlipayTradeWapPayModel 请求
......@@ -86,6 +224,4 @@ public class AlipayWapPayClient extends AbstractAlipayClient {
}
......@@ -121,7 +121,13 @@ public class PayOrderDO implements Serializable {
*
*/
@Column(name = "status")
private Integer status;
private Integer status=0;
/**
* 支付方式
*
*/
@Column(name = "paytype")
private Integer paytype=1;
/**
* 用户 IP
*/
......@@ -207,6 +213,25 @@ public class PayOrderDO implements Serializable {
@Column(name = "updater")
private String updater;
@Column(name = "goodspayid")
private Long goodspayid;
public Integer getPaytype() {
return paytype;
}
public void setPaytype(Integer paytype) {
this.paytype = paytype;
}
public Long getGoodspayid() {
return goodspayid;
}
public void setGoodspayid(Long goodspayid) {
this.goodspayid = goodspayid;
}
public String getNickname() {
return nickname;
......
package com.icloud.server.payutils.enums;
/**
* 可生成 Int 数组的接口
*
* @author
*/
public interface IntArrayValuable {
/**
* @return int 数组
*/
int[] array();
}
......@@ -12,10 +12,12 @@ import lombok.Getter;
@AllArgsConstructor
public enum PayTypeEnum {
FreePAY(0, "免费"),
WXPAY(1, "微信"),
WXJSPAY(3, "微信"),
ALIPAY(2, "支付宝");
private final Integer status;
private final String name;
......
......@@ -9,6 +9,12 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.List;
/** 后期用到的链接过期,目前版本中不需要这个功能
* 优化缓存用的
* @Author : yang
* @Date : 2022-07-31 16:36
* @Version : 2.1.2
*/
public class GoodsPayDaoImpl implements GoodsPayDao{
@PersistenceContext
......
package com.icloud.server.payutils.notify;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.service.WxPayService;
import com.icloud.server.payutils.PayClient;
import com.icloud.server.payutils.PayClientFactory;
import com.icloud.server.payutils.dto.PayNotifyDataDTO;
import com.icloud.server.payutils.enums.PayTypeEnum;
import com.icloud.server.payutils.order.PayOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
import static com.icloud.server.web.err.ServiceExceptionUtil.exception;
import static com.icloud.server.web.err.enums.ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND;
@Api(tags = "用户 APP - 支付订单")
@RestController
@RequestMapping("/pay/order")
@Validated
@Slf4j
public class AppPayOrderController {
// @Resource
// private PayRefundService refundService;
@Resource
private PayOrderService orderService;
@Resource
private PayClientFactory payClientFactory;
@PostMapping(value = "/wxnotify/{channelId}")
@ApiOperation("渠道统一的支付成功,或退款成功 通知url")
public String notifyChannelPay(@PathVariable("channelId") Long channelId,
@RequestParam Map<String, String> params,
@RequestBody String originData) throws Exception {
System.out.println("channelId:"+channelId);
for(String value: params.values()) {
// 输出返回的值
System.out.println("====微信回传参数:"+value + ";======");
}
// 校验支付渠道是否存在
PayClient payClient = payClientFactory.getPayClient(channelId);
if (payClient == null) {
log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channelId);
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
}
// 校验通知数据是否合法
PayNotifyDataDTO notifyData = PayNotifyDataDTO.builder().params(params).body(originData).build();
payClient.verifyNotifyData(notifyData);
// 如果是退款,则发起退款通知
// if (payClient.isRefundNotify(notifyData)) {
// refundService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
// return "success";
// }
// 如果非退款,则发起支付通知
orderService.notifyPayOrder(PayTypeEnum.WXPAY,channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
return "success";
}
@PostMapping(value = "/alinotify/{channelId}")
@ApiOperation("渠道统一的支付成功,或退款成功 通知url")
public String notifyChannelaliPay(@PathVariable("channelId") Long channelId,
@RequestParam Map<String, String> params,
@RequestBody String originData) throws Exception {
System.out.println("channelId:"+channelId);
for(String value: params.values()) {
// 输出返回的值
System.out.print(value + ", ");
}
// 校验支付渠道是否存在
PayClient payClient = payClientFactory.getPayClient(channelId);
if (payClient == null) {
log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channelId);
throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
}
// 校验通知数据是否合法
PayNotifyDataDTO notifyData = PayNotifyDataDTO.builder().params(params).body(originData).build();
payClient.verifyNotifyData(notifyData);
// 如果是退款,则发起退款通知
// if (payClient.isRefundNotify(notifyData)) {
// refundService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
// return "success";
// }
// 如果非退款,则发起支付通知
orderService.notifyPayOrder(PayTypeEnum.ALIPAY,channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());
return "success";
}
}
package com.icloud.server.payutils.notify;
import com.icloud.server.payutils.job.JobHandler;
import javax.annotation.Resource;
/**
* 支付通知 Job
* 通过不断扫描待通知的 PayNotifyTaskDO 记录,回调业务线的回调接口
*
* @author
*/
//@Component
//@Slf4j
public class PayNotifyJob implements JobHandler {
@Resource
private PayNotifyService payNotifyCoreService;
@Override
public String execute(String param) throws Exception {
// int notifyCount = payNotifyCoreService.executeNotify();
return String.format("执行支付通知 %s 个", 1);
}
}
package com.icloud.server.payutils.notify;
//import org.redisson.api.RLock;
//import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
//import static com.icloud.server.payutils.notify.RedisKeyConstants.PAY_NOTIFY_LOCK;
/**
* 支付通知的锁 Redis DAO
*
* @author
*/
@Repository
public class PayNotifyLockRedisDAO {
// @Resource
// private RedissonClient redissonClient;
//
// public void lock(Long id, Long timeoutMillis, Runnable runnable) {
// String lockKey = formatKey(id);
// RLock lock = redissonClient.getLock(lockKey);
// try {
// lock.lock(timeoutMillis, TimeUnit.MILLISECONDS);
// // 执行逻辑
// runnable.run();
// } finally {
// lock.unlock();
// }
// }
// private static String formatKey(Long id) {
// return String.format(PAY_NOTIFY_LOCK.getKeyTemplate(), id);
// }
}
package com.icloud.server.payutils.notify;
import javax.validation.Valid;
/**
* 支付通知 Service 接口
*
* @author
*/
public interface PayNotifyService {
/**
* 创建支付通知任务
*
* @param reqDTO 任务信息
*/
void createPayNotifyTask(@Valid PayNotifyTaskCreateReqDTO reqDTO);
/**
* 执行支付通知
*
* 注意,该方法提供给定时任务调用。目前是 yudao-server 进行调用
* @return 通知数量
*/
// int executeNotify() throws InterruptedException;
}
package com.icloud.server.payutils.notify;
import com.icloud.server.payutils.dto.PayNotifyTaskDO;
import com.icloud.server.payutils.order.PayOrderService;
import com.icloud.server.utils.time.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Date;
import java.util.Objects;
/**
* 支付通知 Core Service 实现类
*
* @author
*/
@Service
@Valid
@Slf4j
public class PayNotifyServiceImpl implements PayNotifyService {
/**
* 通知超时时间,单位:秒
*/
public static final int NOTIFY_TIMEOUT = 120;
/**
* {@link #NOTIFY_TIMEOUT} 的毫秒
*/
public static final long NOTIFY_TIMEOUT_MILLIS = 120 * DateUtils.SECOND_MILLIS;
@Resource
@Lazy // 循环依赖,避免报错
private PayOrderService orderService;
// @Resource
// @Lazy // 循环依赖,避免报错
// private PayRefundService refundService;
@Resource
private ThreadPoolTaskExecutor threadPoolTaskExecutor; // TODO :未来提供独立的线程池
@Resource
private PayNotifyLockRedisDAO payNotifyLockCoreRedisDAO;
@Override
public void createPayNotifyTask(PayNotifyTaskCreateReqDTO reqDTO) {
PayNotifyTaskDO task = new PayNotifyTaskDO();
task.setType(reqDTO.getType()).setDataId(reqDTO.getDataId());
task.setStatus(PayNotifyStatusEnum.WAITING.getStatus()).setNextNotifyTime(new Date())
.setNotifyTimes(0).setMaxNotifyTimes(PayNotifyTaskDO.NOTIFY_FREQUENCY.length + 1);
// 补充 merchantId + appId + notifyUrl 字段
if (Objects.equals(task.getType(), PayNotifyTypeEnum.ORDER.getType())) {
//保存支付单通知
} else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) {
//保存退款单通知
}
// 保存订单
}
}
package com.icloud.server.payutils.notify;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* 支付通知创建 DTO
*
* @author
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayNotifyTaskCreateReqDTO {
/**
* 类型
*/
@NotNull(message = "类型不能为空")
private Integer type;
/**
* 数据编号
*/
@NotNull(message = "数据编号不能为空")
private Long dataId;
}
package com.icloud.server.payutils.notify;
//import org.redisson.api.RLock;
/**
* 支付 Redis Key 枚举类
*
* @author
*/
public interface RedisKeyConstants {
// RedisKeyDefine PAY_NOTIFY_LOCK = new RedisKeyDefine("通知任务的分布式锁",
// "pay_notify:lock:", // 参数来自 DefaultLockKeyBuilder 类
// RedisKeyDefine.KeyTypeEnum.HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构
//
}
package com.icloud.server.payutils;
package com.icloud.server.payutils.notify;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.icloud.server.payutils.dto.PayOrderDO;
import com.icloud.server.scala.goods.Goods;
import com.icloud.server.scala.goods.GoodsRepository;
import com.icloud.server.scala.goods.Goodspay;
import com.icloud.server.scala.goods.GoodspayRepository;
import com.icloud.server.scala.paynotify.PayNotifyEntity;
import com.icloud.server.scala.paynotify.PayNotifyLogEntity;
import com.icloud.server.scala.paynotify.PayNotifyLogRepository;
......@@ -24,16 +28,20 @@ import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.LoggerFactory;
import springfox.documentation.annotations.ApiIgnore;
/**微信
* @Author : yang
* @Date : 2022-07-26 01:09
* @Version : 2.1.2
*/
@ApiIgnore
@Api("微信支付")
@RestController
@RequestMapping("/pay/order2")
@RequestMapping("/occloud/pay/order2")
@AllArgsConstructor
public class WxPayNotify {
......@@ -47,7 +55,11 @@ public class WxPayNotify {
private PayNotifyLogRepository pnlr;
@Resource
private PayOrderRepository por;
@Resource
private GoodsRepository gr;
@Resource
private GoodspayRepository gpr;
static Logger logger = LoggerFactory.getLogger("wxrepay");
// private pay = LoggerFactory.getLogger( "req" );
......@@ -86,6 +98,7 @@ public class WxPayNotify {
//mysql --校验
List<PayNotifyEntity> pnes = pnr.findByMerchantorderidAndOuttradenoAndStatus(out_trade_no, attach,0);
if(!pnes.isEmpty()){
PayNotifyLogEntity paynotifylogentity = new PayNotifyLogEntity().toEntity(nonce_str, xmlData, "wx", "wx", appid.toString());
//log 日志----输出
new Logs(logger).toLog( xmlData);
......@@ -99,6 +112,23 @@ public class WxPayNotify {
por1.setStatus(1);
//mysql --修改订单状态
por.save(por1);
//修改商品订单
try {
Long goodspayid = por1.getGoodspayid();
Optional<Goodspay> goodspay = gpr.findById(goodspayid);
Goodspay goodspay1 = goodspay.get();
Goods goods = gr.findByGoodsid(goodspay1.getGoodsid());
long sellamount = goods.getSellamount();
long sellcount = goods.getSellcount();
sellamount+=Long.parseLong(total_fee);
sellcount+=1;
goods.setSellamount(sellamount);
goods.setSellcount(sellcount);
gr.save(goods);
} catch (NumberFormatException e) {
throw new RuntimeException(e);
}
}
} catch (Exception e) {
......@@ -112,6 +142,9 @@ public class WxPayNotify {
return WxPayNotifyResponse.success("成功");
}
public static Map xmlToMap(String strXML) throws Exception {
try {
Map data = new HashMap();
......
package com.icloud.server.payutils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class tt {
public static void main(String[] args) {
String d="2022-08-02 00:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date time = new Date(); // 获取当前时间
String format = sdf.format(time);// 格式化时间
try {
Date d1 = sdf.parse(d);
long time1 = d1.getTime();
System.out.println("time1:"+time1);
} catch (ParseException e) {
throw new RuntimeException(e);
}
// 时间转换为时间戳
// getTime返回自1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数.
// 时间戳是指自1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
// 单位换算:1秒=1000毫秒
long timestamp = time.getTime() / 1000L;
System.out.println("当前时间:"+time);
System.out.println("当前时间(格式化):"+format);
System.out.println("当前时间戳:"+timestamp);
}
}
package com.icloud.server.scala
import com.icloud.server.web.shiro.handler.LoginInfoThreadLocal
import io.swagger.annotations.{Api, ApiImplicitParam, ApiImplicitParams, ApiOperation}
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.web.bind.annotation.{GetMapping, PostMapping, RequestBody, RequestMapping, RestController}
......@@ -10,7 +11,7 @@ import scala.beans.BeanProperty
@Api( tags = Array( "demo" ), value = "API",hidden = true )
@ApiIgnore
@RestController
@RequestMapping(Array("/aaa/"))
@RequestMapping(Array("/occloud/aaa/"))
class Demo {
@Resource
......@@ -30,11 +31,21 @@ class Demo {
) )
@PostMapping(Array("tt") )
def tt(@RequestBody a:A):String = {
// val userToken = LoginInfoThreadLocal.getContext
// val id = userToken.getClientId
// println(id)
println("a:"+a)
println("a.a:"+a.a)
println("a.b.c:"+a.b.c)
"ok"
}
@PostMapping(Array("ttt") )
def ttt():String = {
// val userToken = LoginInfoThreadLocal.getContext
// val id = userToken.getClientId
// println(id)
"ok"
}
@PostMapping(Array("set") )
def set():String = {
stringredistemplate.opsForValue().set("a","a")
......
......@@ -14,6 +14,9 @@ abstract class AbstractCache[T] {
@PostConstruct def init ={
cache = buildCache
val cc = Runtime.getRuntime().freeMemory()
println("=========当前支付链接的数量:"+cache.size()+" 个===========")
println("=========加载缓存后,当前占用内存:"+(cc/1024/1024)+" M ;===========")
}
@PreDestroy def clear = {
......
......@@ -18,30 +18,70 @@ class GoodsCache extends AbstractCache[Goodspaye]{
@Resource private[cache] var gpr: GoodspayRepositorye = _
override def buildCache: util.Map[String, Goodspaye] = {
val now = DateTime.now
val day = now.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0);
val pays = gpr.getGoodsPaysByHour(now)
//过滤禁用的支付渠道
val goodspayes = new util.ArrayList[Goodspaye]()
pays.asScala.map(x=>{
var goodspaye = gpr.findByIdAndStatus(x.id, 0)
if(goodspaye!=null) {
goodspaye.alipays= goodspaye.alipays.asScala.filter(x=>{
x.paystatus==0
}).toSet.asJava
goodspaye.wxpayes=goodspaye.wxpayes.asScala.filter(x=>{
x.paystatus==0
}).toSet.asJava
goodspayes.add(goodspaye)
}
})
goodsPayeList=goodspayes
// val now = DateTime.now
// val day = now.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0);
// val pays = gpr.getGoodsPaysByHour(now)
// //过滤禁用的支付渠道
// val goodspayes = new util.ArrayList[Goodspaye]()
//
// pays.asScala.map(x=>{
// var goodspaye = gpr.findByIdAndStatus(x.id, 0)
// if(goodspaye!=null) {
// goodspaye.alipays= goodspaye.alipays.asScala.filter(x=>{
// x.paystatus==0
// }).toSet.asJava
// goodspaye.wxpayes=goodspaye.wxpayes.asScala.filter(x=>{
// x.paystatus==0
// }).toSet.asJava
// goodspayes.add(goodspaye)
// }
//
//
// })
goodsPayeList= gpr.findByStatusOrderByIdDesc(0)
// goodsPayeList=goodspaye
val ret = new util.HashMap[String, Goodspaye]()
if(!goodsPayeList.isEmpty){
goodsPayeList.asScala.map(goodspaye=>{
//处理指定
goodspaye.goodspayditches.asScala.map(x => {
if (x.random.toInt == 1) {
if (x.optpay == 2) {
goodspaye.alipays =
goodspaye.alipays.asScala.filter(y => {
y.id == x.appointpay
}).asJava
} else if (x.optpay == 1) {//wx
goodspaye.wxpayes = goodspaye.wxpayes.asScala.filter(y => {
y.id == x.appointpay
}).asJava
}
}else{//处理禁用
if (x.optpay == 2) {
goodspaye.alipays =
goodspaye.alipays.asScala.filter(y => {
y.status==0&&y.paystatus==0
}).asJava
} else if (x.optpay == 1) {//wx
goodspaye.wxpayes = goodspaye.wxpayes.asScala.filter(y => {
y.status==0&&y.paystatus==0
}).asJava
}
}
})
})
goodsPayeList.asScala.map(x=>{
ret.put( x.getId.toString, x)
})
......
......@@ -12,7 +12,7 @@ import scala.beans.BeanProperty
* @Date : 2022-07-15 01:01
* @Version : 2.1.2
*/
class Context(@BeanProperty var goodspayservice: GoodsPayService, @BeanProperty val request: PayType, @BeanProperty var payurl: PayUrl) {
class Context(@BeanProperty var goodspayservice: GoodsPayService, @BeanProperty val request: PayType, @BeanProperty var payurl: PayUrl, @BeanProperty var returnUrl: String) {
@BeanProperty var payLink: String = _
@BeanProperty
......
......@@ -22,13 +22,20 @@ def toRequest(ip:String): PayType ={
new PayType(PayTypeEnum.WXPAY,studentid, ditch, goodsid, phone,ip, openid,nickname,headimgurl)
}else if(paytype==2){
new PayType(PayTypeEnum.ALIPAY,studentid, ditch, goodsid, phone,ip,openid,nickname,headimgurl)
}else { //3
}else if(paytype==3){ //3
new PayType(PayTypeEnum.WXJSPAY,studentid, ditch, goodsid, phone,ip, openid,nickname,headimgurl)
}else {
new PayType(PayTypeEnum.FreePAY,studentid, ditch, goodsid, phone,ip, openid,nickname,headimgurl)
}
}
def getFree(ip:String): PayType={
new PayType(PayTypeEnum.FreePAY,studentid, ditch, goodsid, phone,ip, openid,nickname,headimgurl)
}
}
case class PayType( @BeanProperty paytypeenum:PayTypeEnum,
@BeanProperty studentid: String,
@BeanProperty ditch: String,
......
......@@ -25,6 +25,7 @@ import javax.persistence.{Column, Entity, Id, Table}
import scala.beans.BeanProperty
import scala.jdk.CollectionConverters._
import org.hibernate.annotations.BatchSize
import springfox.documentation.annotations.ApiIgnore
/** 支付引擎专用映射类
......@@ -32,7 +33,7 @@ import org.hibernate.annotations.BatchSize
* @Date : 2022-07-13 23:22
* @Version : 2.1.2
*/
@ApiIgnore
@Api(tags = Array("商品映射"), value = "API", hidden = true)
@RestController
@RequestMapping(Array("/t/"))
......@@ -42,28 +43,30 @@ class GoodsPayController1 {
// @BeanProperty
// var gpr: GoodsRepositorye = _
@Resource
@BeanProperty
var gpr: GoodspayRepositorye = _
@PostMapping(Array("t"))
@ResponseBody
def getgoods(id:Long): Unit ={
// var goodspayes = gpr.getGoodsPaysByHour(DateTime.now.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0))
var goodspayes = gpr.findByIdAndStatus(id,0)
// goodspayes.asScala.map(x=>{
// println(x)
// println(x)
// })
println(goodspayes)
}
// @Resource
// @BeanProperty
// var gpr: GoodspayRepositorye = _
// @PostMapping(Array("t"))
// @ResponseBody
// def getgoods(id:Long): Unit ={
//
// // var goodspayes = gpr.getGoodsPaysByHour(DateTime.now.withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0))
// var goodspayes = gpr.findByIdAndStatus(id,0)
// // goodspayes.asScala.map(x=>{
// // println(x)
// // println(x)
// // })
//
// println(goodspayes)
// }
}
@Repository trait GoodspayRepositorye extends CrudRepository[Goodspaye, Long]
with JpaSpecificationExecutor[Goodspaye] with JpaRepository[Goodspaye, Long]
with PagingAndSortingRepository[Goodspaye, Long] with GoodsPayDao{
def findByIdAndStatus(id:Long,status:Int):Goodspaye
def findByStatus(status:Int):util.List[Goodspaye]
def findByStatusOrderByIdDesc(status:Int):util.List[Goodspaye]
// def findBySubjectLikeAndStatusAndUseridOrderById(subject: String,status:Int,userid: Long) :util.List[Goodspaye]
......
......@@ -2,7 +2,7 @@ package com.icloud.server.scala.engine.service
import com.icloud.server.scala.engine.cache.GoodsCache
import org.slf4j.LoggerFactory
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.scheduling.annotation.{Async, Scheduled}
import org.springframework.stereotype.Service
import javax.annotation.Resource
......@@ -30,8 +30,13 @@ class GoodsPayService {
*
*
**/
@Async("taskExecutor")
def lading(): Unit ={
log.info("异步触发加载商品支付链接数据");
goodscache.init
}
def lading1(): Unit ={
log.info("手动触发加载商品支付链接数据");
goodscache.init
}
......
......@@ -28,6 +28,7 @@ class OnloadPayLink {
def process(context: Context) = {
//查询所有支付的缓存
// val goodspays = goodspayservice.getGoodsPay
// //找商品橱窗的id
......
......@@ -38,7 +38,10 @@ class OptisizingSelectionService {
if (goodspaye == null) {
null
} else {
selectByWeight(selectByPriority(goodspaye),context)
//不用每次处理随机和指定参数了,初始化中做,更加能优化代码
// selectByWeight(selectByPriority(goodspaye),context)
selectByWeight(goodspaye,context)
}
}
......@@ -71,23 +74,24 @@ class OptisizingSelectionService {
//
//不随机,指定支付id 判断是否是指定的
def selectByPriority(goodspaye: Goodspaye): Goodspaye = {
goodspaye.goodspayditches.asScala.map(x => {
if (x.random == 0) {
if (x.optpay == 1) { //wx
goodspaye.alipays =
goodspaye.alipays.asScala.filter(y => {
y.appid != x.appointpay
}).asJava
} else if (x.optpay == 2) {
goodspaye.wxpayes = goodspaye.wxpayes.asScala.filter(y => {
y.appid != x.appointpay
}).asJava
}
}
})
goodspaye
}
// todo 已经在初始化缓存中做了,不需要处理
// def selectByPriority(goodspaye: Goodspaye): Goodspaye = {
// goodspaye.goodspayditches.asScala.map(x => {
// if (x.random.toInt == 1) {
// if (x.optpay == 2) {
// goodspaye.alipays =
// goodspaye.alipays.asScala.filter(y => {
// y.id == x.appointpay
// }).asJava
// } else if (x.optpay == 1) {//wx
// goodspaye.wxpayes = goodspaye.wxpayes.asScala.filter(y => {
// y.id == x.appointpay
// }).asJava
// }
// }
// })
// goodspaye
// }
//通过 权重, 随机 返回 alipayid wxpayid
def selectByWeight(goodspaye: Goodspaye, context: Context): Goodspaye = {
......@@ -101,6 +105,7 @@ class OptisizingSelectionService {
if (goodspaye.wxpayes.size() == 1) {
wx = goodspaye.wxpayes.asScala.toList(0)
} else {
wx = goodspaye.wxpayes.asScala.toList.last
val wxpays = goodspaye.wxpayes.asScala.toList
var totalWeight: Int = 0
......@@ -112,7 +117,7 @@ class OptisizingSelectionService {
var end: Int = 0
var ni: Int = 1
while (ni < wxpays.size) {
if (ni == 1) {
if (ni == 1) { //初始化
start = wxpays(ni - 1).getWeight
end = wxpays(ni - 1).getWeight + wxpays(ni).getWeight
} else {
......@@ -140,6 +145,7 @@ class OptisizingSelectionService {
if (goodspaye.alipays.size() == 1) {
ali = goodspaye.alipays.asScala.toList(0)
} else {
ali = goodspaye.alipays.asScala.toList.last
val alipays = goodspaye.alipays.asScala.toList
var totalWeight: Int = 0
for (wx <- alipays) {
......@@ -184,8 +190,11 @@ class OptisizingSelectionService {
context.alipayid=ali.id
context.wxpayid=wx.id
context.uid=wx.userid
if( context.request.phone!=null)
if( context.request.phone!=null) {
context.phone= context.request.phone
}
println("最后计算_wx_id:"+context.wxpayid)
println("最后计算_ali_id:"+context.alipayid)
println("最后计算_aliappid:"+context.aliappid)
println("最后计算_wxappid:"+context.wxappid)
println("最后计算_goodspaye:"+context.goodspaye)
......
......@@ -29,9 +29,6 @@ class PayOrderServer {
var pnr: PayNotifyRepository = _
def aa(): Unit ={
println("aaa")
}
/**
* @Description:
* @Author: yang
......@@ -52,8 +49,9 @@ class PayOrderServer {
// val url = ""
// val url = context.goodspaye.payrealmname.url+"/unitePay/notify/aliorder"
val url = context.goodspaye.payrealmname.url + s"/pay/aliorder/alinotify/${channelId}"
val url = context.goodspaye.payrealmname.url + s"/occloud/pay/aliorder/alinotify/${channelId}"
println("回调地址:"+url)
println("返回地址:"+context.getReturnUrl)
val aliappid = context.aliappid
val privatekey = context.privatekey
val alipaypublickey = context.alipaypublickey
......@@ -67,6 +65,7 @@ class PayOrderServer {
e.setNotifyurl(url)
e.setOuttradeno(str)
e.setStatus(0)
pnr.save(e)
//todo 订单保存,接收订单,检索订单-------1.0.3
val id = new IdWorker().nextId()
......@@ -82,11 +81,13 @@ class PayOrderServer {
o.setSubject(subject)
o.setUserip(ip)
o.setChannelid(channelId)
o.setGoodspayid(context.request.goodsid)
if(context.request.openid!=null){
o.setOpenid(context.request.openid)
o.setNickname(context.request.nickname)
o.setHeadimgurl(context.request.headimgurl)
}
o.setPaytype(2)
por.save(o)
val pe = new PayEntiy()
......@@ -105,7 +106,7 @@ class PayOrderServer {
pe.setExpireTime(goodspay.getExpireendtime)
pe.setChannelId(channelId)
pe.setReturnUrl(context.goodspaye.payrealmname.url )
pe.setReturnUrl(context.returnUrl)
ps.getPayUrl(pe)
}
......@@ -130,7 +131,7 @@ class PayOrderServer {
// val url = context.goodspaye.payrealmname.url+"/unitePay/notify/wxorder"
//val url = context.goodspaye.payrealmname.url + s"/pay/order/wxnotify/${channelId}"
val url = context.goodspaye.payrealmname.url + s"/pay/order2/notify/order/${channelId}"
val url = context.goodspaye.payrealmname.url + s"/occloud/pay/order2/notify/order/${channelId}"
println("回调地址:"+url)
val OrderId = String.valueOf(System.currentTimeMillis)
context.request.ip
......@@ -166,6 +167,8 @@ class PayOrderServer {
o.setNickname(context.request.nickname)
o.setHeadimgurl(context.request.headimgurl)
}
o.setGoodspayid(context.request.goodsid)
o.setPaytype(1)
por.save(o)
val pe = new PayEntiy()
pe.setBody(subject)
......@@ -203,7 +206,7 @@ class PayOrderServer {
// val url = context.goodspaye.payrealmname.url+"/unitePay/notify/wxorder"
// val url = context.goodspaye.payrealmname.url + s"/pay/order/wxnotify/${channelId}"
val url = context.goodspaye.payrealmname.url + s"/pay/order2/notify/order/${channelId}"
val url = context.goodspaye.payrealmname.url + s"/occloud/pay/order2/notify/order/${channelId}"
println("回调地址:"+url)
......@@ -239,6 +242,8 @@ class PayOrderServer {
o.setHeadimgurl(context.request.headimgurl)
}
o.setChannelid(channelId)
o.setGoodspayid(context.request.goodsid)
o.setPaytype(1)
por.save(o)
val pe = new PayEntiy()
pe.setBody(subject)
......@@ -258,5 +263,45 @@ class PayOrderServer {
ps.getPayUrl(pe)
}
//保存免费的订单
def saveFree(context:Context): String ={
//获取商品信息基础信息
val goodspay = context.goodspaye
val subject = goodspay.subject
val shortname = goodspay.shortname
val channelId = RandomUtil.randomLong
val ip = context.request.ip
val wxpayid = context.wxpayid
val phone = if (context.phone != null) context.phone else null
var uid=context.uid
val id = new IdWorker().nextId()
val OrderId = String.valueOf(System.currentTimeMillis)
val o = new PayOrderDO()
o.setId(id)
o.setMerchantid(uid)
o.setMerchantorderid(OrderId)
o.setAmount(goodspay.payment)
o.setAppid(wxpayid)
o.setBody(shortname)
o.setCreator(phone)
o.setSubject(subject)
o.setUserip(ip)
o.setStatus(1)
if(context.request.openid!=null){
o.setOpenid(context.request.openid)
o.setNickname(context.request.nickname)
o.setHeadimgurl(context.request.headimgurl)
}
o.setChannelid(channelId)
o.setGoodspayid(context.request.goodsid)
o.setPaytype(1)
por.save(o)
"ok"
}
}
......@@ -24,7 +24,7 @@ import java.util.regex.{Matcher, Pattern}
*/
@Api( tags = Array( "H5统一支付--1.0.2" ), value = "API",hidden = true )
@RestController
@RequestMapping(Array("/unitePay/"))
@RequestMapping(Array("/occloud/unitePay/"))
@CrossOrigin
class PayControllerPlus {
@Resource
......@@ -38,7 +38,7 @@ class PayControllerPlus {
var payorderserver: PayOrderServer = _
@PostMapping( Array( "loding" ) )
def Loding(): Unit ={
goodspayservice.lading()
goodspayservice.lading1()
}
@ApiOperation( value = "获取支付链接---通用版本1.0.2版本--风控版本", notes = "" )
......@@ -55,7 +55,7 @@ class PayControllerPlus {
val new_req = req.toRequest(ip)
val cache = goodspayservice.getGoodsPayById(new_req.goodsid.toString)
if(cache==null) return null
val url2 = cache.payrealmname.url
var url2 = cache.payrealmname.url
val wxappid2 = cache.payrealmname.appid
// val url2 = ""
val url = request.getHeader("Referer")
......@@ -63,21 +63,31 @@ class PayControllerPlus {
println("数据库域名:"+url2)
// val bool1 = patterns(url, url2)
// println("域名校验结果:"+bool1)
val bool2 = patterns( url2,url)
println("域名校验结果:"+bool2)
//域名过滤
if(!patterns(url2,url)){
println("====支付域名不对=====")
return null
}
val context = new Context( goodspayservice, new_req,null)
onloadpaylink.process(context)
// if(!patterns(url2,url)){
// println("====支付域名不对=====")
// return null
// }
url2+="#/?ditch="+req.ditch+"&goodsid="+req.goodsid+"&phone=1"
var context = new Context( goodspayservice, new_req,null,url2)
// if(context.goodspayservice.)
val goodspaye = onloadpaylink.process(context)
val payment1 = goodspaye.payment
//判断免费
// if(payment1==0L) context = new Context( goodspayservice, req.getFree(ip),null,url2)
if(wxappid2!=null) context.setWxappid2(wxappid2)
var result =
context. request.paytypeenum match {
case PayTypeEnum.WXPAY => GetWxReq(context)
case PayTypeEnum.ALIPAY =>GetAliReq(context)
case PayTypeEnum.WXJSPAY =>GetWxJsReq(context)
case PayTypeEnum.FreePAY =>saveFree(context)
case _ => null
}
......@@ -116,36 +126,11 @@ class PayControllerPlus {
}
boolean
}
//
// @GetMapping(Array("mini"))
// @ResponseBody
// def getminitets(): JsonResult ={
// val unit = amountredis.WxgetminAmount("1", "2")
// new JsonResult(unit)
// }
// @GetMapping(Array("all"))
// @ResponseBody
// def getminitets1(): JsonResult ={
// new JsonResult(amountredis.WxgetAllPay("1","2"))
// }
// @GetMapping(Array("push"))
// def pustest(payid:String,L:Long): Unit ={
//// val l = new Random(100).
//// println(l)
// amountredis.WxpushAmount("1","2",payid, L)
// }
// @GetMapping(Array("push"))
// def pustest(payid:String,L:Long): Unit ={
// // val l = new Random(100).
// // println(l)
// amountredis.WxpushAmount("1","2",payid, L)
// }
// @GetMapping(Array("push"))
// def pustest(payid:String,L:Long): Unit ={
// // val l = new Random(100).
// // println(l)
// amountredis.WxpushAmount("1","2",payid, L)
// }
def saveFree(context: Context): Object ={
payorderserver.saveFree(context)
}
}
......@@ -4,6 +4,7 @@ import com.icloud.server.utils.JsonUtils
import java.util
import java.util.regex.{Matcher, Pattern}
import scala.collection.convert.ImplicitConversions.`seq AsJavaList`
object test {
def main(args: Array[String]): Unit = {
......@@ -15,18 +16,32 @@ object test {
// var word = "@@全部内容"
// val result = word.search("全部内容")
// console.log(word.search("全部内容") != -1)
var u="http://pay.finekaa.com/#/?ditch=1578582016&goodsid=284406742828216320&phone=1"
val s = u.split("\\//").toList(1)
println(s)
// val a = new AA("q", new BB("q", "1"))
// val b = new AA("2", new BB("c", "2"))
// val c = new AA("3", new BB("d", "3"))
var si=Set(1,2,3,4,5,6)
val a = new AA("q", new BB("q", "1"))
val b = new AA("2", new BB("c", "2"))
val c = new AA("3", new BB("d", "3"))
// var si=Set(1,2,3,4,5,6)
// var s1=Set()
// val value = si.filter(x => x == 1).toSet
// println(value)
// var si=Set(a,b,c)
// println(si)
// val value = si.filter(x => x.b.a.equals("c")).toSet
// println(value)
val cc = new CC(List(a, b),"")
val c1 = new CC(List( c),"")
var dd=new DD(List(cc,c1))
// println(dd)
// dd.cc.map(x=>{x.aas= x.aas.filter(y=>{y.a=="2"})}).filter(x=>{x.!=(null)})
//
// println(dd)
val dd1 = setaa(dd)
println(dd1)
// r
// var s="asdasdasd aas"
// println(s.hashCode)
// println(patterns("1qweqwe", "1qweqweasdas"))
......@@ -35,13 +50,21 @@ object test {
// 请求url = http://pay.finekaa.com/?code=031eUSkl2420B94onZkl2UsF400eUSkn&state=1
// 数据库域名:http://pay.finekaa.com
// 域名校验结果:false
var s1="http://pay.finekaa.com/?code=031eUSkl2420B94onZkl2UsF400eUSkn&state=1"
var s2="http://pay.finekaa.com"
println(patterns(s1, s2))
println(patterns(s2, s1))
// var s1="http://pay.finekaa.com/?code=031eUSkl2420B94onZkl2UsF400eUSkn&state=1"
// var s2="http://pay.finekaa.com"
// println(patterns(s1, s2))
// println(patterns(s2, s1))
}
def setaa(d:DD): DD ={
val value = d.cc.filter(x => {
x.ff = "1123122"
true
})
new DD(value)
}
def patterns(param1:String,param2:String): Boolean ={
var boolean=false
......@@ -50,7 +73,38 @@ object test {
boolean = matcher.find
boolean
}
def r(): Unit ={
var wxpays=List(1,2,1,5,4)
var random=4
var start: Int = 0
var end: Int = 0
var ni: Int = 1
var wx=wxpays.last
while (ni < wxpays.size) {
if (ni == 1) { //初始化
start = wxpays(ni - 1)
end = wxpays(ni - 1) + wxpays(ni)
} else {
start = end
end = start + wxpays(ni)
}
if (random >= start && random < end) {
wx= wxpays(ni)
ni= wxpays.size+1
}
else if (random < start) {
wx= wxpays.get(ni - 1)
ni= wxpays.size+1
}
ni+=1
}
println(wx)
}
}
case class AA(a:String,b:BB)
case class BB(a:String,b:String)
case class CC(var aas: List[AA],var ff:String)
case class DD(cc: List[CC])
\ No newline at end of file
......@@ -32,7 +32,13 @@ import scala.jdk.CollectionConverters._
with PagingAndSortingRepository[Goodspay2, Long] {
def findBySubjectLikeAndStatusAndUseridOrderByIdDesc(subject: String,status:Int,userid: Long) :util.List[Goodspay2]
// def findByUseridAndStatus(userid: String,status: Int): java.util.List[Goodspay2]
def findByStatusAndUseridOrderByIdDesc(status: Int,userid: String,pageable: Pageable): java.util.List[Goodspay2]
def findByStatusAndUseridOrderByIdDesc(status: Int,userid: Long,pageable: Pageable): java.util.List[Goodspay2]
def countByStatusAndUseridOrderByIdDesc(status: Int,userid: Long): Long
def countBySubject(subject: String): Long
def countBySubjectLike(subject: String): Long
def countBySubjectLikeAndStatus(subject: String, status: Int): Long
def countBySubjectLikeAndStatusAndUserid(subject: String, status: Int, userid: Long): Long
def findBySubjectLikeAndStatusAndUseridOrderByIdDesc(subject: String, status: Int, userid: Long,pageable: Pageable): util.List[Goodspay2]
}
@Data
......@@ -66,7 +72,7 @@ class Goodspay2 extends Serializable {
var shortname: String = _
@BeanProperty
@Column( name = "user_id" )
var userid: String = _
var userid: Long = _
@BeanProperty
@Column(name = "goods_id" ,insertable = false, updatable = false)
var goodsid: Long = _
......
......@@ -21,7 +21,7 @@ import scala.beans.BeanProperty
*/
@Api( tags = Array( "获取H5页面参数" ), value = "API",hidden = true )
@RestController
@RequestMapping(Array("/unitePay/"))
@RequestMapping(Array("/occloud/unitePay/"))
@CrossOrigin
class H5PayPageCtroller {
......@@ -65,7 +65,13 @@ class H5PayPageCtroller {
}
val appId = gpp.payrealmname.appid
val url = gpp.payrealmname.url
val res = GetPayListRes(goods.subject, goods.shortname, goods.picurl, goods.body, gp.payment.toString, goods.markingprice.toString, gp.fullphone, gp.expireendtime, appId, url)
val time = try {
gp.expireendtime.getTime
} catch {
case e =>new Date().getTime+1800*1000
}
val res = GetPayListRes(goods.subject, goods.shortname, goods.picurl, goods.body, gp.payment.toString, goods.markingprice.toString, gp.fullphone, time, appId, url)
new JsonResult(res)
}
......@@ -143,7 +149,7 @@ case class GetPayListRes( @BeanProperty subject:String,
@BeanProperty price:String ,
@BeanProperty marking_price:String,
@BeanProperty getphone:String,
@BeanProperty endtime:Date,
@BeanProperty endtime:Long,
@BeanProperty appId:String,
@BeanProperty url:String
)
......
......@@ -25,9 +25,9 @@ import scala.jdk.CollectionConverters._
* @Date : 2022-07-07 6:40 PM
* @Version : 2.1.2
*/
@Api(tags = Array("支付渠道"), value = "API")
@Api(tags = Array("支付渠道与查询"), value = "API")
@RestController
@RequestMapping(Array("/pay/"))
@RequestMapping(Array("/occloud/pay/"))
@CrossOrigin
class PayController {
@Resource
......@@ -40,7 +40,7 @@ class PayController {
@BeanProperty
var wr1: Wxpay1Repository = _
@ApiOperation(value = "在支付配制中查询支付宝的详情", notes = "")
@ApiOperation(value = "在支付配制中---查询支付宝的详情", notes = "")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "uid", value = "支付实体类", required = true, dataType = "String")
))
......@@ -60,13 +60,13 @@ class PayController {
new JsonResult(alipays)
}
@ApiOperation(value = "在支付配制中查询微信渠道信息", notes = "")
@ApiOperation(value = "在支付配制中---查询微信渠道信息", notes = "")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "uid", value = "支付实体类", required = true, dataType = "String")
))
@PostMapping(Array("findWX1"))
@ResponseBody
def findWx1(uid: String): JsonResult = {
def findWx1( uid: String): JsonResult = {
var wxpays = wr1.findByUseridAndStatus(uid, 0)
wxpays=if(!wxpays.isEmpty) {
wxpays.asScala.filter(x=>{
......@@ -82,14 +82,14 @@ class PayController {
}
@ApiOperation(value = "查询支付宝渠道信息", notes = "")
@ApiOperation(value = "在创建支付链接中---查询支付宝渠道信息", notes = "")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "uid", value = "支付实体类", required = true, dataType = "String")
))
@PostMapping(Array("findAli"))
@ResponseBody
def findAli(uid: String): JsonResult = {
var alipays = ar1.findByUseridAndStatus(uid, 0)
var alipays = ar1.findByUseridAndStatusAndPaystate(uid, 0,0)
alipays=if(!alipays.isEmpty){
alipays.asScala.filter(x=>{
x.alipaypublickey=x.alipaypublickey
......@@ -109,14 +109,14 @@ class PayController {
new JsonResult(res)
}
@ApiOperation(value = "查询微信渠道信息", notes = "")
@ApiOperation(value = "在创建支付链接中---查询微信渠道信息", notes = "")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "uid", value = "支付实体类", required = true, dataType = "String")
))
@PostMapping(Array("findWX"))
@ResponseBody
def findWx(uid: String): JsonResult = {
var wxpays = wr1.findByUseridAndStatus(uid, 0)
var wxpays = wr1.findByUseridAndStatusAndPaystate(uid, 0,0)
wxpays=if(!wxpays.isEmpty) {
wxpays.asScala.filter(x=>{
x.appid=x.appid
......@@ -125,17 +125,7 @@ class PayController {
true
}).asJava
}else new util.ArrayList[Wxpay1]()
// @(ApiModelProperty@field)(position = 1, example = "1232", value = "goodsid") @JsonProperty("goodsid") goodsid: Long,
// @ApiIgnore() @(ApiModelProperty@field)(position = 1, example = "1232", value = "goodspayid") @JsonProperty("goodspayid") var goodspayid: Long,
// @(ApiModelProperty@field)(position = 1, example = "1232", value = "payname") @JsonProperty("payname") payname: String,
// @(ApiModelProperty@field)(position = 1, example = "1232", value = "optpay") @JsonProperty("optpay") optpay: Long,
// @(ApiModelProperty@field)(position = 1, example = "1232", value = "random") @JsonProperty("random") random: String,
// @(ApiModelProperty@field)(position = 1, example = "1232", value = "appointpay") @JsonProperty("appointpay") appointpay: Long,
// @(ApiModelProperty@field)(position = 1, example = "1232", value = "status") @JsonProperty("status") status: Int)
// wxpays.asScala.map(x=>{
//
// })
// new GoodspayditchCase()
val wxpay = new Wxpay1()
wxpay.setId(0)
......@@ -160,7 +150,7 @@ class PayController {
// println(s"privatekey = ${req.privatekey}")
// println(s"alipaypublickey = ${req.alipaypublickey}")
// println(s"req.paytype = ${req.paytype}")
ar1.save(new Alipay1().toEntity(req.name, req.appid, req.privatekey, req.alipaypublickey, 0, 1, 500000L, req.uid, req.paytype, 0))
ar1.save(new Alipay1().toEntity(req.name, req.appid, req.privatekey, req.alipaypublickey, 0, 1, 500000L, req.uid, 2, 0))
new JsonResult("ok")
}
......@@ -172,7 +162,7 @@ class PayController {
@ResponseBody
def createwx(@RequestBody req: CreateWxReq): JsonResult = {
wr1.save(new Wxpay1().toEntity(req.name, req.appid, req.mchid, req.mchkey, 0, 1, 500000L, req.uid, req.paytype, 0))
wr1.save(new Wxpay1().toEntity(req.name, req.appid, req.mchid, req.mchkey, 0, 1, 500000L, req.uid, 1, 0))
new JsonResult("ok")
}
......@@ -223,27 +213,27 @@ class PayController {
new JsonResult(pays)
}
@ApiOperation(value = "查询支付宝渠道信息", notes = "")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "uid", value = "支付实体类", required = true, dataType = "String")
))
@PostMapping(Array("findalipay"))
@ResponseBody
def findalipay(uid: Int): JsonResult = {
val userpay = upr.findByIdAndDfe(uid, 0)
val ali = new util.ArrayList[SelectPayRes]()
if (!userpay.alipay.isEmpty) {
userpay.alipay.asScala.map(x => {
ali.add(new SelectPayRes(x.id, x.paytype, x.name, x.amount,x.appid, xxx(x.privatekey),
x.alipaypublickey, null, x.status,
null, null, x.weight))
})
}
new JsonResult(ali)
}
// @ApiOperation(value = "在支付配制中---查询支付宝渠道信息", notes = "")
// @ApiImplicitParams(Array(
// new ApiImplicitParam(name = "uid", value = "支付实体类", required = true, dataType = "String")
// ))
// @PostMapping(Array("findalipay"))
// @ResponseBody
// def findalipay(uid: Int): JsonResult = {
//
// val userpay = upr.findByIdAndDfe(uid, 0)
// val ali = new util.ArrayList[SelectPayRes]()
//
// if (!userpay.alipay.isEmpty) {
//
// userpay.alipay.asScala.map(x => {
// ali.add(new SelectPayRes(x.id, x.paytype, x.name, x.amount,x.appid, xxx(x.privatekey),
// x.alipaypublickey, null, x.status,
// null, null, x.weight))
// })
// }
// new JsonResult(ali)
// }
def xxxappid(str:String): String ={
if(str==null||str.size<4)null else str.substring(0,3)+"*****"+ str.substring(str.size-3)
......@@ -252,27 +242,27 @@ class PayController {
// if(str==null||str.size<15)null else str.substring(0,4)+"*****"+ str.substring(str.size-5)
if(str==null||str.size<15)null else "********"
}
@ApiOperation(value = "查询微信渠道信息", notes = "")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "uid", value = "支付实体类", required = true, dataType = "String")
))
@PostMapping(Array("findwxpay"))
@ResponseBody
def findwxpay(uid: Int): JsonResult = {
val userpay = upr.findByIdAndDfe(uid, 0)
val wx = new util.ArrayList[SelectPayRes]()
if (!userpay.wxpay.isEmpty) {
userpay.wxpay.asScala.map(x => {
wx.add(new SelectPayRes(x.id, x.paytype, x.name, x.amount, xxxappid(x.appid), null,
null, null, x.status,
xxx(x.mchid), xxx(x.mchkey), x.weight))
})
}
new JsonResult(wx)
}
// @ApiOperation(value = "在支付配制中---查询微信渠道信息", notes = "")
// @ApiImplicitParams(Array(
// new ApiImplicitParam(name = "uid", value = "支付实体类", required = true, dataType = "String")
// ))
// @PostMapping(Array("findwxpay"))
// @ResponseBody
// def findwxpay(uid: Int): JsonResult = {
//
// val userpay = upr.findByIdAndDfe(uid, 0)
// val wx = new util.ArrayList[SelectPayRes]()
//
// if (!userpay.wxpay.isEmpty) {
// userpay.wxpay.asScala.map(x => {
// wx.add(new SelectPayRes(x.id, x.paytype, x.name, x.amount, xxxappid(x.appid), null,
// null, null, x.status,
// xxx(x.mchid), xxx(x.mchkey), x.weight))
// })
// }
//
// new JsonResult(wx)
// }
@ApiOperation(value = "更新支付宝渠道信息", notes = "不更新的字段,传null")
@ApiImplicitParams(Array(
......@@ -508,7 +498,7 @@ class Wxpay {
@Repository trait Alipay1Repository extends CrudRepository[Alipay1, Long] with JpaSpecificationExecutor[Alipay1] with JpaRepository[Alipay1, Long] with PagingAndSortingRepository[Alipay1, Long] {
def findByUseridAndStatus(userid: String, status: Int): util.List[Alipay1]
def findByUseridAndStatusAndPaystate(userid: String, status: Int, paystate: Int): util.List[Alipay1]
// override def findById(id: Long ):Alipay1
override def findById(id: Long): Optional[Alipay1]
......@@ -578,7 +568,7 @@ class Alipay1 {
@Repository trait Wxpay1Repository extends CrudRepository[Wxpay1, Long] with JpaSpecificationExecutor[Long] with JpaRepository[Wxpay1, Long] with PagingAndSortingRepository[Wxpay1, Long] {
def findByUseridAndStatus(userid: String, status: Int): util.List[Wxpay1]
def findByUseridAndStatusAndPaystate(userid: String, status: Int, paystate: Int): util.List[Wxpay1]
}
@Data
......
......@@ -18,9 +18,9 @@ import javax.annotation.Resource
import javax.persistence.{Column, Entity, Id, JoinColumn, ManyToOne, Table}
import scala.annotation.meta.field
import scala.beans.BeanProperty
@Api( tags = Array( "支付支付配制" ), value = "API",hidden = true )
@Api( tags = Array( "支付域名配制" ), value = "API",hidden = true )
@RestController
@RequestMapping(Array("/pay/"))
@RequestMapping(Array("/occloud/pay/"))
@CrossOrigin
class PayRealmNameCotroller {
......@@ -47,7 +47,7 @@ class PayRealmNameCotroller {
@PostMapping( Array( "selectrealmname" ) )
@ResponseBody
def select(uid:Long): JsonResult ={
println("uid:"+uid)
new JsonResult(prnr.findByUseridAndStatus(uid,0))
}
@ApiOperation( value = "更新支付域名", notes = "" )
......
......@@ -24,7 +24,7 @@ import scala.beans.BeanProperty
*/
@Api( tags = Array( "商户版本---2.0" ), value = "API",hidden = true )
@RestController
@RequestMapping(Array("/tenant/"))
@RequestMapping(Array("/occloud/tenant/"))
@CrossOrigin
class TenantController {
@Resource
......
......@@ -9,7 +9,10 @@ object test {
def main(args: Array[String]): Unit = {
var ll=List(1,2,31,2,12,123,434,34521,123,12,23)
// ll.sortBy(_>_=>)
val value = ll.filter(x => {
x == 1
})
println(value)
val a = new A(B("b"), null)
if (a.a == null) {println("null")}
......
package com.icloud.server.scala.paynotify
import com.icloud.server.payutils.dto.PayOrderDO
import lombok.{AllArgsConstructor, Data, NoArgsConstructor}
import org.hibernate.annotations.{CreationTimestamp, UpdateTimestamp}
import org.springframework.data.jpa.repository.{JpaRepository, JpaSpecificationExecutor}
import org.springframework.data.repository.{CrudRepository, PagingAndSortingRepository}
import org.springframework.stereotype.Repository
import java.util
import java.util.Date
import javax.persistence.{Column, Entity, GeneratedValue, GenerationType, Id, Table}
import javax.persistence._
import scala.beans.BeanProperty
/**订单校验
/** 订单校验
*
* @Author : yang
* @Date : 2022-07-26 00:41
* @Version : 2.1.2
*/
@Repository
trait PayNotifyRepository extends CrudRepository[PayNotifyEntity, Long] with JpaSpecificationExecutor[PayNotifyEntity] with JpaRepository[PayNotifyEntity, Long] with PagingAndSortingRepository[PayNotifyEntity, Long]{
trait PayNotifyRepository extends CrudRepository[PayNotifyEntity, Long] with JpaSpecificationExecutor[PayNotifyEntity] with JpaRepository[PayNotifyEntity, Long] with PagingAndSortingRepository[PayNotifyEntity, Long] {
def findByMerchantorderidAndOuttradenoAndStatus(merchantorderid: String, outtradeno: String, status: Int): util.List[PayNotifyEntity]
def findByMerchantorderidAndOuttradenoAndStatus(merchantorderid:String,outtradeno: String,status: Int): util.List[PayNotifyEntity]
def findByMerchantorderidAndStatus(merchantorderid:String,status: Int): util.List[PayNotifyEntity]
def findByMerchantorderidAndStatus(merchantorderid: String, status: Int): util.List[PayNotifyEntity]
}
@Data
@Entity
@Table(name = "pay_out_trade_no")
......@@ -49,6 +50,10 @@ class PayNotifyEntity extends Serializable {
@Column(name = "notify_status")
var status: Int = _
@transient
@BeanProperty
@Column
var returnurl: String = _
def toEntity(id: Long, merchantorderid: String, outtradeno: String, notifyurl: String, notifystatus: Int): PayNotifyEntity = {
this.id = id
......@@ -62,13 +67,13 @@ class PayNotifyEntity extends Serializable {
}
@Repository
trait PayNotifyLogRepository extends CrudRepository[PayNotifyLogEntity, Long] with JpaSpecificationExecutor[PayNotifyLogEntity] with JpaRepository[PayNotifyLogEntity, Long] with PagingAndSortingRepository[PayNotifyLogEntity, Long]{
trait PayNotifyLogRepository extends CrudRepository[PayNotifyLogEntity, Long] with JpaSpecificationExecutor[PayNotifyLogEntity] with JpaRepository[PayNotifyLogEntity, Long] with PagingAndSortingRepository[PayNotifyLogEntity, Long] {
// def findByMerchantorderidAndOuttradeno(merchantorderid:String,outtradeno: String): util.List[PayNotifyEntity]
// def findByMerchantorderidAndOuttradeno(merchantorderid:String,outtradeno: String): util.List[PayNotifyEntity]
}
@Data
@Entity
@Table(name = "pay_notify_log")
......@@ -77,7 +82,7 @@ trait PayNotifyLogRepository extends CrudRepository[PayNotifyLogEntity, Long] wi
class PayNotifyLogEntity extends Serializable {
@Id
@BeanProperty
@GeneratedValue( strategy = GenerationType.IDENTITY )
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
var id: Long = _
@BeanProperty
......@@ -106,7 +111,7 @@ class PayNotifyLogEntity extends Serializable {
@Column(name = "appid")
var appid: String = _
def toEntity( taskid: String, response: String, creator: String, updater: String,appid: String): PayNotifyLogEntity = {
def toEntity(taskid: String, response: String, creator: String, updater: String, appid: String): PayNotifyLogEntity = {
this.taskid = taskid
this.notifytimes = notifytimes
this.response = response
......
package com.icloud.server.scala.payorder
import com.icloud.server.payutils.dto.PayOrderDO
import com.icloud.server.scala.goods.Goodspay2
import com.icloud.server.web.JsonResult
import io.swagger.annotations.{Api, ApiOperation}
import org.springframework.data.domain.{PageRequest, Pageable, Sort}
import org.springframework.web.bind.annotation.{CrossOrigin, PostMapping, RequestMapping, RequestParam, ResponseBody, RestController}
import java.util
import javax.annotation.Resource
import scala.beans.BeanProperty
@Api( tags = Array( "订单查询" ), value = "API",hidden = true )
@RestController
@RequestMapping(Array("/orders/"))
@RequestMapping(Array("/occloud/orders/"))
@CrossOrigin
class OrderController {
......@@ -23,8 +26,7 @@ class OrderController {
@ResponseBody
def getorder(@RequestParam uid:Int,@RequestParam page:Int, @RequestParam size:Int): JsonResult ={
val request :Pageable= PageRequest.of(page-1, size, Sort.Direction.DESC, "id")
new JsonResult(por.findAllByMerchantidOrderByIdDesc(uid,request))
new JsonResult(new FindOrderall(por.countAllByMerchantid(uid), por.findAllByMerchantidOrderByIdDesc(uid,request)))
}
@ApiOperation( value = "精确查询订单", notes = "" )
@PostMapping( Array( "findorderid" ) )
......@@ -33,3 +35,6 @@ class OrderController {
new JsonResult(por.findByIdAndMerchantid(orderid,uid))
}
}
case class FindOrderall(@BeanProperty count:Long, @BeanProperty payorder:util.List[PayOrderDO])
......@@ -110,7 +110,7 @@ class OrderServer {
*/
def getAliAppId(uid: Long, appoint_pay: Long, random: Boolean): Alipay1 = {
val alipays = alipay.findByUseridAndStatus(uid.toString, 0)
val alipays = alipay.findByUseridAndStatusAndPaystate(uid.toString, 0,0)
//排序
// alipays.asScala.sortBy()
//权重
......@@ -169,7 +169,7 @@ class OrderServer {
*/
def getWxAppId(uid: Long, appoint_pay: Long, random: Boolean): Wxpay1 = {
val wxpays = wxpay.findByUseridAndStatus(uid.toString, 0)
val wxpays = wxpay.findByUseridAndStatusAndPaystate(uid.toString, 0,0)
//排序
// alipays.asScala.sortBy()
//权重
......
......@@ -13,7 +13,9 @@ trait PayOrderRepository extends CrudRepository[PayOrderDO, Long] with JpaSpecif
def findByChannelid(channelid: Long): PayOrderDO
def findAllByOrderById( pageable: Pageable): util.List[PayOrderDO]
def findAllByMerchantidOrderByIdDesc(merchantid:Long, pageable: Pageable): util.List[PayOrderDO]
def countAllByMerchantid(merchantid:Long):Long
def findByIdAndMerchantid (id: Long,merchantid:Long): PayOrderDO
def findByMerchantorderid (merchantorderid:String): PayOrderDO
def findByGoodspayid(goodspayid:Long):util.List[PayOrderDO]
}
\ No newline at end of file
......@@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.{CrossOrigin, PostMapping, Reques
@Api(tags = Array("统一接口:公共服务"), value = "API", hidden = true)
@RestController
@RequestMapping(Array("/pub/"))
@RequestMapping(Array("/occloud/pub/"))
@CrossOrigin
class PublicUnite {
......
......@@ -21,7 +21,7 @@ import scala.beans.BeanProperty
*/
@Api( tags = Array( "路由初始化" ), value = "API" )
@RestController
@RequestMapping( Array( "/init/" ) )
@RequestMapping( Array( "/occloud/init/" ) )
@CrossOrigin
class IinitController {
@Resource
......
......@@ -17,7 +17,7 @@ import scala.beans.BeanProperty
@Api( tags = Array( "用户" ), value = "API",hidden = true )
//@ApiIgnore
@RestController
@RequestMapping( Array( "/user/" ) )
@RequestMapping( Array( "/occloud/user/" ) )
@CrossOrigin
class UserController {
@BeanProperty
......
package com.icloud.server.scala.shiro
import com.icloud.server.user.{AESUtil, Constants}
import com.icloud.server.utils.IdWorker
import org.apache.shiro.crypto.hash.SimpleHash
import org.springframework.stereotype.Component
......@@ -90,10 +91,15 @@ class UserService {
val hashName = "md5"
// val pwd = "123456"
var salt="OCCLOUD+JWT"
val SECRET = "OCCLOUD_CHANNEL+JWT"
val result = new SimpleHash( hashName, pwd,null , 2 )
val user =new User
user.setUsername(username)
user.setPassword(result.toString)
// user.setPassword(AESUtil.Encrypt(pwd, Constants.PASSWORD_KEY))
user.setLock_flag("0")
user.setMini_openid("aaa")
user.setQq_openid("00")
......
package com.icloud.server.user;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
/**
* @author Administrator
*/
public class AESUtil {
// 加密
public static String Encrypt(String sSrc, String sKey) throws Exception {
if (sKey == null) {
System.out.println("Key为空null");
return null;
}
// 判断Key是否为16位
if (sKey.length() != 16) {
// System.out.println("Key长度不是16位");
return null;
}
byte[] raw = sKey.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
return new Base64().encodeToString(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。
}
// 解密
public static String Decrypt(String sSrc, String sKey) throws Exception {
try {
// 判断Key是否正确
if (sKey == null) {
System.out.println("Key为空null");
return null;
}
// 判断Key是否为16位
if (sKey.length() != 16) {
// System.out.println("Key长度不是16位");
return null;
}
byte[] raw = sKey.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] encrypted1 = new Base64().decode(sSrc);//先用base64解密
try {
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original, "utf-8");
return originalString;
} catch (Exception e) {
System.out.println(e.toString());
return null;
}
} catch (Exception ex) {
System.out.println(ex.toString());
return null;
}
}
public static void main(String[] args) throws Exception {
/*
* 此处使用AES-128-ECB加密模式,key需要为16位。
*/
String cKey = "ocschool20200824";
System.out.println(cKey);
// 需要加密的字串
//欧畅云账户的密码测试账户的密码
String cSrc = "AmIozjGMKNQaoG1U";
//String cSrc = "654321";
System.out.println(cSrc);
// 加密
String enString = AESUtil.Encrypt(cSrc, cKey);
System.out.println("加密后的字串是:" + enString);
//String mm = "ga4JaZdcU0MsUmYLza5MeQ";
// 解密
//String DeString = AESUtil.Decrypt(mm, cKey);
//String DeString = AESUtil.Decrypt("2H5jyO5+zJcwNGZhtWAT8Q==", cKey);
String DeString = AESUtil.Decrypt("b/cMNm2agJxIRWb3HeoCSqCE2+s58C0IbG5n6jxR00M=", cKey);
System.out.println("解密后的字串是:" + DeString);
}
}
\ No newline at end of file
package com.icloud.server.user;
public class Constants {
//密码加密key
public static final String PASSWORD_KEY="ocschool20200824";
//上课通知的时间
public static final String NOTICE_IN_CLASS = "7:00:00";
//每页行数
public static final int ROWS_COUNT_PER_PAGE = 10;
public static final String WX_MP_USER="wx_mp_user:";
public static final String JS_Ticket="JS_Ticket:";
public static final String H5_AUTH_WX="h5_auth_wx_";
public static final String VIDEO_CODE_H264 = "h264";
public static final String OC_VIDEO_IN_BUCKET="oc-video-in";
public static final String OC_VIDEO_OUT_BUCKET="oc-video-out";
public static final String OC_SCHOOL_BUCKET="oc-school";
public static final class JOB_TRACKER{
public static final String VIDEO_JOB="VideoJob";
}
public static final class TASK_TRACKER{
public static final String VIDEO_TRADE_TASKTRACKER="video_trade_TaskTracker";
}
//用户跟踪状态
public static final String [] STEPS = {"新线索", "意向客户", "暂无意向", "无意向", "邀约试听", "试用满意", "试用不满意", "付费承诺", "付费爽约", "付费未签约", "签约未付费", "付费已签约"," 合同执行中", "临近合同结束", "合同已结束"};
//充值路径
public static final String[] CLIENT_TOP_up_PATH = {"秀视对公","方卡对公","私账"};
//员工分配数据来源类型:0 系统自动分配, 1 人为分配
public static final Integer ASSIGN_INFO_TYPE_SYS = 0;
public static final Integer ASSIGN_INFO_TYPE_MAN = 1;
public static final String URL_PREFIX = "https://testapi.finezb.com/2.0/";
//直播数据接口
//查询某一天直播客户数
public static final String URL_GET_TODAY_LIVE_ACCOUNT = URL_PREFIX + "getTodayLiveAccount";
//查询当前直播客户数
public static final String URL_GET_CURRENT_LIVE_ACCOUNT = URL_PREFIX + "getCurrentLiveAccount";
//查询当前观众数
public static final String URL_GET_TODAY_AUDIENCE_ACCOUNT = URL_PREFIX + "getTodayAudienceCount";
//查询当直播客户客户详情
public static final String URL_GET_CURRENT_LIVE_ACCOUNT_INFO = URL_PREFIX + "getCurrentLiveAccountInfo";
// 查询历史直播数据
public static final String URL_GET_YESTERDAY_ACCOUNT_INFO = URL_PREFIX + "getYesterdayAccountInfo";
//渠道类型 私域渠道
public static String CHANNEL_CLASSIFY_PRIVATE = "PRIVATE";
//渠道类型 公共渠道
public static String CHANNEL_CLASSIFY_PUBLIC = "PUBLIC";
//渠道状态有效
public static String CHANNEL_STATUS_VALID = "VALID";
//渠道状态无效
public static String CHANNEL_STATUS_INVALID = "INVALID";
//员工路径标识
public static String SCHOOL_SUB_LOGIN_FLAG = "SCHOOL_SUB_LOGIN_FLAG_";
//渠道管理员最大之
public static Integer CHANNEL_MANAGEMENT_MAX=5;
//欧畅云大账号token
public static String OC_TOKEN="oc_token_";
//欧畅云accessSecretKey
public static String OC_ACCESS_SECRET="oc_access_secret_";
//欧畅云accessSecretKey
public static String OC_ROOM_TOKEN="oc_room_token_";
//默认分组的值
public static Long DEFAULT_GROUP_VALUE=-1L;
//默认分组str
public static String DEFAULT_GROUP_STR="默认分组";
}
package com.icloud.server.utils;
public class Constants {
public static final String SUCCESS_CODE = "100";
public static final String SUCCESS_MSG = "请求成功";
/**
* session中存放用户信息的key值
*/
public static final String SESSION_ACCOUNT_INFO = "accpuntInfo";
public static final String SESSION_ACCOUNT_PERMISSION = "accountPermission";
public static final String SESSION_ACCOUNT_MENU = "accountMenu";
public static final String SESSION_RANDOM_CODE = "randCode";
public static final String SESSION_SMS_CODE = "smsCode";
//固定角色id[系统管理员权限]
public static final String SYSTEM_ROLE_ID = "1";
//固定角色id[客户管理员]
public static final String CLIENT_MANAGER_ROLE_ID = "2";
//每页行数
public static final int ROWS_COUNT_PER_PAGE = 10;
//大数据量是每页行数
public static final int ROWS_COUNT_BIG_PER_PAGE = 20;
//临时文件夹
public static final String TEMP_IMAGE_PATH = "E:\\";
//密码加密key
public static final String PASSWORD_KEY="ocschool20200824";
//用户跟踪状态
public static final String [] STEPS = {"新线索", "意向客户", "暂无意向", "无意向", "邀约试听", "试用满意", "试用不满意", "付费承诺", "付费爽约", "付费未签约", "签约未付费", "付费已签约"," 合同执行中", "临近合同结束", "合同已结束"};
}
package com.icloud.server.utils;
import lombok.*;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @description: 响应消息体
* @author: zjbing
* @create: 2021-01-13 17:04
**/
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class R<T> implements Serializable {
private static final long serialVersionUID = 1L;
@Getter
@Setter
private int code;
@Getter
@Setter
private String msg;
@Getter
@Setter
private long total;
@Getter
@Setter
private T data;
public static <T> R<T> ok() {
return restResult(null, CodeDefs.SUCCESS, "成功",0);
}
public static <T> R<T> ok(String msg) {
return restResult(null, CodeDefs.SUCCESS, msg,0);
}
public static <T> R<T> ok(T data) {
return restResult(data, CodeDefs.SUCCESS, "成功",0);
}
public static <T> R<T> ok(T data,long total) {
return restResult(data, CodeDefs.SUCCESS, "成功",total);
}
public static <T> R<T> ok(T data, String msg) {
return restResult(data, CodeDefs.SUCCESS, msg,0);
}
public static <T> R<T> failed() {
return restResult(null, CodeDefs.FAIL, "失败",0);
}
public static <T> R<T> failed(String msg) {
return restResult(null, CodeDefs.FAIL, msg,0);
}
public static <T> R<T> failed(T data) {
return restResult(data, CodeDefs.FAIL, "失败",0);
}
public static <T> R<T> failed(T data, String msg) {
return restResult(data, CodeDefs.FAIL, msg,0);
}
public static <T> R<T> failed(Integer code) {
return restResult(null, code, "失败",0);
}
public static <T> R<T> failed(Integer code, String msg) {
return restResult(null, code, msg,0);
}
private static <T> R<T> restResult(T data, int code, String msg,long total) {
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
apiResult.setTotal(total);
return apiResult;
}
}
package com.icloud.server.utils.annotation;
import java.lang.annotation.*;
/**
* 鉴权注解
* @Author jiebing
* @Date 2021/3/22 15:58
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AccessRequired {
}
package com.icloud.server.utils.http
import scala.collection.JavaConverters._
object Net {
import scalaj.http._
def run (url: String, requestJson: String) = {
val startTime = System.currentTimeMillis()
val r = Http( url ).timeout( connTimeoutMs = 10000, readTimeoutMs = 20000 ).header( "Content-Type", "application/json; charset=utf8" ).postData( requestJson ).asString
val endTime = System.currentTimeMillis()
val allCost = endTime - startTime // pdbDebug.debug(s"id:${impId}|dsp:${dsp.getName}==>${requestJson}")
// pdbDebug.debug(s"id:${impId}|dsp:${dsp.getName}| cost: $allCost| httpcode: ${r.code} :<==${r.body.replaceAll("\n", "").replaceAll("\r", "")}")
(r.code, r.body)
}
}
package com.icloud.server.utils.threads;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @Author : yang
* @Date : 2019/6/19 5:05 PM
* @Version : 1.2.1
*/
@EnableAsync
@Configuration
public class GetRedThreads {
@Bean("getExecutor")
public Executor getExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("getExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
return executor;
}
}
package com.icloud.server.utils.threads;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* spring 线程池
* @Author : yang
* @Date : 2019/4/1 6:14 PM
* @Version : 1.2.1
*/
@EnableAsync
@Configuration
public class Threads {
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
return executor;
}
}
package com.icloud.server.web.jwt;
package com.icloud.server.web.Jwts;
import com.alibaba.fastjson.JSONObject;
import com.icloud.server.utils.CodeDefs;
......@@ -51,13 +51,20 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json; charset=utf-8");
try (PrintWriter out = httpServletResponse.getWriter()) {
PrintWriter out = null;
try {
out = httpServletResponse.getWriter();
JSONObject object = new JSONObject();
object.put("code", CodeDefs.ERROR_REQUEST);
object.put("message","登录超时,请重新登录");
out.append(object.toJSONString());
object.put("message","您无权限");
out.print(object.toJSONString());
out.flush();;
} catch (IOException e) {
//logger.error("直接返回Response信息出现IOException异常", e);
}finally {
if(out!=null){
out.close();
}
}
return false;
}
......@@ -69,7 +76,7 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
@Override
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
String token = req.getHeader("Token");
String token = req.getHeader("token");
return token != null;
}
......@@ -79,7 +86,7 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = httpServletRequest.getHeader("Token");
String token = httpServletRequest.getHeader("token");
JWTToken jwtToken = new JWTToken(token);
// 提交给realm进行登入,如果错误他会抛出异常并被捕获
try {
......@@ -90,13 +97,20 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json; charset=utf-8");
try (PrintWriter out = httpServletResponse.getWriter()) {
PrintWriter out = null;
try {
out = httpServletResponse.getWriter();
JSONObject object = new JSONObject();
object.put("code", CodeDefs.ERROR_REQUEST);
object.put("message","登录超时,请重新登录");
out.append(object.toJSONString());
object.put("message","您无权限");
out.print(object.toJSONString());
out.flush();
} catch (IOException ex) {
//logger.error("直接返回Response信息出现IOException异常", e);
}finally {
if(out!=null){
out.close();
}
}
return false;
}
......
package com.icloud.server.web.jwt;
package com.icloud.server.web.Jwts;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
......@@ -12,24 +13,23 @@ public class JWTUtil {
// 过期时间 24 小时
private static final long EXPIRE_TIME = 60 * 24 * 60 * 1000;
//private static final long EXPIRE_TIME = 1 * 1 * 60 * 1000;
// private static final long EXPIRE_TIME = 1 * 1 * 60 * 1000;
// 密钥
// private static final String SECRET = "OCCLOUD+JWT"; //ouchang
private static final String SECRET = "ouchang"; //
//private static final String SECRET = "OCCLOUD_CHANNEL+JWT";
private static final String SECRET = "OCCLOUD_CHANNEL+JWT";
/**
* 生成 token, 5min后过期
*
* @param username 用户名
* @param param 用户名
* @return 加密的token
*/
public static String createToken(String username,Long clientId) {
public static String createToken(String param) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(SECRET);
// 附带username信息
return JWT.create()
.withClaim("username", username)
.withClaim("clientId", clientId)
.withClaim("param",param)
//到期时间
.withExpiresAt(date)
//创建一个新的JWT,并使用给定的算法进行标记
......@@ -48,7 +48,7 @@ public class JWTUtil {
Algorithm algorithm = Algorithm.HMAC256(SECRET);
//在token中附带了username信息
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username", username)
.withClaim("param", username)
.build();
//验证 token
verifier.verify(token);
......@@ -66,30 +66,31 @@ public class JWTUtil {
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username").asString();
String json = jwt.getClaim("param").asString();
JSONObject obj = JSONObject.parseObject(json);
return obj.getString("username");
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 获得token中的信息,无需secret解密也能获得
*
* @return token中包含的用户名
* 获取clientId
* @param token
* @return
*/
public static Long getClientId(String token) {
public static String getClientId(String token){
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("clientId").asLong();
String json = jwt.getClaim("param").asString();
JSONObject obj = JSONObject.parseObject(json);
return obj.getString("clientId");
} catch (JWTDecodeException e) {
return null;
}
}
public static void main(String[] args) {
// System.out.println(getUsername("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTgyNDk4NDYsInVzZXJuYW1lIjoiYWRtaW4ifQ.Ls6vU2wURqpd_Rg2Eh663M1gp5E2qNRbgOHgO5dRelQ"));
System.out.println(getUsername("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTgyNDk4NDYsInVzZXJuYW1lIjoiYWRtaW4ifQ.Ls6vU2wURqpd_Rg2Eh663M1gp5E2qNRbgOHgO5dRelQ"));
}
}
package com.icloud.server.web.Jwts;
import com.alibaba.fastjson.JSONObject;
import com.icloud.server.scala.shiro.User;
import com.icloud.server.scala.shiro.UserRepository;
import com.icloud.server.utils.Constants;
import com.icloud.server.web.Jwts.JWTToken;
import com.icloud.server.web.Jwts.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
@Slf4j
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserRepository userrepository;
/**
* 必须重写此方法,不然会报错
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JWTToken;
}
@Override
@SuppressWarnings("unchecked")
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("————权限认证————");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
return info;
}
/**
* 验证当前登录的Subject
* LoginController.login()方法中执行Subject.login()时 执行此方法
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
System.out.println("————身份认证方法————");
String token = (String) authcToken.getCredentials();
// 解密获得username,用于和数据库进行对比
String username = JWTUtil.getUsername(token);
Long clientId = null;
String ddd=JWTUtil.getClientId(token);
if(StringUtils.isNotBlank(JWTUtil.getClientId(token))){
clientId = Long.valueOf(JWTUtil.getClientId(token));
}
JSONObject param = new JSONObject();
param.put("username",username);
param.put("clientId",clientId);
if (clientId==null || username == null || !JWTUtil.verify(token, param.toJSONString())) {
throw new AuthenticationException("token认证失败!");
}
User channelDat = userrepository.findByUsernameAndDfe(username,0);
// String loginName = (String) authcToken.getPrincipal();
// ChannelDat channelDat = channelService.getLoginExist(clientId,username);
// AccountDat accountDat = accountService.getAccountByUserName(username);
if (channelDat == null) {
throw new AuthenticationException("该用户不存在!");
}
JSONObject accountJson = (JSONObject)JSONObject.toJSON(channelDat);
SecurityUtils.getSubject().getSession().setAttribute(Constants.SESSION_ACCOUNT_INFO,accountJson);
return new SimpleAuthenticationInfo(token, token, "MyRealm");
}
}
......@@ -8,6 +8,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.icloud.server.web.shiro.handler.TokenValidateInterceptor;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -16,6 +17,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.io.IOException;
......@@ -53,6 +56,25 @@ public class WebConfig implements WebMvcConfigurer {
// }
//token
// @Autowired
// private TokenValidateInterceptor tokenValidateInterceptor;
//
// @Override
// public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(tokenValidateInterceptor);
// }
//
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("GET","POST","HEAD","PUT","DELETE","OPTIONS")
.allowCredentials(true)
.allowedOriginPatterns("*")
.allowedHeaders("*")
.maxAge(3600);
}
......
......@@ -88,9 +88,10 @@ public class CustomRealm extends AuthorizingRealm {
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("认证 doGetAuthenticationInfo");
System.out.println("token:"+token);
//从token获取用户信息,token代表用户输入
String username = (String)token.getPrincipal();
System.out.println("username:"+username);
User user = userrepository.findByUsernameAndDfe(username,0);
......
package com.icloud.server.web.shiro.config;
import com.alibaba.fastjson.JSONObject;
import com.icloud.server.utils.CodeDefs;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;
/**
......@@ -18,9 +24,8 @@ import java.util.Set;
public class CustomRolesOrAuthorizationFilter extends AuthorizationFilter {
@Override
@SuppressWarnings({"unchecked"})
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
public boolean isAccessAllowed1(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
//
Subject subject = getSubject(request, response);
......@@ -30,9 +35,9 @@ public class CustomRolesOrAuthorizationFilter extends AuthorizationFilter {
// setHeader((HttpServletRequest) request, (HttpServletResponse) response);
// return true;
// }
if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
return true;
}
// if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
// return true;
// }
// if ("OPTIONS".equals(((HttpServletRequest)request).getMethod())){
// ((HttpServletResponse)response).setStatus(org.apache.http.HttpStatus.SC_NO_CONTENT);;
// setHeader((HttpServletRequest)request,(HttpServletResponse)response);
......@@ -44,6 +49,8 @@ public class CustomRolesOrAuthorizationFilter extends AuthorizationFilter {
if (rolesArray == null || rolesArray.length == 0) {
//no roles specified, so nothing to check - allow access.
return true;
}else {
}
......@@ -57,14 +64,63 @@ public class CustomRolesOrAuthorizationFilter extends AuthorizationFilter {
}
return false;
}
// @Override
// protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
// WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
// return false;
// }
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws UnauthorizedException {
//判断请求的请求头是否带上 "Token"
if (isLoginAttempt(request, response)) {
return true;
}else{
return checkToken(request, response);
}
//如果请求头不存在 Token,则可能是执行登陆操作或者是游客状态访问,无需检查 token,直接返回 true
}
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
String token = req.getHeader("token");
return token != null;
}
private boolean checkToken(ServletRequest request, ServletResponse response) {
// 没有携带Token
HttpServletRequest httpRequest = (HttpServletRequest)request;
String httpMethod = httpRequest.getMethod();
String requestURI = httpRequest.getRequestURI();
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
try {
out = httpServletResponse.getWriter();
JSONObject object = new JSONObject();
object.put("code", CodeDefs.ERROR_REQUEST);
object.put("message","您无权限");
out.print(object.toJSONString());
out.flush();;
} catch (IOException e) {
//logger.error("直接返回Response信息出现IOException异常", e);
}finally {
if(out!=null){
out.close();
}
}
return false;
}
//-------
private void setHeader(HttpServletRequest request, HttpServletResponse response) {
System.out.println("setHeader");
System.out.println("===========setHeader=========");
//request.getHeader("Origin")
response.setHeader("Access-Control-Allow-Origin","*" );
response.setHeader("Access-Control-Allow-Credentials", "true");
......@@ -75,46 +131,22 @@ public class CustomRolesOrAuthorizationFilter extends AuthorizationFilter {
response.setStatus(HttpStatus.OK.value());
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) {
// 错误异常提示
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
setHeader(httpRequest,httpResponse);
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setContentType("application/json");
return false;
}
//-------
// /**
// * 为response设置header,实现跨域
// */
// private void setHeader(HttpServletRequest request,HttpServletResponse response){
// //跨域的header设置
// response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
// response.setHeader("Access-Control-Allow-Methods", request.getMethod());
// response.setHeader("Access-Control-Allow-Credentials", "true");
// response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
// //防止乱码,适用于传输JSON数据
// //Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild
// response.setHeader("Content-Type","application/json;charset=UTF-8");
// response.setStatus(HttpStatus.OK.value());
// }
// @Override
// protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
// HttpServletResponse res = (HttpServletResponse)response;
// res.setHeader("Access-Control-Allow-Origin", "*");
// res.setStatus(HttpServletResponse.SC_OK);
// res.setCharacterEncoding("UTF-8");
// PrintWriter writer = res.getWriter();
// Map<String, Object> map= new HashMap<>();
// map.put("code", 702);
// map.put("msg", "未登录");
// writer.write(JSON.toJSONString(map));
// writer.close();
// protected boolean onAccessDenied(ServletRequest request, ServletResponse response) {
// // 错误异常提示
// HttpServletResponse httpResponse = (HttpServletResponse) response;
// HttpServletRequest httpRequest = (HttpServletRequest) request;
// setHeader(httpRequest,httpResponse);
// httpResponse.setCharacterEncoding("UTF-8");
// httpResponse.setContentType("application/json");
// return false;
// }
}
......@@ -6,11 +6,14 @@ import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Map;
public class CustomSessionManager extends DefaultWebSessionManager {
private static final String AUTHORIZATION = "token";
private static final String AUTHORIZATION = "token";//Authorization
// private static final String AUTHORIZATION = "Authorization";//
public CustomSessionManager(){
......@@ -19,7 +22,22 @@ public class CustomSessionManager extends DefaultWebSessionManager {
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
String token = WebUtils.toHttp(request).getHeader("Authorization");
System.out.println("Authorization:"+token);
String sessionId = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
System.out.println(WebUtils.toHttp(request));
String URI = WebUtils.toHttp(request).getRequestURI();
HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
String servletPath = httpServletRequest.getServletPath();
Map<String, String[]> parameterMap = httpServletRequest.getParameterMap();
System.out.println("======路径:"+URI);
for(Object key:parameterMap.keySet()){
String v = parameterMap.get(key)[0];
System.out.println("======参数:"+key+":"+v);
}
System.out.println("======sessionId:"+sessionId);
if(sessionId==null||"".equals(sessionId)){
sessionId=request.getParameter(AUTHORIZATION);
}
......
//package com.icloud.server.web.shiro.config;
//
//import org.apache.shiro.util.CollectionUtils;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.web.cors.CorsConfiguration;
//import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
//import org.springframework.web.filter.CorsFilter;
//
//import java.util.ArrayList;
//import java.util.List;
//
///**https://blog.csdn.net/qq_36950158/article/details/120308594
// * @Author : yang
// * @Date : 2022-08-03 03:30
// * @Version : 2.1.2
// */
//
//@Configuration
//public class GlobalCorsConfig {
//
//
// @Bean
// public CorsFilter corsFilter() {
// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// //配置 可以访问的地址
// source.registerCorsConfiguration("/**", buildConfig()); // 4
// return new CorsFilter(source);
// }
//
//
//
// private CorsConfiguration buildConfig(){
// List<String> stelist = new ArrayList<String>();
// stelist.add("http://localhost:8080");
// CorsConfiguration corsConfiguration = new CorsConfiguration();
//
// if(CollectionUtils.isEmpty(stelist)){
// corsConfiguration.addAllowedOrigin("*");
// }else{
// corsConfiguration.setAllowedOrigins(stelist);
// }
// corsConfiguration.addAllowedHeader("*");
// corsConfiguration.addAllowedMethod("*");
// corsConfiguration.setAllowCredentials(true);
//
// corsConfiguration.addAllowedMethod("POST");
// corsConfiguration.addAllowedMethod("PUT");
// corsConfiguration.addAllowedMethod("GET");
// return corsConfiguration;
// }
//
//
//
//}
package com.icloud.server.web.shiro.config;
import com.icloud.server.web.jwt.JWTFilter;
import com.icloud.server.web.Jwts.JWTFilter;
import com.icloud.server.web.Jwts.JWTToken;
import com.icloud.server.web.Jwts.JWTUtil;
import com.icloud.server.web.Jwts.UserRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
......@@ -36,17 +41,19 @@ public class ShiroConfig {
//需要登录的接口,如果访问某个接口,需要登录却没登录,则调用此接口(如果不是前后端分离,则跳转页面)
shiroFilterFactoryBean.setLoginUrl("/pub/need_login");
// shiroFilterFactoryBean.setLoginUrl("/pub/need_login");
//登录成功,跳转url,如果前后端分离,则没这个调用
shiroFilterFactoryBean.setSuccessUrl("/");
// shiroFilterFactoryBean.setSuccessUrl("/");
//没有权限,未授权就会调用此方法, 先验证登录-》再验证是否有权限
shiroFilterFactoryBean.setUnauthorizedUrl("/pub/not_permit");
//设置自定义filter
//设置自定义filter---过滤规则
Map<String, Filter> filterMap = new LinkedHashMap<>();
filterMap.put("roleOrFilter",new CustomRolesOrAuthorizationFilter());
// filterMap.put("user1",new CustomRolesOrAuthorizationFilter());
filterMap.put("user",new StatelessAuthcFilter());
// filterMap.put("user", new JWTFilter());
// filterMap.put("roleOrFilter",new JWTFilter());
// filterMap.put("jwt",new JWTFilter());
shiroFilterFactoryBean.setFilters(filterMap);
......@@ -55,33 +62,42 @@ public class ShiroConfig {
//拦截器路径,坑一,部分路径无法进行拦截,时有时无;因为同学使用的是hashmap, 无序的,应该改为LinkedHashMap
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
//退出过滤器
filterChainDefinitionMap.put("/logout","logout");
filterChainDefinitionMap.put("/occloud/logout","logout");
// filterChainDefinitionMap.put("/login","anon");
filterChainDefinitionMap.put("/swagger-ui.html**", "anon");
filterChainDefinitionMap.put("/v2/api-docs", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/test/**", "anon");
filterChainDefinitionMap.put("/oss/**", "anon");
filterChainDefinitionMap.put("/occloud/oss/**", "anon");
filterChainDefinitionMap.put("/init/**", "anon");
filterChainDefinitionMap.put("/aaa/**", "anon");
filterChainDefinitionMap.put("/user/**", "anon");
filterChainDefinitionMap.put("/occloud/aaa/**", "anon");
filterChainDefinitionMap.put("/occloud/pub/**","anon");
filterChainDefinitionMap.put("/occloud/user/**", "anon");
filterChainDefinitionMap.put("/tenant/**", "anon");
filterChainDefinitionMap.put("/pay/**", "anon");
filterChainDefinitionMap.put("/unitePay/**", "anon");
filterChainDefinitionMap.put("/goods/**", "anon");
filterChainDefinitionMap.put("/file/**", "anon");
// filterChainDefinitionMap.put("/pay/**", "anon");
filterChainDefinitionMap.put("/occloud/unitePay/**", "anon");
// filterChainDefinitionMap.put("/goods/**", "anon");
// filterChainDefinitionMap.put("/goods/**", "authc");
filterChainDefinitionMap.put("/occloud/file/**", "anon");
filterChainDefinitionMap.put("/t/**", "anon");
filterChainDefinitionMap.put("/wxconfigutils/**", "anon");
filterChainDefinitionMap.put("/weixin/**", "anon");
filterChainDefinitionMap.put("/wxLogin/**", "anon");
filterChainDefinitionMap.put("/wx/**", "anon");
filterChainDefinitionMap.put("/orders/**", "anon");
filterChainDefinitionMap.put("/occloud/pay/aliorder/**", "anon");
filterChainDefinitionMap.put("/occloud/pay/order2/**", "anon");
// filterChainDefinitionMap.put("/wx/**", "authc");
// filterChainDefinitionMap.put("/orders/**", "anon");
// filterChainDefinitionMap.put("/orders/**", "authc");
//匿名可以访问,也是就游客模式
filterChainDefinitionMap.put("/pub/**","anon");
filterChainDefinitionMap.put("/excel/**","anon");
filterChainDefinitionMap.put("/**","anon");
// filterChainDefinitionMap.put("/authcc/**","anon");
......@@ -89,7 +105,7 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/authc/**","authc");
//管理员角色才可以访问
filterChainDefinitionMap.put("/admin/**","roleOrFilter[admin,root]");
// filterChainDefinitionMap.put("/admin/**","roleOrFilter[admin,root]");
//有编辑权限才可以访问
filterChainDefinitionMap.put("/video/update","perms[video_update]");
......@@ -99,7 +115,8 @@ public class ShiroConfig {
//authc : url定义必须通过认证才可以访问
//anon : url可以匿名访问
filterChainDefinitionMap.put("/**", "authc");
filterChainDefinitionMap.put("/**", "user");
// filterChainDefinitionMap.put("/**", "user1");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
......@@ -119,13 +136,35 @@ public class ShiroConfig {
//设置realm(推荐放到最后,不然某些情况会不生效)
securityManager.setRealm(customRealm());
// securityManager.setRealm(userRealm());
return securityManager;
// ==========智客的方案===========
// DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// securityManager.setRealm(userRealm());
// /*
// * 关闭shiro自带的session,详情见文档
// * http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
// */
// DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
// DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
// defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
// subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
// securityManager.setSubjectDAO(subjectDAO);
// return securityManager;
return securityManager;
}
}
//智客的方法
@Bean
public UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
userRealm.setAuthenticationTokenClass(JWTToken.class);
return userRealm;
}
/**
* 自定义realm
* @return
......@@ -133,7 +172,6 @@ public class ShiroConfig {
@Bean
public CustomRealm customRealm(){
CustomRealm customRealm = new CustomRealm();
customRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return customRealm;
}
......@@ -152,9 +190,10 @@ public class ShiroConfig {
//散列次数,好比散列2次,相当于md5(md5(xxxx))
credentialsMatcher.setHashIterations(2);
credentialsMatcher.setStoredCredentialsHexEncoded(true);
// credentialsMatcher.setStoredCredentialsHexEncoded(true);
return credentialsMatcher;
}
......@@ -191,7 +230,8 @@ public class ShiroConfig {
// redisManager.setDatabase(10);
// return redisManager;
RedisManager redisManager = new RedisManager();
redisManager.setHost("43.142.42.187");
// redisManager.setHost("43.142.42.187");
redisManager.setHost("pay.icloud.com");
redisManager.setPassword("eDDxWJfwYsDhRELD");
redisManager.setPort(8979);
redisManager.setDatabase(10);
......@@ -222,8 +262,9 @@ public class ShiroConfig {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(getRedisManager());
//设置sessionid生成器
//设置sessionid生成器 //
redisSessionDAO.setSessionIdGenerator(new CustomSessionIdGenerator());
// redisSessionDAO.setSessionIdGenerator(JWTUtil.createToken(param.toJSONString()));
return redisSessionDAO;
}
......
package com.icloud.server.web.shiro.config;
import com.alibaba.fastjson.JSONObject;
import com.icloud.server.scala.shiro.User;
import com.icloud.server.utils.CodeDefs;
import com.icloud.server.web.Jwts.JWTToken;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.UserFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
// //解决跨域:https://blog.csdn.net/qq_32618611/article/details/105622681
public class StatelessAuthcFilter extends UserFilter {
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpRequest = WebUtils.toHttp(request);
HttpServletResponse httpResponse = WebUtils.toHttp(response);
if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
httpResponse.setHeader("Access-control-Allow-Origin", httpRequest.getHeader("Origin"));
httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod());
httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"));
httpResponse.setStatus(HttpStatus.OK.value());
return false;
}
return super.preHandle(request, response);
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletResponse httpResp = WebUtils.toHttp(response);
HttpServletRequest httpReq = WebUtils.toHttp(request);
/*系统重定向会默认把请求头清空,这里通过拦截器重新设置请求头,解决跨域问题*/
httpResp.addHeader("Access-Control-Allow-Origin", httpReq.getHeader("Origin"));
httpResp.addHeader("Access-Control-Allow-Headers", "*");
httpResp.addHeader("Access-Control-Allow-Methods", "*");
httpResp.addHeader("Access-Control-Allow-Credentials", "true");
this.saveRequestAndRedirectToLogin(request, response);
return false;
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws UnauthorizedException {
//判断请求的请求头是否带上 "Token"
if (isLoginAttempt(request, response)) {
try {
// System.out.println("aa");
// return true;
return executeLogin(request, response);
} catch (Exception e) {
//token 错误
return checkToken(request, response);
}
}else{
return checkToken(request, response);
}
//如果请求头不存在 Token,则可能是执行登陆操作或者是游客状态访问,无需检查 token,直接返回 true
}
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
String token = req.getHeader("token");
return token != null;
}
private boolean checkToken(ServletRequest request, ServletResponse response) {
// 没有携带Token
HttpServletRequest httpRequest = (HttpServletRequest)request;
String httpMethod = httpRequest.getMethod();
String requestURI = httpRequest.getRequestURI();
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
try {
out = httpServletResponse.getWriter();
JSONObject object = new JSONObject();
object.put("code", CodeDefs.ERROR_REQUEST);
object.put("message","您无权限");
out.print(object.toJSONString());
out.flush();;
} catch (IOException e) {
//logger.error("直接返回Response信息出现IOException异常", e);
}finally {
if(out!=null){
out.close();
}
}
return false;
}
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = httpServletRequest.getHeader("token");
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
Serializable id = session.getId();
System.out.println("id:"+id);
System.out.println("token:"+token);
if(id.toString().equals(token)){
System.out.println("验证权限通过");
}
JWTToken jwtToken = new JWTToken(token);
// 提交给realm进行登入,如果错误他会抛出异常并被捕获
try {
if(!(id.toString().equals(token))){
throw new AuthenticationException();
}
} catch (AuthenticationException e) {
System.out.println("验证权限不通过");
// e.printStackTrace();
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
try {
out = httpServletResponse.getWriter();
JSONObject object = new JSONObject();
object.put("code", CodeDefs.ERROR_REQUEST);
object.put("message","您无权限");
out.print(object.toJSONString());
out.flush();
} catch (IOException ex) {
//logger.error("直接返回Response信息出现IOException异常", e);
}finally {
if(out!=null){
out.close();
}
}
return false;
}
// 如果没有抛出异常则代表登入成功,返回true
return true;
}
}
\ No newline at end of file
package com.icloud.server.web.shiro.controller;
import com.icloud.server.web.JsonResult;
import io.swagger.annotations.Api;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
/**
* logout, 映射shiro自带的过滤器
*/
@CrossOrigin
@RestController
@Api( tags = {"登陆,注册"} , value = "API" )
@RequestMapping("pub")
public class LogoutController {
//
//
@RequestMapping("/logout")
public JsonResult findMyPlayRecord() {
Subject subject = SecurityUtils.getSubject();
if (subject.getPrincipals() != null) {
}
SecurityUtils.getSubject().logout();
return new JsonResult("logout成功");
}
}
......@@ -11,6 +11,7 @@ import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
......@@ -18,16 +19,31 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Api( tags = {"登陆,注册"} , value = "API" )
@Api( tags = {"登陆,注册,退出登陆"} , value = "API" )
@RestController
@RequestMapping("pub")
@RequestMapping("/occloud/pub")
@CrossOrigin
public class PublicController {
@Autowired
private UserService us;
@GetMapping("/logout")
public JsonResult findMyPlayRecord() {
Subject subject = SecurityUtils.getSubject();
if (subject.getPrincipals() != null) {
}
SecurityUtils.getSubject().logout();
return new JsonResult("logout成功");
}
@ApiIgnore
@PostMapping("need_login")
public JsonResult needLogin() {
JsonResult jr = new JsonResult("温馨提示:请使用对应的账号登录,-2");
......@@ -36,34 +52,26 @@ public class PublicController {
}
@ApiIgnore
@PostMapping("not_permit")
public JsonResult notPermit() {
return new JsonResult("温馨提示:拒绝访问,没权限,-3");
}
@ApiOperation( value = "index", notes = "",hidden = true )
@PostMapping("index")
public JsonResult index() {
List<String> videoList = new ArrayList<>();
return new JsonResult(videoList);
}
/**
* 登录接口
* 登录接口 账号:hw17321174033@qq.com
* 密码:qq1072869842
*
* @param userQuery
* @param request
* @param response
* @return
*/
@PostMapping("login")
@PostMapping("/login")
// @ApiOperation( value = "login", notes = "",hidden = true )
public JsonResult login(@RequestBody UserQuery userQuery, HttpServletRequest request, HttpServletResponse response) {
Subject subject = SecurityUtils.getSubject();
......@@ -91,6 +99,7 @@ public class PublicController {
}
@ApiIgnore
@PostMapping("login1")
public JsonResult login1(String name, String pwd, String token) {
......@@ -128,44 +137,44 @@ public class PublicController {
}
@PostMapping("register")
public JsonResult register(String name, String pwd, String token) {
if(token=="1"){
}
Subject subject = SecurityUtils.getSubject();
Map<String, Object> info = new HashMap<>();
try {
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(name, pwd);
subject.login(usernamePasswordToken);
info.put("msg", "登录成功");
info.put("session_id", subject.getSession().getId());
info.put("id", us.getid(name).getId());
boolean b = false;
String nick = "";
User user = us.getid(name);
nick = user.getUsername();
System.out.println("nick:"+nick);
info.put("nick", nick);
info.put("checked", b);
System.out.println("token:"+token);
return new JsonResult(info);
} catch (Exception e) {
e.printStackTrace();
e.printStackTrace();
JsonResult jr = new JsonResult("账号或者密码错误");
jr.setState(-2);
return jr;
}
}
// @PostMapping("register")
// public JsonResult register(String name, String pwd, String token) {
// if(token=="1"){
//
// }
// Subject subject = SecurityUtils.getSubject();
// Map<String, Object> info = new HashMap<>();
// try {
// UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(name, pwd);
// subject.login(usernamePasswordToken);
//
// info.put("msg", "登录成功");
// info.put("session_id", subject.getSession().getId());
//
// info.put("id", us.getid(name).getId());
// boolean b = false;
// String nick = "";
// User user = us.getid(name);
//
// nick = user.getUsername();
//
// System.out.println("nick:"+nick);
// info.put("nick", nick);
// info.put("checked", b);
// System.out.println("token:"+token);
//
// return new JsonResult(info);
//
// } catch (Exception e) {
// e.printStackTrace();
// e.printStackTrace();
// JsonResult jr = new JsonResult("账号或者密码错误");
// jr.setState(-2);
// return jr;
//
// }
//
//
// }
}
package com.icloud.server.web.shiro.handler;
/**
* @description: 保存用户会话
* @author: zjbing
* @create: 2021-01-13 14:31
**/
public class LoginInfoThreadLocal {
private static final ThreadLocal<UserToken> context = new ThreadLocal<>();
public static void setContext(UserToken userToken) {
context.set(userToken);
}
public static UserToken getContext() {
return context.get();
}
public static void clear() {
context.remove();
}
}
package com.icloud.server.web.shiro.handler;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.icloud.server.utils.R;
import com.icloud.server.utils.annotation.AccessRequired;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.beans.factory.annotation.Value;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @description: 请求拦截器
* @author: zjbing
* @create: 2021-01-13 14:03
**/
@Slf4j
@Configuration
public class TokenValidateInterceptor extends HandlerInterceptorAdapter {
@Autowired
StringRedisTemplate stringredistemplate;
@Value("${jwt.key}")
private String jwtKey;
// 无需拦截直接访问的地址
/*@NacosValue(value = "${allow.urls}", autoRefreshed = true)
private String[] allowUrls;*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 此处配置的是允许任意域名跨域请求,可根据需求指定
response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "86400");
response.setHeader("Access-Control-Allow-Headers", "*");
if(HttpMethod.OPTIONS.toString().equals(request.getMethod())) return true;
// 请求地址
String requestUri = request.getRequestURI();
System.out.println("request请求的URL为:" + requestUri);
log.debug("request请求的URL为:" + requestUri);
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 获取类上边的注解, 不需要鉴权的则放行
AccessRequired controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), AccessRequired.class);
if (ObjectUtil.isNotNull(controller)) return true;
// 获取方法上边的注解,不需要鉴权的则放行
AccessRequired method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), AccessRequired.class);
if (ObjectUtil.isNotNull(method)) return true;
// 判断请求地址是否无需拦击
/*for (String url : allowUrls) {
if (StrUtil.containsAnyIgnoreCase(requestUri, url.replaceAll("\\*",""))) {
return true;
}
}*/
String token = request.getHeader("Token");
System.out.println("token-------:"+token);
if (StrUtil.isNotBlank(token)) {
DecodedJWT decodedJWT = null;
Long userId = null;
String tokenId = null;
try {
decodedJWT = JWT.require(Algorithm.HMAC256(this.jwtKey)).build().verify(token);
userId = decodedJWT.getClaim("id").asLong();
tokenId = decodedJWT.getId();
} catch (JWTVerificationException e) {
log.warn("解析Token异常:{},token={}", e.getMessage(), token);
}
if (userId != null) {
String tokenKey = "token:" + userId + ":" + tokenId;
Object tokenObject = stringredistemplate.opsForValue().get(tokenKey);
if (tokenObject != null) {
UserToken userToken = JSON.parseObject((String) tokenObject, UserToken.class);
if (userToken != null && userToken.getId().equals(decodedJWT.getId()) && userId.equals(userToken.getUserId())) {
// 此时Token是合法的Token,需要进行续约操作
/*String userTokenStr = JSON.toJSONString(userToken);
redisService.setex(tokenKey, userTokenStr, userToken.isRemember()
? TimeUnit.DAYS.toSeconds(7)
: TimeUnit.MINUTES.toSeconds(30));*/
// 把当前会话信息保存到当前请求的threadlocal
LoginInfoThreadLocal.setContext(userToken);
return true;
}
} else {
//throw new RuntimeException("Token不存在/非法的Token/Token已过期");
response.setContentType(ContentType.JSON.toString());
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.getWriter().print(JSONUtil.toJsonStr(R.failed(401,"Invalid token")));
return false;
}
}
}
//throw new RuntimeException("Token不存在/非法的Token/Token已过期");
response.setContentType(ContentType.JSON.toString());
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.getWriter().print(JSONUtil.toJsonStr(R.failed(401,"Invalid token")));
return false;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//清掉当前线程缓存会话信息
LoginInfoThreadLocal.clear();
}
}
package com.icloud.server.web.shiro.handler;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @description:
* @author: zjbing
* @create: 2021-01-13 13:29
**/
@Data
public class UserToken implements Serializable {
private static final long serialVersionUID = 8798594496773855969L;
// token id
private String id;
// 用户id
private Long userId;
/**
* 用户名
*/
private String username;
/**
* 手机号
*/
private String phone;
/**
* 所属客户ID
*/
private Long clientId;
/**
* 员工所属部门
*/
private Integer department;
/**
* 禁用标识 0启用 1锁定
*/
//private Boolean lockFlag;
/**
* 注册类型 1手机号 2微信 3QQ
*/
private Short registrationType;
// ip
private String ip;
// 客户端
private String userAgent;
// 授权时间
private LocalDateTime issuedAt;
// 过期时间
private LocalDateTime expiresAt;
// 是否记住我
private boolean remember;
}
......@@ -72,6 +72,25 @@ public class TimeUtilss {
}
// public static Long datetotmestmp(Date d){
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//
// String format = sdf.format(d);// 格式化时间
// long time1=1L;
// try {
//
// time1 = format.getTime();
// System.out.println("time1:"+time1);
// } catch (ParseException e) {
// Date time = new Date(); // 获取当前时间
//// Date d1 = sdf.parse(d);
// throw new RuntimeException(e);
// }
//
// }
public static Date StringToDate(String time) throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = simpleDateFormat.parse(time);
......
......@@ -3,23 +3,25 @@ package com.icloud.server.wxserver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import springfox.documentation.annotations.ApiIgnore;
@ApiIgnore
@RestController
@RequestMapping("/weixin")
@Slf4j
public class WeixinController {
@GetMapping("/auth/{goodsid}")
public void auth(@RequestParam("code") String code,@PathVariable("goodsid") Integer goodsid){
String appid="wx3c42b420d22aacbf";
String appsecret="2f755b9edde90d8405285410475c82f1";
System.out.println("goodsid:"+goodsid);
log.info("进入了auth方法...");
log.info("code = {}",code);
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appid+"&secret="+appsecret+"&code=" + code + "&grant_type=authorization_code";
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
System.out.println(response);
}
// @GetMapping("/auth/{goodsid}")
// public void auth(@RequestParam("code") String code,@PathVariable("goodsid") Integer goodsid){
// String appid="wx3c42b420d22aacbf";
// String appsecret="2f755b9edde90d8405285410475c82f1";
// System.out.println("goodsid:"+goodsid);
// log.info("进入了auth方法...");
// log.info("code = {}",code);
// String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appid+"&secret="+appsecret+"&code=" + code + "&grant_type=authorization_code";
// RestTemplate restTemplate = new RestTemplate();
// String response = restTemplate.getForObject(url, String.class);
// System.out.println(response);
// }
}
......@@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
......@@ -20,7 +21,7 @@ import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.util.*;
/**获取微信参数授权
/**获取微信参数授权 ---占时用不到了
* @Author : yang
* @Date : 2022-04-30 12:06 AM
* @Version : 2.1.2
......@@ -29,6 +30,7 @@ import java.util.*;
@RestController
@RequestMapping("wxconfigutils")
@CrossOrigin
@ApiIgnore
public class WxConfigUtils {
@Autowired
......
......@@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
......@@ -19,7 +20,7 @@ import java.net.URLEncoder;
* @Date : 2022-04-30 12:56 AM
* @Version : 2.1.2
*/
@ApiIgnore
@RestController
@RequestMapping("wxLogin/")
@CrossOrigin
......
......@@ -7,6 +7,7 @@ import com.icloud.server.web.JsonResult;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
......@@ -30,7 +31,8 @@ public class WxOpenid {
* code 值是根据回调地址从微信获取的参数信息
* https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
**/
@RequestMapping("getopenid")
@ApiIgnore
@PostMapping ("getopenid")
public String getUsercode(String code,String goodsid, HttpServletRequest request){
// String realmname = request.getHeader("Referer");
// String r2=request.getHeader("realmname");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment