get_brand_wcpay_request:ok 支付成功 get_brand_wcpay_request:cancel 支付過程中用戶取消 get_brand_wcpay_request:fail 支付失敗<\/p><\/td><\/tr><\/tbody><\/table> 表6-6 getBrandWCPayRequest返回值<\/p> JS API的返回結(jié)果 get_brand_wcpay_request:ok 僅在用戶成功完成支付時返回。由于前端交互復(fù)雜,get_brand_wcpay_request:cancel 或者 get_brand_wcpay_request:fail 可以統(tǒng)一處理為用戶遇到錯誤或者\r\n\r\n主動放棄,不必細化區(qū)分。<\/p> pay.aspx后臺頁面代碼:<\/p> \r\n wxJsApiParam { ; ; } \r\n Money { ; OrderId { ; orderMoneySum { ; ; }\r\n orderProductName { ; ; }\r\n Page_Load( (!= JsApiPay( total_fee = Request[\r\n orderMoneySum = ParkName = Request[= ParkName+= Request[ (.IsNullOrWhiteSpace(total_fee)||total_fee== WxPayException( + + =.Parse((Convert.ToDouble(total_fee)*= (Convert.ToDouble(jsApiPay.total_fee)\/=\r\n (Common.OpenId == WxPayException(=== jsApiPay.GetJsApiParameters(); + + \r\n\r\nex.InnerException.Message + + + ex.Message +<\/pre>在這里需要我們注意的是:jsApiPay.openid = common.GetOpenId();<\/p> 在支付的時候,我們需要首先獲取用戶的openId,然而獲取用戶openId的這個過程我們首先要進行Oauth2認證,在官方的demo中提供了JsApiPay.cs這個核心類庫,里面已經(jīng)有這個GetOpenidAndAccessToken()方法 。我這里是拿過來寫成了自己的一個公共幫助類。Common.cs<\/p> \/\/\/ \r\n \/\/\/ 公共幫助類 \/\/\/ <\/summary>\r\n public class Common\r\n { private HttpContext Context { get; set; } public static string OpenId = \"Openid\"; public static string access_token = \"access_token\"; #region 構(gòu)造函數(shù) \/\/\/ \r\n \/\/\/ 構(gòu)造函數(shù) \/\/\/ <\/summary>\r\n \/\/\/ <\/param>\r\n public Common(HttpContext context)\r\n { this.Context = context;\r\n } \r\n #endregion\r\n\r\n\r\n #region 通過code換取AccessToken \/\/\/ \r\n \/\/\/ 通過code換取AccessToken \/\/\/ <\/summary>\r\n public void GetOpenidAndAccessToken()\r\n { if (!string.IsNullOrEmpty(Context.Request.QueryString[\"code\"]))\r\n { \/\/獲取code碼,以獲取openid和access_token\r\n string code = Context.Request.QueryString[\"code\"]; GetOpenidAndAccessTokenFromCode(code);\r\n } else\r\n { \/\/構(gòu)造網(wǎng)頁授權(quán)獲取code的URL\r\n string host = Context.Request.Url.Host;\r\n string path = Context.Request.Path; string redirect_uri = HttpUtility.UrlEncode(\"http:\/\/\" + host + path);\r\n\r\n\r\n WxPayData data = new WxPayData();\r\n data.SetValue(\"appid\", \r\n\r\nWxPayConfig.APPID);\r\n data.SetValue(\"redirect_uri\", redirect_uri);\r\n data.SetValue(\"response_type\", \"code\");\r\n data.SetValue(\"scope\", \"snsapi_base\");\r\n data.SetValue(\"state\", \"STATE\" + \"#wechat_redirect\"); string url = \"https:\/\/open.weixin.qq.com\/connect\/oauth2\/authorize?\" + data.ToUrl(); try\r\n { \/\/觸發(fā)微信返回code碼 \r\n Context.Response.Redirect(url);\/\/Redirect函數(shù)會拋出ThreadAbortException異常,不用處理這個異常 } catch (System.Threading.ThreadAbortException ex)\r\n {\r\n }\r\n }\r\n } \r\n #endregion\r\n\r\n #region 通過用戶授權(quán)獲取AccessToken和OpenId \/\/\/ \r\n \/\/\/ 通過用戶授權(quán)獲取AccessToken和OpenId \/\/\/ <\/summary>\r\n \/\/\/ <\/param>\r\n public void GetOpenidAndAccessTokenFromCode(string code)\r\n { try\r\n { \/\/構(gòu)造獲取openid及access_token的url\r\n WxPayData data = new WxPayData();\r\n data.SetValue(\"appid\", \r\n\r\nWxPayConfig.APPID);\r\n data.SetValue(\"secret\", \r\n\r\nWxPayConfig.APPSECRET);\r\n data.SetValue(\"code\", \r\n\r\ncode);\r\n data.SetValue(\"grant_type\", \"authorization_code\"); string url = \"https:\/\/api.weixin.qq.com\/sns\/oauth2\/access_token?\" + data.ToUrl(); \/\/請求url以獲取數(shù)據(jù)\r\n string result = HttpService.Get(url); \/\/保存access_token,用于收貨地址獲取\r\n JsonData jd = JsonMapper.ToObject(result);\r\n access_token = (string)jd[\"access_token\"]; \/\/獲取用戶openid\r\n OpenId = (string)jd[\"openid\"];\r\n } catch (Exception ex)\r\n { throw new WxPayException(ex.ToString());\r\n }\r\n } \r\n #endregion\r\n\r\n #region 獲取OpenId \/\/\/ \r\n \/\/\/ 獲取OpenId \/\/\/ <\/summary>\r\n \/\/\/ <\/param>\r\n \/\/\/ <\/returns>\r\n public string GetOpenId()\r\n {\r\n Common common = new Common(Context);\r\n common.GetOpenidAndAccessToken(); return OpenId; } \r\n #endregion\r\n }<\/pre> <\/p>
public class JsApiPay\r\n { \/\/\/ \r\n \/\/\/ 保存頁面對象,因為要在類的方法中使用Page的Request對象 \/\/\/ <\/summary>\r\n private Page page {get;set;} \/\/\/ \r\n \/\/\/ openid用于調(diào)用統(tǒng)一下單接口 \/\/\/ <\/summary>\r\n public string openid { get; set; } \/\/\/ \r\n \/\/\/ access_token用于獲取收貨地址js函數(shù)入口參數(shù) \/\/\/ <\/summary>\r\n public string access_token { get; set; } \/\/\/ \r\n \/\/\/ 商品金額,用于統(tǒng)一下單 \/\/\/ <\/summary>\r\n public int total_fee { get; set; } \/\/\/ \r\n \/\/\/ 訂單Id \/\/\/ <\/summary>\r\n public string orderid { get; set; } \/\/\/ \r\n \/\/\/ 統(tǒng)一下單接口返回結(jié)果 \/\/\/ <\/summary>\r\n public WxPayData unifiedOrderResult { get; set; } \r\n\r\n public JsApiPay(Page page)\r\n { this.page = page;\r\n } \/**\r\n * \r\n * 網(wǎng)頁授權(quán)獲取用戶基本信息的全部過程\r\n * 詳情請參看網(wǎng)頁授權(quán)獲取用戶基本信息:http:\/\/mp.weixin.qq.com\/wiki\/17\/c0f37d5704f0b64713d5d2c37b468d75.html\r\n * 第一步:利用url跳轉(zhuǎn)獲取code\r\n * 第二步:利用code去獲取openid和access_token\r\n * \r\n *\/\r\n public void GetOpenidAndAccessToken()\r\n { if (!string.IsNullOrEmpty(page.Request.QueryString[\"code\"]))\r\n { \/\/獲取code碼,以獲取openid和access_token\r\n string code = page.Request.QueryString[\"code\"]; \/\/Log.Debug(this.GetType().ToString(), \"Get code : \" + code); GetOpenidAndAccessTokenFromCode(code);\r\n } else\r\n { \/\/構(gòu)造網(wǎng)頁授權(quán)獲取code的URL\r\n string host = page.Request.Url.Host; \/\/Log.Debug(this.GetType().ToString(), \"host\" + host);\r\n string path = page.Request.Path; string redirect_uri = HttpUtility.UrlEncode(\"http:\/\/\" + host + path);\r\n \r\n\r\n WxPayData data = new WxPayData();\r\n data.SetValue(\"appid\", \r\n\r\nWxPayConfig.APPID);\r\n data.SetValue(\"redirect_uri\", redirect_uri);\r\n data.SetValue(\"response_type\", \"code\");\r\n data.SetValue(\"scope\", \"snsapi_base\");\r\n data.SetValue(\"state\", \"STATE\" + \"#wechat_redirect\"); string url = \"https:\/\/open.weixin.qq.com\/connect\/oauth2\/authorize?\" + data.ToUrl();\r\n Log.Debug(this.GetType().ToString(), \"Will Redirect to URL : \r\n\r\n\" + url); try\r\n { \/\/觸發(fā)微信返回code碼 \r\n page.Response.Redirect(url);\/\/Redirect函數(shù)會拋出ThreadAbortException異常,不用處理這個異常 } catch(System.Threading.ThreadAbortException ex)\r\n {\r\n }\r\n }\r\n } \/**\r\n * \r\n * 通過code換取網(wǎng)頁授權(quán)access_token和openid的返回數(shù)據(jù),正確時返回的JSON數(shù)據(jù)包如下:\r\n * {\r\n * \"access_token\":\"ACCESS_TOKEN\",\r\n * \"expires_in\":7200,\r\n * \"refresh_token\":\"REFRESH_TOKEN\",\r\n * \"openid\":\"OPENID\",\r\n * \"scope\":\"SCOPE\",\r\n * \"unionid\": \"o6_bmasdasdsad6_2sgVt7hMZOPfL\"\r\n * }\r\n * 其中access_token可用于獲取共享收貨地址\r\n * openid是微信支付jsapi支付接口統(tǒng)一下單時必須的參數(shù)\r\n * 更詳細的說明請參考網(wǎng)頁授權(quán)獲取用戶基本信息:http:\/\/mp.weixin.qq.com\/wiki\/17\/c0f37d5704f0b64713d5d2c37b468d75.html\r\n * @失敗時拋異常WxPayException *\/\r\n public void GetOpenidAndAccessTokenFromCode(string code)\r\n { try\r\n { \/\/構(gòu)造獲取openid及access_token的url\r\n WxPayData data = new WxPayData();\r\n data.SetValue(\"appid\", \r\n\r\nWxPayConfig.APPID);\r\n data.SetValue(\"secret\", \r\n\r\nWxPayConfig.APPSECRET);\r\n data.SetValue(\"code\", \r\n\r\ncode);\r\n data.SetValue(\"grant_type\", \"authorization_code\"); string url = \"https:\/\/api.weixin.qq.com\/sns\/oauth2\/access_token?\" + data.ToUrl(); \/\/請求url以獲取數(shù)據(jù)\r\n string result = HttpService.Get(url); \/\/Log.Debug(this.GetType().ToString(), \"GetOpenidAndAccessTokenFromCode response : \" + result); \/\/保存access_token,用于收貨地址獲取\r\n JsonData jd = JsonMapper.ToObject(result);\r\n access_token = (string)jd[\"access_token\"]; \/\/獲取用戶openid\r\n openid = (string)jd[\"openid\"]; \/\/Log.Debug(this.GetType().ToString(), \"Get openid : \" + openid); \/\/Log.Debug(this.GetType().ToString(), \"Get access_token : \" + access_token); } catch (Exception ex)\r\n {\r\n Log.Error(this.GetType().ToString(), ex.ToString()); throw new WxPayException(ex.ToString());\r\n }\r\n } \/**\r\n * 調(diào)用統(tǒng)一下單,獲得下單結(jié)果\r\n * @return 統(tǒng)一下單結(jié)果\r\n * @失敗時拋異常WxPayException *\/\r\n public WxPayData GetUnifiedOrderResult()\r\n { \/\/統(tǒng)一下單\r\n WxPayData data = new WxPayData();\r\n data.SetValue(\"body\", \"test\"); \/\/data.SetValue(\"attach\", \"test\");\r\n data.SetValue(\"out_trade_no\", \r\n\r\nWxPayApi.GenerateOutTradeNo());\r\n data.SetValue(\"total_fee\", \r\n\r\ntotal_fee);\r\n data.SetValue(\"time_start\", DateTime.Now.ToString(\"yyyyMMddHHmmss\"));\r\n data.SetValue(\"time_expire\", DateTime.Now.AddMinutes(10).ToString(\"yyyyMMddHHmmss\")); \/\/data.SetValue(\"goods_tag\", \"test\");\r\n data.SetValue(\"trade_type\", \"JSAPI\");\r\n data.SetValue(\"openid\", \r\n\r\nopenid);\r\n data.SetValue(\"orderid\", \r\n\r\norderid);\r\n\r\n WxPayData result = WxPayApi.UnifiedOrder(data); if (!result.IsSet(\"appid\") || !result.IsSet(\"prepay_id\") || result.GetValue(\"prepay_id\").ToString() == \"\")\r\n {\r\n Log.Error(this.GetType().ToString(), \"UnifiedOrder response \r\n\r\nerror!\"); throw new WxPayException(\"UnifiedOrder response error!\");\r\n }\r\n\r\n unifiedOrderResult = result; return result;\r\n } public WxPayData GetUnifiedOrderResult(string body)\r\n { \/\/統(tǒng)一下單\r\n WxPayData data = new WxPayData();\r\n data.SetValue(\"body\", body); \/\/data.SetValue(\"attach\", \"test\");\r\n data.SetValue(\"out_trade_no\", \r\n\r\nWxPayApi.GenerateOutTradeNo());\r\n data.SetValue(\"total_fee\", \r\n\r\ntotal_fee); \/\/data.SetValue(\"time_start\", DateTime.Now.ToString(\"yyyyMMddHHmmss\")); \/\/data.SetValue(\"time_expire\", DateTime.Now.AddMinutes(10).ToString(\"yyyyMMddHHmmss\")); \/\/data.SetValue(\"goods_tag\", \"test\");\r\n data.SetValue(\"trade_type\", \"JSAPI\");\r\n data.SetValue(\"openid\", \r\n\r\nopenid);\r\n\r\n\r\n WxPayData result = WxPayApi.UnifiedOrder(data); if (!result.IsSet(\"appid\") || !result.IsSet(\"prepay_id\") || result.GetValue(\"prepay_id\").ToString() == \"\")\r\n {\r\n Log.Error(this.GetType().ToString(), \"UnifiedOrder response \r\n\r\nerror!\"); throw new WxPayException(\"UnifiedOrder response error!\");\r\n }\r\n\r\n unifiedOrderResult = result; return result;\r\n } \/**\r\n * \r\n * 從統(tǒng)一下單成功返回的數(shù)據(jù)中獲取微信瀏覽器調(diào)起jsapi支付所需的參數(shù),\r\n * 微信瀏覽器調(diào)起JSAPI時的輸入?yún)?shù)格式如下:\r\n * {\r\n * \"appId\" : \"wx2421b1c4370ec43b\", \/\/公眾號名稱,由商戶傳入 \r\n * \"timeStamp\":\" 1395712654\", \/\/時間戳,自1970年以來的秒數(shù) \r\n * \"nonceStr\" : \"e61463f8efa94090b1f366cccfbbb444\", \/\/隨機串 \r\n * \"package\" : \"prepay_id=u802345jgfjsdfgsdg888\", \r\n * \"signType\" : \"MD5\", \/\/微信簽名方式: \r\n * \"paySign\" : \"70EA570631E4BB79628FBCA90534C63FF7FADD89\" \/\/微信簽名 \r\n * }\r\n * @return string 微信瀏覽器調(diào)起JSAPI時的輸入?yún)?shù),json格式可以直接做參數(shù)用\r\n * 更詳細的說明請參考網(wǎng)頁端調(diào)起支付API:http:\/\/pay.weixin.qq.com\/wiki\/doc\/api\/jsapi.php?chapter=7_7\r\n * \r\n *\/\r\n public string GetJsApiParameters()\r\n {\r\n\r\n WxPayData jsApiParam = new WxPayData();\r\n jsApiParam.SetValue(\"appId\", unifiedOrderResult.GetValue\r\n\r\n(\"appid\"));\r\n jsApiParam.SetValue(\"timeStamp\", WxPayApi.GenerateTimeStamp());\r\n jsApiParam.SetValue(\"nonceStr\", WxPayApi.GenerateNonceStr());\r\n jsApiParam.SetValue(\"package\", \"prepay_id=\" + unifiedOrderResult.GetValue(\"prepay_id\"));\r\n jsApiParam.SetValue(\"signType\", \"MD5\");\r\n jsApiParam.SetValue(\"paySign\", jsApiParam.MakeSign()); string parameters = jsApiParam.ToJson(); return parameters;\r\n } \/**\r\n * \r\n * 獲取收貨地址js函數(shù)入口參數(shù),詳情請參考收貨地址共享接口:http:\/\/pay.weixin.qq.com\/wiki\/doc\/api\/jsapi.php?\r\n\r\nchapter=7_9\r\n * @return string 共享收貨地址js函數(shù)需要的參數(shù),json格式可以直接做參數(shù)使用 *\/\r\n public string GetEditAddressParameters()\r\n { string parameter = \"\"; try\r\n { string host = page.Request.Url.Host; string path = page.Request.Path; string queryString = page.Request.Url.Query; \/\/這個地方要注意,參與簽名的是網(wǎng)頁授權(quán)獲取用戶信息時微信后臺回傳的完整url\r\n string url = \"http:\/\/\" + \r\n\r\nhost + path + queryString; \/\/構(gòu)造需要用SHA1算法加密的數(shù)據(jù)\r\n WxPayData signData = new WxPayData();\r\n signData.SetValue(\"appid\",WxPayConfig.APPID);\r\n signData.SetValue(\"url\", \r\n\r\nurl);\r\n signData.SetValue(\"timestamp\",WxPayApi.GenerateTimeStamp());\r\n signData.SetValue(\"noncestr\",WxPayApi.GenerateNonceStr());\r\n signData.SetValue(\"accesstoken\",access_token); string param = signData.ToUrl();\r\n\r\n Log.Debug(this.GetType().ToString(), \"SHA1 encrypt param : \r\n\r\n\" + param); \/\/SHA1加密\r\n string addrSign = FormsAuthentication.HashPasswordForStoringInConfigFile(param, \"SHA1\");\r\n Log.Debug(this.GetType().ToString(), \"SHA1 encrypt result : \r\n\r\n\" + addrSign); \/\/獲取收貨地址js函數(shù)入口參數(shù)\r\n WxPayData afterData = new WxPayData();\r\n afterData.SetValue(\"appId\",WxPayConfig.APPID);\r\n afterData.SetValue(\"scope\",\"jsapi_address\");\r\n afterData.SetValue(\"signType\",\"sha1\");\r\n afterData.SetValue(\"addrSign\",addrSign);\r\n afterData.SetValue(\"timeStamp\",signData.GetValue(\"timestamp\"));\r\n afterData.SetValue(\"nonceStr\",signData.GetValue(\"noncestr\")); \/\/轉(zhuǎn)為json格式\r\n parameter = afterData.ToJson();\r\n Log.Debug(this.GetType().ToString(), \"Get EditAddressParam : \r\n\r\n\" + parameter);\r\n } catch (Exception ex)\r\n {\r\n Log.Error(this.GetType().ToString(), ex.ToString()); throw new WxPayException(ex.ToString());\r\n } return parameter;\r\n }\r\n }<\/pre>JsApiPay<\/span><\/p> 微信支付協(xié)議接口數(shù)據(jù)類WxPayData.cs官方都有相應(yīng)的代碼.<\/p>  <\/p>
\/\/\/ \r\n \/\/\/ 微信支付協(xié)議接口數(shù)據(jù)類,所有的API接口通信都依賴這個數(shù)據(jù)結(jié)構(gòu), \/\/\/ 在調(diào)用接口之前先填充各個字段的值,然后進行接口通信, \/\/\/ 這樣設(shè)計的好處是可擴展性強,用戶可隨意對協(xié)議進行更改而不用重新設(shè)計數(shù)據(jù)結(jié)構(gòu), \/\/\/ 還可以隨意組合出不同的協(xié)議數(shù)據(jù)包,不用為每個協(xié)議設(shè)計一個數(shù)據(jù)包結(jié)構(gòu) \/\/\/ <\/summary>\r\n public class WxPayData\r\n { public WxPayData()\r\n {\r\n\r\n } \/\/采用排序的Dictionary的好處是方便對數(shù)據(jù)包進行簽名,不用再簽名之前再做一次排序\r\n private SortedDictionary m_values = new SortedDictionary(); \/**\r\n * 設(shè)置某個字段的值\r\n * @param key 字段名\r\n * @param value 字段值 *\/\r\n public void SetValue(string key, object value)\r\n {\r\n m_values[key] = value;\r\n } \/**\r\n * 根據(jù)字段名獲取某個字段的值\r\n * @param key 字段名\r\n * @return key對應(yīng)的字段值 *\/\r\n public object GetValue(string key)\r\n { object o = null;\r\n m_values.TryGetValue(key, out o); return o;\r\n } \/**\r\n * 判斷某個字段是否已設(shè)置\r\n * @param key 字段名\r\n * @return 若字段key已被設(shè)置,則返回true,否則返回false *\/\r\n public bool IsSet(string key)\r\n { object o = null;\r\n m_values.TryGetValue(key, out o); if (null != o) return true; else\r\n return false;\r\n } \/**\r\n * @將Dictionary轉(zhuǎn)成xml\r\n * @return 經(jīng)轉(zhuǎn)換得到的xml串\r\n * @throws WxPayException\r\n **\/\r\n public string ToXml()\r\n { \/\/數(shù)據(jù)為空時不能轉(zhuǎn)化為xml格式\r\n if (0 == m_values.Count)\r\n {\r\n Log.Error(this.GetType().ToString(), \"WxPayData數(shù)據(jù)為空!\"); throw new WxPayException(\"WxPayData數(shù)據(jù)為空!\");\r\n } string xml = \"\"; foreach (KeyValuePair pair in m_values)\r\n { \/\/字段值不能為null,會影響后續(xù)流程\r\n if (pair.Value == null)\r\n {\r\n Log.Error(this.GetType().ToString(), \"WxPayData內(nèi)部含有值\r\n\r\n為null的字段!\"); throw new WxPayException(\"WxPayData內(nèi)部含有值為null的字段!\");\r\n } if (pair.Value.GetType() == typeof(int))\r\n {\r\n xml += \"<\" + pair.Key + \">\" + pair.Value + \"<\/\" + pair.Key + \">\";\r\n } else if (pair.Value.GetType() == typeof(string))\r\n {\r\n xml += \"<\" + pair.Key + \">\" + \"<\/\" + \r\n\r\npair.Key + \">\";\r\n } else\/\/除了string和int類型不能含有其他數(shù)據(jù)類型 {\r\n Log.Error(this.GetType().ToString(), \"WxPayData字段數(shù)據(jù)類\r\n\r\n型錯誤!\"); throw new WxPayException(\"WxPayData字段數(shù)據(jù)類型錯誤!\");\r\n }\r\n }\r\n xml += \"<\/xml>\"; return xml;\r\n } \/**\r\n * @將xml轉(zhuǎn)為WxPayData對象并返回對象內(nèi)部的數(shù)據(jù)\r\n * @param string 待轉(zhuǎn)換的xml串\r\n * @return 經(jīng)轉(zhuǎn)換得到的Dictionary\r\n * @throws WxPayException *\/\r\n public SortedDictionary FromXml(string xml)\r\n { if (string.IsNullOrEmpty(xml))\r\n {\r\n Log.Error(this.GetType().ToString(), \"將空的xml串轉(zhuǎn)換為\r\n\r\nWxPayData不合法!\"); throw new WxPayException(\"將空的xml串轉(zhuǎn)換為WxPayData不合法!\");\r\n }\r\n\r\n XmlDocument xmlDoc = new XmlDocument();\r\n xmlDoc.LoadXml(xml);\r\n XmlNode xmlNode = xmlDoc.FirstChild;\/\/獲取到根節(jié)點\r\n XmlNodeList nodes = xmlNode.ChildNodes; foreach (XmlNode xn in nodes)\r\n {\r\n XmlElement xe = (XmlElement)xn;\r\n m_values[xe.Name] = xe.InnerText;\/\/獲取xml的鍵值對到WxPayData內(nèi)部的數(shù)據(jù)中 } \r\n try\r\n { \/\/2015-06-29 錯誤是沒有簽名\r\n if(m_values[\"return_code\"] != \"SUCCESS\")\r\n { return m_values;\r\n }\r\n CheckSign();\/\/驗證簽名,不通過會拋異常 } catch(WxPayException ex)\r\n { throw new WxPayException(ex.Message);\r\n } return m_values;\r\n } \/**\r\n * @Dictionary格式轉(zhuǎn)化成url參數(shù)格式\r\n * @ return url格式串, 該串不包含sign字段值 *\/\r\n public string ToUrl()\r\n { string buff = \"\"; foreach (KeyValuePair pair in m_values)\r\n { if (pair.Value == null)\r\n {\r\n Log.Error(this.GetType().ToString(), \"WxPayData內(nèi)部含有值\r\n\r\n為null的字段!\"); throw new WxPayException(\"WxPayData內(nèi)部含有值為null的字段!\");\r\n } if (pair.Key != \"sign\" && pair.Value.ToString() != \"\")\r\n {\r\n buff += pair.Key + \"=\" + pair.Value + \"&\";\r\n }\r\n }\r\n buff = buff.Trim('&'); return buff;\r\n } \/**\r\n * @Dictionary格式化成Json\r\n * @return json串?dāng)?shù)據(jù) *\/\r\n public string ToJson()\r\n { string jsonStr = JsonMapper.ToJson(m_values); return jsonStr;\r\n } \/**\r\n * @values格式化成能在Web頁面上顯示的結(jié)果(因為web頁面上不能直接輸出xml格式的字符串) *\/\r\n public string ToPrintStr()\r\n { string str = \"\"; foreach (KeyValuePair pair in m_values)\r\n { if (pair.Value == null)\r\n {\r\n Log.Error(this.GetType().ToString(), \"WxPayData內(nèi)部含有值\r\n\r\n為null的字段!\"); throw new WxPayException(\"WxPayData內(nèi)部含有值為null的字段!\");\r\n }\r\n\r\n str += string.Format(\"{0}={1} \", pair.Key, pair.Value.ToString());\r\n }\r\n Log.Debug(this.GetType().ToString(), \"Print in Web Page : \r\n\r\n\" + str); return str;\r\n } \/**\r\n * @生成簽名,詳見簽名生成算法\r\n * @return 簽名, sign字段不參加簽名 *\/\r\n public string MakeSign()\r\n { \/\/轉(zhuǎn)url格式\r\n string str = ToUrl(); \/\/在string后加入API KEY\r\n str += \"&key=\" + WxPayConfig.KEY; \/\/MD5加密\r\n var md5 = MD5.Create(); var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); var sb = new StringBuilder(); foreach (byte b in bs)\r\n {\r\n sb.Append(b.ToString(\"x2\"));\r\n } \/\/所有字符轉(zhuǎn)為大寫\r\n return sb.ToString().ToUpper();\r\n } \/**\r\n * \r\n * 檢測簽名是否正確\r\n * 正確返回true,錯誤拋異常 *\/\r\n public bool CheckSign()\r\n { \/\/如果沒有設(shè)置簽名,則跳過檢測\r\n if (!IsSet(\"sign\"))\r\n {\r\n Log.Error(this.GetType().ToString(), \"WxPayData簽名存在但不合法\r\n\r\n!\"); throw new WxPayException(\"WxPayData簽名存在但不合法!\");\r\n } \/\/如果設(shè)置了簽名但是簽名為空,則拋異常\r\n else if(GetValue(\"sign\") == null || GetValue(\"sign\").ToString() == \"\")\r\n {\r\n Log.Error(this.GetType().ToString(), \"WxPayData簽名存在但不合\r\n\r\n法!\"); throw new WxPayException(\"WxPayData簽名存在但不合法!\");\r\n } \/\/獲取接收到的簽名\r\n string return_sign = GetValue(\"sign\").ToString(); \/\/在本地計算新的簽名\r\n string cal_sign = MakeSign(); if (cal_sign == return_sign)\r\n { return true;\r\n }\r\n\r\n Log.Error(this.GetType().ToString(), \"WxPayData簽名驗證錯誤!\"); throw new WxPayException(\"WxPayData簽名驗證錯誤!\");\r\n } \/**\r\n * @獲取Dictionary *\/\r\n public SortedDictionary GetValues()\r\n { return m_values;\r\n }\r\n }<\/pre>WxPayData<\/span><\/p> 配置文件信息<\/p>  <\/p>
\/**\r\n * 配置賬號信息 *\/\r\n public class WxPayConfig\r\n { \/\/=======【基本信息設(shè)置】=====================================\r\n \/* 微信公眾號信息配置\r\n * APPID:綁定支付的APPID(必須配置)\r\n * MCHID:商戶號(必須配置)\r\n * KEY:商戶支付密鑰,參考開戶郵件設(shè)置(必須配置)\r\n * APPSECRET:公眾帳號secert(僅JSAPI支付的時候需要配置) *\/\r\n public const string APPID = \"wx14e3e56f3\"; public const string MCHID = \"12352\"; public const string KEY = \"BB6BE71D7CED49A79409C9\"; public const string APPSECRET = \"76eb33f66129692da1624f1\"; \/\/=======【證書路徑設(shè)置】===================================== \r\n \/* 證書路徑,注意應(yīng)該填寫絕對路徑(僅退款、撤銷訂單時需要) *\/\r\n public const string SSLCERT_PATH = \"cert\/apiclient_cert.p12\"; public const string SSLCERT_PASSWORD = \"123502\"; \/\/=======【支付結(jié)果通知url】===================================== \r\n \/* 支付結(jié)果通知回調(diào)url,用于商戶接收支付結(jié)果 *\/\r\n public const string NOTIFY_URL = \"http:\/\/www.baidu.com\/ResultPay.aspx\"; \/\/=======【商戶系統(tǒng)后臺機器IP】===================================== \r\n \/* 此參數(shù)可手動配置也可在程序中自動獲取 *\/\r\n public const string IP = \"150.24.91.151\"; \/\/=======【代理服務(wù)器設(shè)置】===================================\r\n \/* 默認IP和端口號分別為0.0.0.0和0,此時不開啟代理(如有需要才設(shè)置) *\/\r\n public const string PROXY_URL = \"http:\/\/10.152.18.220:8080\"; \/\/=======【上報信息配置】===================================\r\n \/* 測速上報等級,0.關(guān)閉上報; 1.僅錯誤時上報; 2.全量上報 *\/\r\n public const int REPORT_LEVENL = 1; \/\/=======【日志級別】===================================\r\n \/* 日志等級,0.不輸出日志;1.只輸出錯誤信息; 2.輸出錯誤和正常信息; 3.輸出錯誤信息、正常信息和調(diào)試信息 *\/\r\n public const int LOG_LEVENL =3;\r\n }<\/pre>WxPayConfig<\/span><\/p> 接著我們在看2行關(guān)鍵的代碼:<\/p> WxPayData unifiedOrderResult == jsApiPay.GetJsApiParameters();<\/pre>此時如果wxJsApiParam變量能夠順利拿到值,那么我們前臺頁面的:<%=wxJsApiParam%>z這里就可以獲取到我們要傳遞的參數(shù),這時候就可以調(diào)用微信支付的接口,打開我們的付款頁面如圖所示:<\/p> \/\/調(diào)用微信JS api 支付 function jsApiCall()\r\n {\r\n WeixinJSBridge.invoke( 'getBrandWCPayRequest', <%=wxJsApiParam%>,\/\/josn串 function (res)\r\n { if (res.err_msg == \"get_brand_wcpay_request:ok\")\r\n { var OrderId=$(\"#OrderId\").val(); var orderProductName=$(\"#orderProductName\").val(); var orderMoneySum=$(\"#orderMoneySum\").val(); window.location.href=\"http:\/\/www.baodu.com\/PaySkip.aspx?OrderId=\"+OrderId+\"&orderMoneySum=\"+orderMoneySum+\"&orderProductName=\"+orderProductName;\r\n\r\n }else\r\n {\r\n WeixinJSBridge.call('closeWindow');\r\n }\r\n \r\n }\r\n );\r\n }<\/pre> <\/p>
(JsApiPay.cs)得到下單結(jié)果:<\/p> public WxPayData GetUnifiedOrderResult(string body)\r\n { \/\/統(tǒng)一下單\r\n WxPayData data = new WxPayData();\r\n data.SetValue(\"body\", \r\n\r\nbody);\r\n data.SetValue(\"out_trade_no\", \r\n\r\nWxPayApi.GenerateOutTradeNo());\r\n data.SetValue(\"total_fee\", \r\n\r\ntotal_fee);\r\n data.SetValue(\"trade_type\", \"JSAPI\");\r\n data.SetValue(\"openid\", \r\n\r\nopenid); WxPayData result = WxPayApi.UnifiedOrder(data); if (!result.IsSet(\"appid\") || !result.IsSet(\"prepay_id\") || result.GetValue(\"prepay_id\").ToString() == \"\")\r\n {\r\n Log.Error(this.GetType().ToString(), \"UnifiedOrder response \r\n\r\nerror!\"); throw new WxPayException(\"UnifiedOrder response error!\");\r\n }\r\n\r\n unifiedOrderResult = result; return result;\r\n }<\/pre>(WxPayApi.cs)統(tǒng)一下單接口:<\/p> \/**\r\n * \r\n * 統(tǒng)一下單\r\n * @param WxPaydata inputObj 提交給統(tǒng)一下單API的參數(shù)\r\n * @param int timeOut 超時時間\r\n * @throws WxPayException\r\n * @return 成功時返回,其他拋異常 *\/\r\n public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut = \r\n\r\n6)\r\n { string url = \"https:\/\/api.mch.weixin.qq.com\/pay\/unifiedorder\"; \/\/檢測必填參數(shù)\r\n if (!inputObj.IsSet(\"out_trade_no\"))\r\n { throw new WxPayException(\"缺少統(tǒng)一支付接口必填參數(shù)out_trade_no!\");\r\n } else if (!inputObj.IsSet(\"body\"))\r\n { throw new WxPayException(\"缺少統(tǒng)一支付接口必填參數(shù)body!\");\r\n } else if (!inputObj.IsSet(\"total_fee\"))\r\n { throw new WxPayException(\"缺少統(tǒng)一支付接口必填參數(shù)total_fee!\");\r\n } else if (!inputObj.IsSet(\"trade_type\"))\r\n { throw new WxPayException(\"缺少統(tǒng)一支付接口必填參數(shù)trade_type!\");\r\n } \/\/關(guān)聯(lián)參數(shù)\r\n if (inputObj.GetValue(\"trade_type\").ToString() == \"JSAPI\" && !inputObj.IsSet(\"openid\"))\r\n { throw new WxPayException(\"統(tǒng)一支付接口中,缺少必填參數(shù)openid!trade_type為JSAPI時,openid為必填參數(shù)!\");\r\n } if (inputObj.GetValue(\"trade_type\").ToString() == \"NATIVE\" && !inputObj.IsSet(\"product_id\"))\r\n { throw new WxPayException(\"統(tǒng)一支付接口中,缺少必填參數(shù)product_id!trade_type為JSAPI時,product_id為必填參數(shù)!\");\r\n } \/\/異步通知url未設(shè)置,則使用配置文件中的url\r\n if (!inputObj.IsSet(\"notify_url\"))\r\n {\r\n inputObj.SetValue(\"notify_url\", \r\n\r\nWxPayConfig.NOTIFY_URL);\/\/異步通知url }\r\n\r\n inputObj.SetValue(\"appid\", WxPayConfig.APPID);\/\/公眾賬號ID\r\n inputObj.SetValue(\"mch_id\", WxPayConfig.MCHID);\/\/商戶號\r\n inputObj.SetValue(\"spbill_create_ip\", WxPayConfig.IP);\/\/終端ip \r\n inputObj.SetValue(\"nonce_str\", GenerateNonceStr());\/\/隨機字符串 \/\/簽名\r\n inputObj.SetValue(\"sign\", \r\n\r\ninputObj.MakeSign()); string xml = inputObj.ToXml(); var start = DateTime.Now;\r\n string response = HttpService.Post(xml, url, false, timeOut);\r\n var end = DateTime.Now; int timeCost = (int)((end - start).TotalMilliseconds);\r\n\r\n WxPayData result = new WxPayData();\r\n result.FromXml(response);\r\n\r\n ReportCostTime(url, timeCost, result);\/\/測速上報\r\n\r\n return result;\r\n }<\/pre>四.最終開發(fā)的效果<\/h4>\n   <\/p>\n
五.微信公眾號開發(fā)系列導(dǎo)航<\/h4>\n1.0初始微信公眾號<\/p>\n 2.0創(chuàng)建自定義菜單<\/p>\n 3.0查詢自定義菜單<\/p>\n 4.0公眾號消息處理<\/p>\n 5.0微信支付<\/p>\n 6.0模板消息<\/p>"}
Heim
WeChat-Applet
WeChat-Entwicklung
Detailliertes Beispiel für die Entwicklung eines ?ffentlichen .NET WeChat-Kontos (5.0 WeChat-Zahlung).
Detailliertes Beispiel für die Entwicklung eines ?ffentlichen .NET WeChat-Kontos (5.0 WeChat-Zahlung).
May 03, 2017 am 10:31 AM
1. Vorwort
Bevor wir mit der Ausführung dieser Funktion beginnen, müssen wir zun?chst darüber nachdenken, wie wir diese WeChat-Zahlung durchführen, wo wir anfangen sollen, wo wir anfangen sollen, welche offiziellen SDK-Anweisungen wir haben So weiter, gibt es eine offizielle Demo und ob die Informationen, die mir der Chef gegeben hat, vollst?ndig sind und ob die zu beantragenden Schnittstellen verfügbar sind?
Nachdem ich dies auf Dr?ngen meines Chefs endlich abgeschlossen habe, werde ich hier eine Zusammenfassung erstellen. Meine F?higkeiten sind begrenzt . Wenn ich etwas gesagt habe, das nicht gut ist, hoffe ich, dass Sie es mit mir aushalten.
2. Vorbereitung vor der Entwicklung.
1.0 WeChat Pay offizielle Entwicklerdokumentation
2.0 offizieller Demo-Download Wir verwenden c#, also haben wir uns für die .net-Version entschieden, aber diese offizielle Demo l?uft überhaupt nicht
3.0 offizielle Demo l?uft L?sung
Die Fallstricke der offiziellen .net-Version von WeChat Payment 4.0 sind nicht verhandelbar
Einige Konfigurationen der ?ffentlichen WeChat-Plattform vor der Entwicklung von 5.0, bitte unbedingt überprüfen Die Konfiguration sorgf?ltig durchführen ??> Nach Abschluss dieser Vorbereitungen wissen wir, dass es zwei Arten der WeChat-Zahlung gibt: 1. Die ursprüngliche, 2. Die direkt von jsapi aufgerufene zweite wird in meinem Projekt verwendet Nach einiger Verarbeitung meiner eigenen Gesch?ftslogik gelangten wir zu unserer Seite mit den Bestelldetails. Zum Bezahlen müssen Sie nun auf unsere Zahlungsschaltfl?che klicken. Der pay.aspx-Code auf der Zahlungsseite lautet wie folgt:
Vorderseite Seite: 
Es ist zu beachten, dass:  WeChat JS API nur im integrierten Browser von WeChat verwendet werden kann und Aufrufe von anderen Browsern ungültig sind. WeChat stellt die getBrandWCPayRequest-Schnittstelle zum Aufrufen der Front-End-Webseite des H?ndlers bereit. WeChat identifiziert die Zahlungsautorit?t des H?ndlers, bevor er diese aufruft. Wenn der H?ndler berechtigt ist, die Zahlung einzuleiten, beginnt der Zahlungsvorgang. In diesem Abschnitt werden haupts?chlich die Schnittstellenaufrufregeln vor der Zahlung vorgestellt. Bitte beachten Sie den unten stehenden Mechanismus zur Benachrichtigung über den Zahlungsstatus. Zu beachten ist die Schnittstelle: Alle eingehenden Parameter sind vom Typ String! getBrandWCPayRequest-Parameter sind in Tabelle 6-5 aufgeführt.
Parameter <script type="text/javascript"> //調(diào)用微信JS api 支付 function jsApiCall()
{
WeixinJSBridge.invoke( 'getBrandWCPayRequest', <%=wxJsApiParam%>,//josn串 function (res)
{ if (res.err_msg == "get_brand_wcpay_request:ok")
{ var OrderId=$("#OrderId").val(); var orderProductName=$("#orderProductName").val(); var orderMoneySum=$("#orderMoneySum").val();
window.location.href="http://www.baidu.aspx?OrderId="+OrderId+"&orderMoneySum="+orderMoneySum+"&orderProductName="+orderProductName;//支付成功后的跳轉(zhuǎn)頁面
}else
{
WeixinJSBridge.call('closeWindow');
}
}
);
}
function callpay()
{ if (typeof WeixinJSBridge == "undefined")
{ if (document.addEventListener)
{
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
} else if (document.attachEvent)
{
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
} else
{
jsApiCall();
}
}
</script>
<body>
<p>
<br />
<br />
<br />
<input type="hidden" id="OrderId" name="OrderId" value="<%=OrderId %>"/>
<input type="hidden" id="orderMoneySum" name="orderMoneySum" value="<%=orderMoneySum %>"/>
<input type="hidden" id="orderProductName" name="orderProductName" value="<%=orderProductName %>"/>
<span class="fLeft" style="font-size:20px;color:Purple"> 您確認付款<label style="font-size:25px;color:Red"><%=Money%></label>元...</span>
<p><button type="button" class="btn-pay" title="確認支付" onclick="callpay()">立即支付</button></p>
</p>
</body>
</html> Name Erforderlich
| Format
| Beschreibung
| AppId | Offizielle Konto-ID Ja | String-TypEs kann erhalten werden, nachdem der H?ndler erfolgreich ein ?ffentliches Konto mit Zahlungserlaubnis registriert hat | | Zeitstempel | Zeitstempel | ist | String-Typ, weniger als 32 BytesVom H?ndler generiert, die Anzahl der Sekunden vom 1. Januar 1970 um 00:00:00 Uhr bis heute, d. h aktuelle Zeit, und muss schlie?lich in String-Form umgewandelt werden; ??> | ist | Zeichenfolgentyp, weniger als 32 Bytes | eine vom H?ndler generierte zuf?llige Zeichenfolge | Paket | Bestelldetails erweiterte Zeichenfolge | ist | String-Typ, weniger als 4096 Bytes | Der H?ndler fügt die Bestellinformationen in diesen String ein. Das spezifische Kompositionsschema finden Sie in der Hilfe zur Paketgruppierung in der Schnittstellenanleitung. ; Eingesplei?t vom H?ndler gem?? den Spezifikationen; Die Signaturmethode | ist ein Zeichenfolgentyp von | . Der Parameterwert ist ?SHA1“ wie im Dokument gezeigt. Unterstützt derzeit nur SHA1; | 簽名 | 是 | 字符串類型 | 商戶將接口列表中的參數(shù)按照指定方式迚行簽名,簽名方式使用signType中標(biāo)示的簽名方式,具體簽名方案參見接口使用說明中簽名幫劣;由商戶按照規(guī)范簽名后傳入; |
表6-5 getBrandWCPayRequest參數(shù) getBrandWCPayRequest返回值如表6-6所示。
返回值 | 說明 | err_msg | get_brand_wcpay_request:ok 支付成功 get_brand_wcpay_request:cancel 支付過程中用戶取消 get_brand_wcpay_request:fail 支付失敗 |
表6-6 getBrandWCPayRequest返回值 JS API的返回結(jié)果 get_brand_wcpay_request:ok 僅在用戶成功完成支付時返回。由于前端交互復(fù)雜,get_brand_wcpay_request:cancel 或者 get_brand_wcpay_request:fail 可以統(tǒng)一處理為用戶遇到錯誤或者
主動放棄,不必細化區(qū)分。 pay.aspx后臺頁面代碼:
wxJsApiParam { ; ; }
Money { ; OrderId { ; orderMoneySum { ; ; }
orderProductName { ; ; }
Page_Load( (!= JsApiPay( total_fee = Request[
orderMoneySum = ParkName = Request[= ParkName+= Request[ (.IsNullOrWhiteSpace(total_fee)||total_fee== WxPayException( + + =.Parse((Convert.ToDouble(total_fee)*= (Convert.ToDouble(jsApiPay.total_fee)/=
(Common.OpenId == WxPayException(=== jsApiPay.GetJsApiParameters(); + +
ex.InnerException.Message + + + ex.Message + 在這里需要我們注意的是:jsApiPay.openid = common.GetOpenId(); 在支付的時候,我們需要首先獲取用戶的openId,然而獲取用戶openId的這個過程我們首先要進行Oauth2認證,在官方的demo中提供了JsApiPay.cs這個核心類庫,里面已經(jīng)有這個GetOpenidAndAccessToken()方法 。我這里是拿過來寫成了自己的一個公共幫助類。Common.cs /// <summary>
/// 公共幫助類 /// </summary>
public class Common
{ private HttpContext Context { get; set; } public static string OpenId = "Openid"; public static string access_token = "access_token"; #region 構(gòu)造函數(shù) /// <summary>
/// 構(gòu)造函數(shù) /// </summary>
/// <param name="Context"></param>
public Common(HttpContext context)
{ this.Context = context;
}
#endregion
#region 通過code換取AccessToken /// <summary>
/// 通過code換取AccessToken /// </summary>
public void GetOpenidAndAccessToken()
{ if (!string.IsNullOrEmpty(Context.Request.QueryString["code"]))
{ //獲取code碼,以獲取openid和access_token
string code = Context.Request.QueryString["code"]; GetOpenidAndAccessTokenFromCode(code);
} else
{ //構(gòu)造網(wǎng)頁授權(quán)獲取code的URL
string host = Context.Request.Url.Host;
string path = Context.Request.Path; string redirect_uri = HttpUtility.UrlEncode("http://" + host + path);
WxPayData data = new WxPayData();
data.SetValue("appid",
WxPayConfig.APPID);
data.SetValue("redirect_uri", redirect_uri);
data.SetValue("response_type", "code");
data.SetValue("scope", "snsapi_base");
data.SetValue("state", "STATE" + "#wechat_redirect"); string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl(); try
{ //觸發(fā)微信返回code碼
Context.Response.Redirect(url);//Redirect函數(shù)會拋出ThreadAbortException異常,不用處理這個異常 } catch (System.Threading.ThreadAbortException ex)
{
}
}
}
#endregion
#region 通過用戶授權(quán)獲取AccessToken和OpenId /// <summary>
/// 通過用戶授權(quán)獲取AccessToken和OpenId /// </summary>
/// <param name="code"></param>
public void GetOpenidAndAccessTokenFromCode(string code)
{ try
{ //構(gòu)造獲取openid及access_token的url
WxPayData data = new WxPayData();
data.SetValue("appid",
WxPayConfig.APPID);
data.SetValue("secret",
WxPayConfig.APPSECRET);
data.SetValue("code",
code);
data.SetValue("grant_type", "authorization_code"); string url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + data.ToUrl(); //請求url以獲取數(shù)據(jù)
string result = HttpService.Get(url); //保存access_token,用于收貨地址獲取
JsonData jd = JsonMapper.ToObject(result);
access_token = (string)jd["access_token"]; //獲取用戶openid
OpenId = (string)jd["openid"];
} catch (Exception ex)
{ throw new WxPayException(ex.ToString());
}
}
#endregion
#region 獲取OpenId /// <summary>
/// 獲取OpenId /// </summary>
/// <param name="postStr"></param>
/// <returns></returns>
public string GetOpenId()
{
Common common = new Common(Context);
common.GetOpenidAndAccessToken(); return OpenId; }
#endregion
}  
public class JsApiPay
{ /// <summary>
/// 保存頁面對象,因為要在類的方法中使用Page的Request對象 /// </summary>
private Page page {get;set;} /// <summary>
/// openid用于調(diào)用統(tǒng)一下單接口 /// </summary>
public string openid { get; set; } /// <summary>
/// access_token用于獲取收貨地址js函數(shù)入口參數(shù) /// </summary>
public string access_token { get; set; } /// <summary>
/// 商品金額,用于統(tǒng)一下單 /// </summary>
public int total_fee { get; set; } /// <summary>
/// 訂單Id /// </summary>
public string orderid { get; set; } /// <summary>
/// 統(tǒng)一下單接口返回結(jié)果 /// </summary>
public WxPayData unifiedOrderResult { get; set; }
public JsApiPay(Page page)
{ this.page = page;
} /**
*
* 網(wǎng)頁授權(quán)獲取用戶基本信息的全部過程
* 詳情請參看網(wǎng)頁授權(quán)獲取用戶基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
* 第一步:利用url跳轉(zhuǎn)獲取code
* 第二步:利用code去獲取openid和access_token
*
*/
public void GetOpenidAndAccessToken()
{ if (!string.IsNullOrEmpty(page.Request.QueryString["code"]))
{ //獲取code碼,以獲取openid和access_token
string code = page.Request.QueryString["code"]; //Log.Debug(this.GetType().ToString(), "Get code : " + code); GetOpenidAndAccessTokenFromCode(code);
} else
{ //構(gòu)造網(wǎng)頁授權(quán)獲取code的URL
string host = page.Request.Url.Host; //Log.Debug(this.GetType().ToString(), "host" + host);
string path = page.Request.Path; string redirect_uri = HttpUtility.UrlEncode("http://" + host + path);
WxPayData data = new WxPayData();
data.SetValue("appid",
WxPayConfig.APPID);
data.SetValue("redirect_uri", redirect_uri);
data.SetValue("response_type", "code");
data.SetValue("scope", "snsapi_base");
data.SetValue("state", "STATE" + "#wechat_redirect"); string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl();
Log.Debug(this.GetType().ToString(), "Will Redirect to URL :
" + url); try
{ //觸發(fā)微信返回code碼
page.Response.Redirect(url);//Redirect函數(shù)會拋出ThreadAbortException異常,不用處理這個異常 } catch(System.Threading.ThreadAbortException ex)
{
}
}
} /**
*
* 通過code換取網(wǎng)頁授權(quán)access_token和openid的返回數(shù)據(jù),正確時返回的JSON數(shù)據(jù)包如下:
* {
* "access_token":"ACCESS_TOKEN",
* "expires_in":7200,
* "refresh_token":"REFRESH_TOKEN",
* "openid":"OPENID",
* "scope":"SCOPE",
* "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
* }
* 其中access_token可用于獲取共享收貨地址
* openid是微信支付jsapi支付接口統(tǒng)一下單時必須的參數(shù)
* 更詳細的說明請參考網(wǎng)頁授權(quán)獲取用戶基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
* @失敗時拋異常WxPayException */
public void GetOpenidAndAccessTokenFromCode(string code)
{ try
{ //構(gòu)造獲取openid及access_token的url
WxPayData data = new WxPayData();
data.SetValue("appid",
WxPayConfig.APPID);
data.SetValue("secret",
WxPayConfig.APPSECRET);
data.SetValue("code",
code);
data.SetValue("grant_type", "authorization_code"); string url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + data.ToUrl(); //請求url以獲取數(shù)據(jù)
string result = HttpService.Get(url); //Log.Debug(this.GetType().ToString(), "GetOpenidAndAccessTokenFromCode response : " + result); //保存access_token,用于收貨地址獲取
JsonData jd = JsonMapper.ToObject(result);
access_token = (string)jd["access_token"]; //獲取用戶openid
openid = (string)jd["openid"]; //Log.Debug(this.GetType().ToString(), "Get openid : " + openid); //Log.Debug(this.GetType().ToString(), "Get access_token : " + access_token); } catch (Exception ex)
{
Log.Error(this.GetType().ToString(), ex.ToString()); throw new WxPayException(ex.ToString());
}
} /**
* 調(diào)用統(tǒng)一下單,獲得下單結(jié)果
* @return 統(tǒng)一下單結(jié)果
* @失敗時拋異常WxPayException */
public WxPayData GetUnifiedOrderResult()
{ //統(tǒng)一下單
WxPayData data = new WxPayData();
data.SetValue("body", "test"); //data.SetValue("attach", "test");
data.SetValue("out_trade_no",
WxPayApi.GenerateOutTradeNo());
data.SetValue("total_fee",
total_fee);
data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss")); //data.SetValue("goods_tag", "test");
data.SetValue("trade_type", "JSAPI");
data.SetValue("openid",
openid);
data.SetValue("orderid",
orderid);
WxPayData result = WxPayApi.UnifiedOrder(data); if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "")
{
Log.Error(this.GetType().ToString(), "UnifiedOrder response
error!"); throw new WxPayException("UnifiedOrder response error!");
}
unifiedOrderResult = result; return result;
} public WxPayData GetUnifiedOrderResult(string body)
{ //統(tǒng)一下單
WxPayData data = new WxPayData();
data.SetValue("body", body); //data.SetValue("attach", "test");
data.SetValue("out_trade_no",
WxPayApi.GenerateOutTradeNo());
data.SetValue("total_fee",
total_fee); //data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss")); //data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss")); //data.SetValue("goods_tag", "test");
data.SetValue("trade_type", "JSAPI");
data.SetValue("openid",
openid);
WxPayData result = WxPayApi.UnifiedOrder(data); if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "")
{
Log.Error(this.GetType().ToString(), "UnifiedOrder response
error!"); throw new WxPayException("UnifiedOrder response error!");
}
unifiedOrderResult = result; return result;
} /**
*
* 從統(tǒng)一下單成功返回的數(shù)據(jù)中獲取微信瀏覽器調(diào)起jsapi支付所需的參數(shù),
* 微信瀏覽器調(diào)起JSAPI時的輸入?yún)?shù)格式如下:
* {
* "appId" : "wx2421b1c4370ec43b", //公眾號名稱,由商戶傳入
* "timeStamp":" 1395712654", //時間戳,自1970年以來的秒數(shù)
* "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //隨機串
* "package" : "prepay_id=u802345jgfjsdfgsdg888",
* "signType" : "MD5", //微信簽名方式:
* "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名
* }
* @return string 微信瀏覽器調(diào)起JSAPI時的輸入?yún)?shù),json格式可以直接做參數(shù)用
* 更詳細的說明請參考網(wǎng)頁端調(diào)起支付API:http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7
*
*/
public string GetJsApiParameters()
{
WxPayData jsApiParam = new WxPayData();
jsApiParam.SetValue("appId", unifiedOrderResult.GetValue
("appid"));
jsApiParam.SetValue("timeStamp", WxPayApi.GenerateTimeStamp());
jsApiParam.SetValue("nonceStr", WxPayApi.GenerateNonceStr());
jsApiParam.SetValue("package", "prepay_id=" + unifiedOrderResult.GetValue("prepay_id"));
jsApiParam.SetValue("signType", "MD5");
jsApiParam.SetValue("paySign", jsApiParam.MakeSign()); string parameters = jsApiParam.ToJson(); return parameters;
} /**
*
* 獲取收貨地址js函數(shù)入口參數(shù),詳情請參考收貨地址共享接口:http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?
chapter=7_9
* @return string 共享收貨地址js函數(shù)需要的參數(shù),json格式可以直接做參數(shù)使用 */
public string GetEditAddressParameters()
{ string parameter = ""; try
{ string host = page.Request.Url.Host; string path = page.Request.Path; string queryString = page.Request.Url.Query; //這個地方要注意,參與簽名的是網(wǎng)頁授權(quán)獲取用戶信息時微信后臺回傳的完整url
string url = "http://" +
host + path + queryString; //構(gòu)造需要用SHA1算法加密的數(shù)據(jù)
WxPayData signData = new WxPayData();
signData.SetValue("appid",WxPayConfig.APPID);
signData.SetValue("url",
url);
signData.SetValue("timestamp",WxPayApi.GenerateTimeStamp());
signData.SetValue("noncestr",WxPayApi.GenerateNonceStr());
signData.SetValue("accesstoken",access_token); string param = signData.ToUrl();
Log.Debug(this.GetType().ToString(), "SHA1 encrypt param :
" + param); //SHA1加密
string addrSign = FormsAuthentication.HashPasswordForStoringInConfigFile(param, "SHA1");
Log.Debug(this.GetType().ToString(), "SHA1 encrypt result :
" + addrSign); //獲取收貨地址js函數(shù)入口參數(shù)
WxPayData afterData = new WxPayData();
afterData.SetValue("appId",WxPayConfig.APPID);
afterData.SetValue("scope","jsapi_address");
afterData.SetValue("signType","sha1");
afterData.SetValue("addrSign",addrSign);
afterData.SetValue("timeStamp",signData.GetValue("timestamp"));
afterData.SetValue("nonceStr",signData.GetValue("noncestr")); //轉(zhuǎn)為json格式
parameter = afterData.ToJson();
Log.Debug(this.GetType().ToString(), "Get EditAddressParam :
" + parameter);
} catch (Exception ex)
{
Log.Error(this.GetType().ToString(), ex.ToString()); throw new WxPayException(ex.ToString());
} return parameter;
}
} JsApiPay 微信支付協(xié)議接口數(shù)據(jù)類WxPayData.cs官方都有相應(yīng)的代碼.  
/// <summary>
/// 微信支付協(xié)議接口數(shù)據(jù)類,所有的API接口通信都依賴這個數(shù)據(jù)結(jié)構(gòu), /// 在調(diào)用接口之前先填充各個字段的值,然后進行接口通信, /// 這樣設(shè)計的好處是可擴展性強,用戶可隨意對協(xié)議進行更改而不用重新設(shè)計數(shù)據(jù)結(jié)構(gòu), /// 還可以隨意組合出不同的協(xié)議數(shù)據(jù)包,不用為每個協(xié)議設(shè)計一個數(shù)據(jù)包結(jié)構(gòu) /// </summary>
public class WxPayData
{ public WxPayData()
{
} //采用排序的Dictionary的好處是方便對數(shù)據(jù)包進行簽名,不用再簽名之前再做一次排序
private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>(); /**
* 設(shè)置某個字段的值
* @param key 字段名
* @param value 字段值 */
public void SetValue(string key, object value)
{
m_values[key] = value;
} /**
* 根據(jù)字段名獲取某個字段的值
* @param key 字段名
* @return key對應(yīng)的字段值 */
public object GetValue(string key)
{ object o = null;
m_values.TryGetValue(key, out o); return o;
} /**
* 判斷某個字段是否已設(shè)置
* @param key 字段名
* @return 若字段key已被設(shè)置,則返回true,否則返回false */
public bool IsSet(string key)
{ object o = null;
m_values.TryGetValue(key, out o); if (null != o) return true; else
return false;
} /**
* @將Dictionary轉(zhuǎn)成xml
* @return 經(jīng)轉(zhuǎn)換得到的xml串
* @throws WxPayException
**/
public string ToXml()
{ //數(shù)據(jù)為空時不能轉(zhuǎn)化為xml格式
if (0 == m_values.Count)
{
Log.Error(this.GetType().ToString(), "WxPayData數(shù)據(jù)為空!"); throw new WxPayException("WxPayData數(shù)據(jù)為空!");
} string xml = "<xml>"; foreach (KeyValuePair<string, object> pair in m_values)
{ //字段值不能為null,會影響后續(xù)流程
if (pair.Value == null)
{
Log.Error(this.GetType().ToString(), "WxPayData內(nèi)部含有值
為null的字段!"); throw new WxPayException("WxPayData內(nèi)部含有值為null的字段!");
} if (pair.Value.GetType() == typeof(int))
{
xml += "<" + pair.Key + ">" + pair.Value + "</" + pair.Key + ">";
} else if (pair.Value.GetType() == typeof(string))
{
xml += "<" + pair.Key + ">" + "<![CDATA
[" + pair.Value + "]]></" +
pair.Key + ">";
} else//除了string和int類型不能含有其他數(shù)據(jù)類型 {
Log.Error(this.GetType().ToString(), "WxPayData字段數(shù)據(jù)類
型錯誤!"); throw new WxPayException("WxPayData字段數(shù)據(jù)類型錯誤!");
}
}
xml += "</xml>"; return xml;
} /**
* @將xml轉(zhuǎn)為WxPayData對象并返回對象內(nèi)部的數(shù)據(jù)
* @param string 待轉(zhuǎn)換的xml串
* @return 經(jīng)轉(zhuǎn)換得到的Dictionary
* @throws WxPayException */
public SortedDictionary<string, object> FromXml(string xml)
{ if (string.IsNullOrEmpty(xml))
{
Log.Error(this.GetType().ToString(), "將空的xml串轉(zhuǎn)換為
WxPayData不合法!"); throw new WxPayException("將空的xml串轉(zhuǎn)換為WxPayData不合法!");
}
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
XmlNode xmlNode = xmlDoc.FirstChild;//獲取到根節(jié)點<xml>
XmlNodeList nodes = xmlNode.ChildNodes; foreach (XmlNode xn in nodes)
{
XmlElement xe = (XmlElement)xn;
m_values[xe.Name] = xe.InnerText;//獲取xml的鍵值對到WxPayData內(nèi)部的數(shù)據(jù)中 }
try
{ //2015-06-29 錯誤是沒有簽名
if(m_values["return_code"] != "SUCCESS")
{ return m_values;
}
CheckSign();//驗證簽名,不通過會拋異常 } catch(WxPayException ex)
{ throw new WxPayException(ex.Message);
} return m_values;
} /**
* @Dictionary格式轉(zhuǎn)化成url參數(shù)格式
* @ return url格式串, 該串不包含sign字段值 */
public string ToUrl()
{ string buff = ""; foreach (KeyValuePair<string, object> pair in m_values)
{ if (pair.Value == null)
{
Log.Error(this.GetType().ToString(), "WxPayData內(nèi)部含有值
為null的字段!"); throw new WxPayException("WxPayData內(nèi)部含有值為null的字段!");
} if (pair.Key != "sign" && pair.Value.ToString() != "")
{
buff += pair.Key + "=" + pair.Value + "&";
}
}
buff = buff.Trim('&'); return buff;
} /**
* @Dictionary格式化成Json
* @return json串?dāng)?shù)據(jù) */
public string ToJson()
{ string jsonStr = JsonMapper.ToJson(m_values); return jsonStr;
} /**
* @values格式化成能在Web頁面上顯示的結(jié)果(因為web頁面上不能直接輸出xml格式的字符串) */
public string ToPrintStr()
{ string str = ""; foreach (KeyValuePair<string, object> pair in m_values)
{ if (pair.Value == null)
{
Log.Error(this.GetType().ToString(), "WxPayData內(nèi)部含有值
為null的字段!"); throw new WxPayException("WxPayData內(nèi)部含有值為null的字段!");
}
str += string.Format("{0}={1}<br>", pair.Key, pair.Value.ToString());
}
Log.Debug(this.GetType().ToString(), "Print in Web Page :
" + str); return str;
} /**
* @生成簽名,詳見簽名生成算法
* @return 簽名, sign字段不參加簽名 */
public string MakeSign()
{ //轉(zhuǎn)url格式
string str = ToUrl(); //在string后加入API KEY
str += "&key=" + WxPayConfig.KEY; //MD5加密
var md5 = MD5.Create(); var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); var sb = new StringBuilder(); foreach (byte b in bs)
{
sb.Append(b.ToString("x2"));
} //所有字符轉(zhuǎn)為大寫
return sb.ToString().ToUpper();
} /**
*
* 檢測簽名是否正確
* 正確返回true,錯誤拋異常 */
public bool CheckSign()
{ //如果沒有設(shè)置簽名,則跳過檢測
if (!IsSet("sign"))
{
Log.Error(this.GetType().ToString(), "WxPayData簽名存在但不合法
!"); throw new WxPayException("WxPayData簽名存在但不合法!");
} //如果設(shè)置了簽名但是簽名為空,則拋異常
else if(GetValue("sign") == null || GetValue("sign").ToString() == "")
{
Log.Error(this.GetType().ToString(), "WxPayData簽名存在但不合
法!"); throw new WxPayException("WxPayData簽名存在但不合法!");
} //獲取接收到的簽名
string return_sign = GetValue("sign").ToString(); //在本地計算新的簽名
string cal_sign = MakeSign(); if (cal_sign == return_sign)
{ return true;
}
Log.Error(this.GetType().ToString(), "WxPayData簽名驗證錯誤!"); throw new WxPayException("WxPayData簽名驗證錯誤!");
} /**
* @獲取Dictionary */
public SortedDictionary<string, object> GetValues()
{ return m_values;
}
} WxPayData 配置文件信息  
/**
* 配置賬號信息 */
public class WxPayConfig
{ //=======【基本信息設(shè)置】=====================================
/* 微信公眾號信息配置
* APPID:綁定支付的APPID(必須配置)
* MCHID:商戶號(必須配置)
* KEY:商戶支付密鑰,參考開戶郵件設(shè)置(必須配置)
* APPSECRET:公眾帳號secert(僅JSAPI支付的時候需要配置) */
public const string APPID = "wx14e3e56f3"; public const string MCHID = "12352"; public const string KEY = "BB6BE71D7CED49A79409C9"; public const string APPSECRET = "76eb33f66129692da1624f1"; //=======【證書路徑設(shè)置】=====================================
/* 證書路徑,注意應(yīng)該填寫絕對路徑(僅退款、撤銷訂單時需要) */
public const string SSLCERT_PATH = "cert/apiclient_cert.p12"; public const string SSLCERT_PASSWORD = "123502"; //=======【支付結(jié)果通知url】=====================================
/* 支付結(jié)果通知回調(diào)url,用于商戶接收支付結(jié)果 */
public const string NOTIFY_URL = "http://www.baidu.com/ResultPay.aspx"; //=======【商戶系統(tǒng)后臺機器IP】=====================================
/* 此參數(shù)可手動配置也可在程序中自動獲取 */
public const string IP = "150.24.91.151"; //=======【代理服務(wù)器設(shè)置】===================================
/* 默認IP和端口號分別為0.0.0.0和0,此時不開啟代理(如有需要才設(shè)置) */
public const string PROXY_URL = "http://10.152.18.220:8080"; //=======【上報信息配置】===================================
/* 測速上報等級,0.關(guān)閉上報; 1.僅錯誤時上報; 2.全量上報 */
public const int REPORT_LEVENL = 1; //=======【日志級別】===================================
/* 日志等級,0.不輸出日志;1.只輸出錯誤信息; 2.輸出錯誤和正常信息; 3.輸出錯誤信息、正常信息和調(diào)試信息 */
public const int LOG_LEVENL =3;
} WxPayConfig 接著我們在看2行關(guān)鍵的代碼: WxPayData unifiedOrderResult == jsApiPay.GetJsApiParameters(); 此時如果wxJsApiParam變量能夠順利拿到值,那么我們前臺頁面的:<%=wxJsApiParam%>z這里就可以獲取到我們要傳遞的參數(shù),這時候就可以調(diào)用微信支付的接口,打開我們的付款頁面如圖所示: //調(diào)用微信JS api 支付 function jsApiCall()
{
WeixinJSBridge.invoke( 'getBrandWCPayRequest', <%=wxJsApiParam%>,//josn串 function (res)
{ if (res.err_msg == "get_brand_wcpay_request:ok")
{ var OrderId=$("#OrderId").val(); var orderProductName=$("#orderProductName").val(); var orderMoneySum=$("#orderMoneySum").val(); window.location.href="http://www.baodu.com/PaySkip.aspx?OrderId="+OrderId+"&orderMoneySum="+orderMoneySum+"&orderProductName="+orderProductName;
}else
{
WeixinJSBridge.call('closeWindow');
}
}
);
} 
(JsApiPay.cs)得到下單結(jié)果: public WxPayData GetUnifiedOrderResult(string body)
{ //統(tǒng)一下單
WxPayData data = new WxPayData();
data.SetValue("body",
body);
data.SetValue("out_trade_no",
WxPayApi.GenerateOutTradeNo());
data.SetValue("total_fee",
total_fee);
data.SetValue("trade_type", "JSAPI");
data.SetValue("openid",
openid); WxPayData result = WxPayApi.UnifiedOrder(data); if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "")
{
Log.Error(this.GetType().ToString(), "UnifiedOrder response
error!"); throw new WxPayException("UnifiedOrder response error!");
}
unifiedOrderResult = result; return result;
} (WxPayApi.cs)統(tǒng)一下單接口: /**
*
* 統(tǒng)一下單
* @param WxPaydata inputObj 提交給統(tǒng)一下單API的參數(shù)
* @param int timeOut 超時時間
* @throws WxPayException
* @return 成功時返回,其他拋異常 */
public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut =
6)
{ string url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; //檢測必填參數(shù)
if (!inputObj.IsSet("out_trade_no"))
{ throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù)out_trade_no!");
} else if (!inputObj.IsSet("body"))
{ throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù)body!");
} else if (!inputObj.IsSet("total_fee"))
{ throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù)total_fee!");
} else if (!inputObj.IsSet("trade_type"))
{ throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù)trade_type!");
} //關(guān)聯(lián)參數(shù)
if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
{ throw new WxPayException("統(tǒng)一支付接口中,缺少必填參數(shù)openid!trade_type為JSAPI時,openid為必填參數(shù)!");
} if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
{ throw new WxPayException("統(tǒng)一支付接口中,缺少必填參數(shù)product_id!trade_type為JSAPI時,product_id為必填參數(shù)!");
} //異步通知url未設(shè)置,則使用配置文件中的url
if (!inputObj.IsSet("notify_url"))
{
inputObj.SetValue("notify_url",
WxPayConfig.NOTIFY_URL);//異步通知url }
inputObj.SetValue("appid", WxPayConfig.APPID);//公眾賬號ID
inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商戶號
inputObj.SetValue("spbill_create_ip", WxPayConfig.IP);//終端ip
inputObj.SetValue("nonce_str", GenerateNonceStr());//隨機字符串 //簽名
inputObj.SetValue("sign",
inputObj.MakeSign()); string xml = inputObj.ToXml(); var start = DateTime.Now;
string response = HttpService.Post(xml, url, false, timeOut);
var end = DateTime.Now; int timeCost = (int)((end - start).TotalMilliseconds);
WxPayData result = new WxPayData();
result.FromXml(response);
ReportCostTime(url, timeCost, result);//測速上報
return result;
} 四.最終開發(fā)的效果
   
五.微信公眾號開發(fā)系列導(dǎo)航
1.0初始微信公眾號
2.0創(chuàng)建自定義菜單
3.0查詢自定義菜單
4.0公眾號消息處理
5.0微信支付
6.0模板消息 Das obige ist der detaillierte Inhalt vonDetailliertes Beispiel für die Entwicklung eines ?ffentlichen .NET WeChat-Kontos (5.0 WeChat-Zahlung).. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!
Erkl?rung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Teilen Sie mehrere .NET-Open-Source-KI- und LLM-bezogene Projekt-Frameworks
May 06, 2024 pm 04:43 PM
Die Entwicklung von Technologien der künstlichen Intelligenz (KI) ist heute in vollem Gange und sie haben in verschiedenen Bereichen gro?es Potenzial und Einfluss gezeigt. Heute wird Dayao Ihnen 4 .NET Open-Source-KI-Modell-LLM-bezogene Projekt-Frameworks vorstellen und hofft, Ihnen einige Referenzen zu geben. https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel ist ein Open-Source-Softwareentwicklungskit (SDK), das für die Integration gro?er Sprachmodelle (LLM) wie OpenAI und Azure entwickelt wurde
.NET CORE Quick Start Tutorial 1. Der Anfang: über .NET Core sprechen
May 07, 2025 pm 04:54 PM
1. Der Ursprung von .NetCore Wenn wir über .NetCore sprechen, dürfen wir seinen Vorg?nger .NET nicht erw?hnen. Java war zu dieser Zeit im Rampenlicht, und Microsoft bevorzugte auch Java. Die Java Virtual Machine auf der Windows -Plattform wurde von Microsoft basierend auf den JVM -Standards entwickelt. Es soll die beste Leistung Java Virtual Machine zu dieser Zeit sein. Microsoft hat jedoch einen eigenen kleinen Abakus, der versucht, Java mit der Windows-Plattform zu bündeln und einige Windows-spezifische Funktionen hinzuzufügen. Die Unzufriedenheit von Sun führte dazu zu einer Aufschlüsselung der Beziehung zwischen den beiden Parteien, und Microsoft startete dann .NET. .NET hat seit seiner Gründung viele Merkmale von Java geliehen und hat Java in Sprachmerkmalen und Formentwicklung nach und nach übertroffen. Java in Version 1.6
Wo kann man das WeChat-Zahlungspasswort ?ndern?
Mar 31, 2024 am 07:39 AM
1. ?ffnen Sie die WeChat-App, klicken Sie unten in der Benutzeroberfl?che auf [Ich] und w?hlen Sie die Option [Service]. 2. Klicken Sie auf [Wallet], klicken Sie unten in der Wallet-Oberfl?che auf [Zahlungseinstellungen] und w?hlen Sie [Zahlungspasswort ?ndern]. 3. Geben Sie das Zahlungspasswort ein, legen Sie ein neues Zahlungspasswort fest, geben Sie das neue Zahlungspasswort erneut ein und klicken Sie auf [Fertig stellen].
C# .NET: Erstellen von Anwendungen mit dem .NET -?kosystem
Apr 27, 2025 am 12:12 AM
Wie erstelle ich Anwendungen mit .NET? Erstellen Anwendungen mit .NET k?nnen in den folgenden Schritten erreicht werden: 1) Verstehen Sie die Grundlagen von .NET, einschlie?lich C# Sprache und plattformübergreifender Entwicklungsunterstützung; 2) Kernkonzepte wie Komponenten und Arbeitsprinzipien des .NET -?kosystems lernen; 3) Master Basic und Advanced Nutzung, von einfachen Konsolenanwendungen bis hin zu komplexen Webapis- und Datenbankvorg?ngen; 4) Mit gemeinsamen Fehlern und Debugging -Techniken wie Konfigurations- und Datenbankverbindungsproblemen vertraut sein; 5) Optimierung der Anwendungsleistung und Best Practices wie asynchrone Programmieren und Zwischenspeichern.
Vom Web zum Desktop: Die Vielseitigkeit von C# .NET
Apr 15, 2025 am 12:07 AM
C#.NETisversatileforbothwebanddesktopdevelopment.1)Forweb,useASP.NETfordynamicapplications.2)Fordesktop,employWindowsFormsorWPFforrichinterfaces.3)UseXamarinforcross-platformdevelopment,enablingcodesharingacrossWindows,macOS,Linux,andmobiledevices.
C# .NET: Erforschen von Kernkonzepten und Programmierfundamentaldaten
Apr 10, 2025 am 09:32 AM
C# ist eine moderne, objektorientierte Programmiersprache, die von Microsoft und als Teil des .NET-Frameworks entwickelt wurde. 1.C# unterstützt die objektorientierte Programmierung (OOP), einschlie?lich Einkapselung, Vererbung und Polymorphismus. 2. Asynchrones Programmieren in C# wird über Async implementiert und wartet auf Schlüsselw?rter, um die Reaktionsf?higkeit der Anwendungen zu verbessern. 3.. Verwenden Sie LINQ, um Datensammlungen pr?zise zu verarbeiten. 4. H?ufige Fehler umfassen Null-Referenzausnahmen und Indexausnahmen au?erhalb des Bereichs. Zu den Debugging -F?higkeiten geh?rt die Verwendung eines Debuggers und Ausnahmeberechnung. 5. Leistungsoptimierung umfasst die Verwendung von StringBuilder und das Vermeiden von unn?tigem Packung und Unboxing.
Bereitstellen von C# .NET-Anwendungen in Azure/AWS: Eine Schritt-für-Schritt-Anleitung
Apr 23, 2025 am 12:06 AM
Wie bereitete ich eine C# .NET -App für Azure oder AWS bereit? Die Antwort ist, AzureAppservice und Awselasticbeanstalk zu verwenden. 1. Automatisieren Sie bei Azure die Bereitstellung mit AzureAppservice und AzurePipelines. 2. Verwenden Sie bei AWS Amazon ElasticbeanSpalk und AWSLambda, um Bereitstellungen und serverlosen Computer zu implementieren.
See all articles
|