PayPal(V2)IPN问题


在这里插入图片描述

中文乱码

首先就是关于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();
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
PP_IPN_PDT_Guide_CHN.pdf PaypalIPN和PDT变量对照表(中文版) Instant Payment Notification (即时付款通知) & Payment Data Transfer (付款数据传输) 说明 目录 1 付款数据传输 PDT.....................................................................................................................3 1.1 什么是PDT........................................................................................................................3 1.2 如何启用PDT...................................................................................................................3 1.3 PDT 示例代码....................................................................................................................6 1.3.1 PDT for PHP 示例代码...........................................................................................6 1.3.2 PDT for ASP 示例代码............................................................................................7 2 即时付款通知 IPN ....................................................................................................................10 2.1 什么是即时付款通知 IPN .............................................................................................10 2.2 如何启用IPN? ..............................................................................................................11 2.3 通知确认 - 给PayPal 的HTTPS 回发.........................................................................12 2.4 处理IPN 的示例代码.....................................................................................................13 2.4.1 IPN for JAVA 示例代码........................................................................................13 2.4.2 IPN for Perl 示例代码..........................................................................................14 2.4.3 IPN for PHP 示例代码.........................................................................................16 2.4.4 IPN for ASP/VBScript 示例代码.........................................................................17 2.4.5 IPN for .NET/VB 示例代码.................................................................................18 2.4.6 IPN for .NET/C# 示例代码..................................................................................19 3 集成PayPal 建议........................................................................................................................21 4 附录5:IPN 和PDT 变量列表.................................................................................................21

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥肥肥柯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值