apicloud使用支付宝app支付

aipcloud安装支付宝模块

aliPay v1.0.12

前端

使用模块,传递订单,获得支付str文本


<html>

<head>
    <title>title>
    <script src="../../../script/template/mobile/xianhua/static/js/jquery-3.1.1.min.js">script>
    <script src="../../../script/api.js">script>
    <script type="text/javascript"> //https://docs.apicloud.com/Client-API/Open-SDK/aliPay var orderInfo = ''; apiready = function() { aliPay = api.require('aliPay'); get_str(); if (orderInfo=='') { window.location.href="../order/order_list.html"; return; } alert(orderInfo); aliPay.payOrder({ orderInfo: orderInfo }, function(ret, err) { api.alert({ title: '支付结果', msg: ret.code, buttons: ['确定'] }); }); }; function get_str() { var pay_order_sn = window.localStorage.getItem("pay_order_sn"); if (pay_order_sn==null) { alert("请选择订单支付!"); window.location.href="../order/order_list.html"; return; } $.ajax({ type: "POST", url: "http://g421.com/apprun/Apppay/get_alipay_str", dataType: 'json', data:{ pay_order_sn:pay_order_sn }, async: false, success: function(e) { if (e.code == 1) { orderInfo = e.data; }else{ alert(e.msg); window.location.href="../order/order_list.html"; } } }) } script>
head>

<body>
body>

html>

后端处理


namespace app\apprun\controller;

use think\Controller;
use think\Db;

