綠界電子發票串接攻略

綠界電子發票串接攻略

這篇文章說明該如何利用套件來快速進行電子發票串接

實作方式很單純,與金流串接流程相同,但在發送參數時追加電子發票參數,就能夠讓綠界幫我們上傳電子發票到大平台

綠界科技提供合作特店透過介接方式整合電子發票作業功能,且支援48小時內將發票上傳至財政部。消費者若持有對應的「載具」(如自然人憑證),便不需列印紙本發票可直接將發票儲存於載具中。同時也提供發票查詢功能,可協助合作特店將其功能整合至網站(以下簡稱為合作特店系統),讓消費者能在線上查詢發票。合作特店也可透過電子郵件或簡訊的方式將發票通知寄出

PS:這篇文章所稱的大平台指的是國稅局所設立的電子發票大平台

開立流程

綠界科技系統收到營業人(賣家)傳送開立發票參數後,立即開立電子發票上傳大平台,並即時通知消費者(買家)電子發票已開立。營業人可於網站購物車頁面或會員資料頁面,提供以下發票資料設定項目供買受人選擇(下圖為參考範例,營業人可自行設計)

綠界電子發票串接攻略

綠界電子發票串接攻略

前置準備

取得介接金鑰

如果需要透過綠界來進行付款,是需要申請綠界帳號並且通過審核得到信用卡付款資格的。但如果只是想要練習串接測試的話,則不需要,這裡提供測試電子發票的金鑰

綠界電子發票串接攻略

PS:正式環境的金鑰可以在管理後台 > 系統開發管理 > App金流/物流介接設定去取得

設定允許連接的 IP Address

到「綠界科技廠商管理後台->系統開發管理->系統介接設定」設定[允許的IP],以方便後續API介接

基於資訊安全考量,綠界科技會限制介接來源IP位址的存取,所以需要填寫合作特店系統Server的對外IP位址至[允許的IP]欄位)

綠界電子發票串接攻略

實作流程

PS:以下流程大部分均與綠界金流串接內容重複,如果已經做過金流串接的部分,則該步驟可以直接跳過

Step 1. 下載套件

開啟 Terminal ,輸入以下指令:

composer require tsaiyihua/laravel-ecpay

PS:需注意此套件支援 PHP 7.2 版本,Laravel 版本 6.0 以上

如果想參考綠界的技術文件,套件資料夾內有一份,路徑為 vendor/tsaiyihua/laravel-ecpay/documents/ecpay_gw_i110.pdf

Step 2. 環境設定

同樣在 Terminal ,輸入以下指令:

這將會在 config 資料夾裡頭加入一個名為 ecpay.php 的設定檔,但你無需進行任何修改

php artisan vendor:publish --tag=ecpay

修改 .env 檔案,在裡頭加入以下金鑰設定,我預設已經為你準備好了測試帳密,可先不修改直接使用。但如果要連正式環境,就記得要改成申請得到的金鑰了!

ECPAY_MERCHANT_ID=2000132
ECPAY_HASH_KEY=5294y06JbISpM5x9
ECPAY_HASH_IV=v77hoKGq4kWxNNIS
ECPAY_INVOICE_HASH_KEY=ejCk326UnaZWKisg
ECPAY_INVOICE_HASH_IV=q9jcZX8Ib9LM8wYk
ECPAY_SEND_FORM=

Step 3.修改訂單表格(非必須)

一般來說當付款完畢會需要儲存金流端所傳回的資料,因此有必要擴增訂單表格的欄位,以下給出一個建議訂單表格的欄位

//database\migrations\create_orders_table

public function up()
    {
        Schema::create('orders', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('owner_id')->index(); //下單人
            $table->foreign('owner_id')->references('id')->on('users')->onDelete('cascade');
            $table->string('receiver', 10)->nullable(); //收件人姓名
            $table->string('receiverTitle', 10)->nullable(); //收件人頭銜
            $table->string('receiverMobile', 20)->nullable(); //收件人手機號碼
            $table->string('receiverEmail', 100)->nullable(); //收件人電子郵箱
            $table->string('receiverAddress', 100)->nullable(); //收件人地址
            $table->string('message', 500)->nullable(); //訊息
            $table->string('couponCode', 100)->nullable(); //優惠券序號
            $table->integer('subtotal')->default(0); //訂單金額
            $table->integer('shipCost')->default(0); //運費
            $table->string('status', 20)->default('create'); //訂單狀態,包含 create 建立 paid 已付款 done 已完成 canceled 已取消
            $table->string('pay_type', 100)->nullable(); //付款類型
            $table->string('trade_no', 100)->nullable(); //金流序號
            $table->timestamp('pay_at')->nullable(); //付款時間
            $table->string('reply_desc', 255)->nullable(); //回覆給客戶的訊息
            $table->string('type', 255)->default('normal'); //類型
                        $table->string('invoiceNumber',20)->nullable(); //發票號碼
            $table->timestamps();
        });
    }

Step 4.修改訂單模型(可選)

最好是把訂單表格可被修改的欄位都寫進 $fillable 屬性內,以免出現 MassAssignment 錯誤

//app\Models\Order.php

protected $fillable = ['owner_id', 'trade_no', 'pay_type', 'pay_at', 'status'];

