netCore 接入微信支付<小程序,APP,H5>,内含普通支付,微信V3支付,服务商模式【支付,支付回写,退款,分账给个人,服务商模式支付,服务商模式支付回写,服务商模式分账给子商户,
十年河东,十年河西,莫欺少年穷
学无止境,精益求精
项目下载地址:https://download.csdn.net/download/bbwolong/82007689
首先来张API截图
然后简单分享下代码片段:
公共访问类:
namespace PayCommon { public class WechatConstants { ////// 微信V3支付密钥 /// public const string WxAPIV3SecretKey = ""; /// /// 微信支付证书路径 /// public static string WxPayCertPath = AppConfigurtaionUtil.GetConfig("WechatOptions:CertPath"); /// /// 微信支付Token前缀,使用v3支付api,用curl需要添加请求头,Authorization的类型必须为“WECHATPAY2-SHA256-RSA2048” [可参考:https://blog.csdn.net/jzd161989/article/details/119868370] /// public const string WxPayTokenPrefix = "WECHATPAY2-SHA256-RSA2048"; /// /// 微信支付加密方式 /// public const string WxPaySignType = "HMAC-SHA256"; /// /// 服務商模式 V3支付回調 /// public static string WxPayNotifyUrl = "https://portal.one5a.com/WechatPay/Api/V1/FwsV3Pay/WxPayBack"; /// /// 微信支付Api URL /// public static string WxPayUrl = "https://api.mch.weixin.qq.com"; /// /// 微信支付Api URL V3 jsapi支付 参考官方: https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter4_5_1.shtml /// public static string WxPayOfJsapiUri = "/v3/pay/partner/transactions/jsapi"; public static string WxPayOfJsapiUrl = $"{WxPayUrl}{WxPayOfJsapiUri}"; /// /// URL:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml 微信原生支付 /// public static string WxPayOfNativeUri = "/v3/pay/partner/transactions/native"; public static string WxPayOfNativeUrl = $"{WxPayUrl}{WxPayOfNativeUri}"; /// /// 服务商模式:微信支付分账添加分账接收方 /// public static string WxPayOfShareAddReceiverUri = "/pay/profitsharingaddreceiver"; public static string WxPayOfShareAddReceiverUrl = $"{WxPayUrl}{WxPayOfShareAddReceiverUri}"; /// /// 微信分账接口 /// 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"; /// /// 微商城统一下单支付回调URL /// public static string WxUnifiedPayNotifyUrl = "https://portal.one5a.com/WechatPay/Api/V1/Pay/WxPayBack"; /// /// 微信支付退款 /// 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"; /// /// 微信支付附加信息 /// public const string OMPayAttach = ""; public const string OMPayBody = "小程序支付,商城购买"; /// /// 微信子商户相关参数,商户名称 /// public const string MerchantName_2 = ""; /// /// 微信支付服务商模式 子商户商户ID /// public const string MerchantId_2 = ""; /// /// 微信支付 服务商商户名称 /// public const string MerchantName = ""; /// /// 微信支付 服务商模式子商户商户ID /// public const string MerchantId = ""; /// /// 微信支付证书序列号 /// public const string MerchantSerialNo = "66D729C81331C58AFDF7B7470108403C376B9890"; /// /// 小程序APPID /// public const string MerchantAppId = ""; /// /// 小程序APP KEY /// public const string MerchantAppKey = ""; /// /// 私钥 /// public const string MerchantPrivateKey = @""; #region 子商户信息 /// /// 子商户信息 分账接收方 /// 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 { ////// 微信支付 原生支付 /// /// /// 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 (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)); } } /// /// 服务商模式 分账相关 /// /// /// 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 = $@" "; return HttpHelper.PostWithCert {appid} {mchid} {request.sub_appid} {request.sub_mchid} {nonce} {request.out_trade_no} {request.transaction_id} {sign} {WechatConstants.WxPaySignType} {receiversString} (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 = $@" "; return HttpHelper.PostWithCert {mchid} {request.sub_mchid} {appid} {request.sub_appid} {nonce} {sign} {WechatConstants.WxPaySignType} {receiverJson} (WechatConstants.WxPayOfShareAddReceiverUrl, body); } /// /// JSAPI 预支付 /// /// /// 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 (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; } /// /// 生成预支付信息 /// /// /// 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 (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; } /// /// 添加分账接收子商户 /// /// /// 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 (responseStr); } return result; } /// /// 分账相关 /// /// /// public static ShareProfitResponse UnifiedShareProfit(UnifiedShareProfitRequest request) { request.appid = WechatConstants.CustomerAppId; request.mch_id = WechatConstants.CustomerMchId; request.GenerateSign(); return HttpHelper.PostWithCert (WechatConstants.WxPayOfShareProfitUrl, XmlHelper.ObjectToXML(request), WechatConstants.WxUnifiedPayCertPath, WechatConstants.CustomerMchId); } /// /// 需要证书 /// /// /// 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 (WechatConstants.WxUnifiedPayOfRefundUrl, XmlHelper.ObjectToXML(request), WechatConstants.WxUnifiedPayCertPath, WechatConstants.CustomerMchId); } /// /// 退款 /// /// /// public static RefundResponse Refund(RefundRequest request) { request.notify_url = WechatConstants.WxRefundNotifyUrl; var requestBody = request.ToJson(); var authInfo = BuildAuthAsync(WechatConstants.WxPayOfRefundUri, requestBody); return HttpHelper.PostWithToken (WechatConstants.WxPayOfRefundUrl, requestBody, GetToken(authInfo.Auth)); } } }
项目架构
下载地址:https://download.csdn.net/download/bbwolong/82007689
@天才卧龙的博客