Web

ASP.NET Core 綜合筆記

Database Code First //設定appsettings.json  "ConnectionStrings": {     "CodeFirstDbDatabase": "Server=.;Database=資料庫名稱;Trusted_Connection=True;User ID=sa;Password=密碼"   }   //建立Data > DataContext  public class DataContext:DbContext     {         public DataContext(DbContextOptions<DataContext> options):base(options)         {         }         public DbSet<Category> Categories { get; set; }         public DbSet<Product> Products { get; set; }         public DbSet<Student> Students { get; set; }      }   //Program.cs設定 builder.Services.AddDbContext<DataContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("CodeFirstDbDatabase")));   //Model建立完後 dotnet ef migrations add InitialCreate   //更新資料庫 dotnet ef database update //nuget主控台中文亂碼 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8   Database DB First Local: Scaffold-DbContext "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\jhinw\source\repos\slnAlbum\prjAlbum\App_Data\檔名.mdf;Integrated Security=True;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -context DbContext   Sql Server: Scaffold-DbContext "Data Source=主機;Initial Catalog=資料庫名稱;User ID=帳號;Password=密碼;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -context DbContext名稱  套件安裝 加入 > NuGet套件 Microsoft.entityframeworkcore.SqlServer Microsoft.entityframeworkcore.Design Microsoft.entityframeworkcore.Tools Program.cs   builder.Services.AddMvc(); //啟用MVC服務   var cnstr = $"Data Source=(LocalDB)\\MSSQLLocalDB; AttachDbFilename ={builder.Environment.ContentRootPath}App_Data\\資料檔名.mdf; Integrated Security = True; Trusted_Connection = True; "; //資料庫資訊字串,Source可從DbFirst的DbContext OnConfiguring中複製 builder.Services.AddDbContext<DbContext>(options=>options.UseSqlServer(cnstr)); //使用資料庫   builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => {    //限制cookie只能由Http/Https存取     options.Cookie.HttpOnly = true;       //未登入時自動導到登入頁     options.LoginPath = new PathString("/Home/Login");      //權限不夠拒絕訪問導到此路徑     options.AccessDeniedPath = new PathString("/Home/NoAuthorization");   }); //載入驗證 var app = builder.Build(); app.MapControllerRoute(name: "default", pattern: "{Controller=Home}/{Action=Index}/{id?}"); //預設入口   app.UseStaticFiles(); //啟用靜態資源 app.UseCookiePolicy(); //啟用Cookie app.UseAuthentication();//登入驗證 app.UseAuthorization(); //身分授權 Model模型驗證   public partial class TEmployee     {         [Display(Name="員工編號")]         [Required(ErrorMessage="員工編號必填")]         public string FEmpId { get; set; } = null!;           [Display(Name = "姓名")]         [Required(ErrorMessage = "姓名必填")]         public string? FName { get; set; }           [Display(Name = "信箱")]         [EmailAddress(ErrorMessage = "必須符合信箱格式")]         public string? FMail { get; set; }           [Display(Name = "薪資")]         [Range(25000,65000,ErrorMessage ="薪資範圍25000~65000")]         public int? FSalary { get; set; }           [Display(Name = "雇用日期")]         [Required(ErrorMessage = "雇用日期必填")]         [DataType(DataType.Date)]         public DateTime? FEmploymentDate { get; set; }           [Display(Name = "密碼")]         [Required(ErrorMessage = "密碼必填")]         public string Pwd { get; set; }           [Display(Name = "確認密碼")]         [Required(ErrorMessage = "確認密碼必填")]         [Compare("Pwd", ErrorMessage = "密碼與確認密碼需相同")]         public string RePwd { get; set; }       } 版面配置   //預設新建頁面套用Layout ~/Views/_ViewStart.cshtml @{  Layout = "_Layout";  }   //全域套用TagHelper ~/Views/_ViewImports.cshtml  @addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers   ~/Views/shared/_Layout @RenderBody() //必要 @RenderSection("Scripts",required:false) @await Html.PartialAsync("檔名") //同樣位於shared   載入Bootstrap、jquery   加入 > 用戶端程式庫 jquery、jquery-validate、jquery-validation-unobtrusive   //~/Views/shared/_Layout   <link href="~/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" />   <script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/bootstrap/js/bootstrap.bundle.min.js"></script> Controller中使用DbContext   public class HomeController : Controller {          private AlbumDbContext _context;          private string _path;  //靜態檔案路徑   public HomeController(AlbumDbContext context, IWebHostEnvironment hostEnvironment)          {              _context = context;              _path = $"{hostEnvironment.WebRootPath}\\Album";         }   } 跨域開放 var MyAllowSpecificOrigins = "http://localhost:5500";   builder.Services.AddCors(options => {     options.AddPolicy(name: MyAllowSpecificOrigins,                       build =>                       {                           build.WithOrigins("*", "*", "*")                           .AllowAnyOrigin()                           .AllowAnyHeader()                           .AllowAnyMethod();                       }); });

