Возник такой вопрос: как можно организовать в PHP отправку нескольких запросов с интервалом в 1 секунду?
В ВК есть ограничение на выполнение метода secure.sendNotification, не более 100 уведомлений в секунду.
Эту проблему мне уже доводилось решать на джаве, там я писал класс таймер, который каждую секунду слал следующие 100 уведомлений.
package com.stavaco.vk.tools;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
/**
*
* @author Konstantin
*/
public class VK
{
public static int SEND_NOTIFICATION = 1;
public static int SET_USER_LEVEL = 2;
public static String API_URL = "http://api.vk.com/api.php";
public static String API_ID = "******";
public static String API_SECRET = "Iu1V*********emKm";
private static int lastIndex = 0; // при отправке сообщений ставится через каждые 100 id пользователей
private static String messageToSend = "";
private static ArrayList<String> allUids = null;
private static int totalRecepients = 0;
public static void sendNotification(ArrayList<String> uids, String message) { // должно посылать уведомление 100 пользователям каждую секунду
allUids = uids;
totalRecepients = allUids.size();
if (totalRecepients < 1) {
System.out.println("NO RECEPIENTS [VK.sendNotification()]");
onTimerStop();
return;
}
messageToSend = message;
if (allUids.size() > 100) {
VKNotificationTimer vnt = new VKNotificationTimer(1000, (int)(allUids.size() / 100) + 1);
vnt.start();
} else {
String totalUIDS = "";
for (int i = 0; i < totalRecepients; i++) {
totalUIDS += allUids.get(i) + ((i < totalRecepients - 1) ? "," : "");
}
HashMap<String, String> map = new HashMap<String, String>();
map.put("message", messageToSend);
map.put("uids", totalUIDS);
VK.callMethod(VK.SEND_NOTIFICATION, map);
}
}
public static void flushMessage() {
int indecesLeft = totalRecepients - lastIndex;
int increment = 100;
if (indecesLeft < increment) increment = indecesLeft;
String totalUIDS = "";
int stopIndex = lastIndex + increment;
for (int i = lastIndex; i < stopIndex; i++) {
totalUIDS += allUids.get(i) + ((i < stopIndex - 1) ? "," : "");
}
HashMap<String, String> map = new HashMap<String, String>();
map.put("message", messageToSend);
map.put("uids", totalUIDS);
VK.callMethod(VK.SEND_NOTIFICATION, map);
lastIndex += increment;
}
public static void onTimerStop() {
lastIndex = 0;
messageToSend = "";
allUids = null;
totalRecepients = 0;
}
public static void callMethod(int method, HashMap<String, String> dataParams) {
try {
String m = getMethod(method);
if (m.equals("")) return;
Date date = new Date();
long time = date.getTime();
String timestamp = String.valueOf(time).substring(0, 10);
int random = (int)(Math.random() * 100000000);
HashMap<String, String> params = new HashMap<String, String>();
params.put("api_id", API_ID);
params.put("format", "JSON");
params.put("method", m);
params.put("random", random + "");
params.put("timestamp", timestamp + "");
params.put("v", "2.0");
params.putAll(dataParams);
String sig = getSignature(params);
params.put("sig", sig);
String paramString = getParamsString(params);
//System.out.println("PARAM STRING " + paramString);
URL url = new URL(API_URL);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(connection.getOutputStream());
byte[] b = paramString.getBytes("UTF-8");
paramString = new String(b, "UTF-8");
outputStreamWriter.write(paramString);
outputStreamWriter.flush();
// чтение результата запроса
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response;
String responseStr = "";
while ((response = bufferedReader.readLine()) != null) {
responseStr = response;
}
// System.out.println("RESPONCE " + responseStr);
outputStreamWriter.close();
bufferedReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static String getParamsString(HashMap<String, String> params) {
String s = "";
Iterator iter = params.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry pairs = (Map.Entry)iter.next();
s += pairs.getKey() + "=" + pairs.getValue() + "&";
}
s = s.substring(0, s.length() - 1);
return s;
}
private static String getMethod(int method) {
if (method == VK.SEND_NOTIFICATION) {
return "secure.sendNotification";
} else if (method == VK.SET_USER_LEVEL) {
return "secure.setUserLevel";
}
return "";
}
private static String getSignature(HashMap<String, String> params) {
Iterator<String> iter = params.keySet().iterator();
String[] toSort = new String[params.keySet().size()];
int i = 0;
while (iter.hasNext()) {
String key = iter.next();
String value = (String)params.get(key);
toSort[i] = key + "=" + value; // сначала натромбовываем массив строками, затем сортируем по алфавиту
i++;
}
Arrays.sort(toSort, Collator.getInstance());
String strToHash = "";
for (i = 0; i < toSort.length; i++) {
strToHash += toSort[i];
}
String hash = MD5.encrypt(strToHash + VK.API_SECRET);
//System.out.println("HASH NOW: " + hash);
return hash;
}
public static int getAccountVotes(String login, String password, String apiURL) {
try {
Date date = new Date();
long time = date.getTime();
String timestamp = String.valueOf(time).substring(0, 10);
int random = (int)(Math.random() * 100000000);
String stringForSig = "api_id=" + API_ID
+ "format=JSON"
+ "method=secure.getBalance"
+ "random=" + random
+ "timestamp=" + timestamp
+ "uid=" + login
+ "v=2.0"
+ API_SECRET;
String sig = MD5.encrypt(stringForSig);
String request = "api_id=" + API_ID
+ "&format=JSON"
+ "&method=secure.getBalance"
+ "&random=" + random
+ "×tamp=" + timestamp
+ "&uid=" + login
+ "&v=2.0"
+ "&sig=" + sig;
if (!apiURL.equals("http://api.vkontakte.ru/api.php") && !apiURL.equals("http://api.vk.com/api.php")) {
return 0;
}
URL url = new URL(apiURL);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(connection.getOutputStream());
outputStreamWriter.write(request);
outputStreamWriter.flush();
// чтение результата запроса
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response;
String stringForJson = "";
while ((response = bufferedReader.readLine()) != null) {
stringForJson = response;
}
JSONObject json = (JSONObject) new JSONParser().parse(stringForJson); // парсинг ответа от сервера вконтакте
int money = safeLongToInt((Long)json.get("response"));
outputStreamWriter.close();
bufferedReader.close();
} catch (Exception ex) {
}
return 0;
}
public static int safeLongToInt(long ln) {
if (ln < Integer.MIN_VALUE || ln > Integer.MAX_VALUE) {
return (int)0;
}
return (int) ln;
}
}
Теперь встала задача портировать это на php, но так как с PHP дружу похуже, чем с джавой или as3, сразу уперся в такую проблему.
Как это можно по-лучше обойти?