paypal支付接口准备工作
至此准备工作差不多了,开始动代码。
PayPal-PHP-SDK下载
{
"require" : {
"paypal/rest-api-sdk-php" : "1.7.4"
},
"repositories": {
"packagist": {
"type": "composer",
"url": "https://packagist.phpcomposer.com"
} }}切换至项目目录并执行composer install,PayPal-PHP-SDK安装完毕。
因为PayPal-PHP-SDK里面的composer.json里面的require有psr/log,所以在在目录vendor下有三个文件夹:composer,paypal和psr。
此时项目的目录结构如下,其中的app文件夹是下面实例化创建的文件夹。

PayPal-PHP-SDK支付接口测试
然后就简单了,PayPal-PHP-SDK里面有一个sample项目,里面有各种实例。
打开浏览器,输入http://~/rest-api-sdk-php/sample/index.php,“~”符号改为你自己的路径。
可以看到sample了,如下图:
图中的PayPal Payments - similar to Express Checkout in Classic APIs即为支付接口,对应的代码路径为~/rest-api-sdk-php/sample/payments/CreatePaymentUsingPayPal.php。
PayPal Payments的逻辑大致如下:
实现如下:
~/rest-api-sdk-php/sample/payments/CreatePaymentUsingPayPal.php有如下代码
// ### Get redirect url// The API response provides the url that you must redirect// the buyer to. Retrieve the url from the $payment->getApprovalLink()// method// 获取到重定向地址$approvalUrl = $payment->getApprovalLink();// NOTE: PLEASE DO NOT USE RESULTPRINTER CLASS IN YOUR ORIGINAL CODE. FOR SAMPLE ONLY// 将重定向地址打印出来ResultPrinter::printResult("Created Payment Using PayPal. Please visit the URL to Approve.".$approvalUrl, "Payment", "<a href='$approvalUrl' >$approvalUrl</a>", $request, $payment);12345678910点击
页面执行完毕,既看到paypal服务端返回的授权地址
转链到授权地址
用户登录授权之后
点击继续,返回用户设置的execute地址
至此,PayPal-PHP-SDK支付接口sample支付过程完毕。
支付接口实例化
在项目根目录创建app文件夹,创建几个必须的文件如下:
其中:
- payment.php,创建支付
- exec.php,执行支付,用户授权返回地址
- cancel.php,用户取消支付
- common.php,公共文件
payment.php文件
<?php// +----------------------------------------------------------------------// | Perfect Is Shit// +----------------------------------------------------------------------// | paypal支付DEMO// +----------------------------------------------------------------------// | Author: alexander <gt199899@gmail.com>// +----------------------------------------------------------------------// | Datetime: 2016-07-28 10:56:40// +----------------------------------------------------------------------// | Copyright: Perfect Is Shit// +----------------------------------------------------------------------require_once('./common.php');
use PayPalApiAmount;
use PayPalApiDetails;
use PayPalApiItem;
use PayPalApiItemList;
use PayPalApiPayer;
use PayPalApiPayment;
use PayPalApiRedirectUrls;
use PayPalApiTransaction;
use PayPalApiShippingAddress;// ### Payer// A resource representing a Payer that funds a payment// For paypal account payments, set payment method// to 'paypal'.$payer = new Payer();$payer->setPaymentMethod("paypal");// ### Itemized information// (Optional) Lets you specify item wise// 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// Use this optional field to set additional// payment information such as tax, shipping// charges etc.$details = new Details();$details->setShipping(5) ->setTax(10) ->setSubtotal(70);// ### Amount// Lets you specify a payment amount.// You can also specify additional details// such as shipping, tax.$amount = new Amount();$amount->setCurrency("USD") ->setTotal(85) ->setDetails($details);// ### Transaction// A transaction defines the contract of a// payment - what is the payment for and who// is fulfilling it.$transaction = new Transaction();$transaction->setAmount($amount) ->setItemList($itemList) ->setDescription("Payment description") ->setInvoiceNumber(uniqid());// ### Redirect urls// Set the urls that the buyer must be redirected to after// payment approval/ cancellation.$baseUrl = getBaseUrl();$redirectUrls = new RedirectUrls();$redirectUrls->setReturnUrl("$baseUrl/exec.php?success=true") ->setCancelUrl("$baseUrl/cancel.php?success=false");// ### Payment// A Payment Resource; create one using// the above types and intent set to 'sale'$payment = new Payment();$payment->setIntent("sale") ->setPayer($payer) ->setRedirectUrls($redirectUrls) ->setTransactions(array($transaction));$payment->create($apiContext);$approvalUrl = $payment->getApprovalLink();// 打印出用户授权地址,这里仅仅实现支付过程,流程没有进一步完善。dump($approvalUrl);123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116exec.php文件
<?php// +----------------------------------------------------------------------// | Perfect Is Shit// +----------------------------------------------------------------------// | 执行支付DEMO// +----------------------------------------------------------------------// | Author: alexander <gt199899@gmail.com>// +----------------------------------------------------------------------// | Datetime: 2016-07-28 11:53:10// +----------------------------------------------------------------------// | Copyright: Perfect Is Shit// +----------------------------------------------------------------------set_time_limit(3600);require_once('./common.php');use PayPalApiAmount;use PayPalApiDetails;use PayPalApiExecutePayment;use PayPalApiPayment;use PayPalApiPaymentExecution;use PayPalApiTransaction;// ### Approval Status// Determine if the user approved the payment or notif (isset($_GET['success']) && $_GET['success'] == 'true') { // Get the payment Object by passing paymentId
// payment id was previously stored in session in
// CreatePaymentUsingPayPal.php
$paymentId = $_GET['paymentId']; $payment = Payment::get($paymentId, $apiContext); // ### Payment Execute
// PaymentExecution object includes information necessary
// to execute a PayPal account payment.
// The payer_id is added to the request query parameters
// when the user is redirected from paypal back to your site
$execution = new PaymentExecution(); $execution->setPayerId($_GET['PayerID']); // ### Optional Changes to Amount
// If you wish to update the amount that you wish to charge the customer,
// based on the shipping address or any other reason, you could
// do that by passing the transaction object with just `amount` field in it.
// Here is the example on how we changed the shipping to $1 more than before.
$transaction = new Transaction(); $amount = new Amount(); $details = new Details(); $details->setShipping(5)
->setTax(10)
->setSubtotal(70); $amount->setCurrency('USD'); $amount->setTotal(85); $amount->setDetails($details); $transaction->setAmount($amount); // Add the above transaction object inside our Execution object.
$execution->addTransaction($transaction); try { // Execute the payment
$result = $payment->execute($execution, $apiContext); echo "支付成功";
} catch (Exception $ex) { echo "支付失败"; exit(1);
} return $payment;
} else { echo "PayPal返回回调地址参数错误";
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475cancel.php文件
<?php// +----------------------------------------------------------------------// | Perfect Is Shit// +----------------------------------------------------------------------// | 取消支付DEMO// +----------------------------------------------------------------------// | Author: alexander <gt199899@gmail.com>// +----------------------------------------------------------------------// | Datetime: 2016-07-29 11:31:32// +----------------------------------------------------------------------// | Copyright: Perfect Is Shit// +----------------------------------------------------------------------echo "用户取消支付";12345678910111213
common.php文件
<?php// +----------------------------------------------------------------------// | Perfect Is Shit// +----------------------------------------------------------------------// | 公共文件// +----------------------------------------------------------------------// | Author: alexander <gt199899@gmail.com>// +----------------------------------------------------------------------// | Datetime: 2016-07-28 11:55:30// +----------------------------------------------------------------------// | Copyright: ShowMore// +----------------------------------------------------------------------require_once('../vendor/autoload.php');use PayPalRestApiContext;use PayPalAuthOAuthTokenCredential;// 下面为申请app获得的clientId和clientSecret,必填项,否则无法生成token。$clientId = '';$clientSecret = '';$apiContext = new ApiContext( new OAuthTokenCredential( $clientId, $clientSecret
)
);$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' => 'PayPalLogDefaultLogFactory' // Factory class implementing PayPalLogPayPalLogFactory
)
);// 浏览器友好的变量输出function dump($var, $echo=true, $label=null, $strict=true) {
$label = ($label === null) ? '' : rtrim($label) . ' '; if (!$strict) { if (ini_get('html_errors')) { $output = print_r($var, true); $output = "<pre>" . $label . htmlspecialchars($output, ENT_QUOTES) . "</pre>";
} else { $output = $label . print_r($var, true);
}
} else {
ob_start();
var_dump($var); $output = ob_get_clean(); if (!extension_loaded('xdebug')) { $output = preg_replace("/]=>n(s+)/m", "] => ", $output); $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
}
} if ($echo) { echo($output); return null;
}else
return $output;
}/**
* ### 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);
}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889支付接口实例测试
执行payment.php文件,得到授权地址,如下:
转链到用户授权地址
用户登录授权,可以看到在我们设置过收货地址之后,支付收货地址是默认无法更改的。
用户点击继续,会转链到我们的支付成功回调地址exec.php。
用户点击取消并返回,会转链到我们的支付失败回调地址cancel.php
支付过后可进入sandbox账号中心查看是否有交易。
测试的款项都在这里,有个问题,sandbox上面的交易时间总比我这边晚一天,比如今天是7月29日完成的交易,但是在sandbox里面显示的都是7月28日。不知道是不是个BUG。
至此,PayPal-PHP-SDK的支付接口OK。
可以对PayPal-PHP-SDK底层代码进行进一步研究,有时间再弄。
来源网址:http://blog.csdn.net/alexander_phper/article/details/52057524