2023 使用 PHP SDK 搭配 ngrok 串接藍新金流 API

Yu Lin Chou
24 min readFeb 2, 2023

--

說明

本說明為詳細講解如何使用此範例,以及在本地測試的方法。

使用的範例程式碼:https://github.com/xup6m6fu04/newebpay-example.git

使用的 SDK 為 : https://github.com/xup6m6fu04/newebpay-sdk-php

示意圖都以 Mac 畫面為主
但其實 Windows 只要做好對應設定即可。

閱讀前提:至少有一點 PHP 的基礎知識,入門幾個月那種就行。
請操作過程中務必搭配官方文件使用,有錯誤一律以官方文件為準!

事前準備

註冊藍新測試用(網址為 cwww 開頭)企業帳號
https://cwww.newebpay.com/website/Page/content/register

註冊成功後登入企業會員,選擇上方的選單的『會員中心』->『商店管理』
會看到一間商店,記住『商店代號』!

記住 M 開頭的商店代號

點擊中間的『詳細資料』前往詳細設定頁
進入後,右側會看到支付方式,看到『信用卡一次付清』的部分請『開啟』

開啟信用卡一次付清

並往下拉看到『API串接金鑰』,將 HashKey、HashIV 記下來。

不要偷抄我的,我已經更換過了。

完成上述步驟後會取得
- 商店代號
- Hash Key
- Hash IV

並確認已經開啟信用卡一次付清功能。

建立本地環境

1. 安裝 PHP 至少 7.2.5 以上版本,可以在終端機上輸入指令已確認版本

php -v

2. 下載本地開發工具,說明以 MAMP PRO 為範例
MAMP 或 MAMP PRO 下載地址:https://www.mamp.info/en/downloads/

範例專案建置

1. 下載專案

git clone https://github.com/xup6m6fu04/newebpay-example.git

2. 切換至專案目錄下

cd newebpay-example.git

3. 安裝

composer install

備註:沒安裝 composer 的請到官方網站下載
https://getcomposer.org/download/

4. 路徑指定

打開 MAMP 或 MAMP PRO 將 Document Root 指定至 newebpay-example

5. Port 確認

將 Port 調整為一般設定,維持也可以,這裡為了後續說明 ngrok 時順利,請初學者一步一步照著做。

確認 Apache 是 80 即可

6. 啟動測試

啟動 Server ,確保 Apache 已經打開,並打開瀏覽器在網址輸入 localhost,確認畫面是否如下所示

這是我們測試的地方

專案結構說明

以下只列出重要檔案進行說明,其餘只列出但不討論

newebpay-example
│ index.html // 表單主要入口
│ .env // 設定檔位置
│ composer.json
│ README.md

└───src
│ │ payment.php // 送出 MPG 交易範例
│ │ notify.php // 接收回調 (callback)
│ │ return.php // 交易完成後轉跳頁面
│ │
│ └───Config
│ │ │ Config.php // 讀取設定檔
│ │ │
│ └───CreditCard
│ │ │ cancelAuthorization.php // 取消授權範例
│ │ │ cancelChargeback.php // 取消請款範例
│ │ │ cancelRefund.php // 取消退款範例
│ │ │ chargeback.php // 請款範例
│ │ │ refund.php // 退款範例
│ │ │
│ └───Log
│ │ │ api.log // 儲存回調 (callback)
│ │ │
│ └───Query
│ │ │ query.php // 查詢交易範例
│ │ │
└───vendor

寫入設定檔

第一步最重要,請先打開 .env 並將前面取得的資訊貼上,務必要打上自己的資訊,否則呼叫 API 並不會成功。

PS. DEBUG = true 表示使用的是測試環境,false 則代表正式環境

記得要改喔,這組只是隨機產生的,並沒有辦法呼叫 API

程式碼說明

首先我們的入口是 index.html,這裡面用 bootstrap 簡單切了一個版,裡面有多個表單,分別送 POST 請求到不同的地方。

首先以送出交易為例,可以看到部分程式碼為