/** * 支付 * 支付宝 * 私钥->获取订单支付->回调用公钥校验支付 * 注意: * 新版的app使用新的app支付接口(alipay.trade.app.pay)和RSA2校验,且只有一种签名结构(老版本有3种),老版本的支付是不支持RSA2的,只支持RSA1. * 详情:https://docs.open.alipay.com/204/105465/ * 验证:https://docs.open.alipay.com/200/106120 */
class Apppay extends Controller {
    private $fileCharset          = "UTF-8";
    public $postCharset           = "UTF-8";
    public $rsaPrivateKeyFilePath = "";
    public $rsaPublicKeyFilePath  = "";
    public $sign_type             = "RSA2";
    //商户私钥,您的原始格式RSA私钥
    public $rsaPrivateKey      = 'xxx';
    //支付宝公钥
    public $alipayrsaPublicKey = 'xxx';
    /** * 获取支付宝支付字符串信息 * @return [type] [description] */
    public function get_alipay_str() {
        is_crossdomain_app(true);
        $params['app_id']      = "2018062160408670";
        $params['method']      = "alipay.trade.app.pay";
        $params['format']      = "json";
        $params['charset']     = "utf-8";
        $params['timestamp']   = date("Y-m-d H:i:s");
        $params['version']     = "1.0";
        $params['notify_url']  = "http://m.luhong421.com/apprun/Apppay/notify_url"; // 异步通知地址
        $params['sign_type']   = $this->sign_type;
        $order_sn = input('pay_order_sn');
        if (empty($order_sn)) {
            return json(['code' => 0, 'msg' => '请选择订单!']);
        }
        $order_info = Db::name('order')->where('order_sn',$order_sn)->find();
        if (empty($order_info)) {
            return json(['code' => 0, 'msg' => '订单不存在!']);
        }
        if ($order_info['pay_status']==1) {
            return json(['code' => 0, 'msg' => '订单已经支付!']);
        }
        $params['biz_content'] = json_encode([
            'body'                 => '支付',
            'subject'              => '支付',
            'out_trade_no'         => $order_info['order_sn'],
            'total_amount'         => $order_info['order_amount'],
            'product_code'         => 'QUICK_MSECURITY_PAY',
            'disable_pay_channels' => 'creditCard',
        ], JSON_UNESCAPED_UNICODE);
        # 排序,签名,排序
        $str            = $this->getSignContent($params);
        $params['sign'] = $this->sign($str, $params['sign_type']);
        foreach ($params as $key => $value) {
            if ($key != 'timestamp') {
                $params[$key] = urlencode($value);
            }
        }
        $str = $this->getSignContent($params);
        return json(['code' => 1, 'msg' => '获取成功!', 'data' => $str]);
    }
    public function notify_url() {
        $arr = $_POST;
        //返回格式 {"gmt_create":"2018-09-08 13:03:08","charset":"utf-8","seller_email":"[email protected]","subject":"测试app支付","sign":"gZydvv7bOkzwnkVlsPKky5EDy3BS4OL1NLwnFn64jYCa3geDwAAKiBkpGNI87AVddodixTCz9Ll9hA6T8SYK8xTCFq4VTdbXrW6RGEqVdDfdu75RBSyEflCuf5jkIZXdIxe1C5idvbCthzS7ICvbDp7eYInKFOEgaewrXhs\/ddoaMxeK2etpOJiRi3\/ioSJKGYdvU+ReKXYvWX3dg5+zaQjKp8vLnKjag4XDhBO6yB1xzQYam8jHfJgn\/ZGCAVFOWEHuAHhM2qasWXKZei+gT3OnRHnvcJDhVp0NzLWRJtFiHy02yuaLS+TlLKRcvb4fN+S4e4JWL4lzzPrG6DLUWQ==","body":"测试app支付","buyer_id":"2088212942567899","invoice_amount":"0.01","notify_id":"2018090800222130309067890520057262","fund_bill_list":"[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]","notify_type":"trade_status_sync","trade_status":"TRADE_SUCCESS","receipt_amount":"0.01","app_id":"2018062160408670","buyer_pay_amount":"0.01","sign_type":"RSA2","seller_id":"2088411957695896","gmt_payment":"2018-09-08 13:03:08","notify_time":"2018-09-08 13:03:09","version":"1.0","out_trade_no":"20180621604086000000005","total_amount":"0.01","trade_no":"2018090822001467890528225092","auth_app_id":"2018062160408670","buyer_logon_id":"j.c***@foxmail.com","point_amount":"0.00","result_data":1}
        $check = $this->check($arr);
        if ($check) {
            $out_trade_no = $_POST['out_trade_no'];
            if (empty($out_trade_no)) {
                Db::name('alipay_topay')->insert(['order_sn' => 'log:app订单不存在']);
                exit(0);
            }
            Db::name('alipay_topay')->insert(['order_sn' => $out_trade_no.'app支付']);
            //支付宝交易号
            $trade_no = $_POST['trade_no'];
            //交易状态
            $trade_status = $_POST['trade_status'];
            //交易金额
            $total_amount = $_POST['total_amount'];
            if ($_POST['trade_status'] == 'TRADE_SUCCESS') { // 支付成功
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                //如果有做过处理,不执行商户的业务程序
                //注意:
                //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
                $data = [
                    'order_status' => 1,
                    'pay_status'   => 1,
                    'pay_code'     => 'alipay',
                    'pay_name'     => 'app支付宝支付',
                    'pay_time'     => time(), // $arr['time_end'] 表示非时间戳时间
                ];
                # 判断是否支付,没有支付才进行支付
                $pay_status = Db::name('order')->where('order_sn', $out_trade_no)->value('pay_status');
                if ($pay_status != 1) {
                    $order_amount = Db::name('order')->where('order_sn', $out_trade_no)->value('order_amount');
                    $order_id     = Db::name('order')->where('order_sn', $out_trade_no)->value('order_id');
                    if ($total_amount != $order_amount) {
                        Db::name('alipay_topay')->insert(['order_sn' => $out_trade_no . '支付金额不对:' . $total_amount . '/' . $order_amount]);
                        exit();
                    }
                    Db::name('order')->where('order_sn', $out_trade_no)->update($data);
                    $surplus                = Db::name('order')->where('order_sn', $out_trade_no)->value('voucher_surplus');
                    $uid                    = Db::name('order')->where('order_sn', $out_trade_no)->value('user_id');
                    $voucher_surplus_before = Db::name('users')->where('user_id', $uid)->value('voucher_surplus');
                    Db::name('users')->where('user_id', $uid)->setDec('voucher_surplus', $surplus);
                    Db::name('users')->where('user_id', $uid)->setInc('consume_total', $order_amount);
                    // 支付成功通知
                    $templates = new \app\api\controller\TemplateMsg();
                    $templates->sendOrderTemplate($uid, "支付成功");
                    $templates->sendShareMsg($order_id);
                    $templates->AdminSendOrderTemplate($out_trade_no, "支付成功");
                    $data = [
                        'user_id'      => $uid,
                        'money'        => $surplus,
                        'money_before' => $voucher_surplus_before,
                        'money_last'   => $voucher_surplus_before - $surplus,
                        'type'         => "voucher_surplus",
                        'add_time'     => time(),
                        'remark'       => '抵扣券使用',
                        'ip'           => request()->ip(),
                        'order_sn'     => $out_trade_no,
                    ];
                    Db::name('money_books')->insert($data);
                }
            }
            echo "success";
        } else {
            echo "fail";
        }
        $str = json_encode($arr,JSON_UNESCAPED_UNICODE);
        Db::name('atest')->insert(['info' => $str]);
    }
    public function check($arr) {
        $result = $this->rsaCheckV1($arr, $this->rsaPublicKeyFilePath, $this->sign_type);
        return $result;
    }
    /** rsaCheckV1 & rsaCheckV2 * 验证签名 * 在使用本方法前,必须初始化AopClient且传入公钥参数。 * 公钥是否是读取字符串还是读取文件,是根据初始化传入的值判断的。 **/
    public function rsaCheckV1($params, $rsaPublicKeyFilePath, $signType = 'RSA') {
        $sign = $params['sign'];
        unset($params['sign']);
        unset($params['sign_type']);
        return $this->verify($this->getSignContent($params), $sign, $rsaPublicKeyFilePath, $signType);
    }
    public function verify($data, $sign, $rsaPublicKeyFilePath, $signType = 'RSA') {

        if ($this->checkEmpty($this->rsaPublicKeyFilePath)) {
            $pubKey = $this->alipayrsaPublicKey;
            $res    = "-----BEGIN PUBLIC KEY-----\n" .
            wordwrap($pubKey, 64, "\n", true) .
                "\n-----END PUBLIC KEY-----";
        } else {
            //读取公钥文件
            $pubKey = file_get_contents($rsaPublicKeyFilePath);
            //转换为openssl格式密钥
            $res = openssl_get_publickey($pubKey);
        }
        ($res) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确');
        //调用openssl内置方法验签,返回bool值
        if ("RSA2" == $signType) {
            $result = (bool) openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256);
        } else {
            $result = (bool) openssl_verify($data, base64_decode($sign), $res);
        }
        if (!$this->checkEmpty($this->rsaPublicKeyFilePath)) {
            //释放资源
            openssl_free_key($res);
        }
        return $result;
    }
    public function make_sign($it_b_pay, $service, $body, $out_trade_no, $partner, $_input_charset, $notify_url, $subject, $payment_type, $seller_id, $total_fee, $sign_type) {
        $params['it_b_pay']       = $it_b_pay;
        $params['service']        = $service;
        $params['body']           = $body;
        $params['out_trade_no']   = $out_trade_no;
        $params['partner']        = $partner;
        $params['_input_charset'] = $_input_charset;
        $params['notify_url']     = $notify_url;
        $params['subject']        = $subject;
        $params['payment_type']   = $payment_type;
        $params['seller_id']      = $seller_id;
        $params['total_fee']      = $total_fee;
        ksort($params);
        $sign = $this->generateSign($params, $sign_type);
        return $sign;
    }
    public function generateSign($params, $signType = "RSA") {
        return $this->sign($this->getSignContent($params), $signType);
    }
    protected function sign($data, $signType = "RSA") {
        if ($this->checkEmpty($this->rsaPrivateKeyFilePath)) {
            $priKey = $this->rsaPrivateKey;
            $res    = "-----BEGIN RSA PRIVATE KEY-----\n" .
            wordwrap($priKey, 64, "\n", true) .
                "\n-----END RSA PRIVATE KEY-----";
        } else {
            $priKey = file_get_contents($this->rsaPrivateKeyFilePath);
            $res    = openssl_get_privatekey($priKey);
        }
        ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置');

        if ("RSA2" == $signType) {
            openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);
        } else {
            openssl_sign($data, $sign, $res);
        }

        if (!$this->checkEmpty($this->rsaPrivateKeyFilePath)) {
            openssl_free_key($res);
        }
        $sign = base64_encode($sign);
        return $sign;
    }
    protected 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->postCharset);

                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . "$v";
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }
        unset($k, $v);
        return $stringToBeSigned;
    }
    /** * 校验$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;
    }
    /** * 转换字符集编码 * @param $data * @param $targetCharset * @return string */
    public function characet($data, $targetCharset) {

        if (!empty($data)) {
            $fileType = $this->fileCharset;
            if (strcasecmp($fileType, $targetCharset) != 0) {
                $data = mb_convert_encoding($data, $targetCharset, $fileType);
                // $data = iconv($fileType, $targetCharset.'//IGNORE', $data);
            }
        }

        return $data;
    }
}

你可能感兴趣的:(apicloud)