@@ -184,6 +184,61 @@ public async Task DuplicateWebhookWithMismatchedAmountDoesNotChangeStoredAmount(
184184 Assert . Equal ( 1234 , promptDetails . ValueInCents ) ;
185185 }
186186
187+ [ Fact ( Timeout = TestUtils . TestTimeout ) ]
188+ public async Task CreatedP2PInvoiceIsRestrictedToPixPaymentPrompt ( )
189+ {
190+ var storeId = await CreateStoreAsync ( ) ;
191+ var handlers = _server . PayTester . GetService < PaymentMethodHandlerDictionary > ( ) ;
192+ var pixHandler = handlers [ PixPmid ] ;
193+ var invoiceRepository = _server . PayTester . InvoiceRepository ;
194+ var storeRepository = _server . PayTester . GetService < StoreRepository > ( ) ;
195+ var store = await storeRepository . FindStore ( storeId ) ?? throw new InvalidOperationException ( "Store not found." ) ;
196+ var invoice = invoiceRepository . CreateNewInvoice ( storeId ) ;
197+ invoice . Currency = "BRL" ;
198+ invoice . Price = 12.34m ;
199+ invoice . AddRate ( new CurrencyPair ( "BRL" , "BRL" ) , 1m ) ;
200+ invoice . SetPaymentPrompts ( new PaymentPromptDictionary ( [
201+ new PaymentPrompt
202+ {
203+ PaymentMethodId = PixPmid ,
204+ Currency = "BRL" ,
205+ Divisibility = 2 ,
206+ Destination = "https://example.invalid/pix.png" ,
207+ Details = JToken . FromObject ( new DePixPaymentMethodDetails
208+ {
209+ QrId = "qr-p2p-restricted" ,
210+ P2PMode = true ,
211+ ValueInCents = 1234
212+ } , pixHandler . Serializer )
213+ } ,
214+ new PaymentPrompt
215+ {
216+ PaymentMethodId = PaymentTypes . CHAIN . GetPaymentMethodId ( "BTC" ) ,
217+ Currency = "BRL" ,
218+ Divisibility = 2 ,
219+ Destination = "bitcoin-address" ,
220+ Details = new JObject ( )
221+ }
222+ ] ) ) ;
223+
224+ await invoiceRepository . CreateInvoiceAsync ( new InvoiceCreationContext (
225+ store ,
226+ store . GetStoreBlob ( ) ,
227+ invoice ,
228+ new InvoiceLogs ( ) ,
229+ handlers ,
230+ invoicePaymentMethodFilter : null ) ) ;
231+
232+ _server . PayTester . GetService < EventAggregator > ( ) . Publish ( new InvoiceEvent ( invoice , InvoiceEvent . Created ) ) ;
233+
234+ await TestUtils . EventuallyAsync ( async ( ) =>
235+ {
236+ var storedInvoice = await invoiceRepository . GetInvoice ( invoice . Id ) ;
237+ var prompt = Assert . Single ( storedInvoice . GetPaymentPrompts ( ) ) ;
238+ Assert . Equal ( PixPmid , prompt . PaymentMethodId ) ;
239+ } ) ;
240+ }
241+
187242 [ Fact ( Timeout = TestUtils . TestTimeout ) ]
188243 public async Task FirstConfirmedWebhookWithMismatchedAmountUsesPromptAmount ( )
189244 {
@@ -211,6 +266,61 @@ public async Task FirstConfirmedWebhookWithMismatchedAmountUsesPromptAmount()
211266 Assert . Equal ( 1234 , promptDetails . ValueInCents ) ;
212267 }
213268
269+ [ Fact ( Timeout = TestUtils . TestTimeout ) ]
270+ public async Task ConfigurePromptReturnsUnavailableWhenP2PCommissionAddressCannotBeGenerated ( )
271+ {
272+ var storeId = await CreateStoreAsync ( ) ;
273+ var storeRepository = _server . PayTester . GetService < StoreRepository > ( ) ;
274+ var handlers = _server . PayTester . GetService < PaymentMethodHandlerDictionary > ( ) ;
275+ var handler = handlers [ PixPmid ] ;
276+ var protector = _server . PayTester . GetService < ISecretProtector > ( ) ;
277+ var store = await storeRepository . FindStore ( storeId ) ?? throw new InvalidOperationException ( "Store not found." ) ;
278+
279+ store . SetPaymentMethodConfig ( handler , new PixPaymentMethodConfig
280+ {
281+ EncryptedApiKey = protector . Protect ( "fixture-api-key" ) ,
282+ WebhookSecretHashHex = BTCPayServer . Plugins . Depix . Services . Utils . ComputeSecretHash (
283+ "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" ) ,
284+ IsEnabled = true ,
285+ P2PMode = true ,
286+ P2PCommissionPercent = "5%"
287+ } ) ;
288+ var storeBlob = store . GetStoreBlob ( ) ;
289+ storeBlob . SetExcluded ( PixPmid , false ) ;
290+ store . SetStoreBlob ( storeBlob ) ;
291+ await storeRepository . UpdateStore ( store ) ;
292+
293+ var invoice = _server . PayTester . InvoiceRepository . CreateNewInvoice ( storeId ) ;
294+ invoice . Currency = "BRL" ;
295+ invoice . Price = 12.34m ;
296+ invoice . AddRate ( new CurrencyPair ( "BRL" , "BRL" ) , 1m ) ;
297+ #pragma warning disable CS0618
298+ invoice . Payments = [ ] ;
299+ #pragma warning restore CS0618
300+ invoice . UpdateTotals ( ) ;
301+ invoice . Metadata = new InvoiceMetadata
302+ {
303+ AdditionalData = new Dictionary < string , JToken >
304+ {
305+ [ "depixAddress" ] = "buyer-depix-address"
306+ }
307+ } ;
308+ var context = new PaymentMethodContext (
309+ store ,
310+ store . GetStoreBlob ( ) ,
311+ new JObject ( ) ,
312+ handler ,
313+ invoice ,
314+ new InvoiceLogs ( ) ) ;
315+ context . Prompt . ParentEntity = invoice ;
316+ context . Prompt . PaymentMethodId = PixPmid ;
317+ context . Prompt . Currency = "BRL" ;
318+ context . Prompt . Divisibility = 2 ;
319+
320+ var ex = await Assert . ThrowsAsync < PaymentMethodUnavailableException > ( ( ) => handler . ConfigurePrompt ( context ) ) ;
321+ Assert . Contains ( "DePix" , ex . Message , StringComparison . OrdinalIgnoreCase ) ;
322+ }
323+
214324 private async Task < string > CreateStoreAsync ( )
215325 {
216326 var account = _server . NewAccount ( ) ;
0 commit comments