paypal 支付流程

2020-07-11  本文已影响0人  云龙789

推荐资料

主要是参考官方的 SDK PayPal-PHP-SDK wiki 操作的 https://github.com/paypal/PayPal-PHP-SDK/wiki,按照上面的步骤一步步操作

以下三点也很重要

1.下载 SDK

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

2.创建支付订单。比如我们使用first.php 页面

// 1.引入 sdk 包
<?php
// 1. Autoload the SDK Package. This will include all the files and classes to your autoloader
// Used for composer based installation
require __DIR__  . '/vendor/autoload.php';
// Use below for direct download installation
// require __DIR__  . '/PayPal-PHP-SDK/autoload.php';

// 2. 添加你的 clientId 和 secret
// After Step 1
$apiContext = new \PayPal\Rest\ApiContext(
        new \PayPal\Auth\OAuthTokenCredential(
            'ClientID',     // ClientID
            'ClientSecret'      // ClientSecret
        )
);

// 3.  创建订单
// 付款人信息
$payer = new \PayPal\Api\Payer();
$payer->setPaymentMethod('paypal'); // 付款方式

// 金额信息
$amount = new \PayPal\Api\Amount();
$amount->setTotal('1.00');
$amount->setCurrency('USD');

// 交易信息
$transaction = new \PayPal\Api\Transaction();
$transaction->setAmount($amount);

// 回调信息
$redirectUrls = new \PayPal\Api\RedirectUrls();
$redirectUrls->setReturnUrl("https://xxx.com/callback.phpl") //支付后, 同步回调 url
    ->setCancelUrl("https://xxx.com/cancel.php");// 取消支付后跳转的的url

// 创建支付实例,并赋值
$payment = new \PayPal\Api\Payment();
$payment->setIntent('sale')
    ->setPayer($payer)
    ->setTransactions(array($transaction))
    ->setRedirectUrls($redirectUrls);

// 4. 请求支付
try {
    $payment->create($apiContext);
            如果支付成功,则肯定有第三方的订单号,我们应该记录此单号。因为paypal 并没有记录我们本地的单号
            // 获取订单id
            $arr = json_decode($payment, true);
            // 订单id 赋值
            $paypal_order_id = isset($arr['id']) ? $arr['id'] : '';

    echo $payment; // 支付信息
    echo  $payment->getApprovalLink(); //客户支付,需要跳转的连接
}
catch (\PayPal\Exception\PayPalConnectionException $ex) {
    // This will print the detailed information on the exception.
    //REALLY HELPFUL FOR DEBUGGING
    echo $ex->getData();
}

2.1 请求支付,返回的数据

> php -f first.php   // 终端执行,也可以直接访问  first.php  路由
{
    "intent": "sale",
    "payer": {
        "payment_method": "paypal"
    },
    "transactions": [
        {
            "amount": {
                "total": "1.00",
                "currency": "USD"
            },
            "related_resources": []
        }
    ],
    "redirect_urls": {
        "return_url": "https://example.com/your_redirect_url.html",
        "cancel_url": "https://example.com/your_cancel_url.html"
    },
    "id": "PAY-3MC96102SY030652JLHXXPMA",
    "state": "created",
    "create_time": "2017-10-24T17:26:07Z",
    "links": [
        {
            "href": "https://api.sandbox.paypal.com/v1/payments/payment/PAY-3MC96102SY030652JLHXXPMA",
            "rel": "self",
            "method": "GET"
        },
        {
            "href": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-1NT485541R0509947",
            "rel": "approval_url",
            "method": "REDIRECT"
        },
        {
            "href": "https://api.sandbox.paypal.com/v1/payments/payment/PAY-3MC96102SY030652JLHXXPMA/execute",
            "rel": "execute",
            "method": "POST"
        }
    ]
}
Redirect user to approval_url: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-1NT485541R0509947

3.添加请求日志

