使用支付宝沙箱的方法

准备

我们接下来要为网站中添加支付的功能,在添加这些功能之前,我们需要先做些准备的工作。

curl

curl 是一个比较常用的小软件,它可以用来在命令行中发送 GET 、POST 等请求,在开发时非常有用。

可以在命令行中输入 curl 来查看是否电脑已经安装了该软件,如果没有安装可以下载安装。

如果已经安装了会提示以下信息:(注意是cmd中执行,不是 powershell中~)

image-20180906152846884

curl下载地址:https://curl.haxx.se/download.html,如下图所示:**

image-20180828170832374

安装扩展包

专注 支付宝微信支付 的支付扩展包。

composer require yansongda/pay

使用文档:https://packagist.org/packages/yansongda/pay

支付宝

image-20180828162125062

获取沙箱参数

支付宝有一个沙箱环境,可以让我们不需要拥有真实的商家账号就可以进行支付的开发测试。

首先到支付定的开放平台中注册账号 https://open.alipay.com/platform/home.htm,用你的支付宝账号登录并找到沙箱环境:

image-20180828162720396

进入沙箱之后,我们可以得到 APPID,然后点击设置应用公钥:

image-20180828162804856

点击设置应用公钥:

image-20180828162840788

点击设置公钥按钮:

image-20180828162950239

点击 查看密钥生成方法 链接之后会跳转到一篇文档,里面可以下载 RSA 密钥生成工具,请根据自己的系统下载对应的版本并打开:

image-20180828163039944

复制公钥内容到框中:

image-20180828163118867

点击保存之后,查看支付宝公钥

image-20180828163148944

复制这段支付宝公钥:

image-20180828163213391

到此我们得到了以下三个参数,我们在代码里面要使用!!:

APPID:

image-20180907105411040

2016091600527626

商户应用私钥:

image-20180907105431202

MIIEpAIBAAKCAQEAuoy1DMW1bDvNQc7CZOALVRERL+wcVV3UhbP59ICtpBx+zGiEsDuOmAFAcEPDwGNk4NhXdAkN9n/1jGiSZaKwfkBNU3tmyuYVLH0shgGzWL/S4XG51EwonUH2a6rVaI2OaiAjUXcYPfxbnpo/52PwiF8B/bfezUp+G6pjC0UbxruO2tE8nyfCq0cz1qYNGBulmECPyG5y69ECtiwVvw/+cK3rm+lxlSCUXp5cqB+HaGgd+trXLOJxZONd/fPkmKEts1pllCkTsDTxT77O0ZLtM5+D1e7VE68OMiIQvNRyl1p+HNQjsUNVX62cNfRb3cjtET5wqUT56AOeJgl9qVDDFwIDAQABAoIBAQCoy9C2sd6rBKGBPjifVipq2nqWxioNBE3cfTFaj2SO7km9Y4VMgVdRKzDHZEmnt0f8O0VGdTrxJG9mkOiGlmLkmgJd23bzeKUIEGtNBhTl5QxHecQP2KmXQaxbV8SqSgvm8xWCDSUeUU4FgMT59nAatPz0On+beiAJoG7mL64mbtuW8YsUB0wIFhTwe1T1+Q9qTO+YEh4ejteXZc1flGahjGDJbzCWwErmMILAAopiNaLNDcgx3AXeqf+ddP6jK32MikXhddYSDogX7/BXIMkOg7co5gXCG/aXMueMKsuR2wWC+pUZfxl7VBM8IEBfR8ptq9DIE8QcfMWYml4qpPNhAoGBAOZ0twlxxPGthlJ1q1EWdUy6qGD/yzHvVY0TEW4dXTJNqBv4GyF0sQktDRG0FCQtqk1lzbOHcbsEz737xwn9EpuJGWqFB4gy3Z1e77Dr5qM6bXScm5HSPX7MfC99H6cu4uxogrGLqlgE/S7OO0bNFEU4nFNcaASqZjcH9C82P1FTAoGBAM86If8Sk1tYm/TqT8p9IB2ww8+mNwZo7AVrTgYvmampRPfDX0UrmrlkdZLJVbdxYLNexmu+AwsvS3XXknWNyPf6UXqELPYNO9y+0VNusNRl03UabW4Czf5QWZPSlC0bu8xbBjVUA3O761XMfBbPtS7/X41wn3/4w1T2eGVyPjqtAoGAOMiBYR5bPIFZG3BK6gvykxla66ubUY57MeuE2/D4SbDAv0N+y9uI0436LmaEn/VwhOmUqaux5jblSRaEkH1+3DwHuytUE8cUu/XscVdu2MFIvvbnjiKTbG7OGpVl+zeeSknmCgEz08RG7gV6rZNSb0vnmNKn/p5N2TlofUmMiGkCgYApXKgWeoWxEOGoI/CjMRBs/LBIzRtkiyK4/i8Hqw6Xv7KFZZipfMeYQ4X4M3mJcPblNoCSVs3SuLDuJ4YTMqavYGZM9v7macPODsRHS+u9qUlosUqwT50AKteGWty6mDOG2ZBGqqs5uYOCj5shDnpSlCRlXdpoN6X9Wmizjvb+zQKBgQCJl5ppVH363lV6cY1dVY80oEfLHBaiMom3O/N5WcDe6G4rulBvJYtZeTF2A/EoYozsPz25MrtEFCwvluNFoH36U6hg5HL8HiXYdbp442KY/GMWLYJsSpWo737fmU5hlSqrqzOYy+ukGX/toKgBAMC72UY2S4Z5gaywlUA9GiNPHg==

