环境准备

  • 注册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/

更多相关文章

  1. php扫马、内网查mysql数据库账号密码(内网webshell渗透)
  2. 豆瓣的账号登录及api操作
  3. 利用python破解sqlserver账号密码
  4. 【原】记一次找回mac root账号的苦逼经历

随机推荐

  1. 我们都是IT民工--流浪人IDE开发札记--牛
  2. 去芜湖、看房子、拿体检报告,魔幻的2021开
  3. 一个带有邮戳的锁StampedLock(jdk1.8出现)
  4. Android常用功能实例
  5. Flux
  6. Redux
  7. 手牵手一起学Springcloud(1)理解微服务
  8. 一个对任务分而治之的java类ForkJoin详解
  9. 5分钟学会mysql的逻辑架构原理
  10. mysql中你应该要知道的变量知识点