详解PHP 如何对接 paypal 支付

环境准备

  • 注册paypal账号
  • 注册paypal开发者账号
  • 创建paypal沙盒测试账户
  • 创建paypal应用
  • 下载PHP SDK
  • 实现支付
  • 实现支付成功回调
  • 实现退款
  • 更多API代码模板

注册paypal账号

  • www.paypal.com 注册商家账户
  • 选择,”创建商家用户”,根据要求填写信息,注册完得去邮箱激活

注册paypal开发者账号

  • developer.paypal.com 使用上一步注册的账号登录
  • 在左侧导航栏点击Accounts,创建两个sandbox账号,一个个人账号(personal)用于付款,一个商家账号(business)用于收款,系统已经默认创建了两个,可以自己选择创建,方便记忆; 创建账号后记得给当前账号添加余额用于接下来的测试。
    创建账号
  • 用刚才创建的测试账号登录沙盒测试站点,查看金额和交易信息www.sandbox.paypal.com

创建沙盒应用APP

  • 账号默认给创建好了一个Default Application,点击查看获取 ClientId和Secret;保存起来,接下来接口调用会使用到;(上线时请重新创建一个Live的应用)
    查看ClientId和Secret

下载SDK

  • 本人使用laravel框架,使用composer下载paypal包
  • composer require paypal/rest-api-sdk-php

实现支付

  • 以下是生成支付的代码片段,伪代码

    function createPayPal(){
          $shippingPrice = 2;
          $taxPrice = 0;
          $subTotal = 26;
          $item1 = new PayPal\\Api\\Item();
          $item1->setName("产品2")->setCurrency("USD")->setQuantity(1)->setPrice(10);
          $item2 = new PayPal\\Api\\Item();
          $item2->setName("产品1")->setCurrency("USD")->setQuantity(2)->setPrice(8);
    
          $itemList = new PayPal\\Api\\ItemList();
          $itemList->addItems([$item1,$item2]);
    
          // Set payment details
          $details = new PayPal\\Api\\Details();
          $details->setShipping($shippingPrice)->setTax($taxPrice)->setSubtotal($subTotal);
    
          // Set payment amount
          //注意,此处的subtotal,必须是产品数*产品价格,所有值必须是正确的,否则会报错
          $total = $shippingPrice + $subTotal + $taxPrice;
          $amount = new PayPal\\Api\\Amount();
          $amount->setCurrency("USD")->setTotal($total)->setDetails($details);
    
          // Set transaction object
          $transaction = new PayPal\\Api\\Transaction();
          $transaction->setAmount($amount)->setItemList($itemList)->setDescription("这是交易描述")
              ->setInvoiceNumber(uniqid());//setInvoiceNumber为支付唯一标识符,在使用时建议改成订单号
    
          $payer = new PayPal\\Api\\Payer();
          $payer->setPaymentMethod('paypal');//["credit_card", "paypal"]
          $redirectUrls = new PayPal\\Api\\RedirectUrls();
          $redirectUrl = "http://test.com/redirect/success";//支付成功跳转的回调
          $cancelUrl = "http://test.com/redirect/cancel";//取消支付的回调
          $redirectUrls->setReturnUrl($redirectUrl)->setCancelUrl($cancelUrl);
    
          // Create the full payment object
          $payment = new PayPal\\Api\\Payment();
          $payment->setIntent("sale")->setPayer($payer)->setRedirectUrls($redirectUrls)->addTransaction($transaction);
    
          try {
              $clientId = "xxxxxx";//上面应用的clientId和secret
              $secret = "XXXXXX";
              $oAuth = new \\PayPal\\Auth\\OAuthTokenCredential($clientId, $secret);
              $apiContext =  new \\PayPal\\Rest\\ApiContext($oAuth);
              if(env('APP_DEBUG') === false ){
                  $apiContext->setConfig(['mode' => 'live']);//设置线上环境,默认是sandbox
              }
              $payment->create($apiContext);
              $approvalUrl = $payment->getApprovalLink();
              dd($approvalUrl);//这个是请求支付的链接,在浏览器中请求此链接就会跳转到支付页面
          } catch (\\Exception $e) {
              dd($e->getMessage());//错误提示
          }
      }

    交易记录

  • 以下是支付成功的回调代码片段,伪代码

    function payRedirect(Request $request)
      {
          $paymentID = $request->get('paymentId');
          $payerId = $request->get('PayerID');
    
          $clientId = "xxxxxx";//上面应用的clientId和secret
          $secret = "XXXXXX";
          $oAuth = new \\PayPal\\Auth\\OAuthTokenCredential($clientId, $secret);
          $apiContext =  new \\PayPal\\Rest\\ApiContext($oAuth);       
          if(env('APP_DEBUG') === false ){
              $apiContext->setConfig(['mode' => 'live']);//设置线上环境,默认是sandbox
          }
          $payment = \\PayPal\\Api\\Payment::get($paymentID, $apiContext);
    
          $execute = new \\PayPal\\Api\\PaymentExecution();
          $execute->setPayerId($payerId);
    
          try{
              $payment = $payment->execute($execute, $apiContext);//执行,从paypal获取支付结果
              $paymentState = $payment->getState();//Possible values: created, approved, failed.
              $invoiceNum = $payment->getTransactions()[0]->getInvoiceNumber();
              $payNum = $payment->getTransactions()[0]->getRelatedResources()[0]->getSale()->getId();//这是支付的流水单号,必须保存,在退款时会使用到
              $total = $payment->getTransactions()[0]->getRelatedResources()[0]->getSale()->getAmount()->getTotal();//支付总金额
              $transactionState = $payment->getTransactions()[0]->getRelatedResources()[0]->getSale()->getState();//Possible values: completed, partially_refunded, pending, refunded, denied.
    
              if($paymentState == 'approved' && $transactionState == 'completed'){
                  //处理成功的逻辑,例如:判断支付金额与订单金额,更新订单状态等
                  return "success";//返回成功标识
              }else{
                  //paypal回调错误,paypal状态不正确
                  return "error";//返回错误标识
              }
          }catch(\\Exception $e){
              dd($e->getMessage());
          }
      }

