客户有一网站,需要实paypal支付功能:
paypal支付有很多中实现方式,可以参考其官方文档,我用的是最简单的方式,提交form表单,发送post请求
paypal支付实现步骤:
1 登陆https://developer.paypal.com,注册paypal账号,然后点击Application ,Sendbox accounts ,添加卖家,买家账号,卖家账号类型必须business的,
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<!-- 按钮的类型// -->
<input type="hidden" name="business" value="[email protected]">
<!-- 收款人账户// -->
<input type="hidden" name="item_name" value="bbs">
<!-- 购买商品的名称// -->
<input type="hidden" name="amount" value="1000">
<!-- 购买商品的价格// -->
<input type="hidden" name="currency_code" value="USD">
<!-- 交易币种,目前paypal好像不支持RMB// -->
<input type="hidden" name="lc" value="US">
<!-- 用于设置目标客户国家所在地// -->
<input type="hidden" name="item_number" value="5">
<!-- 自定义的参数1 -->
<input type="hidden" name="rm" value="2">
<input type="hidden" name="notify_url" value="http://www.whofic2013.org/html/paypalNotify.jsp">
<!-- IPN 及时付款通知url(paypal异步完成),paypal付款完成后调用-->
<input type="hidden" name="return" value="http://www.whofic2013.org/register/toTestSuccess.do">
<!-- paypal付款完成后,paypal页面跳转的时候调用 -->
<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but23.gif"
border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
</form>
向paypal发送付款请求,在发送请求前必须先在沙盒环境登陆paypal,不然的话paypal不认识虚拟买家账号。说明:这是在paypal给我们提供的沙盒环境中测试的,只走业务逻辑,不执行实际付款操作。
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<!-- 按钮的类型// -->
<input type="hidden" name="business" value="[email protected]">
<!-- 收款人账户// -->
<input type="hidden" name="item_name" value="<s:property value='#session.accommodationName'/>">
<!-- 购买商品的名称// -->
<input type="hidden" name="amount" value="<s:property value='#session.tatolPrice'/>">
<!-- 购买商品的价格// -->
<input type="hidden" name="currency_code" value="USD">
<!-- 交易币种// -->
<input type="hidden" name="lc" value="US">
<!-- 用于设置目标客户国家所在地// -->
<input type="hidden" name="item_number" value="<s:property value='res.registerId'/>">
<!-- 自定义的参数1 -->
<input type="hidden" name="rm" value="2">
<input type="hidden" name="return" value="xxxxxxxxxxxxxxxxxx/success.do">
<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but23.gif"
border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
<!--这里告诉paypal付款的通信url,即当客户付款后调用这个url通知系统-->
<input type="hidden" name="notify_url" value="xxxxxxxxxxxxxxxxxxxxxxxxxx/html/paypalNotify.jsp">
</form>
这是正式环境提交的表单,和沙盒环境基本相同,无需做过多的解释。
这是paypalNotify页面:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ page import="test.action.NotifyUrlMgr" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%
NotifyUrlMgr mgr = new NotifyUrlMgr();
String ret = mgr.insert(request);
if(ret == null){
out.print("200 OK");
} else {
out.print("fail");
}
%>
处理付款通知后台类方法
NotifyUrlMgr.java
public String insert(HttpServletRequest request) {
System.out.println("paypal支付完成系统确认开始");
try{
// 从 PayPal 出读取 POST 信息同时添加变量„cmd‟
Enumeration en = request.getParameterNames();
String str = "cmd=_notify-validate";
while (en.hasMoreElements()) {
String paramName = (String) en.nextElement();
String paramValue = request.getParameter(paramName);
str = str + "&" + paramName + "=" + URLEncoder.encode(paramValue, "utf-8");
}
System.out.println("paypal支付请求参数:" + str);
// 将信息 POST 回给 PayPal 进行验证
// 设置 HTTP 的头信息
// 在 Sandbox 情况下,设置:
// URL u= new URL(“http://www.sandbox.paypal.com/cgi-bin/webscr”);
URL u = new URL("https://www.paypal.com/cgi-bin/webscr");
URLConnection uc = u.openConnection();
uc.setDoOutput(true);
uc.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
PrintWriter pw = new PrintWriter(uc.getOutputStream());
pw.println(str);
pw.close();
// 接受 PayPal 对 IPN 回发的回复信息
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String res = in.readLine();
in.close();
// 将 POST 信息分配给本地变量,可以根据您的需要添加
// 该付款明细所有变量可参考:
// https://www.paypal.com/IntegrationCenter/ic_ipn-pdt-variable-reference.html
String itemNumber = request.getParameter("item_number");
String paymentStatus = request.getParameter("payment_status");
//付款金额
String paymentAmount = request.getParameter("mc_gross");
//付款邮箱
String payerEmail = request.getParameter("payer_email");
//付款日期
String paymentDate = getCurrentDate();
System.out.println("paypalIPN最终握手确认结果:" + res);
// 获取 PayPal 对回发信息的回复信息,判断刚才的通知是否为 PayPal 发出的
if ("VERIFIED".equals(res)) {
// 处理其他数据,包括写数据库
IRegisterService registerService = (IRegisterService)getBeanInstance("registerService");
if("Completed".equals(paymentStatus)){
//根据项目实际需要处理其业务逻辑
} else {
System.out.println("paypal完成支付发送IPN通知返回结果合法,支付状态非法,请联系管理员,请求参数:" + str);
return "confirmError";
}
} else if (res.equals("INVALID")) {
System.out.println("paypal完成支付发送IPN通知返回状态非法,请联系管理员,请求参数:" + str);
return "confirmError";
} else {
System.out.println("paypal完成支付发送IPN通知发生其他异常,请联系管理员,请求参数:" + str);
return "confirmError";
}
} catch (IOException e){
System.out.println("确认付款信息发生IO异常" + e);
return "confirmError";
}
}
paypal支付代码完成,在此说下IPN(及时付款通知),我们在发送paypal支付form表单请求时指定notify_url,在paypal支付完成后会调用改url,我们也就是在这个时刻执行我们需要执行的业务操作,修改用户订单状态等等 ,关于IPN的具体资料,google一下会有n多。
正式环境收款账号设置注意事项:
1 paypal编码和网站编码必须一致
profile -->My selling tools --> PayPal button language encoding --> More Options -->设置编码保存
2 开启return自动返回并且正确配置返回url
profile -->My selling tools -->Website preferences --> Auto Return开启,填写Return URL保存:
3 开启IPN并且配置其url
profile -->My selling tools -->Instant payment notifications -->Edit Settings -->接受IPN并且配置Notity_Url保存