""" Convert PEM certificate to P7B (PKCS#7) format for Square webhooks Square requires P7B format for webhook signature verification """ import subprocess import sys import os def convert_pem_to_p7b(cert_file="cert.pem", output_file="cert.p7b"): """ Convert PEM certificate to P7B (PKCS#7) format Args: cert_file: Input PEM certificate file output_file: Output P7B file """ # Check if OpenSSL is available try: subprocess.run(["openssl", "version"], capture_output=True, check=True) except (subprocess.CalledProcessError, FileNotFoundError): print("ERROR: OpenSSL not found!") print("\nFor Windows, you can:") print( "1. Install OpenSSL from: https://slproweb.com/products/Win32OpenSSL.html" ) print("2. Or use Git Bash which includes OpenSSL") print("3. Or use WSL (Windows Subsystem for Linux)") return False # Check if input file exists if not os.path.exists(cert_file): print(f"ERROR: Certificate file not found: {cert_file}") print(f"Current directory: {os.getcwd()}") print("\nMake sure you've generated the certificate first:") print(" python generate_cert.py") return False print(f"Converting {cert_file} to P7B format...") # Convert PEM to P7B (PKCS#7) # -certfile can include intermediate certificates if needed cmd = [ "openssl", "crl2pkcs7", "-nocrl", "-certfile", cert_file, "-out", output_file, ] try: result = subprocess.run(cmd, check=True, capture_output=True, text=True) if os.path.exists(output_file): print(f"\n✓ P7B certificate created: {os.path.abspath(output_file)}") print(f" File size: {os.path.getsize(output_file)} bytes") print("\n" + "=" * 60) print("Square Webhook Configuration:") print("=" * 60) print(f"1. Upload this file to Square Developer Dashboard:") print(f" {os.path.abspath(output_file)}") print("\n2. In Square Dashboard:") print(" - Go to Webhooks settings") print(" - Click 'Manage Notification Settings'") print(" - Upload the P7B file for signature verification") print("\n3. Square will use this to verify webhook signatures") print("=" * 60) # Show file contents preview print("\nP7B file preview (first 500 chars):") with open(output_file, "r") as f: content = f.read(500) print(content) if len(content) == 500: print("...") return True else: print("ERROR: Output file was not created") return False except subprocess.CalledProcessError as e: print(f"ERROR: Conversion failed: {e}") if e.stderr: print(f"OpenSSL error: {e.stderr}") return False def convert_with_chain(cert_file="cert.pem", chain_file=None, output_file="cert.p7b"): """ Convert PEM certificate with certificate chain to P7B format Use this if you have intermediate certificates Args: cert_file: Your certificate file chain_file: Intermediate/chain certificate file (optional) output_file: Output P7B file """ if not chain_file: return convert_pem_to_p7b(cert_file, output_file) # Check files exist for f in [cert_file, chain_file]: if not os.path.exists(f): print(f"ERROR: File not found: {f}") return False print(f"Converting {cert_file} with chain {chain_file} to P7B format...") # Create combined cert file combined = "combined_cert.pem" with open(combined, "w") as out: with open(cert_file, "r") as f: out.write(f.read()) with open(chain_file, "r") as f: out.write(f.read()) result = convert_pem_to_p7b(combined, output_file) # Clean up combined file if os.path.exists(combined): os.remove(combined) return result if __name__ == "__main__": import argparse parser = argparse.ArgumentParser( description="Convert PEM certificate to P7B (PKCS#7) for Square webhooks" ) parser.add_argument( "--cert", default="cert.pem", help="Input PEM certificate file (default: cert.pem)", ) parser.add_argument( "--chain", default=None, help="Optional: Intermediate certificate chain file" ) parser.add_argument( "--output", default="cert.p7b", help="Output P7B file (default: cert.p7b)" ) args = parser.parse_args() print("=" * 60) print("PEM to P7B Certificate Converter for Square Webhooks") print("=" * 60) print() if args.chain: success = convert_with_chain(args.cert, args.chain, args.output) else: success = convert_pem_to_p7b(args.cert, args.output) if not success: sys.exit(1) print("\n✓ Conversion complete!")