一、支付功能
1.1 支付宝支付安装配置
然后支付宝扫码登陆。因为个人号是没法去申请支付密钥,所以我们使用它的沙箱环境。
沙箱环境下我们这边都可以随便充值金额。
同样的在laravel
中开发可以使用第三方包,来加快我们开发的进度,以及非常简便的使用。
运行命令composer require yansongda/laravel-pay
:
运行命令php artisan vendor:publish --provider="Yansongda\LaravelPay\PayServiceProvider" --tag=laravel-pay
配置文件:
接着按照文档。生成公钥证书,
下载安装文档指定生成即可。
将下载的证书放到code
文件夹下:
我是将3个证书文件放到自己新建文件夹cert
下。
接着修改配置:
'alipay' => [
'default' => [
// 支付宝分配的 app_id 沙箱测试就有
'app_id' => '2021000118617661',
// 应用私钥
'app_secret_cert' => '', // 你申请的证书密钥
// 应用公钥证书 路径
'app_public_cert_path' => '/home/vagrant/code/cert/appCertPublicKey_2021000118617661.crt',
// 支付宝公钥证书 路径
'alipay_public_cert_path' => '/home/vagrant/code/cert/alipayCertPublicKey_RSA2.crt',
// 支付宝根证书 路径
'alipay_root_cert_path' => '/home/vagrant/code/cert/alipayRootCert.crt',
// 支付成功后同步通知地址
'return_url' => '',
// 异步通知地址
'notify_url' => 'http://8bee-211-97-129-32.ngrok.io/api/pay/notify/aliyun', // 你的支付完成回调地址处理路由,这边采用了内网穿透的方式,在本章第4小节有说到配置
'mode' => Pay::MODE_SANDBOX, // 沙箱环境,由于我们没有商户号,所以采用沙箱环境配置
// 'mode' => Pay::MODE_NORMAL, // 正式环境
],
],
1.2 创建支付控制器
运行命令php artisan make:controller Web/PayController
写入支付时的方法,以及支付完成时的回调方法:
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Yansongda\LaravelPay\Facades\Pay;
class PayController extends Controller
{
// 支付
public function pay(Request $request, Order $order)
{
$request->validate([
'type' => 'required|in:aliyun,wechat',
], [
'type.required' => '支付类型不能为空',
'type.in' => '支付类型只能是支付宝或者微信支付'
]);
// 如果订单状态不是1,直接返回
if ($order->status != 1) {
return $this->response->errorBadRequest('订单状态异常,请重新下单!');
}
if ($request->input('type') == 'aliyun') {
$order = [
'out_trade_no' => $order->order_no,
'total_amount' => $order->amount/100,
'subject' => $order->goods()->first()->title.' 等 '.$order->goods()->count() .'件商品',
];
return Pay::alipay()->scan($order);
}
if ($request->input('type') == 'wechat') {
}
}
/**
* 支付宝支付成功之后的回调
*/
public function notifyAliyun(Request $request) {
$alipay = Pay::alipay();
try{
$data = $alipay->callback(); // 是的,验签就这么简单!
// 请自行对 trade_status 进行判断及其它逻辑进行判断,在支付宝的业务通知中,只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时,支付宝才会认定为买家付款成功。
// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号;
// 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额);
// 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email);
// 4、验证app_id是否为该商户本身。
// 5、其它业务逻辑情况
// 判断支付状态 成功的状态
if ($data->trade_status == 'TRADE_SUCCESS' || $data->trade_status == 'TRADE_FINISHED') {
// 查询订单
$order = Order::where('order_no', $data->out_trade_no)->first();
// 更新订单数据 (简单的写,如果要完整的要按照以上5点去写)
$order->update([
'status' => 2, // 支付完成
'pay_time' => $data->gmt_payment, // 支付的时间
'pay_type' => '支付宝', // 支付的类型
'trade_no' => $data->trade_no, // 支付宝的单号 在写的退款的时候会用到
]);
}
// Log::info($data); 打印log知道回调都给了什么字段
Log::debug('Alipay notify', $data->all()); // 打印log知道回调都给了什么字段
} catch (\Exception $e) {
// $e->getMessage();
}
return $alipay->success();
}
}
我们在支付回调时候插入的数据,所以Order.php
需要增加可允许批量赋值的字段:
1.3 创建支付路由
/**
* 支付
*/
$api->get('orders/{order}/pay', [PayController::class, 'pay']);
1.4 内网穿透
由于我们使用的是本地的域名,外网是访问不到,这个支付宝的回调函数它就请求不到,所以我们这边需要配置内网穿透:
运行命令share shopprojectapi.com
(shopprojectapi.com是你自己配置的域名
)
会出现报错:-bash: /usr/local/bin/ngrok: cannot execute binary file: Exec format error
原因很简单,却弄了几个小时,是因为我的电脑是m1 arm64
架构的,而homestead
中ngrok
估计不是,所以我们去官网下载ngrok
的linux
下载完解压后将虚拟机上这个路径/usr/local/bin/ngrok
的ngrok
替换,可以使用工具FileZilla
。
替换之后,接着运行命令share shopprojectapi.com
,可以看到:
接着访问它给我们的域名,可以看到外网已经可以访问到我们的内网项目了:
1.5 创建支付完成回调路由
需要注意的是这个回调路由是不需要登陆的,所以放在需要登陆中间件的外面。
/**
* 回调
*/
// 支付宝支付成功之后的回调
$api->any('pay/notify/aliyun', [PayController::class, 'notifyAliyun']);
1.6 测试效果
支付接口
生成链接,我们将链接通过该网址转为二维码,下载沙箱测试的支付宝版本
然后扫描生成的二维码,然后点击支付,支付成功后,我们查看订单是否有数据插入:
可以看到我们这条订单就是状态2了,并且也有支付宝的订单号。至此我们支付宝支付的功能已经相当完善了。
微信支付的话也是一样的申请商户号,配置方法逻辑和支付宝类似。
在学习的php的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。