3 Комити

Аутор SHA1 Порука Датум
  zhouliwu 118d077114 19 пре 1 недеља
  zhouliwu 6404ff021b 18 пре 2 недеља
  zhouliwu 82603d1d17 18 пре 2 недеља

+ 111
- 0
frame-module-admin/src/main/java/com/bohuikeji/frame/module/admin/sms/Base64Util.java Прегледај датотеку

@@ -0,0 +1,111 @@
1
+package com.bohuikeji.frame.module.admin.sms;
2
+
3
+import java.io.ByteArrayOutputStream;
4
+
5
+public class Base64Util {
6
+    private static char[] base64EncodeChars = new char[]{
7
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
8
+            'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
9
+            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
10
+            'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
11
+            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
12
+            'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
13
+            'w', 'x', 'y', 'z', '0', '1', '2', '3',
14
+            '4', '5', '6', '7', '8', '9', '+', '/'};
15
+    private static byte[] base64DecodeChars = new byte[]{
16
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
17
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
18
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
19
+            52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
20
+            -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
21
+            15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
22
+            -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
23
+            41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1};
24
+
25
+    private Base64Util() {
26
+    }
27
+
28
+    public static String encode(byte[] data) {
29
+        StringBuffer sb = new StringBuffer();
30
+        int len = data.length;
31
+        int i = 0;
32
+        int b1, b2, b3;
33
+        while (i < len) {
34
+            b1 = data[i++] & 0xff;
35
+            if (i == len) {
36
+                sb.append(base64EncodeChars[b1 >>> 2]);
37
+                sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
38
+                sb.append("==");
39
+                break;
40
+            }
41
+            b2 = data[i++] & 0xff;
42
+            if (i == len) {
43
+                sb.append(base64EncodeChars[b1 >>> 2]);
44
+                sb.append(
45
+                        base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
46
+                sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
47
+                sb.append("=");
48
+                break;
49
+            }
50
+            b3 = data[i++] & 0xff;
51
+            sb.append(base64EncodeChars[b1 >>> 2]);
52
+            sb.append(
53
+                    base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
54
+            sb.append(
55
+                    base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);
56
+            sb.append(base64EncodeChars[b3 & 0x3f]);
57
+        }
58
+        return sb.toString();
59
+    }
60
+
61
+
62
+    public static byte[] decode(String str) {
63
+        byte[] data = str.getBytes();
64
+        int len = data.length;
65
+        ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
66
+        int i = 0;
67
+        int b1, b2, b3, b4;
68
+        while (i < len) {
69
+            /* b1 */
70
+            do {
71
+                b1 = base64DecodeChars[data[i++]];
72
+            } while (i < len && b1 == -1);
73
+            if (b1 == -1) {
74
+                break;
75
+            }
76
+            /* b2 */
77
+            do {
78
+                b2 = base64DecodeChars[data[i++]];
79
+            } while (i < len && b2 == -1);
80
+            if (b2 == -1) {
81
+                break;
82
+            }
83
+            buf.write(((b1 << 2) | ((b2 & 0x30) >>> 4)));
84
+            /* b3 */
85
+            do {
86
+                b3 = data[i++];
87
+                if (b3 == 61) {
88
+                    return buf.toByteArray();
89
+                }
90
+                b3 = base64DecodeChars[b3];
91
+            } while (i < len && b3 == -1);
92
+            if (b3 == -1) {
93
+                break;
94
+            }
95
+            buf.write((((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));
96
+            /* b4 */
97
+            do {
98
+                b4 = data[i++];
99
+                if (b4 == 61) {
100
+                    return buf.toByteArray();
101
+                }
102
+                b4 = base64DecodeChars[b4];
103
+            } while (i < len && b4 == -1);
104
+            if (b4 == -1) {
105
+                break;
106
+            }
107
+            buf.write((((b3 & 0x03) << 6) | b4));
108
+        }
109
+        return buf.toByteArray();
110
+    }
111
+}

+ 110
- 0
frame-module-admin/src/main/java/com/bohuikeji/frame/module/admin/sms/CryptUtil.java Прегледај датотеку

@@ -0,0 +1,110 @@
1
+package com.bohuikeji.frame.module.admin.sms;
2
+
3
+import javax.crypto.Cipher;
4
+import javax.crypto.SecretKey;
5
+import javax.crypto.spec.IvParameterSpec;
6
+import javax.crypto.spec.SecretKeySpec;
7
+import java.security.MessageDigest;
8
+
9
+public class CryptUtil {
10
+    private static final String desAlgorithm = "DESede/CBC/NoPadding";
11
+    private static final String desKeyAlgorithm = "DESede";
12
+    private static final char[] DIGITS = {
13
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
14
+            'a', 'b', 'c', 'd', 'e', 'f'};
15
+    private static final byte[] defaultIV = new byte[]{'0', '0', '0', '0', '0', '0', '0', '0'};
16
+
17
+    public CryptUtil() {
18
+    }
19
+
20
+    private static SecretKey KeyGenerator(String keyStr) throws Exception {
21
+        byte[] input = md5Hex(keyStr).substring(0, 24).getBytes("GBK");
22
+        SecretKey triDesKey = new SecretKeySpec(input, desKeyAlgorithm);
23
+        return triDesKey;
24
+    }
25
+
26
+    public static String encryptBy3DesAndBase64(String content, String keyStr) throws Exception {
27
+        return encryptBy3DesAndBase64(content, keyStr, "UTF-8");
28
+    }
29
+
30
+    public static String decryptBy3DesAndBase64(String content, String keyStr) throws Exception {
31
+        return decryptBy3DesAndBase64(content, keyStr, "UTF-8");
32
+    }
33
+
34
+    public static String encryptBy3DesAndBase64(String content, String keyStr, String encoding) throws
35
+            Exception {
36
+        byte[] output = null;
37
+        byte[] input = null;
38
+        int residue = (content.getBytes(encoding).length) % 8;
39
+        if (0 != residue) {
40
+            int padLen = 8 - residue;
41
+            StringBuffer strBuf = new StringBuffer(content);
42
+            for (int i = 0; i < padLen; i++) {
43
+                strBuf.append(' ');
44
+            }
45
+            input = (new String(strBuf)).getBytes(encoding);
46
+        } else {
47
+            input = content.getBytes(encoding);
48
+        }
49
+        output = encryptBy3Des(input, keyStr);
50
+        return Base64Util.encode(output).replaceAll("[\\n\\r]", "");
51
+    }
52
+
53
+    public static String decryptBy3DesAndBase64(String content, String keyStr, String encoding) throws
54
+            Exception {
55
+        byte[] output = null;
56
+        byte[] input = null;
57
+        input = Base64Util.decode(content);
58
+        output = decryptBy3Des(input, keyStr);
59
+        String retStr = new String(output, encoding);
60
+        return (retStr.trim());
61
+    }
62
+
63
+    public static byte[] encryptBy3Des(byte[] content, String keyStr) throws Exception {
64
+        return cryptBy3Des(keyStr, 1, null, content);
65
+    }
66
+
67
+    public static byte[] decryptBy3Des(byte[] content, String keyStr) throws Exception {
68
+        return cryptBy3Des(keyStr, 2, null, content);
69
+    }
70
+
71
+    public static byte[] cryptBy3Des(String keyStr, int cryptModel, byte[] iv, byte[] content) throws Exception {
72
+        Cipher cipher = null;
73
+        SecretKey key = KeyGenerator(keyStr);
74
+        IvParameterSpec IVSpec = iv == null ? IvGenerator(defaultIV) : IvGenerator(iv);
75
+        cipher = Cipher.getInstance(desAlgorithm);
76
+        cipher.init(cryptModel, key, IVSpec);
77
+        return cipher.doFinal(content);
78
+    }
79
+
80
+    public static String md5Hex(String content) throws Exception {
81
+        MessageDigest md5 = null;
82
+        md5 = MessageDigest.getInstance("MD5");
83
+        md5.update(content.getBytes("GBK"));
84
+        return new String(encodeHex(md5.digest()));
85
+    }
86
+
87
+    public static String md5Hex(String content, String charsetName) throws Exception {
88
+        MessageDigest md5 = null;
89
+        md5 = MessageDigest.getInstance("MD5");
90
+        md5.update(content.getBytes(charsetName));
91
+        return new String(encodeHex(md5.digest()));
92
+    }
93
+
94
+    public static char[] encodeHex(byte[] data) {
95
+        int len = data.length;
96
+        char[] out = new char[len << 1];
97
+        int i = 0;
98
+        int j = 0;
99
+        for (; i < len; i++) {
100
+            out[j++] = DIGITS[(0xf0 & data[i]) >>> 4];
101
+            out[j++] = DIGITS[0xf & data[i]];
102
+        }
103
+        return out;
104
+    }
105
+
106
+    private static IvParameterSpec IvGenerator(byte[] b) {
107
+        IvParameterSpec IV = new IvParameterSpec(b);
108
+        return IV;
109
+    }
110
+}

+ 157
- 0
frame-module-admin/src/main/java/com/bohuikeji/frame/module/admin/sms/HttpUtil.java Прегледај датотеку

@@ -0,0 +1,157 @@
1
+package com.bohuikeji.frame.module.admin.sms;
2
+
3
+import com.alibaba.fastjson.JSON;
4
+
5
+import java.io.BufferedReader;
6
+import java.io.IOException;
7
+import java.io.InputStreamReader;
8
+import java.io.PrintWriter;
9
+import java.net.URL;
10
+import java.net.URLConnection;
11
+import java.nio.charset.StandardCharsets;
12
+import java.util.HashMap;
13
+import java.util.Map;
14
+import java.util.Map.Entry;
15
+
16
+/**
17
+ * @author: Chenzhenyong
18
+ * @description: 简单发送请求工具类
19
+ * @date: Created in 12:21 2018/7/24
20
+ */
21
+public class HttpUtil {
22
+
23
+    // 设置连接超时时间,单位毫秒。
24
+    private static final int CONNECT_TIMEOUT = 20000;
25
+    // 请求获取数据的超时时间(即响应时间),单位毫秒。
26
+    private static final int SOCKET_TIMEOUT = 20000;
27
+    // 记录http调用开始时间
28
+    public static ThreadLocal<Long> httpStartTime = new ThreadLocal() {
29
+        @Override
30
+        protected Long initialValue() {
31
+            return 0L;
32
+        }
33
+    };
34
+
35
+    /**
36
+     * post 请求
37
+     * @param url
38
+     * @param body
39
+     * @return
40
+     */
41
+    public static String doHttpPost(String url, Map<String, String> body) throws IOException {
42
+        return doHttpPost(url, null, body);
43
+    }
44
+
45
+    /**
46
+     * get 请求
47
+     * @param url
48
+     * @param req
49
+     * @return
50
+     * @throws Exception
51
+     */
52
+    public static String doHttpGet(String url, Map<String, String> req,boolean urlEncode) throws Exception{
53
+        StringBuffer sb = new StringBuffer().append("?");
54
+        for(Entry<String, String> entry : req.entrySet()){
55
+            sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
56
+        }
57
+        return doHttpPost(url+sb.toString(),null,"");
58
+    }
59
+
60
+    /**
61
+     * HTTP POST
62
+     *
63
+     * @param url    请求地址
64
+     * @param header 请求头
65
+     * @param req    请求参数
66
+     * @return 应答参数
67
+     */
68
+    public static String doHttpPost(String url, Map<String, String> header, String req) throws IOException {
69
+        httpStartTime.set(System.currentTimeMillis());
70
+        PrintWriter outPrintWriter = null;
71
+        BufferedReader inBufferedReader = null;
72
+        try {
73
+            URLConnection urlConnection = new URL(url).openConnection(); // 打开和URL之间的连接
74
+            // 设置通用的请求属性
75
+            urlConnection.setRequestProperty("accept", "*/*");
76
+            urlConnection.setRequestProperty("connection", "Keep-Alive");
77
+            urlConnection.setRequestProperty("user-agent",
78
+                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
79
+            if (header != null) {
80
+                for (Entry<String, String> entry : header.entrySet()) {
81
+                    urlConnection.setRequestProperty(entry.getKey(), entry.getValue());
82
+                }
83
+            }
84
+
85
+            urlConnection.setDoOutput(true);
86
+            urlConnection.setDoInput(true);
87
+            urlConnection.setConnectTimeout(CONNECT_TIMEOUT);
88
+            urlConnection.setReadTimeout(SOCKET_TIMEOUT);
89
+            urlConnection.connect();
90
+
91
+            outPrintWriter = new PrintWriter(urlConnection.getOutputStream());
92
+            outPrintWriter.print(req);
93
+            outPrintWriter.flush();
94
+            inBufferedReader = new BufferedReader(new InputStreamReader(
95
+                    urlConnection.getInputStream(), StandardCharsets.UTF_8));
96
+            String line = "";
97
+            String response = "";
98
+            while ((line = inBufferedReader.readLine()) != null) {
99
+                response += line;
100
+            }
101
+            return response;
102
+
103
+        } finally {
104
+            try {
105
+                if (outPrintWriter != null) {
106
+                    outPrintWriter.close();
107
+                }
108
+                if (inBufferedReader != null) {
109
+                    inBufferedReader.close();
110
+                }
111
+            } catch (IOException e) {
112
+                e.printStackTrace();
113
+            }
114
+        }
115
+    }
116
+
117
+    /**
118
+     * HTTP POST
119
+     *
120
+     * @param url    请求地址
121
+     * @param header 请求头
122
+     * @param object 请求参数
123
+     * @return 应答参数
124
+     */
125
+    public static String doHttpPostJson(String url, Map<String, String> header, Object object) throws IOException {
126
+        if (header == null) {
127
+            header = new HashMap<String, String>();
128
+        }
129
+        header.put("Content-Type", "application/json;charset=UTF-8");
130
+        String req = "";
131
+        if (object != null) {
132
+            req = JSON.toJSONString(object);
133
+        }
134
+        return doHttpPost(url, header, req);
135
+    }
136
+
137
+    /**
138
+     * HTTP POST
139
+     *
140
+     * @param url    请求地址
141
+     * @param header 请求头
142
+     * @param body   请求参数
143
+     * @return 应答参数
144
+     */
145
+    public static String doHttpPost(String url, Map<String, String> header, Map<String, String> body) throws IOException {
146
+        String req = "";
147
+        if (body != null) {
148
+            StringBuilder sb = new StringBuilder();
149
+            for (Entry<String, String> entry : body.entrySet()) {
150
+                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
151
+            }
152
+            req = sb.toString();
153
+        }
154
+        return doHttpPost(url, header, req);
155
+    }
156
+
157
+}

+ 58
- 18
frame-module-admin/src/main/java/com/bohuikeji/frame/module/admin/utils/YiXunGmsUtils.java Прегледај датотеку

@@ -1,19 +1,26 @@
1 1
 package com.bohuikeji.frame.module.admin.utils;
2 2
 
3 3
 import com.alibaba.fastjson.JSON;
4
+import com.alibaba.fastjson.JSONArray;
4 5
 import com.alibaba.fastjson.JSONObject;
5 6
 import com.bohuikeji.frame.module.admin.component.RedisUtil;
7
+import com.bohuikeji.frame.module.admin.sms.CryptUtil;
8
+import com.bohuikeji.frame.module.admin.sms.HttpUtil;
6 9
 import jodd.http.HttpRequest;
7 10
 import lombok.extern.slf4j.Slf4j;
8 11
 import org.junit.Test;
9 12
 import org.springframework.util.DigestUtils;
10 13
 
14
+import java.io.IOException;
11 15
 import java.nio.charset.StandardCharsets;
16
+import java.text.SimpleDateFormat;
12 17
 import java.time.Duration;
13 18
 import java.time.LocalDateTime;
14 19
 import java.time.format.DateTimeFormatter;
20
+import java.util.Date;
15 21
 import java.util.HashMap;
16 22
 import java.util.Map;
23
+import java.util.UUID;
17 24
 
18 25
 /**
19 26
  * 51易迅短信平台工具类
@@ -30,27 +37,31 @@ import java.util.Map;
30 37
 @Slf4j
31 38
 public class YiXunGmsUtils {
32 39
 
40
+    //private static final String SENDBATCH_URL = "https://nsms.51yixun.com/sms/sendBatch";
41
+    private static final String SEND_URL = "https://nsms.51yixun.com/sms/send";
42
+    private static final String REPORT_URL = "https://nsms.51yixun.com/sms/report";
43
+    private static final String MO_URL = "https://nsms.51yixun.com/sms/mo";
33 44
 
34 45
 
35
-    public static String SEND_URL="http://sms.51yixun.com:8200/sms/send";
46
+    /*public static String SEND_URL="http://sms.51yixun.com:8200/sms/send";
36 47
 
37 48
     public static String REPORT_URL="http://sms.51yixun.com:8200/sms/report";
38 49
 
39 50
     public static String PRICE_URL="http://sms.51yixun.com:8200/sms/balance";
40 51
 
41
-    public static String MO_URL="http://sms.51yixun.com:8200/sms/mo";
52
+    public static String MO_URL="http://sms.51yixun.com:8200/sms/mo";*/
42 53
 
43 54
     /**
44 55
      * 短信验证码
45 56
      */
46
-    public static String APPID="LHW-SMS-03ZEV";
47
-    public static String secretKey="8E9FC62D170554C3";
57
+    public static String APPID="991727676356580131";
58
+    public static String secretKey="56f2d1de4b2b40588536673802331115";
48 59
 
49 60
     /**
50 61
      * 普通物流短信
51 62
      */
52
-    public static String APPID_2="LHW-SMS-0T6PH";
53
-    public static String secretKey_2="AD7FFB4C865654C4";
63
+    public static String APPID_2="991727676385745955";
64
+    public static String secretKey_2="a7e6e8b33e2b4a0da073325059548121";
54 65
 
55 66
     public static String MSG_SIGN="【同城急送】";
56 67
 
@@ -154,10 +165,16 @@ public class YiXunGmsUtils {
154 165
             Object v = entry.getValue();
155 166
             content = content.replace("${" + k + "}", v.toString());
156 167
         }
157
-        Map<String,String> reqParams=getPublicParams("SMS_184115918".equals(templateCode));
168
+        Map<String,String> reqParams=getPublicParamsn("SMS_184115918".equals(templateCode));
158 169
         reqParams.put(phone, content);
159
-        String resStr=HttpRequest.get(SEND_URL).query(reqParams).send().bodyText();
170
+        String resStr= null;
171
+        try {
172
+            resStr = HttpUtil.doHttpPost(SEND_URL, reqParams);
173
+        } catch (IOException e) {
174
+            e.printStackTrace();
175
+        }
160 176
         JSONObject res=JSON.parseObject(resStr);
177
+        log.error("【短信发送失败】1号码:{},发送内容:{},返回信息:{}",phone,content,res);
161 178
         if("SUCCESS".equals(res.getString("code"))){
162 179
             if (isCache){
163 180
                 //放入缓存
@@ -165,25 +182,24 @@ public class YiXunGmsUtils {
165 182
             }
166 183
             return true;
167 184
         }
168
-        log.error("【短信发送失败】号码:{},发送内容:{},返回信息:{}",phone,content,resStr);
185
+        log.error("【短信发送失败】2号码:{},发送内容:{},返回信息:{}",phone,content,resStr);
169 186
         return false;
170 187
     }
171
-
172
-    public static JSONObject getReport(){
188
+   /* public static JSONObject getReport(){
173 189
         String resStr=HttpRequest.get(REPORT_URL).query(getPublicParams(false)).send().bodyText();
174 190
         log.info("状态查询接口接口返回:{}",resStr);
175 191
         return null;
176
-    }
177
-    public static JSONObject getPrice(){
192
+    }*/
193
+    /*public static JSONObject getPrice(){
178 194
         String resStr=HttpRequest.get(PRICE_URL).query(getPublicParams(false)).send().bodyText();
179 195
         log.info("余额接口接口返回:{}",resStr);
180 196
         return null;
181
-    }
182
-    public static JSONObject geMo(){
197
+    }*/
198
+    /*public static JSONObject geMo(){
183 199
         String resStr=HttpRequest.get(MO_URL).query(getPublicParams(false)).send().bodyText();
184 200
         log.info("查询上行信息接口接口返回:{}",resStr);
185 201
         return null;
186
-    }
202
+    }*/
187 203
 
188 204
     @Test
189 205
     public void test(){
@@ -193,7 +209,7 @@ public class YiXunGmsUtils {
193 209
         params.put("mag","内蒙古自治区呼和浩特市玉泉区昭乌达路三里应B区东门。");
194 210
         params.put("rep","内蒙古自治区呼和浩特市玉泉区昭乌达路三里应B区东门。");
195 211
 
196
-        sendMsg("15771335697","SMS_TEMP_ADDRESS_EDIT",params);
212
+        sendMsg("15540709945","SMS_TEMP_ADDRESS_EDIT",params);
197 213
         //getReport();
198 214
     }
199 215
 
@@ -219,7 +235,7 @@ public class YiXunGmsUtils {
219 235
      * @param isCode 是否为验证码短信
220 236
      * @return
221 237
      */
222
-    public static Map<String,String> getPublicParams(boolean isCode){
238
+    /*public static Map<String,String> getPublicParams(boolean isCode){
223 239
         Map<String,String> reqParams=new HashMap<>();
224 240
         String timestamp=getTimestamp();
225 241
         reqParams.put("appId",isCode?APPID:APPID_2);
@@ -227,6 +243,30 @@ public class YiXunGmsUtils {
227 243
         reqParams.put("sign",sign(timestamp,isCode?APPID:APPID_2,isCode?secretKey:secretKey_2));
228 244
         reqParams.put("batchId","10");
229 245
         return reqParams;
246
+    }*/
247
+
248
+    public static Map<String,String> getPublicParamsn(boolean isCode){
249
+        Map<String, String> params = new HashMap();
250
+        String timestamp=getTimestamp();
251
+        params.put("appId",isCode?APPID:APPID_2);
252
+        params.put("timestamp",timestamp);
253
+        params.put("type", "msms");
254
+        try {
255
+            if(isCode){
256
+                params.put("sign",CryptUtil.md5Hex(APPID+secretKey+timestamp));
257
+                log.error("【短信发送1】1发送内容:{}",params);
258
+            }else {
259
+                params.put("sign",CryptUtil.md5Hex(APPID_2+secretKey_2+timestamp));
260
+                log.error("【短信发送2】2发送内容:{}",params);
261
+            }
262
+
263
+        } catch (Exception e) {
264
+            e.printStackTrace();
265
+        }
266
+        params.put("schTime","");
267
+        params.put("batchId",UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10));
268
+        params.put("addserial",NumberUtils.getShort());
269
+        return params;
230 270
     }
231 271
 
232 272
 }

Loading…
Откажи
Сачувај