2022-08-08

Web

Linux中SSH設定連線與存取Github使用者

  SSH設定   參考資料 [教學] 產生SSH Key並且透過KEY進行免密碼登入 | 辛比誌 (xenby.com) 2 ways to fix bad owner or permissions on SSH config (windowsreport.com)   設定 > 應用程式 > 選用功能 >新增功能 > OpenSSH Client(用戶端)   打開PowerShell(管理員啟動) ssh-keygen 接著一路Enter 備註:passphrase可設定輸入密碼,安全性較高 接著會產生公私鑰 預設位置:C:\Users\User\.ssh 副檔名.pub為公鑰 進入Linux伺服器  cd /root/.ssh 開啟 authorized_keys  將公鑰內容貼到裡面 給予權限 chmod -R go= ~/.ssh chown -R root:root ~/.ssh 測試連線 ssh [email protected]   windows可能遇到的問題 bad owner or permissions ... 到C:\Users\User\.ssh中的config按右鍵 內容 > 安全性 > 進階 > 停用繼承 > 刪除所有繼承  並將上面所有主體刪除 接著按 新增 > 選取一個主體 > 進階 > 立即尋找 > 選取現在window登入的使用者     ==================================== Github設定 git config --global credential.helper store 接著git pull一次 會把git登入資訊紀錄在.git-credentials vim ~/.git-credentials https://Github使用者名稱:Github密碼@github.com 之後就可以不需輸入密碼

2022-07-06

Web

ASP.NET CORE 6 Code First

1. 新建Data資料夾 > DataContext.cs public class DataContext :DbContext{         public DataContext(DbContextOptions<DataContext> options) : base(options){}        public DbSet<Employee> Employees { get; set; }  } DataContext為檔名   2. 新建Model資料夾 > Employee.cs     public class Employee     {         public int EmployeeId { get; set; }         public string Name { get; set; }         public string Address { get; set; }         public string CompanyName { get; set; }         public string Designation { get; set; }     }   3. appsettings.json設定全域連線字串  "ConnectionStrings": {     "DefaultConnection": "Server=.;Database=CodeTest;Trusted_Connection=True;User ID=sa;Password=密碼"   }   4.Program.cs 設定連線 builder.Services.AddDbContext<DataContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); DefaultConnection 為第三部設定的變數 DataContext為第一步設定的Context UseSqlServer需引入using Microsoft.EntityFrameworkCore;   5.套件管理器主控台 > dotnet ef migrations add "commit字串"   6. 更新資料庫 >   dotnet ef database update        

2022-07-04

Web

