ThinkPHP接入PayPal支付

server/2025/1/1 7:48:52/

ThinkPHP 5接入PayPal 支付,PayPal的流程是服务器请求Paypal的接口下单(需要传订单id/支付成功的重定向地址/支付失败的重定向地址),接会返回一个支付地址,项目服务器把地址返给用户,用户打开链接登录Paypal完成付款,然后Paypal给重定向到指定地址。

在paypal官网开通商户号,设置通知地址。

开通沙箱模式用于测试,后台会给沙箱模式生成商户账号和用户账号,请注意区分。

申请和开通网上有教程不在赘述。

具体实现步骤如下

1.安装包

composer require paypal/rest-api-sdk-php:*

2.具体实现代码

<?phpnamespace app\api\controller;use app\common\controller\Api;
use app\common\model\ShopOrder;
use PayPal\Api\Amount;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\Transaction;
use PayPal\Api\PaymentExecution;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Rest\ApiContext;
use PayPal\Api\RedirectUrls;
use think\Log;
class Paypal extends Api
{protected $noNeedLogin = ['*'];protected $noNeedRight = ['*'];private $apiContext;public function __construct(){parent::__construct();// 初始化PayPal API上下文$this->apiContext = new ApiContext(new OAuthTokenCredential('AV8d**************************N-jbpRvV-K0_dLuEA5d8uodUowab6jdWtM',     // 客户端ID'EByrRAncAi*****************************RSqIRA'         // 客户端密钥));$this->apiContext->setConfig(['mode' => 'sandbox',      // 或者 'live'// 其他配置...]);}/*** 下单接口* @return \think\response\Json|void* @throws \think\db\exception\DataNotFoundException* @throws \think\db\exception\ModelNotFoundException* @throws \think\exception\DbException*/public function createPaypalPaymentUrl(){// 获取前端传递的order_Id$orderId = input('post.order_id');// 查询订单信息(这里你需要根据自己的数据库结构进行查询)// 假设我们得到了一个包含订单详情的数组$orderInfo$orderInfo = ShopOrder::where('id', $orderId)->where('status', '1')->find();if (empty($orderInfo)) {$this->error('订单不存在或不是待支付状态');}// 设置Payer信息,表明付款人是通过PayPal付款$payer = new Payer();$payer->setPaymentMethod("paypal");// 设置交易金额$amount = new Amount();$amount->setCurrency("AUD")->setTotal(number_format($orderInfo['actual_money'], 2, '.', ''));// 创建Transaction对象,并使用订单ID作为发票号$transaction = new Transaction();$transaction->setAmount($amount)->setDescription("Slem order pay")  // 描述可选->setInvoiceNumber($orderInfo->order_num);  // 使用订单order_num作为发票号// 创建RedirectUrls对象$redirectUrls = new RedirectUrls();$redirectUrls->setReturnUrl("https://*******.cn/api/paypal/paymentSuccess")  // 支付成功后的回调地址->setCancelUrl("https://********/api/paypal/paymentCancel");  // 用户取消支付后的回调地址// 创建Payment对象$payment = new Payment();$payment->setIntent("sale")->setPayer($payer)->setRedirectUrls($redirectUrls)->setTransactions([$transaction]);try {// 创建支付请求$payment->create($this->apiContext);// 获取approval_url,这是用户需要访问来完成支付的URLforeach ($payment->getLinks() as $link) {if ($link->getRel() == 'approval_url') {// 返回支付链接给客户端return json(['code' => 1, 'data' => $link->getHref()]);
//                    $data = ['status' => 'success', 'approval_url' => $link->getHref()];
//                    $this->success(__('SUccess'),$data);}}} catch (\Exception $ex) {// 输出详细的错误信息return json(['status' => 'error','message' => 'Error creating PayPal payment: ' . $ex->getMessage(),'details' => $ex->getTraceAsString(),'response' => $payment->toArray()]);}}/*** 支付成功跳转的页面* 建议前端出个html后台做渲染,本方法只为展示流程* @return \think\response\Json*/public function paymentSuccess(){// 获取PayPal传递过来的参数$paymentId = input('get.paymentId');$payerId = input('get.PayerID');if (empty($paymentId) || empty($payerId)) {return json(['status' => 'error', 'message' => 'Missing payment ID or payer ID']);}try {// 获取支付信息$payment = Payment::get($paymentId, $this->apiContext);// 创建PaymentExecution对象并设置payer_id$execution = new PaymentExecution();$execution->setPayerId($payerId);// 执行支付请求$result = $payment->execute($execution, $this->apiContext);// 检查支付状态if ($result->getState() === 'approved') {// 使用发票号(即订单ID)来查找订单$invoiceNumber = $payment->getTransactions()[0]->getInvoiceNumber();$order = ShopOrder::where('order_num', $invoiceNumber)->find();if (!empty($order)) {// 更新订单状态为已支付$order->payment = 'paypal';$order->status = '2';$order->save();// 你可以在这里添加更多的业务逻辑,比如发送确认邮件等// 返回成功信息给前端return json(['status' => 'success', 'message' => 'Payment successful']);} else {return json(['status' => 'error', 'message' => 'Order not found']);}} else {return json(['status' => 'error', 'message' => 'Payment not approved']);}} catch (\Exception $ex) {// 错误处理Log::error('PayPal Error: ' . $ex->getMessage());return json(['status' => 'error','message' => 'Error executing payment: ' . $ex->getMessage(),'details' => $ex->getTraceAsString()]);}}/*** 支付取消跳转的页面* @return \think\response\Json*/public function paymentCancel(){// 获取订单ID或其他相关信息(如果需要)$orderId = input('get.order_id'); // 如果PayPal回调包含order_idif (!empty($orderId)) {try {// 根据订单ID查找订单信息$order = ShopOrder::where('id', $orderId)->find();if (!empty($order)) {// 你可以在这里添加更多的业务逻辑,比如记录取消原因、发送通知等// 更新订单状态为已取消或保持不变,视业务需求而定// 这里假设我们不改变订单状态,仅记录取消事件Log::info("Payment cancelled for order ID: " . $orderId);// 返回取消信息给前端return json(['status' => 'info', 'message' => 'Payment cancelled.']);} else {return json(['status' => 'error', 'message' => 'Order not found.']);}} catch (\Exception $ex) {// 错误处理Log::error('Error handling payment cancellation: ' . $ex->getMessage());return json(['status' => 'error','message' => 'An error occurred while processing your request.','details' => $ex->getTraceAsString()]);}} else {// 如果没有提供订单ID,则简单地告知用户支付已被取消return json(['status' => 'info', 'message' => 'Payment cancelled.']);}}
}


http://www.ppmy.cn/server/154367.html

相关文章

深入探索 npm cache clean --force:清理 npm 缓存的艺术

npm 是 JavaScript 编程语言的包管理器&#xff0c;它是 Node.js 运行环境的默认包管理器。npm 提供了一个丰富的生态系统&#xff0c;包括数以百万计的可重用代码包。然而&#xff0c;随着时间的推移&#xff0c;npm 的缓存可能会变得庞大&#xff0c;影响性能或导致一些奇怪的…

Windows下Python+PyCharm的安装步骤及PyCharm的使用

Windows下PythonPyCharm的安装步骤及PyCharm的使用 文章目录 Windows下PythonPyCharm的安装步骤及PyCharm的使用一、Python的安装&#xff08;1&#xff09;环境准备&#xff08;2&#xff09;Python安装&#xff08;3&#xff09;pip组件的安装 二、PyCharm的安装&#xff08;…

基于springboot校园招聘系统源码和论文

可做计算机毕业设计JAVA、PHP、爬虫、APP、小程序、C#、C、python、数据可视化、大数据、文案 使用旧方法对校园招聘系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在校园招聘系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比…

自动化测试模型(一)

8.8.1 自动化测试模型概述 在自动化测试运用于测试工作的过程中&#xff0c;测试人员根据不同自动化测试工具、测试框架等所进行的测试活动进行了抽象&#xff0c;总结出线性测试、模块化驱动测试、数据驱动测试和关键字驱动测试这4种自动化测试模型。 线性测试 首先&#…

【每日学点鸿蒙知识】Web请求支持Http、PDF展示、APP上架应用搜索问题、APP备案不通过问题、滚动列表问题

1、HarmonyOS Web不支持http请求&#xff0c;只支持https&#xff1f; Web组件http请求失败&#xff0c;改成https是好的&#xff0c;是否可以通过配置打开http的请求 参考文档&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-basic-c…

Qt 应用程序转换为服务

一、在 Windows 上将 Qt 应用程序转换为服务 方法1&#xff1a; 创建一个 Windows 服务应用程序&#xff1a; Windows 服务应用程序是一个没有用户界面的后台进程&#xff0c;通常由 Win32 Service 模板创建&#xff0c;或者直接编写 main() 函数以实现服务逻辑。 修改 Qt 应…

leetcode81:搜索旋转排序数组II

原题地址&#xff1a;81. 搜索旋转排序数组 II - 力扣&#xff08;LeetCode&#xff09; 题目描述 已知存在一个按非降序排列的整数数组 nums &#xff0c;数组中的值不必互不相同。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums…

微服务——数据管理与一致性

1、在微服务架构中&#xff0c;每个微服务都有自己的数据库&#xff0c;这种设计有什么优点和挑战&#xff1f; 优点挑战服务自治&#xff1a;每个微服务可独立选择适合自己的数据库类型。数据一致性&#xff1a;跨微服务的事务难以保证强一致性。故障隔离&#xff1a;一个微服…