.Net微信服务商平台ApiV3接口

news/2024/10/10 16:33:24/文章来源:https://www.cnblogs.com/flms/p/18456616

转载:https://www.cnblogs.com/xilen/p/15380183.html

开始

在开始之前建议仔细读微信官方文档,接口规则及api文档

https://pay.weixin.qq.com/wiki/doc/apiv3_partner/wechatpay/wechatpay-1.shtml

https://pay.weixin.qq.com/wiki/doc/apiv3_partner/index.shtml

目录

整个流程开发步骤如下:

一、(签名)

二、(获取证书、敏感信息加密)

三、(上传图片)

四、(特约商户进件)

五、(生成小程序码)

六、(微信小程序支付)

七、(分账)

正文

在开始之前请确保你已经获取商户号、证书、秘钥、小程序appid、appsecret

一、签名

文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml

1、生成签名

/// <param name="url">微信的接口地址</param>/// <param name="method">请求的方式GET,POST,PUT</param>/// <param name="jsonParame">post请求的数据,json格式  ,get时传空</param>/// <param name="privateKey">apiclient_key.pem中的内容,不要-----BEGIN PRIVATE KEY-----  -----END PRIVATE KEY-----</param>/// <param name="merchantId">发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid</param>/// <param name="serialNo">商户证书号</param>/// <returns></returns>protected string GetAuthorization(string url, string method, string jsonParame, string privateKey, string merchantId, string serialNo){var uri = new Uri(url);string urlPath = uri.PathAndQuery;string nonce = Guid.NewGuid().ToString();var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();//数据签名     HTTP请求方法\n接口地址的url\n请求时间戳\n请求随机串\n请求报文主体\nmethod = string.IsNullOrEmpty(method) ? "" : method;string message = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n", method, urlPath, timestamp, nonce, jsonParame);string signTxt = Sign(message, privateKey);//Authorization和格式string authorzationTxt = string.Format("WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"",merchantId,nonce,timestamp,serialNo,signTxt);return authorzationTxt;}protected string Sign(string message, string privateKey){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));}}

  

 2、放到请求头

string Authorization = GetAuthorization(url, method, postData, privateKey, merchantId, serialNo);
request.Headers.Add("Authorization", Authorization);

3、完整的请求方法

/// <param name="url">微信的接口地址</param>
/// <param name="postData">post请求的数据,json格式 </param>
/// <param name="privateKey">apiclient_key.pem中的内容,不要-----BEGIN PRIVATE KEY-----  -----END PRIVATE KEY-----</param>
/// <param name="merchantId">发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid</param>
/// <param name="serialNo">商户证书号</param>
/// <returns></returns>
public string postJson(string url, string postData, string privateKey, string merchantId, string serialNo, string method = "POST"){HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);request.Method = method;request.ContentType = "application/json;charset=UTF-8";request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";request.Accept = "application/json";string Authorization = GetAuthorization(url, method, postData, privateKey, merchantId, serialNo);request.Headers.Add("Authorization", Authorization);if (!string.IsNullOrEmpty(postData)){byte[] paramJsonBytes;paramJsonBytes = System.Text.Encoding.UTF8.GetBytes(postData);request.ContentLength = paramJsonBytes.Length;Stream writer;try{writer = request.GetRequestStream();}catch (Exception){writer = null;Console.Write("连接服务器失败!");}writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);writer.Close();}HttpWebResponse response;try{response = (HttpWebResponse)request.GetResponse();}catch (WebException ex){response = ex.Response as HttpWebResponse;}Stream resStream = response.GetResponseStream();StreamReader reader = new StreamReader(resStream);string text = reader.ReadToEnd();return text;}

  

二、获取证书、敏感信息加密

调用特约商户进件接口之前需要做三个工作:获取证书、敏感信息加密、上传图片

获取证书的目的是敏感信息加密需要用证书里解密得到的pubkey,然后用pubkey去对敏感信息进行加密

1、获取证书

获取证书接口比较简单,直接调用上边的请求方法