Expo 建置與上架

  安裝套件 npm install -g expo-cli   啟用 Expo start   掃描Qrcode、Barcode套件推薦 expo install expo-camera expo install expo-barcode-scanner   用法與範例   引入模組 import { Camera, CameraType } from 'expo-camera'; import { BarCodeScanner } from 'expo-barcode-scanner';   相機狀態設定 const [cameraStatus,setCameraStatus] = useState(false); //相機開啟狀態 const [hasPermission, setHasPermission] = useState(null);//相機允許狀態 const [scanned, setScanned] = useState(false);//相機掃描狀態   // 準備相機 useEffect(() => {     (async () => {     const { status } = await Camera.requestCameraPermissionsAsync();     setHasPermission(status === 'granted');     })(); }, []);    // 相機掃描動作 const handleBarCodeScanned = ({ type, data }) => {     setScanned(true);     alert(`成功掃描國際碼 ${data} `);     let str = data.toString();     setEan(str);     setScanned(false);     setCameraStatus(false)      };   相機內容 flashMode為閃光燈 <Camera style={styles.camera}          flashMode={cameraStatus ? "torch" : "no"}         type={Camera.Constants.Type.back}         barCodeScannerSettings={{         barCodeTypes: [BarCodeScanner.Constants.BarCodeType.ean13],         }}         onBarCodeScanned={handleBarCodeScanned}> </Camera>     app.js解說   "expo": {     "name": “App名稱", //App名稱,可中文     "slug": “AppName”,//App英文名稱     "version": “1.0.4”,//App版號,AppStore看得到     "orientation": "portrait",     "icon": "./assets/icon.png",     "userInterfaceStyle": "light",     "splash": {       "image": "./assets/splash.png”,//Loading圖       "resizeMode": "contain",       "backgroundColor": "#ffffff"     },     "updates": {       "fallbackToCacheTimeout": 0     },     "assetBundlePatterns": [       "**/*"     ],     "ios": {       "supportsTablet": true,       "bundleIdentifier": "com.daliapp.iosver",       "buildNumber": “1.0.4”//編譯版號,每次編譯都要改     },     "android": {       "adaptiveIcon": {         "foregroundImage": "./assets/adaptive-icon.png",         "backgroundColor": "#FFFFFF"       },       "permissions": [         "android.permission.CAMERA",         "android.permission.RECORD_AUDIO"       ],       "package": "com.daliapp.iosver"     },     "web": {       "favicon": "./assets/favicon.png"     }   } }   記得下expo eject來產生xcode專案檔 因為上架AppStore會要求說明相機使用權限原因 因此需要開啟xcode來新增授權原因 參考:https://github.com/expo/expo/blob/main/exponent-view-template/ios/exponent-view-template/Supporting/Info.plist#L28-L45 路徑:ios/app/Info.plist     接著下 eas build:configure 會產生eas.json   eas.json解說 {   "cli": {     "version": ">= 0.54.1"   },   "build": {     "development": {       "developmentClient": true,       "distribution": "internal"     },     "preview": {       "distribution": "internal"     },     "production": {}   },   "submit": {     "production": {       "ios":{         "appleId":"[email protected]", //有Apple Developer權限的帳號         "ascAppId":"1630029473",//在Apple Developer中新建專案的AppId         "appleTeamId":"MK59ZY495D"//TeamId       }     }   } }     接著下 eas build --platform ios   會開始進行編譯,並上傳到Expo   成功後再下 eas submit -p ios --latest 即可上傳到AppleStore審核頁

2022-06-17

Web

Laravel Livewire初探

