ThinkPHP使用Paypal支付接口的模块开发

<?php
/**
 * 
 * PaypalAction.class.php
 * 
 * ThinkPHP Paypal支付接口模块
 * 
**/


class PaymentAction extends Action { 

/** 
* 自己的paypal账号 
*/ 
private $account = 'admin@gmail.com';

/** 
* paypal支付网关地址 
*/ 
private $gateway = 'https://www.paypal.com/cgi-bin/webscr?'; 

public function index() { 
	echo '<a href="'.U('Payment/order').'">Payment this order.</a>'; 
} 

/** 
  * 生成订单并跳转到Paypal进行支付 
  */ 
public function order() { 
	/** 
	* 自己的逻辑代码 
	* 判断是否登录、购买的哪个商品、购物车等等逻辑 
	* 当然可以调用Model更简单点 
	* 这里不在赘述 
	*/ 
	/** ...... **/ 

	$order_info	= array();	// 初始化订单数据 
	$order_id	= uniqid();	// 按照自己的规则生成订单号入库 

	/** 
	* 订单包含哪几种商品、谁买的、什么时间、几件 
	*/ 
	$order_info['order_id']		= $order_id; 
	$order_info['member_id']	= Session::get('member_id'); 
	/** .... **/ 

	$order = D('Order'); 

	if( $order->createOrder($order_info) ) { 
		unset($order,$order_info); 
		// 初始化准备提交到Paypal的数据 
		$pp_info = array();
		// 告诉Paypal,我的网站是用的我自己的购物车系统 
		$pp_info['cmd']			= '_xclick';
		// 告诉paypal,我的(商城的商户)Paypal账号,就是这钱是付给谁的 
		$pp_info['business']	= $this->account;
		// 用户将会在Paypal的支付页面看到购买的是什么东西,只做显示,没有什么特殊用途,
		// 如果是多件商品,则直接告诉用户,只支付某个订单就可以了 
		$pp_info['item_name']	= "支付订单:{$order_id}";
		$pp_info['amount']		= '13'; // 告诉Paypal,我要收多少钱 
		// 告诉Paypal,我要用什么货币。这里需要注意的是,由于汇率问题,
		// 如果网站提供了更改货币的功能,那么上面的amount也要做适当更改,
		// paypal是不会智能的根据汇率更改总额的 
		$pp_info['currency_code']	= 'USD';
		// 当用户成功付款后paypal会将用户自动引导到此页面。
		// 如果为空或不传递该参数,则不会跳转 
		$pp_info['return']		= 'http#//www.sjolzy.cn/index.php/payment/finish';	
		$pp_info['invoice']	= $order_id; 
		$pp_info['charset']	= 'utf-8'; 
		$pp_info['no_shipping']	= '1'; 
		$pp_info['no_note']		= '1'; 
		// 当跳转到paypal付款页面时,用户又突然不想买了。则会跳转到此页面 
		$pp_info['cancel_return']	= 'http#//www.sjolzy.com/index.php/product/view/pid/3';	
		// Paypal会将指定 invoice 的订单的状态定时发送到此URL 
		// (Paypal的此操作,是paypal的服务器和我方商城的服务器点对点的通信,用户感觉不到)
		$pp_info['notify_url']	= 'http#//www.sjolzy.com/index.php/payment/notify/orderid/'.$order_id; 
		$pp_info['rm']	= '2'; 
		$paypal_payment_url = $this->gateway.http_build_query($pp_info); 
		echo "<a href='{$paypal_payment_url}'>Go Paypal!</a>"; 
		unset($pp_info); 
	} else { 
		$this->error(L('order_create_fail')); 
	} 
} 

public function finish() { 
	$this->success('购买成功'); 
} 

public function notify() { 
	// 由于这个文件只有被Paypal的服务器访问,所以无需考虑做什么页面什么的,
	// 这个页面不是给人看的,是给机器看的 
	$order_id = (int) $_GET['orderid']; 
	$order_info = D('Order')->getOrderDetail($order_id); 

	// 由于该URL不仅仅只有Paypal的服务器能访问,其他任何服务器都可以向该方法发起请求。
	// 所以要判断请求发起的合法性,也就是要判断请求是否是paypal官方服务器发起的 

	// 拼凑 post 请求数据 
	$req = 'cmd=_notify-validate';// 验证请求 
	foreach ($_POST as $k=>$v){ 
		$v = urlencode(stripslashes($v)); 
		$req .= "&{$k}={$v}"; 
	} 

	$ch = curl_init(); 
	curl_setopt($ch,CURLOPT_URL,'http://www.paypal.com/cgi-bin/webscr'); 
	curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 
	curl_setopt($ch,CURLOPT_POST,1); 
	curl_setopt($ch,CURLOPT_POSTFIELDS,$req); 
	$res = curl_exec($ch); 
	curl_close($ch); 

	if( $res && !emptyempty($order_info) ) { 
		// 本次请求是否由Paypal官方的服务器发出的请求 
		if(strcmp($res, 'VERIFIED') == 0) { 
			/** 
			* 判断订单的状态 
			* 判断订单的收款人 
			* 判断订单金额 
			* 判断货币类型 
			*/ 
			if(($_POST['payment_status'] != 'Completed' && $_POST['payment_status'] != 'Pending')
			 OR ($_POST['receiver_email'] != $this->account)
			  OR ($_POST['mc_gross'] != 13)
			   OR ('USD' != $_POST['mc_currency'])) { 
			// 如果有任意一项成立,则终止执行。由于是给机器看的,所以不用考虑什么页面。直接输出即可 
				exit('fail'); 
			} else {// 如果验证通过,则证明本次请求是合法的 
				D('Order')->finishOrder($order_id);// 更改订单状态 
				exit('success'); 
			} 
		} else { 
			exit('fail'); 
		} 
	} 
} 
} 

