使用paypal-php-sdk开发php国际支付
参考: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
<?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()
->setSku("testpro1_01")
->setPrice(2.3);
$item2 = new Item();
$item2->setName('test pro 2')
->setCurrency('USD')
->setQuantity()
->setSku("testpro2_01")
->setPrice(1.1);
$itemList = new ItemList();
$itemList->setItems(array($item1, $item2));
// 自定义用户收货地址,如果这里不定义,在支付页面能够修改,可能会误操作,与用户想等地质不一致
$address = new ShippingAddress(); $address->setRecipientName("张三")
->setLine1("小区名")
->setLine2("楼号")
->setCity("城市")
->setState("省份")
->setPhone() //收货电话
->setPostalCode() //邮编
->setCountryCode('CN'); $itemList->setShippingAddress($address); //设置总价,运费等金额。注意:setSubtotal的金额必须与详情里计算出的总金额相等,否则会失败
$details = new Details();
$details->setShipping()
->setTax()
->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,(注:是自己的卖家账号)就能看到刚才支付的详情了

这样一个完整的支付流程就跑通了,如果需要根据自己的业务去设置商品价格详情。
注:这个流程只对两位小数有效,我们的业务是四位小数,当传入四位小数时一直提示传入参数错误,目前还没有找到解决办法,等解决后再来补充,如果有能解决的大佬,欢迎留言,不胜感激。
使用paypal-php-sdk开发php国际支付的更多相关文章
- PayPal 开发详解(六):下载paypal立即付款SDK 并编译打包
1.下载PayPal REST SDKs,地址:https://developer.paypal.com/docs/api/rest-sdks/ paypal api比较混乱,有的已经不推荐使用,比如 ...
- IOS开发之—— iOS 支付 [支付宝、银联、微信]
支付宝iOSsdk官方下载sdk地址:https://b.alipay.com/order/productDetail.htm?productId=2013080604609654&tabId ...
- php 微信开发之 微信支付 V3 开发 -CURLOP_TIMEOUT问题
如果不懂怎么配置的话请看文章 php 微信开发之 微信支付配置 基本配置后在继续本文章的开发 . 本文章就先继续基本的实现!也并不困难.我大概的思路的返回购买者的唯一id 和 订单号的唯一 id 就2 ...
- PHP微信支付开发之扫描支付(模式二)后如何回调
其实在写这篇文章的时候感觉自己已经落伍了,不过笔者在百度上搜索"微信支付开发之扫描支付(模式二)后如何回调"寻找答案时,发现依旧有很多朋友没有解决这个问题,所以就把自己的解决思路分 ...
- Android SDK开发与使用的那些事儿
前言 最近由于工作需要,将应用里的部分功能独立了出来,封装成 SDK 提供给合作伙伴使用.由于经验不足,网上也没多少写这方面内容的文章,遇到了不少的坑,决定记录下来. SDK 其实,刚说到要写SDK也 ...
- android开发之微信支付功能的实现
移动开发中,支付类的App越来越多,对于开发者来说也是不可少的,不可不会的:下面就来说一说支付开发的流程 1.申请你的AppID 请到 开发者应用登记页面 进行登记,登记并选择移动应用进行设置后,将该 ...
- Kinect for Windows SDK开发学习相关资源
Kinect for Windows SDK(K4W)将Kinect的体感操作带到了平常的应用学习中,提供了一种不同于传统的鼠标,键盘及触摸的无接触的交互方式,在某种程度上实现了自然交互界面的理想,即 ...
- 微信公众账号 Senparc.Weixin.MP SDK 开发教程 索引
Senparc.Weixin.MP SDK从一开始就坚持开源的状态,这个过程中得到了许多朋友的认可和支持. 目前SDK已经达到比较稳定的版本,这个过程中我觉得有必要整理一些思路和经验,和大家一起分享. ...
- 高拍仪拍照SDK开发(良田影像S300L|S500L)
高拍仪拍照SDK开发下载地址:点击下载 本SDK适用于:良田影像S300L|S500L 高拍仪如图: SDN开发包安装之后找到安装目录,如图: 大家找到各自需要的版本即可,需要注意的是如果需要上传图片 ...
随机推荐
- GC的判定的2种方式
对象是否死亡的2中判定方法:引用计数和可达性分析(又称引用链) 1.引用计数 对象再被创建时,对象头里会存储引用计数器,对象被引用,计数器+1:引用失效,计数器 -1:GC时会回收计数器为0的对象.但 ...
- 系统调优:如何解决系统报错too many open files
一.检查系统版本是否手工升级 关于lsb_release -a和/etc/issue显示的发行版本号不同,原因只有一个:系统内核手动升级了 对于高并发高http连接的应用程序例如www或Java,会遇 ...
- 认识wsgi
WSGI是什么? WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义 ...
- JS 定时器的4种写法及介绍
JS提供了一些原生方法来实现延时去执行某一段代码,下面来简单介绍一下setTiemout.setInterval.setImmediate.requestAnimationFrame. 一.什么是定时 ...
- git补充(命令)转自https://github.com/Wasdns/github-example-repo
在使用命令行进行提交时,通常使用git commit -m '注释信息'来填写commit注释信息,但是-m参数适合单行注释,对于多行的commit注释来说是不合适的.这里推荐使用git commit ...
- 使用Qt Creator作为Linux IDE,代替Vim:实现两台Linux电脑远程部署和gdb调试(一台电脑有桌面系统,一台电脑无桌面系统)
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/libaineu2004/article/details/62423830 尊重作者,支持原创,如 ...
- SparkConf和SparkContext
任何Spark程序都是SparkContext开始的,SparkContext的初始化需要一个SparkConf对象,SparkConf包含了Spark集群配置的各种参数. 初始化后,就可以使用Spa ...
- Windows 自动定时执行任务的方法
windows 自动定时执行任务的几种实现方法 Task Schedul Windows自动定时执行任务,常见的方法有三种: Windows 任务计划程序 Windows Service SQL ...
- C# 多线程Thread.IsBackground=True的作用
C#中多线程的线程加.IsBackground = true与不加有什么区别? 按照MSDN上讲:“获取或设置一个值,该值指示某个线程是否为后台线程.” 其实这个解释并不到位,至少应该解释一下后台线程 ...
- vue页面刷新重定向
在App.vue中,添加如下代码: created(){ if(this.$router.path !== '/RealTimeMonitoring'){ this.$router.replace(' ...