using DSWeb.EntityDA ;
using Newtonsoft.Json ;
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Net ;
using System.Net.Security ;
using System.Security.Cryptography ;
using System.Security.Cryptography.X509Certificates ;
using System.Text ;
using System.Web ;
using System.Linq ;
using System.Text.RegularExpressions ;
using log4net ;
using Newtonsoft.Json.Linq ;
using DSWeb.Areas.Account.DAL.Chfee_Invoice_HangXin ;
using DSWeb.MvcShipping.DAL.MsCompanysDAL ;
using DSWeb.MvcShipping.DAL.MsSysParamSet ;
using DSWeb.Areas.CommMng.DAL ;
using DSWeb.Common.DB ;
using DSWeb.Areas.Account.Models.Chfee_Invoice_HangXin ;
using DSWeb.Areas.Account.Models.Chfee_do_detail ;
using static DSWeb . Common . DB . CommonDataContext ;
using DSWeb.MvcShipping.DAL.DsSendmail ;
namespace DSWeb.Common.Helper
{
public class RuihongHelper
{
private const string apiUrlTest = "https://www.chinaeinv.com:943/igs/api/invoiceApi.jspa" ; //测试环境
private const string apiUrl = "https://www.chinaeinv.com/igs/api/invoiceApi.jspa" ; //正式环境
public RuihongHelper ( )
{
}
/// <summary>
/// 开启测试模式(使用测试环境)
/// </summary>
private bool IsTestMode = false ;
#region 对象属性
private string AppCode
{
get
{
if ( IsTestMode )
{
return "PTTEST17" ;
}
else
{
return "PT000147" ;
}
}
}
private string KeyStore
{
get
{
if ( IsTestMode )
{
return "PTTEST17.pfx" ;
}
else
{
return "PT000147.pfx" ;
}
}
}
private string KeyStorePsw
{
get
{
if ( IsTestMode )
{
return "PTTEST17" ;
}
else
{
return "vfrsedazsed" ;
}
}
}
private string ApiUrl
{
get
{
if ( IsTestMode )
{
return apiUrlTest ;
}
else
{
return apiUrl ;
}
}
}
# endregion
#region 公共方法
#region 开票
/// <summary>
/// 开票
/// </summary>
/// <param name="strParams"></param>
/// <returns></returns>
public string PostInvoice ( string strParams )
{
BasicDataRefDAL . SaveLog ( $"{strParams}" , "" , "瑞宏开票" , "发出" ) ;
var rtn = DoPostData ( strParams , "chinaeinv.api.invoice.v3.kp_async" ) ;
BasicDataRefDAL . SaveLog ( $"{rtn}" , "" , "瑞宏开票" , "返回" ) ;
return rtn ;
}
/// <summary>
/// 开票
/// </summary>
/// <param name="strParams"></param>
/// <returns></returns>
public string PostInvoice ( RuihongPostModel postModel )
{
var strJson = JsonConvert . SerializeObject ( postModel ) ;
if ( postModel . notices = = null | | postModel . notices . Count = = 0 )
{
JObject jobj = JObject . Parse ( strJson ) ;
jobj . Remove ( "notices" ) ;
strJson = jobj . ToString ( ) ;
}
return PostInvoice ( strJson ) ;
}
/// <summary>
/// 开票
/// </summary>
/// <param name="invId"></param>
/// <returns></returns>
public bool PostInvoiceRecord ( string invId , out string msg )
{
var inv = ChinvoiceDAL . GetData ( "cm.GID='" + invId + "'" ) ;
var invItems = ChinvoiceDAL . GetDetailList ( "PID='" + invId + "'" ) ;
RuihongPostModel postModel = new RuihongPostModel ( ) ;
postModel . serialNo = inv . GID ;
postModel . postTime = DateTime . Now . ToString ( "yyyy-MM-dd HH:mm:ss" ) ;
postModel . order = new RuihongPostOrderModel ( ) { orderNo = inv . GID } ;
if ( inv . RECVCURR = = "USD" )
{
postModel . dynamicParams = new { dollarAmount = inv . OTCURRAMOUNT . ToString ( ) } ;
}
RuihongPostInvoiceModel postInv = new RuihongPostInvoiceModel ( ) ;
if ( IsTestMode )
{
postInv . taxpayerCode = "91370200264807TEST4A" ;
}
else
{
//var company = MsCompanysDAL.GetNoPicData("GID='" + inv.COMPANYID + "'");
postInv . taxpayerCode = inv . TAXCODE ;
postInv . taxpayerName = inv . BILLRISES ;
postInv . taxpayerAddress = inv . ADDRESS ;
postInv . taxpayerTel = inv . OFFICEPHONE ;
}
if ( ! string . IsNullOrEmpty ( inv . PUSHEMAIL ) ) {
postModel . notices = new List < RuihongPostNoticeModel > ( ) ;
postModel . notices . Add ( new RuihongPostNoticeModel ( )
{
type = "email" ,
value = inv . PUSHEMAIL
} ) ;
}
//分拆银行和账号
for ( int idx = inv . ACCOUNT . Length - 1 ; idx > = 0 ; idx - - )
{
var idxStr = inv . ACCOUNT [ idx ] . ToString ( ) ;
if ( Regex . IsMatch ( idxStr , "[0-9\\s-]{1}" ) )
{
continue ;
}
postInv . taxpayerBankName = inv . ACCOUNT . Substring ( 0 , idx + 1 ) ;
postInv . taxpayerBankAccount = inv . ACCOUNT . Substring ( idx + 1 ) ;
break ;
}
postInv . customerCode = inv . CUSTRATENO ;
postInv . customerName = inv . INVOICECUSTNAME ;
postInv . customerAddress = inv . CUSTADDR ;
postInv . customerTel = inv . CUSTTEL ;
//分拆银行和账号
for ( int idx = inv . CUSTBANK . Length - 1 ; idx > = 0 ; idx - - )
{
var idxStr = inv . CUSTBANK [ idx ] . ToString ( ) ;
if ( Regex . IsMatch ( idxStr , "[0-9\\s-]{1}" ) )
{
continue ;
}
postInv . customerBankName = inv . CUSTBANK . Substring ( 0 , idx + 1 ) ;
postInv . customerBankAccount = inv . CUSTBANK . Substring ( idx + 1 ) ;
break ;
}
postInv . drawer = inv . OPERATORNAME ;
postInv . reviewer = inv . CHECKER ;
postInv . payee = inv . PAYEE ;
postInv . totalAmount = inv . INVAMOUNT ;
postInv . remark = inv . REMARK ;
postModel . invoice = postInv ;
postInv . items = new List < RuihongPostInvoiceItemModel > ( ) ;
foreach ( var item in invItems )
{
var goodsCode = item . GOODCODE = = null ? string . Empty : item . GOODCODE ;
goodsCode = goodsCode . PadRight ( 19 , '0' ) ;
//零税率标识。1:免税,2:不征税,3:普通零税率。税率为零的情况下, 如果不传, 则默认为1:免税。
var 零 税 率 标 识 = "1" ;
if ( item . TAXRATE > 0 )
{
零 税 率 标 识 = null ;
}
else
{
if ( item . ZTAXTYPE = = "免税" ) 零 税 率 标 识 = "1" ;
if ( item . ZTAXTYPE = = "不征税" ) 零 税 率 标 识 = "2" ;
if ( item . ZTAXTYPE = = "普通零税率" ) 零 税 率 标 识 = "3" ;
}
postInv . items . Add ( new RuihongPostInvoiceItemModel ( )
{
type = "0" ,
name = item . GOODSNAMEREF ,
spec = item . SPEC ,
uom = item . UNIT ,
quantity = item . PKGS ,
taxRate = item . TAXRATE / 100 ,
amount = Math . Round ( item . AMOUNT + item . TAX , 2 , MidpointRounding . AwayFromZero ) ,
price = item . PRICE ,
catalogCode = goodsCode ,
preferentialPolicyFlg = item . ISUSEPREF ,
addedValueTaxFlg = item . DEFREMARK ,
zeroTaxRateFlg = 零 税 率 标 识
} ) ;
}
string rtn = PostInvoice ( postModel ) ;
var rtnObj = JsonConvert . DeserializeObject < RuihongRespCommon > ( rtn ) ;
if ( rtnObj . code = = "0" )
{
T_ALL_DA T_ALL_DA = new EntityDA . T_ALL_DA ( ) ;
var blUpSQL = "update ch_fee_invoice set INVOICESERIALNUM='" + rtnObj . serialNo + "',EINVOICESTATE='1' where GID='" + invId + "' " ;
bool bl = T_ALL_DA . GetExecuteSqlCommand ( blUpSQL ) ;
//inv.SerialNo = rtnObj.serialNo;
//inv.Status = InvoiceRecord.StatusPost;
//invDB.SaveChanges();
msg = rtnObj . message ;
return true ;
}
else
{
T_ALL_DA T_ALL_DA = new EntityDA . T_ALL_DA ( ) ;
var blUpSQL = "update ch_fee_invoice set EINVOICESTATE='1' where GID='" + invId + "' " ;
bool bl = T_ALL_DA . GetExecuteSqlCommand ( blUpSQL ) ;
msg = rtnObj . message ;
return false ;
}
}
# endregion
#region 查票
/// <summary>
/// 查票
/// </summary>
/// <param name="strParams"></param>
/// <returns></returns>
public string QueryInvoice ( string strParams )
{
BasicDataRefDAL . SaveLog ( $"{strParams}" , "" , "瑞宏查票" , "发出" ) ;
//logger.Debug($"瑞宏查票:{strParams}");
var rtn = DoPostData ( strParams , "chinaeinv.api.invoice.v3.cx" ) ;
BasicDataRefDAL . SaveLog ( $"{rtn}" , "" , "瑞宏查票返回" , "返回" ) ;
//logger.Debug($"瑞宏查票返回:{rtn}");
return rtn ;
}
/// <summary>
/// 根据操作流水号单个查询
/// </summary>
/// <param name="strParams">单个操作流水号</param>
/// <returns></returns>
public string QueryInvoiceSerialNo ( params string [ ] serNO )
{
if ( serNO = = null | | serNO . Length = = 0 )
{
return null ;
}
RuihongQueryModel reqModel = new RuihongQueryModel ( ) ;
reqModel . serialNo = Guid . NewGuid ( ) . ToString ( ) ;
reqModel . postTime = DateTime . Now . ToString ( "yyyy-MM-dd HH:mm:ss" ) ;
reqModel . criteria = new List < RuihongQueryInner > ( ) ;
foreach ( var item in serNO )
{
reqModel . criteria . Add ( new RuihongQueryInner ( )
{
name = "singlesSerialNo" ,
value = item
} ) ;
}
return QueryInvoice ( JsonConvert . SerializeObject ( reqModel ) ) ;
}
/// <summary>
/// 查询发票开出
/// </summary>
/// <param name="invId"></param>
/// <param name="msg"></param>
/// <returns></returns>
public bool QueryInvoiceRecord ( string invId , string INVOICESERIALNUM , out string msg )
{
//var inv = ChinvoiceDAL.GetData("cm.GID='" + invId + "'");
if ( string . IsNullOrEmpty ( INVOICESERIALNUM ) )
{
msg = "还未成功进行平台开票,无可读数据" ;
return false ;
}
string rtn = QueryInvoiceSerialNo ( INVOICESERIALNUM ) ;
var rtnObj = JsonConvert . DeserializeObject < RuihongRespQuery > ( rtn ) ;
if ( rtnObj . code = = "0" )
{
var InvCode = rtnObj . invoices [ 0 ] . code . Substring ( 0 , 12 ) ;
var InvNum = rtnObj . invoices [ 0 ] . code . Substring ( 12 ) ;
var PdfUrl = rtnObj . invoices [ 0 ] . pdfUnsignedUrl ;
PdfUrl = PdfUrl . Replace ( "Unsigned" , "" ) ;
var PictureUrl = rtnObj . invoices [ 0 ] . viewUrl ;
var InvoiceDate = Convert . ToDateTime ( rtnObj . invoices [ 0 ] . generateTime ) . ToString ( "yyyy-MM-dd" ) ;
var needautolock = MsSysParamSetDAL . GetSysParam ( "INVOICEAUTOLOCK" ) . isnullortrue ( ) ;
T_ALL_DA T_ALL_DA = new EntityDA . T_ALL_DA ( ) ;
var blUpSQL = "update ch_fee_invoice set INVOICECODE='" + InvCode + "',INVOICENO='" + InvNum + "',INVOICEINFOURL='" + PictureUrl + "',INVOICEPDFURL='" + PdfUrl + "',INVOICEMAKETIME='" + InvoiceDate + "',EINVOICESTATE='2' where GID='" + invId + "' " ;
if ( needautolock )
{
blUpSQL = "update ch_fee_invoice set BILLSTATUS=1,INVOICECODE='" + InvCode + "',INVOICENO='" + InvNum + "',INVOICEINFOURL='" + PictureUrl + "',INVOICEPDFURL='" + PdfUrl + "',INVOICEMAKETIME='" + InvoiceDate + "',EINVOICESTATE='2' where GID='" + invId + "' " ;
}
bool bl = T_ALL_DA . GetExecuteSqlCommand ( blUpSQL ) ;
//读取成功后,发送邮件
//首先确定目标邮箱 如果该客户有邮件地址 使用这个邮件地址
//如果没有 寻找 销售 的邮件地址
//如果还没有 不发送邮件
SendInvMail ( invId ) ;
//读取成功后,发送邮件
//if (inv.PushMode == "0" && !string.IsNullOrEmpty(inv.Email))
//{
// MailHelper.SendMailInvoiceRecord(inv.GID);
//}
msg = rtnObj . message ;
return true ;
}
else
{
msg = rtnObj . message ;
return false ;
}
}
public class InvMailInfo2 : InvMailInfo
{
public string MBLNO { get ; set ; }
public string CUSTOMERNAME { get ; set ; }
public string ETD { get ; set ; }
public string CURRENCY { get ; set ; }
public string AMOUNT { get ; set ; }
public string INVOICENO { get ; set ; }
public string pdfurl { get ; set ; }
public string mailTitle { get ; set ; }
public string mailBody { get ; set ; }
public InvMailInfo2 ( ) { }
public InvMailInfo2 ( ChInvoice_HangXin inv , List < Chfee_do_detail > invItems )
{
MBLNO = "" ;
ETD = "" ;
CUSTOMERNAME = inv . CUSTOMERNAME ;
CURRENCY = inv . CURRENCY ;
AMOUNT = inv . AMOUNT . ToString ( ) ;
INVOICENO = inv . INVOICENO ;
pdfurl = inv . INVOICEPDFURL ;
foreach ( var item in invItems )
{
if ( MBLNO . IndexOf ( item . MBLNO ) < 0 )
{
if ( MBLNO ! = "" ) MBLNO + = " " ;
MBLNO + = item . MBLNO ;
}
if ( ETD . IndexOf ( item . ETD ) < 0 )
{
if ( ETD ! = "" ) ETD + = " " ;
ETD + = item . ETD ;
}
}
CommonDataContext cdc = new CommonDataContext ( ) ;
var customer = cdc . info_client . FirstOrDefault ( x = > x . SHORTNAME = = inv . CUSTOMERNAME ) ;
if ( ! string . IsNullOrWhiteSpace ( customer . EMAIL ) )
{
EMAIL = customer . EMAIL ;
}
else
{
var SALE = invItems [ 0 ] . SALE ;
var _user = cdc . VW_user . FirstOrDefault ( x = > x . SHOWNAME = = SALE ) ;
if ( ! string . IsNullOrWhiteSpace ( _user . EMAIL1 ) )
{
EMAIL = _user . EMAIL1 ;
}
}
mailTitle = "" ;
mailTitle + = "提单号:" + MBLNO ;
mailTitle + = "---" ;
mailTitle + = "客户名称:" + CUSTOMERNAME ;
mailTitle + = "---" ;
mailTitle + = "开船日期:" + ETD ;
mailTitle + = "---" ;
mailTitle + = "币别:" + CURRENCY ;
mailTitle + = "---" ;
mailTitle + = "金额:" + AMOUNT ;
mailTitle + = "---" ;
mailTitle + = "发票号:" + INVOICENO ;
mailBody = "" ;
mailBody + = "提单号:" + MBLNO ;
mailBody + = "<br/>" ;
mailBody + = "客户名称:" + CUSTOMERNAME ;
mailBody + = "<br/>" ;
mailBody + = "开船日期:" + ETD ;
mailBody + = "<br/>" ;
mailBody + = "币别:" + CURRENCY ;
mailBody + = "<br/>" ;
mailBody + = "金额:" + AMOUNT ;
mailBody + = "<br/>" ;
mailBody + = "发票号:" + INVOICENO ;
mailBody + = "<br/>" ;
mailBody + = "< a href = \"" + pdfurl + "\" > 发票文件地址 </ a >" ;
}
}
private void SendInvMail ( string invId )
{
var inv = ChinvoiceDAL . GetData ( "cm.GID='" + invId + "'" ) ;
var invItems = ChinvoiceDAL . GetBodyList ( " c.BILLNO='" + inv . BILLNO + "'" ) ;
var invinfo = new InvMailInfo2 ( inv , invItems ) ;
if ( ! string . IsNullOrWhiteSpace ( invinfo . EMAIL ) )
{
SendEmail se = new SendEmail ( invinfo . EMAIL , "" , "" , "" , invinfo . mailTitle , invinfo . mailBody , false ) ;
string filePath = invinfo . pdfurl ;
se . Attachments ( filePath ) ;
se . SetSmtp ( "admin@dongshengsoft.com" , "ds!@#)(*" , "smtpcom.263xmail.com" , 465 , false , System . Net . Mail . MailPriority . Normal ) ; //必须在所有参数设置完后调用此方法
}
}
# endregion
#region 冲红
/// <summary>
/// 冲红
/// </summary>
/// <param name="strParams"></param>
/// <returns></returns>
public string RedInvoice ( string strParams )
{
BasicDataRefDAL . SaveLog ( $"{strParams}" , "" , "瑞宏冲红" , "发出" ) ;
var rtn = DoPostData ( strParams , "chinaeinv.api.invoice.v3.ch_async" ) ;
BasicDataRefDAL . SaveLog ( $"{rtn}" , "" , "瑞宏冲红返回" , "返回" ) ;
return rtn ;
}
/// <summary>
/// 冲红
/// </summary>
/// <param name="redModel"></param>
/// <returns></returns>
public string RedInvoice ( RuihongRedInvoiceModel redModel )
{
return RedInvoice ( JsonConvert . SerializeObject ( redModel ) ) ;
}
/// <summary>
/// 冲红
/// </summary>
/// <param name="invId"></param>
/// <returns></returns>
public bool RedInvoiceRecord ( string invId , out string msg )
{
var inv = ChinvoiceDAL . GetData ( "cm.GID='" + invId + "'" ) ;
//var invItems = ChinvoiceDAL.GetDetailList("PID='" + invId + "'");
RuihongRedInvoiceModel redModel = new RuihongRedInvoiceModel ( ) ;
redModel . serialNo = inv . GID ;
redModel . postTime = DateTime . Now . ToString ( "yyyy-MM-dd HH:mm:ss" ) ;
redModel . originalCode = inv . REDCODE + inv . REDNUM ;
redModel . reason = "开票有误" ;
string rtn = RedInvoice ( redModel ) ;
var rtnObj = JsonConvert . DeserializeObject < RuihongRespCommon > ( rtn ) ;
if ( rtnObj . code = = "0" )
{
//inv.SerialNo = rtnObj.serialNo;
//inv.Status = InvoiceRecord.StatusPost;
//invDB.SaveChanges();
T_ALL_DA T_ALL_DA = new EntityDA . T_ALL_DA ( ) ;
var blUpSQL = "update ch_fee_invoice set INVOICESERIALNUM='" + rtnObj . serialNo + "',EINVOICESTATE='2' where GID='" + invId + "' " ;
bool bl = T_ALL_DA . GetExecuteSqlCommand ( blUpSQL ) ;
msg = rtnObj . message ;
return true ;
}
else
{
msg = rtnObj . message ;
return false ;
}
}
# endregion
public string DoPostData ( string kpParams , string cmd )
{
//appCode
string appcode = UrlEncode ( AppCode , Encoding . UTF8 ) ;
//cmdName
string cmdName = UrlEncode ( cmd , Encoding . UTF8 ) ;
//sign
string sign = UrlEncode ( GetSign ( kpParams ) , Encoding . UTF8 ) ;
//URL
StringBuilder Url = new StringBuilder ( ) ;
Url . Append ( ApiUrl ) ;
Url . Append ( "?sign=" + sign ) ;
Url . Append ( "&cmdName=" + cmdName ) ;
Url . Append ( "&appCode=" + appcode ) ;
//Post 请求URL
HttpWebRequest request = null ;
HttpWebResponse response = null ;
try
{
//设置最大连接数
ServicePointManager . DefaultConnectionLimit = 200 ;
//设置https验证方式
if ( ApiUrl . StartsWith ( "https" , StringComparison . OrdinalIgnoreCase ) )
{
ServicePointManager . ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback ( CheckValidationResult ) ;
}
request = WebRequest . Create ( Url . ToString ( ) ) as HttpWebRequest ;
byte [ ] requestBytes = Encoding . GetEncoding ( "UTF-8" ) . GetBytes ( kpParams ) ;
request . Method = "POST" ;
request . Timeout = 180 * 1000 ;
request . ContentType = "application/json;charset=UTF-8" ;
request . ContentLength = requestBytes . Length ;
using ( Stream requestStream = request . GetRequestStream ( ) )
{
requestStream . Write ( requestBytes , 0 , requestBytes . Length ) ;
requestStream . Close ( ) ;
}
//获取响应报文
response = request . GetResponse ( ) as HttpWebResponse ;
using ( StreamReader reader = new StreamReader ( request . GetResponse ( ) . GetResponseStream ( ) , Encoding . GetEncoding ( "UTF-8" ) ) )
{
return reader . ReadToEnd ( ) . Trim ( ) ;
}
}
catch ( Exception ex )
{
return ex . Message ;
}
finally
{
//关闭连接和流
if ( response ! = null )
{
response . Close ( ) ;
}
if ( request ! = null )
{
request . Abort ( ) ;
}
}
}
# endregion
#region 私有方法
private bool CheckValidationResult ( object sender , X509Certificate certificate , X509Chain chain , SslPolicyErrors errors )
{
return true ;
}
/// <summary>
/// UrlEncode
/// </summary>
/// <param name="temp">要转码的文本</param>
/// <param name="encoding">编码</param>
/// <returns></returns>
private string UrlEncode ( string temp , Encoding encoding )
{
StringBuilder stringBuilder = new StringBuilder ( ) ;
for ( int i = 0 ; i < temp . Length ; i + + )
{
string t = temp [ i ] . ToString ( ) ;
string k = HttpUtility . UrlEncode ( t , encoding ) ;
if ( t = = k )
{
stringBuilder . Append ( t ) ;
}
else
{
stringBuilder . Append ( k . ToUpper ( ) ) ;
}
}
return stringBuilder . ToString ( ) ;
}
/// <summary>
/// 数字签名
/// </summary>
/// <returns></returns>
private string GetSign ( string kpParams )
{
try
{
var keyStorePath = Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , KeyStore ) ;
//logger.Debug($"keyStorePath:{keyStorePath}");
//logger.Debug($"KeyStorePsw:{KeyStorePsw}");
X509Certificate2 x = new X509Certificate2 ( keyStorePath , KeyStorePsw , X509KeyStorageFlags . Exportable ) ;
RSACryptoServiceProvider rsa = x . PrivateKey as RSACryptoServiceProvider ;
byte [ ] data = Encoding . UTF8 . GetBytes ( kpParams ) ;
RSACryptoServiceProvider privateKey1 = new RSACryptoServiceProvider ( ) ;
privateKey1 . ImportParameters ( rsa . ExportParameters ( true ) ) ;
byte [ ] sign = privateKey1 . SignData ( data , "MD5" ) ;
string strSign = Convert . ToBase64String ( sign ) ;
string s1 = strSign . Substring ( 0 , 76 ) ;
string s2 = strSign . Substring ( 76 * 1 , 76 ) ;
string s3 = strSign . Substring ( 76 * 2 ) ;
string resultSign = UrlEncode ( s1 , Encoding . UTF8 ) + "%0D%0A"
+ UrlEncode ( s2 , Encoding . UTF8 ) + "%0D%0A"
+ UrlEncode ( s3 , Encoding . UTF8 ) ;
return resultSign ;
}
catch ( Exception ex )
{
var excep = ex ;
while ( excep ! = null )
{
//logger.Error(excep.Message);
//logger.Error(excep.StackTrace);
excep = excep . InnerException ;
}
return string . Empty ;
}
}
# endregion
}
#region 交互对象
#region 开票请求
public class RuihongPostModel
{
/// <summary>
/// 是 50 操作流水号。传入重复的操作流水号则认为是重复操作。
/// </summary>
public string serialNo { get ; set ; }
/// <summary>
/// 是 19 请求发送时间。格式为yyyy-MM-dd HH:mm:ss。
/// </summary>
public string postTime { get ; set ; }
/// <summary>
/// 是 订单信息。
/// </summary>
public RuihongPostOrderModel order { get ; set ; }
/// <summary>
/// 是 发票信息。
/// </summary>
public RuihongPostInvoiceModel invoice { get ; set ; }
/// <summary>
/// 否 3 通知方式列表, 最多3条。
/// </summary>
public List < RuihongPostNoticeModel > notices { get ; set ; }
/// <summary>
/// 否 20 扩展参数。一组Key-Value形式的数据, 会在响应报文中回传给调用方, 由调用者和瑞宏网双方根据实际情况协商使用。
/// </summary>
public object extendedParams { get ; set ; }
/// <summary>
/// 否 自定义参数。一组Key-Value形式的数据, key值: callbackUrl, Value为回调地址“http://wwww.***.com/test/invoice”
/// </summary>
public object dynamicParams { get ; set ; }
}
public class RuihongPostOrderModel
{
/// <summary>
/// 是 50 订单编号。
/// </summary>
public string orderNo { get ; set ; }
/// <summary>
/// 否 100 消费者的用户名。
/// </summary>
public string account { get ; set ; }
/// <summary>
/// 否 250 货物配送地址。
/// </summary>
public string address { get ; set ; }
/// <summary>
/// 否 消费者电话号码。手机号码或区号-固定电话号码。
/// </summary>
public string tel { get ; set ; }
/// <summary>
/// 否 消费者电子邮件地址。电子邮件格式。
/// </summary>
public string email { get ; set ; }
}
public class RuihongPostInvoiceItemModel
{
/// <summary>
/// 是 1 发票行性质 0 正常行、1 折扣行、2 被 折扣行。
/// </summary>
public string type { get ; set ; }
/// <summary>
/// 否 50 商品编码。
/// </summary>
public string code { get ; set ; }
/// <summary>
/// 是 90 商品名称。可在每一行商品下加入折扣行,折扣行商品名称与被折扣商品名称一致,金额和税额栏以负数填写,税率与被折扣行商品税率相同,其它栏不填写。
/// </summary>
public string name { get ; set ; }
/// <summary>
/// 否 40 规格型号。
/// </summary>
public string spec { get ; set ; }
/// <summary>
/// 两者要么都为空,要么都不为空。 18(整)6(小) 商品单价。必须等于amount/quantity的四舍五入值。
/// </summary>
public decimal price { get ; set ; }
/// <summary>
/// 两者要么都为空,要么都不为空。 18(整)6(小) 数量。必须大于等于0.000001。
/// </summary>
public decimal quantity { get ; set ; }
/// <summary>
/// 否 20 单位。
/// </summary>
public string uom { get ; set ; }
/// <summary>
/// 是 6(小) 税率。只能为0、 0.03、0.04、0.06、0.10、0.11、0.16、0.17。
/// </summary>
public decimal taxRate { get ; set ; }
/// <summary>
/// 是 18(整)2(小) 税价合计金额。
/// </summary>
public decimal amount { get ; set ; }
/// <summary>
/// 是 50 商品分类编码。目前的分类编码为19位, 不足19位的在后面补0。
/// </summary>
public string catalogCode { get ; set ; }
/// <summary>
/// 否 1 优惠政策标识。0:不使用,1:使用。
/// </summary>
public string preferentialPolicyFlg { get ; set ; }
/// <summary>
/// 否 50 增值税特殊管理( 当优惠政策标识为1时必填) 。
/// </summary>
public string addedValueTaxFlg { get ; set ; }
/// <summary>
/// 否 1 零税率标识。1:免税,2:不征税,3:普通零税率。税率为零的情况下, 如果不传, 则默认为3:普通零税率。
/// </summary>
public string zeroTaxRateFlg { get ; set ; }
}
public class RuihongPostInvoiceModel
{
/// <summary>
/// 是 20 销货方纳税人识别号。
/// </summary>
public string taxpayerCode { get ; set ; }
/// <summary>
/// 否 100 销货方纳税人名称
/// </summary>
public string taxpayerName { get ; set ; }
/// <summary>
/// 否 79 销货方地址。如果填写则使用填写的信息,否则使用纳税人注册时预留的信息。
/// </summary>
public string taxpayerAddress { get ; set ; }
/// <summary>
/// 否 20 销货方电话。
/// </summary>
public string taxpayerTel { get ; set ; }
/// <summary>
/// 否 69 销货方开户银行。
/// </summary>
public string taxpayerBankName { get ; set ; }
/// <summary>
/// 否 30 销货方银行账号。
/// </summary>
public string taxpayerBankAccount { get ; set ; }
/// <summary>
/// 是 100 购货方名称,即发票抬头。
/// </summary>
public string customerName { get ; set ; }
/// <summary>
/// 否 20 购货方纳税人识别号或者个人身份证号
/// </summary>
public string customerCode { get ; set ; }
/// <summary>
/// 否 79 购货方地址。
/// </summary>
public string customerAddress { get ; set ; }
/// <summary>
/// 否 20 购货方电话。
/// </summary>
public string customerTel { get ; set ; }
/// <summary>
/// 否 69 购货方开户银行。
/// </summary>
public string customerBankName { get ; set ; }
/// <summary>
/// 否 30 购货方银行账号。
/// </summary>
public string customerBankAccount { get ; set ; }
/// <summary>
/// 否 2 开票类型。p:电子增值税普通发票(默认) ps:电子收购发票 py: 成品油
/// </summary>
public string invoiceType { get ; set ; }
/// <summary>
/// 否 50 店铺编号
/// </summary>
public string shopCode { get ; set ; }
/// <summary>
/// 否 50 店铺名称
/// </summary>
public string shopName { get ; set ; }
/// <summary>
/// 否 50 支付方式
/// </summary>
public string payType { get ; set ; }
/// <summary>
/// 否 50 支付流水号
/// </summary>
public string payBillNo { get ; set ; }
/// <summary>
/// 是 8 开票人。
/// </summary>
public string drawer { get ; set ; }
/// <summary>
/// 否 8 收款人。
/// </summary>
public string payee { get ; set ; }
/// <summary>
/// 否 8 复核人。
/// </summary>
public string reviewer { get ; set ; }
/// <summary>
/// 是 18(整)2(小) 税价合计金额。必须大于等于0.01元;必须等于发票明细合计金额;必须小于等于在税务局进行票种核定时确定的单张发票开票限额。
/// </summary>
public decimal totalAmount { get ; set ; }
/// <summary>
/// 否 130 发票备注。
/// </summary>
public string remark { get ; set ; }
/// <summary>
/// 是 100 发票项目明细列表。每张发票最多一百条。
/// </summary>
public List < RuihongPostInvoiceItemModel > items { get ; set ; }
}
public class RuihongPostNoticeModel
{
/// <summary>
/// 是 通知类型。短信: sms; 电子邮件: email。
/// </summary>
public string type { get ; set ; }
/// <summary>
/// 是 通知类型为短信时,必须为手机号码;通知类型为电子邮件时,必须为邮件地址。
/// </summary>
public string value { get ; set ; }
}
# endregion
#region 查票请求
public class RuihongQueryModel
{
public string serialNo { get ; set ; }
public string postTime { get ; set ; }
public List < RuihongQueryInner > criteria { get ; set ; }
}
public class RuihongQueryInner
{
public string name { get ; set ; }
public string value { get ; set ; }
}
# endregion
#region 冲红请求
public class RuihongRedInvoiceModel
{
/// <summary>
/// 是 50 操作流水号。传入重复的操作流水号则认为是重复操作。
/// </summary>
public string serialNo { get ; set ; }
/// <summary>
/// 是 19 请求发送时间。格式为yyyy-MM-dd HH:mm:ss。
/// </summary>
public string postTime { get ; set ; }
/// <summary>
/// 是 20 原发票代码+原发票号码。
/// </summary>
public string originalCode { get ; set ; }
/// <summary>
/// 是 250 冲红原因。
/// </summary>
public string reason { get ; set ; }
/// <summary>
/// 否 3 通知方式列表。
/// </summary>
public List < RuihongPostNoticeModel > notices { get ; set ; }
/// <summary>
/// 否 100 发票项目明细列表。每张发票最多一百条。如果为空则按照原发票金额和明细全额冲红。如果不为空则按照该明细和金额进行部分冲红。
/// </summary>
public List < RuihongPostInvoiceItemModel > items { get ; set ; }
}
# endregion
#region 返回
public class RuihongRespCommon
{
public string serialNo { get ; set ; }
public string postTime { get ; set ; }
public string code { get ; set ; }
public string message { get ; set ; }
}
public class RuihongRespQuery : RuihongRespCommon
{
public List < RuihongRespQueryInner > invoices { get ; set ; }
}
public class RuihongRespQueryInner
{
public string orderNo { get ; set ; }
public string code { get ; set ; }
public string checkCode { get ; set ; }
public string fiscalCode { get ; set ; }
public string status { get ; set ; }
public string generateTime { get ; set ; }
public string pdfUnsignedUrl { get ; set ; }
public string viewUrl { get ; set ; }
public string relatedCode { get ; set ; }
public string validReason { get ; set ; }
public string validTime { get ; set ; }
}
# endregion
# endregion
}