Skip to content

Instantly share code, notes, and snippets.

@yidas
Last active February 27, 2024 09:08
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save yidas/08c0f7009a72102df3b57fcbe3da6681 to your computer and use it in GitHub Desktop.
Save yidas/08c0f7009a72102df3b57fcbe3da6681 to your computer and use it in GitHub Desktop.
LINE Pay API (v3) sample codes in multi-languages

LINE Pay API (v3) sample codes in multi-languages

PHP (v5, v7)

HMAC:

<?php

function getAuthSignature($channelSecret, $uri, $queryOrBody, $nonce)
{
    $authMacText = $channelSecret . $uri . $queryOrBody . $nonce;
    return base64_encode(hash_hmac('sha256', $authMacText, $channelSecret, true));
}

$channelSecret = 'a917ab6a2367b536f8e5a6e2977e06f4';
$requestUri = '/v3/payments/request';
$body = json_encode([
    'amount' => 250,
    'currency' => 'TWD',
    'orderId' => 'Your order ID',
    'packages' => [
        [
            'id' => 'Your package ID',
            'amount' => 250,
            'name' => 'Your package name',
            'products' => [
                [
                    'name' => 'Your product name',
                    'quantity' => 1,
                    'price' => 250,
                    'imageUrl' => 'https://yourname.com/assets/img/product.png',
                ],
            ],
        ],
    ],
    'redirectUrls' => [
        'confirmUrl' => 'https://yourname.com/line-pay/confirm',
        'cancelUrl' => 'https://yourname.com/line-pay/cancel',
    ],
]);
$authNonce = date('c') . uniqid('-'); // ISO 8601 date + UUID 1

$signature = getAuthSignature($channelSecret, $requestUri, $body, $authNonce);

Request API:

<?php

use GuzzleHttp\Client;

$client = new Client([
    'base_uri' => 'https://sandbox-api-pay.line.me',
    'headers' => [
        'Content-Type' => 'application/json',
        'X-LINE-ChannelId' => '{your channelId}',
        'X-LINE-Authorization-Nonce' => '44453d45-768e-40e8-8349-748e797c450f',
        'X-LINE-Authorization' => '{Hmac signature}',
        'X-LINE-MerchantDeviceProfileId' => '{your device profile id}',
    ],
]);

$response = $client->request('POST', '/v3/payments/request', [
    'body' => '{Body string}',
]);

C#

HMAC:

static string GetAuthSignature(string secretKey, string uri, string queryOrBody, string nonce) 
{
    Encoding ascii = Encoding.ASCII;
    HMACSHA256 hmac = new HMACSHA256(ascii.GetBytes(secretKey));
    string authMacText = secretKey + uri + queryOrBody + nonce;
    return Convert.ToBase64String(hmac.ComputeHash(ascii.GetBytes(authMacText)));
}

Class namespaces: System.Text, System.Security.Cryptography

Request API:

public static void Main()
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri("https://sandbox-api-pay.line.me");
        client.DefaultRequestHeaders.Add("X-LINE-ChannelId", "{Your ChannelId}");
        client.DefaultRequestHeaders.Add("X-LINE-Authorization-Nonce", "{Your Nonce}");
        client.DefaultRequestHeaders.Add("X-LINE-Authorization", "{Hmac Signature}");

        var content = new StringContent("{json body}", Encoding.UTF8, "application/json");
        var response = client.PostAsync("/v3/payments/request", content).Result;
        // ...
    }
}

Python (v2, v3)

HMAC:

import hashlib
import hmac
import base64

def getAuthSignature(secret, uri, queryOrBody, nonce):
    authMacText = secret + uri + queryOrBody + nonce
    return base64.b64encode(hmac.new(str.encode(secret), str.encode(authMacText), digestmod=hashlib.sha256).digest()).decode("utf-8")

Request API:

import time
import json
import requests

channelId = "{channelId}"
channelSecret = "{channelSecret}"
uri = "/v3/payments/request"
nonce = str(round(time.time() * 1000))  # nonce = str(uuid.uuid4())
jsonBody = json.dumps({"orderId": "..."})  

headers = {   
    'Content-Type': 'application/json',        
    'X-LINE-ChannelId': channelId,
    'X-LINE-Authorization-Nonce': nonce,
    'X-LINE-Authorization': getAuthSignature(channelSecret, uri, jsonBody, nonce) 
    }  

response = requests.post("https://sandbox-api-pay.line.me"+uri, headers=headers,data=jsonBody)
print(response.json())

Ruby (v2)

HMAC:

require 'securerandom'
require "base64"

def getAuthSignature(secrect, uri, queryOrBody, nonce)
    authMacText = secrect + uri + queryOrBody + nonce
    return Base64.urlsafe_encode64(OpenSSL::HMAC.hexdigest("SHA256", secrect, authMacText))
end

Golang

HMAC:

func getAuthSignature(secret string, uri string, queryOrBody string, nonce string) string {
	hash := hmac.New(sha256.New, []byte(secret))
	hash.Write([]byte(secret + uri + queryOrBody + nonce))
	return base64.StdEncoding.EncodeToString(hash.Sum(nil))
}

import (crypto/hmac, crypto/sha256, encoding/base64)

Request API:

func main() {

	channelId, channelSecret, baseUri, uri := "{ChannelId", "{ChannelSecret}", "https://sandbox-api-pay.line.me", "/v3/payments/request"
	var nonce = strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10) // Unix time in milliseconds
	var jsonBody = `{"amount":100, ...}`                                            // API body in JSON string

	client := &http.Client{}
	req, err := http.NewRequest("POST", baseUri+uri, bytes.NewBuffer([]byte(jsonBody)))
	if err != nil {
		// Error handling
	}
	req.Header.Set("Content-Type", "application/json; charset=UTF-8")
	req.Header.Set("X-LINE-ChannelId", channelId)
	req.Header.Set("X-LINE-Authorization-Nonce", nonce)
	req.Header.Set("X-LINE-Authorization", getAuthSignature(channelSecret, uri, string(jsonBody), nonce))
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	
	body, err := ioutil.ReadAll(resp.Body)
	fmt.Println("response Body:", string(body))
}

import (bytes, io/ioutil, net/http, strconv, time)

Java

HMAC:

public static String getAuthSignature(final String channelSecret, final String requestUri, final String queryOrBody, final String nonce) {
    String data = channelSecret + requestUri + queryOrBody + nonce;
    byte[] bytes = HmacUtils.getInitializedMac(HmacAlgorithms.HMAC_SHA_256, channelSecret.getBytes()).doFinal(data.getBytes());
    return new String(Base64.encodeBase64(bytes));
}

Package: Apache Commons Codec

import org.apache.commons.codec.binary.Base64, org.apache.commons.codec.digest.HmacAlgorithms, org.apache.commons.codec.digest.HmacUtils

Request API:

public static void main(String[] args) {
    String body = "{\"bar\": \"foo\"}";
    String ChannelSecret = "a917ab6a2367b536f8e5a6e2977e06f4";
    String requestUri = "/v3/payments/request";
    String nonce = UUID.randomUUID().toString();
    String signature = getAuthSignature(ChannelSecret, ChannelSecret + requestUri + body + nonce);
    
    // TBC
}

NodeJS

HMAC:

function getAuthSignature(channelSecret, uri, queryOrBody, nonce) {
    var HmacSHA256 = require("crypto-js/hmac-sha256");
    var Base64 = require("crypto-js/enc-base64");
    var authMacText = channelSecret + uri + queryOrBody + nonce;
    return Base64.stringify(HmacSHA256(authMacText,channelSecret));
}

Require crypto-js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment