C#¶
简介¶
为了提高客户的接入体验,特提供封装的开发SDK,使用本SDK将极大的简化开发者的工作,开发者将无需考虑通信、签名、验签等,只需要关注业务参数的拼装。
版本要求¶
.Net Framework 4.0以上
接入方法¶
下载 SDK
下载文件里包含 sdk 、 libs 、 BasePayDemo 三个目录。sdk 目录下为待添加到项目中的sdk依赖库,libs 目录下为需要的第三方依赖库, BasePayDemo 目录下为示例项目,供接入时参考使用。
添加 SDK 引用
BasePaySdk.dll
导入第三方依赖库
接入本 SDK 需依赖以下第三方库,参考 libs 文件夹下提供的 dll 文件
Newtonsoft.Json
BouncyCastle.Crypto
使用方法¶
系统初始化
在使用 SDK 调用汇付接口前,请先进行商户配置,否则可能导致交易异常。
正常情况下只有一套商户配置,如有业务需求向汇付申请了多套配置信息,也可配置多个商户配置,并做好商户配置命名管理,配置名必须唯一
调用示例
// 是否调试模式,默认为false,调试模式会打印调试信息,供开发联调时使用
BasePay.debug = false;
// 是否生产模式,默认为true
BasePay.prodMode = true;
// 单套商户配置
// 配置key默认为default,上送报文时无需指定配置key
MerConfig config = new MerConfig();
config.ProductId = DemoConstants.DEMO_PRODUCT_ID;
config.SysId = DemoConstants.DEMO_SYS_ID;
config.RsaPrivateKey = DemoConstants.RSA_PRIVATE_KEY;
config.RsaPublicKey = DemoConstants.RSA_PUBLIC_KEY;
BasePay.initWithMerConfig(config);
// 下面示例为多套商户配置的情形
// 如商户因特殊需要,申请多套配置,则需自行做好配置管理,上送报文时需明确指定使用哪套商户配置
Dictionary<string, MerConfig> configs = new Dictionary<string, MerConfig>();
MerConfig config1 = new MerConfig();
config1.ProductId = DemoConstants.DEMO_PRODUCT_ID1;
config1.SysId = DemoConstants.DEMO_SYS_ID1;
config1.RsaPrivateKey = DemoConstants.RSA_PRIVATE_KEY1;
config1.RsaPublicKey = DemoConstants.RSA_PUBLIC_KEY1;
// 多套配置的key自行指定,保持唯一即可
configs.Add("merchantKey1", config1);
MerConfig config2 = new MerConfig();
config2.ProductId = DemoConstants.DEMO_PRODUCT_ID2;
config2.SysId = DemoConstants.DEMO_SYS_ID2;
config2.RsaPrivateKey = DemoConstants.RSA_PRIVATE_KEY2;
config2.RsaPublicKey = DemoConstants.RSA_PUBLIC_KEY2;
// 多套配置的key自行指定,保持唯一即可
configs.Add("merchantKey2", config2);
BasePay.initWithMerConfigs(configs);
接口调用¶
接口调用均由 BasePayClient.postRequest 方法发起,上传文件接口由 BasePayClient.postRequestFile 方法发起
/// <summary>
/// 发送报文请求
/// </summary>
///
/// <param name="funcCode">功能编码</param>
/// <param name="requestParams">请求报文</param>
/// <param name="merchantKey">商户配置key</param>
///
/// <returns>返回报文</returns>
///
public static Dictionary<string, object> postRequest(string funcCode, Dictionary<string, object> requestParams, string merchantKey = "default");
/// <summary>
/// 上传文件请求
/// </summary>
///
/// <param name="funcCode">功能编码</param>
/// <param name="requestParams">请求报文</param>
/// <param name="filePath">上传文件路径</param>
/// <param name="merchantKey">商户配置key</param>
///
/// <returns>返回报文</returns>
///
public static Dictionary<string, object> postRequestFile(string funcCode, Dictionary<string, object> requestParams, string filePath, string merchantKey = "default");
requestParams
为请求报文体BODY中的 data
- 「接口规则-参数规定-报文体」 ,需根据调用接口的API说明组装参数。
funcCode
为请求接口的功能编码,请参考 交易接口功能编码、商户管理接口功能编码。
filePath
为文件上传时文件所在路径。
merchantKey
为上一步初始化时配置的商户配置key。
接口调用实例¶
以下以聚合反扫接口为例,展示如何使用 SDK 来调用接口。
DateTime dt = DateTime.Now;
string nowStr = DateTime.Now.ToString("yyyyMMddHHmmss");
string nowDate = DateTime.Now.ToString("yyyyMMdd");
string reqSeqId = nowStr + "01234567890";
// merOrdId = nowStr + "1234567890";
string merOrdId = reqSeqId;
string timeExpire = dt.AddMinutes(2).ToString("yyyyMMddHHmmss");
/**
* 聚合反扫调用实例
**/
Dictionary<string, Object> transParam = new Dictionary<string, Object>();
// 请求流水号,需保证当天商户下唯一,推荐采用日期时间+几位流水号的形式
transParam.Add("req_seq_id", reqSeqId);
// 请求日期,请求接口的日期,因服务器时间可能有差异,允许前后1天
transParam.Add("req_date", nowDate);
// 系统号,由汇付分配
transParam.Add("sys_id", DemoConstants.DEMO_SYS_ID);
// 商户订单号,需保证商户下唯一,推荐采用日期时间+几位流水号的形式,可与req_seq_id相同
transParam.Add("mer_ord_id", merOrdId);
// 分配商户号
transParam.Add("huifu_id", DemoConstants.DEMO_HUIFU_ID);
// 渠道号,若需使用自有渠道请联系业务对接人
transParam.Add("bank_channel_no", "");
// 交易金额
transParam.Add("trans_amt", "0.02");
// 商品描述
transParam.Add("goods_desc", "测试商品");
// 支付二维码
transParam.Add("auth_code" , "用户展示的付款二维码");
// 设备信息
Dictionary<string, Object> terminalDeviceInfo = new Dictionary<string, Object>();
terminalDeviceInfo.Add("device_type", "4");
terminalDeviceInfo.Add("device_ip", "139.207.19.246");
transParam.Add("terminal_device_info", terminalDeviceInfo);
// 风控信息
Dictionary<string, Object> riskCheckInfo = new Dictionary<string, Object>();
riskCheckInfo.Add("ipAddr", "139.207.19.246");
Dictionary<string, Object> riskMngInfo = new Dictionary<string, Object>();
riskMngInfo.Add("subTradeType" , "4300");
riskCheckInfo.Add("riskMngInfo", riskMngInfo);
// 注意,风控信息为JSON字符串
transParam.Add("risk_check_info", JsonConvert.SerializeObject(riskCheckInfo, Formatting.None));
// 异步通知地址
transParam.Add("notify_url" , "virgo://http://www.xxx.com");
// 交易有效期
transParam.Add("time_expire" , timeExpire);
// 指定支付方式 是否禁止用户使用信用卡支付。默认不禁用,若禁止请填1
transParam.Add("limit_pay" , "1");
// 延时标志 1为延迟 0为不延迟
transParam.Add("is_delay_acct" , "0");
// 传入分帐遇到优惠的处理规则 1-按比例分 2-按顺序保障 3-只给交易商户
transParam.Add("term_div_coupon_type" , "3");
// 分账串
// 注意只有真实分账场景才需要传入分账串,请避免传入多个分账方为同一商户的分账串
Dictionary<string, Object> acctSplitBunch = new Dictionary<string, Object>();
List<Dictionary<string, Object>> acctInfos = new List<Dictionary<string, Object>>();
// 分账方1
Dictionary<string, Object> acctInfo1 = new Dictionary<string, Object>();
acctInfo1.Add("huifu_id", DemoConstants.DEMO_HUIFU_ID);
acctInfo1.Add("div_amt" , "0.01");
acctInfos.Add(acctInfo1);
// 分账方2
Dictionary<string, Object> acctInfo2 = new Dictionary<string, Object>();
acctInfo2.Add("huifu_id", DemoConstants.DIV_HUIFU_ID);
acctInfo2.Add("div_amt" , "0.01");
acctInfos.Add(acctInfo2);
acctSplitBunch.Add("acct_infos", acctInfos);
transParam.Add("acct_split_bunch", acctSplitBunch);
// 商户私有域
transParam.Add("mer_priv", "");
// 微信扩展参数集合
transParam.Add("wx_data" , "");
// 支付宝扩展参数集合
transParam.Add("alipay_data" , "");
// 银联扩展参数集合
transParam.Add("unionpay_data" , "");
// 手续费类型 01:标准费率线上,02:标准费率线下,03:非盈利费率,04:缴费费率,05:保险费率,06:行业活动费率,07:校园餐饮费率,08:K12中小幼费率
// 不送时取业务入驻配置的默认费率
transParam.Add("pay_scene" , "02");
// 调用接口,使用默认商户配置时可省略配置key
Dictionary<string, Object> result = null;
try {
result = BasePayClient.postRequest("top.trans.authCodePay" , transParam);
// 使用指定配置调用接口
// result = Dictionary<string, Object> result = BasePayClient.postRequest("top.trans.authCodePay", dataParams, "merchantKey2");
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
object subRespCode = null;
result.TryGetValue("sub_resp_code", out subRespCode);
if (string.Equals("00000000", (string)subRespCode))
{
// 处理成功
// 获取交易状态
object transStat = null;
result.TryGetValue("trans_stat", out transStat);
Console.WriteLine("交易状态:" + transStat);
// 微信反扫时获取用户openid
object wxData = null;
if (result.TryGetValue("wx_response", out wxData)) {
Console.WriteLine(wxData);
JObject wxResponse = (JObject)wxData;
Console.WriteLine("wx_response:" + JsonConvert.SerializeObject(wxResponse, Formatting.None));
JToken openid = null;
if (wxResponse.TryGetValue("openid", out openid)) {
Console.WriteLine("openid:=" + openid);
}
}
}
else if (string.Equals("00000100", (string)subRespCode))
{
// 处理中
object transStat = null;
result.TryGetValue("trans_stat", out transStat);
Console.WriteLine("交易状态:" + transStat);
// 后续可调用交易查询获取处理中状态的最终支付结果
}
else
{
// 失败
object subRespDesc = null;
result.TryGetValue("sub_resp_desc", out subRespDesc);
Console.WriteLine("sub_resp_desc" + subRespDesc);
}