【php接入PayPal】贝宝支付2020-12月版

支付逻辑简介

跟微信和支付宝支付不一样,微信和支付宝都是先走统一下单接口,然后返回创建的下单会话id等然后传给前端,贝宝支付是我们先通过API发起个支付请求,然后贝宝给我们个支付链接,前端打开我们的支付链接:例如https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-7K8740615W719670D ,然后该链接会有我们支付订单的部分信息,然后利用沙盒的账号支付确认要支付后,会返回到下单时设置的回调支付那里,如下图:

const accept_url = 'http://fumei.com:8082/service.php?action=paypal_callback&com_id=1210';//返回地址
$redirectUrls = new RedirectUrls()$redirectUrls->setReturnUrl(self::accept_url.'&orderId='.$order->orderId.'&success=true')
             ->setCancelUrl(self::accept_url.'&orderId='.$order->orderId.'&success=false');

这里回调会带着订单号和发起是否成功或者失败,如果成功,其实到这里我们并没有完成支付,只有在回调地址里才能完成payment支付,不像微信和支付宝,前端调起真实的支付,支付完毕后就要跳转前端准备的支付成功或失败的页面。

PayPal账号设置

  • 创建账号:
    创建沙盒账号 https://www.paypal.com/c2/webapps/mpp/account-selection

  • 登录沙盒后台
    https://developer.paypal.com/developer/applications/

  • 创建项目APP 查看 APPID和Secret
    在这里插入图片描述
    在这里插入图片描述

  • 设置沙盒支付测试账号,充值,创建
    在这里插入图片描述

  • 设置回调地址
    在这里插入图片描述
    代码实现

  • SDK下载

  • 引入composer 管理包或者直接下载

  • 引入文件

    use PayPal\Api\Payer;
    use PayPal\Api\Item;
    use PayPal\Api\ItemList;
    use PayPal\Api\Details;
    use PayPal\Api\Amount;
    use PayPal\Api\Transaction;
    use PayPal\Api\RedirectUrls;
    use PayPal\Api\Payment;
    use PayPal\Auth\OAuthTokenCredential;
    use PayPal\Exception\PayPalConnectionException;
    use PayPal\Rest\ApiContext;
    use PayPal\Api\PaymentExecution;
    
  • 初始化

       protected $PayPal;
    
       public function __construct()
       {
           $this->PayPal = new ApiContext(
               new OAuthTokenCredential(
                   self::clientId,
                   self::clientSecret
               )
           );
           $this->PayPal->setConfig(
               array(
                   'mode' => 'sandbox',//线上的则配置为live
                   'log.LogEnabled' => true,
                   'log.FileName' => '../PayPal.log',
                   'log.LogLevel' => 'DEBUG', // PLEASE USE `INFO` LEVEL FOR LOGGING IN LIVE ENVIRONMENTS
                   'cache.enabled' => true
               )
           );
       }
    
  • 创建支付链接(即下单接口)

    /**
        * @param
        * $product 商品
        * $price 价钱
        * $shipping 运费
        * $description 描述内容
        */
       public function pay()
       {
           global $db,$request,$comId;
           $fenbiao = getFenbiao($comId,20);
           $userId = (int)$request['user_id'];
           $oid = $request['order_id'];
           $order = $db->get_row("select * from order$fenbiao where id = $oid");
    
           $product_json = json_decode($order->product_json);
           $subject = '';
           $daizhifu = $order->price;
           $item = [];
           foreach ($product_json as $pdt) {
               $product_item = array(
                   'title' => $pdt->title,
                   'sn' => $pdt->sn,
                   'num' => (int)$pdt->num,
                   'price' => (int) $pdt->price_sale
               );
               $subject.=','.$pdt->title.'*'.$pdt->num;
           }
           $body = substr($subject,1);
           $subject = sys_substr($body,30,true);
           $subject = str_replace('_','',$subject);
           $num = (int)$order->pdtNums;
           $price = (int)$order->price;
           try {
               $payer = new Payer();
               $payer->setPaymentMethod('paypal');
               $item = new Item();
               $item->setName($product_item['title']) // 子订单的名称
               ->setDescription($product_item['sn']) // 子订单描述
               ->setCurrency(self::Currency) // 币种
               ->setQuantity($product_item['num']) // 数量
               ->setPrice($product_item['price']); // 价格
    
               $itemList = new ItemList();
               $itemList->setItems([$item]); // 设置子订单列表
    
               // 这里是设置运费等
               $details = new Details();
               $details->setShipping(0)
                   ->setSubtotal($price);
               // 设置总计费用
               $amount = new Amount();
               $amount->setCurrency(self::Currency)
                   ->setTotal($price)
                   ->setDetails($details);
               // 创建交易
               $transaction = new Transaction();
               $transaction->setAmount($amount)
                   ->setItemList($itemList)
                   ->setDescription($subject)
                   ->setInvoiceNumber($order->orderId);
               
               // 这里设置支付成功和失败后的跳转链接
               $redirectUrls = new RedirectUrls();
    
               $redirectUrls->setReturnUrl(self::accept_url.'&orderId='.$order->orderId.'&success=true')
                   ->setCancelUrl(self::accept_url.'&orderId='.$order->orderId.'&success=false');
    
               $payment = new Payment();
               $payment->setIntent('sale')
                   ->setPayer($payer)
                   ->setRedirectUrls($redirectUrls)
                   ->setTransactions([$transaction]);
    
               $payment->create($this->PayPal);
    
               // 得到支付链接
               $link = $payment->getApprovalLink();
               $return['code'] = 1;
               $return['message'] = '';
               $return['data'] = array();
               $return['data']['link'] = $link;
               return json_encode($return,JSON_UNESCAPED_UNICODE);
           } catch (HttpException $e) {
               $data = (['msg' => $e->getMessage(), 'code' => $e->getStatusCode(), 'data' => ['order' => ['no' => '1112323231']]]);
               return null;
           }
       }
    
  • 前端支付密码输入完毕后,发起支付

        /**
        * 回调
        */
       public function callback()
       {
           global $db,$request,$comId;
           $fenbiao = getFenbiao($comId,20);
           $success = trim($_GET['success']);
    
           if ($success == 'false' && !isset($_GET['paymentId']) && !isset($_GET['PayerID'])) {
               echo '取消付款';die;
           }
    
           $paymentId = trim($_GET['paymentId']);
           $PayerID = trim($_GET['PayerID']);
           $orderId = trim($_GET['orderId']);
    
           if (!isset($success, $paymentId, $PayerID)) {
               echo '支付失败';die;
           }
    
           if ((bool)$_GET['success'] === 'false') {
               echo  '支付失败,支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】';die;
           }
    
           $payment = Payment::get($paymentId, $this->PayPal);
    
           $execute = new PaymentExecution();
    
           $execute->setPayerId($PayerID);
    
           try {
               $payment->execute($execute, $this->PayPal);
               //todo 记录
               $db->query("update order10 set paypal_no = '$paymentId', paypal_payerId ='$PayerID' where orderId = '$orderId'");
               //todo 直接跳转前端页面
               $url = '';
               header("localtion:$url");
           } catch (Exception $e) {
               echo ',支付失败,支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】';die;
           }
           echo '支付成功,支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】';die;
       }
    
  • 支付后台回调,更改订单状态等

       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;
       }
    
  • 退款

     /**
        *
        * 根据异步回调的txn_id进行退款操作
        * @param Order $order
        * @return mixed
        */
       public function payPalRefundForTxnId()
       {
           try {
               $txn_id = ‘这个值在回调的时候获取到’;
               $apiContext = new ApiContext(
                   new OAuthTokenCredential(
                       ‘client_id’,
                       ‘client_secret’
                   ));  // 这里是我们第一步拿到的数据
               // $apiContext->setConfig(['mode' => 'live']);  // live下设置
    
               $amt = new Amount();
               $amt->setCurrency('USD')
                   ->setTotal(100);  // 退款的费用
    
               $refund = new Refund();
               $refund->setAmount($amt);
    
               $sale = new Sale();
               $sale->setId($txn_id);
               $refundedSale = $sale->refund($refund, $apiContext);
    
           } catch (\Exception $e) {
               // PayPal无效退款
               return json_decode(json_encode(['message' => $e->getMessage(), 'code' => $e->getCode(), 'state' => $e->getMessage()]));  // to object
           }
          // 退款完成
           return $refundedSale; 
       }
    
  • 代码总:

    namespace Zhishang;
    
    use PayPal\Api\Payer;
    use PayPal\Api\Item;
    use PayPal\Api\ItemList;
    use PayPal\Api\Details;
    use PayPal\Api\Amount;
    use PayPal\Api\Transaction;
    use PayPal\Api\RedirectUrls;
    use PayPal\Api\Payment;
    use PayPal\Auth\OAuthTokenCredential;
    use PayPal\Exception\PayPalConnectionException;
    use PayPal\Rest\ApiContext;
    use PayPal\Api\PaymentExecution;
    
    class Paypal{
        const clientId = 'AV-SNw2j-1wNqAb1ygg0I4iKT8E8zHT1QCh8eLEbeFZQN2slHhq4dX5pKn4mfz7CHGDhCaVX1N';//ID
        const clientSecret = 'EHjumNJEwf5lkurMyNqo1DJ1v64jsZ9mpFYlKIkVQBh6Kksygxx_u77F8G0rSQHW9Awezdqd4RCd';//秘钥
        const accept_url = 'http://fumei.com:8082/service.php?action=paypal_callback&com_id=1210';//返回地址
        const Currency = 'USD';//币种
        protected $PayPal;
    
        public function __construct()
        {
            $this->PayPal = new ApiContext(
                new OAuthTokenCredential(
                    self::clientId,
                    self::clientSecret
                )
            );
            //如果是沙盒测试环境不设置,请注释掉
    //        $this->paypal->setConfig(
    //            array(
    //                'mode' => 'sandbox',
    //            )
    //        );
    
    //        $this->PayPal->setConfig([
    //            'mode' => 'sandbox',
    //            'log.LogEnabled' => true,
    //            'log.FileName' => 'logs/PayPal.log',
    //            'log.LogLevel' => 'DEBUG', // PLEASE USE `INFO` LEVEL FOR LOGGING IN LIVE ENVIRONMENTS
    //            'cache.enabled' => true,
    //        ]);
            $this->PayPal->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
                )
            );
        }
    
        /**
         * @param
         * $product 商品
         * $price 价钱
         * $shipping 运费
         * $description 描述内容
         */
        public function pay()
        {
            global $db,$request,$comId;
            $fenbiao = getFenbiao($comId,20);
            $userId = (int)$request['user_id'];
            $oid = $request['order_id'];
            $order = $db->get_row("select * from order$fenbiao where id = $oid");
    
            $product_json = json_decode($order->product_json);
            $subject = '';
            $daizhifu = $order->price;
            $item = [];
            foreach ($product_json as $pdt) {
                $product_item = array(
                    'title' => $pdt->title,
                    'sn' => $pdt->sn,
                    'num' => (int)$pdt->num,
                    'price' => (int) $pdt->price_sale
                );
                $subject.=','.$pdt->title.'*'.$pdt->num;
            }
            $body = substr($subject,1);
            $subject = sys_substr($body,30,true);
            $subject = str_replace('_','',$subject);
            $num = (int)$order->pdtNums;
            $price = (int)$order->price;
            try {
                $payer = new Payer();
                $payer->setPaymentMethod('paypal');
                $item = new Item();
                $item->setName($product_item['title']) // 子订单的名称
                ->setDescription($product_item['sn']) // 子订单描述
                ->setCurrency(self::Currency) // 币种
                ->setQuantity($product_item['num']) // 数量
                ->setPrice($product_item['price']); // 价格
    
                $itemList = new ItemList();
                $itemList->setItems([$item]); // 设置子订单列表
    
                // 这里是设置运费等
                $details = new Details();
                $details->setShipping(0)
                    ->setSubtotal($price);
                // 设置总计费用
                $amount = new Amount();
                $amount->setCurrency(self::Currency)
                    ->setTotal($price)
                    ->setDetails($details);
                // 创建交易
                $transaction = new Transaction();
                $transaction->setAmount($amount)
                    ->setItemList($itemList)
                    ->setDescription($subject)
                    ->setInvoiceNumber($order->orderId);
                
                // 这里设置支付成功和失败后的跳转链接
                $redirectUrls = new RedirectUrls();
    
                $redirectUrls->setReturnUrl(self::accept_url.'&orderId='.$order->orderId.'&success=true')
                    ->setCancelUrl(self::accept_url.'&orderId='.$order->orderId.'&success=false');
    
                $payment = new Payment();
                $payment->setIntent('sale')
                    ->setPayer($payer)
                    ->setRedirectUrls($redirectUrls)
                    ->setTransactions([$transaction]);
    
                $payment->create($this->PayPal);
    
                // 得到支付链接
                $link = $payment->getApprovalLink();
                $return['code'] = 1;
                $return['message'] = '';
                $return['data'] = array();
                $return['data']['link'] = $link;
                return json_encode($return,JSON_UNESCAPED_UNICODE);
            } catch (HttpException $e) {
                $data = (['msg' => $e->getMessage(), 'code' => $e->getStatusCode(), 'data' => ['order' => ['no' => '1112323231']]]);
                return null;
            }
        }
    
        /**
         * 回调
         */
        public function callback()
        {
            global $db,$request,$comId;
            $fenbiao = getFenbiao($comId,20);
            $success = trim($_GET['success']);
    
            if ($success == 'false' && !isset($_GET['paymentId']) && !isset($_GET['PayerID'])) {
                echo '取消付款';die;
            }
    
            $paymentId = trim($_GET['paymentId']);
            $PayerID = trim($_GET['PayerID']);
            $orderId = trim($_GET['orderId']);
    
            if (!isset($success, $paymentId, $PayerID)) {
                echo '支付失败';die;
            }
    
            if ((bool)$_GET['success'] === 'false') {
                echo  '支付失败,支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】';die;
            }
    
            $payment = Payment::get($paymentId, $this->PayPal);
    
            $execute = new PaymentExecution();
    
            $execute->setPayerId($PayerID);
    
            try {
                $payment->execute($execute, $this->PayPal);
                //todo 记录
                $db->query("update order10 set paypal_no = '$paymentId', paypal_payerId ='$PayerID' where orderId = '$orderId'");
            } catch (Exception $e) {
                echo ',支付失败,支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】';die;
            }
            echo '支付成功,支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】';die;
        }
    
        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;
        }
    }
    

