视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
详解PHP 如何对接 paypal 支付
2020-11-02 17:28:52 责编:小采
文档

推荐:《PHP视频教程》

环境准备

  • 注册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的应用)
  • 下载SDK

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

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

    function createPayPal(){
     $shippingPrice = 2;
     $taxPrice = 0;
     $subTotal = 26;
     $item1 = new PayPalApiItem();
     $item1->setName("产品2")->setCurrency("USD")->setQuantity(1)->setPrice(10);
     $item2 = new PayPalApiItem();
     $item2->setName("产品1")->setCurrency("USD")->setQuantity(2)->setPrice(8);
    
     $itemList = new PayPalApiItemList();
     $itemList->addItems([$item1,$item2]);
    
     // Set payment details
     $details = new PayPalApiDetails();
     $details->setShipping($shippingPrice)->setTax($taxPrice)->setSubtotal($subTotal);
    
     // Set payment amount
     //注意,此处的subtotal,必须是产品数*产品价格,所有值必须是正确的,否则会报错
     $total = $shippingPrice + $subTotal + $taxPrice;
     $amount = new PayPalApiAmount();
     $amount->setCurrency("USD")->setTotal($total)->setDetails($details);
    
     // Set transaction object
     $transaction = new PayPalApiTransaction();
     $transaction->setAmount($amount)->setItemList($itemList)->setDescription("这是交易描述")
     ->setInvoiceNumber(uniqid());//setInvoiceNumber为支付唯一标识符,在使用时建议改成订单号
    
     $payer = new PayPalApiPayer();
     $payer->setPaymentMethod('paypal');//["credit_card", "paypal"]
     $redirectUrls = new PayPalApiRedirectUrls();
     $redirectUrl = "http://test.com/redirect/success";//支付成功跳转的回调
     $cancelUrl = "http://test.com/redirect/cancel";//取消支付的回调
     $redirectUrls->setReturnUrl($redirectUrl)->setCancelUrl($cancelUrl);
    
     // Create the full payment object
     $payment = new PayPalApiPayment();
     $payment->setIntent("sale")->setPayer($payer)->setRedirectUrls($redirectUrls)->addTransaction($transaction);
    
     try {
     $clientId = "xxxxxx";//上面应用的clientId和secret
     $secret = "XXXXXX";
     $oAuth = new PayPalAuthOAuthTokenCredential($clientId, $secret);
     $apiContext = new PayPalRestApiContext($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 PayPalAuthOAuthTokenCredential($clientId, $secret);
     $apiContext = new PayPalRestApiContext($oAuth); 
     if(env('APP_DEBUG') === false ){
     $apiContext->setConfig(['mode' => 'live']);//设置线上环境,默认是sandbox
     }
     $payment = PayPalApiPayment::get($paymentID, $apiContext);
    
     $execute = new PayPalApiPaymentExecution();
     $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 PayPalApiRefundRequest();
     $amount = new PayPalApiAmount();
     $amount->setCurrency("USD")->setTotal(10);//退总金额
     $refundRequest->setAmount($amount);
     $refundRequest->setDescription("退款测试");
     $sale = new PayPalApiSale();
     $sale->setId("XXXXXXXXX");//支付单号,支付成功时保存的支付流水单号
     $clientId = "xxxxxx";//上面应用的clientId和secret
     $secret = "XXXXXX";
     $oAuth = new PayPalAuthOAuthTokenCredential($clientId, $secret);
     $apiContext = new PayPalRestApiContext($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/

  • 下载本文
    显示全文
    专题