支付宝公钥:(注意:这里是支付宝公钥!!!!!! 不是商户应用公钥)

image-20180907105457043

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcDiUmAFgiaBi2PzVpP+GdyPNLQuja3B26Z/3tcDDiuWbndLaA4o45J+Xj6KZ2GgQpZe5a9ZGoasas7YLGxPA5Z91eTooqmVwfPsaTUx4JHJlhiS+3R4738kA7BCXvmVKAHjG52ExwjwM4XWh+zN0jldPaS+4EtZnCrciDQtUk7IU7hbjDwqe6mUzwpI0zgyGQ0CPvug1VJBLdRgOlIaGNwVn1WbwqkrXYkHXMKHZhgT/WF4UTr+X4TpFIyA24ZVl2BtLchvFvf9C0+Ui8pWjfxjD6uE1VHtVQNEJ4MIaisfXpDMgQgkqClYDQN/udub7mq/CQUGsm9ZN5SUJEUXLwIDAQAB

支付流程

image-20180906155807746

立即支付

创建支付控制器:

controllers/AlipayController.php

<?php
namespace controllers;

use Yansongda\Pay\Pay;

class AlipayController
{
    public $config = [
        'app_id' => '2016091600527626',
        // 通知地址
        'notify_url' => 'http://requestbin.fullcontact.com/r6s2a1r6',
        // 跳回地址
        'return_url' => 'http://localhost:9999/alipay/return',
        // 支付宝公钥
        'ali_public_key' => 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcDiUmAFgiaBi2PzVpP+GdyPNLQuja3B26Z/3tcDDiuWbndLaA4o45J+Xj6KZ2GgQpZe5a9ZGoasas7YLGxPA5Z91eTooqmVwfPsaTUx4JHJlhiS+3R4738kA7BCXvmVKAHjG52ExwjwM4XWh+zN0jldPaS+4EtZnCrciDQtUk7IU7hbjDwqe6mUzwpI0zgyGQ0CPvug1VJBLdRgOlIaGNwVn1WbwqkrXYkHXMKHZhgT/WF4UTr+X4TpFIyA24ZVl2BtLchvFvf9C0+Ui8pWjfxjD6uE1VHtVQNEJ4MIaisfXpDMgQgkqClYDQN/udub7mq/CQUGsm9ZN5SUJEUXLwIDAQAB',
        // 商户应用密钥
        'private_key' => 'MIIEpAIBAAKCAQEAuoy1DMW1bDvNQc7CZOALVRERL+wcVV3UhbP59ICtpBx+zGiEsDuOmAFAcEPDwGNk4NhXdAkN9n/1jGiSZaKwfkBNU3tmyuYVLH0shgGzWL/S4XG51EwonUH2a6rVaI2OaiAjUXcYPfxbnpo/52PwiF8B/bfezUp+G6pjC0UbxruO2tE8nyfCq0cz1qYNGBulmECPyG5y69ECtiwVvw/+cK3rm+lxlSCUXp5cqB+HaGgd+trXLOJxZONd/fPkmKEts1pllCkTsDTxT77O0ZLtM5+D1e7VE68OMiIQvNRyl1p+HNQjsUNVX62cNfRb3cjtET5wqUT56AOeJgl9qVDDFwIDAQABAoIBAQCoy9C2sd6rBKGBPjifVipq2nqWxioNBE3cfTFaj2SO7km9Y4VMgVdRKzDHZEmnt0f8O0VGdTrxJG9mkOiGlmLkmgJd23bzeKUIEGtNBhTl5QxHecQP2KmXQaxbV8SqSgvm8xWCDSUeUU4FgMT59nAatPz0On+beiAJoG7mL64mbtuW8YsUB0wIFhTwe1T1+Q9qTO+YEh4ejteXZc1flGahjGDJbzCWwErmMILAAopiNaLNDcgx3AXeqf+ddP6jK32MikXhddYSDogX7/BXIMkOg7co5gXCG/aXMueMKsuR2wWC+pUZfxl7VBM8IEBfR8ptq9DIE8QcfMWYml4qpPNhAoGBAOZ0twlxxPGthlJ1q1EWdUy6qGD/yzHvVY0TEW4dXTJNqBv4GyF0sQktDRG0FCQtqk1lzbOHcbsEz737xwn9EpuJGWqFB4gy3Z1e77Dr5qM6bXScm5HSPX7MfC99H6cu4uxogrGLqlgE/S7OO0bNFEU4nFNcaASqZjcH9C82P1FTAoGBAM86If8Sk1tYm/TqT8p9IB2ww8+mNwZo7AVrTgYvmampRPfDX0UrmrlkdZLJVbdxYLNexmu+AwsvS3XXknWNyPf6UXqELPYNO9y+0VNusNRl03UabW4Czf5QWZPSlC0bu8xbBjVUA3O761XMfBbPtS7/X41wn3/4w1T2eGVyPjqtAoGAOMiBYR5bPIFZG3BK6gvykxla66ubUY57MeuE2/D4SbDAv0N+y9uI0436LmaEn/VwhOmUqaux5jblSRaEkH1+3DwHuytUE8cUu/XscVdu2MFIvvbnjiKTbG7OGpVl+zeeSknmCgEz08RG7gV6rZNSb0vnmNKn/p5N2TlofUmMiGkCgYApXKgWeoWxEOGoI/CjMRBs/LBIzRtkiyK4/i8Hqw6Xv7KFZZipfMeYQ4X4M3mJcPblNoCSVs3SuLDuJ4YTMqavYGZM9v7macPODsRHS+u9qUlosUqwT50AKteGWty6mDOG2ZBGqqs5uYOCj5shDnpSlCRlXdpoN6X9Wmizjvb+zQKBgQCJl5ppVH363lV6cY1dVY80oEfLHBaiMom3O/N5WcDe6G4rulBvJYtZeTF2A/EoYozsPz25MrtEFCwvluNFoH36U6hg5HL8HiXYdbp442KY/GMWLYJsSpWo737fmU5hlSqrqzOYy+ukGX/toKgBAMC72UY2S4Z5gaywlUA9GiNPHg==',
        // 沙箱模式(可选)
        'mode' => 'dev',
    ];
    // 发起支付
    public function pay()
    {
        $order = [
            'out_trade_no' => time(),    // 本地订单ID
            'total_amount' => '0.01',    // 支付金额
            'subject' => 'test subject', // 支付标题
        ];

        $alipay = Pay::alipay($this->config)->web($order);

        $alipay->send();
    }
    // 支付完成跳回
    public function return()
    {
        $data = Pay::alipay($this->config)->verify(); // 是的,验签就这么简单!
        echo '<h1>支付成功!</h1> <hr>';
        var_dump( $data->all() );
    }
    // 接收支付完成的通知
    public function notify()
    {
        $alipay = Pay::alipay($this->config);
        try{
            $data = $alipay->verify(); // 是的,验签就这么简单!
            // 这里需要对 trade_status 进行判断及其它逻辑进行判断,在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
            // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号;
            // 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额);
            echo '订单ID:'.$data->out_trade_no ."\r\n";
            echo '支付总金额:'.$data->total_amount ."\r\n";
            echo '支付状态:'.$data->trade_status ."\r\n";
            echo '商户ID:'.$data->seller_id ."\r\n";
            echo 'app_id:'.$data->app_id ."\r\n";
        } catch (\Exception $e) {
            echo '失败:';
            var_dump($e->getMessage()) ;
        }
        // 返回响应
        $alipay->success()->send();
    }
}