<h2 class="mt-3 mb-3">送出 MPG 交易</h2>
<small style="color: red">MPG (Multiple Payment Gateway) 是藍新金流提供的 RWD 頁面 <br> 使用於線上交易的幕前情境供消費者進行付款</small>
<form action="/src/payment.php" method="post">
<div class="mb-3 mt-3">
<label class="form-label">訂單編號 (無填寫即隨機)</label>
<input type="text" class="form-control" name="MerchantOrderNo" placeholder="訂單編號">
</div>
<div class="mb-3">
<label class="form-label">訂單金額 (無填寫即隨機)</label>
<input type="text" class="form-control" name="Amt" placeholder="訂單金額">
</div>
<div class="mb-3">
<label class="form-label">商品名稱 (無填寫即隨機)</label>
<input type="text" class="form-control" name="ItemDesc" placeholder="商品名稱">
</div>
<div class="mb-3">
<label class="form-label">付款人電子信箱</label>
<input type="text" class="form-control" name="Email" placeholder="付款人電子信箱" value="sarah82529@gmail.com" required>
</div>
<input type="submit" class="btn btn-primary" value="送出">
</form>

可以找到 form 的 action 為 /src/payment.php,於是我們繼續看下去。

打開 payment.php。

其中關於 autoload 以及 namespace 的概念在此不贅述,如不懂的小夥伴也可以用 require 或是 include 進行程式碼引入。

我們從取得 $config 開始

$config = Config::get();

注意看,這裡 $config 會是一個陣列,並且讀取的地方就是 /src/Config/Config.php 裡面回傳的陣列。

打開 Config.php 會長這樣

<?php
namespace Src\Config;
use Dotenv\Dotenv;

