jiafeimao-dabai

 

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 = "支付回调信息:\r\n";
            foreach ($_POST as $key => $value) {
                $notify_str.=$key."=".$value.";\r\n";
            }
        }
        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\')."\r\n".$msg."\r\n---------------------------------------------------------------\r\n", 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 app\api\controller;
require \'../extend/PayPal/autoload.php\';
use app\api\controller\Common;
use app\api\controller\Order;
use think\db;
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\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Api\ExecutePayment;
use PayPal\Api\PaymentExecution;


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 \PayPal\Rest\ApiContext(
          new \PayPal\Auth\OAuthTokenCredential(
            \'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 (PayPal\Exception\PayPalConnectionException $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 (PayPal\Exception\PayPalConnectionException $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:\r\n".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回调结果\';

 

分类:

技术点:

相关文章: