iT邦幫忙

2021 iThome 鐵人賽

DAY 9
0
永豐金融APIs

試著讀懂與串接永豐金融APIs系列 第 9

Day 0x9 - 插播 - 建立 Sinopac Controller

0x1 前言

  • 是的,要繼續寫 Webhook 時卻發現,Day 0x4 ~ 0x6 寫的函數的都沒有先包裝好,要呼叫 API 時得再寫一次,所以今天先把要傳得先包好。
  • 嚴格來說應該是要建立 Service,但這個分界點一直有點混亂,因此這裡依照自己腦海的想法來走,歡迎各位給我建議。

0x2 API Controller 建立

$ php artisan make:controller Sinopac

然後把函數建立好,如下

// app/Http/Controllers/Sinopac.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class Sinopac extends Controller
{
    private $shop_no;
    private $key_a1;
    private $key_a2;
    private $key_b1;
    private $key_b2;

    public function __construct(string $shop_no, string $key_a1, string $key_a2, string $key_b1, string $key_b2)
    {
        $this->shop_no = $shop_no;
        $this->key_a1 = $key_a1;
        $this->key_a2 = $key_a2;
        $this->key_b1 = $key_b1;
        $this->key_b2 = $key_b2;
    }

    public function callApi($url, $post_data)
    {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_HEADER => 0,
            CURLOPT_NOBODY => 1,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_HTTPHEADER => ["Content-type: application/json; charset=utf-8"],
            CURLOPT_POST => 1,
            CURLOPT_POSTFIELDS => json_encode($post_data),
            CURLOPT_SSL_VERIFYPEER => 0,
            CURLOPT_SSL_VERIFYHOST => 0,
            CURLOPT_SSLVERSION => 6
        ]);
        $result = curl_exec($ch);
        curl_close($ch);

        return json_decode($result, true);
    }

    public function getNonce()
    {
        $url = 'https://sandbox.sinopac.com/QPay.WebAPI/api/Nonce';
        return $this->callApi($url, ['ShopNo' => $this->shop_no]);
    }

    public function calculateIv($nonce): string
    {
        $hash = hash('SHA256', $nonce);
        return strtoupper(substr($hash, 48));
    }

    private function calcHashId(): string
    {
        $a = $b = '';
        $length = strlen($this->key_a1);
        for ($i = 0; $i < $length; $i += 4) {
            $a .= dechex(hexdec(substr($this->key_a1, $i, 4)) ^ hexdec(substr($this->key_a2, $i, 4)));
            $b .= dechex(hexdec(substr($this->key_b1, $i, 4)) ^ hexdec(substr($this->key_b2, $i, 4)));
        }
        return strtoupper($a . $b);
    }

    public function generateSign($data, $nonce, $hash_id): string
    {
        $keys = array_keys($data);
        foreach ($keys as $key) {
            $value = array_shift($data);
            if (gettype($value) === 'array' || trim($value) === '') {
                continue;
            }

            $upper_key = strtoupper($key);
            $data[$upper_key] = "$key=$value";
        }

        ksort($data);
        $body = implode('&', $data) . $nonce . $hash_id;
        return strtoupper(hash('sha256', $body));
    }

    public function encryptMessage($data, $key, $iv): string
    {
        $data = json_encode(array_filter((array)($data)));

        $padding = 16 - (strlen($data) % 16);
        $data .= str_repeat(chr($padding), $padding);
        $encrypt = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);

        return strtoupper(bin2hex($encrypt));
    }

    public function decryptMessage($data, $key, $iv)
    {
        $encrypt = hex2bin($data);
        $decrypt = openssl_decrypt($encrypt, 'AES-256-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
        $padding = ord($decrypt[strlen($decrypt) - 1]);

        $result = substr($decrypt, 0, -$padding);
        return json_decode($result, true);
    }
}

0x3 今日小結

  • 今天花了一些時間整理程式,看能不能再把函數切得更細,雖然都是複製貼上前幾天的程式碼 ;D
  • 明天把 recevie_msg 完成

上一篇
Day 0x8 - WebHook Api 建立( part 1 )
下一篇
Day 0xA - WebHook Api 建立( part 2 )
系列文
試著讀懂與串接永豐金融APIs30

尚未有邦友留言

立即登入留言