Step 5. 修改路由檔

套件會為我們建立一些需要的路由,但因為我們希望付款完成後能通知我們來變更訂單狀態,所以需要新增 callback 路由

Route::namespace('App\Http\Controllers')->group(function(){
    ...
    Route::get('/checkoutinvoice','SiteController@checkoutWithInvoice');
    Route::post('/checkout/callback','SiteController@checkoutCallback');
    ...
});

Step 6.修改 CsrfToken 中介層

預設所有 Post 請求都需要附帶 Token 來防止跨站攻擊,但因為金流不會有我們的 Token ,所以要將提供給綠界轉址的路由予以除外才行

//app\Http\Middleware\VerifyCsrfToken.php

protected $except = [
   'checkout/callback'
];

Step 7.調整視圖檔案

別忘了根據所設置的路由檔路徑來制定超連結,並且將之置入於你的視圖裡頭,就像這個例子:

@if (setting('admin.is_send_invoice') == 'off')
    <a class="btn_1 checkout_btn_1" href="{{ url('/checkout') }}">結帳</a>
@else
    <a class="btn_1 checkout_btn_1" href="{{ url('/checkoutinvoice') }}">結帳</a>
@endif

Step 8.擴展控制器

控制器的邏輯你可根據自己需求來建立,以下提供一些基礎的結帳常見程式碼

//app\Http\Controllers\SiteController.php

use Carbon\Carbon;
use App\Models\Item;
use App\Models\Order;
use App\Models\OrderItem;
use Darryldecode\Cart\Cart;
use Illuminate\Http\Request;
use TsaiYiHua\ECPay\Checkout;
use Illuminate\Support\Facades\Log;

class SiteController extends Controller
{
    protected $checkout;

    public function __construct(Checkout $checkout)
    {
        $this->checkout = $checkout;
        $this->checkout->setReturnUrl(url('checkout/callback'));
    }

        public function checkoutWithInvoice()
    {
        $items = array();
        //建立訂單&明細
        $items_cart = \Cart::session(1)->getContent();
        $order = Order::create([
            'owner_id' => 1
        ]);
        foreach ($items_cart as $item_cart) {
            $item = Item::find($item_cart->id);
            OrderItem::create(['order_id' => $order->id, 'item_id' => $item_cart->id, 'qty' => $item_cart->quantity]);
            $items[] = [
                'name' => $item->title,
                'qty' => $item_cart->quantity,
                'unit' => '個',
                'price' => $item->price
            ];
        }

        //串接金流做付款
        //串接綠界金流做付款
        $formData = [
            'ItemDescription' => $order->itemsName, //商品描述,可自己修改
                        'MerchantTradeNo' => 'Goblin' . $order->id, //特店訂單編號
            'Items' => $items,
            'PaymentMethod' => 'Credit',// ALL, Credit, ATM, WebATM
            'UserId' => 1, // 用戶ID , 非必須
            'CustomField1' => $order->id //自定義欄位1
        ];

        //串接電子發票
        $user = User::find(1);
        $invData = [
            'Items' => $items,
            'UserId' => $user->id,
            'CustomerName' => $user->name,
            'CustomerAddr' => '',
            'CustomerEmail' => $user->email, //用戶Email
            'CustomerPhone' => '', //用戶電話
            'CarruerType' => 1,
            'CarruerNum' => ''
        ];
        return $this->checkout->setPostData($formData)->withInvoice($invData)->send();
    }
    //綠界付完款轉址路由方法
    public function checkoutCallback(Request $request)
    {
        $response = $request->all();
        $order = Order::find($response['CustomField1']);
        if ($response['RtnCode'] == 1) {
            if ($response['PaymentType'] == 'Credit_CreditCard') {
                $order->pay_type = 'credit';
            }
            $order->trade_no = $response['TradeNo']; //綠界訂單編號
                        $order->invoiceNumber = $response['InvoiceNumber'];
            $order->pay_at = Carbon::now();
            $order->status = 'paid';
            $order->save();
            Log::info('訂單編號' . $order->id . '付款成功');
        } else {
            Log::error('訂單編號' . $order->id . '付款失敗');
        }
        return redirect('/'); //返回首頁
    }
}

綠界電子發票串接可接受參數列表

功能測試

以上改動完畢之後,就可以試看看功能能否正常執行

內部確認

可以開啟 log 檔看看是否有出現付款成功的訊息,路徑為 storage/logs/laravel.log

綠界電子發票串接攻略

外部確認

可以進到綠界的測試環境後台,切換到電子發票加值中心,看看所送出的訂單是否已經產生電子發票了,網址為

綠界電子發票串接攻略

綠界電子發票串接攻略


分享這篇文章:

關聯文章:

訂閱電子報,索取 Laravel 學習手冊

價值超過 3000 元,包含常用 Laravel 語法與指令!

一小時免費求職講座

3個應徵軟體工程師前該知道的秘訣

取得免費課程連結

Laravel 百萬年薪特訓營

從最基礎的 PHP 語法開始,包含所有你該知道的網頁基礎知識,連同 Laravel 從零開始一直到實戰,最後還將告訴你如何找好工作,讓你及早擁有百萬年薪