參考影片:【Laravel進階】Livewire核心觀念篇3:組件渲染 #哥布林挨踢頻道 - YouTube   安裝Livewire composer require livewire/livewire   新建layout => views/layouts/base.blade.php 其中slot是Livewire組件生成會顯示的地方 <html> <head>     @livewireStyles </head> <body>   {{ $slot }}     @livewireScripts </body> </html>   發布設定檔,可更改預設layout檔 php artisan livewire:publish --config   建立組件 php artisan make:livewire Counter 將會生成兩個檔案 app/Http/Livewire/Counter.php resources/views/livewire/counter.blade.php   建立route Route::get('/counter/{id?}',App\Http\Livewire\Counter::class)->name('counter');   看看livewire/counter.php mount為進入組件時會先執行的function render為渲染動作,可設定layout與特定slot public function mount($id = null){         $this->route_id = empty($id) ? null : $id;     }          public function render()     {         if(!empty($this->route_id)){             return view('livewire.counter')->layout('layouts.app');             // return view('livewire.counter')->layout('layouts.base')->slot('counter_slot');         }else{             return view('livewire.counter')->layout('layouts.app');             // return view('livewire.counter')->layout('layouts.base')->slot('counter_slot');         }     }     參考原始碼:tuchin1228/Laravel-LivewireExercise (github.com)      

2022-05-08

Web

Window 獨立安裝Apache、PHP8與MySQL

參考影片:(13) Install Full Webserver On Windows 10 | Apache PHP 8.0 MySQL - YouTube   1.先安裝ApacheHaus,要注意的是這邊選得位元版本必須與稍後PHP的一致否則Apache無法正常啟動PHP Apache Haus Downloads 並且設定環境變數 安裝Apache httpd.exe -k install 啟動Apache httpd -k restart     2. 配置Apache,修改D:\Apache24\conf\httpd.conf  Define SRVROOT "D:/Apache24" 解鎖以下內容 LoadModule access_compat_module modules/mod_access_compat.so LoadModule headers_module modules/mod_headers.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule rewrite_module modules/mod_rewrite.so LoadModule vhost_alias_module modules/mod_vhost_alias.so Include conf/extra/httpd-vhosts.conf   搜尋DirectoryIndex 後面加上index.php   並且在文檔最下方加入以下內容 LoadModule php_module "D:/php/php8apache2_4.dll" <IfModule php_module>     PHPIniDir "D:/php/"     AddType application/x-httpd-php .php     AddType application/x-httpd-php-source .phps </IfModule>     3. 下載PHP,選擇執行續安全(Thread Safe )的版本下載,並注意位元需與前面Apache一致 參考:各式安裝包 Apac Apache2.4+MySQL8+PHP8 安裝配置一條龍和各種坑 - 代碼青雲 (codeqingyun.com) 參考:Windows10下安裝PHP 7.4+MySQL 8.0+Apache2.4(WAMP)_其它_程式人生 (796t.com) PHP For Windows: Binaries and sources Releases 設定環境變數 接著到php資料夾下,複製php.ini-development並改名為php.ini 並將php.ini裡的 extension_dir = "ext" 註解解開 有些功能也是可以解開的 extension=curl extension=gd2 extension=gmp extension=mbstring extension=Mysqli extension=openssl extension=pdo_mysql extension=pdo_sqlite     5.安裝mysql  MySQL   下載後解壓縮 設定環境變數 在MYSQL資料夾裡開一個my.ini 內容如下 [mysqld] # 設定3306埠 port=3306 # 設定mysql的安裝目錄 basedir=D:\mysql-8.0.28-winx64 # 設定mysql資料庫的資料的存放目錄 datadir=D:\mysql-8.0.28-winx64\data # 允許最大連線數 max_connections=200 # 允許連線失敗的次數。這是為了防止有人從該主機試圖攻擊資料庫系統 max_connect_errors=10 # 服務端使用的字符集預設為UTF8 character-set-server=utf8 # 建立新表時將使用的預設儲存引擎 default-storage-engine=INNODB [mysql] # 設定mysql客戶端預設字符集 default-character-set=utf8 [client] # 設定mysql客戶端連線服務端時預設使用的埠 port=3306 default-character-set=utf8   mysql初始化 mysqld --initialize --user=mysql --console 初始化完成會有一個臨時密碼,第一次登入就靠它了因此要記著 安裝mysql mysqld -install 啟動mysql net start mysql mysql -u root -p 接著輸入臨時密碼即可登入 修改密碼 ALTER USER [email protected] IDENTIFIED BY '新密碼';              