public static certModel GetCert()
{string url = "https://api.mch.weixin.qq.com/v3/certificates";string merchantId = WxPayConfig.MCHID;   //商户号string serialNo = WxPayConfig.SERIAL_NO;  //证书编号string privateKey = WxPayConfig.PRIVATEKEY; // NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY----- 亦不包括结尾的-----END PRIVATE KEY-----string transactionsResponse = postJson(url, string.Empty, privateKey, merchantId, serialNo,"GET");var result = JsonConvert.DeserializeObject<certModel>(transactionsResponse);return result;      
}GetCert()

  

用到的model

public class certModel
{
public List<Data> data { get; set; }
}

public class Data
{
public string serial_no { get; set; }
public string effective_time { get; set; }
public string expire_time { get; set; }
public Encrypt_certificate encrypt_certificate { get; set; }

}
public class Encrypt_certificate
{
public string algorithm { get; set; }
public string nonce { get; set; }
public string associated_data { get; set; }
public string ciphertext { get; set; }
}

 

复制代码
public class certModel{public List<Data> data { get; set; }}public class Data{public string serial_no { get; set; }public string effective_time { get; set; }public string expire_time { get; set; }public Encrypt_certificate encrypt_certificate { get; set; }}public class Encrypt_certificate{public string algorithm { get; set; }public string nonce { get; set; }public string associated_data { get; set; }public string ciphertext { get; set; }}
复制代码

调用成功直接返回证书list,我们需要用v3秘钥解密得到公钥

var cmodel = GetCert().data.OrderByDescending(t => t.expire_time).FirstOrDefault();
string pubkey = AesGcmHelper.AesGcmDecrypt(cmodel.encrypt_certificate.associated_data, cmodel.encrypt_certificate.nonce, cmodel.encrypt_certificate.ciphertext);
pubkey = pubkey.Replace("-----BEGIN CERTIFICATE-----", "").Replace("-----END CERTIFICATE-----", "");//解密方法
public class AesGcmHelper{private static string ALGORITHM = "AES/GCM/NoPadding";private static int TAG_LENGTH_BIT = 128;private static int NONCE_LENGTH_BYTE = 12;private static string AES_KEY = WxPayConfig.V3KEY;//你的v3秘钥public static string AesGcmDecrypt(string associatedData, string nonce, string ciphertext){GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());AeadParameters aeadParameters = new AeadParameters(new KeyParameter(Encoding.UTF8.GetBytes(AES_KEY)),128,Encoding.UTF8.GetBytes(nonce),Encoding.UTF8.GetBytes(associatedData));gcmBlockCipher.Init(false, aeadParameters);byte[] data = Convert.FromBase64String(ciphertext);byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);gcmBlockCipher.DoFinal(plaintext, length);return Encoding.UTF8.GetString(plaintext);}}pubkey

  

2、敏感信息加密

我们上一步得到了pubkey,然后对一些敏感信息字段(如用户的住址、银行卡号、手机号码等)进行加密

//text 为要加密的字段值
RSAEncrypt(text, UTF8Encoding.UTF8.GetBytes(pubkey));public static string RSAEncrypt(string text, byte[] publicKey){using (var x509 = new X509Certificate2(publicKey)){using (var rsa = (RSACryptoServiceProvider)x509.PublicKey.Key){var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.OaepSHA1);return Convert.ToBase64String(buff);}}}RSAEncrypt

  

这一步需要注意

var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.OaepSHA1);

三、上传图片

特约商户进件需要上传身份证、营业执照、银行卡等,这就需要通过图片上传API预先生成MediaID

先看接口文档https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter2_1_1.shtml

我封装了一个方法,直接上代码

