AliwapService.php 6.17 KB
<?php

namespace Plugin\Pay\aliwap;

use Plugin\Pay\aliwap\AliwapConfig;
use Plugin\Pay\aliwap\AliwapReqparams;
use Plugin\Pay\aliwap\AliwapRspparams;

/**
 * 支付宝手机网页支付
 */
class AliwapService
{

    var $config;
    var $alipay_config;

    public function __construct()
    {
        $this->logProjectPrefix = 'aliwap';
        $this->config = new AliwapConfig();

        $this->alipay_config = array(
            'partner' => $this->config->partner,
            'key' => $this->config->alipay_key,
            'sign_type' => 'MD5',
            'input_charset' => 'utf-8',
            'cacert' => dirname(__FILE__) . '/cacert.pem',
            'transport' => 'http'
        );
        require_once("lib/alipay_core.function.php");
        require_once("lib/alipay_rsa.function.php");
        require_once("lib/alipay_md5.function.php");
        require_once("lib/alipay_notify.class.php");
        require_once("lib/alipay_submit.class.php");
    }

    /**
     * 构造请求参数
     * @see QPay_Utils_Interface::getPayRequestPars()
     */
    public function getPayRequestPars(AliwapReqparams $params)
    {
        $para_token = array(
            'service' => 'alipay.wap.trade.create.direct',
            'partner' => $this->config->partner,
            'sec_id' => $this->config->sign_type,
            'format' => 'xml',
            'v' => '2.0',
            'req_id' => date('Ymdhis') . $params->orderCode,
            'req_data' => $this->getTokenReqData($params->orderCode, $params->goodsName, $params->totalFee / 100),
            '_input_charset' => $this->config->input_charset
        );
        //建立请求
        $alipaySubmit = new \AlipaySubmit($this->alipay_config);
        $html_text = $alipaySubmit->buildRequestHttp($para_token);
        //URLDECODE返回的信息
        $html_text_decode = urldecode($html_text);
        //解析远程模拟提交后返回的信息
        $para_html_text = $alipaySubmit->parseResponse($html_text_decode);

        if (empty($para_html_text) || empty($para_html_text['request_token'])) {
            return false;
//            error_log("token获取失败:" . var_export($para_token, true) . "\n" . '返回结果:' . $html_text, 3, '/tmp/aliwap.log');
//            throw new Exception('支付系统繁忙,请稍后再试');
        }
        //获取request_token
        $request_token = $para_html_text['request_token'];
        //业务详细
        $req_data = '<auth_and_execute_req><request_token>' . $request_token . '</request_token></auth_and_execute_req>';
        //必填
        //构造要请求的参数数组,无需改动
        $parameter = array(
            "service" => "alipay.wap.auth.authAndExecute",
            'partner' => $this->config->partner,
            'sec_id' => $this->config->sign_type,
            "format" => 'xml',
            "v" => '2.0',
            "req_id" => date('Ymdhis') . $params->orderCode,
            "req_data" => $req_data,
            "_input_charset" => $this->config->input_charset
        );

        //建立请求
        $alipaySubmit = new \AlipaySubmit($this->alipay_config);
        $strUrl = $alipaySubmit->buildRequestUrl($parameter);
        return array(
            'pay_url' => $this->config->pay_url,
            'pars' => $strUrl,
            'reqType' => 'get'
        );
    }

    /**
     * 解析结果
     * 
     * @see AliwapInterface::parseResponse()
     */
    public function parseResponse(Array $arrResponse)
    {
        $rsp = new AliwapRspparams();
        if ($arrResponse['type'] == 'return') {
            //return 返回
            $alipayNotify = new \AlipayNotify($this->alipay_config);
            $verify_result = $alipayNotify->verifyReturn();
            if ($verify_result) {
                //商户订单号
                $rsp->orderCode = $_GET['out_trade_no'];
                $rsp->payResult = 200;
                //支付宝交易号
                $trade_no = $_GET['trade_no'];
            } else {
                $rsp->payResult = 400;
            }
        } else {
            //服务器返回
            $alipayNotify = new \AlipayNotify($this->alipay_config);
            $verify_result = $alipayNotify->verifyNotify();
            if ($verify_result) {
                //解密(如果是RSA签名需要解密,如果是MD5签名则下面一行清注释掉)
                // $notify_data = $alipayNotify->decrypt($_POST['notify_data']);
                //解析notify_data
                //注意:该功能PHP5环境及以上支持,需开通curl、SSL等PHP配置环境。建议本地调试时使用PHP开发软件
                $doc = new \DOMDocument();
                $doc->loadXML($_POST['notify_data']);
                if (!empty($doc->getElementsByTagName("notify")->item(0)->nodeValue)) {
                    //商户订单号
                    $out_trade_no = $doc->getElementsByTagName("out_trade_no")->item(0)->nodeValue;
                    //支付宝交易号
                    $trade_no = $doc->getElementsByTagName("trade_no")->item(0)->nodeValue;
                    //交易状态
                    $trade_status = $doc->getElementsByTagName("trade_status")->item(0)->nodeValue;
                    if ($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') {
                        $rsp->orderCode = $out_trade_no;
                        $rsp->payResult = 200;
                    } else {
                        $rsp->payResult = 400;
                    }
                }
            } else {
                $rsp->payResult = 401;
            }
        }
        return $rsp;
    }

    private function getTokenReqData($out_trade_no, $subject, $total_fee)
    {
        return '<direct_trade_create_req><notify_url>' . $this->config->notify_url .
            '</notify_url><call_back_url>' . $this->config->return_url .
            '</call_back_url><seller_account_name>' . $this->config->sellerMail .
            '</seller_account_name><out_trade_no>' . $out_trade_no . '</out_trade_no><subject>' . 'yoho order:' . $out_trade_no .
            '</subject><total_fee>' . $total_fee . '</total_fee><merchant_url>' . $this->config->merchant_url . $out_trade_no .
            '</merchant_url></direct_trade_create_req>';
    }

}