1501 lines
54 KiB
C#
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 호출 끝]#######################################//
|
|||
|
}
|