LINE Pay款流程:
reserve Page(紅科) 發送 reserve API => 取得 payment URL => 轉址到 payment URL => LINE Pay 檢查USER狀態 => 轉回confirm page(紅科), 發送 confirm API => DOWN.
付款需要程式:
reserve API, confirm API:
send request JSON and read return JSON:
C#:
using System.Net;
using System.IO;
public partial class TEST : System.Web.UI.Page
{
DB.OrderMain oOrderObj = null;
protected void Page_Load(object sender, EventArgs e)
{
//Setting request header
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("__APIRootURL__");
httpWebRequest.ContentType = "application/json; charset=UTF-8";
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add("X-LINE-ChannelId", DB.SysConfig.LINEPay.ChannelId);
httpWebRequest.Headers.Add("X-LINE-ChannelSecret", DB.SysConfig.LINEPay.SecretKey);
//加入參數
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string requestJSON = "{\"productName\": \"" + DB.SysConfig.SYSTEM_NAME + "\"," +
"\"productImageUrl\": \"" + DB.SysConfig.URL_Shopping + "images/Logo.jpg\"," +
"\"amount\": " + oOrderObj.TotalAmount() + "," +
"\"currency\": \"TWD\"," +
"\"orderId\": \"" + oOrderObj.DisplayOrderId + "\"," +
"\"confirmUrl\": \"" + DB.SysConfig.URL_Shopping + "Handler/LinePay/GotoComfirm.aspx?Id=" + oOrderObj.Id + "\"," +
"\"cancelUrl\": \"" + DB.SysConfig.URL_Shopping + "Shopping/OrderComplete.aspx?Id=" + oOrderObj.Id + "\"," +
"\"capture\": \"true\"," +
"\"confirmUrlType\": \"CLIENT\"}";
streamWriter.Write(requestJSON);
streamWriter.Flush();
streamWriter.Close();
}
//取得回覆資訊
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
//解讀回覆資訊
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseJSON = streamReader.ReadToEnd();
//將 JSON 轉為物件
GN.LinePay.reserveRes.ReturnJSON oReturnObj = (GN.LinePay.reserveRes.ReturnJSON)Newtonsoft.Json.JsonConvert.DeserializeObject(responseJSON, typeof(GN.LinePay.reserveRes.ReturnJSON));
if (oReturnObj.returnCode == "0000")
{
//成功
}
else
{
//失敗
string ErrMsg = "Error Code: " + oReturnObj.returnCode + "\r\n" + oReturnObj.returnMessage;
}
}
}
}
.vb
Imports System.Net
Imports System.IO
Partial Class TEST
Inherits System.Web.UI.Page
Dim oOrderObj As DB.OrderMain
Private Sub Admin_TEST_Load(sender As Object, e As EventArgs) Handles Me.Load
'Setting request header
Dim httpWebRequest As HttpWebRequest = WebRequest.Create("__APIRootURL__")
httpWebRequest.ContentType = "application/json; charset=UTF-8"
httpWebRequest.Method = "POST"
httpWebRequest.Headers.Add("X-LINE-ChannelId", DB.SysConfig.LINEPay.ChannelId)
httpWebRequest.Headers.Add("X-LINE-ChannelSecret", DB.SysConfig.LINEPay.SecretKey)
'加入參數
Using streamWriter As New StreamWriter(httpWebRequest.GetRequestStream())
Dim requestJSON As String = "{""productName"": """ + DB.SysConfig.SYSTEM_NAME + """," +
"""productImageUrl"": """ + DB.SysConfig.URL_Shopping + "images/Logo.jpg""," +
"""amount"": " + oOrderObj.TotalAmount() + "," +
"""currency"": ""TWD""," +
"""orderId"": """ + oOrderObj.DisplayOrderId + """," +
"""confirmUrl"": """ + DB.SysConfig.URL_Shopping + "Handler/LinePay/GotoComfirm.aspx?Id=" + oOrderObj.Id + """," +
"""cancelUrl"": """ + DB.SysConfig.URL_Shopping + "Shopping/OrderComplete.aspx?Id=" + oOrderObj.Id + """," +
"""capture"": ""true""," +
"""confirmUrlType"": ""CLIENT""}"
streamWriter.Write(requestJSON)
streamWriter.Flush()
streamWriter.Close()
End Using
'取得回覆資訊
Dim httpResponse As HttpWebResponse = httpWebRequest.GetResponse
'解讀回覆資訊
Using streamReader As New StreamReader(httpResponse.GetResponseStream())
Dim responseJSON As String = streamReader.ReadToEnd()
'將 JSON 轉為物件
Dim oReturnObj As GN.LinePay.reserveRes.ReturnJSON = Newtonsoft.Json.JsonConvert.DeserializeObject(responseJSON, GetType(GN.LinePay.reserveRes.ReturnJSON))
Dim ResMsg As String = ""
If oReturnObj.returnCode = "0000" Then
'成功
Else
'失敗
End If
End Using
End Sub
End Class
工具網站:
JSON 轉物件
http://json2csharp.com/
C# to VB :
http://converter.telerik.com/
#專案: 紅科
Reiko, 2017/6/21 下午 07:22:58
Post 的資料好像會變大, 要改 Web.config
<system.web>
<httpRuntime requestValidationMode="2.0" maxRequestLength="1024000"/>
</system.web>
程式碼如下:
public string UploadFilesToRemoteUrl(string url, string[] files, NameValueCollection formFields = null)
{
string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "multipart/form-data; boundary=" +
boundary;
request.Method = "POST";
request.KeepAlive = true;
Stream memStream = new System.IO.MemoryStream();
var boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "\r\n");
var endBoundaryBytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "--");
string formdataTemplate = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
if (formFields != null)
{
foreach (string key in formFields.Keys)
{
string formitem = string.Format(formdataTemplate, key, formFields[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
memStream.Write(formitembytes, 0, formitembytes.Length);
}
}
string headerTemplate =
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n" +
"Content-Type: application/octet-stream\r\n\r\n";
for (int i = 0; i < files.Length; i++)
{
memStream.Write(boundarybytes, 0, boundarybytes.Length);
var header = string.Format(headerTemplate, "uplTheFile", files[i]);
var headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
using (var fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read))
{
var buffer = new byte[1024];
var bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
Response.Write("bytesRead: " + bytesRead.ToString() + "<br>");
memStream.Write(buffer, 0, bytesRead);
}
}
}
memStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
request.ContentLength = memStream.Length;
using (Stream requestStream = request.GetRequestStream())
{
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
}
try
{
using (var response = request.GetResponse())
{
Stream stream2 = response.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
return reader2.ReadToEnd();
}
}
catch (Exception ex)
{
return (ex.ToString());
throw;
}
}
Bike, 2017/1/12 下午 08:21:09
客戶要求
1. 檔案只能放在 Firewall 內的後台用 Web server (Server A).
2. 使用者只能存取 DMZ 的 Web server (Server B).
3. Server B 只能用 HTTP 通過 Firewall 向 Server A 要資料.(i.e. Server B 不能掛戴 Server A 的目錄成為虛擬目錄)
所以在 Server B 上面建立了一支程式用 HTTP 的方式讀取 Server A 的檔案再寫出去.
例如, http://ServerB/Upload/test.pdf 會讀取 http://ServerA/Upload/test.pdf 再送到 Client 端
namespace WWW.Controllers
{
public class UploadController : Controller
{
// GET: Upload
public void Index(string Filename)
{
//Create a stream for the file
Stream stream = null;
//This controls how many bytes to read at a time and send to the client
int bytesToRead = 10000;
// Buffer to read bytes in chunk size specified above
byte[] buffer = new Byte[bytesToRead];
string url = "http://admin-dev.nanya.bike.idv.tw/newnanyaback/Upload/" + Filename;
// The number of bytes read
try
{
//Create a WebRequest to get the file
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(url);
//Create a response for this request
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
//Get the Stream returned from the response
stream = fileResp.GetResponseStream();
// prepare the response to the client. resp is the client Response
var resp = HttpContext.Response;
if (Filename.ToLower().EndsWith(".png") ||
Filename.ToLower().EndsWith(".jpg") ||
Filename.ToLower().EndsWith(".jpeg") ||
Filename.ToLower().EndsWith(".gif")
)
{
resp.ContentType = "image";
}
else
{
//Indicate the type of data being sent
resp.ContentType = "application/octet-stream";
//Name the file
resp.AddHeader("Content-Disposition", "attachment; filename=\"" + HttpUtility.UrlEncode(Filename, Encoding.UTF8) + "\"");
}
resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
// Verify that the client is connected.
if (resp.IsClientConnected)
{
// Read data into the buffer.
length = stream.Read(buffer, 0, bytesToRead);
// and write it out to the response's output stream
resp.OutputStream.Write(buffer, 0, length);
// Flush the data
resp.Flush();
//Clear the buffer
buffer = new Byte[bytesToRead];
}
else
{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}
}
}
}
但不是這樣就好了, 在 RouteConfig.cs 中要加上:
routes.MapRoute(
name: "Upload",
url: "Upload/{filename}",
defaults: new { controller = "Upload", action = "Index", filename = UrlParameter.Optional }
);
此外在 Web.Config 中也要加上:
<system.webServer>
<handlers>
<add name="UrlRoutingHandler_Upload"
type="System.Web.Routing.UrlRoutingHandler,
System.Web, Version=4.0.0.0,
Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
path="/Upload/*"
verb="GET"/>
</handlers>
</system.webServer>
參考:
http://stackoverflow.com/questions/5596747/download-stream-file-from-url-asp-net
http://blog.darkthread.net/post-2014-12-05-mvc-routing-for-url-with-filename.aspx
Bike, 2016/12/1 下午 09:34:30
--抓所有的 Table
Select * from INFORMATION_SCHEMA.TABLES
--抓所有的 COLUMNS
Select * from INFORMATION_SCHEMA.COLUMNS
--抓欄位的 Description
select
st.name [Table],
sc.name [Column],
sep.value [Description]
from sys.tables st
inner join sys.columns sc on st.object_id = sc.object_id
left join sys.extended_properties sep on st.object_id = sep.major_id
and sc.column_id = sep.minor_id
and sep.name = 'MS_Description'
where st.name = 'TableName'
and sc.name = 'ColumnName'
--修改欄位的 Description.
EXEC sp_updateextendedproperty
@name = N'MS_Description', @value = 'Your description',
@level0type = N'Schema', @level0name = 'dbo',
@level1type = N'Table', @level1name = 'TableName',
@level2type = N'Column', @level2name = 'Name';
EXEC sp_addextendedproperty
@name = N'MS_Description', @value = 'Code description',
@level0type = N'Schema', @level0name = 'dbo',
@level1type = N'Table', @level1name = 'TableName',
@level2type = N'Column', @level2name = 'ColumnName';
--新增 Table 的 extendedproperty
EXEC sp_addextendedproperty
@name = N'Description', @value = 'Hey, here is TableName description!',
@level0type = N'Schema', @level0name = 'dbo',
@level1type = N'Table', @level1name = 'TableName'
GO
--修改 Table 的 extendedproperty
EXEC sp_updateextendedproperty
@name = N'Description', @value = 'Hey, here is my description! 123',
@level0type = N'Schema', @level0name = 'dbo',
@level1type = N'Table', @level1name = 'TableName'
GO
--讀取 Extended Property
SELECT sys.objects.name AS TableName, ep.name AS PropertyName,
ep.value AS Description
FROM sys.objects
CROSS APPLY fn_listextendedproperty(default,
'SCHEMA', schema_name(schema_id),
'TABLE', name, null, null) ep
WHERE sys.objects.name NOT IN ('sysdiagrams')
ORDER BY sys.objects.name
--讀取 Column 的 Description
SELECT objtype, objname, name, value
FROM fn_listextendedproperty (NULL, 'schema', 'dbo', 'table', 'TableName', 'column', default);
GO
--讀取特定 Table 的 Description
SELECT *
FROM fn_listextendedproperty (NULL, 'schema', 'dbo', 'table', 'TableName', default, default);
GO
--讀取 所有 Table 的 Description
SELECT *
FROM fn_listextendedproperty (NULL, 'schema', 'dbo', 'table', default, default, default);
GO
--新增或修改資料表說明
IF not exists(SELECT * FROM ::fn_listextendedproperty (NULL, 'user', 'dbo', 'table', '資料表名稱', NULL, NULL))
BEGIN
exec sp_addextendedproperty 'MS_Description', '資料表說明', 'user', 'dbo', 'table', '資料表名稱'
END
ELSE
BEGIN
exec sp_updateextendedproperty 'MS_Description', '資料表說明', 'user', 'dbo', 'table', '資料表名稱'
END
--新增或修改欄位說明
IF not exists(SELECT * FROM ::fn_listextendedproperty (NULL, 'user', 'dbo', 'table', '資料表名稱', 'column', '欄位名稱'))
BEGIN
exec sp_addextendedproperty 'MS_Description', '欄位說明', 'user', 'dbo', 'table', '資料表名稱', 'column', '欄位名稱'
END
ELSE
BEGIN
exec sp_updateextendedproperty 'MS_Description', '欄位說明', 'user', 'dbo', 'table', '資料表名稱', 'column', '欄位名稱'
END
Bike, 2016/6/29 下午 04:42:25