微信支付
parent
959f8d3503
commit
f0c94a6356
|
|
@ -6,47 +6,49 @@ use App\Events\OrderPaid;
|
||||||
use App\Exceptions\BizException;
|
use App\Exceptions\BizException;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\OrderRefundLog;
|
use App\Models\OrderRefundLog;
|
||||||
use App\Services\OrderService;
|
use App\Services\PayService;
|
||||||
use App\Services\WeChatPayService;
|
use App\Services\WeChatPayService;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class WeChatPayController extends Controller
|
class WeChatPayController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* 订单支付结果通知
|
* 支付结果通知
|
||||||
*
|
*
|
||||||
* @param \App\Services\WeChatPayService $weChatPayService
|
* @param \App\Services\WeChatPayService $weChatPayService
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\Response
|
||||||
*/
|
*/
|
||||||
public function orderPaidNotify(WeChatPayService $weChatPayService)
|
public function paidNotify(WeChatPayService $weChatPayService)
|
||||||
{
|
{
|
||||||
return $weChatPayService->handlePaidNotify(function ($message, $fail) {
|
return $weChatPayService->handlePaidNotify(function ($message, $fail) {
|
||||||
$this->log('order paid notify', $message);
|
|
||||||
|
|
||||||
// 通信失败
|
// 通信失败
|
||||||
if (data_get($message, 'return_code') !== 'SUCCESS') {
|
if (data_get($message, 'return_code') !== 'SUCCESS') {
|
||||||
return $fail('通信失败');
|
return $fail('通信失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 支付失败
|
|
||||||
if (data_get($message, 'result_code') !== 'SUCCESS') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$order = DB::transaction(function () use ($message) {
|
$payLog = DB::transaction(function () use ($message) {
|
||||||
return (new OrderService())->paySuccess($message['out_trade_no'], [
|
$payService = new PayService();
|
||||||
'pay_sn' => $message['transaction_id'],
|
|
||||||
'pay_way' => Order::PAY_WAY_WXPAY,
|
if (data_get($message, 'result_code') !== 'SUCCESS') {
|
||||||
|
return $payService->payFailed($message['out_trade_no'], [
|
||||||
|
'pay_sn' => $message['transaction_id'] ?? null,
|
||||||
|
'failed_reason' => '['.$message['err_code'].']'.$message['err_code_des'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $payService->paySuccess($message['out_trade_no'], [
|
||||||
|
'out_trade_no' => $message['transaction_id'],
|
||||||
'pay_at' => Carbon::parse($message['time_end']),
|
'pay_at' => Carbon::parse($message['time_end']),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
OrderPaid::dispatchIf($order->isPaid(), $order);
|
if ($payLog->payable instanceof Order) {
|
||||||
|
OrderPaid::dispatchIf($payLog->payable->isPaid(), $payLog->payable);
|
||||||
|
}
|
||||||
} catch (ModelNotFoundException | BizException $e) {
|
} catch (ModelNotFoundException | BizException $e) {
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
throw $e;
|
throw $e;
|
||||||
|
|
@ -65,8 +67,6 @@ class WeChatPayController extends Controller
|
||||||
public function orderRefundedNotify(WeChatPayService $weChatPayService)
|
public function orderRefundedNotify(WeChatPayService $weChatPayService)
|
||||||
{
|
{
|
||||||
return $weChatPayService->handleRefundedNotify(function ($message, $reqInfo, $fail) {
|
return $weChatPayService->handleRefundedNotify(function ($message, $reqInfo, $fail) {
|
||||||
$this->log('order refunded notify', $reqInfo);
|
|
||||||
|
|
||||||
// 通信失败
|
// 通信失败
|
||||||
if (data_get($message, 'return_code') !== 'SUCCESS') {
|
if (data_get($message, 'return_code') !== 'SUCCESS') {
|
||||||
return $fail('通信失败');
|
return $fail('通信失败');
|
||||||
|
|
@ -85,19 +85,4 @@ class WeChatPayController extends Controller
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 微信回调日志
|
|
||||||
*
|
|
||||||
* @param string $message
|
|
||||||
* @param array $context
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function log(string $message, array $context = [])
|
|
||||||
{
|
|
||||||
return Log::build([
|
|
||||||
'driver' => 'daily',
|
|
||||||
'path' => storage_path('logs/wxpay.log'),
|
|
||||||
])->info($message, $context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,5 @@ use Illuminate\Support\Facades\Route;
|
||||||
//快递100物流推送
|
//快递100物流推送
|
||||||
Route::post('kuaidi100', [Kuaidi100Controller::class, 'notify']);
|
Route::post('kuaidi100', [Kuaidi100Controller::class, 'notify']);
|
||||||
// 微信支付通知
|
// 微信支付通知
|
||||||
Route::post('wxpay/order-paid-notify', [WeChatPayController::class, 'orderPaidNotify'])->name('wxpay.order_paid_notify');
|
Route::post('wxpay/paid-notify', [WeChatPayController::class, 'paidNotify'])->name('wxpay.paid_notify');
|
||||||
Route::post('wxpay/order-refund-notify', [WeChatPayController::class, 'orderRefundedNotify'])->name('wxpay.order_refund_notify');
|
Route::post('wxpay/order-refund-notify', [WeChatPayController::class, 'orderRefundedNotify'])->name('wxpay.order_refund_notify');
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Helpers;
|
|
||||||
|
|
||||||
class Order
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* 生成订单流水号
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function serialNumber(): string
|
|
||||||
{
|
|
||||||
return date('YmdHis').sprintf('%06d', mt_rand(1, 999999));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Events\OrderPaid;
|
||||||
|
use App\Services\CouponService;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class SendCoupons
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param \App\Services\CouponService $couponService
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public CouponService $couponService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param \App\Events\OrderPaid $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle(OrderPaid $event)
|
||||||
|
{
|
||||||
|
$order = $event->order;
|
||||||
|
|
||||||
|
if (is_null($order)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理购买分区商品送券
|
||||||
|
try {
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
$products = $order->products()->with('sku.parts')->get();
|
||||||
|
|
||||||
|
// 整理订单商品的分区
|
||||||
|
$inValidParts = [];
|
||||||
|
|
||||||
|
foreach ($products->pluck('sku.parts') as $parts) {
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
if ($part->is_show) {
|
||||||
|
// 分区去重
|
||||||
|
$inValidParts[$part->id] = $part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($inValidParts as $inValidPart) {
|
||||||
|
$this->couponService->receivePartCoupon($inValidPart, $order->user);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
} catch (Throwable $th) {
|
||||||
|
DB::rollBack();
|
||||||
|
|
||||||
|
report($th);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -36,7 +36,6 @@ class Order extends Model
|
||||||
public const PAY_WAY_WALLET = 'wallet'; // 钱包
|
public const PAY_WAY_WALLET = 'wallet'; // 钱包
|
||||||
public const PAY_WAY_BALANCE = 'balance'; // 余额
|
public const PAY_WAY_BALANCE = 'balance'; // 余额
|
||||||
public const PAY_WAY_OFFLINE = 'offline'; // 现金支付
|
public const PAY_WAY_OFFLINE = 'offline'; // 现金支付
|
||||||
public const PAY_WAY_NONE = 'none'; // 无
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
|
|
@ -74,6 +73,7 @@ class Order extends Model
|
||||||
'pay_sn',
|
'pay_sn',
|
||||||
'pay_way',
|
'pay_way',
|
||||||
'pay_at',
|
'pay_at',
|
||||||
|
'out_trade_no',
|
||||||
'consignee_name',
|
'consignee_name',
|
||||||
'consignee_telephone',
|
'consignee_telephone',
|
||||||
'consignee_zone',
|
'consignee_zone',
|
||||||
|
|
@ -154,6 +154,14 @@ class Order extends Model
|
||||||
return $this->belongsToMany(Tag::class, 'taggables', 'taggable_id', 'tag_id')->wherePivot('taggable_type', self::class)->withTimestamps();
|
return $this->belongsToMany(Tag::class, 'taggables', 'taggable_id', 'tag_id')->wherePivot('taggable_type', self::class)->withTimestamps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属于此订单的支付记录
|
||||||
|
*/
|
||||||
|
public function payLogs()
|
||||||
|
{
|
||||||
|
return $this->morphMany(PayLog::class, 'payable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 此订单是否待付款
|
* 此订单是否待付款
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class PayLog extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 支付状态
|
||||||
|
*/
|
||||||
|
public const STATUS_PENDING = 0; // 待付款
|
||||||
|
public const STATUS_SUCCESS = 1; // 成功
|
||||||
|
public const STATUS_FAILED = 2; // 失败
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付方式
|
||||||
|
*/
|
||||||
|
public const PAY_WAY_WXPAY = 'wxpay'; // 微信支付
|
||||||
|
public const PAY_WAY_ALIPAY = 'alipay'; // 支付宝
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $attributes = [
|
||||||
|
'status' => self::STATUS_PENDING,
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $casts = [
|
||||||
|
'pay_at' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'pay_sn',
|
||||||
|
'pay_way',
|
||||||
|
'pay_at',
|
||||||
|
'out_trade_no',
|
||||||
|
'status',
|
||||||
|
'failed_reason',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取支付记录所属的模型
|
||||||
|
*/
|
||||||
|
public function payable()
|
||||||
|
{
|
||||||
|
return $this->morphTo();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取支付记录是否是待付款
|
||||||
|
*/
|
||||||
|
public function isPending()
|
||||||
|
{
|
||||||
|
return $this->status === static::STATUS_PENDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ class EventServiceProvider extends ServiceProvider
|
||||||
],
|
],
|
||||||
\App\Events\OrderPaid::class => [
|
\App\Events\OrderPaid::class => [
|
||||||
\App\Listeners\OrderPaidNotify::class,
|
\App\Listeners\OrderPaidNotify::class,
|
||||||
|
\App\Listeners\SendCoupons::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ use App\Endpoint\Api\Http\Resources\UserCouponResource;
|
||||||
use App\Exceptions\BizException;
|
use App\Exceptions\BizException;
|
||||||
use App\Exceptions\ShippingNotSupportedException;
|
use App\Exceptions\ShippingNotSupportedException;
|
||||||
use App\Helpers\Numeric;
|
use App\Helpers\Numeric;
|
||||||
use App\Helpers\Order as OrderHelper;
|
|
||||||
use App\Models\DistributionPreIncomeJob;
|
use App\Models\DistributionPreIncomeJob;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\OrderProduct;
|
use App\Models\OrderProduct;
|
||||||
|
|
@ -20,7 +19,6 @@ use App\Models\User;
|
||||||
use App\Models\UserCoupon;
|
use App\Models\UserCoupon;
|
||||||
use Illuminate\Database\QueryException;
|
use Illuminate\Database\QueryException;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Throwable;
|
|
||||||
|
|
||||||
class OrderService
|
class OrderService
|
||||||
{
|
{
|
||||||
|
|
@ -144,7 +142,7 @@ class OrderService
|
||||||
$totalAmount += $shippingFee;
|
$totalAmount += $shippingFee;
|
||||||
|
|
||||||
$orderAttrs = [
|
$orderAttrs = [
|
||||||
'sn' => OrderHelper::serialNumber(),
|
'sn' => serial_number(),
|
||||||
'user_coupon_id' => $coupon?->id,
|
'user_coupon_id' => $coupon?->id,
|
||||||
'coupon_discount_amount' => $couponDiscountAmount,
|
'coupon_discount_amount' => $couponDiscountAmount,
|
||||||
'vip_discount_amount' => $vipDiscountAmount,
|
'vip_discount_amount' => $vipDiscountAmount,
|
||||||
|
|
@ -162,8 +160,8 @@ class OrderService
|
||||||
if ($totalAmount === 0) {
|
if ($totalAmount === 0) {
|
||||||
$orderAttrs = array_merge([
|
$orderAttrs = array_merge([
|
||||||
'status' => Order::STATUS_PAID,
|
'status' => Order::STATUS_PAID,
|
||||||
'pay_sn' => OrderHelper::serialNumber(),
|
'pay_sn' => serial_number(),
|
||||||
'pay_way' => Order::PAY_WAY_NONE,
|
'pay_way' => Order::PAY_WAY_BALANCE,
|
||||||
'pay_at' => now(),
|
'pay_at' => now(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
@ -708,20 +706,24 @@ class OrderService
|
||||||
throw new BizException('订单状态不是待付款');
|
throw new BizException('订单状态不是待付款');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array($payWay, $this->wxpayWays)) {
|
$payLog = $order->payLogs()->create([
|
||||||
return (new WeChatPayService())->pay([
|
'pay_sn' => serial_number(),
|
||||||
'attach' => json_encode([
|
'pay_way' => $payWay,
|
||||||
'pay_way' => $payWay,
|
]);
|
||||||
]),
|
|
||||||
'body' => app_settings('app.app_name').'-商城订单',
|
|
||||||
'out_trade_no' => $order->sn,
|
|
||||||
'total_fee' => $order->total_amount,
|
|
||||||
'notify_url' => url(route('wxpay.order_paid_notify', [], false), [], true),
|
|
||||||
'trade_type' => PayWay::$wxpayTradeTypes[$payWay],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new BizException('支付方式不支持');
|
switch ($payWay) {
|
||||||
|
case PayWay::WXPAY_APP:
|
||||||
|
case PayWay::WXPAY_H5:
|
||||||
|
case PayWay::WXPAY_JSAPI:
|
||||||
|
case PayWay::WXPAY_MINI:
|
||||||
|
return (new WeChatPayService())->pay([
|
||||||
|
'body' => app_settings('app_name').'-商城订单',
|
||||||
|
'out_trade_no' => $payLog->pay_sn,
|
||||||
|
'total_fee' => $order->total_amount,
|
||||||
|
'trade_type' => PayWay::$wxpayTradeTypes[$payWay],
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -731,10 +733,8 @@ class OrderService
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* @return \App\Models\Order
|
* @return \App\Models\Order
|
||||||
*/
|
*/
|
||||||
public function paySuccess(string $sn, array $params = []): Order
|
public function paySuccess(Order $order, array $params = []): Order
|
||||||
{
|
{
|
||||||
$order = Order::where('sn', $sn)->firstOrFail();
|
|
||||||
|
|
||||||
if (! $order->isPending()) {
|
if (! $order->isPending()) {
|
||||||
throw new BizException('订单状态不是待支付');
|
throw new BizException('订单状态不是待支付');
|
||||||
}
|
}
|
||||||
|
|
@ -743,19 +743,10 @@ class OrderService
|
||||||
'pay_sn' => $params['pay_sn'],
|
'pay_sn' => $params['pay_sn'],
|
||||||
'pay_way' => $params['pay_way'],
|
'pay_way' => $params['pay_way'],
|
||||||
'pay_at' => $params['pay_at'],
|
'pay_at' => $params['pay_at'],
|
||||||
|
'out_trade_no' => $params['out_trade_no'],
|
||||||
'status' => Order::STATUS_PAID,
|
'status' => Order::STATUS_PAID,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 处理购买分区商品送券
|
|
||||||
try {
|
|
||||||
DB::beginTransaction();
|
|
||||||
$this->sendPartCoupon($order);
|
|
||||||
DB::commit();
|
|
||||||
} catch (Throwable $th) {
|
|
||||||
DB::rollBack();
|
|
||||||
report($th);
|
|
||||||
}
|
|
||||||
|
|
||||||
DistributionPreIncomeJob::create([
|
DistributionPreIncomeJob::create([
|
||||||
'jobable_id' => $order->id,
|
'jobable_id' => $order->id,
|
||||||
'jobable_type' => $order->getMorphClass(),
|
'jobable_type' => $order->getMorphClass(),
|
||||||
|
|
@ -803,7 +794,7 @@ class OrderService
|
||||||
|
|
||||||
if ($order->isWaitShipping()) {
|
if ($order->isWaitShipping()) {
|
||||||
$refundLog = $order->refundLogs()->create([
|
$refundLog = $order->refundLogs()->create([
|
||||||
'sn' => OrderHelper::serialNumber(),
|
'sn' => serial_number(),
|
||||||
'amount' => $order->total_amount,
|
'amount' => $order->total_amount,
|
||||||
'reason' => '取消订单',
|
'reason' => '取消订单',
|
||||||
]);
|
]);
|
||||||
|
|
@ -857,31 +848,4 @@ class OrderService
|
||||||
'status' => Order::STATUS_CANCELLED,
|
'status' => Order::STATUS_CANCELLED,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送分区优惠券
|
|
||||||
*
|
|
||||||
* @param Order $order
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function sendPartCoupon(Order $order)
|
|
||||||
{
|
|
||||||
$products = $order->products()->with('sku.parts')->get();
|
|
||||||
// 整理订单商品的分区
|
|
||||||
$inValidParts = [];
|
|
||||||
foreach ($products->pluck('sku.parts') as $parts) {
|
|
||||||
foreach ($parts as $part) {
|
|
||||||
if ($part->is_show) {
|
|
||||||
// 分区去重
|
|
||||||
$inValidParts[$part->id] = $part;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将有效的分区丢进去领券
|
|
||||||
$couponService = new CouponService();
|
|
||||||
foreach ($inValidParts as $inValidPart) {
|
|
||||||
$couponService->receivePartCoupon($inValidPart, $order->user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Constants\PayWay;
|
||||||
|
use App\Exceptions\BizException;
|
||||||
|
use App\Models\Order;
|
||||||
|
use App\Models\PayLog;
|
||||||
|
|
||||||
|
class PayService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 支付成功
|
||||||
|
*
|
||||||
|
* @param string $sn
|
||||||
|
* @param array $params
|
||||||
|
* @return \App\Models\PayLog
|
||||||
|
*
|
||||||
|
* @throws \App\Exceptions\BizException
|
||||||
|
*/
|
||||||
|
public function paySuccess(string $sn, array $params = []): PayLog
|
||||||
|
{
|
||||||
|
$payLog = PayLog::where('pay_sn', $sn)->firstOrFail();
|
||||||
|
|
||||||
|
if (! $payLog->isPending()) {
|
||||||
|
throw new BizException('支付记录状态异常');
|
||||||
|
}
|
||||||
|
|
||||||
|
$payLog->update([
|
||||||
|
'pay_at' => $params['pay_at'] ?? now(),
|
||||||
|
'out_trade_no' => $params['out_trade_no'] ?? null,
|
||||||
|
'status' => PayLog::STATUS_SUCCESS,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($payLog->payable instanceof Order) {
|
||||||
|
switch ($payLog->pay_way) {
|
||||||
|
case PayWay::WXPAY_APP:
|
||||||
|
case PayWay::WXPAY_H5:
|
||||||
|
case PayWay::WXPAY_JSAPI:
|
||||||
|
case PayWay::WXPAY_MINI:
|
||||||
|
case PayWay::WXPAY_NATIVE:
|
||||||
|
$payWay = Order::PAY_WAY_WXPAY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$payWay = $payLog->pay_way;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
(new OrderService())->paySuccess($payLog->payable, [
|
||||||
|
'pay_sn' => $payLog->pay_sn,
|
||||||
|
'pay_way' => $payWay,
|
||||||
|
'pay_at' => $payLog->pay_at,
|
||||||
|
'out_trade_no' => $payLog->out_trade_no,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $payLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付失败
|
||||||
|
*
|
||||||
|
* @param string $sn
|
||||||
|
* @param array $params
|
||||||
|
* @return \App\Models\PayLog
|
||||||
|
*
|
||||||
|
* @throws \App\Exceptions\BizException
|
||||||
|
*/
|
||||||
|
public function payFailed(string $sn, array $params = []): PayLog
|
||||||
|
{
|
||||||
|
$payLog = PayLog::where('pay_sn', $sn)->firstOrFail();
|
||||||
|
|
||||||
|
if (! $payLog->isPending()) {
|
||||||
|
throw new BizException('支付记录状态异常');
|
||||||
|
}
|
||||||
|
|
||||||
|
$payLog->update([
|
||||||
|
'out_trade_no' => $params['out_trade_no'] ?? null,
|
||||||
|
'status' => PayLog::STATUS_FAILED,
|
||||||
|
'failed_reason' => $params['failed_reason'] ?? null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $payLog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,7 +9,7 @@ return [
|
||||||
'key' => env('WECHAT_PAYMENT_KEY'),
|
'key' => env('WECHAT_PAYMENT_KEY'),
|
||||||
'cert_path' => env('WECHAT_PAYMENT_CERT_PATH'), // 绝对地址
|
'cert_path' => env('WECHAT_PAYMENT_CERT_PATH'), // 绝对地址
|
||||||
'key_path' => env('WECHAT_PAYMENT_KEY_PATH'), // 绝对地址
|
'key_path' => env('WECHAT_PAYMENT_KEY_PATH'), // 绝对地址
|
||||||
'notify_url' => env('WECHAT_PAYMENT_NOTIFY_URL'),
|
'notify_url' => url(route('wxpay.paid_notify', [], false), [], true),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreatePayLogsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('pay_logs', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->morphs('payable');
|
||||||
|
$table->string('pay_sn')->unique()->comment('支付流水号');
|
||||||
|
$table->string('pay_way')->comment('支付方式');
|
||||||
|
$table->string('out_trade_no')->nullable()->comment('外部交易单号');
|
||||||
|
$table->timestamp('pay_at')->nullable()->comment('支付时间');
|
||||||
|
$table->tinyInteger('status')->comment('状态: 0 待付款, 1 支付成功, 2 支付失败');
|
||||||
|
$table->string('failed_reason')->nullable()->comment('失败原因');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('pay_logs');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddTradeOutNoToOrdersTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('orders', function (Blueprint $table) {
|
||||||
|
$table->string('out_trade_no')->nullable()->comment('外部交易单号');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('orders', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['out_trade_no']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue