From 473293a5a5c30d51db9c822b6a4c4da4d7e05615 Mon Sep 17 00:00:00 2001 From: Michael Moffett Date: Mon, 5 Oct 2026 14:43:36 -0600 Subject: [PATCH 1/2] PayKit interface drifts Add `Gate::accepts(Protocol $p): bool` to the PHP SDK. This is the PHP `Gate::accepts` item from issue . The spec (`docs/paykit-interface.md:154-158`) names `accepts(protocol)` as a Gate method in every SDK, and PHP does not have it. --- docs/paykit-interface.md | 1 - php/src/Gate.php | 9 +++++++++ php/tests/GateTest.php | 25 +++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/paykit-interface.md b/docs/paykit-interface.md index a7d433c31..fbe769ded 100644 --- a/docs/paykit-interface.md +++ b/docs/paykit-interface.md @@ -293,7 +293,6 @@ conformant. functions over the request attribute) so non-middleware code paths exist, matching Ruby and Python. - Add `Config::fromEnv()`. -- Add `accepts(Protocol $p): bool` on `Gate`. - Add `payer` to `Payment`. - Simplify `MppConfig::resolveExpiresIn` (plain int + dedicated `EXPIRES_NEVER = 0` constant). diff --git a/php/src/Gate.php b/php/src/Gate.php index e57eb9391..91d6345bd 100644 --- a/php/src/Gate.php +++ b/php/src/Gate.php @@ -127,6 +127,15 @@ public function hasFees(): bool return count($this->fees) > 0; } + /** Whether this gate admits `$p`; a null `accept` defers to Config. */ + public function accepts(Protocol $p): bool + { + if ($p === Protocol::X402 && $this->hasFees()) { + return false; + } + return $this->accept === null || in_array($p, $this->accept, true); + } + private static function buildFee(int|string $recipient, Price $price, string $kind, Price $amount): Fee { if (!is_string($recipient) || $recipient === '') { diff --git a/php/tests/GateTest.php b/php/tests/GateTest.php index 47e08b03d..1ea92eec8 100644 --- a/php/tests/GateTest.php +++ b/php/tests/GateTest.php @@ -75,6 +75,31 @@ public function testExplicitX402AcceptOnFeeGateRejected(): void ); } + public function testAcceptsBothProtocolsWhenAcceptInherited(): void + { + $g = new Gate(amount: Price::usd('1.00')); + $this->assertTrue($g->accepts(Protocol::X402)); + $this->assertTrue($g->accepts(Protocol::Mpp)); + } + + public function testAcceptsHonorsExplicitAllowlist(): void + { + $g = new Gate(amount: Price::usd('1.00'), accept: [Protocol::Mpp]); + $this->assertFalse($g->accepts(Protocol::X402)); + $this->assertTrue($g->accepts(Protocol::Mpp)); + } + + public function testAcceptsRefusesX402OnFeeGate(): void + { + $g = new Gate( + amount: Price::usd('1.00'), + payTo: 'SELLER', + feeWithin: ['PLATFORM' => Price::usd('0.10')], + ); + $this->assertFalse($g->accepts(Protocol::X402)); + $this->assertTrue($g->accepts(Protocol::Mpp)); + } + public function testPayoutNullForUnaddressedRecipient(): void { $g = new Gate(amount: Price::usd('1.00'), payTo: 'SELLER'); From 545dc054de881916e2cffc5f60a1489d46019006 Mon Sep 17 00:00:00 2001 From: caliperforge Date: Mon, 5 Oct 2026 14:43:37 -0600 Subject: [PATCH 2/2] greptile.json: review on request only --- greptile.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 greptile.json diff --git a/greptile.json b/greptile.json new file mode 100644 index 000000000..3e653b565 --- /dev/null +++ b/greptile.json @@ -0,0 +1 @@ +{"autoReview": []}