注意事项:

  • 正式站:当你切换到正式环境去测试支付的时候不要拿0.1美元去做测试,因为你的支付完毕之后,他在商户管理那边不会显示,可能是因为手续费等不知名问题,请尝试1美元。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在中国文化中, "c" 不再只是代表字母表中的第三个字母,也有其他不同的意思。 首先, "c" 可能代表"中国"或"中国人"。"C国"用来简称中国,常在网络上使用。例如,"C国队员"指中国国家队队员。"C族"则是指中国人。 另外, "c" 也可能表示某种程度上的夸张和夸大。这个用法源自互联网上的网络用语和流行语。例如,有时人们会用"c位出道",意味着某人以独特的方式出现并获得关注。 此外, "c" 还可以代表"萌"。"萌"是一种形容可爱、可人的感觉,经常与动物、动漫和娃娃等有关。例如,"c女郎" 代表着可爱的女孩,"c妹" 则指一个可爱的女生。 总之,"c" 在中国文化中已经拥有了新的含义。不仅仅是字母表中的字母,它也代表着中国或中国人,同时也有着夸张和夸大的意味以及表示可爱的含义。 ### 回答2: 这是一个非常简洁的问题,因此我会用同样简洁的回答来回答: C是英文字母表的第三个字母。 它在英语中经常被用作一个标识符,例如在编程语言中。C还可以代表一些其他的概念,例如在音乐中代表一个升高半音的标志。在一些领域中,C也可以代表某种形象,例如在贝宝公司的标志中。总的来说,C是一个广泛使用的字母,具有许多不同的含义和应用。 ### 回答3: c 是英文字母中的第三个字母,也是拉丁字母表中常见的字母之一。它在26个字母中的位置使得它在很多场合被用作代表数字三。例如,罗马数字中的C代表数字100。 此外,C也是许多单词的首字母,具有多种含义和用法。例如,C可以代表“中文”,这是我母语使用的语言,拥有丰富的文化和词汇。C也可以代表“酷”,这是一种形容词,用来形容某人或某事物非常令人印象深刻、出色或令人羡慕的。 在科学中,C也代表一些重要的概念,比如光速。光速(C)是一个物理学中的常数,代表光在真空中传播的速度,被定义为每秒299,792,458米。这个常数在相对论中起着重要的作用,对于测量距离和时间的标准也有很大的影响。 总之,C是一个具有多个意义和用途的字母。无论在数学、语言、科学还是文化中,C都扮演着重要的角色,并且在日常生活中也经常出现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值