中文乱码
首先就是关于IPN中文乱码的问题,比如你的商品名称如果是中文的,就会出现中文乱码
解决方法:登录你对应环境的对应卖家账号(ipn的是卖家),修改encoding
选择简体中文后点击“更多选项”
选择如图选项点击“保存”即可
再次测试一下IPN
参数验签
参数检验这个工作并不是必要的,根据个人需求而定。为了防止别人拦截IPN(本人的回调是http,相对https不安全),篡改参数,然后导致你拿到这些参数到本地入库或者做逻辑处理的时候造成损失,所以本人选择验签。
Paypal验签并不需要我们拿到verify_sign做解密处理,直接发http请求到paypal的https://ipnpb.sandbox.paypal.com/cgi-bin/webscr即可,不过需要保证以下三点:
1、必须以表单的形式使用POST请求
2、必须携带特定参数cmd=_notify-validate
3、必须将paypal ipn过来的ParameterMap里面的所有参数原封不动地请求到该url
由于我们国内某些商品或者其他地方使用了中文,所以要保证编码正确,否则你请求回去的参数是不会通过校验的。
代码如下:
FormBody.Builder body = new FormBody.Builder();
body.add("cmd","_notify-validate");
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<String, String> next = iterator.next();
body.add(next.getKey(),next.getValue());
}
String result = HttpUtils.netForm("https://ipnpb.sandbox.paypal.com/cgi-bin/webscr", body.build());
if ("VERIFIED".equals(result)){
//验签成功
} else if ("INVALID".equals(result)){
//验签失败
}
提供一个Http工具类
import okhttp3.*;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Configuration
public class HttpUtils {
private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
// 网关地址
private static String GATEWAY_ADDR;
public static void setGATEWAY_ADDR(String gATEWAY_ADDR) {
GATEWAY_ADDR = gATEWAY_ADDR;
}
@Value("${gateway.addr}")
public void setGatewayAddr(String gatewayAddr) {
setGATEWAY_ADDR(gatewayAddr);
}
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
public static final MediaType wwwForm = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");
private static final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(120, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.build();
public static String sendInstructions(String imei,String insContent,String timeOut,String custom,String type) {
// request body
Map<String, Object> foo = new HashMap<>();
foo.put("imei", imei);
foo.put("content", insContent);
foo.put("timeout", timeOut);//超时时间
foo.put("custom", custom);//自定义唯一ID
foo.put("type", type);//指令类型 sync-同步 anysc-异步
logger.info("发送指令中:"+JSONObject.toJSONString(foo));
try {
String url = GATEWAY_ADDR+"?"+urlencode(foo);
String resp = post(url,JSONObject.toJSONString(foo));
return resp;
} catch (Exception e) {
logger.error("指令发送失败:"+JSONObject.toJSONString(foo),e);
}
return null;
}
/**
*
* @param url 请求地址
* @param params 请求参数
* @param method 请求方法
* @return 网络请求字符串
* @throws Exception
*/
public static String net(String url, Map<String, Object> params, String method) {
String resp = null;
try {
if (method == null || method.equals("GET")) {
resp = get(url, params);
} else {
resp = post(url, JSONObject.toJSONString(params));
}
} catch (IOException e) {
logger.error("url请求异常:",e);
}
return resp;
}
/**
* 提交方式,表单
* @param url 请求地址
* @param formBody 请求表单
* @return 网络请求字符串
* @throws Exception
*/
public static String netForm(String url, FormBody formBody) {
String resp = null;
try {
resp = postForm(url, formBody);
} catch (IOException e) {
}
return resp;
}
public static String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder().url(url).post(body).build();
Response response = client.newCall(request).execute();
return response.body().string();
}
public static String postForm(String url, FormBody formBody) throws IOException {
OkHttpClient client = new OkHttpClient.Builder().connectTimeout(120, TimeUnit.SECONDS)
.readTimeout(120, TimeUnit.SECONDS).writeTimeout(120, TimeUnit.SECONDS).build();
Request request = new Request.Builder().url(url).post(formBody).build();
Response response = client.newCall(request).execute();
return response.body().string();
}
public static String get(String url, Map<String, Object> params) throws IOException {
if (!params.isEmpty()) {
url = url + "?" + urlencode(params);
}
Request.Builder builder = new Request.Builder();
Request request = builder.get().url(url).build();
try {
Response response = client.newCall(request).execute();
if (response.code() == 200) {
logger.info("http GET 请求成功; [url={}]", url);
return response.body().string();
} else {
logger.warn("Http GET 请求失败; [errorCode = {} , url={}]", response.code(), url);
}
} catch (IOException e) {
throw new RuntimeException("同步http GET 请求失败,url:" + url, e);
}
return null;
}
// 将map型转为请求参数型
public static String urlencode(Map<String, Object> data) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, Object> i : data.entrySet()) {
try {
sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", "UTF-8")).append("&");
} catch (UnsupportedEncodingException e) {
logger.error("map型转为请求参数型异常:",e);
}
}
return sb.toString();
}
public static String getByStringMap(String url, Map<String,String> params) throws IOException {
if(!params.isEmpty()) {
url = url +"?"+urlencodeString(params);
}
Request.Builder builder = new Request.Builder();
Request request = builder.get().url(url).build();
try {
Response response = client.newCall(request).execute();
if (response.code() == 200) {
logger.info("http GET 请求成功; [url={}]", url);
return response.body().string();
} else {
logger.warn("Http GET 请求失败; [errorCode = {} , url={}]", response.code(), url);
}
} catch (IOException e) {
logger.error("同步http GET 请求失败,url:" + url,e);
}
return null;
}
//将map型转为请求参数型
public static String urlencodeString(Map<String,String> data) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String,String> i : data.entrySet()) {
try {
sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue()+"","UTF-8")).append("&");
} catch (UnsupportedEncodingException e) {
logger.error("请求异常", e);
}
}
return sb.toString();
}
/**
* 通过发送http get 请求获取文件资源
*
* @param url
* @param filepath
* @return
*/
public static void download(String url, String filepath)throws IOException {
OkHttpClient client = new OkHttpClient();
Request req = new Request.Builder().url(url).build();
Response resp = null;
FileOutputStream fops= null;
File imgFile = null;
try {
resp = client.newCall(req).execute();
if (resp.isSuccessful()) {
ResponseBody body = resp.body();
InputStream is = body.byteStream();
byte[] data = readInputStream(is);
imgFile = new File(URLDecoder.decode(filepath, "utf-8"));
fops = new FileOutputStream(imgFile);
fops.write(data);
}
} catch (IOException e) {
e.printStackTrace();
logger.error("Unexpected code: ",resp);
}finally {
if (fops != null) {
fops.close();
}
}
}
/**
* 读取字节输入流内容
*
* @param is
* @return
*/
private static byte[] readInputStream(InputStream is) {
ByteArrayOutputStream writer = new ByteArrayOutputStream();
byte[] buff = new byte[1024 * 2];
int len = 0;
try {
while ((len = is.read(buff)) != -1) {
writer.write(buff, 0, len);
}
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return writer.toByteArray();
}
}