浏览器中访问 http://localhost:9999/aliypay/pay 跳转到支付宝网站:

image-20180906163609195

使用沙箱账号完成支付:

image-20180828163720996

支付通知

在支付宝网站当中完成支付之后,支付宝网站会做两种事件:

  1. 跳转回我们的网站
  2. 在后台向我们的网站发消息通知我们已经支付成功,我们收到通知之后需要回复收到通知,否则支付宝会定期重复的向我们发消息

我们需要在设置在设置 支付成功跳转地址支付成功的通知地址

$config = [
    ...
    'notify_url' => 'http://localhost:9999/alipay/notify',   // 支付成功后台通知地址
    'return_url' => 'http://localhost:9999/alipay/return',   // 支付成功后跳转地址
    ...
];

回调通知

因为我们的项目现在处在内网之中(http://localhost:9999/alipay/notify),支付宝向我们发的通知,我们现在根本就收不到,我们需要把网站放到外网上线之后才能收到通知。

我们便于开发,我们可以借助一些第三方的网站来帮我们接收通知。

RequestBin 网站就是一个接收各种通知的网站,我们可以借助它来接收通知。

1、创建新的接收地址

首先我们需要先创建网站创建一个用来接收通知的地址。

访问 https://requestbin.fullcontact.com/ ,点击中间那个绿按钮 Create a RequestBin

image-20180828165824684

系统会分配一个 URL:

image-20180828165847040

这个 URL 就是我们用来接收通知的地址,把这个地址放到支付时的通知地址上:

$config = [
    ...
    'notify_url' => 'http://requestbin.fullcontact.com/r6s2a1r6',   // 支付成功后台通知地址
    ...
];

设置好通知地址之后,重新完成一次支付流程,支付成功之后,到网站中查看接收到的通知。

点击以下小圆点查看接收到的消息:

image-20180828165918180

然后点击查看已经收到了数据:

image-20180828165945623

复制最下方 的数据:

image-20180828170056437

最下方的 RAW BODY,就是支付宝发给我们的通知。

处理通知

现在我们通过 ResustBin 网站接收到的支付宝的通知,现在我们就可以手动的把这个通知发给我们自己的网站,我们可以使用 curl 指令完成该操作。

使用 curl 把数据以 POST 方式发给我们的网站:

$ curl -XPOST http://localhost:9999/alipay/notify -d'复制 raw body 内容'

如:

image-20180906170009373

发送之后会显示违法操作,这是因为我们之前项目中添加了 CSRF 防御功能,所以这里我们先注释掉 CSRF 防御的代码。

<?php
// 使用 redis 保存 SESSION
ini_set('session.save_handler', 'redis');
// 设置 redis 服务器的地址、端
ini_set('session.save_path', 'tcp://127.0.0.1:32768?database=3');

session_start();

// 如果用户以 POST 方式访问网站时,需要验证令牌
// if($_SERVER['REQUEST_METHOD'] == 'POST')
// {
//     if(!isset($_POST['_token']))
//         die('违法操作!');

//     if($_POST['_token'] != $_SESSION['token'])
//         die('违法操作!');
// }

去掉之后,就可以接收通知了。

通知数据

支付宝在给我们发送通知时,会传递以下数据:

array(23) {
  ["gmt_create"]=>
  string(19) "2018-09-06 17:51:14"
  ["charset"]=>
  string(3) "GBK"
  ["gmt_payment"]=>
  string(19) "2018-09-06 17:51:19"
  ["notify_time"]=>
  string(19) "2018-09-06 17:51:20"
  ["subject"]=>
  string(12) "test subject"
  ["sign"]=>
  string(344) "cL6kVn8q5UQdnzoM1RmKR8GR8Z3kg7RQ5ftpg9GatlLQLodnw1r2RLPgkKXTYgGwi6ZqNuKgQzGacYNSpdk7arWAzfeFEl266KR73y0WM+bvGVFaBejX9jLl4WTIyzn742WoJfFklA3hleYh9q8DlFeJQh6acFEwvx9GJiuxv5521xWWNN91mzLF2a4XHjkIvFqZBYU/hc1CFCx/9+bBTNebf9sOBsD0H3q9NiQrnSfI9EQ9n2UYF/NYPhsrZ0ZV/jej5CPbHyggic8OQUszmknm8EEga5VjtGRs+oJQZHI9K+HrpeFTdtmX2Ecyv/Ob7D+qLSsiGndlllOGoZ7lRQ=="
  ["buyer_id"]=>
  string(16) "2088102176659083"
  ["invoice_amount"]=>
  string(4) "0.01"
  ["version"]=>
  string(3) "1.0"
  ["notify_id"]=>
  string(34) "a835b845abf96ff1e5c23a20d9b6505gmd"
  ["fund_bill_list"]=>
  string(49) "[{"amount":"0.01","fundChannel":"ALIPAYACCOUNT"}]"
  ["notify_type"]=>
  string(17) "trade_status_sync"
  ["out_trade_no"]=>
  string(10) "1536227456"
  ["total_amount"]=>
  string(4) "0.01"
  ["trade_status"]=>
  string(13) "TRADE_SUCCESS"
  ["trade_no"]=>
  string(28) "2018090621001004080500252780"
  ["auth_app_id"]=>
  string(16) "2016091600527626"
  ["receipt_amount"]=>
  string(4) "0.01"
  ["point_amount"]=>
  string(4) "0.00"
  ["app_id"]=>
  string(16) "2016091600527626"
  ["buyer_pay_amount"]=>
  string(4) "0.01"
  ["sign_type"]=>
  string(4) "RSA2"
  ["seller_id"]=>
  string(16) "2088102175946009"
}

退款

退款时也需要有一个订单号,之后通过这个订单号可以在支付宝中查看退款的进度。

// 退款
public function refund()
{
    // 生成唯一退款订单号
    $refundNo = md5( rand(1,99999) . microtime() );
    try{
        // 退款
        $ret = Pay::alipay($this->config)->refund([
            'out_trade_no' => '1536227456',    // 之前的订单流水号
            'refund_amount' => 0.01,              // 退款金额,单位元
            'out_request_no' => $refundNo,     // 退款订单号
        ]);
        if($ret->code == 10000)
        {
            echo '退款成功!';
        }
    }
    catch(\Exception $e)
    {
        var_dump( $e->getMessage() );
    }
}

退款结果

退款之后,如果服务器返回的 code 是 10000 则说明退款成功:

if($ret->code == 10000)
{
    echo '退款成功!';
}
else
{
    echo '退款失败,错误信息'.$ret->sub_msg;
    echo '错误编号':$ret->sub_code;
}

作业:用户充值系统

  1. 显示一个充值的表单,用户输入充值金额 ,点击充值按钮
  2. 在本地生成一个充值的订单,跳转到订单列表页
  3. 在列表中显示支付按钮,
  4. 用户点击支付按钮跳转到支付宝支付
  5. 支付成功之后,订单状态变为已支付,并且为用户账号中添加相应的积分
  6. 30分钟之内 ,用户还可以退款

上一篇
JavaScript高级题 JavaScript高级题
JavaScript高级题1.Java和JavaScript是什么关系?就像雷锋和雷霆塔的关系一样。 一般认为,当时 Netscape 之所以将 LiveScript 命名为 JavaScript,是因为 Java 是当时最流行的编程语言,
2018-12-25
下一篇
使用微信支付接口的方法 使用微信支付接口的方法
微信支付 微信支付的开发需要有一个微信公众号并且开通了微信支付才能正常进行,申请微信支付需要有公司资质。对于手上没有支付商户号的同学,可以下载测试账号体验基本的支付功能。 测试账号首先,我们需要访问 https://pay.weixin
2018-12-19