feat: Payment 订单商品化——多态 payable 关联购买实体
- payments 表新增 payable_type/payable_id(nullableMorphs),订单可关联文章/套餐等可购买实体 - createOrder 接收 $payable 模型,取代 description 字符串解析 - membership 支付回调按 payable instanceof 分发(激活订阅 / 解锁单篇) - Post/MembershipPlan 提供 payableLabel/payableUrl 约定方法;Payment 用约定方法生成展示标签与后台链接(皮肤等新实体可直接接入) - 订单表格新增「类型」徽章(文章/会员套餐),商品列链接到对应后台编辑页;无 payable 的旧订单显示 —
This commit is contained in:
@@ -56,7 +56,8 @@ class MembershipFlowTest extends TestCase
|
||||
$payment = Payment::query()->where('user_id', $this->user->id)->first();
|
||||
$this->assertNotNull($payment);
|
||||
$this->assertSame('pending', $payment->status);
|
||||
$this->assertSame('MembershipPlan#'.$this->plan->id, $payment->description);
|
||||
$this->assertTrue($payment->payable->is($this->plan));
|
||||
$this->assertNull($payment->description);
|
||||
}
|
||||
|
||||
public function test_sandbox_payment_activates_subscription(): void
|
||||
@@ -101,4 +102,49 @@ class MembershipFlowTest extends TestCase
|
||||
->assertOk()
|
||||
->assertSee('付费隐藏内容');
|
||||
}
|
||||
|
||||
public function test_unlock_post_creates_payment_with_payable_and_grants_access(): void
|
||||
{
|
||||
$post = Post::create([
|
||||
'title' => '单篇付费',
|
||||
'slug' => 'single-paid',
|
||||
'content' => '付费内容正文',
|
||||
'content_format' => 'markdown',
|
||||
'status' => 'published',
|
||||
'published_at' => now(),
|
||||
'meta' => ['price' => 500],
|
||||
]);
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->post('/posts/'.$post->id.'/unlock')
|
||||
->assertRedirect();
|
||||
|
||||
$payment = Payment::query()->where('user_id', $this->user->id)->first();
|
||||
$this->assertNotNull($payment);
|
||||
$this->assertTrue($payment->payable->is($post));
|
||||
$this->assertSame(500, $payment->amount);
|
||||
$this->assertStringContainsString('单篇付费', $payment->payable_label);
|
||||
$this->assertNotNull($payment->payable_url);
|
||||
|
||||
// 沙箱支付后写入解锁用户
|
||||
$this->actingAs($this->user)->post('/pay/sandbox/'.$payment->order_no.'/confirm');
|
||||
|
||||
$post->refresh();
|
||||
$this->assertContains($this->user->id, $post->meta['unlocked_user_ids']);
|
||||
}
|
||||
|
||||
public function test_legacy_order_without_payable_shows_placeholder(): void
|
||||
{
|
||||
$payment = Payment::create([
|
||||
'order_no' => 'LEGACY0001',
|
||||
'user_id' => $this->user->id,
|
||||
'subject' => '历史订单',
|
||||
'amount' => 100,
|
||||
'status' => 'paid',
|
||||
'paid_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertSame('—', $payment->payable_label);
|
||||
$this->assertNull($payment->payable_url);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user