在     $payment->create($apiContext);  之前添加以下代码。必须放在 try catch  之前
$apiContext->setConfig(
    array(
        'log.LogEnabled' => true,
        'log.FileName' => 'PayPal.log',
        'log.LogLevel' => 'DEBUG',
        'mode' => 'live', // 默认是使用沙盒。开启这个,表示使用正式环境
    )
);

以下是执行结构,我吧 client 写错,会出现 ERROR 的报错

[11-07-2020 07:14:37] PayPal\Core\PayPalHttpConnection : INFO: POST https://api.sandbox.paypal.com/v1/oauth2/token
[11-07-2020 07:14:39] PayPal\Core\PayPalHttpConnection : INFO: Response Status  : 200
[11-07-2020 07:14:39] PayPal\Core\PayPalHttpConnection : INFO: POST https://api.sandbox.paypal.com/v1/payments/payment
[11-07-2020 07:14:40] PayPal\Core\PayPalHttpConnection : INFO: Response Status  : 201
[11-07-2020 07:15:58] PayPal\Core\PayPalHttpConnection : INFO: POST https://api.sandbox.paypal.com/v1/oauth2/token
[11-07-2020 07:16:00] PayPal\Core\PayPalHttpConnection : INFO: Response Status  : 401
[11-07-2020 07:16:00] PayPal\Core\PayPalHttpConnection : ERROR: Got Http response code 401 when accessing https://api.sandbox.paypal.com/v1/oauth2/token. {"error":"invalid_client","error_description":"Client Authentication failed"}

4. 同步回调

这个是按照支付流程,付款后,paypal 跳转的 url格式如下
http://pay.xxx.com/callback.php?r=index/callback&paymentId=PAYID-L4GSHBA2UL56165LM176404F&token=EC-7R537316F06356329&PayerID=HNANHU3TEQETQ
可以看到看到有 paymentId,token ,PayerID 三个参数。但是 paypal 并没有给支付是否成功的参数。以后我测试下正式环境,参数如果有变化,再做补充
如果取消,则会跳转到取消后的 url
    /**
     * 回调
     */
    public function Callback()
    {
        if ( !isset($_GET['paymentId']) && !isset($_GET['PayerID'])) {
            echo '取消付款';die;
        }

        $paymentId = trim($_GET['paymentId']);
        $PayerID = trim($_GET['PayerID']);

        if (!isset( $paymentId, $PayerID)) {
            echo '支付失败';die;
        }

        $payment = Payment::get($paymentId, $this->PayPal);
        $execute = new PaymentExecution();
        $execute->setPayerId($PayerID);

        try {
            $payment->execute($execute, $this->PayPal);
        } catch (Exception $e) {
            echo ',支付失败,支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】';die;
        }
        echo '支付成功,支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】';die;
    }

5.异步回调

这个是在后台设置的 https://developer.paypal.com/developer/applications/->My Apps & Crentials->REST API apps 中的APP name->页面的最下面选择Add Webhook->输入Webhook URL

  public function notify(){

        //获取回调结果
        $json_data = $this->get_JsonData();

        if(!empty($json_data)){
             Log::debug("paypal notify info:\r\n".json_encode($json_data));
        }else{
            Log::debug("paypal notify fail:参加为空");
        }
          //自己打印$json_data的值看有那些是你业务上用到的
          //比如我用到
          $data['invoice'] = $json_data['resource']['invoice_number'];
          $data['txn_id'] = $json_data['resource']['id'];
          $data['total'] = $json_data['resource']['amount']['total'];
          $data['status'] = isset($json_data['status'])?$json_data['status']:'';
          $data['state'] = $json_data['resource']['state'];

        try {
                 //处理相关业务
        } catch (\Exception $e) {
            //记录错误日志
            Log::error("paypal notify fail:".$e->getMessage());

            return "fail";
        }
        return "success";
    }

    public function get_JsonData(){
        $json = file_get_contents('php://input');
        if ($json) {
            $json = str_replace("'", '', $json);
            $json = json_decode($json,true);
        }
        return $json;
    }

6.沙盒测试账号 https://developer.paypal.com/developer/accounts/

图片.png
上一篇下一篇

猜你喜欢

热点阅读