十年河东,十年河西,莫欺少年穷
学无止境,精益求精
项目下载地址:https://download.csdn.net/download/bbwolong/82007689
首先来张API截图
然后简单分享下代码片段:
公共访问类:
namespace PayCommon { public class WechatConstants { /// <summary> /// 微信V3支付密钥 /// </summary> public const string WxAPIV3SecretKey = ""; /// <summary> /// 微信支付证书路径 /// </summary> public static string WxPayCertPath = AppConfigurtaionUtil.GetConfig("WechatOptions:CertPath"); /// <summary> /// 微信支付Token前缀,使用v3支付api,用curl需要添加请求头,Authorization的类型必须为“WECHATPAY2-SHA256-RSA2048” [可参考:https://blog.csdn.net/jzd161989/article/details/119868370] /// </summary> public const string WxPayTokenPrefix = "WECHATPAY2-SHA256-RSA2048"; /// <summary> /// 微信支付加密方式 /// </summary> public const string WxPaySignType = "HMAC-SHA256"; /// <summary> /// 服務商模式 V3支付回調 /// </summary> public static string WxPayNotifyUrl = "https://portal.one5a.com/WechatPay/Api/V1/FwsV3Pay/WxPayBack"; /// <summary> /// 微信支付Api URL /// </summary> public static string WxPayUrl = "https://api.mch.weixin.qq.com"; /// <summary> /// 微信支付Api URL V3 jsapi支付 参考官方: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_1.shtml /// </summary> public static string WxPayOfJsapiUri = "/v3/pay/partner/transactions/jsapi"; public static string WxPayOfJsapiUrl = $"{WxPayUrl}{WxPayOfJsapiUri}"; /// <summary> /// URL:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml 微信原生支付 /// </summary> public static string WxPayOfNativeUri = "/v3/pay/partner/transactions/native"; public static string WxPayOfNativeUrl = $"{WxPayUrl}{WxPayOfNativeUri}"; /// <summary> /// 服务商模式:微信支付分账添加分账接收方 /// </summary> public static string WxPayOfShareAddReceiverUri = "/pay/profitsharingaddreceiver"; public static string WxPayOfShareAddReceiverUrl = $"{WxPayUrl}{WxPayOfShareAddReceiverUri}"; /// <summary> /// 微信分账接口 /// </summary> public static string WxPayOfShareProfitUri = "/secapi/pay/profitsharing"; public static string WxPayOfShareProfitUrl = $"{WxPayUrl}{WxPayOfShareProfitUri}"; //对应微信地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 public static string WxPayOfUnifiedUrl = $"{WxPayUrl}/pay/unifiedorder"; //写在配置文件内的AppID是小程序APPID --有商户平台关联 public static string CustomerAppId = ""; //写在配置文件内的MchId是商户的 MchId public static string CustomerMchId = ""; //商户平台Api密钥 public static string CustomerKey = ""; //微商城退款需要证书,证书路径 public static string WxUnifiedPayCertPath = @"xxx\apiclient_cert.p12"; /// <summary> /// 微商城统一下单支付回调URL /// </summary> public static string WxUnifiedPayNotifyUrl = "https://portal.one5a.com/WechatPay/Api/V1/Pay/WxPayBack"; /// <summary> /// 微信支付退款 /// </summary> public static string WxUnifiedRefundNotifyUrl = "https://portal.one5a.com/WechatPay/Api/V1/Pay/WxRefundBack";//todo public static string WxUnifiedPayOfRefundUrl = $"{WxPayUrl}/secapi/pay/refund"; public static string WxPayOfRefundUri = "/v3/refund/domestic/refunds"; public static string WxPayOfRefundUrl = $"{WxPayUrl}{WxPayOfRefundUri}"; public static string WxRefundNotifyUrl = "https://portal.one5a.com/WechatPay/Api/V1/FwsV3Pay/RefundBack"; /// <summary> /// 微信支付附加信息 /// </summary> public const string OMPayAttach = ""; public const string OMPayBody = "小程序支付,商城购买"; /// <summary> /// 微信子商户相关参数,商户名称 /// </summary> public const string MerchantName_2 = ""; /// <summary> /// 微信支付服务商模式 子商户商户ID /// </summary> public const string MerchantId_2 = ""; /// <summary> /// 微信支付 服务商商户名称 /// </summary> public const string MerchantName = ""; /// <summary> /// 微信支付 服务商模式子商户商户ID /// </summary> public const string MerchantId = ""; /// <summary> /// 微信支付证书序列号 /// </summary> public const string MerchantSerialNo = "66D729C81331C58AFDF7B7470108403C376B9890"; /// <summary> /// 小程序APPID /// </summary> public const string MerchantAppId = ""; /// <summary> /// 小程序APP KEY /// </summary> public const string MerchantAppKey = ""; /// <summary> /// 私钥 /// </summary> public const string MerchantPrivateKey = @""; #region 子商户信息 /// <summary> /// 子商户信息 分账接收方 /// </summary> public static string zsfwsMchName = ""; public static string fwsMchId = ""; //服务商商户ID public static string fwsAppId = ""; //服务器小程序APPID public static string fwsAppSecret = "";//App密钥 #endregion } }
支付代码片段
namespace PayCommon { public class WxPayExternal { /// <summary> /// 微信支付 原生支付 /// </summary> /// <param name="request"></param> /// <returns></returns> public static NativePayResponse NativePrePay(NativePayRequest request) { NativePayResponse result = null; request.sp_appid = WechatConstants.MerchantAppId; request.sp_mchid = WechatConstants.MerchantId; request.notify_url = WechatConstants.WxPayNotifyUrl; request.settle_info = new NativePaySettle { profit_sharing = true }; var requestBody = request.ToJson(); var authInfo = BuildAuthAsync(WechatConstants.WxPayOfNativeUri, requestBody); result = HttpHelper.PostWithToken<NativePayResponse>(WechatConstants.WxPayOfNativeUrl, requestBody, GetToken(authInfo.Auth)); return result; } private static SignInfo BuildAuthAsync(string uri, string body) { var method = "POST"; var info = new SignInfo { timeStamp = DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), nonceStr = Path.GetRandomFileName(), }; string message = $"{method}\n{uri}\n{info.timeStamp}\n{info.nonceStr}\n{body}\n"; var signedValue = Sign(message); info.Auth = $"mchid=\"{WechatConstants.MerchantId}\",nonce_str=\"{info.nonceStr}\",timestamp=\"{info.timeStamp}\",serial_no=\"{WechatConstants.MerchantSerialNo}\",signature=\"{signedValue}\""; return info; } private static string GetToken(string auth) { return $"{WechatConstants.WxPayTokenPrefix} {auth}"; } private static string Sign(string message) { string privateKey = WechatConstants.MerchantPrivateKey; byte[] keyData = Convert.FromBase64String(privateKey); using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob)) using (RSACng rsa = new RSACng(cngKey)) { byte[] data = System.Text.Encoding.UTF8.GetBytes(message); return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); } } /// <summary> /// 服务商模式 分账相关 /// </summary> /// <param name="request"></param> /// <returns></returns> public static ShareProfitResponse ShareProfit(ShareProfitRequest request) { var result = new ShareProfitResponse(); var receivers = new ReceiverInfo[] {//分账接收方列表 new ReceiverInfo { account = WechatConstants.MerchantId, name = WechatConstants.MerchantName, amount = request.amount, description = "分给商户"+WechatConstants.MerchantName } , new ReceiverInfo { account = WechatConstants.fwsMchId, name = WechatConstants.zsfwsMchName, amount = request.amount, description = "分给商户"+WechatConstants.zsfwsMchName } }; foreach (var receiver in receivers) { var receiverResult = AddReceiver(request, receiver); if (receiverResult.IsNull() || !receiverResult.IsSuccess) { return result.Fail("微信分账添加接收方失败"); } } var receiversString = receivers.ToJson(); var nonce = Path.GetRandomFileName(); var appid = WechatConstants.MerchantAppId; var mchid = WechatConstants.MerchantId; var appKey = WechatConstants.MerchantAppKey; string strA = $"appid={appid}&mch_id={mchid}" + $@"&nonce_str={nonce}&out_order_no={request.out_trade_no}&receivers={receiversString}&sign_type={WechatConstants.WxPaySignType}" + $@"&sub_appid={request.sub_appid}&sub_mch_id={request.sub_mchid}&transaction_id={request.transaction_id}&key={appKey}"; string sign = WxPayHelper.HmacSHA256(strA, appKey).ToUpper();//签名 var body = $@"<xml> <appid>{appid}</appid> <mch_id>{mchid}</mch_id> <sub_appid>{request.sub_appid}</sub_appid> <sub_mch_id>{request.sub_mchid}</sub_mch_id> <nonce_str>{nonce}</nonce_str> <out_order_no>{request.out_trade_no}</out_order_no> <transaction_id>{request.transaction_id}</transaction_id> <sign>{sign}</sign> <sign_type>{WechatConstants.WxPaySignType}</sign_type> <receivers>{receiversString}</receivers> </xml>"; return HttpHelper.PostWithCert<ShareProfitResponse>(WechatConstants.WxPayOfShareProfitUrl, body); } private static ShareAddReciverReturnData AddReceiver(ShareProfitRequest request, ReceiverInfo receiver) { var nonce = Path.GetRandomFileName(); var receiverJson = receiver.ToJson(); var appid = WechatConstants.MerchantAppId; var mchid = WechatConstants.MerchantId; //签名算法 string strA = $@"appid={appid}&mch_id={mchid}" + $@"&nonce_str={nonce}&receiver={receiverJson}&sign_type={WechatConstants.WxPaySignType}" + $@"&sub_appid={request.sub_appid}&sub_mch_id={request.sub_mchid}&key={WechatConstants.MerchantAppKey}"; string sign = WxPayHelper.HmacSHA256(strA, WechatConstants.MerchantAppKey).ToUpper();//签名 var body = $@"<xml> <mch_id>{mchid}</mch_id> <sub_mch_id>{request.sub_mchid}</sub_mch_id> <appid>{appid}</appid> <sub_appid>{request.sub_appid}</sub_appid> <nonce_str>{nonce}</nonce_str> <sign>{sign}</sign> <sign_type>{WechatConstants.WxPaySignType}</sign_type> <receiver>{receiverJson}</receiver> </xml>"; return HttpHelper.PostWithCert<ShareAddReciverReturnData>(WechatConstants.WxPayOfShareAddReceiverUrl, body); } /// <summary> /// JSAPI 预支付 /// </summary> /// <param name="request"></param> /// <returns></returns> public static SignInfo JsApiPrePay(JsApiPayRequest request) { request.sp_appid = WechatConstants.MerchantAppId; request.sp_mchid = WechatConstants.MerchantId; request.notify_url = WechatConstants.WxPayNotifyUrl; if (request.settle_info.IsNull()) { //是否分账 request.settle_info = new JsApiPaySettle { profit_sharing = true }; } var requestBody = request.ToJson(); var authInfo = BuildAuthAsync(WechatConstants.WxPayOfJsapiUri, requestBody); authInfo.OutTradNo = request.out_trade_no; var response = HttpHelper.PostWithToken<JsApiPayResponse>(WechatConstants.WxPayOfJsapiUrl, requestBody, GetToken(authInfo.Auth)); Asserts.Assert(response.NotNull() && response.code.IsNullOrWhiteSpace(), response?.message ?? ""); //参考 JSAPI调起支付API https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_1_4.shtml authInfo.package = $"prepay_id={response.prepay_id}"; authInfo.paySign = Sign($"{request.sub_appid}\n{authInfo.timeStamp}\n{authInfo.nonceStr}\n{authInfo.package}\n"); return authInfo; } /// <summary> /// 生成预支付信息 /// </summary> /// <param name="request"></param> /// <returns></returns> public static UnifiedPayResult UnifiedPrePay(UnifiedPayRequest request) { UnifiedPayResult result = null; request.appid = WechatConstants.CustomerAppId; request.mch_id = WechatConstants.CustomerMchId; request.notify_url = WechatConstants.WxUnifiedPayNotifyUrl; request.GenerateSign(); var responseStr = HttpHelper.Post(WechatConstants.WxPayOfUnifiedUrl, XmlHelper.ObjectToXML(request)); if (responseStr.NotNullOrWhiteSpace()) { var response = XmlHelper.XMLToObject<UnifiedPayResponse>(responseStr); if (response.IsSuccess) { var time = TimeHelper.GetTimestamp().ToString(); result = new UnifiedPayResult { nonceStr = request.nonce_str, timeStamp = time, package = $"prepay_id={response.prepay_id}", paySign = WxPayHelper.MD5($"appId={request.appid}&nonceStr={request.nonce_str}&package=prepay_id={response.prepay_id}&signType=MD5&timeStamp={time}&key={WechatConstants.CustomerKey}") }; } } return result; } /// <summary> /// 添加分账接收子商户 /// </summary> /// <param name="receiver"></param> /// <returns></returns> public static UnifiedAddReceiveResult UnifiedAddReceiver(WXReceiver receiver) { UnifiedAddReceiveResult result = null; var request = new UnifiedAddReceiverRequest { appid = WechatConstants.CustomerAppId, mch_id = WechatConstants.CustomerMchId, receiver = receiver.ToJson() }; request.GenerateSign(); var responseStr = HttpHelper.Post(WechatConstants.WxPayOfShareAddReceiverUrl, XmlHelper.ObjectToXML(request)); if (responseStr.NotNullOrWhiteSpace()) { result = XmlHelper.XMLToObject<UnifiedAddReceiveResult>(responseStr); } return result; } /// <summary> /// 分账相关 /// </summary> /// <param name="request"></param> /// <returns></returns> public static ShareProfitResponse UnifiedShareProfit(UnifiedShareProfitRequest request) { request.appid = WechatConstants.CustomerAppId; request.mch_id = WechatConstants.CustomerMchId; request.GenerateSign(); return HttpHelper.PostWithCert<ShareProfitResponse>(WechatConstants.WxPayOfShareProfitUrl, XmlHelper.ObjectToXML(request), WechatConstants.WxUnifiedPayCertPath, WechatConstants.CustomerMchId); } /// <summary> /// 需要证书 /// </summary> /// <param name="request"></param> /// <returns></returns> public static UnifiedRefundResponse UnifiedRefund(UnifiedRefundRequest request) { request.appid = WechatConstants.CustomerAppId; request.mch_id = WechatConstants.CustomerMchId; request.notify_url = WechatConstants.WxUnifiedRefundNotifyUrl; request.GenerateSign(); return HttpHelper.PostWithCert<UnifiedRefundResponse>(WechatConstants.WxUnifiedPayOfRefundUrl, XmlHelper.ObjectToXML(request), WechatConstants.WxUnifiedPayCertPath, WechatConstants.CustomerMchId); } /// <summary> /// 退款 /// </summary> /// <param name="request"></param> /// <returns></returns> public static RefundResponse Refund(RefundRequest request) { request.notify_url = WechatConstants.WxRefundNotifyUrl; var requestBody = request.ToJson(); var authInfo = BuildAuthAsync(WechatConstants.WxPayOfRefundUri, requestBody); return HttpHelper.PostWithToken<RefundResponse>(WechatConstants.WxPayOfRefundUrl, requestBody, GetToken(authInfo.Auth)); } } }
项目架构
下载地址:https://download.csdn.net/download/bbwolong/82007689
@天才卧龙的博客