paypal支付接口准备工作

  • 首先去申请一个paypal账号,https://www.paypal.com/
  • 申请完毕并登录,进入https://developer.paypal.com/developer/accounts/。即可看到你申请账号自动配属的两个测试账号,账号类别分别是:BUSINESS和PERSONAL,PERSONAL的账号里面有$9999,测试费用,表激动。
  • 下面去给两个账号设置密码,点击账号展开,然后点击Profile,会弹出账号信息框,里面可以设置密码等一堆属性。如果点击账号始终无法展开,请吐槽下paypal,然后F5再点。
  • 下面进入https://developer.paypal.com/developer/applications/申请APP,点击REST API apps栏目下面的Create App按钮,写进一个APP名称,然后选择一个测试账户作为此APP绑定的账号,如果你在上一步没有申请新的测试账号,那么这里默认就是选择了BUSINESS账号。
  • 然后打开创建的APP,可以看到APP的clientId和clientSecret。
  • paypal的测试环境域名为sandbox.paypal.com,正式域名为www.paypal.com。一下测试均为测试环境。

至此准备工作差不多了,开始动代码。

PayPal-PHP-SDK下载

我比较推荐composer  毕竟是个神器

composer require paypal/rest-api-sdk-php

默认是下载最新版本的包

此时项目的目录结构如下图:

PayPal Payments的逻辑大致如下:

  • 创建一个支付,发送到paypal服务端
  • paypal服务端返回一个用户授权地址
  • 转链到用户授权地址,用户授权
  • 用户授权完毕,paypal返回到客户端设置的execute地址,付款实现。

实现如下:

一、支付类的引入

use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Api\ShippingAddress;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Rest\ApiContext;

二、配置数据

    // 下面为申请app获得的clientId和clientSecret,必填项,否则无法生成token
    protected $clientId = 'AcNeLwCIjMLv6yqXxT9UPbQ**********5-yAO8-mhPp4ssys9D01qz';
    protected $clientSecret = 'EGODX7jzbBx25psLCLK*********vh84T9ztZDyPRP7T8Wl4aeOnUUNMY_WwrXyyTAi5fWWZ';

初始化支付配置数据

public function __construct()
    {
        $this->apiContext = new ApiContext(
            new OAuthTokenCredential(
                $this->clientId,
                $this->clientSecret
            )
        );
        $this->apiContext->setConfig(
            array(
                'mode' => 'sandbox',
                'log.LogEnabled' => true,
                'log.FileName' => '../PayPal.log',
                'log.LogLevel' => 'DEBUG', // PLEASE USE `INFO` LEVEL FOR LOGGING IN LIVE ENVIRONMENTS
                'cache.enabled' => true,
                // 'http.CURLOPT_CONNECTTIMEOUT' => 30
                // 'http.headers.PayPal-Partner-Attribution-Id' => '123123123'
                //'log.AdapterFactory' => '\PayPal\Log\DefaultLogFactory' // Factory class implementing \PayPal\Log\PayPalLogFactory
            )
        );

三、支付方法编写

/**
     * 发起支付请求
     * @author 勇敢的小笨羊
     */
    public function pay(){
        // ### Payer
        $payer = new Payer();
        $payer->setPaymentMethod("paypal");

        // ### Itemized information
        $item1 = new Item();
        $item1->setName('test pro 1')
            ->setCurrency('USD')
            ->setQuantity(1)
            ->setSku("testpro1_01") // Similar to `item_number` in Classic API
            ->setPrice(20);
        $item2 = new Item();
        $item2->setName('test pro 2')
            ->setCurrency('USD')
            ->setQuantity(5)
            ->setSku("testpro2_01") // Similar to `item_number` in Classic API
            ->setPrice(10);

        $itemList = new ItemList();
        $itemList->setItems(array($item1, $item2));

        // 自定义用户收货地址,避免用户在paypal上账单的收货地址和销售方收货地址有出入
        // 这里定义了收货地址,用户在支付过程中就不能更改收货地址,否则,用户可以自己更改收货地址
        $address = new ShippingAddress();
        $address->setRecipientName('什么名字')
            ->setLine1('什么街什么路什么小区')
            ->setLine2('什么单元什么号')
            ->setCity('城市名')
            ->setState('浙江省')
            ->setPhone('12345678911')
            ->setPostalCode('12345')
            ->setCountryCode('CN');

        $itemList->setShippingAddress($address);


        // ### Additional payment details
        $details = new Details();
        $details->setShipping(5)
            ->setTax(10)
            ->setSubtotal(70);

        // ### Amount
        $amount = new Amount();
        $amount->setCurrency("USD")
            ->setTotal(100) //设置金额
            ->setDetails($details);

        // ### Transaction
        $transaction = new Transaction();
        $transaction->setAmount($amount)
            ->setItemList($itemList)
            ->setDescription("Payment description")
            ->setInvoiceNumber(uniqid());

        // ### Redirect urls
        $redirectUrls = new RedirectUrls();
        $redirectUrls->setReturnUrl( $this->getBaseUrl()."/exec.php?success=true") //支付成功跳转
                     ->setCancelUrl( $this->getBaseUrl()."/cancel.php?success=false"); //取消支付返回

        // ### Payment
        $payment = new Payment();
        $payment->setIntent("sale")
            ->setPayer($payer)
            ->setRedirectUrls($redirectUrls)
            ->setTransactions(array($transaction));

        $payment->create($this->apiContext);

        $approvalUrl = $payment->getApprovalLink();
        // 打印出用户授权地址,这里仅仅实现支付过程,流程没有进一步完善。
        halt($approvalUrl);
    }

    /**
     * ### getBaseUrl function
     * // utility function that returns base url for
     * // determining return/cancel urls
     *
     * @return string
     */
    function getBaseUrl()
    {
        if (PHP_SAPI == 'cli') {
            $trace=debug_backtrace();
            $relativePath = substr(dirname($trace[0]['file']), strlen(dirname(dirname(__FILE__))));
            echo "Warning: This sample may require a server to handle return URL. Cannot execute in command line. Defaulting URL to http://localhost$relativePath \n";
            return "http://localhost" . $relativePath;
        }
        $protocol = 'http';
        if ($_SERVER['SERVER_PORT'] == 443 || (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on')) {
            $protocol .= 's';
        }
        $host = $_SERVER['HTTP_HOST'];
        $request = $_SERVER['PHP_SELF'];
        return dirname($protocol . '://' . $host . $request);
    }

以上就是简单的向paypal获取到了支付申请地址,如下图: