转自 https://www.cnblogs.com/lxhyty/p/11207244.html
参考:https://github.com/paypal/PayPal-PHP-SDK/wiki
https://blog.csdn.net/markely/article/details/79044145
最近公司做一个国际版商城,国内的支付宝和微信支付不太适用,故而选择PayPal。PayPal在国内开发还是比较少的,不如支付宝和微信,所以没有中文文档,辛辛苦苦啃了好几天终于跑通了,在这里做一下总结,方便以后再用。
PayPal在国外的市场占有率还是很高的,只是手续费之高让人有点儿肾疼,不过这不是我关心的东西,只是实现功能。
废话不多说,直接展示开发过程。
一、准备工作:
首先需要测试账号,PayPal开发感觉好的一点是提供测试账号(也叫沙箱账号)
1、浏览器访问 https://www.paypal.com/c2/home 进入PayPal官网
2、点击注册,根据 要求填写信息进行注册(easy)
3、注册完成以后,访问https://developer.paypal.com/
4、点击右上角的 Log Into Dashboard 按钮,登录你刚才注册的账号,进入仪表盘
5、登录之后点击左侧的accounts,左侧页面会显示你的买家和买家测试账号
6、点击profile,会进入买家的账户管理,在里面可以设置密码和金额等信息
7、点击左上角的My apps & credentials ,出现如下页面
8、点击create app,创建自己的应用,这一步主要clientID和secret,在调用API接口是生成token需要这两个值,很重要
二、准备工作做完了,要上代码了
1、根据wiki上提供的有两种方式下载安装
我选择的是composer,没有安装composer的童鞋自行安装,这里不再赘述。当然也可以使用第二种方式
2、新建文件夹
3、进去后打开cmd,输入composer require "paypal/rest-api-sdk-php:*" ,回车
4、当看到这个的时候说明下载完成
目录结构如下:vendor目录下是PayPal-PHP-SDK的API接口
新建目录:目录结构如下
payment.php
<?phprequire_once("./common.php");
use PayPal\Api\Amount; use PayPal\Api\Details; use PayPal\Api\Item; use PayPal\Api\ItemList; use PayPal\Api\Payer; use PayPal\Api\Payment; use PayPal\Api\RedirectUrls; use PayPal\Api\ShippingAddress; use PayPal\Api\Transaction; $payer = new Payer(); $payer->setPaymentMethod("paypal"); //设置商品详情 /** * 详情信息:单价、收货地址等请结合自己的业务去数据库或者其他存储数据的地方查询 * 这里只是演示支付流程,不结合实际业务 */ $item1 = new Item(); $item1->setName('test pro 1') ->setCurrency('USD') ->setQuantity(1) ->setSku("testpro1_01") ->setPrice(2.3); $item2 = new Item(); $item2->setName('test pro 2') ->setCurrency('USD') ->setQuantity(5) ->setSku("testpro2_01") ->setPrice(1.1); $itemList = new ItemList(); $itemList->setItems(array($item1, $item2)); // 自定义用户收货地址,如果这里不定义,在支付页面能够修改,可能会误操作,与用户想等地质不一致 $address = new ShippingAddress(); $address->setRecipientName("张三") ->setLine1("小区名") ->setLine2("楼号") ->setCity("城市") ->setState("省份") ->setPhone(15211111111) //收货电话 ->setPostalCode(000000) //邮编 ->setCountryCode('CN'); $itemList->setShippingAddress($address); //设置总价,运费等金额。注意:setSubtotal的金额必须与详情里计算出的总金额相等,否则会失败 $details = new Details(); $details->setShipping(1) ->setTax(2) ->setSubtotal(7.8); // 同上,金额要相等 $amount = new Amount(); $amount->setCurrency("USD") ->setTotal(10.8) ->setDetails($details); $transaction = new Transaction(); $transaction->setAmount($amount) ->setItemList($itemList) ->setDescription("Payment description") ->setInvoiceNumber(uniqid()); /** * 回调 * 当支付成功或者取消支付的时候调用的地址 * success=true 支付成功 * success=false 取消支付 */ $redirectUrls = new RedirectUrls(); $redirectUrls->setReturnUrl("http://localhost/paypal/payment/exec.php?success=true") ->setCancelUrl("http://localhost/paypal/payment/cancel.php?success=false"); $payment = new Payment(); $payment->setIntent("sale") ->setPayer($payer) ->setRedirectUrls($redirectUrls) ->setTransactions(array($transaction)); //创建支付 $payment->create($apiContext); //生成地址 $approvalUrl = $payment->getApprovalLink(); // var_dump($approvalUrl); //跳转 header("location:" . $approvalUrl);
exec.php
<?php set_time_limit(3600); require_once('./common.php'); use PayPal\Api\Amount; use PayPal\Api\Details; use PayPal\Api\ExecutePayment; use PayPal\Api\Payment; use PayPal\Api\PaymentExecution; use PayPal\Api\Transaction; if (isset($_GET['success']) && $_GET['success'] == 'true') { $paymentId = $_GET['paymentId']; $payment = Payment::get($paymentId, $apiContext); $execution = new PaymentExecution(); $execution->setPayerId($_GET['PayerID']); $transaction = new Transaction(); $amount = new Amount(); $details = new Details(); $details->setShipping(1) ->setTax(2) ->setSubtotal(7.8); $amount->setCurrency('USD'); $amount->setTotal(10.8); $amount->setDetails($details); $transaction->setAmount($amount); $execution->addTransaction($transaction); try { $result = $payment->execute($execution, $apiContext); echo "支付成功"; } catch (Exception $ex) { echo "支付失败"; die; } return $payment; } else { echo "PayPal返回回调地址参数错误"; }
common.php
<?php require_once('../vendor/autoload.php'); use PayPal\Rest\ApiContext; use PayPal\Auth\OAuthTokenCredential; // 下面为申请app获得的clientId和clientSecret,必填项,否则无法生成token。 $clientId = 'ATnuSLiYPPpNovryQJ4ZsiD1FfR2Jelv5GBkSGNjd59Ef8SW8XEH48fFwOf7L9wcyZARGx3LanesBuvb'; $clientSecret = 'EAadzJ40KVcpBanjhdAR13N2mxPBi2O7uQYMs8h-wMga5scKmwHEyCIOLLgQk2FLEcEOc2xS5ORwyQSo'; $apiContext = new ApiContext( new OAuthTokenCredential( $clientId, $clientSecret ) ); $apiContext->setConfig( array( 'mode' => 'sandbox', 'log.LogEnabled' => true, 'log.FileName' => '../PayPal.log', 'log.LogLevel' => 'DEBUG', 'cache.enabled' => true ) );
cancel.php
<?php echo "用户取消支付";
浏览器访问:http://localhost/paypal/payment/payment.php
成功后跳转到
登录买家的账号,在前面提到过。登录成功后跳转到支付页面
点击继续进行付款,成功后回调代码中提供的url
然后登陆自己的沙箱账号:https://sandbox.paypal.com/us/signin,(注:是自己的卖家账号)就能看到刚才支付的详情了
这样一个完整的支付流程就跑通了,如果需要根据自己的业务去设置商品价格详情。
注:这个流程只对两位小数有效,我们的业务是四位小数,当传入四位小数时一直提示传入参数错误,目前还没有找到解决办法,等解决后再来补充,如果有能解决的大佬,欢迎留言,不胜感激。