Linepay
寫在前面
這次的筆記是關於Linepay的串接,有區分線上及線下的api,我們是在購物網站上使用,所以會是對線上的部分做紀錄。
串接之前,要先去申請一組sandbox 的帳號,作為測試串接使用,申請通過後會得到一組測試的帳號密碼,裡面可以找到要串接api 需要有的channel_id
、channel_secret_key
。
先將申請連結及文件連結放上來:
以下正文:
付款流程
首先先了解到,使用Linepay的整個流程:
消費者在結帳頁面填妥資料並選擇Linepay後進行結帳
↓
呼叫Request Api
↓
跳轉LinePay 付款頁面
↓
使用者選擇付款方式(一卡通、Line Points、信用卡)
↓
callback (ConfirmURL)
↓
呼叫 Confirm Api確認付款結果
↓
跳轉至付款完成頁
付款
接著我們會準備好付款及確認的程式碼,我是將付款及呼叫api 的程式提出來寫成一個class,
而確認的api 因為就直接寫在linepay 的異步通知裡面,共用同一個呼叫api 的方法。
- 付款 class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86//>
namespace your_namespace;
class Linepay {
public static function applyPayment($order, $member) {
// [
// 'url' => 'https://sandbox-api-pay.line.me',
// 'currency' => 'TWD',
// 'channel-id' => '你的channel-id',
// 'channel-secret' => '你的channel-secret-key',
// 'product-name' => '產品名稱',
// ]
$linepay = "config 取出 linepay 設定檔";
$amount = "總應付金額";
$param = [
'amount' => $amount,
'currency' => $linepay['currency'],
'orderId' => "{$order['order_no']}v{$order['payment_ver']}", // 帶版本號的訂單號碼
'packages' => [[
'id' => "{$order['id']}",
'amount' => $amount,
'products' => [[
'name' => $linepay['product-name'], //
'quantity' => 1,
'price' => $amount,
]],
]],
'redirectUrls' => [
'confirmUrl' => 'your-callback-url',
'cancelUrl' => 'your-cancel-url',
],
];
$response = self::request('/v3/payments/request', $linepay, $param);
if ($response) {
if ($response['returnCode'] === '0000') {
$order['cashier'] = $response['info']['paymentUrl']['web']; // 網頁付款網址
$order['cashier_type'] = 'redirect'; // 告訴前台是要跳轉
$order['payment_request'] = json_encode($param, JSON_UNESCAPED_UNICODE); //將付款request 記錄下來
$order['payment_response'] = json_encode($response, JSON_UNESCAPED_UNICODE); //將付款response記錄下來
return $order;
} else {
return false;
}
}
return null;
}
public static function request($api, $linepay, $param) {
$nonce = round(microtime(true) * 1000); //唯一值,也可以產生UUID
$data = json_encode($param, JSON_UNESCAPED_UNICODE);
$authorization = base64_encode(hash_hmac('sha256', "{$linepay['channel-secret']}{$api}{$data}{$nonce}", $linepay['channel-secret'], true));// 官方文件上有註明簽章方式
$headers = [
'Content-Type: application/json',
"X-LINE-ChannelId: {$linepay['channel-id']}",
"X-LINE-Authorization-Nonce: {$nonce}",
"X-LINE-Authorization: {$authorization}",
];
$request = [
'http' => [
'method' => 'POST',
'header' => implode("\r\n", $headers),
'content' => $data,
],
];
$response = @file_get_contents("{$linepay['url']}{$api}", false, stream_context_create($request)); // 呼叫api
return json_decode($response, true);
}
}
準備好class 後就可以來使用了
execute (前台呼叫成立訂單&執行付款)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17//>
// ... 略過建立訂單流程
// 如果訂單金額 > 0 呼叫Linepay 付款
$order = call_user_func(['your_namespace\Linepay', 'applyPayment'], $order, $member);
if ($order === false) {
return ['error' => '連線失敗'];
} else if ($order === null) {
return ['error' => '串接失敗'];
}
$order = '資料庫更新訂單';
return [
'success' => true,
'order' => $order, // 根據order的內容,前台會知道要跳轉至Linepay 付款網址
];callback (ConfirmUrl)
Linepay 在消費者完成付款之後,會根據ConfirmUrl 帶上orderId,通知站方該筆訂單的付款狀態已變更,
我們收到這個通知的時候,要去確認此筆訂單付款狀態為何,並更新資料庫中的訂單資訊。
1 | //> |
sandbox 沒有看到取消付款的功能,所以暫時先不準備取消付款的作業,
原則上只要沒有付款成功,該筆訂單的付款狀態就會維持未付款,
消費者可以在訂單查詢頁面再次付款,如果有特別設定經過多久會變成取消訂單,才會無法付款。
以上是簡單的linepay 付款串接,後續可以根據使用情境不同,再另外串接作廢、退款等等的api。