一,先注册商业账号paypal官网www.paypal.com
二,接下来我们开始沙箱测试;当账户注册成功以后,paypal会分配给开发者账号两个沙箱测试账号(一个买家账号和一个商家账号)。
去paypal开发者账号管理端查看,登录地址:https://developer.paypal.com,用上面刚刚注册的账号密码即可,然后进入后台看到如下界面
我画红框的那两个账号就是paypal自动分配给我的,但是这个又是一个坑!!!!!我们可以看到Country的值为C2(代表中国区账号),但是我们千万不要同时拿着这两个账号来进行沙箱收付款测试,因为Paypal规定中国地区和中国地区的账户之间无法实现付款。把其中一个同账号修改为其它国家即可.
三,给你的商家测试账号是可以单独登录的.登录后,可以查看收款情况.里面的余额是虚拟的.登录地址为https://www.sandbox.paypal.com/,这里需要用上面红框中的商家账号登录
四.php代码
<?php
namespace Home\Controller;
use Think\Controller;
class PaypalController extends Controller {
/**
* 自己的paypal账号
*/
//private $account = 'info@ld.com';
private $account = 'sb-ylrml6894057@business.example.com';
/**
* paypal支付网关地址
*/
//private $gateway = 'https://www.paypal.com/cgi-bin/webscr?';
private $gateway = 'https://www.sandbox.paypal.com/cgi-bin/webscr?';
public function order(){
//print_r(I('get'));exit;
$order_id=I('get.order_id');
$price = I('get.price');
// 初始化准备提交到Paypal的数据
$pp_info = array();
// 告诉Paypal,我的网站是用的我自己的购物车系统
$pp_info['cmd'] = '_xclick';
// 告诉paypal,我的(商城的商户)Paypal账号,就是这钱是付给谁的
$pp_info['business'] = $this->account;
// 用户将会在Paypal的支付页面看到购买的是什么东西,只做显示,没有什么特殊用途,
// 如果是多件商品,则直接告诉用户,只支付某个订单就可以了
$pp_info['item_name'] = "支付订单:".$order_id;
$pp_info['amount'] = $price; // 告诉Paypal,我要收多少钱
// 告诉Paypal,我要用什么货币。这里需要注意的是,由于汇率问题,
// 如果网站提供了更改货币的功能,那么上面的amount也要做适当更改,
// paypal是不会智能的根据汇率更改总额的
$pp_info['currency_code'] = 'USD';
// 当用户成功付款后paypal会将用户自动引导到此页面。
// 如果为空或不传递该参数,则不会跳转
//支付页面时,点击返回商家.也会返回这个地址
$pp_info['return'] = 'http://www.asml.com/index.php?s=/home/index/user_order.html';
$pp_info['invoice'] = $order_id;
$pp_info['charset'] = 'utf-8';
$pp_info['no_shipping'] = '2';
$pp_info['shipping address'] = 'beijing';
$pp_info['no_note'] = '1';
// 当跳转到paypal付款页面时,用户又突然不想买了。则会跳转到此页面
$pp_info['cancel_return'] = 'http://www.asml.com/index.php?s=/home/index/user_order.html';
// Paypal会将指定 invoice 的订单的状态定时发送到此URL
// (Paypal的此操作,是paypal的服务器和我方商城的服务器点对点的通信,用户感觉不到)
//post回调页面
$pp_info['notify_url'] = 'http://www.asml.com/index.php?s=/home/paypal/notify/orderid/'.$order_id;
$pp_info['rm'] = '2';
$pp_info['lc'] = 'en_US';
$paypal_payment_url = $this->gateway.http_build_query($pp_info);
//echo "<a href='{$paypal_payment_url}'>Go Paypal!</a>";
header("Location: {$paypal_payment_url}");
}
public function notify() {
//本页面,可以测试时,单独访问,用来测试,订单号可以手动填好
// 由于这个文件只有被Paypal的服务器访问,所以无需考虑做什么页面什么的,
// 这个页面不是给人看的,是给机器看的
$order_id = floor( $_GET['orderid']);
//订单号,非法过滤,不要用int()过滤,否则超过10位的数字会显示不全
$order_info = M('order')->where(array('code'=>$order_id))->find();
//print_r($order_info);exit;
$id=$order_info['id'];
// 由于该URL不仅仅只有Paypal的服务器能访问,其他任何服务器都可以向该方法发起请求。
// 所以要判断请求发起的合法性,也就是要判断请求是否是paypal官方服务器发起的
// 拼凑 post 请求数据
$req = 'cmd=_notify-validate';// 验证请求
foreach ($_POST as $k=>$v){
$v = urlencode(stripslashes($v));
$req .= "&{$k}={$v}";
}
// $req="cmd=_notify-validate&mc_gross=10.00&invoice=1629876154398&protection_eligibility=Eligible&address_status=confirmed&payer_id=MS6Q4WXDA6VP8&address_street=1+Main+St&payment_date=00%3A22%3A51+Aug+25%2C+2021+PDT&payment_status=Completed&charset=gb2312&address_zip=95131&first_name=John&mc_fee=0.69&address_country_code=US&address_name=John+Doe¬ify_version=3.9&custom=&payer_status=verified&business=sb-ylrml6894057%40business.example.com&address_country=United+States&address_city=San+Jose&quantity=1&verify_sign=AnHDRp16zRtu62B-gdTexFGNDtX8A01Yl0VBl4FxJtT7ephovzX7HUfB&payer_email=sb-epigs7127455%40personal.example.com&txn_id=0CR94435AC472235R&payment_type=instant&last_name=Doe&address_state=CA&receiver_email=sb-ylrml6894057%40business.example.com&payment_fee=0.69&shipping_discount=0.00&insurance_amount=0.00&receiver_id=EX2HU5HT9AUHC&txn_type=web_accept&item_name=%D6%A7%B8%B6%B6%A9%B5%A5%A3%BA1629876154398&discount=0.00&mc_currency=USD&item_number=&residence_country=US&test_ipn=1&shipping_method=Default&transaction_subject=&payment_gross=10.00&ipn_track_id=579f60def14a7";
//$cache2=RUNTIME_PATH.'2_'.rand().'.txt';
//file_put_contents($cache2,$req);//通过上面二行,可以打印出post给我们的数据.类似上面的参数$req
$url_par=parse_url($this->gateway);
$fp = fsockopen($url_par[host],"80",$errnum,$errstr,30);
if(!$fp) {
return false;
} else {
fputs($fp, "POST ".$url_par[path]." HTTP/1.1\r\n");
fputs($fp, "Host: ".$url_par[host]."\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ".strlen($req)."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $req . "\r\n\r\n");
// loop through the response from the server and append to variable
while(!feof($fp)) {
$this->validate_ipn_response .= fgets($fp, 1024);
}
fclose($fp); // close connection
}
if (eregi("VERIFIED",$this->validate_ipn_response)) {
//$cache3=RUNTIME_PATH.'3_'.rand().'.txt';
// file_put_contents($cache3,$res);
/**
* 判断订单的状态
* 判断订单的收款人
* 判断订单金额
* 判断货币类型
payment_status'] != 'Pending 证明这个款项正在审核,一般要一个星期左右,会自动到账,放心。
*/
if(($_POST['payment_status'] != 'Completed' && $_POST['payment_status'] != 'Pending') //Pending 证明这个款项付款成功,正在审核
OR ($_POST['receiver_email'] != $this->account)
OR ($_POST['mc_gross'] != $order_info['allprice'])
OR ('USD' != $_POST['mc_currency'])) {
// 如果有任意一项成立,则终止执行。由于是给机器看的,所以不用考虑什么页面。直接输出即可
//$cache3=RUNTIME_PATH.'fail_'.rand().'.txt';
// file_put_contents($cache3,1);//先用php生成缓存.
echo 'fail';exit;
} else {// 如果验证通过,则证明本次请求是合法的
$data['state']=2;//订单状态,2表示付款成功
$orders=M('order_list')->where(array('oid'=>$id))->select();
foreach($orders as $k=>$v){
$product_id=$v['cid'];
$oldkucun=M('contlist')->where(array('id'=>$product_id))->getField('kucun');
$kucun=$oldkucun-$v['num'];
//$data['kucun']=$kucun;//这里可以修改库存情况
M('contlist')->where(array('id'=>$product_id))->save($data);
}
// $cache3=RUNTIME_PATH.'success_1_'.rand().'.txt';
//file_put_contents($cache3,1);//先用php生成缓存.
M('order')->where(array('code'=>$_POST['invoice']))->save($data);
echo 'success';exit;
}
} else {
echo 'fail';exit;
}
}
}
?>