class Config
{
public static function get(): array
{
$dotenv = Dotenv::createImmutable(__DIR__, '../../.env');
$dotenv->load();

return [
/*
* 開啟藍新金流測試模式 (bool)
*/
'Debug' => $_ENV['DEBUG'],

/*
* 藍新金流商店代號
*/

'MerchantID' => $_ENV['MERCHANT_ID'],
'HashKey' => $_ENV['HASH_KEY'],
'HashIV' => $_ENV['HASH_IV'],

/*
* 回傳格式 JSON/String
*/

'RespondType' => 'JSON',

/*
* 串接版本
*/

'Version' => '2.0',

.... 以下省略

這裡可以看到我把幾個參數設定成 .env ,這裡可以根據自己的需求進行設定。全部都要設定到 .env 也可以,或是沒設定的話給個預設值也可以,看自己的需求,我這裡只是給個範例供參考。

另外小夥伴可以在自己的專案用自己的方法載入設定檔案,我這份專案把 .env 傳上來只是為了給小夥伴們參考,正式專案請不要將機密資訊上傳到 git 或任何可能外洩的地方喲。

我們繼續看 payment.php

$newebpay = new NewebPay($config);
// 設定訂單內容
$newebpay = $newebpay->payment(
$_POST['MerchantOrderNo'] ?: generateRandomString(), // 訂單編號
$_POST['Amt'] ?: random_int(10, 1000), // 訂單金額
$_POST['ItemDesc'] ?: '測試商品 - ' . generateRandomString(6), // 商品名稱
$_POST['Email'] ?: 'sarah82529@gmail.com' // 付款人電子信箱
);
// 要更改設定用 ->set + 屬性名稱 (ex: setReturnURL)
$newebpay->setReturnURL('https://1ca9-1-162-18-21.jp.ngrok.io/src/return.php');
$newebpay->setNotifyURL('https://1ca9-1-162-18-21.jp.ngrok.io/src/notify.php');
$newebpay->setTokenTerm($_POST['Email']);
// 送出表單
echo $newebpay->submit();

首先我們先實例化一個 NewebPay 以便後續使用各個方法

$newebpay = new NewebPay($config);

為了使用 MPG 付款,我們需要呼叫一個名為 payment 的方法,並帶入四個參數,這四個參數在 index.html 中可以看到。程式碼中為了方便測試,我預計不帶入的時候可以自動隨機產生。

$newebpay = $newebpay->payment(
$_POST['MerchantOrderNo'] ?: generateRandomString(), // 訂單編號
$_POST['Amt'] ?: random_int(10, 1000), // 訂單金額
$_POST['ItemDesc'] ?: '測試商品 - ' . generateRandomString(6), // 商品名稱
$_POST['Email'] ?: 'sarah82529@gmail.com' // 付款人電子信箱
);

雖然我們一開始有帶入了 $config ,但難保有時候需要客製化參數呼叫,這時候我們就可以用 ->set 開頭 + 想要改的屬性名稱去改變內容

// 要更改設定用 ->set + 屬性名稱 (ex: setReturnURL)
$newebpay->setReturnURL('https://1ca9-1-162-18-21.jp.ngrok.io/src/return.php');
$newebpay->setNotifyURL('https://1ca9-1-162-18-21.jp.ngrok.io/src/notify.php');
$newebpay->setTokenTerm($_POST['Email']);

至於有哪些參數需要傳遞以及可以修改可以參考

1. 官方文件:https://www.newebpay.com/website/Page/content/download_api

2. SDK 原始碼:https://github.com/xup6m6fu04/newebpay-sdk-php

最後我們將表單產出並送出

// 送出表單
echo $newebpay->submit();

其中 $newebpay->submit(); 之後會回傳一段字串,字串內容大概會如下

<form id="order-form" method="post" action=https://ccore.newebpay.com/MPG/mpg_gateway ><input type="hidden" name="MerchantID" value="TestMerchantID1234"><input type="hidden" name="TradeInfo" value="e88e33cc07d106bcba1c1bd02d5d421fa9f86ef5a1469c0e801b3813b360f8333fd9fef8bf7312a3e5e66e1f6b5601b633b2b337c5dc2f6001d3f14dcb80df6cfc4ffe7a624838789bc47fcdd438db49a5f3e2b48d1740160d307a1bf6f27190b8825723f59d0cdf4071229db0a7bb6b2ef12ce7be24b0467db60a4185908770e1b5238444fb00fa24bb7693f9fb8d8c38577702e5ef0cab44b8d25e86f43e4599ca40b486efe32aae055626ca86d322055b161886fd13884252afbf7604ba739af778f00bdff9166f51143e5c5bd7326129fa1289fac0d1d66d0d41b9937058a69f5bb0f312ad4f1045aa8b74f354f5f8b260fed32f386bcec3e973f9c631fee1a8c0479fc45054c91e7eeaecbc692ae67561e71f31bb61964a5d51a7b6cb987d5bff4e838b2dfe02d1c2d83c2c0c34027ade4dc4dbbfe1644dcfc79d99944c5cff4e0cd95992114542a59c3240f4b4df9bc90ba2d4fc1c9a42f9f9e1093e8ef0ead9b02d89679d35e0609a8fc1745e0094cbc6fe07664d5393205e98b537b6b262e1409173740f132d1c1be5f57e404679c38768417b6db2b5df985d7c8629034f9dce7b01b70d0e90f0b7c4a6b24c744118db37e4fd5a8970125e6d2088a437446fa655246220266e1b73a27bcd7a18547d459460277f66accb18caf10302"><input type="hidden" name="TradeSha" value="F2C84870AE3964EE6E7110020307B27FD3B713A32F87C31E01A7E28441BEBED3"><input type="hidden" name="Version" value="1.5"></form>
<script type="text/javascript">document.getElementById(\'order-form\').submit();</script>

當我們把這個字段 echo 在頁面上的結果就是產出一段 form 並且用 javascript 進行送出。就會帶著參數將頁面轉跳到藍新的付款頁面。

Ngrok

看了這麼多,該實際測試看看了。
但為了接收藍新的回調,我們必須使用到 ngrok 這個服務。

由於我們 localhost 只有自己的電腦可以訪問,其餘人是無法傳資料給我們,解決方案除了自己架設一台線上主機之外,也可以使用 ngrok 這個服務

首先前往官網註冊:https://ngrok.com/

註冊完畢後請根據自己的平台走安裝流程:https://dashboard.ngrok.com/get-started/setup

最後在終端機上輸入

ngrok http 80

如果出現以下畫面代表成功了

這時候前往 ngrok 派給我們的網址
https://495e-1-162-18-21.jp.ngrok.io ,應該要顯示跟 localhost ㄧ樣的畫面
第一次進入會先出現一個警告頁,直接點擊 Visit Site 按鈕即可

看看網址是 ngrok 的

如果一直進不去畫面可以嘗試

ngrok http --host-header=rewrite 80

如果都進不去則需要根據平台或使用的工具進行除錯。

實際測試操作

我們回到 payment.php 將其中的

$newebpay->setReturnURL('https://1ca9-1-162-18-21.jp.ngrok.io/src/return.php');
$newebpay->setNotifyURL('https://1ca9-1-162-18-21.jp.ngrok.io/src/notify.php');

這兩行前面的網址修改為我們剛剛得到的
https://495e-1-162-18-21.jp.ngrok.io

$newebpay->setReturnURL('https://495e-1-162-18-21.jp.ngrok.io/src/return.php');
$newebpay->setNotifyURL('https://495e-1-162-18-21.jp.ngrok.io/src/notify.php');

當然也可以移除這兩行,直接將這段網址寫到 .env 裏面,或是直接到藍新後台進行預設的設定,只要 API 沒有設定,藍新會以後台設定的為準。

修改完畢後我們回到瀏覽器並輸入 localhost。
注意!不可以在 ngrok 的環境下對藍新送出表單,會被阻擋。

回到 localhost 喲!

首先我們要測試的是 『送出 MPG 交易』,這就是對應到剛剛的 payment.php,我們先把付款人電子信箱改掉!才能正確地收到信喲

其他我們讓他隨機產生,點選『送出』後,如無問題會來到藍新的付款頁面

藍新測試卡號為 4000–2211–1111–1111,官方文件也有說明
有效年月以及背面末三碼都可以自由輸入。

順帶一提,記住結帳資訊的勾,會出現的原因是因為我們有傳遞 TokenTerm

$newebpay->setTokenTerm($_POST['Email']);

如果沒有傳遞就不會出現紀錄卡號的勾勾。
詳細請參考官方文件說明。

輸入完資訊後我們送出交易,如果順利就會轉跳回
https://495e-1-162-18-21.jp.ngrok.io/src/return.php
也就是我們剛剛設定的 ReturnURL 的地址。

成功啦!

接著我們去藍新後台的交易查詢即可查到這筆交易。

沒意外的話過沒多久

/src/Log/api.log 也會有紀錄出現

[2023-02-02T09:22:10.413697+00:00] logger.DEBUG: callback:  {"Status":"SUCCESS","MerchantID":"MS347687905","Version":"2.0","TradeInfo":"c45fef7615e6b12d4370bcfb03cbf739a5d2fe2f9294048331474f9aaf4b5782d3b9f89c457ab0f0f87cccfd7924051be6b891650b248c93446bc1061c5b1da6366e76a9403869ef0352f73cb551406a4cbf490b6f64126e70dfbb1274c9a0b94a0d9aab0058a62b0f5ea7e21acaeb701d8bc93e8d630143ef4555c2114fb9d524136b151755e7cf13409d035b1aa9414df53d6b1cc4274d2c85c18ee04b039234b6a68f54cdacb90314ed722f7a67b2de174a5a2f714c85f9a213f37bfcc901cf11c0b5d2a954c5c3558af7aad27ac65d97d4f63601f2a604f965a96c56592c4289e2d850c6b2cb1a9e4212bc91451c2d368acac4026c996ea49c4eafccd9cf02526d36a22bfc8b11c38d94f7e729725b08f98ab75067547bf4dc185fde7bbb56d8b90546fabfd14db425975e2e945295cb2407b69cc4a3ef9ddcd2f111e0b791546fa6430c778865dcf593f8f790de07ec01ca8d6d54ce522f70d64c172d3276c624576e57db9e019f25e3448264f21d84cadb91608014c83ddfe9b6e63f90a2857e6f0a886c264b0b9cee521c5e4e3444f976d09c5eb505f7a09a0796deb3525ec61bcdaedc6724918ed805ea43588da3050a002d14ef3c993cd95d7b5565dc988290a3d7b9d83c7362902a776afd32af354af3d6f187dbe9028b1b238bb3","TradeSha":"B920482F4012AD1D70B3574718260E59D57772F419B5642B5C6F532F23B8247E"} []
[2023-02-02T09:22:10.415466+00:00] logger.DEBUG: Status=SUCCESS&MerchantID=MS347687905&Version=2.0&TradeInfo=c45fef7615e6b12d4370bcfb03cbf739a5d2fe2f9294048331474f9aaf4b5782d3b9f89c457ab0f0f87cccfd7924051be6b891650b248c93446bc1061c5b1da6366e76a9403869ef0352f73cb551406a4cbf490b6f64126e70dfbb1274c9a0b94a0d9aab0058a62b0f5ea7e21acaeb701d8bc93e8d630143ef4555c2114fb9d524136b151755e7cf13409d035b1aa9414df53d6b1cc4274d2c85c18ee04b039234b6a68f54cdacb90314ed722f7a67b2de174a5a2f714c85f9a213f37bfcc901cf11c0b5d2a954c5c3558af7aad27ac65d97d4f63601f2a604f965a96c56592c4289e2d850c6b2cb1a9e4212bc91451c2d368acac4026c996ea49c4eafccd9cf02526d36a22bfc8b11c38d94f7e729725b08f98ab75067547bf4dc185fde7bbb56d8b90546fabfd14db425975e2e945295cb2407b69cc4a3ef9ddcd2f111e0b791546fa6430c778865dcf593f8f790de07ec01ca8d6d54ce522f70d64c172d3276c624576e57db9e019f25e3448264f21d84cadb91608014c83ddfe9b6e63f90a2857e6f0a886c264b0b9cee521c5e4e3444f976d09c5eb505f7a09a0796deb3525ec61bcdaedc6724918ed805ea43588da3050a002d14ef3c993cd95d7b5565dc988290a3d7b9d83c7362902a776afd32af354af3d6f187dbe9028b1b238bb3&TradeSha=B920482F4012AD1D70B3574718260E59D57772F419B5642B5C6F532F23B8247E [] []

這就是藍新呼叫我的當初設定的 NotifyURL (也就是 /src/notify.php),並將結帳結果再傳一次給我們確認。

交易查詢

我們回到 localhost,在交易查詢的地方輸入剛剛交易的訂單編號及金額,如果沒記下來也可以到藍新後台查詢。

如果查詢成功就會出現

以上查詢的程式碼都在 /src/Query/query.php

$config = Config::get();

$newebpay = new NewebPay($config);
$result = $newebpay->query($_POST['MerchantOrderNo'], $_POST['Amt'])->submit();

echo json_encode($result, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);

也是先讀取設定檔,然後實例化一個 NewebPay後使用其中的 query 方法,並傳入訂單編號以及金額,最後將藍新回傳的 json 結果印出來。就這麼簡單。

其他方法

至於信用卡的取消授權、請款以及退款等等,跟查詢也都是一樣的邏輯概念,只是分別對應呼叫了不同的方法,可以自己研究。

例如請款只是將 query 方法改成 creditCardChargeback 方法,帶入的參數都是一樣的。

結語

後續如果藍新有更新 API 我也會儘速把 SDK 進行更新,如果我遺漏了也請寄信或留言告訴我。如果有任何問題也歡迎留言討論。

再次附上相關連結

PHP SDK : https://github.com/xup6m6fu04/newebpay-sdk-php
範例程式碼 : https://github.com/xup6m6fu04/newebpay-example

謝謝。

--

--