支付宝支付接口集成——手机网站支付单文件代码
/*** 配置结束 ***/
$aliPay = new AlipayService();
$aliPay->setAppid($ali_appid);
$aliPay->setReturnUrl($returnurl);
$aliPay->setNotifyUrl($notifyurl);
$aliPay->setRsaPrivateKey($ali_rsaPrivateKey);
$aliPay->setTotalFee($total_fee);
$aliPay->setOutTradeNo($sdorderno);
$aliPay->setOrderName("充值");
$aliPay->setpassbackparams($remark);
$sHtml = $aliPay->doPay();
echo $sHtml;
class AlipayService
{
protected $appId;
protected $charset;
protected $returnUrl;
protected $notifyUrl;
//私钥值
protected $rsaPrivateKey;
protected $totalFee;
protected $outTradeNo;
protected $orderName;
protected $passbackparams;
public function __construct()
{
$this->charset = 'utf-8';
}
public function setAppid($appid)
{
$this->appId = $appid;
}
public function setpassbackparams($str)
{
$this->passbackparams = $str;
}
public function setReturnUrl($returnUrl)
{
$this->returnUrl = $returnUrl;
}
public function setNotifyUrl($notifyUrl)
{
$this->notifyUrl = $notifyUrl;
}
public function setRsaPrivateKey($rsaPrivateKey)
{
$this->rsaPrivateKey = $rsaPrivateKey;
}
public function setTotalFee($payAmount)
{
$this->totalFee = $payAmount;
}
public function setOutTradeNo($outTradeNo)
{
$this->outTradeNo = $outTradeNo;
}
public function setOrderName($orderName)
{
$this->orderName = $orderName;
}
/**
* 发起订单
* @return array
*/
public function doPay()
{
//请求参数
$requestConfigs = array(
'out_trade_no'=>$this->outTradeNo,
'product_code'=>'QUICK_WAP_WAY',
'total_amount'=>$this->totalFee, //单位 元
'subject'=>$this->orderName, //订单标题
"passback_params"=>urldecode($this->passbackparams)
);
$commonConfigs = array(
//公共参数
'app_id' => $this->appId,
'method' => 'alipay.trade.wap.pay', //接口名称
'format' => 'JSON',
'return_url' => $this->returnUrl,
'charset'=>$this->charset,
'sign_type'=>'RSA2',
'timestamp'=>date('Y-m-d H:i:s'),
'version'=>'1.0',
'notify_url' => $this->notifyUrl,
'biz_content'=>json_encode($requestConfigs),
);
$commonConfigs["sign"] = $this->generateSign($commonConfigs, $commonConfigs['sign_type']);
return $this->buildRequestForm($commonConfigs);
}
/**
* 建立请求,以表单HTML形式构造(默认)
* @param $para_temp 请求参数数组
* @return 提交表单HTML文本
*/
protected function buildRequestForm($para_temp) {
$sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='https://openapi.alipay.com/gateway.do?charset=".$this->charset."' method='POST'>";
foreach($para_temp as $key=>$val){
if (false === $this->checkEmpty($val)) {
$val = str_replace("'","'",$val);
$sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";
}
}
//submit按钮控件请不要含有name属性
$sHtml = $sHtml."<input type='submit' value='ok' style='display:none;''></form>";
$sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>";
return $sHtml;
}
public function generateSign($params, $signType = "RSA") {
return $this->sign($this->getSignContent($params), $signType);
}
protected function sign($data, $signType = "RSA") {
$priKey=$this->rsaPrivateKey;
$res = "-----BEGIN RSA PRIVATE KEY-----\n" .
wordwrap($priKey, 64, "\n", true) .
"\n-----END RSA PRIVATE KEY-----";
($res) or die('您使用的私钥格式错误,请检查RSA私钥配置');
if ("RSA2" == $signType) {
openssl_sign($data, $sign, $res, version_compare(PHP_VERSION,'5.4.0', '<') ? SHA256 : OPENSSL_ALGO_SHA256); //OPENSSL_ALGO_SHA256是php5.4.8以上版本才支持
} else {
openssl_sign($data, $sign, $res);
}
$sign = base64_encode($sign);
return $sign;
}
/**
* 校验$value是否非空
* if not set ,return true;
* if is null , return true;
**/
protected function checkEmpty($value) {
if (!isset($value))
return true;
if ($value === null)
return true;
if (trim($value) === "")
return true;
return false;
}
public function getSignContent($params) {
ksort($params);
$stringToBeSigned = "";
$i = 0;
foreach ($params as $k => $v) {
if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
// 转换成目标字符集
$v = $this->characet($v, $this->charset);
if ($i == 0) {
$stringToBeSigned .= "$k" . "=" . "$v";
} else {
$stringToBeSigned .= "&" . "$k" . "=" . "$v";
}
$i++;
}
}
unset ($k, $v);
return $stringToBeSigned;
}
/**
* 转换字符集编码
* @param $data
* @param $targetCharset
* @return string
*/
function characet($data, $targetCharset) {
if (!empty($data)) {
$fileType = $this->charset;
if (strcasecmp($fileType, $targetCharset) != 0) {
$data = mb_convert_encoding($data, $targetCharset, $fileType);
//$data = iconv($fileType, $targetCharset.'//IGNORE', $data);
}
}
return $data;
}
}
这段代码实现了通过支付宝的 WAP
支付接口发起支付请求的过程。以下是对代码各个部分的详细解析,帮助理解支付宝支付流程的实现。
一、主要流程
实例化支付对象:
代码一开始通过$aliPay = new AlipayService();
实例化AlipayService
类,用来处理支付的相关逻辑。设置支付相关参数:
支付宝支付接口需要一些关键信息来完成支付,包括:AppID
:支付宝开放平台上的应用ID。Return URL
:支付完成后,支付宝页面重定向的URL。Notify URL
:支付宝异步通知结果的回调地址。RSA私钥
:用于签名请求参数,确保支付安全。Total Fee
:订单金额。Out Trade No
:商户订单号。Order Name
:订单标题。Passback Params
:回传给商户的附加信息。
发起支付请求:
调用$aliPay->doPay();
发起支付请求,最终会生成一个提交支付宝支付的HTML表单,并自动提交表单,跳转到支付宝支付页面。
二、类结构分析
1. AlipayService
类的属性:
$appId
:支付宝分配给开发者的应用ID。$charset
:编码格式,默认为utf-8
。$returnUrl
:支付完成后的同步通知地址。$notifyUrl
:支付结果的异步通知地址。$rsaPrivateKey
:商户生成的RSA私钥,用于签名。$totalFee
:订单金额。$outTradeNo
:商户订单号。$orderName
:订单名称。$passbackparams
:回传参数,支付成功后支付宝会原样返回该参数。
2. set
方法:
该类提供了一些 set
方法,用于设置支付请求中的各个参数,如:
setAppid()
:设置支付宝应用ID。setTotalFee()
:设置支付金额。setOutTradeNo()
:设置商户订单号。setOrderName()
:设置订单标题。setpassbackparams()
:设置附加回传参数。
这些方法使得用户能够灵活地在实例化后设置支付请求参数。
3. doPay()
方法:
这个方法是发起支付请求的核心,它构建了支付请求的参数,并调用了支付宝接口:
$requestConfigs
:包含订单的主要信息,如订单号、金额、标题和回传参数。$commonConfigs
:包含支付宝支付接口的公共参数,如应用ID、接口方法、通知地址等。generateSign()
:为请求参数生成签名,保证数据的完整性和安全性。
4. buildRequestForm()
方法:
该方法生成了一个HTML表单,将请求参数通过表单的方式提交到支付宝支付网关,并通过JavaScript自动提交表单。这是WAP支付的一种常见方式。
5. generateSign()
和 sign()
方法:
这两个方法负责生成支付请求的签名:
generateSign()
:首先将参数排序并生成待签名的字符串。sign()
:使用RSA私钥对字符串进行签名。
6. getSignContent()
方法:
该方法将请求参数按字典序排序并生成待签名的字符串,确保签名的内容是有序的,符合支付宝的签名规范。
7. checkEmpty()
方法:
这是一个工具方法,用来检查参数值是否为空,以避免提交空值的参数影响签名和支付请求。
8. characet()
方法:
该方法用于转换字符集编码,确保提交给支付宝的参数符合 charset
要求(默认是 utf-8
)。
三、关键代码详解
签名生成:
支付宝的支付请求必须经过签名,以确保数据的安全性和完整性。代码中的generateSign()
方法通过将请求参数进行排序并拼接成字符串,再用商户的RSA私钥进行签名来完成这一过程。public function generateSign($params, $signType = "RSA") { return $this->sign($this->getSignContent($params), $signType); }
自动提交支付表单:
代码中buildRequestForm()
方法构建了支付请求的表单,并且通过以下代码自动提交表单,跳转到支付宝支付页面:$sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>";
回传参数处理:
支付宝在支付成功后会将商户传入的passback_params
原样返回给商户,这对于支付后处理业务逻辑非常有用。代码通过urldecode()
对该参数进行了处理。"passback_params"=>urldecode($this->passbackparams)
四、总结
这段代码展示了如何通过支付宝WAP支付接口实现支付功能。它通过设置一系列参数,构建签名,生成表单并自动提交到支付宝支付网关。整个流程的核心在于生成请求参数并对其进行签名,以确保安全性。通过异步通知或同步通知,商户能够获得支付结果并进行进一步的业务处理。
这段代码设计得较为清晰,分工明确,扩展性强。