支付宝支付接口集成——手机网站支付单文件代码
/*** 配置结束 ***/
$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支付接口实现支付功能。它通过设置一系列参数,构建签名,生成表单并自动提交到支付宝支付网关。整个流程的核心在于生成请求参数并对其进行签名,以确保安全性。通过异步通知或同步通知,商户能够获得支付结果并进行进一步的业务处理。
这段代码设计得较为清晰,分工明确,扩展性强。