paypal nvp接口编程笔记

paypal的工作流程

    1:首先,用户将paypal所需的参数,诸如该次交易的目的账号,金额,货物名,个数等等一并按paypal提供的参数手册写成一个NVP字符串大概如下面这样

    

$nvpstr=
        "&AMT=".$payAmount     //总金额
        ."&PAYMENTACTION=".$payType //交易类型,一般是‘sale’,也可以是捐助的类型
        ."&RETURNURL=".$returnURL   //如果交易成功,返回到的URL
        ."&CANCELURL=".$cancelURL   //如果交易失败,返回到的url
        ."&CURRENCYCODE=".$currency //货币类型
        ."&DESC=".$desc;            //货物描述
这些参数为最基本的,也有一些其他可选的参数,具体可参考官方文档

写完后,将这字符串发送给paypal生成一个token,具体做法就是将其与提供的生成token的url连起来发送一个http请求,我是用php的curl库来实现的

define('API_ENDPOINT', 'https://api-3t.sandbox.paypal.com/nvp');
$API_Endpoint =API_ENDPOINT;
                $ch = curl_init();
		curl_setopt($ch, CURLOPT_URL,$API_Endpoint);
		curl_setopt($ch, CURLOPT_VERBOSE, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
		curl_setopt($ch, CURLOPT_POST, 1);
		$nvpreq="METHOD=".urlencode($methodName)."//方法名(有三种,这里是取得token所以是SetExpressCheckout)
                         &VERSION=".urlencode($version)."//api的版本号
                         &PWD=".urlencode($API_Password)."//商户的密码,该参数为商家在paypal注册后通过申请获得
                         &USER=".urlencode($API_UserName)."//商户的用户名,该参数为商家在paypal注册后通过申请获得
                         &SIGNATURE=".urlencode($API_Signature)//商户的签名证书,该参数为商家在paypal注册后通过申请获得
                        .$nvpStr; //之前生成的商品交易信息字符串

		curl_setopt($ch,CURLOPT_POSTFIELDS,$nvpreq);

		$response = curl_exec($ch);

上面代码的最后行为执行curl然后获得返回值$response,这个值中包含一些诸如是否成功,时间等等,但最重要的是token

token是一个杂乱的字符串,可能是paypal通过某种算法算出来的,也可能是随机生成的,但不管怎么样,你必须将这个token附加到paypal的支付页面的URL的最后的token=后面,然后访问该URL便可开始交易

define('PAYPAL_URL', 'https://www.sandbox.paypal.com/cgi-bin/webscr&cmd=_express-checkout&useraction=commit&token=');
    $token = urldecode($resArray["TOKEN"]);//获取token         
    $payPalURL = PAYPAL_URL.$token;//
    header($payPalURL);//访问paypal页面进行交易
2:这个时候,应该进入paypal支付页面了,当买家登陆并确认了订单,页面将返回你之前在NVP字符串中设置的returnURL页面,如果买家点了取消,跳到cancelURL

在returnURL我们将调用paypal提供的第二个函数GetExpressCheckoutDetails来取得一些购买者的信息,比如说,送货地址,这个函数一般做实物交易的用的比较多。同时,token也被传输回来,应为在接下来需要这个。

3:以上的步骤仅仅只是paypal获取交易所有信息,买家卖家做准备的过程,最后一步,调用DoExpressCheckoutPayment后,paypal才真正的将钱从买家账户转移到卖家账户并收取它的服务费用。

 以上大致为paypal的支付过程,整个过程中,paypal的token作为整个交易的唯一标示,从将参数发往api-endpiont获得开始,一直参与其中直到交易的完成,这个token是有时效的。

以下为我使用的完整的paypal nvp类

<?php
//以下URL为sanbox,亦即沙盒,表明属于测试环境,真实环境为https://api-3t.paypal.com/nvp和https://www.paypal.com/cgi-bin/webscr&cmd=_express-checkout&useraction=commit&token=
define('API_ENDPOINT', 'https://api-3t.sandbox.paypal.com/nvp');
define('PAYPAL_URL', 'https://www.sandbox.paypal.com/cgi-bin/webscr&cmd=_express-checkout&useraction=commit&token=');
$API_Endpoint =API_ENDPOINT;
class paypal {
	public $errMsg = array();
	function __construct() {
	}
        //获取token的函数
	function SetExpressCheckout($params) {
		$token = '';
		$serverName = $_SERVER['SERVER_NAME'];
		$serverPort = $_SERVER['SERVER_PORT'];
		$url = dirname('https://'.$serverName.':'.$serverPort.$_SERVER['REQUEST_URI']);
		$payAmount = $params['amount'];
		$currency = $params['currency'];
		$payType = $params['payType'];
		$desc = $params['DESC'];
		$returnURL = urlencode($url.'/'.$params['returnPage'].'?cmd=paypal&currency='.$currency.'&payType='.$payType.'&payAmount='.$payAmount);
		$cancelURL = urlencode($url.'/'.$params['cancelPage'].'?cmd=cancel');
		$nvpstr = "&AMT=".$payAmount."&PAYMENTACTION=".$payType."&RETURNURL=".$returnURL."&CANCELURL=".$cancelURL."&CURRENCYCODE=".$currency."&DESC=".$desc;
		$resArray=self::makeCall("SetExpressCheckout", $nvpstr);
		if(!$resArray) {
			return false;
		}
		if(array_key_exists('ACK', $resArray) AND strtoupper($resArray['ACK']) == 'SUCCESS') {
			if (array_key_exists("TOKEN",$resArray)) {
				$token = urldecode($resArray["TOKEN"]);
			}
			$payPalURL = PAYPAL_URL.$token;
			echo $payPalURL;
			return $payPalURL;
		}
		//插入你的异常处理
	}
        //
	function GetExpressCheckoutDetails($params) {
		$token = urlencode($params['token']);
		$nvpstr = "&TOKEN=".$token;
		$resArray = self::makeCall("GetExpressCheckoutDetails",$nvpstr);
		if(!$resArray) {
			return false;
		}
		if(array_key_exists('ACK', $resArray) AND strtoupper($resArray['ACK']) == 'SUCCESS') {
			return $resArray;
		} else {
			//插入你的异常处理
		}
	}
        //确定执行交易
	function DoExpressCheckoutPayment($params) {
		$token = urlencode( $params['token']);
		$payAmount = urlencode ($params['payAmount']);
		$payType = urlencode($params['payType']);
		$payerID = urlencode($params['PayerID']);
		$nvpstr = '&TOKEN='.$token.'&PAYERID='.$payerID.'&PAYMENTACTION='.$payType.'&AMT='.$payAmount ;
		$resArray = self::makeCall("DoExpressCheckoutPayment",$nvpstr);
		if(!$resArray) {
			return false;
		}
		if(array_key_exists('ACK', $resArray) AND strtoupper($resArray['ACK']) == 'SUCCESS') {
			return $resArray;
		} else {
			 //插入你的异常处理
		}
	}

	function RefundTransaction($params) {
		$type = $params['type'];
		$transactionId = $params['transactionId'];
		$amount = urlencode($params['amount']);
		$nvpstr = '&TRANSACTIONID='.$transactionId.'&REFUNDTYPE='.$type;
		if($type == 'Full')
		$nvpstr .= '&AMT='.$amount;
		$resArray = self::makeCall("RefundTransaction", $nvpstr);
		if(!$resArray){
			return false;
		}
		if(array_key_exists('ACK', $resArray) AND strtoupper($resArray['ACK']) == 'SUCCESS') {
			return $resArray;
		} else {
			 //插入你的异常处理
		}
	}
        通过curl库来发送请求,被以上的函数调用
	function makeCall($methodName,$nvpStr) {
		global $API_Endpoint;
		$version = '82.0';
                //获取商家,亦即卖家的账户名,密码和签名,我将这些放在一个xml文件中读取,读者可自行决定如何取这些
                $xml = new DOMDocument ( );
		$xml->load("xml/xmlforpaypal.xml");
		$item = $xml->getElementsByTagName("root")->item(0);
		$item = $xml->getElementsByTagName("paypal")->item(0);
		$username = $item->getElementsByTagName("username")->item(0)->textContent;
		$password = $item->getElementsByTagName("password")->item(0)->textContent;
		$signature = $item->getElementsByTagName("signature")->item(0)->textContent;
		$API_UserName = $username;
		$API_Password = $password;
		$API_Signature = $signature;

                //  $nvp_Header;
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL,$API_Endpoint);
		curl_setopt($ch, CURLOPT_VERBOSE, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_POST, 1);
		/*  if(USE_PROXY)//如果使用代理
		 {
		 curl_setopt ($ch, CURLOPT_PROXY, PROXY_HOST.":".PROXY_PORT);
		 }*/
		$nvpreq = "METHOD=".urlencode($methodName)."&VERSION=".urlencode($version)."&PWD=".urlencode($API_Password)."&USER=".urlencode($API_UserName)."&SIGNATURE=".urlencode($API_Signature).$nvpStr;
		curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
		$response = curl_exec($ch);
		$nvpResArray=self::deformatNVP($response);
		if (!$response) {
			//插入你的异常处理函数
			return false;
		} else {
			curl_close($ch);
		}
		return $nvpResArray;
	}
        //关于字符串的你懂的
	function deformatNVP($nvpstr) {
		$intial = 0;
		$nvpArray = array();
		while(strlen($nvpstr)) {
			$keypos = strpos($nvpstr, '=');
			$valuepos = strpos($nvpstr,'&') ? strpos($nvpstr,'&') : strlen($nvpstr);
			$keyval = substr($nvpstr, $intial, $keypos);
			$valval = substr($nvpstr, $keypos+1, $valuepos-$keypos-1);
			$nvpArray[urldecode($keyval)] = urldecode($valval);
			$nvpstr = substr($nvpstr, $valuepos+1, strlen($nvpstr));
		}
		return $nvpArray;
	}
}
?>


阅读更多

更多精彩内容