spc-kiosk-pb/Service/BsvPayment/PunchhHappyPoint_US.cs
2019-06-16 14:12:09 +09:00

1501 lines
54 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cosmos.UserFrame;
using Cosmos.ServiceProvider;
using Cosmos.Common;
using Cosmos.CommonManager;
using System.Data;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Net.Cache;
using System.IO;
using System.Collections.Specialized;
using System.Management;
using System.Security.Cryptography;
//************************************************************************************************
// 최초 작성 : 2018.02.22, 미주 펀치 APP 와 해피포인트 기능 ; girak.kim
// Class : Model > PunchhPosClient(PunchhClientResponse) <--> PunchhServiceCaller (PunchhAPIResponse)
// 변경 이력 :
//------------------------------------------------------------------------------------------------
// - 수정 이유 :
// - 수정 내용 :
// - 수정 적용된 내용 :
// - 기 타 :
//************************************************************************************************
namespace Cosmos.Service
{
//##############################[결제, 포인트 관련 인터페이스 구현 클래스]#############################################//
class PunchhHappyPoint_US : PaymentBase, IPaymentUs
{
private IOCBDirect m_OCBDirect = null;
public PunchhHappyPoint_US()
{
m_OCBDirect = (IOCBDirect)sManager.InitServiceInstance(ServiceLists.AGENT_OLEDEVICE.DLL, ServiceLists.AGENT_OLEDEVICE.OCB_DIRECT);
}
#region SearchPayment
/// <summary>
/// 결제 조회
/// </summary>
/// <param name="aParam"></param>
/// <param name="aRet"></param>
/// <returns></returns>
public string SearchPayment(string[] aParam, ref string[] aRet)
{
string sRet = UserCom.RST_ERR;
return sRet;
}
#endregion
#region GetPayment
/// <summary>
/// 결제 정보 획득
/// </summary>
/// <param name="aParam"></param>
/// <returns></returns>
public object GetPayment(string[] aParam)
{
return m_cPayItem;
}
#endregion
#region SetPayment
/// <summary>
/// 결제 등록(제휴 포인트 사용)
/// </summary>
/// <param name="aParam"></param>
/// <returns></returns>
public string SetPayment(string[] aParam)
{
string sRet = UserCom.RST_ERR;
return sRet;
}
#endregion
#region CancelPayment
/// <summary>
/// 결제 취소
/// </summary>
/// <param name="aParam"></param>
/// <returns></returns>
public string CancelPayment(string[] aParam)
{
string sRet = UserCom.RST_ERR;
return sRet;
}
#endregion
#region RefundPayment
/// <summary>
/// 결제 반품
/// </summary>
/// <param name="aParam"></param>
/// <returns></returns>
public string RefundPayment(string[] aParam)
{
string sRet = UserCom.RST_ERR;
return sRet;
}
#endregion
#region SetMenualPayment
public string SetMenualPayment(string[] aParam)
{
string sRet = UserCom.RST_ERR;
return sRet;
}
#endregion
}
//##############################[결제, 포인트 관련 인터페이스 구현 클래스 끝]#############################################//
#region Punchh
public class PunchhConst
{
public const string LOCATION_KEY = "9079df560fad175e29c5dff19c5acbda";//"273b9a4039481b5063e1d1001cdaef4e";
public const string USER_LOOKUP_API_URL = "/users/search";//사용자 정보 조회
public static string POSSIBLE_REDEMPTION_API_URL = "/redemptions/possible"; //
public static string CREATE_OR_VOID_REDEMPTION_API_URL = "/redemptions";
public static string CHECKIN_API_URL = "/checkins";
}
#endregion
#region / Strat (API Json
#region (Balance, Reward, MenuItem) Strat
public class Balance
{
[JsonProperty(PropertyName = "banked_rewards")]
public double BankedRewards { get; set; }
[JsonProperty(PropertyName = "membership_level")]
public string MembershipLevel { get; set; }
[JsonProperty(PropertyName = "membership_level_id")]
public int? MembershipLevelId { get; set; }
[JsonProperty(PropertyName = "membership_program_id")]
public int? MembershipProgramId { get; set; }
[JsonProperty(PropertyName = "net_balance")]
public double? NetBalance { get; set; }
[JsonProperty(PropertyName = "net_debits")]
public double? NetDebits { get; set; }
[JsonProperty(PropertyName = "pending_points")]
public double? PendingPoints { get; set; }
[JsonProperty(PropertyName = "points_balance")]
public double? PointsBalance { get; set; }
[JsonProperty(PropertyName = "signup_anniversary_day")]
public string SignupAnniversaryDay { get; set; }
[JsonProperty(PropertyName = "total_credits")]
public double? TotalCredits { get; set; }
[JsonProperty(PropertyName = "total_debits")]
public double? TotalDebits { get; set; }
[JsonProperty(PropertyName = "total_point_credits")]
public double? TotalPointCredits { get; set; }
[JsonProperty(PropertyName = "total_redeemable_visits")]
public int? TotalRedeemableVisits { get; set; }
[JsonProperty(PropertyName = "expired_membership_level")]
public string ExpiredMembershipLevel { get; set; }
[JsonProperty(PropertyName = "total_visits")]
public int? TotalVisits { get; set; }
[JsonProperty(PropertyName = "initial_visits")]
public int? InitialVisits { get; set; }
[JsonProperty(PropertyName = "unredeemed_cards")]
public int? UnredeemedCards { get; set; }
}
public class Reward
{
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "discount_amount")]
public double DiscountAmount { get; set; }
[JsonProperty(PropertyName = "points")]
public double Points { get; set; }
[JsonProperty(PropertyName = "image")]
public string Image { get; set; }
[JsonProperty(PropertyName = "created_at")]
public DateTime? CreatedAt { get; set; }
[JsonProperty(PropertyName = "end_date_tz")]
public DateTime? EndDateTz { get; set; }
[JsonProperty(PropertyName = "start_date_tz")]
public DateTime? StartDateTz { get; set; }
[JsonProperty(PropertyName = "updated_at")]
public DateTime? UpdatedAt { get; set; }
[JsonProperty(PropertyName = "redeemable_properties")]
public string RedeemableProperties { get; set; }
[JsonProperty(PropertyName = "status")]
public string Status { get; set; }
}
public class MenuItem
{
[JsonProperty(PropertyName = "item_name")]
public string ItemName { get; set; }
[JsonProperty(PropertyName = "item_qty")]
public int? ItemQty { get; set; }
[JsonProperty(PropertyName = "item_amount")]
public double? ItemAmount { get; set; }
[JsonProperty(PropertyName = "menu_item_type")]
public string MenuItemType { get; set; }
[JsonProperty(PropertyName = "menu_item_id")]
public int? MenuItemId { get; set; }
[JsonProperty(PropertyName = "menu_family")]
public string MenuFamily { get; set; }
[JsonProperty(PropertyName = "menu_major_group")]
public string MenuMajorGroup { get; set; }
[JsonProperty(PropertyName = "serial_number")]
public int? SerialNumber { get; set; }
}
#endregion (Balance, Reward, MenuItem) End
#region UserLookup Model ,
public class UserLookupRequest
{
[JsonProperty(PropertyName = "location_key")]
public string LocationKey { get; set; }
[JsonProperty(PropertyName = "phone")]
public string Phone { get; set; }
[JsonProperty(PropertyName = "user_as_qrcode")]
public string UserAsQRcode { get; set; }
[JsonProperty(PropertyName = "redemption_code")]
public string RedemptionCode { get; set; }
[JsonProperty(PropertyName = "card_number")]
public string CardNumber { get; set; }
}
public class UserLookupResponse
{
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
[JsonProperty(PropertyName = "created_at")]
public DateTime? CreatedAt { get; set; }
[JsonProperty(PropertyName = "updated_at")]
public DateTime? UpdatedAt { get; set; }
[JsonProperty(PropertyName = "first_name")]
public string FirstName { get; set; }
[JsonProperty(PropertyName = "last_name")]
public string LastName { get; set; }
[JsonProperty(PropertyName = "phone")]
public string Phone { get; set; }
[JsonProperty(PropertyName = "fb_uid")]
public string FbUid { get; set; }
[JsonProperty(PropertyName = "birthday")]
public DateTime? Birthday { get; set; }
[JsonProperty(PropertyName = "gender")]
public string Gender { get; set; }
[JsonProperty(PropertyName = "city")]
public string City { get; set; }
[JsonProperty(PropertyName = "state")]
public string State { get; set; }
[JsonProperty(PropertyName = "selected_card_number")]
public string SelectedCardNumber { get; set; }
[JsonProperty(PropertyName = "selected_reward_id")]
public int? selected_reward_id { get; set; }
[JsonProperty(PropertyName = "balance")]
public Balance Balance { get; set; }
[JsonProperty(PropertyName = "rewards")]
public List<Reward> Rewards { get; set; }
}
#endregion UserLookup Model End
#region Redemption Possible Model ( )
public class RedemptionRequest
{
[JsonProperty(PropertyName = "location_key")]
public string LocationKey { get; set; }
[JsonProperty(PropertyName = "discount_type")]
public string DiscountType { get; set; }
[JsonProperty(PropertyName = "reward_id")]
public int? RewardId { get; set; }
[JsonProperty(PropertyName = "redemption_code")]
public string RedemptionCode { get; set; }
[JsonProperty(PropertyName = "user_as_qrcode")]
public string UserAsQRcode { get; set; }
[JsonProperty(PropertyName = "punchh_key")]
public string PunchhKey { get; set; }
[JsonProperty(PropertyName = "transaction_no")]
public int? TransactionNo { get; set; }
[JsonProperty(PropertyName = "receipt_datetime")]
public DateTime? ReceiptDateTime { get; set; }
[JsonProperty(PropertyName = "menu_items")]
public List<MenuItem> MenuItems { get; set; }
[JsonProperty(PropertyName = "subtotal_amount")]
public double? SubTotalAmount { get; set; }
[JsonProperty(PropertyName = "receipt_amount")]
public double? ReceiptAmount { get; set; }
#region
/*
[JsonProperty(PropertyName = "email")]
public string Email { get; set; }
[JsonProperty(PropertyName = "cc_last4")]
public int? CCLast4 { get; set; }
[JsonProperty(PropertyName = "employee_id")]
public int? EmployeeId { get; set; }
[JsonProperty(PropertyName = "employee_name")]
public string EmployeeName { get; set; }
[JsonProperty(PropertyName = "external_uid")]
public string ExternalUid { get; set; }
[JsonProperty(PropertyName = "pos_version")]
public string POSVersion { get; set; }
[JsonProperty(PropertyName = "pos_type")]
public string POSType { get; set; }
[JsonProperty(PropertyName = "process")]
public bool? Process { get; set; }
* */
#endregion
}
public class RedemptionResponse
{
[JsonProperty(PropertyName = "redemption_id")]
public int? RedemptionId { get; set; }
[JsonProperty(PropertyName = "redemption_code")]
public string RedemptionCode { get; set; }
[JsonProperty(PropertyName = "redemption_amount")]
public double? RedemptionAmount { get; set; }
[JsonProperty(PropertyName = "status")]
public string Status { get; set; }
[JsonProperty(PropertyName = "category")]
public string Category { get; set; }
[JsonProperty(PropertyName = "previous_amount")]
public string PreviousAmount { get; set; }
}
#endregion Redemption Possible Model End
#region User Checkin Model ,
public class CheckinRequest
{
[JsonProperty(PropertyName = "location_key")]
public string LocationKey { get; set; }
[JsonProperty(PropertyName = "punchh_key")]
public string PunchhKey { get; set; }
[JsonProperty(PropertyName = "receipt_datetime")]
public DateTime? ReceiptDateTime { get; set; }
[JsonProperty(PropertyName = "payable")]
public double? Payable { get; set; }
[JsonProperty(PropertyName = "subtotal_amount")]
public double SubTotalAmount { get; set; }
[JsonProperty(PropertyName = "receipt_amount")]
public double ReceiptAmount { get; set; }
[JsonProperty(PropertyName = "pos_version")]
public string POSVersion { get; set; }
[JsonProperty(PropertyName = "employee_id")]
public int EmployeeId { get; set; }
[JsonProperty(PropertyName = "sequence_no")]
public int SequenceNo { get; set; }
[JsonProperty(PropertyName = "pos_type")]
public string POSType { get; set; }
[JsonProperty(PropertyName = "cc_last4")]
public string CCLast4 { get; set; }
[JsonProperty(PropertyName = "amount")]
public string Amount { get; set; }
[JsonProperty(PropertyName = "employee_name")]
public string EmployeeName { get; set; }
[JsonProperty(PropertyName = "transaction_no")]
public int TransactionNo { get; set; }
[JsonProperty(PropertyName = "revenue_code")]
public string RevenueCode { get; set; }
[JsonProperty(PropertyName = "menu_items")]
public List<MenuItem> MenuItems { get; set; }
[JsonProperty(PropertyName = "phone")]
public string Phone { get; set; }
[JsonProperty(PropertyName = "email")]
public string Email { get; set; }
[JsonProperty(PropertyName = "user_as_qrcode")]
public string UserAsQRcode { get; set; }
[JsonProperty(PropertyName = "card_number")]
public string CardNumber { get; set; }
[JsonProperty(PropertyName = "single_scan_token")]
public string SingleScanToken { get; set; }
[JsonProperty(PropertyName = "redemption_code")]
public string RedemptionCode { get; set; }
[JsonProperty(PropertyName = "user_token")]
public string UserToken { get; set; }
}
public class CheckinResponse
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "first_name")]
public string FirstName { get; set; }
[JsonProperty(PropertyName = "last_name")]
public string LastName { get; set; }
[JsonProperty(PropertyName = "email")]
public string Email { get; set; }
[JsonProperty(PropertyName = "phone")]
public string Phone { get; set; }
[JsonProperty(PropertyName = "fb_uid")]
public string FbUid { get; set; }
[JsonProperty(PropertyName = "user_as_qrcode")]
public string UserAsQRcode { get; set; }
[JsonProperty(PropertyName = "birthday")]
public string Birthday { get; set; }
[JsonProperty(PropertyName = "gender")]
public string Gender { get; set; }
[JsonProperty(PropertyName = "anniversary")]
public DateTime? Anniversary { get; set; }
[JsonProperty(PropertyName = "created_at")]
public DateTime? CreatedAt { get; set; }
[JsonProperty(PropertyName = "rewards")]
public List<Reward> Rewards { get; set; }
[JsonProperty(PropertyName = "balance")]
public Balance Balance { get; set; }
}
#endregion User Checkin Model End
#region Void Redemption Model
public class VoidRedemptionRequest
{
[JsonProperty(PropertyName = "location_key")]
public string LocationKey { get; set; }
[JsonProperty(PropertyName = "phone")]
public string Phone { get; set; }
[JsonProperty(PropertyName = "user_as_qrcode")]
public string UserAsQRcode { get; set; }
[JsonProperty(PropertyName = "card_number")]
public string CardNumber { get; set; }
[JsonProperty(PropertyName = "redemption_id")]
public int? RedemptionId { get; set; }
[JsonProperty(PropertyName = "redemption_code")]
public string RedemptionCode { get; set; }
[JsonProperty(PropertyName = "store_number")]
public string StoreNumber { get; set; }
[JsonProperty(PropertyName = "transaction_no")]
public string TransactionNo { get; set; }
}
#endregion Void Redemption Model End
#endregion End
#region Punchh API Library
public static class PunchhLib
{
/// <summary>
/// request json key-value
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="requestModel"></param>
/// <returns></returns>
public static NameValueCollection GetNameValue<T>(T requestModel)
{
NameValueCollection nameValue = new NameValueCollection();
var lstRequest = requestModel.GetType().GetProperties().ToList();
foreach (var item in lstRequest)
{
var attributes = item.GetCustomAttributes(typeof(JsonPropertyAttribute), false);
foreach (var att in attributes)
{
var atts = (JsonPropertyAttribute)att;
var attName = atts.PropertyName;//json property
var attValue = Convert.ToString(item.GetValue(requestModel, null));
nameValue.Add(attName, attValue);
}
}
return nameValue;
}
/// <summary>
/// http 통신 시 에 userAgent 정보
/// </summary>
/// <param name="locationKey"></param>
/// <returns></returns>
public static string GetUserAgent(string locationKey)
{
var windowsVersion = GetOSFriendlyName();
var dotNetVersion = System.Environment.Version;
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
System.Diagnostics.FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location);
var productVerArr = fvi.ProductVersion.Split('.');
string assemblyVersion = productVerArr[0] + "." + productVerArr[1] + "." + productVerArr[2];
StringBuilder sb = new StringBuilder();
sb.AppendFormat("pchposlib/{0};{1};{2};lkey:{3} ", assemblyVersion, dotNetVersion, windowsVersion, locationKey);
return sb.ToString();
}
/// <summary>
/// OS 정보
/// </summary>
/// <returns></returns>
public static string GetOSFriendlyName()
{
string result = string.Empty;
result = "Windows";
/* 큰 의미 없어 보임.
try
{
//System.Managemet 참조 추가 필요
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
foreach (ManagementObject os in searcher.Get())
{
result = os["Caption"].ToString();
break;
}
var resultArr = result.Split(' ');
result = resultArr[1] + " " + resultArr[2];
}
catch (Exception ex)
{
}
* */
return result;
}
public static string GenerateXPchDigest(string message, string secretKey)
{
var encoding = new System.Text.ASCIIEncoding();
byte[] keyBytes = encoding.GetBytes(secretKey);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacSHA256 = new HMACSHA1(keyBytes))
{
byte[] hashMessage = hmacSHA256.ComputeHash(messageBytes);
return BitConverter.ToString(hashMessage).Replace("-", "").ToLower();
}
}
public static T ToEnum<T>(this string value)
{
return (T)Enum.Parse(typeof(T), value, true);
}
public static int CreateTransactionNo()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(2018, 1, 1, 0, 0, 0, 0);
//double dTime = ts.TotalSeconds;
int nTime = (int)Math.Truncate(ts.TotalSeconds);
Random ran = new Random();
return nTime + ran.Next(0, 9999);
}
}
#endregion
//##############################[POS Client 기능 구현]#############################################//
#region Punchh POS Config
public class PunchhConfiguration
{
/// <summary>
/// The Location Key.
/// </summary>
public string LocationKey { get; set; }
/// <summary>
/// Punchh Environment.
/// </summary>
public PunchhEnvironment Environment { get; set; }
/// <summary>
/// Client Secret.
/// </summary>
public string ClientSecret { get; set; }
/// <summary>
/// Is Retry Enabled.
/// </summary>
public bool IsRetryCalls { get; set; }
/// <summary>
/// The Region.
/// </summary>
public string Region { get; set; }
}
public enum PunchhEnvironment
{
SANDBOX,
PRODUCTION
}
#endregion
#region POS Client
public class PunchhPosClient
{
private string _locationKey { get; set; }
private string _region { get; set; } /// The Base Url.
//생성자
public PunchhPosClient(PunchhConfiguration configuration)
{
//클라이언트 부분 설정
_locationKey = configuration.LocationKey;
_region = configuration.Region;
SetAPIUrls(configuration);
//서버 연동 부분 설정
if (!string.IsNullOrEmpty(configuration.ClientSecret))
{
PunchhServiceCaller.ClientSecret = configuration.ClientSecret;
PunchhServiceCaller.IsXPchEnabled = true;
}
PunchhServiceCaller.UserAgent = PunchhLib.GetUserAgent(configuration.LocationKey);
PunchhServiceCaller.IsRetryCalls = configuration.IsRetryCalls;
}
public void SetAPIUrls(PunchhConfiguration configuration)
{
string baseUrl = string.Empty;
string dataSinkUrl = string.Empty;
switch (configuration.Region)
{
case "asia":
baseUrl = "https://posasia.punchh.com";
dataSinkUrl = "https://islasia.punchh.com";
break;
case "au":
baseUrl = "https://posau.punchh.com";
dataSinkUrl = "https://islau.punchh.com";
break;
case "eu":
baseUrl = "https://poseu.punchh.com";
dataSinkUrl = "https://isleu.punchh.com";
break;
case "uk":
baseUrl = "https://posuk.punchh.com";
dataSinkUrl = "https://isluk.punchh.com";
break;
default:
baseUrl = "https://pos.punchh.com";
dataSinkUrl = "https://isl.punchh.com";
break;
}
if (configuration.Environment == PunchhEnvironment.SANDBOX)
{
baseUrl = "https://sandbox.punchh.com";
dataSinkUrl = "https://isl-sandbox.punchh.com";
}
PunchhServiceCaller.BaseUrl = baseUrl + "/api/pos";
PunchhServiceCaller.DataSinkBaseUrl = dataSinkUrl;
}
//사용자 조회
public PunchhClientResponse<UserLookupResponse> UserLookup(UserLookupRequest requestModel)
{
try
{
NameValueCollection headers = new NameValueCollection();
headers.Add("Authorization", string.Format("Token token={0}", _locationKey));
NameValueCollection content = PunchhLib.GetNameValue<UserLookupRequest>(requestModel);//요청값 json key, value 로 변경
PunchhAPIResponse apiResponse = PunchhServiceCaller.PunchhAPIRequest(PunchhConst.USER_LOOKUP_API_URL, headers, content);
if (apiResponse.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
var resp = JsonConvert.DeserializeObject<UserLookupResponse>(apiResponse.Message);
return new PunchhClientResponse<UserLookupResponse>
{
Data = resp,
Message = apiResponse.Message,
Status = apiResponse.HttpStatusCode.ToString().ToEnum<PunchhResponseStatus>()
};
}
else
{
return new PunchhClientResponse<UserLookupResponse>
{
Data = null,
Message = apiResponse.Message,
Status = apiResponse.HttpStatusCode.ToString().ToEnum<PunchhResponseStatus>()
};
}
}
catch (WebException ex)
{
return new PunchhClientResponse<UserLookupResponse>
{
Message = ex.Message,
Status = ex.Status.ToString().ToEnum<PunchhResponseStatus>()
};
}
catch (Exception ex)
{
return new PunchhClientResponse<UserLookupResponse>
{
Data = null,
Message = "Exception.",
Status = PunchhResponseStatus.EXCEPTION
};
}
//return new PunchhResponse<UserLookupResponse>
//{
// Data = null,
// Status = PunchhResponseStatus.EXCEPTION,
// Message = "Message"
//};
}
//해피 포인트 잔액, 결제 가능 금액 조회
public PunchhClientResponse<RedemptionResponse> RedemptionPossible(RedemptionRequest requestModel)
{
try
{
NameValueCollection headers = new NameValueCollection();
headers.Add("Authorization", string.Format("Token token={0}", _locationKey));
JObject jsonObj = JObject.FromObject(requestModel);
string content = jsonObj.ToString();
PunchhAPIResponse apiResponse = PunchhServiceCaller.PunchhAPIPostRequest(PunchhConst.POSSIBLE_REDEMPTION_API_URL, headers, content);
if (apiResponse.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
var resp = JsonConvert.DeserializeObject<RedemptionResponse>(apiResponse.Message);
return new PunchhClientResponse<RedemptionResponse>
{
Data = resp,
Message = apiResponse.Message,
Status = apiResponse.HttpStatusCode.ToString().ToEnum<PunchhResponseStatus>()
};
}
else
{
return new PunchhClientResponse<RedemptionResponse>
{
Data = null,
Message = apiResponse.Message,
Status = apiResponse.HttpStatusCode.ToString().ToEnum<PunchhResponseStatus>()
};
}
}
catch (WebException ex)
{
return new PunchhClientResponse<RedemptionResponse>
{
Message = ex.Message,
Status = ex.Status.ToString().ToEnum<PunchhResponseStatus>()
};
}
catch (Exception ex)
{
return new PunchhClientResponse<RedemptionResponse>
{
Data = null,
Message = "Exception.",
Status = PunchhResponseStatus.EXCEPTION
};
}
}
//해피 포인트 결제
public PunchhClientResponse<RedemptionResponse> RedemptionCreate(RedemptionRequest requestModel)
{
try
{
NameValueCollection headers = new NameValueCollection();
headers.Add("Authorization", string.Format("Token token={0}", _locationKey));
JObject jsonObj = JObject.FromObject(requestModel);
string content = jsonObj.ToString();
PunchhAPIResponse apiResponse = PunchhServiceCaller.PunchhAPIPostRequest(PunchhConst.CREATE_OR_VOID_REDEMPTION_API_URL, headers, content);
if (apiResponse.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
var resp = JsonConvert.DeserializeObject<RedemptionResponse>(apiResponse.Message);
return new PunchhClientResponse<RedemptionResponse>
{
Data = resp,
Message = apiResponse.Message,
Status = apiResponse.HttpStatusCode.ToString().ToEnum<PunchhResponseStatus>()
};
}
else
{
return new PunchhClientResponse<RedemptionResponse>
{
Data = null,
Message = apiResponse.Message,
Status = apiResponse.HttpStatusCode.ToString().ToEnum<PunchhResponseStatus>()
};
}
}
catch (WebException ex)
{
return new PunchhClientResponse<RedemptionResponse>
{
Message = ex.Message,
Status = ex.Status.ToString().ToEnum<PunchhResponseStatus>()
};
}
catch (Exception ex)
{
return new PunchhClientResponse<RedemptionResponse>
{
Data = null,
Message = "Exception.",
Status = PunchhResponseStatus.EXCEPTION
};
}
}
// 해피 포인트 적립
public PunchhClientResponse<CheckinResponse> UserCheckin(CheckinRequest requestModel)
{
try
{
NameValueCollection headers = new NameValueCollection();
headers.Add("Authorization", string.Format("Token token={0}", _locationKey));
JObject jsonObj = JObject.FromObject(requestModel);
string content = jsonObj.ToString();
PunchhAPIResponse apiResponse = PunchhServiceCaller.PunchhAPIPostRequest(PunchhConst.CHECKIN_API_URL, headers, content);
if (apiResponse.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
var resp = JsonConvert.DeserializeObject<CheckinResponse>(apiResponse.Message);
return new PunchhClientResponse<CheckinResponse>
{
Data = resp,
Message = apiResponse.Message,
Status = apiResponse.HttpStatusCode.ToString().ToEnum<PunchhResponseStatus>()
};
}
else
{
return new PunchhClientResponse<CheckinResponse>
{
Data = null,
Message = apiResponse.Message,
Status = apiResponse.HttpStatusCode.ToString().ToEnum<PunchhResponseStatus>()
};
}
}
catch (WebException ex)
{
return new PunchhClientResponse<CheckinResponse>
{
Message = ex.Message,
Status = ex.Status.ToString().ToEnum<PunchhResponseStatus>()
};
}
catch (Exception ex)
{
return new PunchhClientResponse<CheckinResponse>
{
Data = null,
Message = "Exception.",
Status = PunchhResponseStatus.EXCEPTION
};
}
}
// 해피 포인트 결제 취소
public PunchhClientResponse<string> VoidRedemption(VoidRedemptionRequest requestModel)
{
try
{
NameValueCollection headers = new NameValueCollection();
headers.Add("Authorization", string.Format("Token token={0}", _locationKey));
NameValueCollection content = PunchhLib.GetNameValue<VoidRedemptionRequest>(requestModel);
PunchhAPIResponse apiResponse = PunchhServiceCaller.PunchhAPIDeleteRequest(PunchhConst.CREATE_OR_VOID_REDEMPTION_API_URL, headers, content);
return new PunchhClientResponse<string>
{
Data = string.Empty,
Message = apiResponse.Message,
Status = apiResponse.HttpStatusCode.ToString().ToEnum<PunchhResponseStatus>()
};
}
catch (WebException ex)
{
return new PunchhClientResponse<string>
{
Message = ex.Message,
Status = ex.Status.ToString().ToEnum<PunchhResponseStatus>()
};
}
catch (Exception e)
{
return new PunchhClientResponse<string>
{
Data = null,
Message = "Exception : ",
Status = PunchhResponseStatus.EXCEPTION
};
}
}
}
#endregion
#region Punchh Server API POS Client
//각 기능 응답 제네릭 클래스
//API 에서 리턴 되어 오는 형식 그대로 에서 각 요청 메뉴 별로 형태 변경
public class PunchhClientResponse<T>
{
public T Data { get; set; }
public PunchhResponseStatus Status { get; set; }
public string Message { get; set; }
}
public enum PunchhResponseStatus
{
OK = 200,
CREATED = 201,
ACCEPTED = 202,
NotModified = 304,
NOTFOUND = 404,
BADREQUEST = 400,
UNAUTHORIZED = 401,
PRECONDITIONFAILED = 412,
UNPROCESSABLE_ENTITY = 422,
INTERNAL_SERVER_ERROR = 500,
EXCEPTION = -1,
PARAMETERS_NOT_SET = -2,
TIMEOUT = -3,
NAMERESOLUTIONFAILURE = -4,
CONNECTFAILURE = -5
}
#endregion
//##############################[POS Client 기능 구현 끝]##########################################//
//###############################[Punchh Server API 호출]##########################################//
#region Punchh Server API
public static class PunchhServiceCaller
{
#region
//속성의 값들은 PunchhPosClient 에서 호출 시 설정함.
public static string BaseUrl { get; set; }
public static string DataSinkBaseUrl { get; set; }
public static bool IsXPchEnabled { get; set; }
public static string ClientSecret { get; set; }//현재는 사용 안 되는 함.
public static string UserAgent { get; set; }
public static bool IsRetryCalls { get; set; } // 서버 오류 발생시 재요청 여부
public static bool IsDataSinkCall { get; set; } // Is Receipt Datasink Call.
#endregion
#region Request API
public static PunchhAPIResponse PunchhAPIRequest(string apiURL, NameValueCollection headers = null, NameValueCollection content = null)
{
int retryCall = 3;
while (true)
{
try
{
//요청
#region
string queryString = string.Empty;
if (content != null)
{
queryString = string.Join("&", content.AllKeys.Where(key => !string.IsNullOrWhiteSpace(content[key])).Select(key => string.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(key)
, System.Web.HttpUtility.UrlEncode(content[key])
)));
queryString = "?" + queryString;
}
string punchhAPI_URL = BaseUrl + apiURL + queryString;
HttpWebRequest.DefaultCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Revalidate);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(punchhAPI_URL);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "GET";
request.Timeout = 30000;
request.UserAgent = PunchhLib.GetUserAgent(UserAgent);
request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Revalidate);
if (IsXPchEnabled && string.IsNullOrEmpty(ClientSecret))//ClientSecret 가 사용 되지 않음므로 해당 사항 없음
{
Uri uri = new Uri(punchhAPI_URL);
string sPath = uri.AbsolutePath;
string sBody = queryString;
string sValue = sPath + sBody;
string xPchDigest = PunchhLib.GenerateXPchDigest(sValue, ClientSecret);
headers.Add("x-pch-digest", xPchDigest);
}
if (headers != null)
{
foreach (var key in headers.AllKeys)
{
request.Headers[key] = headers[key];//웹통신에 header 추가
}
}
#endregion
//응답
#region
string responseMessage = string.Empty;
HttpWebResponse response = null;
response = (HttpWebResponse)request.GetResponse();
using (Stream stream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
responseMessage = reader.ReadToEnd();
}
}
#endregion
retryCall = 0;
return new PunchhAPIResponse
{
Message = responseMessage,
HttpStatusCode = response.StatusCode,
Headers = response.Headers
};
}
catch (WebException ex)
{
retryCall--;
if (ex.Response != null)
{
#region
var webResp = (HttpWebResponse)ex.Response;
var respMsg = new StreamReader(webResp.GetResponseStream()).ReadToEnd();
if (IsRetryCalls && retryCall > 0 && webResp.StatusCode == HttpStatusCode.InternalServerError)
continue;
retryCall = 0;
string filteredRespMsg = string.Empty;
try
{
filteredRespMsg = (respMsg.Contains("error")) ? JsonConvert.DeserializeObject<PunchhErrorResponse>(respMsg).Error.Message :
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JArray>(respMsg)[0].ToString();
}
catch (Exception e)
{
//e.Message;
}
return new PunchhAPIResponse
{
Message = string.IsNullOrEmpty(filteredRespMsg) ? ex.Message : filteredRespMsg,
HttpStatusCode = webResp.StatusCode,
Headers = webResp.Headers
};
#endregion
}
else
{
if (IsRetryCalls && retryCall > 0)
continue;
else
throw ex;
}
}
catch (Exception ex)
{
throw ex;
}
}//while end
}
public static PunchhAPIResponse PunchhAPIPostRequest(string apiURL, NameValueCollection headers, string content)
{
int retryCall = 3;
while (true)
{
try
{
#region
string punchhAPI_URL = BaseUrl + apiURL;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(punchhAPI_URL);
request.ContentType = "application/json";
request.Method = "POST";
request.Timeout = 30000;
request.UserAgent = PunchhLib.GetUserAgent(UserAgent);
if (IsXPchEnabled && !string.IsNullOrEmpty(ClientSecret) && !IsDataSinkCall)
{
Uri uri = new Uri(punchhAPI_URL);
string sPath = uri.AbsolutePath;
string sBody = content;
string sValue = sPath + sBody;
string xPchDigest = PunchhLib.GenerateXPchDigest(sValue, ClientSecret);
headers.Add("x-pch-digest", xPchDigest);
}
if (headers != null)
{
foreach (var key in headers.AllKeys)
{
request.Headers[key] = headers[key];
}
}
// Convert post data into bytes.
byte[] contentBytes = Encoding.ASCII.GetBytes(content);
// Set post data to request stream.
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(contentBytes, 0, contentBytes.Length);
requestStream.Close();
}
string responseMessage = string.Empty;
HttpWebResponse response = null;
response = (HttpWebResponse)request.GetResponse();
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
responseMessage = reader.ReadToEnd();
// Logger.Log("Response Body: " + responseMessage, LogType.INFO);
}
retryCall = 0;
return new PunchhAPIResponse
{
Message = responseMessage,
HttpStatusCode = response.StatusCode,
Headers = response.Headers
};
#endregion
}
catch (WebException ex)
{
#region
retryCall--;
if (ex.Response != null)
{
#region
var webResp = (HttpWebResponse)ex.Response;
var respMsg = new StreamReader(webResp.GetResponseStream()).ReadToEnd();
if (IsRetryCalls && retryCall > 0 && webResp.StatusCode == HttpStatusCode.InternalServerError)
continue;
retryCall = 0;
string filteredRespMsg = string.Empty;
try
{
filteredRespMsg = (respMsg.Contains("error")) ? JsonConvert.DeserializeObject<PunchhErrorResponse>(respMsg).Error.Message :
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JArray>(respMsg)[0].ToString();
}
catch (Exception e)
{
//e.Message;
}
return new PunchhAPIResponse
{
Message = string.IsNullOrEmpty(filteredRespMsg) ? ex.Message : filteredRespMsg,
HttpStatusCode = webResp.StatusCode,
Headers = webResp.Headers
};
#endregion
}
else
{
if (IsRetryCalls && retryCall > 0)
continue;
else
throw ex;
}
#endregion
}// try end
}//while end
}
public static PunchhAPIResponse PunchhAPIDeleteRequest(string apiURL, NameValueCollection headers, NameValueCollection content)
{
int retryCall = 3;
while (true)
{
try
{
#region
string queryString = string.Empty;
if (content != null)
{
queryString = string.Join("&", content.AllKeys.Where(key => !string.IsNullOrWhiteSpace(content[key])).Select(key => string.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(key, Encoding.UTF8), System.Web.HttpUtility.UrlEncode(content[key], Encoding.UTF8))));
queryString = "?" + queryString;
}
string punchhAPI_URL = BaseUrl + apiURL + queryString;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(punchhAPI_URL);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "DELETE";
request.Timeout = 30000;
request.UserAgent = PunchhLib.GetUserAgent(UserAgent);
if (IsXPchEnabled)
{
Uri uri = new Uri(punchhAPI_URL);
string sPath = uri.AbsolutePath;
string sBody = queryString;
string sValue = sPath + sBody;
string xPchDigest = PunchhLib.GenerateXPchDigest(sValue, ClientSecret);
headers.Add("x-pch-digest", xPchDigest);
}
if (headers != null)
{
foreach (var key in headers.AllKeys)
{
request.Headers[key] = headers[key];//웹통신에 header 추가
}
}
#endregion
//응답
#region
string responseMessage = string.Empty;
HttpWebResponse response = null;
response = (HttpWebResponse)request.GetResponse();
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
responseMessage = reader.ReadToEnd();
}
#endregion
retryCall = 0;
return new PunchhAPIResponse
{
Message = responseMessage,
HttpStatusCode = response.StatusCode,
Headers = response.Headers
};
}//end try
catch (WebException ex)
{
retryCall--;
if (ex.Response != null)
{
#region
var webResp = (HttpWebResponse)ex.Response;
var respMsg = new StreamReader(webResp.GetResponseStream()).ReadToEnd();
if (IsRetryCalls && retryCall > 0 && webResp.StatusCode == HttpStatusCode.InternalServerError)
continue;
retryCall = 0;
string filteredRespMsg = string.Empty;
try
{
filteredRespMsg = (respMsg.Contains("error")) ? JsonConvert.DeserializeObject<PunchhErrorResponse>(respMsg).Error.Message :
JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JArray>(respMsg)[0].ToString();
}
catch (Exception e)
{
//e.Message;
}
return new PunchhAPIResponse
{
Message = string.IsNullOrEmpty(filteredRespMsg) ? ex.Message : filteredRespMsg,
HttpStatusCode = webResp.StatusCode,
Headers = webResp.Headers
};
#endregion
}
else
{
if (IsRetryCalls && retryCall > 0)
continue;
else
throw ex;
}
}
catch (Exception ex)
{
throw ex;
}//end catch
}//while end
}
#endregion
}
#endregion
#region Punchh Server API Response (Punchh API )
public class PunchhAPIResponse
{
public System.Net.WebHeaderCollection Headers { get; set; }
public HttpStatusCode HttpStatusCode { get; set; }
public string Message { get; set; }
}
public class PunchhErrorResponse
{
public Error Error { get; set; }
}
public class Error
{
public string Message { get; set; }
}
#endregion
//###############################[Punchh Server API 호출 끝]#######################################//
}