使用插件:
https://packagist.org/packages/yansongda/pay
1、注册服务,,调用 Yansongda\Pay 来创建一个支付宝支付对象
2、配置文件
3、代码控制器
<?php
namespace App\Http\Controllers;
use App\Events\OrderPaid;
use App\Exceptions\InvalidRequestException;
use App\Models\Order;
use Carbon\Carbon;
use Endroid\QrCode\QrCode;
use Illuminate\Http\Request;
class PaymentController extends Controller
{
public function payByAlipay(Order $order, Request $request)
{
// 判断订单是否属于当前用户
$this->authorize('own', $order);
// 订单已支付或者已关闭
if ($order->paid_at || $order->closed) {
throw new InvalidRequestException('订单状态不正确');
}
// 调用支付宝的网页支付
return app('alipay')->web([
'out_trade_no' => $order->no, // 订单编号,需保证在商户端不重复
'total_amount' => $order->total_amount, // 订单金额,单位元,支持小数点后两位
'subject' => '支付 Laravel Shop 的订单:'.$order->no, // 订单标题
]);
}
public function alipayReturn()
{
try {
app('alipay')->verify();
} catch (\Exception $e) {
return view('pages.error', ['msg' => '数据不正确']);
}
return view('pages.success', ['msg' => '付款成功']);
}
public function alipayNotify()
{
// 校验输入参数
$data = app('alipay')->verify();
// 如果订单状态不是成功或者结束,则不走后续的逻辑
// 所有交易状态:https://docs.open.alipay.com/59/103672
if(!in_array($data->trade_status, ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
return app('alipay')->success();
}
// $data->out_trade_no 拿到订单流水号,并在数据库中查询
$order = Order::where('no', $data->out_trade_no)->first();
// 正常来说不太可能出现支付了一笔不存在的订单,这个判断只是加强系统健壮性。
if (!$order) {
return 'fail';
}
// 如果这笔订单的状态已经是已支付
if ($order->paid_at) {
// 返回数据给支付宝
return app('alipay')->success();
}
$order->update([
'paid_at' => Carbon::now(), // 支付时间
'payment_method' => 'alipay', // 支付方式
'payment_no' => $data->trade_no, // 支付宝订单号
]);
$this->afterPaid($order);
return app('alipay')->success();
}
public function payByWechat(Order $order, Request $request)
{
$this->authorize('own', $order);
if ($order->paid_at || $order->closed) {
throw new InvalidRequestException('订单状态不正确');
}
// 之前是直接返回,现在把返回值放到一个变量里
$wechatOrder = app('wechat_pay')->scan([
'out_trade_no' => $order->no,
'total_fee' => $order->total_amount * 100,
'body' => '支付 Laravel Shop 的订单:'.$order->no,
]);
// 把要转换的字符串作为 QrCode 的构造函数参数
$qrCode = new QrCode($wechatOrder->code_url);
// 将生成的二维码图片数据以字符串形式输出,并带上相应的响应类型
return response($qrCode->writeString(), 200, ['Content-Type' => $qrCode->getContentType()]);
}
public function wechatNotify()
{
// 校验回调参数是否正确
$data = app('wechat_pay')->verify();
// 找到对应的订单
$order = Order::where('no', $data->out_trade_no)->first();
// 订单不存在则告知微信支付
if (!$order) {
return 'fail';
}
// 订单已支付
if ($order->paid_at) {
// 告知微信支付此订单已处理
return app('wechat_pay')->success();
}
// 将订单标记为已支付
$order->update([
'paid_at' => Carbon::now(),
'payment_method' => 'wechat',
'payment_no' => $data->transaction_id,
]);
$this->afterPaid($order);
return app('wechat_pay')->success();
}
protected function afterPaid(Order $order)
{
event(new OrderPaid($order));
}
public function wechatRefundNotify(Request $request)
{
// 给微信的失败响应
$failXml = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>';
$data = app('wechat_pay')->verify(null, true);
// 没有找到对应的订单,原则上不可能发生,保证代码健壮性
if(!$order = Order::where('no', $data['out_trade_no'])->first()) {
return $failXml;
}
if ($data['refund_status'] === 'SUCCESS') {
// 退款成功,将订单退款状态改成退款成功
$order->update([
'refund_status' => Order::REFUND_STATUS_SUCCESS,
]);
} else {
// 退款失败,将具体状态存入 extra 字段,并表退款状态改成失败
$extra = $order->extra;
$extra['refund_failed_code'] = $data['refund_status'];
$order->update([
'refund_status' => Order::REFUND_STATUS_FAILED,
'extra' => $extra
]);
}
return app('wechat_pay')->success();
}
}
4、说明
该文档为 v2.x 版本,如果您想找 v1.x 版本文档,请点击
https://github.com/yansongda/pay/tree/v1.x
注意:v1.x 与 v2.x 版本不兼容
开发了多次支付宝与微信支付后,很自然产生一种反感,惰性又来了,想在网上找相关的轮子,可是一直没有找到一款自己觉得逞心如意的,要么使用起来太难理解,要么文件结构太杂乱,只有自己撸起袖子干了。
!!请先熟悉 支付宝/微信 说明文档!!请具有基本的 debug 能力!!
6、官方文档地址:
https://opendocs.alipay.com/apis/api_1
https://pay.weixin.qq.com/wiki/doc/api/index.html
2021年5月17日17:59:42
版权声明:本文为php_xml原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。