退款

  • 退款必须要有支付成功的流水单号

  • 一个流水单号可以进行多次退款

  • 退款成功之后,在账号的交易记录中不体现,测试时请登录测试账号自己记录一下余额的变化情况,以确定退款是否成功

  • 商家账号会减少余额并增加手续费(手续费是之前付款多收的),用户账号会增加余额

    function refundOrder()
      {
          try{
              $refundRequest = new \\PayPal\\Api\\RefundRequest();
              $amount = new \\PayPal\\Api\\Amount();
              $amount->setCurrency("USD")->setTotal(10);//退总金额
              $refundRequest->setAmount($amount);
              $refundRequest->setDescription("退款测试");
              $sale = new \\PayPal\\Api\\Sale();
              $sale->setId("XXXXXXXXX");//支付单号,支付成功时保存的支付流水单号
              $clientId = "xxxxxx";//上面应用的clientId和secret
              $secret = "XXXXXX";
              $oAuth = new \\PayPal\\Auth\\OAuthTokenCredential($clientId, $secret);
              $apiContext =  new \\PayPal\\Rest\\ApiContext($oAuth);
              if(env('APP_DEBUG') === false ){
                  $apiContext->setConfig(['mode' => 'live']);//设置线上环境,默认是sandbox
              }
              $detailedRefund = $sale->refundSale($refundRequest, $apiContext);//调接口
              $refundState = $detailedRefund->getState();//Possible values: pending, completed, cancelled, failed.
    
              //var_dump($refundedSale);
              if($refundState == 'completed'){
                  //退款成功,返回
              }else{
                  dd('paypal 退款失败, 状态不正确');
              }
          }catch (\\Exception $exception){
              dd($exception->getMessage());//发生异常
          }
      }

    更多接口代码示例

  • http://paypal.github.io/PayPal-PHP-SDK/sample/

关于详解PHP 如何对接 paypal 支付的文章就分享到这,如果对你有帮助欢迎继续关注我们哦

本文来自投稿,不代表重蔚自留地立场,如若转载,请注明出处https://www.cwhello.com/41669.html

如有侵犯您的合法权益请发邮件951076433@qq.com联系删除

(0)
php学习php学习订阅用户
上一篇 2022年6月21日 22:42
下一篇 2022年6月21日 22:42

相关推荐

  • 详解 PHP 异步后台处理

    PHP 异步后台处理PHP 作为后台的接口服务器已经很常见,在实际应用场景中经常需要异步后台处理。PHP 当然具有它能作为后台服务器的优势之处,但是,在处理一些客户端并不关心的结果时,就显出它的弊端了,没有异步…

    2022年6月25日
    0135
  • 十个PHP安全的必备技巧

    你好,PHP 开发人员。 在这篇文章中,我将尝试为你提供一些可以提高 PHP 应用程序安全性的具体步骤。我关注的是 PHP 配置本身,所以我们不会讨论 SQL 注入、HTTPS 或其他与 PHP 无关的问题。我将使用我的docker-ent…

    2022年6月21日
    0119
  • 重蔚php学习第二十七天——php可变变量,匿名函数

    运算符:赋值运算符,算术运算符,错误抑制符,比较运算符,逻辑运算符,三元运算符,位运算符,连接运算符,自操作运算符(在项目计算当中,非常不建议使用多个自操作一起运算) 源码反码补码 整数的原码反码和补…

    2017年5月5日 PHP自学教程
    0380
  • 一起学习PHP的rar解压读取扩展包吧!

    一起学习PHP的rar解压读取扩展包吧!PHP的rar解压读取扩展包学习作为压缩解压方面的扩展学习,两大王牌压缩格式 rar 和 zip 一直是计算机领域的压缩终结者。rar 格式的压缩包是 Windows 系统中有接近统治地位的存在…

    2023年3月29日
    01
  • PHP实现数据库容器化监控的方法。

    随着容器化技术在云计算领域的广泛应用,大量的应用程序也开始在容器中运行,其中数据库也不例外。但是容器的动态性和快速的扩展能力,也给数据库的监控和管理带来一些困难。为了解决这个问题,本文将介绍一种基于P…

    2023年5月21日
    07
  • PHP函数的封装性

    使用一个表单,输入任意数字,使之可以在2,8,16进制到10进制或10进制到2,8,16进制之间转换,形式大致如下如下: 原始代码实现 Document 数: 十进制转二进制 二进制转十进制

    2018年4月5日 PHP自学教程
    0216
  • php类与对象的关系

    介绍 在面向对象编程中,最重要的概念就是 类 和对象,因此我们必须将他们的关系和区别搞清楚. 举例说明 说明: 从上面的代码我们可以看出 一个类可以创建多个对象 不同的对象的标识符#编码,是不一样的,有系统在…

    2018年4月9日
    0387
  • PHP商城的售后服务系统设计与实现。

    随着网络购物在当今社会中逐渐普及,越来越多的商家利用网络平台来销售产品,而PHP作为一种广泛应用的服务器端脚本语言,自然成为了许多商城系统的首选。然而,在购买商品之后,消费者的售后服务需求也逐渐增多,如…

    2023年5月23日
    01

联系我们

QQ:951076433

在线咨询:点击这里给我发消息邮件:951076433@qq.com工作时间:周一至周五,9:30-18:30,节假日休息