2022-04-20

API串接

Line Pay v3 串接 (Online)

參考API文件: https://pay.line.me/tw/developers/apis/apis?locale=zh_TW   先註冊Sandbox LINE Pay Developers : Sandbox creation 之後信箱會收到一組ID跟Password 這組帳密是用來登入LinePay商店的 LINE Pay 行動支付 登入後點擊右上角測試環境並切換繁體中文 點擊「管理付款連結」-> 「管理連結金鑰」 ->輸入登入的密碼 會拿到一組Channel ID與Channel Secret Key 這兩項是待會串接會需要的資料     準備動作完成,接下來開始進行串接 由於LINE PAY API用瀏覽器會有跨域問題,所以用後端Laravel來做     Online API 付款 ( 使用者掃描條碼並確認付款 )   API URL  $channelId = '上面拿到的ChannelId'; $key = '上面拿到的Secret Key'; $requestUrl = '/v3/payments/request'; //目前先把訂單寫死,每個欄位皆為必填並且格是必須一樣,注意orderId不能重複 //須注意商品價錢要對的起來不要算錯了  $order = [             'amount' => 100,             'currency' => 'TWD',             'orderId' => "asa81f5s2ass2fd12333",             'packages' => [                 [                     'id' => '202203311d2ef',                     'amount' => 100,                     'name' => '麥當勞六塊炸雞',                     'products' => [                         [                             'name' => "麥當勞六塊雞餐",                             'quantity' => 2,                             'price' => 50,                         ],                     ],                 ],             ],             'redirectUrls' => [                 'confirmUrl' => '', //使用者按下確認結帳後導向的網址,使用者成功付款時會將transactionId帶到這個網址的query,再利用這個confirmUrl取得transactionId來觸發Confirm API                 'cancelUrl' => '',//使用者按下取消結帳後導向的網址             ],      ];   //不重複的UUID or timestamp  $nonce = $this->create_uuid(); /***************UUID實作****************/ public static function create_uuid($prefix = "")     {         $chars = md5(uniqid(mt_rand(), true));         $uuid = substr($chars, 0, 8) . '-'         . substr($chars, 8, 4) . '-'         . substr($chars, 12, 4) . '-'         . substr($chars, 16, 4) . '-'         . substr($chars, 20, 12);         return $prefix . $uuid;     } /************************************/   接下來是重點,打這支API會驗證Header 其中的X-LINE-Authorization需要進行加密        $data = $key . $requestUrl . json_encode($order) . $nonce;        $hash = hash_hmac('sha256', $data, $key, true);        $hmacBase64 = base64_encode($hash); 接來下組合Header $headers = array(             'Content-Type:application/json',             'X-LINE-ChannelId:' . $channelId,             'X-LINE-Authorization-Nonce:' . $nonce,             'X-LINE-Authorization:' . $hmacBase64,    );   //要打API的網址 $url = "https://sandbox-api-pay.line.me" . $requestUrl;   //進行API $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($order)); $output = curl_exec($ch); return $output;   此時會收到web與app的網址,將使用者畫面導向這個網址即可到達付款頁面 如超過授權期限,這筆交易會進入後台交易失敗   接著必須帶上 transactionId 去打Confirm API 來請款   $channelId = env('LINEPAY_channelId');         $key = env('LINEPAY_SecretKey');         $requestUrl = '/v3/payments/' . $transactionId . '/confirm';         $nonce = $this->create_uuid();           $url = env('LINEPAY_URL') . $requestUrl;         $body = [             'amount' => $amount,             'currency' => 'TWD',         ];           $data = $key . $requestUrl . json_encode($body) . $nonce;         $hash = hash_hmac('sha256', $data, $key, true);         $hmacBase64 = base64_encode($hash);           $headers = array(             'Content-Type:application/json',             'X-LINE-ChannelId:' . $channelId,             'X-LINE-Authorization-Nonce:' . $nonce,             'X-LINE-Authorization:' . $hmacBase64,         );  $ch = curl_init();         curl_setopt($ch, CURLOPT_URL, $url);         curl_setopt($ch, CURLOPT_POST, true);         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);         curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);         curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));         $output = curl_exec($ch); 出現以下回傳值才代表交易成功 此回傳格式為string 需使用json_decode才能取值   Online付款到這邊告一段落

