綠界電子發票串接攻略

這篇文章說明該如何利用套件來快速進行電子發票串接
實作方式很單純,與金流串接流程相同,但在發送參數時追加電子發票參數,就能夠讓綠界幫我們上傳電子發票到大平台
綠界科技提供合作特店透過介接方式整合電子發票作業功能,且支援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
外部確認
可以進到綠界的測試環境後台,切換到電子發票加值中心,看看所送出的訂單是否已經產生電子發票了,網址為