發票列印 - PDF

應用場景

  • 特店可使用此API取得單一發票PDF檔
  • 同一IP,10秒內最多只可呼叫2次

API介接網址

  • 測試環境:https://einvoice-stage.ecpay.com.tw/B2BInvoice/DownloadB2BPdf
  • 正式環境:https://einvoice.ecpay.com.tw/B2BInvoice/DownloadB2BPdf

HTTPS傳輸協定

  • Content Type :application/json
  • HTTP Method :POST

特店傳入參數(Json格式)

PlatformID String(10)
特約合作平台商代號

  • 提供特約合作平台商向綠界申請開通後使用,一般廠商介接請放空值。
  • 平台商使用時,MerchantID(特店編號)欄位僅限帶入已綁定子廠商的特店編號,以免造成失敗。

MerchantID String(10)
特店編號 必填

RqHeader Object
傳入資料 必填

Timestamp Number
傳入時間 必填

請將傳輸時間轉換為時間戳(GMT+8),綠界會利用此參數將當下的時間轉為Unix TimeStamp來驗證此次介接的時間區間。

❗ 注意事項

  • 驗證時間區間暫訂為 10 分鐘內有效,若超過此驗證時間則此次訂單將無法建立,參考資料:http://www.epochconverter.com/
  • 合作特店須進行主機「時間校正」,避免主機產生時差,導致API無法正常運作。

Data String
加密資料 必填

回傳相關資料,此為加密過JSON格式的資料。加密方法說明

特店傳入參數範例(Json格式)

				
					{
    "MerchantID": "2000132",
    "RqHeader": {
        "Timestamp": 1525168923
    },
    "Data": "加密資料"
}

				
			

Data參數說明(Json格式)

MerchantID String(10)
特店編號 必填

InvoiceCategory Int
B2B發票種類

  • 0:銷項發票(查詢特店開給交易相對人的發票明細)- (預設值)
  • 1:進項發票(查詢交易相對人開給特店的發票明細)

InvoiceNo String(10)
發票號碼 必填

2碼字軌+8碼數字

InvoiceDate String(20)
發票開立日期 必填

格式為「yyyy-MM-dd」

PrintStyle Int
發票列印格式

  • 1:A4列印 (預設值)
  • 2:A5列印

Data參數範例(Json格式)

				
					{
    "MerchantID": "2000132",
    "InvoiceCategory": 0,
    "InvoiceNo": "UV11100016",
    "InvoiceDate": "2018-10-28",
    "InvoiceNo": 1
}
				
			

綠界回傳參數格式

  • Content Type :application/pdf
  • Content-Disposition: attachment; filename=”xxxx.pdf”

綠界回傳一串PDF文件的二進位檔,可直接存成 .pdf 檔

Python 版本範例程式

				
					import requests
import json
import urllib.parse
from Crypto.Cipher import AES
import base64

class ECPayInvoice:
    def __init__(self, merchant_id, hash_key, hash_iv, is_production=False):
        """
        初始化 ECPay 發票物件
        :param merchant_id: 特店編號
        :param hash_key: HashKey
        :param hash_iv: HashIV
        :param is_production: 是否為正式環境
        """
        self.merchant_id = merchant_id
        self.hash_key = hash_key.encode('utf-8')
        self.hash_iv = hash_iv.encode('utf-8')
        
        # 設定環境 URL
        self.url = "https://einvoice.ecpay.com.tw/B2BInvoice/DownloadB2BPdf" if is_production else \
                  "https://einvoice-stage.ecpay.com.tw/B2BInvoice/DownloadB2BPdf"

    def encrypt_data(self, data):
        """
        加密資料
        :param data: 要加密的資料字典
        :return: 加密後的字串
        """
        # 1. 將 dict 轉換為 JSON 字串
        json_str = json.dumps(data, sort_keys=True)
        
        # 2. 進行 URL encode(使用大寫編碼)
        url_encoded = urllib.parse.quote(json_str, safe='')
        
        # 3. AES 加密
        cipher = AES.new(self.hash_key, AES.MODE_CBC, self.hash_iv)
        # 補足長度至 16 的倍數(PKCS7)
        pad = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16)
        raw = pad(url_encoded)
        encrypted = cipher.encrypt(raw.encode('utf-8'))
        
        # 4. Base64 編碼
        return base64.b64encode(encrypted).decode('utf-8')

    def download_invoice_pdf(self, invoice_no, invoice_date, invoice_category=0, print_style=1):
        """
        下載發票 PDF
        :param invoice_no: 發票號碼
        :param invoice_date: 發票日期 (yyyy-MM-dd)
        :param invoice_category: 發票類型 (0 or 1)
        :param print_style: 列印格式 (1=一般發票, 2=三聯式發票)
        :return: 成功時返回 True 和檔案路徑,失敗時返回 False 和錯誤訊息
        """
        # 準備加密資料
        data = {
            "InvoiceNo": invoice_no,
            "InvoiceDate": invoice_date,
            "InvoiceCategory": invoice_category,
            "PrintStyle": print_style
        }
        
        # 加密資料
        encrypted_data = self.encrypt_data(data)
        
        # 準備請求參數
        payload = {
            "PlatformID": "",
            "MerchantID": self.merchant_id,
            "RqHeader": {
                "Timestamp": 1672534831  # 請替換為實際時間戳記
            },
            "Data": encrypted_data
        }
        
        # 設定標頭
        headers = {
            "Content-Type": "application/json"
        }
        
        try:
            # 發送請求
            response = requests.post(self.url, json=payload, headers=headers, stream=True)
            
            if response.status_code == 200:
                # 儲存 PDF
                file_path = f"invoice_{invoice_no}.pdf"
                with open(file_path, "wb") as f:
                    for chunk in response.iter_content(chunk_size=8192):
                        if chunk:
                            f.write(chunk)
                return True, file_path
            else:
                return False, f"下載失敗,HTTP 狀態碼: {response.status_code}, 回應內容: {response.text}"
                
        except Exception as e:
            return False, f"發生錯誤: {str(e)}"

# 使用範例
if __name__ == "__main__":
    # 測試環境參數
    merchant_id = "2000132"
    hash_key = "ejCk326UnaZWKisg"
    hash_iv = "q9jcZX8Ib9LM8wYk"
    
    # 初始化物件
    ecpay = ECPayInvoice(merchant_id, hash_key, hash_iv, is_production=False)
    
    # 下載發票
    success, result = ecpay.download_invoice_pdf(
        invoice_no="AB12345678",
        invoice_date="2023-08-01",
        invoice_category=0,
        print_style=1
    )
    
    if success:
        print(f"PDF 下載成功,已儲存為 {result}")
    else:
        print(f"下載失敗:{result}")
				
			

Copyright © Green World FinTech Service Co., Ltd. All rights reserved.

綠界官方網站