2022-04-01

API串接

Line Pay v2 串接 (Offline)

由於Offline跟Online差別只有在API的部分,因此前面註冊Sandbox部分可參考Online做法 Line Pay v3 串接 (Online & Offline)   Online API 付款 ( 可由店家掃描客戶的條碼 )   Offline的API URL 與 Header規則   $channelId = 'LinePay後臺拿到的ChannelId'; $key = 'LinePay後臺拿到的Secret Key'; $url = 'https://sandbox-api-pay.line.me/v2/payments/oneTimeKeys/pay';   //這邊Header跟v3不一樣,比起來較簡單點 $headers = array(             'Content-Type:application/json',             'X-LINE-ChannelId:' . $channelId,             'X-LINE-ChannelSecret:' . $key, ); $body = [             'productName' => '商品測試',             'amount' => '20',             'currency' => 'TWD',             'orderId' => '2323sdsf2sd3fdg2332', //訂單編號,記得不要重複             'oneTimeKey' => '388176489952165252', //取得使用者的條碼內容,可參考下面的產生器,條碼授權時間有限 ]; /********************/ LinePay條碼產生器 付款給廠商 (line.me) /*********************/   //打api $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body)); $output = curl_exec($ch); return $output; 基本上此時已付款完成 sandbox付款條碼產生器的點數購買勾選調,選項就不會寫信用卡。     假如等待時間過久,需要執行另一隻檢查API來查看交易狀況 $url = 'https://sandbox-api-pay.line.me/v2/payments/orders/' . $orderId . '/check'; Header的部分跟上面一模一樣,只不過方法是用Get $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $output = curl_exec($ch); return $output;   若超過20分鐘這筆交易將會被歸類為交易失敗   //查看已請款訂單 $url = 'https://sandbox-api-pay.line.me/v2/payments?orderId=' . $orderId . '&transactionId=' . $transactionId; transactionId為成功付款後回傳的項目 Header部分跟上面一樣,方法同樣是使用Get $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $output = curl_exec($ch); return $output;

2022-04-01

未分類

Visual Studio Code環境設定上傳Github

1. VS CODE 安裝Setting SYNC 插件   2. 開啟Github頁面->右上角選單->setting-> Developer settings->Personal access tokens->Generate new token   3. Expiration=> no Expiration,下方gist打勾送出,得到Token後記下。   4. 右上角「+」,新增Gist, Gist內容先隨意輸入,並記下網址最後一段的Gist ID。   5.VSCode按F1,輸入Sync 選擇->Sync進階選項->編輯本機延伸設定模組,找到"token"貼上第二步驟的token。   6. VSCode搜尋setting sync 旁邊的齒輪選擇「擴充設定」,於Sync:Gist貼上步驟四的Gist ID   7.接著按快捷鍵 Shift + Alt + U 即可完成上傳,檢查Github裡的Gist內容會更新。   下載設定 1. 別台電腦一樣下載 Setting SYNC 插件   2. VSCode搜尋setting sync 旁邊的齒輪選擇「擴充設定」,於Sync:Gist貼上Gist ID(Github裡gist專案網址最後一段)   3. 按快捷鍵 Shift + Alt + D 即可開始下載  

2022-03-13

React

PM2部署Next.js筆記

為了實現伺服器重開機能夠自動啟用pm2的專案   pm2 startup   切換到專案目錄下 pm2 start npm --name "專案名" -- start   pm2 save

2022-02-22