?>

更多Paypal参数的使用参考:PayPal支付接口的PHP开发方式

Magento默认订单状态

require_once('app/Mage.php');
umask(0);
Mage::app('default');

$order = Mage::getModel('sales/order');
$order->loadByIncrementId(100000001);  // 100000001为订单编号

// 获取订单状态
$status = $order->getStatus();
$state  = $order->getState();

echo $status;
echo "\r\n";
echo $state;

// 设置订单状态
$order->setStatus(Mage_Sales_Model_Order::STATE_PROCESSING);
$order->save();
 

Magento订单
有两个状态变量:state和status,这让人困惑,只有测试下了,于是下了个单,然后在Magneto后台处理订单,得出下面的Magento订单状态值。

1. 新订单
state  : new
status : pending

2. 配送后
state  : processing
status : processing

3. 收款后
state  : processing
status : processing

4. 订单完成
state  : complete
status : complete

5. 订单取消
state  : canceled
status : canceled

6. 订单关闭
state  : closed
status : closed

7. 订单挂起
state  : holded
status : holded
 

Magento订单状态
是定义在Magento代码文件app\code\core\Mage\Sales\Model\Order.php中定义了订单的状态常量:

/**
 * Order model
 *
 * Supported events:
 *  sales_order_load_after
 *  sales_order_save_before
 *  sales_order_save_after
 *  sales_order_delete_before
 *  sales_order_delete_after
 *
 * @author Magento Core Team <core@magentocommerce.com>
 */
class Mage_Sales_Model_Order extends Mage_Sales_Model_Abstract
{

    /**
     * Order states
     */
    const STATE_NEW             = 'new';
    const STATE_PENDING_PAYMENT = 'pending_payment';
    const STATE_PROCESSING      = 'processing';
    const STATE_COMPLETE        = 'complete';
    const STATE_CLOSED          = 'closed';
    const STATE_CANCELED        = 'canceled';
    const STATE_HOLDED          = 'holded';
    const STATE_PAYMENT_REVIEW  = 'payment_review'; // added magento 1.4

    /**
     * Order flags
     */
    const ACTION_FLAG_CANCEL    = 'cancel';
    const ACTION_FLAG_HOLD      = 'hold';
    const ACTION_FLAG_UNHOLD    = 'unhold';
    const ACTION_FLAG_EDIT      = 'edit';
    const ACTION_FLAG_CREDITMEMO= 'creditmemo';
    const ACTION_FLAG_INVOICE   = 'invoice';
    const ACTION_FLAG_REORDER   = 'reorder';
    const ACTION_FLAG_SHIP      = 'ship';
    const ACTION_FLAG_COMMENT   = 'comment';

    // ...
}
</core@magentocommerce.com>

 

其中,pending_payment, payment_review 是支付(Paypal, Amazon Pay)过程中引入的订单状态。