zoukankan      html  css  js  c++  java
  • php PayPal 支付/回调

     

    paypal开发者账号申请地址

    https://developer.paypal.com/

    创建开发者账号后有一个买家账号 一个卖家账号 就可以测试paypal支付了

     支付方式一:

    paypal支付页面

    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Paypal订单支付</title>
    </head>
    <body>
    <form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="POST"  name="form_starPay"> <!-- // Live https://www.paypal.com/cgi-bin/webscr -->
        <input type='hidden' name='cmd' value='_xclick'>  <!-- //告诉paypal该表单是立即购买 -->
        <input type='hidden' name='business' value='test-facilitator@test.com'> <!-- //卖家帐号 也就是收钱的帐号 -->
        <input type='hidden' name='item_name' value='支付订单:20180828080706000039'> <!-- //商品名称 item_number -->
        <input type='hidden' name='item_number' value='20180828080706000039'> <!-- //物品号 item_number -->
        <input type='hidden' name='amount' value='0.01'> <!-- .// 订单金额 -->
        <input type='hidden' name='currency_code' value='HKD'> <!-- .// 货币 -->
        <input type='hidden' name='return' value='http://test.cq.com/'> <!-- .// 支付成功后网页跳转地址 -->
        <input type='hidden' name='notify_url' value='https://www.test.net/api/order/notify'> <!-- .//支付成功后paypal后台发送订单通知地址 -->
        <input type='hidden' name='cancel_return' value='http://test.cq.com/'> <!-- .//用户取消交易返回地址 -->
        <input type='hidden' name='invoice' value='20180828080706000039'> <!-- .//自定义订单号 -->
        <input type='hidden' name='charset' value='utf-8'> <!-- .// 字符集 -->
        <input type='hidden' name='no_shipping' value='1'> <!-- .// 不要求客户提供收货地址 -->
        <input type='hidden' name='no_note' value='1'> <!-- .// 付款说明 -->
        <input type='hidden' name='rm' value='2'> <!-- 不知道是什么 -->
        <input type="image" name="submit"   src="https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif" />
    </form>
    正在跳转Paypal支付,请稍等。。。
    <script>
        function sub(){
            document.form_starPay.submit();
        }
        onload(sub())
    </script>
    </body>
    </html>

    支付回调,并进行ipn验证 将回调字段添加上$data['cmd'] = '_notify-validate';返回进行验证

      /**
         * 支付回调函数
         * @author gyj <375023402@qq.com>
         * @createtime 2018-08-24T11:38:23+0800
         * @return     
         */
        public function notify(){
            if(!$this->request->isPost()) die();
    
            //记录支付回调信息
            if(!empty($_POST)){
                    $notify_str = "支付回调信息:
    ";
                foreach ($_POST as $key => $value) {
                    $notify_str.=$key."=".$value.";
    ";
                }
            }
            log_result($notify_str,"paypal");
    
            //ipn验证
            $data = $_POST;
            $data['cmd'] = '_notify-validate';
            $url = config('paypal.gateway');//支付异步验证地址
            $res = https_request($url,$data);
            //记录支付ipn验证回调信息
            log_result($res,'paypal');
            
            if (!empty($res)) {
                if (strcmp($res, "VERIFIED") == 0) {
    
                    if ($_POST['payment_status'] == 'Completed' || $_POST['payment_status'] == 'Pending') {
                        //付款完成,这里修改订单状态
                        $order_res = $this->order_pay($_POST);
                        if(!$order_res){
                            log_result('update order result fail','paypal');
                        }
                        return 'success';
                    }
                } elseif (strcmp($res, "INVALID") == 0) {
                    //未通过认证,有可能是编码错误或非法的 POST 信息
                    return 'fail';
                }
            } else {
                //未通过认证,有可能是编码错误或非法的 POST 信息
    
                return 'fail';
    
            }
            return 'fail';
        }

    附上log_result函数 和https_result函数

    log_result函数:

    /**
    * 记录自定义日志
    * @author gyj  <375023402@qq.com>
    * @createtime 2018-08-24 14:12:01
    * @param $msg 错误信息
    * @param $type 写入类型 wechat aliyun
    * @return [type] [description]
    */
    if(!function_exists('log_result')){
      function log_result($msg='',$type='normal')
      {
        $dir = dirname(LOG_PATH)."/log/".$type."/";
        if(!is_dir($dir)){
            mkdir($dir,0777);
        }
        $dir .= date('Ym')."/";
        $file = $dir.date('d').".log";
        if(!is_dir($dir)){
            mkdir($dir,0777);
        }
        file_put_contents($file,date('Y-m-d H:i:s')."
    ".$msg."
    ---------------------------------------------------------------
    ", FILE_APPEND);
      }
      
    }

    https_result函数:

    /**
     * 发送post请求
     * @author ganyuanjiang  <3164145970@qq.com>
     * @createtime 2017-07-26 14:06:04
     * @param string $url 请求地址
     * @param array $post_data post键值对数据
     * @return string
     */
    if (!function_exists('https_request')) {
        
      function https_request($url,$data=null){
        header("Content-type: text/html; charset=utf-8");
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $tmpInfo = curl_exec($ch);
        if (curl_errno($ch)) {
          return curl_error($ch);
        }
    
        curl_close($ch);
        return $tmpInfo;
    
      }
    }

    附上paypal支付记录表:

    /*
    Navicat MySQL Data Transfer
    
    Source Server         : localhost
    Source Server Version : 50553
    Source Host           : localhost:3306
    Source Database       : museum
    
    Target Server Type    : MYSQL
    Target Server Version : 50553
    File Encoding         : 65001
    
    Date: 2018-08-30 17:44:49
    */
    
    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for yu_paypal
    -- ----------------------------
    DROP TABLE IF EXISTS `yu_paypal`;
    CREATE TABLE `yu_paypal` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增编号',
      `cmd` char(20) NOT NULL DEFAULT '' COMMENT '购物车系统',
      `amount` decimal(11,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '订单支付金额',
      `currency_code` char(10) NOT NULL DEFAULT '' COMMENT '货币类型',
      `return` varchar(255) NOT NULL DEFAULT '' COMMENT '支付成功跳转页面',
      `no_shipping` char(5) CHARACTER SET utf8mb4 NOT NULL DEFAULT '',
      `no_note` char(5) NOT NULL DEFAULT '',
      `cancel_return` varchar(255) NOT NULL DEFAULT '' COMMENT '订单取消支付跳转链接',
      `notify_url` varchar(255) NOT NULL DEFAULT '' COMMENT '支付回调',
      `rm` char(5) NOT NULL DEFAULT '',
      `transaction_subject` varchar(255) NOT NULL DEFAULT '' COMMENT '交易主体',
      `txn_type` char(50) NOT NULL DEFAULT '' COMMENT '类型',
      `payment_date` char(50) NOT NULL DEFAULT '' COMMENT '支付时间',
      `first_name` char(50) NOT NULL DEFAULT '' COMMENT '',
      `last_name` char(50) NOT NULL DEFAULT '' COMMENT '',
      `residence_country` char(20) NOT NULL DEFAULT '' COMMENT '居住国家',
      `pending_reason` varchar(255) NOT NULL DEFAULT '' COMMENT '支付原因',
      `item_name` varchar(255) NOT NULL DEFAULT '' COMMENT '支付商品名称',
      `payment_gross` decimal(11,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '支付总额',
      `mc_currency` char(20) NOT NULL DEFAULT '' COMMENT '返回货币类型',
      `business` char(100) NOT NULL DEFAULT '' COMMENT 'paypal商家账号',
      `payment_type` char(20) NOT NULL DEFAULT '' COMMENT '支付类型',
      `protection_eligibility` char(100) NOT NULL DEFAULT '' COMMENT '保护资质',
      `verify_sign` varchar(255) NOT NULL DEFAULT '' COMMENT '验证字符串',
      `payer_status` char(50) NOT NULL DEFAULT '' COMMENT '付款人状态',
      `test_ipn` char(20) NOT NULL DEFAULT '' COMMENT '测试穿透网络',
      `payer_email` varchar(255) NOT NULL DEFAULT '' COMMENT '支付者账号',
      `txn_id` char(50) NOT NULL DEFAULT '' COMMENT 'txn编号',
      `quantity` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '数量',
      `receiver_email` char(100) NOT NULL DEFAULT '' COMMENT '收款账号',
      `invoice` char(20) NOT NULL DEFAULT '' COMMENT '订单号',
      `payer_id` char(50) NOT NULL DEFAULT '' COMMENT '付款人编号',
      `receiver_id` char(50) NOT NULL DEFAULT '' COMMENT '收款人编号',
      `item_number` char(50) NOT NULL DEFAULT '' COMMENT '物品号',
      `payment_status` char(100) NOT NULL DEFAULT '' COMMENT '支付状态',
      `mc_gross` decimal(11,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '订单金额',
      `custom` varchar(255) NOT NULL DEFAULT '' COMMENT '客户',
      `charset` char(10) NOT NULL DEFAULT '' COMMENT '编码',
      `notify_version` char(5) NOT NULL DEFAULT '' COMMENT '支付回调版本',
      `ipn_track_id` char(20) NOT NULL DEFAULT '' COMMENT 'ipn追踪编号',
      `payment_fee` char(50) NOT NULL DEFAULT '' COMMENT '支付金额',
      `mc_fee` decimal(11,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '交易金额',
      `create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
      `update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='paypal支付表';

     支付方式二:

    1.引入官方demo 

    2.配置

    登入paypal 开发者管理 找到client id 和secret

    回调地址配置

    <?php
    // +----------------------------------------------------------------------
    // | PAYPAL[ PAYPAL ]
    // +----------------------------------------------------------------------
    // | Copyright (c) 2018 https://www.cq.com All rights reserved.
    // +----------------------------------------------------------------------
    // | Base on ( ThinkPHP 5.0 http://thinkphp.cn)
    // +----------------------------------------------------------------------
    // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
    // +----------------------------------------------------------------------
    // | Author: gyj <375023402@qq.com>
    // +----------------------------------------------------------------------
    // | CreateTime: 2018-09-13 15:34:49
    // +----------------------------------------------------------------------
    namespace appapicontroller;
    require '../extend/PayPal/autoload.php';
    use appapicontrollerCommon;
    use appapicontrollerOrder;
    use thinkdb;
    use PayPalApiAmount;
    use PayPalApiDetails;
    use PayPalApiItem;
    use PayPalApiItemList;
    use PayPalApiPayer;
    use PayPalApiPayment;
    use PayPalApiRedirectUrls;
    use PayPalApiTransaction;
    use PayPalApiExecutePayment;
    use PayPalApiPaymentExecution;
    
    
    class Paypal extends Common {
    
        /**
         * 初始化
         * @author gyj <375023402@qq.com>
         * @createtime 2018-09-13T15:38:07+0800
         * @return     
         */
        public function _initialize(){
           
            // Autoload SDK package for composer based installations
            $this->apiContext = new PayPalRestApiContext(
              new PayPalAuthOAuthTokenCredential(
                'Client ID', 
                'Secret'
              )
            );
        }
    
        /**
         * 创建paypal支付订单
         * @author gyj <375023402@qq.com>
         * @createtime 2018-09-13T15:43:35+0800
         * @return     
         */
        public function pay($order_no='',$pay=0){
            
            //parameters validate
            if (empty($order_no) || empty($pay)) {
                $this->error('Lack of parameters of order_no or pay');
            }
    
            // Create new payer and method
            $payer = new Payer();
            $payer->setPaymentMethod("paypal");
    
            // Set redirect URLs
            $redirectUrls = new RedirectUrls();
            $redirectUrls->setReturnUrl(config('paypal.return'))
              ->setCancelUrl(config('paypal.cancel_return'));
    
            // Set payment amount
            $amount = new Amount();
            $amount->setCurrency(config('paypal.currency_code'))
              ->setTotal($pay);
    
            // Set transaction object
            $transaction = new Transaction();
            $transaction->setAmount($amount)
              ->setDescription("yucolab order pay,order_no:".$order_no)
              ->setInvoiceNumber($order_no);
    
            // Create the full payment object
            $payment = new Payment();
            $payment->setIntent('sale')
              ->setPayer($payer)
              ->setRedirectUrls($redirectUrls)
              ->setTransactions(array($transaction));
    
            // Create payment with valid API context
            try {
                $payment->create($this->apiContext);
    
                // Get PayPal redirect URL and redirect the customer
                 $approvalUrl = $payment->getApprovalLink();
    
              // Redirect the customer to $approvalUrl
            } catch (PayPalExceptionPayPalConnectionException $ex) {
                echo $ex->getCode();
                echo $ex->getData();
                die($ex);
            } catch (Exception $ex) {
                die($ex);
            }
    
            $this->redirect($approvalUrl);
        }
    
        /**
         * 支付提交
         * @author gyj <375023402@qq.com>
         * @createtime 2018-09-13T15:44:15+0800
         * @return     
         */
        public function execute(){
            // Get payment object by passing paymentId
            $paymentId = $_GET['paymentId'];
            $payment = Payment::get($paymentId, $this->apiContext);
            $payerId = $_GET['PayerID'];
    
            // Execute payment with payer ID
            $execution = new PaymentExecution();
            $execution->setPayerId($payerId);
    
            try {
              // Execute payment
              $result = $payment->execute($execution, $this->apiContext);
            } catch (PayPalExceptionPayPalConnectionException $ex) {
              echo $ex->getCode();
              echo $ex->getData();
              die($ex);
            } catch (Exception $ex) {
              die($ex);
            }
            //success page 
            $this->redirect(config('paypal.success_url'));
        }
    
        /**
         * 取消支付
         * @author gyj <375023402@qq.com>
         * @createtime 2018-09-13T16:00:31+0800
         * @return     
         */
        public function cancel(){
            //cancel page 
            $this->redirect(config('paypal.cancel_url'));
        }
    
        /**
         * 回调函数
         * @author gyj <375023402@qq.com>
         * @createtime 2018-09-14T16:38:20+0800
         * @return   
         */
        public function notify(){
          
            if(!$this->request->isPost()) die();
    
            //获取回调结果
            $json_data = get_JsonData();
    
            if(!empty($json_data)){
                log_result("paypal notify info:
    ".json_encode($json_data),"paypal");
            }
    
            //组装支付回调信息
            $data['invoice'] = $json_data['resource']['invoice_number'];
            $data['txn_id'] = $json_data['id'];
            $data['total'] = $json_data['resource']['amount']['total'];
            $data['status'] = $json_data['status']?$json_data['status']:'';
            $data['state'] = $json_data['resource']['state'];
            $data['result'] = json_encode($json_data);
            $data['create_time'] = time();
    
            try {
              //查询订单信息
              $where_order['status'] = 0;
              $where_order['order_no'] = $data['invoice'];
              $order_info = db('order')->where($where_order)->find();
              if(!$order_info){
                throw new Exception("no pay order not find,order_no:".$data['invoice']." ");
              }
              if($order_info['pay'] != $data['total']){
                $is_eq = ($order_info['pay'] == $data['total'])?"yes":"no";
                throw new Exception("order pay neq paypal total:order_info=".$order_info['pay']."&paypal total=".$data['total']."&result=".$is_eq);
              }
              
              //数据库记录支付回调信息
              $res = db('paypal')->insert($data);
              if(!$res){
                throw new Exception("Payment callback:Update paypal payment information failed-update fail");
              }
              //判断支付结果,如果支付完成 修改订单状态
              if($json_data['resource']['state'] == 'completed'){
                  //订单状态修改
                  $order = new Order();
                  $order->pay($data);
              }
    
            } catch (Exception $e) {
              //记录错误日志
              log_result("paypal notify fail:".$e->getMessage(),"paypal");
              return "fail";
            }
            return "success";
        }
    
    } 

    回调返回json

    {
    "id": "WH-35K39776SH675420T-56W661149E290963N",
    "event_version": "1.0",
    "create_time": "2018-09-14T10:49:03.910Z",
    "resource_type": "sale",
    "event_type": "PAYMENT.SALE.COMPLETED",
    "summary": "Payment completed for HKD 66.0 HKD",
    "resource": {
    "id": "16R917890C546780W",
    "state": "completed",
    "amount": {
    "total": "66.00",
    "currency": "HKD",
    "details": {
    "subtotal": "66.00"
    }
    },
    "payment_mode": "INSTANT_TRANSFER",
    "protection_eligibility": "ELIGIBLE",
    "protection_eligibility_type": "ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE",
    "transaction_fee": {
    "value": "4.59",
    "currency": "HKD"
    },
    "invoice_number": "20180914172359000001",
    "parent_payment": "PAY-4DS45691CB844050NLONZD2Y",
    "create_time": "2018-09-14T10:48:42Z",
    "update_time": "2018-09-14T10:48:42Z",
    "links": [
    {
    "href": "https://api.sandbox.paypal.com/v1/payments/sale/16R917890C546780W",
    "rel": "self",
    "method": "GET"
    },
    {
    "href": "https://api.sandbox.paypal.com/v1/payments/sale/16R917890C546780W/refund",
    "rel": "refund",
    "method": "POST"
    },
    {
    "href": "https://api.sandbox.paypal.com/v1/payments/payment/PAY-4DS45691CB844050NLONZD2Y",
    "rel": "parent_payment",
    "method": "GET"
    }
    ]
    },
    "links": [
    {
    "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-35K39776SH675420T-56W661149E290963N",
    "rel": "self",
    "method": "GET"
    },
    {
    "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-35K39776SH675420T-56W661149E290963N/resend",
    "rel": "resend",
    "method": "POST"
    }
    ]
    }

     附上函数:

    获取json数据转换成数组

    /**获取json数据
     * @param $uid 用户主键id
     * @param $salt 用户盐值
     * @return string token字符串
     */
    function get_JsonData(){
        $json = file_get_contents('php://input');
        if ($json) {
            $json = str_replace("'", '', $json);
            $json = json_decode($json,true);
        }
        return $json;
    }

    paypal数据库

    /*
    Navicat MySQL Data Transfer
    
    Source Server         : 127.0.0.1
    Source Server Version : 50553
    Source Host           : 127.0.0.1:3306
    Source Database       : museum
    
    Target Server Type    : MYSQL
    Target Server Version : 50553
    File Encoding         : 65001
    
    Date: 2018-09-17 11:22:29
    */
    
    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for yu_paypal
    -- ----------------------------
    DROP TABLE IF EXISTS `yu_paypal`;
    CREATE TABLE `yu_paypal` (
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增编号',
      `invoice` char(20) NOT NULL DEFAULT '' COMMENT '订单号',
      `txn_id` char(100) NOT NULL DEFAULT '' COMMENT '回调编号',
      `total` decimal(11,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '支付金额',
      `status` char(50) NOT NULL DEFAULT '' COMMENT '请求状态',
      `state` char(50) NOT NULL DEFAULT '' COMMENT '支付状态',
      `result` text NOT NULL COMMENT '回调结果',
      `create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='paypal回调结果';
  • 相关阅读:
    用错每日活跃用户(DAU)这个指标,无异于挖坑给自己跳
    自我修复型设计-常用的架构设计原则
    UParams
    nodejs的使用场景
    问题
    GitHub Copilot可对整行或全部代码给出AI分析建
    Your AI pair programmer
    飞冰React框架如何配置懒加载
    【630】keras 实现多输出模型
    【629】图像增强(imgaug 包)
  • 原文地址:https://www.cnblogs.com/jiafeimao-dabai/p/9561763.html
Copyright © 2011-2022 走看看