public string UploadImg(string imgPath){string filePath = HttpContext.Current.Server.MapPath(imgPath);var filename = Path.GetFileName(filePath);FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);Byte[] imgBytesIn = new Byte[fs.Length];fs.Read(imgBytesIn, 0, imgBytesIn.Length);fs.Close();byte[] hash = SHA256Managed.Create().ComputeHash(imgBytesIn);StringBuilder builder = new StringBuilder();for (int i = 0; i < hash.Length; i++){builder.Append(hash[i].ToString("x2"));}var sha256 = builder.ToString();string metaStr = "{\"filename\":\""+ filename + "\",\"sha256\":\"" + sha256 + "\"}";string media_id = UploadImgApi(metaStr, imgBytesIn, filename);return media_id;}public static string UploadImgApi(string metaStr, Byte[] imgBytesIn,string filename){string url = "https://api.mch.weixin.qq.com/v3/merchant/media/upload";string merchantId = WxPayConfig.MCHID;   //商户号string serialNo = WxPayConfig.SERIAL_NO;  //证书编号string privateKey = WxPayConfig.PRIVATEKEY;#region 定义请求体中的内容 并转成二进制string boundary = "lc199aecd61b4653ef";string Enter = "\r\n";string campaignIDStr1= "--" + boundary+ Enter+ "Content-Disposition: form-data; name=\"meta\";"+ Enter+ "Content-Type:application/json;"+ Enter+ Enter+ metaStr+ Enter+ "--" + boundary+ Enter+ "Content-Disposition:form-data;name=\"file\";filename=\""+ filename + "\";"+ Enter+ "Content-Type:image/jpeg"+ Enter+ Enter;byte[] byteData2= imgBytesIn;string campaignIDStr3 = Enter+ "--" + boundary + Enter;var byteData1 = System.Text.Encoding.UTF8.GetBytes(campaignIDStr1);var byteData3 = System.Text.Encoding.UTF8.GetBytes(campaignIDStr3);#endregionstring transactionsResponse = UploadImg_postJson(url, byteData1, byteData2, byteData3, metaStr, privateKey, merchantId, serialNo, boundary, "POST");var result=JsonConvert.DeserializeObject<uploadModel>(transactionsResponse);Thread.Sleep(500);return result.media_id;}public class uploadModel{public string media_id { get; set; }}UploadImg

  

上传图片api需要注意请求主体类型、参与签名的字符串及body格式

我又单独写了个请求方法

public string UploadImg_postJson(string url, byte[] b1, byte[] b2, byte[] b3, string metaStr, string privateKey, string merchantId, string serialNo, string boundary, string method = "POST"){HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);request.Method = method;//request.ContentType = "application/json;charset=UTF-8";request.ContentType = "multipart/form-data;boundary=" + boundary;request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";request.Accept = "application/json";string Authorization = GetAuthorization(url, method, metaStr, privateKey, merchantId, serialNo);request.Headers.Add("Authorization", Authorization);Stream writer;try{writer = request.GetRequestStream();}catch (Exception){writer = null;}writer.Write(b1, 0, b1.Length);writer.Write(b2, 0, b2.Length);writer.Write(b3, 0, b3.Length);writer.Close();HttpWebResponse response;try{response = (HttpWebResponse)request.GetResponse();}catch (WebException ex){response = ex.Response as HttpWebResponse;}Stream resStream = response.GetResponseStream();StreamReader reader = new StreamReader(resStream);string text = reader.ReadToEnd();return text;}UploadImg_postJson

  

最终返回media_id,存入合适的位置,方便使用

{
"media_id": "H1ihR9JUtVj-J7CJqBUY5ZOrG_Je75H-rKhTG7FUmg9sxNTbRN54dFiUHnhg
rBQ6EKeHoGcHTJMHn5TAuLVjHUQDBInSWXcIHYXOeRa2OHA"
}

四、特约商户进件

上边步骤通了之后,到这就很简单了,这一步的主要难点是请求参数太多了,很容易出错

注意:

• 商户上送敏感信息时使用微信支付平台公钥加密,证书序列号包含在请求HTTP头部的Wechatpay-Seria

需要在请求接口helder里加入Wechatpay-Seria

request.Headers.Add("Wechatpay-Serial", serial_no);

另外一点注意的这里的serial_no是GetCert()接口里获取到的serial_no

调用成功返回微信支付申请单号

{"applyment_id": 2000002124775691
}

这一步完成之后可以拿到applyment_id请求查询申请单接口获取结果

成功返回sign_url签约连接发给特约商户相应负责人完成签约,即结束商户进件流程

 五、生成带参数的小程序码

特约商户签约完成之后,服务商平台便可以代商户发起收款,此时我们需要分别给不同的商户生成不同的收款码,其实只需要传入商家的id即可区别处理

//storeid是商家唯一Id
public static string CreateQR(string storeid)
{
{
var page = "pages/custom/index";//扫码打开页面
var scene = storeid;//参数
//获取小程序的appid和secret
var appId = WxPayConfig.XCXAPPID;
var secret = WxPayConfig.XCXKEY;
string result = HttpGet($"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={secret}");

tokenModel rb = JsonConvert.DeserializeObject<tokenModel>(result);

var url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + rb.access_token;

var strUrl = url;
var request = (HttpWebRequest)WebRequest.Create(strUrl);
request.Method = "POST";
request.ContentType = "application/json;charset=UTF-8";
var data = new JsonData { ["page"] = page, ["scene"] = scene };

string jso = data.ToJson();
var payload = Encoding.UTF8.GetBytes(jso);
request.ContentLength = payload.Length;
var writer = request.GetRequestStream();
writer.Write(payload, 0, payload.Length);
writer.Close();
var response = (HttpWebResponse)request.GetResponse();
var s = response.GetResponseStream();

var qrCodeImgBase64 = StreamToBytes(s);

//将流保存
string filename= storeid + ".png";
string returnpath= "/UpLoadFiles/StoreQR/" + filename;
string filepath = HttpContext.Current.Server.MapPath("/UpLoadFiles/StoreQR/") + filename;
System.IO.File.WriteAllBytes(filepath, qrCodeImgBase64);
return returnpath;
}
}

CreateQR

复制代码
//storeid是商家唯一Id
public static string CreateQR(string storeid){{var page = "pages/custom/index";//扫码打开页面var scene = storeid;//参数//获取小程序的appid和secretvar appId = WxPayConfig.XCXAPPID;var secret = WxPayConfig.XCXKEY;string result = HttpGet($"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={secret}");tokenModel rb = JsonConvert.DeserializeObject<tokenModel>(result);var url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + rb.access_token;var strUrl = url;var request = (HttpWebRequest)WebRequest.Create(strUrl);request.Method = "POST";request.ContentType = "application/json;charset=UTF-8";var data = new JsonData { ["page"] = page, ["scene"] = scene };string jso = data.ToJson();var payload = Encoding.UTF8.GetBytes(jso);request.ContentLength = payload.Length;var writer = request.GetRequestStream();writer.Write(payload, 0, payload.Length);writer.Close();var response = (HttpWebResponse)request.GetResponse();var s = response.GetResponseStream();var qrCodeImgBase64 = StreamToBytes(s);//将流保存string filename= storeid + ".png";string returnpath= "/UpLoadFiles/StoreQR/" + filename;string filepath = HttpContext.Current.Server.MapPath("/UpLoadFiles/StoreQR/") + filename;System.IO.File.WriteAllBytes(filepath, qrCodeImgBase64);return returnpath;}}
复制代码

六、小程序支付JSAPI下单接口

有了商家码就能分别为商家发起支付申请,签约商户都有一个分配的商户号sub_mchid,注意请求参数里的商户号即这个,需要根据二维码的参数去获取

public static string V3Pay(string sub_mchid,string openid,int amount,string ordernumber,string description)
{
string url = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi";

string appid = WxPayConfig.XCXAPPID;
string merchantId = WxPayConfig.MCHID; //商户号
string serialNo = WxPayConfig.SERIAL_NO; //证书编号
string privateKey = WxPayConfig.PRIVATEKEY; // NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY----- 亦不包括结尾的-----END PRIVATE KEY-----

WxPayData postData = new WxPayData();
postData.SetValue("sp_appid", appid);
postData.SetValue("sp_mchid", merchantId);
postData.SetValue("sub_mchid", sub_mchid);
postData.SetValue("description", description);
postData.SetValue("out_trade_no", ordernumber);
postData.SetValue("notify_url", WxPayConfig.NOTIFY_URL);
WxPayData settle_info = new WxPayData();
settle_info.SetValue("profit_sharing",true);
postData.SetValue("settle_info", settle_info);
WxPayData _amount = new WxPayData();
_amount.SetValue("total", amount);
_amount.SetValue("currency", "CNY");
postData.SetValue("amount", _amount);
WxPayData payer = new WxPayData();
payer.SetValue("sp_openid", openid);
postData.SetValue("payer", payer);

var postJson = postData.ToJsonFor();
string result = postJson(url, postJson, privateKey, merchantId, serialNo, "POST");
var result = JsonConvert.DeserializeObject<payModel>(result);
return result.prepay_id;
}

V3Pay

复制代码
public static string V3Pay(string sub_mchid,string openid,int amount,string ordernumber,string description){string url = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi";string appid = WxPayConfig.XCXAPPID;string merchantId = WxPayConfig.MCHID;   //商户号string serialNo = WxPayConfig.SERIAL_NO;  //证书编号string privateKey = WxPayConfig.PRIVATEKEY; // NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY----- 亦不包括结尾的-----END PRIVATE KEY-----WxPayData postData = new WxPayData();postData.SetValue("sp_appid", appid);postData.SetValue("sp_mchid", merchantId);postData.SetValue("sub_mchid", sub_mchid);postData.SetValue("description", description);postData.SetValue("out_trade_no", ordernumber);postData.SetValue("notify_url", WxPayConfig.NOTIFY_URL);WxPayData settle_info = new WxPayData();settle_info.SetValue("profit_sharing",true);postData.SetValue("settle_info", settle_info);WxPayData _amount = new WxPayData();_amount.SetValue("total", amount);_amount.SetValue("currency", "CNY");postData.SetValue("amount", _amount);WxPayData payer = new WxPayData();payer.SetValue("sp_openid", openid);postData.SetValue("payer", payer);var postJson = postData.ToJsonFor();string result = postJson(url, postJson, privateKey, merchantId, serialNo, "POST");var result = JsonConvert.DeserializeObject<payModel>(result);return result.prepay_id;}
复制代码

请求参数按照自己的方法去构建,json格式

通过JSAPI下单接口获取到发起支付的必要参数prepay_id,然后使用微信支付提供的小程序方法调起小程序支付

public static string GetJsApiParameters(string prepay_id)
{
string appid = WxPayConfig.XCXAPPID;
string privateKey = WxPayConfig.PRIVATEKEY;
string timestamp = WxPayApi.GenerateTimeStamp();
string nonceStr = WxPayApi.GenerateNonceStr();
string package = "prepay_id=" + prepay_id;
WxPayData jsApiParam = new WxPayData();
jsApiParam.SetValue("appId", appid);
jsApiParam.SetValue("timeStamp", timestamp);
jsApiParam.SetValue("nonceStr", nonceStr);
jsApiParam.SetValue("package", package);
jsApiParam.SetValue("signType", "RSA");
string message = string.Format("{0}\n{1}\n{2}\n{3}\n", appid, timestamp, nonceStr, package);
string signTxt = Sign(message, privateKey);
jsApiParam.SetValue("paySign", signTxt);

string parameters = jsApiParam.ToJson();
return parameters;
}

GetJsApiParameters

复制代码
public static string GetJsApiParameters(string prepay_id){string appid = WxPayConfig.XCXAPPID;string privateKey = WxPayConfig.PRIVATEKEY;string timestamp = WxPayApi.GenerateTimeStamp();string nonceStr = WxPayApi.GenerateNonceStr();string package = "prepay_id=" + prepay_id;WxPayData jsApiParam = new WxPayData();jsApiParam.SetValue("appId", appid);jsApiParam.SetValue("timeStamp", timestamp);jsApiParam.SetValue("nonceStr", nonceStr);jsApiParam.SetValue("package", package);jsApiParam.SetValue("signType", "RSA");string message = string.Format("{0}\n{1}\n{2}\n{3}\n", appid, timestamp, nonceStr, package);string signTxt = Sign(message, privateKey);jsApiParam.SetValue("paySign", signTxt);string parameters = jsApiParam.ToJson();return parameters;}
复制代码

返回给小程序调用wx.requestPayment(OBJECT)发起微信支付

注意回调URL:该链接是通过基础下单接口中的请求参数“notify_url”来设置的,要求必须为https地址。请确保回调URL是外部可正常访问的,且不能携带后缀参数,否则可能导致商户无法接收到微信的回调通知信息。回调URL示例: “https://pay.weixin.qq.com/wxpay/pay.action”

public class V3Notify
{

public callbackViewModel GetNotifyData()
{
//接收从微信后台POST过来的数据
System.IO.Stream s = System.Web.HttpContext.Current.Request.InputStream;
int count = 0;
byte[] buffer = new byte[1024];
StringBuilder builder = new StringBuilder();
while ((count = s.Read(buffer, 0, 1024)) > 0)
{
builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
}
s.Flush();
s.Close();
s.Dispose();

var ReadStr = builder.ToString();

notifyModel wxPayNotify = Newtonsoft.Json.JsonConvert.DeserializeObject<notifyModel>(ReadStr);
//开始解密
string WxPayResourceDecryptModel = AesGcmHelper.AesGcmDecrypt(wxPayNotify.resource.associated_data, wxPayNotify.resource.nonce, wxPayNotify.resource.ciphertext);
var decryptModel= Newtonsoft.Json.JsonConvert.DeserializeObject<WxPayResourceDecryptModel>(WxPayResourceDecryptModel);

var viewModel = new callbackViewModel();
if (decryptModel != null)
{
//查询
var model = queryOrder(decryptModel.out_trade_no, decryptModel.sp_mchid, decryptModel.sub_mchid);//订单查询接口
viewModel.code = model.trade_state;
viewModel.message = model.trade_state_desc;
}
else
{
viewModel.code = "FAIL";
viewModel.message = "数据解密失败";
}
return viewModel;
}
}

V3Notify

复制代码
public class V3Notify{public callbackViewModel GetNotifyData(){//接收从微信后台POST过来的数据System.IO.Stream s = System.Web.HttpContext.Current.Request.InputStream;int count = 0;byte[] buffer = new byte[1024];StringBuilder builder = new StringBuilder();while ((count = s.Read(buffer, 0, 1024)) > 0){builder.Append(Encoding.UTF8.GetString(buffer, 0, count));}s.Flush();s.Close();s.Dispose();var ReadStr = builder.ToString();notifyModel wxPayNotify = Newtonsoft.Json.JsonConvert.DeserializeObject<notifyModel>(ReadStr);//开始解密string WxPayResourceDecryptModel = AesGcmHelper.AesGcmDecrypt(wxPayNotify.resource.associated_data, wxPayNotify.resource.nonce, wxPayNotify.resource.ciphertext);var decryptModel= Newtonsoft.Json.JsonConvert.DeserializeObject<WxPayResourceDecryptModel>(WxPayResourceDecryptModel);var viewModel = new callbackViewModel();if (decryptModel != null){//查询var model = queryOrder(decryptModel.out_trade_no, decryptModel.sp_mchid, decryptModel.sub_mchid);//订单查询接口viewModel.code = model.trade_state;viewModel.message = model.trade_state_desc;}else{viewModel.code = "FAIL";viewModel.message = "数据解密失败";}return viewModel;}}
复制代码

整个下单没有牵涉到业务方面的代码,你可以把你的业务代码写在合适的位置处理

七、分账

在请求分账之前先在微信服务商后台邀约商户授权分账并指定分账比例(最大30%),并且发起支付申请时请求参数指定profit_sharing为true

1、首先添加分账接收方

接收方必须先调用接口添加才能在下一步请求分账时使用,注意不允许重复的openid

public static receiverModel AddReceivers(string sub_mchid,string type,string account,string relation_type)
{
string url = "https://api.mch.weixin.qq.com/v3/profitsharing/receivers/add";

string appid = WxPayConfig.XCXAPPID;
string merchantId = WxPayConfig.MCHID; //商户号
string serialNo = WxPayConfig.SERIAL_NO; //证书编号
string privateKey = WxPayConfig.PRIVATEKEY; // NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY----- 亦不包括结尾的-----END PRIVATE KEY-----

WxPayData postData = new WxPayData();
postData.SetValue("sub_mchid", sub_mchid);
postData.SetValue("appid", appid);
postData.SetValue("type", type);
postData.SetValue("account", account);
postData.SetValue("relation_type", relation_type);
string postJson = postData.ToJson();

string transactionsResponse = postJson(url, postJson, privateKey, merchantId, serialNo, "POST");
var result = JsonConvert.DeserializeObject<receiverModel>(transactionsResponse);
return result;
}

AddReceivers

复制代码
public static receiverModel AddReceivers(string sub_mchid,string type,string account,string relation_type){string url = "https://api.mch.weixin.qq.com/v3/profitsharing/receivers/add";string appid = WxPayConfig.XCXAPPID;string merchantId = WxPayConfig.MCHID;   //商户号string serialNo = WxPayConfig.SERIAL_NO;  //证书编号string privateKey = WxPayConfig.PRIVATEKEY; // NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY----- 亦不包括结尾的-----END PRIVATE KEY-----WxPayData postData = new WxPayData();postData.SetValue("sub_mchid", sub_mchid);postData.SetValue("appid", appid);postData.SetValue("type", type);postData.SetValue("account", account);postData.SetValue("relation_type", relation_type);string postJson = postData.ToJson();string transactionsResponse = postJson(url, postJson, privateKey, merchantId, serialNo, "POST");var result = JsonConvert.DeserializeObject<receiverModel>(transactionsResponse);return result;}
复制代码

2、请求分账

public static receiverModel PayReceivers(string sub_mchid, string transaction_id, string out_order_no,List<WxPayData> receivers)
{
string url = "https://api.mch.weixin.qq.com/v3/profitsharing/orders";

string appid = WxPayConfig.XCXAPPID;
string merchantId = WxPayConfig.MCHID; //商户号
string serialNo = WxPayConfig.SERIAL_NO; //证书编号
string privateKey = WxPayConfig.PRIVATEKEY; // NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY----- 亦不包括结尾的-----END PRIVATE KEY-----

WxPayData postData = new WxPayData();
postData.SetValue("sub_mchid", sub_mchid);
postData.SetValue("appid", appid);
postData.SetValue("transaction_id", transaction_id);
postData.SetValue("out_order_no", out_order_no);
postData.SetValue("unfreeze_unsplit", true);
postData.SetValue("receivers", receivers);
string postJson = postData.ToJsonFor();
LogHelper.WriteLogToFile("PayReceivers-postJson:" + postJson);

string transactionsResponse = postJson(url, postJson, privateKey, merchantId, serialNo, "POST");
var result = JsonConvert.DeserializeObject<receiverModel>(transactionsResponse);
return result;
}

PayReceivers

复制代码
public static receiverModel PayReceivers(string sub_mchid, string transaction_id, string out_order_no,List<WxPayData> receivers){string url = "https://api.mch.weixin.qq.com/v3/profitsharing/orders";string appid = WxPayConfig.XCXAPPID;string merchantId = WxPayConfig.MCHID;   //商户号string serialNo = WxPayConfig.SERIAL_NO;  //证书编号string privateKey = WxPayConfig.PRIVATEKEY; // NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY----- 亦不包括结尾的-----END PRIVATE KEY-----WxPayData postData = new WxPayData();postData.SetValue("sub_mchid", sub_mchid);postData.SetValue("appid", appid);postData.SetValue("transaction_id", transaction_id);postData.SetValue("out_order_no", out_order_no);postData.SetValue("unfreeze_unsplit", true);postData.SetValue("receivers", receivers);string postJson = postData.ToJsonFor();LogHelper.WriteLogToFile("PayReceivers-postJson:" + postJson);string transactionsResponse = postJson(url, postJson, privateKey, merchantId, serialNo, "POST");var result = JsonConvert.DeserializeObject<receiverModel>(transactionsResponse);return result;}
复制代码

用到的model

public class receiverModel
{
public string sub_mchid { get; set; }
public string type { get; set; }
public string account { get; set; }
public string name { get; set; }
public string relation_type { get; set; }
public string custom_relation { get; set; }
}

receiverModel

复制代码
public class receiverModel{public string sub_mchid { get; set; }public string type { get; set; }public string account { get; set; }public string name { get; set; }public string relation_type { get; set; }public string custom_relation { get; set; }}
复制代码

至此完整流程全部走完,总结下来技术难度并不大,就是步骤多,并且要把握好调用的时机,再一个就是请求参数多,容易出错,要耐心。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/811148.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware vCenter Server 8.0U3c 发布下载,修复 U3b 更新停止响应的问题

VMware vCenter Server 8.0U3c 发布下载,修复 U3b 更新停止响应的问题VMware vCenter Server 8.0U3c 发布下载 - 集中式管理 vSphere 环境 Server Management Software | vCenter 请访问原文链接:https://sysin.org/blog/vmware-vcenter-8-u3/ 查看最新版。原创作品,转载请保…

vue插件-less、less-loader样式管理

说明:有的项目采用的是less样式,浏览器不识别less样式,需要通过less、less-loader【安装5版本的】对less进行处理,把less样式变为css样式,浏览器才可以识别。另外引入的版本不宜过高,否则也会出现莫名奇妙的错误。安装命令如下: cnpm install --save less less-loader@5…

解决找不到文件端口问题

1.出现此问题是找不到该路径2.找到start.sh文件此为docker中访问网址路径3.找到conf文件夹下的nginx.conf文件并编辑 找到这个位置将root路径改为 root /xh/web;

字符编码发展史6 — BOM字节序标记

上一篇《字符编码发展史5 — UTF-16和UTF-32》我们讲解了UTF-16和UTF-32编码。本篇我们将继续讲解字符编码中的字节序标记(BOM)。 2.3. 第三个阶段 国际化 2.3.2. Unicode的编码方式 2.3.2.5. BOM 1. 什么是BOM? BOM是Byte Order Mark的缩写,翻译成中文是:字节序标记,主要用…

解决docker启动数据库

1.用docker下载数据库并启动2.若启动失败显示端口被占用 删除虚拟机下载的数据库删除占用的端口号

系统设计 - 笔记

参考 https://www.zhihu.com/question/268090534

回忆上了发条

该文被密码保护。...该文被密码保护。 GGrun happy! happy~ ha~ppy来自WPS 你爱我我爱你我们两个甜蜜蜜~来自 HDK

Guava中的Joiner和Splitter

目录Guava 介绍Joinerlist转stringmap转string处理嵌套集合处理null值Splitterstring转liststring转map多个拆分符输出代码 Guava 介绍 Guava 是 Google 开发的一个开源 Java 库,提供一系列核心功能增强 Java 的标准库。 它包含许多有用的工具和集合类,使 Java 开发更加高效,…

十二、pytorch的基础知识

1、快捷命令2、TensorTensor是PyTorch中重要的数据结构,可认为是一个高维数组。它可以是一个数(标量)、一维数组(向量)、二维数组(矩阵)以及更高维的数组。Tensor和Numpy的ndarrays类似,但Tensor可以使用GPU进行加速。Tensor的基本使用: from __future__ import print…

还在花钱做GIS影像切片?GISBox帮你免费搞定!

GIS影像切片是指将大范围的地理影像数据切割成多个小块,以便更高效地存储、处理和显示。这种技术广泛应用于地图服务、地理信息系统(GIS)、三维可视化等领域,尤其在需要显示大规模地理数据时,通过切片可以显著提升渲染速度和用户体验。目前许多提供GIS影像切片服务的产品都…

硬货!Zabbix监控AIX系统服务案例

本文将介绍如何使用Zabbix自定义键值脚本方式监控AIX 系统IBM CICS中间件进程服务以及日志文件等信息。 Customer Information Control System (CICS) Transaction Server 是 IBM 针对 z/OS 的多用途事务处理软件。这是一个功能强大的应用程序服务器,用于大型和小型企业中的事…

获取pytdx行情服务器ip和port

之前一直用的api.connect(124.71.187.122, 7709)突然不能用了,调查了一下,给出如下解决方案 打开通达信客户端,选项->通讯设置。勾掉"登录时查找最快的主站",手动选择"行情主站",点确定。 点击"选项"中的"断开行情主站",再点…