Closed layinka closed 6 years ago
Yes it supports, check PaymentTests.cs.
var uri = server.GetPaymentRequestUri(2);
BitcoinUrlBuilder btcUri = new BitcoinUrlBuilder(uri);
var request = btcUri.GetPaymentRequest();
Assert.True(request.VerifySignature());
Assert.Equal(2, BitConverter.ToInt32(request.Details.MerchantData, 0));
var ack = request.CreatePayment().SubmitPayment();
Assert.NotNull(ack);
Thanks,i am trying that now.
Please can you confirm how i can handle Certificates.
I am using NBitCoin with a .net Core app, and i am getting this error.
DefaultCertificateServiceProvider or CertificateServiceProvider must be set before calling this method
Thanks
@layinka ok thanks a lot, new version 4.0.0.10 should solve the situation, can you update your package and let me know how it goes ?
It seems I deactivated certificate verification on .NET Core because I was unaware I could do it, I just fixed that.
Great, That works.
But a few more questions?
So how do i specify certificates in .Net core, will that be handled automatically ? or do you have a sample implementation?
Do you know how i can write out the request in .net core? This is the code i have presently, but i dont think its getting signed accurately, and something is definitely broken as the wallets cant understand the output. Please can you help check?
public IActionResult GetBitcoinPaymentRequest(string payId){
string baseUrl = "http://localhost:5000";
foreach(var provider in new ICertificateServiceProvider[]{})
{
PaymentRequest.DefaultCertificateServiceProvider = provider;
}
PaymentRequest request = new PaymentRequest();
request.Details.Outputs.Add(new PaymentOutput(new Money(0.00001m, MoneyUnit.BTC), new BitcoinPubKeyAddress("addrs1").ScriptPubKey )); //Destination
request.Details.Outputs.Add(new PaymentOutput(new Money(0.00001m, MoneyUnit.BTC), new BitcoinPubKeyAddress("addrs2").ScriptPubKey));// dest charge 2
request.Details.MerchantData = ASCIIEncoding.ASCII.GetBytes(payId.ToString());
request.Details.PaymentUrl = new Uri(baseUrl + "?id=" + payId);
request.Sign(System.IO.File.ReadAllBytes("data/cert.pfx"), PKIType.X509SHA256);
request.WriteTo(Response.Body);
return Ok();
}
Normally now the correct DefaultCertificateServiceProvider
is set for .NETCore, and you should not touch it.
The test CanCreatePaymentRequest
in PaymentTests
show how to sign.
Your request seems fine to me, check it is correctly signed with
Assert.True(request.VerifySignature());
Assert.True(request.VerifyChain());
Wallets might reject if your certificate is not trusted.
Nicolas,
You can try your own server with:
BitcoinUrlBuilder.GetPaymentRequest
I guess your problem is that your server does not set the content type.
Hi Nicolas, I am not sure i understad how i can use
BitcoinUrlBuilder.GetPaymentRequest
When i try using it,i either get a Task Error or i get an error saying No Valid PaymentRequest.
Let me explain what i am trying to do again, so maybe you can help better.(The fact that the final request is a binary format that i cannot open to see is also very limiting)
I want to automate the payment on my site so that when a user clicks a link like bticoin:?r=myweburl/myproductid , i can use the myproductid to detect the price the user wants to pay and then compose a paymentrequest matching the price and send it to some multiple outputs.
Is this something you have implemented before? I cannot use the sample codes you have in your test files as they are mixed with test codes that i am not sure i understand.
And i have been able to set the content type from the server so thats not a problem, i suspect the problem is in the actual response written out, as even when i send out a PaymentRequest that is not signed (PKIType.None), i get an error of "Invalid Paymentrequest Url" on the wallet.
Here is my code once again.
public IActionResult GetBitcoinPaymentRequest(string payScheduleId){
string baseUrl = "http://localhost:5000";
// BitcoinUrlBuilder bb=new BitcoinUrlBuilder(){
// PaymentRequestUrl = new Uri(baseUrl + "/api/paywithbtc/tre23")
// };
// PaymentRequest request = bb.GetPaymentRequest();
PaymentRequest request = new PaymentRequest();
request.Details.Outputs.Add(new PaymentOutput(new Money(0.001m, MoneyUnit.BTC), new BitcoinPubKeyAddress("wallet address").ScriptPubKey )); //Destination
request.Details.Outputs.Add(new PaymentOutput(new Money(0.001m, MoneyUnit.BTC), new BitcoinPubKeyAddress("TWT wallet address").ScriptPubKey));//Transaction charge
request.Details.MerchantData = ASCIIEncoding.ASCII.GetBytes(payScheduleId.ToString());
request.Details.Memo= "Payment for ...";
request.Details.Network= Network.Main;
request.Details.PaymentUrl = new Uri(baseUrl + "?id=" + payScheduleId);
request.Details.Expires = new DateTimeOffset(2017,7,25,22,0,0,0,TimeSpan.Zero);
request.PKIType = PKIType.None; //Unsigned
// request.Sign(System.IO.File.ReadAllBytes("data/cert.pfx"), PKIType.X509SHA256);
Response.ContentType="application/bitcoin-paymentrequest";
Response.Headers.AddOrReplace("Content-Transfer-Encoding","binary");
request.WriteTo(Response.Body);
return Ok();
}
new BitcoinUrlBuilder("bitcoin://bitcoinaddress?r=http://localhost:5000/GetBitcoinPaymentRequest/2939393").GetPaymentRequest()
Your error is with the URL, not with the paymentrequest.
Thanks for always answering Nicolas.
To clarify, Is this what I should place as a link in my application? if its not, then what?
<a href="bitcoin://bitcoinaddress?r=http://localhost:5000/GetBitcoinPaymentRequest/2939393">Pay</a>
and then change my code to
public IActionResult GetBitcoinPaymentRequest(string payScheduleId){
string baseUrl = "http://localhost:5000";
BitcoinUrlBuilder bb=new BitcoinUrlBuilder("bitcoin://bitcoinaddress?r=http://localhost:5000/GetBitcoinPaymentRequest/2939393");
PaymentRequest request = bb.GetPaymentRequest();
// PaymentRequest request = new PaymentRequest();
request.Details.Outputs.Add(new PaymentOutput(new Money(0.001m, MoneyUnit.BTC), new BitcoinPubKeyAddress("wallet address").ScriptPubKey )); //Destination
request.Details.Outputs.Add(new PaymentOutput(new Money(0.001m, MoneyUnit.BTC), new BitcoinPubKeyAddress("TWT wallet address").ScriptPubKey));//Transaction charge
request.Details.MerchantData = ASCIIEncoding.ASCII.GetBytes(payScheduleId.ToString());
request.Details.Memo= "Payment for ...";
request.Details.Network= Network.Main;
request.Details.PaymentUrl = new Uri(baseUrl + "?id=" + payScheduleId);
request.Details.Expires = new DateTimeOffset(2017,7,25,22,0,0,0,TimeSpan.Zero);
request.PKIType = PKIType.None; //Unsigned
// request.Sign(System.IO.File.ReadAllBytes("data/cert.pfx"), PKIType.X509SHA256);
Response.ContentType="application/bitcoin-paymentrequest";
Response.Headers.AddOrReplace("Content-Transfer-Encoding","binary");
request.WriteTo(Response.Body);
return Ok();
}
But wont that become a cyclic and recursive call, it looks like its calling itself
Yes, this is what you need, with bitcoinaddress
has to be the destination address, this is in case the wallet does not support BIP37.
There is no recursion, PaymentUrl is different from the r= address as you can see https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki
Hi,
Ok, i will try it out, but how will i handle mutliple outputs if the wallet doesnt support BIP37 , i dont think i can add the two adresses to the url or can i?
Thanks
Just tried this,
new BitcoinUrlBuilder("bitcoin://bitcoinaddressr=http://localhost:5000/GetBitcoinPaymentRequest/2939393")
.GetPaymentRequest()
i got this error
Exception has occurred: CLR/System.Threading.Tasks.TaskCanceledException
An exception of type 'System.Threading.Tasks.TaskCanceledException' occurred in System.Private.CoreLib.ni.dll but was not handled in user code: 'A task was canceled.'
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at NBitcoin.Payment.BitcoinUrlBuilder.GetPaymentRequest()
Hi, I keep getting that TaskcancelledException when i try to use the bitcoin builder, but it doesnt show up if i build the paymentrequest directly.
Since the main error i am gettig on the wallet is
Payment Request Url is invalid
Could this error be showing up on the wallets because i am using a localhost address? Do you know if this could be what is causing it, because its even showing up for unsigned requests.
Please give me the Bitcoin url you are using, this is a parsing error, I think you misunderstand the URI format of bitcoin://
I am testing on my localhost server. So you might not have access to the url.
but essentially the url is something in the anchor tag looks like this <a href="bitcoin:n1wKTykkSox49o2FzQfyewmNZTnjQSeUxn?r= http://localhost:5000/api/groups/paywithbtc/tre23 ">Pay
When this is clicked, the wallet opens and is supposed to call the api via http://localhost:5000/api/groups/paywithbtc/tre23 which should then return the Payment request.
Thats why i was asking that wont using bitcoinUrlBuilder the way you were mentioning lead to a cyclic call, since getPaymentRequest on BitcoinUrlBuilder also calls http://localhost:5000/api/groups/paywithbtc/tre23 behind the scene.
On Fri, Jul 28, 2017 at 3:59 PM, Nicolas Dorier notifications@github.com wrote:
Please give me the Bitcoin url you are using.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MetacoSA/NBitcoin/issues/263#issuecomment-318675413, or mute the thread https://github.com/notifications/unsubscribe-auth/AAmbROdg10QoNXwbtxaKLO0DoSeZ3HdRks5sSfdhgaJpZM4Ob7AC .
-- Olayinka Tanimomo (MCTS,CCNA) Software/Web/Mobile Developer
your error "Payment Request Url is invalid" appears nowhere in NBitcoin code, which software are you using ? I suspect they have a bug in parsing the bitcoin: url
any progress?
Not really, i had to compose and write my own protobuf to the wire directly.
which software gave the error? It should recognize my format, if it does not can you tell me the difference between the one you created and mine?
I really cant tell the difference in the final output, all i see is that this one works with all the wallets. I am using silentorbit.com/protobuf to generate the protobuf.
On Mon, Aug 7, 2017 at 3:52 PM, Nicolas Dorier notifications@github.com wrote:
which software are you using please ? It should recognize my format, if it does not can you tell me the difference between the one you created and mine?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MetacoSA/NBitcoin/issues/263#issuecomment-320685896, or mute the thread https://github.com/notifications/unsubscribe-auth/AAmbRIK0NNHxwMGkmAJBI81wMY4kCGY2ks5sVySfgaJpZM4Ob7AC .
-- Olayinka Tanimomo (MCTS,CCNA) Software/Web/Mobile Developer
please can you give me a way to reproduce the error or something, I spend significant time trying to debug your issue, I would like at least to find out what was wrong
Something like the byte serialization of my code versus yours.
Or even posting your code which work would help me
I understand.
Maybe i was doing something wrong with your library,but i just couldnt get it to work.
This is a working sample from my working code
public void GetBitcoinPaymentRequest(string payScheduleId){
string baseUrl = "http://127.0.0.1:5000";
var businessId = "treas";
NewPayments.PaymentDetails pd = new NewPayments.PaymentDetails();
//pd.Time = DateTime.UtcNow.;
pd.Memo = "Payment fr TWT";
pd.Network = "test";
pd.MerchantData = ASCIIEncoding.ASCII.GetBytes(payScheduleId.ToString());
pd.Time =(ulong) DateTimeOffset.Now.ToUnixTimeSeconds();
DateTime foo = DateTime.Now.AddDays(1);
long unixTime = ((DateTimeOffset)foo).ToUnixTimeSeconds();
pd.Expires =(ulong) unixTime;
NewPayments.Output out1 = new NewPayments.Output( (ulong)( 0.00001*1000000), "address...");
NewPayments.Output transactionChargeOutput = new NewPayments.Output( (ulong)( 0.0000001m*1000000), "addresss.....");
pd.Outputs = new List<NewPayments.Output> { out1, transactionChargeOutput };
pd.PaymentUrl = baseUrl + "?id=" + payScheduleId;
var payReq = new NewPayments.PaymentRequest();
payReq.SerializedPaymentDetails = NewPayments.PaymentDetails.SerializeToBytes(pd);
// payReq.PkiType = "none";//Unsigned
payReq.PkiType = "x509+sha256";
// payReq.PkiData
payReq.Sign(System.IO.File.ReadAllBytes("certificates/mycert.pfx"), PKIType.X509SHA256);
// request.Sign(System.IO.File.ReadAllBytes("data/NicolasDorierMerchant.pfx"), PKIType.X509SHA256);
//payReq.Serialize();
// PaymentRequest.SerializeToBytes(payReq);
Response.ContentType="application/bitcoin-paymentrequest";
Response.Headers.AddOrReplace("Content-Transfer-Encoding","binary");
NewPayments.PaymentRequest.Serialize(Response.Body,payReq);
}
I am using this proto file
package newPayments;
option java_package = "org.bitcoin.protocols.payments";
option java_outer_classname = "Protos";
// Generalized form of "send payment to this/these bitcoin addresses"
message Output {
optional uint64 amount = 1 [default = 0]; // amount is integer-number-of-satoshis
required bytes script = 2; // usually one of the standard Script forms
}
message PaymentDetails {
optional string network = 1 [default = "main"]; // "main" or "test"
repeated Output outputs = 2; // Where payment should be sent
required uint64 time = 3; // Timestamp; when payment request created
optional uint64 expires = 4; // Timestamp; when this request should be considered invalid
optional string memo = 5; // Human-readable description of request for the customer
optional string payment_url = 6; // URL to send Payment and get PaymentACK
optional bytes merchant_data = 7; // Arbitrary data to include in the Payment message
}
message PaymentRequest {
optional uint32 payment_details_version = 1 [default = 1];
optional string pki_type = 2 [default = "none"]; // none / x509+sha256 / x509+sha1
optional bytes pki_data = 3; // depends on pki_type
required bytes serialized_payment_details = 4; // PaymentDetails
optional bytes signature = 5; // pki-dependent signature
}
message X509Certificates {
repeated bytes certificate = 1; // DER-encoded X.509 certificate chain
}
message Payment {
optional bytes merchant_data = 1; // From PaymentDetails.merchant_data
repeated bytes transactions = 2; // Signed transactions that satisfy PaymentDetails.outputs
repeated Output refund_to = 3; // Where to send refunds, if a refund is necessary
optional string memo = 4; // Human-readable message for the merchant
}
message PaymentACK {
required Payment payment = 1; // Payment message that triggered this ACK
optional string memo = 2; // human-readable message for customer
}
thanks a lot, will take a look today
what is your Sign Method ?
mmh your way of doing might not work on other software.... BIP37 is really a shitty BIP. As there is so many way to serialize the same data, the gap are left to interpretation.
I advise you to test your implementation with another client (like copay or bitcoin core) to be sure that it works.
Can you also send me the hex of a signed request from you ? Just to check if I can verify correctly. Also can you send me your Sign method ?
I have tested with bitcoin core and it works.
Sent from my Windows Phone
-----Original Message----- From: "Nicolas Dorier" notifications@github.com Sent: 8/8/2017 3:33 AM To: "MetacoSA/NBitcoin" NBitcoin@noreply.github.com Cc: "layinka" xcelsis02@gmail.com; "Mention" mention@noreply.github.com Subject: Re: [MetacoSA/NBitcoin] Question BIP70, 71 ,72 and 73 (#263)
mmh your way of doing might not work on other software.... BIP37 is really a shitty BIP. As there is so many way to serialize the same data, the gap are left to interpretation. I advise you to test your stuff with another client (like copay or bitcoin core) to be sure that it works. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
Can you also send me the hex of a signed request from you ? Just to check if I can verify correctly. Also can you send me your Sign method ?
How do i get the hex?
I am using your sign method since you already implemented that.
On Tue, Aug 8, 2017 at 7:56 AM, Nicolas Dorier notifications@github.com wrote:
Can you also send me the hex of a signed request from you ? Just to check if I can verify correctly. Also can you send me your Sign method ?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MetacoSA/NBitcoin/issues/263#issuecomment-320867575, or mute the thread https://github.com/notifications/unsubscribe-auth/AAmbRLllIPMLGb5oPgxsLcEjB89mpwvjks5sWAaJgaJpZM4Ob7AC .
-- Olayinka Tanimomo (MCTS,CCNA) Software/Web/Mobile Developer
Please can you tell me which software said to you Payment Request Url is invalid
? I tested my implementation against bitcoin core and it worked fine.
All of them.
Bitcoin core, copay, Electrum.
On Tue, Aug 8, 2017 at 10:26 AM, Nicolas Dorier notifications@github.com wrote:
Please can you tell me which software said to you Payment Request Url is invalid ?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MetacoSA/NBitcoin/issues/263#issuecomment-320902263, or mute the thread https://github.com/notifications/unsubscribe-auth/AAmbRLHUhUjoKSBKBtpAY0ZU1Fatn1-6ks5sWCnhgaJpZM4Ob7AC .
-- Olayinka Tanimomo (MCTS,CCNA) Software/Web/Mobile Developer
very strange, look my test
var businessId = int.Parse(context.Request.QueryString.Get("id"));
var now = DateTimeOffset.UtcNow;
var expire = now + TimeSpan.FromDays(1);
TxOut txOut = new TxOut(Money.Coins(1), new Key().ScriptPubKey);
if(type == "Request")
{
Assert.Equal(PaymentRequest.MediaType, context.Request.AcceptTypes[0]);
context.Response.ContentType = PaymentRequest.MediaType;
PaymentRequest request = new PaymentRequest();
request.Details.MerchantData = BitConverter.GetBytes(businessId);
request.Details.Network = Network.RegTest;
request.Details.Expires = expire;
request.Details.Time = now;
request.Details.PaymentUrl = new Uri(_Prefix + "?id=" + businessId + "&type=Payment");
request.Details.Outputs.Add(new PaymentOutput(txOut));
request.Sign(File.ReadAllBytes("data/NicolasDorierMerchant.pfx"), PKIType.X509SHA256);
request.WriteTo(context.Response.OutputStream);
}
This request is accepted by Core on for me. I am thinking, you may have forgot to specify some mandatory property.
Maybe, thats possible. But then ,thats why i also copied my code here for u to see several times.
Its fine, i will test yours again later.
But it will be good if you have a form of documentaion on this apart from the test code, i will see if i can write something on it later.
Thanks a lot for your help
On Tue, Aug 8, 2017 at 11:58 AM, Nicolas Dorier notifications@github.com wrote:
very strange, look my test
var businessId = int.Parse(context.Request.QueryString.Get("id")); var now = DateTimeOffset.UtcNow; var expire = now + TimeSpan.FromDays(1); TxOut txOut = new TxOut(Money.Coins(1), new Key().ScriptPubKey); if(type == "Request") { Assert.Equal(PaymentRequest.MediaType, context.Request.AcceptTypes[0]); context.Response.ContentType = PaymentRequest.MediaType; PaymentRequest request = new PaymentRequest(); request.Details.MerchantData = BitConverter.GetBytes(businessId); request.Details.Network = Network.RegTest; request.Details.Expires = expire; request.Details.Time = now; request.Details.PaymentUrl = new Uri(_Prefix + "?id=" + businessId + "&type=Payment"); request.Details.Outputs.Add(new PaymentOutput(txOut)); request.Sign(File.ReadAllBytes("data/NicolasDorierMerchant.pfx"), PKIType.X509SHA256); request.WriteTo(context.Response.OutputStream); }
This request is accepted by Core on for me. I am thinking, you may have forgot to specify some mandatory property.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MetacoSA/NBitcoin/issues/263#issuecomment-320922340, or mute the thread https://github.com/notifications/unsubscribe-auth/AAmbRHNL5tn98SLYhFhywW-_u3rxTiVWks5sWD9IgaJpZM4Ob7AC .
-- Olayinka Tanimomo (MCTS,CCNA) Software/Web/Mobile Developer
Thanks, I updated my test code to include more specified field. Maybe it will do the trick, let me know when you have time to test.
Hi, Its working now. Though its still not working with copay, but it works with Bitcoin core.
Please how do i handle broadcasting the transaction on the network? Do you have any sample code?
Thanks
Sorry forget my previous deleted comment, I mixed up your issue with someone else.
I advise you to use your own Bitcoin Core node and use RPCClient.SendRawTransaction
, if not possible, using QBitNinjaClient
, you can see on https://programmingblockchain.gitbooks.io/
@layinka try to set VersionDetails field explicitely request.DetailsVersion = 1;
, and tell me if better for copay.
Hi Nicolas, It still didnt work, Is it possible you try it on your end?
I do not plan to support Copay for now since they are forking to another crypto currency. I will fix it if either they come back to bitcoin, or if you can give me the bytes of a request generated by NBitcoin versus generated by yourself so I can compare.
Closing here, feel free to open again once you have an example of payment request not accepted by Copay but created by NBitcoin.
Hello, I have installed your certifacete (NicolasDorierMerchant.pfx). I'm trying to implement a merchant server that supports Payment Protocol BIP70. This is my simple code for the server:
public class PaymentServer : IDisposable
{
HttpListener _Listener;
Random rand = new Random();
string _Prefix;
public PaymentServer()
{
while (true)
{
try
{
_Prefix = "http://localhost:37391" /*+ rand.Next(2000, 50000)*/ + "/";
_Listener = new HttpListener();
_Listener.Prefixes.Add(_Prefix);
_Listener.Start();
_Listener.BeginGetContext(ListenerCallback, null);
break;
}
catch (HttpListenerException)
{
}
}
}
void ListenerCallback(IAsyncResult ar)
{
try
{
var context = _Listener.EndGetContext(ar);
//var type = context.Request.QueryString.Get("type");
var businessId = 0;// int.Parse(context.Request.QueryString.Get("id"));
var now = DateTimeOffset.UtcNow;
var expire = now + TimeSpan.FromDays(1);
TxOut txOut = new TxOut(Money.Satoshis(1), new Key().ScriptPubKey);
//TxOut txOut = new TxOut(Money.Satoshis(123), new BitcoinPubKeyAddress("mim5ukG6fbWn91dPiuyYPZLqB9pyQTbn61").ScriptPubKey);
//if (type == "Request")
//{
//Assert.Equal(PaymentRequest.MediaType, context.Request.AcceptTypes[0]);
context.Response.ContentType = PaymentRequest.MediaType;
PaymentRequest request = new PaymentRequest();
//request.Details.MerchantData = BitConverter.GetBytes(businessId);
request.Details.Network = Network.TestNet;
request.Details.Expires = expire;
request.Details.Time = now;
request.Details.PaymentUrl = new Uri(_Prefix + "?id=" + businessId + "&type=Payment");
request.Details.Outputs.Add(new PaymentOutput(txOut));
//request.Details.Outputs.Add(new PaymentOutput(new Money(0.0000124m, MoneyUnit.BTC), new BitcoinPubKeyAddress("mim5ukG6fbWn91dPiuyYPZLqB9pyQTbn61").ScriptPubKey)); //Destination
//request.Details.Outputs.Add(new PaymentOutput(new Money(0.00001m, MoneyUnit.BTC), new BitcoinPubKeyAddress("addrs2").ScriptPubKey));// dest charge 2
//request.Details.Memo = "Payment for ...";
request.PKIType = PKIType.X509SHA256;
//context.Response.ContentType = "application/bitcoin-paymentrequest";
//context.Response.Headers.AddOrReplace("Content-Transfer-Encoding", "binary");
var cert = File.ReadAllBytes("data/NicolasDorierMerchant.pfx");
request.Sign(cert, PKIType.X509SHA256);
Assert.True(request.VerifySignature());
//Assert.True(request.VerifyChain());
request.WriteTo(context.Response.OutputStream);
//}
//else if (type == "Payment")
//{
// //Assert.Equal(PaymentMessage.MediaType, context.Request.ContentType);
// //Assert.Equal(PaymentACK.MediaType, context.Request.AcceptTypes[0]);
// var payment = PaymentMessage.Load(context.Request.InputStream);
// //Assert.Equal(businessId, BitConverter.ToInt32(payment.MerchantData, 0));
// context.Response.ContentType = PaymentACK.MediaType;
// var ack = payment.CreateACK();
// ack.Memo = "Thanks for your purchase";
// ack.WriteTo(context.Response.OutputStream);
//}
//else
// Assert.False(true, "Impossible");
context.Response.Close();
_Listener.BeginGetContext(ListenerCallback, null);
}
catch (Exception)
{
if (!_Stopped)
throw;
}
}
}
After click on the bitcoin: URI link, the wallet is launched then send a request to the server. The server then send back a PaymentRequest as above code. I'm testing with Copay and Electrum.
Copay said: "Payment Protocol Invalid". As I investigated, it seems because of src/js/services/payproService.js :
else if (!paypro.verified) {
$log.warn('Failed to verify payment protocol signatures');
return cb(gettextCatalog.getString('Payment Protocol Invalid'));
}
Electrum said: "ERROR: CA Certificate Chain Not Provided by Payment Processor". As I investigated, it seems because of electrum/blob/master/lib/paymentrequest.py:
def verify_cert_chain(chain):
""" Verify a chain of certificates. The last certificate is the CA"""
load_ca_list()
# parse the chain
cert_num = len(chain)
x509_chain = []
for i in range(cert_num):
x = x509.X509(bytearray(chain[i]))
x509_chain.append(x)
if i == 0:
x.check_date()
else:
if not x.check_ca():
raise BaseException("ERROR: Supplied CA Certificate Error")
if not cert_num > 1:
raise BaseException("ERROR: CA Certificate Chain Not Provided by Payment Processor")
Please help me!
NicolasDorier.pfx
is a test certificate, it is not trusted. You need your own certificate. I advise you against using certificates in your payment requests. Copay is not verifying right for some reason, and they do not add much security.
Thanks Nocolas,
I have no experience in PKI. I'm just researching about payment system and trying to implement a demo. So I must buy a certificate, right? Is there a free certificate for testing? Now I can test with Electrum without signing.
@mrviit remove the certificate for tests. And really I advise to remove for prod as well, as this protocol does not really offer any security at all with certs.
Hi, Does Nbitcoin support Paymentrequests?
Where can i find sample code or sample implementation using nbitcoin? I cant find any mention of this in the ebook.