def generate_payment_request(crypto_addr, x509_cert, expires, signer=None, amount=0, memo=None, payment_url=None, merchant_data=None): # Setup & Populate PaymentDetails payment_details = PaymentDetails() # Setup Single PaymentDetails Output output = payment_details.outputs.add() output.amount = amount * 100000000 # BTC to Satoshis if crypto_addr[0] == '1': output.script = serialize_script([OP_DUP, OP_HASH160, b58check_to_hex(crypto_addr), OP_EQUALVERIFY, OP_CHECKSIG]).decode('hex') else: try: int(crypto_addr, 16) output.script = str(crypto_addr).decode('hex') except ValueError: output.script = str(crypto_addr) # Add current and expiration epoch time values payment_details.time = int(datetime.utcnow().strftime('%s')) payment_details.expires = expires # Handle Various Optional Fields in PaymentDetails payment_details.memo = memo if memo else '' payment_details.payment_url = payment_url if payment_url else '' payment_details.merchant_data = str(merchant_data) if merchant_data else '' # Setup & Populate PaymentRequest payment_request = PaymentRequest() payment_request.payment_details_version = 1 payment_request.serialized_payment_details = payment_details.SerializeToString() # Set PKI Type / Data if not x509_cert or not signer: payment_request.pki_type = 'none' payment_request.pki_data = '' else: payment_request.pki_type = signer.get_pki_type() pki_data = X509Certificates() for cert in get_certs(x509_cert): pki_data.certificate.append(cert) payment_request.pki_data = pki_data.SerializeToString() # Sign PaymentRequest if signer and x509_cert: payment_request.signature = '' payment_request.signature = signer.sign(payment_request.SerializeToString()) # Log Payment Request to Logging System logger = PluginManager.get_plugin('LOGGER', config.logger_type) logger.log_payment_request(crypto_addr, signer.__class__.__name__, amount, expires, memo, payment_url, merchant_data) log.debug('Generated Payment Request [Address: %s | Signer: %s | Amount: %s | Expires: %s | Memo: %s | Payment URL: %s | Merchant Data: %s]' % (crypto_addr, signer.__class__.__name__, amount, expires, memo, payment_url, merchant_data)) return payment_request.SerializeToString()
def test_bip75_flow(self): ################### # Load Crypto Keys ################### self.x509_sender_cert = crypto.load_certificate(crypto.FILETYPE_PEM, SENDER_CERT) self.x509_sender_cert_privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, SENDER_CERT_PRIVKEY) self.x509_receiver_cert = crypto.load_certificate(crypto.FILETYPE_PEM, RECEIVER_CERT) self.x509_receiver_cert_privkey = crypto.load_privatekey(crypto.FILETYPE_PEM, RECEIVER_CERT_PRIVKEY) ######################### # Create InvoiceRequest ######################### log.info("Building InvoiceRequest") sender_certs = X509Certificates() sender_certs.certificate.append(ssl.PEM_cert_to_DER_cert(crypto.dump_certificate(crypto.FILETYPE_PEM, self.x509_sender_cert))) invoice_request = InvoiceRequest() invoice_request.sender_public_key = BIP75FunctionalTest.sender_sk.get_verifying_key().to_der() invoice_request.amount = 75 invoice_request.pki_type = 'x509+sha256' invoice_request.pki_data = sender_certs.SerializeToString() invoice_request.notification_url = 'https://notify.me/longId' invoice_request.signature = "" # Handle x509 Signature sig = crypto.sign(self.x509_sender_cert_privkey, invoice_request.SerializeToString(), 'sha1') invoice_request.signature = sig ################################## # Create Encrypted InvoiceRequest ################################## eir = self.create_encrypted_protocol_message( message=invoice_request, receiver_pubkey=BIP75FunctionalTest.receiver_sk.get_verifying_key(), sender_pubkey=BIP75FunctionalTest.sender_sk.get_verifying_key(), private_key=BIP75FunctionalTest.sender_sk ) BIP75FunctionalTest.identifier = eir.identifier ############################# # Sign & Submit HTTP Request ############################# post_url = "%s/address/testid/resolve" % self.get_server_url() msg_sig = BIP75FunctionalTest.sender_sk.sign(post_url + eir.SerializeToString()) ir_headers = { 'X-Identity': BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex'), 'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message', 'Content-Transfer-Encoding': 'binary' } log.info("Submitting InvoiceRequest using an EncryptedProtocolMessage") response = requests.post(post_url, headers=ir_headers, data=eir.SerializeToString()) # Validate Response self.assertEqual(202, response.status_code) self.assertTrue(response.headers.get('Location').startswith('https://%s/paymentprotocol' % config.site_url)) self.payment_id = response.headers.get('Location').rsplit('/', 1)[1] log.info('Payment ID: %s' % self.payment_id) ############################################### # Get Pending InvoiceRequests from Addressimo ############################################### sign_url = "%s/address/testid/paymentprotocol" % self.get_server_url() msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url) ir_req_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex') } log.info("Retrieving Encrypted InvoiceRequests") response = requests.get(sign_url, headers=ir_req_headers) log.info("Encrypted InvoiceRequest Retrieval Response [CODE: %d | TEXT: %s]" % (response.status_code, response.text)) self.assertEqual(200, response.status_code) self.assertIsNotNone(response.text) ############################################### # Retrieve and Decrypt Encrypted InvoiceRequest ############################################### received_eir = None for epm in response.json()['encrypted_protocol_messages']: _local_msg = self.parse_protocol_message(epm.decode('hex')) if _local_msg.message_type == ProtocolMessageType.Value('INVOICE_REQUEST') and _local_msg.identifier == BIP75FunctionalTest.identifier: received_eir = _local_msg if not received_eir: self.fail('Failed to Retrieve Encrypted InvoiceRequest message') sender_vk = VerifyingKey.from_der(received_eir.sender_public_key) self.assertEqual(received_eir.receiver_public_key, BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der()) received_invoice_request = self.get_decrypted_protocol_message(received_eir, sender_vk, BIP75FunctionalTest.receiver_sk) ######################### # Create PaymentRequest ######################### log.info("Building PaymentRequest") pd = PaymentDetails() pd.network = 'main' output = pd.outputs.add() output.amount = received_invoice_request.amount output.script = 'paymesomemoneyhere'.encode('hex') pd.time = int(datetime.utcnow().strftime('%s')) pd.expires = int((datetime.utcnow() + timedelta(seconds=3600)).strftime('%s')) pd.memo = '' pd.payment_url = '' pd.merchant_data = '' receiver_certs = X509Certificates() receiver_certs.certificate.append(ssl.PEM_cert_to_DER_cert(crypto.dump_certificate(crypto.FILETYPE_PEM, self.x509_receiver_cert))) pr = PaymentRequest() pr.payment_details_version = 1 pr.pki_type = 'x509+sha256' pr.pki_data = receiver_certs.SerializeToString() pr.serialized_payment_details = pd.SerializeToString() pr.signature = '' sig = crypto.sign(self.x509_receiver_cert_privkey, pr.SerializeToString(), 'sha1') pr.signature = sig log.info('Encapsulating PaymentRequest in EncryptedProtocolMessage') epr = self.create_encrypted_protocol_message( message=pr, receiver_pubkey=BIP75FunctionalTest.receiver_sk.get_verifying_key(), sender_pubkey=BIP75FunctionalTest.sender_sk.get_verifying_key(), private_key=BIP75FunctionalTest.receiver_sk, identifier=BIP75FunctionalTest.identifier ) sign_url = "%s/address/testid/paymentprotocol" % self.get_server_url() msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url + epr.SerializeToString()) ir_req_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex'), 'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message', 'Content-Transfer-Encoding': 'binary' } log.info("Submitting PaymentRequest using an EncryptedProtocolMessage") response = requests.post(sign_url, data=epr.SerializeToString(), headers=ir_req_headers) log.info('Submit PaymentRequest Response: %s' % response.text) self.assertEqual(200, response.status_code) ############################################################################## # Delete InvoiceRequest after the PaymentRequest was submitted successfully delete_url = "%s/address/testid/paymentprotocol/%s/invoice_request" % (self.get_server_url(), received_eir.identifier.encode('hex')) msg_sig = BIP75FunctionalTest.receiver_sk.sign(delete_url) ir_delete_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.delete(delete_url, headers=ir_delete_headers) self.assertEqual(response.status_code, requests.codes.no_content) ##################################### # Retrieve Encrypted PaymentRequest ##################################### log.info("Retrieving PaymentRequest") sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url) get_message_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.get(sign_url, headers=get_message_headers) self.assertIsNotNone(response) self.assertIn('Content-Type', response.headers) self.assertEqual('application/json', response.headers.get('Content-Type')) received_epr = None for epm in response.json()['encrypted_protocol_messages']: _local_msg = self.parse_protocol_message(epm.decode('hex')) if _local_msg.message_type == ProtocolMessageType.Value('PAYMENT_REQUEST') and _local_msg.identifier == BIP75FunctionalTest.identifier: received_epr = _local_msg log.info('Received Encrypted PaymentRequest') self.assertEqual(BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(), received_epr.receiver_public_key) self.assertEqual(BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(), received_epr.sender_public_key) # Decrypt Response returned_paymentrequest = self.get_decrypted_protocol_message( message=received_epr, pubkey=VerifyingKey.from_der(received_epr.receiver_public_key), privkey=BIP75FunctionalTest.sender_sk ) self.assertEqual(1, returned_paymentrequest.payment_details_version) self.assertEqual(pr.pki_type, returned_paymentrequest.pki_type) self.assertEqual(pr.pki_data, returned_paymentrequest.pki_data) self.assertEqual(pd.SerializeToString(), returned_paymentrequest.serialized_payment_details) self.assertEqual(pr.signature, returned_paymentrequest.signature) ####################################### # Create / Submit Payment ####################################### payment = Payment() payment.merchant_data = 'nodusttxs'.encode('hex') payment.transactions.append('btc_tx'.encode('hex')) out = payment.refund_to.add() out.script = 'myp2shaddress'.encode('hex') encrypted_payment = self.create_encrypted_protocol_message( message=payment, receiver_pubkey=VerifyingKey.from_der(received_epr.receiver_public_key), sender_pubkey=VerifyingKey.from_der(received_epr.sender_public_key), private_key=BIP75FunctionalTest.sender_sk, identifier=BIP75FunctionalTest.identifier ) # Submit Payment sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.sender_sk.sign(sign_url + encrypted_payment.SerializeToString()) ep_req_headers = { 'X-Identity': BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex'), 'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message', 'Content-Transfer-Encoding': 'binary' } log.info("Submitting Payment using an EncryptedProtocolMessage") response = requests.post(sign_url, data=encrypted_payment.SerializeToString(), headers=ep_req_headers) log.info('Submit Payment Response: %s' % response.text) self.assertEqual(200, response.status_code) ############################################################################## # Delete PaymentRequest after the Payment was submitted successfully delete_url = "%s/paymentprotocol/%s/%s/payment_request" % (self.get_server_url(), self.payment_id, received_eir.identifier.encode('hex')) msg_sig = BIP75FunctionalTest.receiver_sk.sign(delete_url) ir_delete_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.delete(delete_url, headers=ir_delete_headers) self.assertEqual(response.status_code, requests.codes.no_content) ############################ # Retrieve Payment ############################ log.info("Retrieving Payment") sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url) get_message_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.get(sign_url, headers=get_message_headers) self.assertIsNotNone(response) self.assertIn('Content-Type', response.headers) self.assertEqual('application/json', response.headers.get('Content-Type')) returned_ep = None for epm in response.json()['encrypted_protocol_messages']: _local_msg = self.parse_protocol_message(epm.decode('hex')) if _local_msg.message_type == ProtocolMessageType.Value('PAYMENT') and _local_msg.identifier == BIP75FunctionalTest.identifier: returned_ep = _local_msg self.assertEqual(BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(), returned_ep.receiver_public_key) self.assertEqual(BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(), returned_ep.sender_public_key) self.assertEqual(encrypted_payment.encrypted_message, returned_ep.encrypted_message) payment_msg = self.get_decrypted_protocol_message( message=returned_ep, pubkey=VerifyingKey.from_der(returned_ep.sender_public_key), privkey=BIP75FunctionalTest.receiver_sk ) self.assertEqual('nodusttxs'.encode('hex'), payment_msg.merchant_data) self.assertEqual(1, len(payment_msg.transactions)) self.assertEqual('btc_tx'.encode('hex'), payment_msg.transactions[0]) ####################################### # Create / Submit PaymentACK ####################################### paymentack = PaymentACK() paymentack.payment.CopyFrom(payment_msg) paymentack.memo = 'Payment ACKed' encrypted_paymentack = self.create_encrypted_protocol_message( message=paymentack, receiver_pubkey=VerifyingKey.from_der(epr.receiver_public_key), sender_pubkey=VerifyingKey.from_der(epr.sender_public_key), private_key=BIP75FunctionalTest.receiver_sk, identifier=BIP75FunctionalTest.identifier ) # Submit PaymentAck sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url + encrypted_paymentack.SerializeToString()) ep_req_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex'), 'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message', 'Content-Transfer-Encoding': 'binary' } log.info("Submitting PaymentAck using an EncryptedProtocolMessage") response = requests.post(sign_url, data=encrypted_paymentack.SerializeToString(), headers=ep_req_headers) log.info('Submit PaymentAck Response: %s' % response.text) self.assertEqual(200, response.status_code) ############################################################################## # Delete Payment after the PaymentACK was submitted successfully delete_url = "%s/address/testid/paymentprotocol/%s/payment" % (self.get_server_url(), received_eir.identifier.encode('hex')) msg_sig = BIP75FunctionalTest.receiver_sk.sign(delete_url) ir_delete_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.delete(delete_url, headers=ir_delete_headers) self.assertEqual(response.status_code, requests.codes.no_content) ############################### # Retrieve PaymentAck ############################### log.info("Retrieving EncryptedPaymentAck") sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.receiver_sk.sign(sign_url) get_message_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.get(sign_url, headers=get_message_headers) self.assertIsNotNone(response) self.assertIn('Content-Type', response.headers) self.assertEqual('application/json', response.headers.get('Content-Type')) returned_epa = None for epm in response.json()['encrypted_protocol_messages']: _local_msg = self.parse_protocol_message(epm.decode('hex')) if _local_msg.message_type == ProtocolMessageType.Value('PAYMENT_ACK') and _local_msg.identifier == BIP75FunctionalTest.identifier: returned_epa = _local_msg log.info('Received PaymentACK') self.assertEqual(BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(), returned_ep.receiver_public_key) self.assertEqual(BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(), returned_ep.sender_public_key) self.assertEqual(encrypted_paymentack.encrypted_message, returned_epa.encrypted_message) paymentack_msg = self.get_decrypted_protocol_message( message=returned_epa, pubkey=VerifyingKey.from_der(returned_epa.sender_public_key), privkey=BIP75FunctionalTest.receiver_sk ) self.assertEqual(paymentack_msg, paymentack) ############################################################################## # Delete PaymentACK after the PaymentACK was retrieved successfully delete_url = "%s/address/testid/paymentprotocol/%s/payment_ack" % (self.get_server_url(), received_eir.identifier.encode('hex')) msg_sig = BIP75FunctionalTest.receiver_sk.sign(delete_url) ir_delete_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der().encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.delete(delete_url, headers=ir_delete_headers) self.assertEqual(response.status_code, requests.codes.no_content)
def test_bip75_flow(self): ################### # Load Crypto Keys ################### self.x509_sender_cert = crypto.load_certificate( crypto.FILETYPE_PEM, SENDER_CERT) self.x509_sender_cert_privkey = crypto.load_privatekey( crypto.FILETYPE_PEM, SENDER_CERT_PRIVKEY) self.x509_receiver_cert = crypto.load_certificate( crypto.FILETYPE_PEM, RECEIVER_CERT) self.x509_receiver_cert_privkey = crypto.load_privatekey( crypto.FILETYPE_PEM, RECEIVER_CERT_PRIVKEY) ################################ # Register Addressimo Endpoint ################################ self.register_endpoint() ######################### # Create InvoiceRequest ######################### log.info("Building InvoiceRequest") sender_certs = X509Certificates() sender_certs.certificate.append( ssl.PEM_cert_to_DER_cert( crypto.dump_certificate(crypto.FILETYPE_PEM, self.x509_sender_cert))) invoice_request = InvoiceRequest() invoice_request.sender_public_key = BIP75FunctionalTest.sender_sk.get_verifying_key( ).to_der() invoice_request.amount = 75 invoice_request.pki_type = 'x509+sha256' invoice_request.pki_data = sender_certs.SerializeToString() invoice_request.notification_url = 'https://notify.me/longId' invoice_request.signature = "" # Handle x509 Signature sig = crypto.sign(self.x509_sender_cert_privkey, invoice_request.SerializeToString(), 'sha256') invoice_request.signature = sig ################################## # Create Encrypted InvoiceRequest ################################## eir = self.create_encrypted_protocol_message( message=invoice_request, receiver_pubkey=BIP75FunctionalTest.receiver_sk.get_verifying_key( ), sender_pubkey=BIP75FunctionalTest.sender_sk.get_verifying_key(), private_key=BIP75FunctionalTest.sender_sk) BIP75FunctionalTest.identifier = eir.identifier ############################# # Sign & Submit HTTP Request ############################# post_url = "%s/address/%s/resolve" % (self.get_server_url(), self.addressimo_endpoint_id) msg_sig = BIP75FunctionalTest.sender_sk.sign(self.get_signing_data( post_url, 'post', eir.SerializeToString()), hashfunc=sha256, sigencode=sigencode_der) ir_headers = { 'X-Identity': BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode( 'hex'), 'X-Signature': msg_sig.encode('hex'), 'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message', 'Content-Transfer-Encoding': 'binary' } log.info("Submitting InvoiceRequest using an EncryptedProtocolMessage") response = requests.post(post_url, headers=ir_headers, data=eir.SerializeToString()) # Validate Response self.assertEqual(202, response.status_code) self.assertTrue( response.headers.get('Location').startswith( 'https://%s/paymentprotocol' % config.site_url)) self.payment_id = response.headers.get('Location').rsplit('/', 1)[1] log.info('Payment ID: %s' % self.payment_id) ############################################### # Get Pending InvoiceRequests from Addressimo ############################################### sign_url = "%s/address/%s/paymentprotocol" % ( self.get_server_url(), self.addressimo_endpoint_id) msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data( sign_url, 'get'), hashfunc=sha256, sigencode=sigencode_der) ir_req_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(). encode('hex'), 'X-Signature': msg_sig.encode('hex') } log.info("Retrieving Encrypted InvoiceRequests") response = requests.get(sign_url, headers=ir_req_headers) log.info( "Encrypted InvoiceRequest Retrieval Response [CODE: %d | TEXT: %s]" % (response.status_code, response.text)) self.assertEqual(200, response.status_code) self.assertIsNotNone(response.text) ############################################### # Retrieve and Decrypt Encrypted InvoiceRequest ############################################### received_eir = None for epm in response.json()['encrypted_protocol_messages']: _local_msg = self.parse_protocol_message(epm.decode('hex')) if _local_msg.message_type == ProtocolMessageType.Value( 'INVOICE_REQUEST' ) and _local_msg.identifier == BIP75FunctionalTest.identifier: received_eir = _local_msg if not received_eir: self.fail('Failed to Retrieve Encrypted InvoiceRequest message') sender_vk = VerifyingKey.from_der(received_eir.sender_public_key) self.assertEqual( received_eir.receiver_public_key, BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der()) received_invoice_request = self.get_decrypted_protocol_message( received_eir, sender_vk, BIP75FunctionalTest.receiver_sk) ######################### # Create PaymentRequest ######################### log.info("Building PaymentRequest") pd = PaymentDetails() pd.network = 'main' output = pd.outputs.add() output.amount = received_invoice_request.amount output.script = 'paymesomemoneyhere'.encode('hex') pd.time = int(datetime.utcnow().strftime('%s')) pd.expires = int( (datetime.utcnow() + timedelta(seconds=3600)).strftime('%s')) pd.memo = '' pd.payment_url = '' pd.merchant_data = '' receiver_certs = X509Certificates() receiver_certs.certificate.append( ssl.PEM_cert_to_DER_cert( crypto.dump_certificate(crypto.FILETYPE_PEM, self.x509_receiver_cert))) pr = PaymentRequest() pr.payment_details_version = 1 pr.pki_type = 'x509+sha256' pr.pki_data = receiver_certs.SerializeToString() pr.serialized_payment_details = pd.SerializeToString() pr.signature = '' sig = crypto.sign(self.x509_receiver_cert_privkey, pr.SerializeToString(), 'sha256') pr.signature = sig log.info('Encapsulating PaymentRequest in EncryptedProtocolMessage') epr = self.create_encrypted_protocol_message( message=pr, receiver_pubkey=BIP75FunctionalTest.receiver_sk.get_verifying_key( ), sender_pubkey=BIP75FunctionalTest.sender_sk.get_verifying_key(), private_key=BIP75FunctionalTest.receiver_sk, identifier=BIP75FunctionalTest.identifier) sign_url = "%s/address/%s/paymentprotocol" % ( self.get_server_url(), self.addressimo_endpoint_id) msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data( sign_url, 'post', epr.SerializeToString()), hashfunc=sha256, sigencode=sigencode_der) ir_req_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(). encode('hex'), 'X-Signature': msg_sig.encode('hex'), 'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message', 'Content-Transfer-Encoding': 'binary' } log.info("Submitting PaymentRequest using an EncryptedProtocolMessage") response = requests.post(sign_url, data=epr.SerializeToString(), headers=ir_req_headers) log.info('Submit PaymentRequest Response: %s' % response.text) self.assertEqual(200, response.status_code) ############################################################################## # Delete InvoiceRequest after the PaymentRequest was submitted successfully ############################################################################## delete_url = "%s/address/%s/paymentprotocol/%s/invoice_request" % ( self.get_server_url(), self.addressimo_endpoint_id, received_eir.identifier.encode('hex')) msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data( delete_url, 'delete'), hashfunc=sha256, sigencode=sigencode_der) ir_delete_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(). encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.delete(delete_url, headers=ir_delete_headers) self.assertEqual(response.status_code, requests.codes.no_content) ##################################### # Retrieve Encrypted PaymentRequest ##################################### log.info("Retrieving PaymentRequest") sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.sender_sk.sign(self.get_signing_data( sign_url, 'get'), hashfunc=sha256, sigencode=sigencode_der) get_message_headers = { 'X-Identity': BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode( 'hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.get(sign_url, headers=get_message_headers) self.assertIsNotNone(response) self.assertIn('Content-Type', response.headers) self.assertEqual('application/json', response.headers.get('Content-Type')) received_epr = None for epm in response.json()['encrypted_protocol_messages']: _local_msg = self.parse_protocol_message(epm.decode('hex')) if _local_msg.message_type == ProtocolMessageType.Value( 'PAYMENT_REQUEST' ) and _local_msg.identifier == BIP75FunctionalTest.identifier: received_epr = _local_msg log.info('Received Encrypted PaymentRequest') self.assertEqual( BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(), received_epr.receiver_public_key) self.assertEqual( BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(), received_epr.sender_public_key) # Decrypt Response returned_paymentrequest = self.get_decrypted_protocol_message( message=received_epr, pubkey=VerifyingKey.from_der(received_epr.receiver_public_key), privkey=BIP75FunctionalTest.sender_sk) self.assertEqual(1, returned_paymentrequest.payment_details_version) self.assertEqual(pr.pki_type, returned_paymentrequest.pki_type) self.assertEqual(pr.pki_data, returned_paymentrequest.pki_data) self.assertEqual(pd.SerializeToString(), returned_paymentrequest.serialized_payment_details) self.assertEqual(pr.signature, returned_paymentrequest.signature) ####################################### # Create / Submit Payment ####################################### payment = Payment() payment.merchant_data = 'nodusttxs'.encode('hex') payment.transactions.append('btc_tx'.encode('hex')) out = payment.refund_to.add() out.script = 'myp2shaddress'.encode('hex') encrypted_payment = self.create_encrypted_protocol_message( message=payment, receiver_pubkey=VerifyingKey.from_der( received_epr.receiver_public_key), sender_pubkey=VerifyingKey.from_der( received_epr.sender_public_key), private_key=BIP75FunctionalTest.sender_sk, identifier=BIP75FunctionalTest.identifier) # Submit Payment sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.sender_sk.sign(self.get_signing_data( sign_url, 'post', encrypted_payment.SerializeToString()), hashfunc=sha256, sigencode=sigencode_der) ep_req_headers = { 'X-Identity': BIP75FunctionalTest.sender_sk.get_verifying_key().to_der().encode( 'hex'), 'X-Signature': msg_sig.encode('hex'), 'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message', 'Content-Transfer-Encoding': 'binary' } log.info("Submitting Payment using an EncryptedProtocolMessage") response = requests.post(sign_url, data=encrypted_payment.SerializeToString(), headers=ep_req_headers) log.info('Submit Payment Response: %s' % response.text) self.assertEqual(200, response.status_code) ############################################################################## # Delete PaymentRequest after the Payment was submitted successfully ############################################################################## delete_url = "%s/paymentprotocol/%s/%s/payment_request" % ( self.get_server_url(), self.payment_id, received_eir.identifier.encode('hex')) msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data( delete_url, 'delete'), hashfunc=sha256, sigencode=sigencode_der) ir_delete_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(). encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.delete(delete_url, headers=ir_delete_headers) self.assertEqual(response.status_code, requests.codes.no_content) ############################ # Retrieve Payment ############################ log.info("Retrieving Payment") sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data( sign_url, 'get'), hashfunc=sha256, sigencode=sigencode_der) get_message_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(). encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.get(sign_url, headers=get_message_headers) self.assertIsNotNone(response) self.assertIn('Content-Type', response.headers) self.assertEqual('application/json', response.headers.get('Content-Type')) returned_ep = None for epm in response.json()['encrypted_protocol_messages']: _local_msg = self.parse_protocol_message(epm.decode('hex')) if _local_msg.message_type == ProtocolMessageType.Value( 'PAYMENT' ) and _local_msg.identifier == BIP75FunctionalTest.identifier: returned_ep = _local_msg self.assertEqual( BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(), returned_ep.receiver_public_key) self.assertEqual( BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(), returned_ep.sender_public_key) self.assertEqual(encrypted_payment.encrypted_message, returned_ep.encrypted_message) payment_msg = self.get_decrypted_protocol_message( message=returned_ep, pubkey=VerifyingKey.from_der(returned_ep.sender_public_key), privkey=BIP75FunctionalTest.receiver_sk) self.assertEqual('nodusttxs'.encode('hex'), payment_msg.merchant_data) self.assertEqual(1, len(payment_msg.transactions)) self.assertEqual('btc_tx'.encode('hex'), payment_msg.transactions[0]) ####################################### # Create / Submit PaymentACK ####################################### paymentack = PaymentACK() paymentack.payment.CopyFrom(payment_msg) paymentack.memo = 'Payment ACKed' encrypted_paymentack = self.create_encrypted_protocol_message( message=paymentack, receiver_pubkey=VerifyingKey.from_der(epr.receiver_public_key), sender_pubkey=VerifyingKey.from_der(epr.sender_public_key), private_key=BIP75FunctionalTest.receiver_sk, identifier=BIP75FunctionalTest.identifier) # Submit PaymentAck sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data( sign_url, 'post', encrypted_paymentack.SerializeToString()), hashfunc=sha256, sigencode=sigencode_der) ep_req_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(). encode('hex'), 'X-Signature': msg_sig.encode('hex'), 'Content-Type': 'application/bitcoin-encrypted-paymentprotocol-message', 'Content-Transfer-Encoding': 'binary' } log.info("Submitting PaymentAck using an EncryptedProtocolMessage") response = requests.post(sign_url, data=encrypted_paymentack.SerializeToString(), headers=ep_req_headers) log.info('Submit PaymentAck Response: %s' % response.text) self.assertEqual(200, response.status_code) ############################################################################## # Delete Payment after the PaymentACK was submitted successfully ############################################################################## delete_url = "%s/address/%s/paymentprotocol/%s/payment" % ( self.get_server_url(), self.addressimo_endpoint_id, received_eir.identifier.encode('hex')) msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data( delete_url, 'delete'), hashfunc=sha256, sigencode=sigencode_der) ir_delete_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(). encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.delete(delete_url, headers=ir_delete_headers) self.assertEqual(response.status_code, requests.codes.no_content) ############################### # Retrieve PaymentAck ############################### log.info("Retrieving EncryptedPaymentAck") sign_url = "%s/paymentprotocol/%s" % (self.get_server_url(), self.payment_id) msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data( sign_url, 'get'), hashfunc=sha256, sigencode=sigencode_der) get_message_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(). encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.get(sign_url, headers=get_message_headers) self.assertIsNotNone(response) self.assertIn('Content-Type', response.headers) self.assertEqual('application/json', response.headers.get('Content-Type')) returned_epa = None for epm in response.json()['encrypted_protocol_messages']: _local_msg = self.parse_protocol_message(epm.decode('hex')) if _local_msg.message_type == ProtocolMessageType.Value( 'PAYMENT_ACK' ) and _local_msg.identifier == BIP75FunctionalTest.identifier: returned_epa = _local_msg log.info('Received PaymentACK') self.assertEqual( BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(), returned_ep.receiver_public_key) self.assertEqual( BIP75FunctionalTest.sender_sk.get_verifying_key().to_der(), returned_ep.sender_public_key) self.assertEqual(encrypted_paymentack.encrypted_message, returned_epa.encrypted_message) paymentack_msg = self.get_decrypted_protocol_message( message=returned_epa, pubkey=VerifyingKey.from_der(returned_epa.sender_public_key), privkey=BIP75FunctionalTest.receiver_sk) self.assertEqual(paymentack_msg, paymentack) ############################################################################## # Delete PaymentACK after the PaymentACK was retrieved successfully ############################################################################## delete_url = "%s/address/%s/paymentprotocol/%s/payment_ack" % ( self.get_server_url(), self.addressimo_endpoint_id, received_eir.identifier.encode('hex')) msg_sig = BIP75FunctionalTest.receiver_sk.sign(self.get_signing_data( delete_url, 'delete'), hashfunc=sha256, sigencode=sigencode_der) ir_delete_headers = { 'X-Identity': BIP75FunctionalTest.receiver_sk.get_verifying_key().to_der(). encode('hex'), 'X-Signature': msg_sig.encode('hex') } response = requests.delete(delete_url, headers=ir_delete_headers) self.assertEqual(response.status_code, requests.codes.no_content) ################################ # Delete Addressimo Endpoint ################################ self.cleanup_endpoint()