\r\n    

\r\n       \r\n       \r\n       \r\n       \r\n       \"\/>\r\n       \"\/>\r\n       \"\/>\r\n         您確認(rèn)付款<%=Money%><\/label>元...<\/span>\r\n      

立即支付<\/button><\/p>\r\n    <\/p>\r\n<\/body>\r\n<\/html><\/pre>

需要注意的是:<\/p>

微信JS API只能在微信內(nèi)置瀏覽器中使用,其他瀏覽器調(diào)用無效。微信提供getBrandWCPayRequest接口供商戶前端網(wǎng)頁調(diào)用,調(diào)用之前微信會鑒定商戶支付權(quán)限,若商戶具有調(diào)起支付的權(quán)限,則將開始支付流程。 這里主要介紹支付前的接口調(diào)用規(guī)則,支付狀態(tài)消息通知機(jī)制請參加下文。接口需要注意:所有傳入?yún)?shù)都是字符串類型!<\/p>

getBrandWCPayRequest參數(shù)如表6-5所示。<\/p>

<label id="vd0zm"></label>

參數(shù)<\/strong><\/p><\/td>

名稱<\/strong><\/p><\/td>

必填<\/strong><\/p><\/td>

格式<\/strong><\/p><\/td>

說明<\/strong><\/p><\/td><\/tr><\/thead>

appId<\/p><\/td>

公眾號id<\/p><\/td>

是<\/p><\/td>

字符串類型<\/p><\/td>

商戶注冊具有支付權(quán)限的公眾號成功后即可獲得;<\/p><\/td><\/tr>

timeStamp<\/p><\/td>

時間戳<\/p><\/td>

是<\/p><\/td>

字符串類型,32個字節(jié)以下<\/p><\/td>

商戶生成,從1970年1月1日00:00:00至今的秒數(shù),即當(dāng)前的時間,且最終需要轉(zhuǎn)換為字符串形式;<\/p><\/td><\/tr>

nonceStr<\/p><\/td>

隨機(jī)字符串<\/p><\/td>

是<\/p><\/td>

字符串類型,32個字節(jié)以下<\/p><\/td>

商戶生成的隨機(jī)字符串;<\/p><\/td><\/tr>

package<\/p><\/td>

訂單詳情擴(kuò)展字符串<\/p><\/td>

是<\/p><\/td>

字符串類型,4096個字節(jié)以下<\/p><\/td>

商戶將訂單信息組成該字符串,具體組成方案參見接口使用說明中package組包幫劣;由商戶按照規(guī)范拼接后傳入;<\/p><\/td><\/tr>

signType<\/p><\/td>

簽名方式<\/p><\/td>

是<\/p><\/td>

字符串類型,參數(shù)取值\"SHA1\"<\/p><\/td>

按照文檔中所示填入,目前僅支持SHA1;<\/p><\/td><\/tr>

paySign<\/p><\/td>

簽名<\/p><\/td>

是<\/p><\/td>

字符串類型<\/p><\/td>

商戶將接口列表中的參數(shù)按照指定方式迚行簽名,簽名方式使用signType中標(biāo)示的簽名方式,具體簽名方案參見接口使用說明中簽名幫劣;由商戶按照規(guī)范簽名后傳入;<\/p><\/td><\/tr><\/tbody><\/table>

表6-5 getBrandWCPayRequest參數(shù)<\/p>

    getBrandWCPayRequest返回值如表6-6所示。<\/p>

<\/p>

<rt id="vd0zm"><noframes id="vd0zm">
  • 返回值<\/strong><\/p><\/td>

    說明<\/strong><\/p><\/td><\/tr>

    err_msg<\/p><\/td>

    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)一處理為用戶遇到錯誤或者\(yùn)r\n\r\n主動放棄,不必細(xì)化區(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的這個過程我們首先要進(jìn)行Oauth2認(rèn)證,在官方的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        \/\/\/ 保存頁面對象,因?yàn)橐陬惖姆椒ㄖ惺褂肞age的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的返回?cái)?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        * 更詳細(xì)的說明請參考網(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\", \/\/隨機(jī)串     \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        * 更詳細(xì)的說明請參考網(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)用接口之前先填充各個字段的值,然后進(jìn)行接口通信,    \/\/\/ 這樣設(shè)計(jì)的好處是可擴(kuò)展性強(qiáng),用戶可隨意對協(xié)議進(jìn)行更改而不用重新設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),    \/\/\/ 還可以隨意組合出不同的協(xié)議數(shù)據(jù)包,不用為每個協(xié)議設(shè)計(jì)一個數(shù)據(jù)包結(jié)構(gòu)    \/\/\/ <\/summary>\r\n    public class WxPayData\r\n    {        public WxPayData()\r\n        {\r\n\r\n        }        \/\/采用排序的Dictionary的好處是方便對數(shù)據(jù)包進(jìn)行簽名,不用再簽名之前再做一次排序\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é)點(diǎn)\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();\/\/驗(yàn)證簽名,不通過會拋異常            }            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é)果(因?yàn)閣eb頁面上不能直接輸出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();            \/\/在本地計(jì)算新的簽名\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簽名驗(yàn)證錯誤!\");            throw new WxPayException(\"WxPayData簽名驗(yàn)證錯誤!\");\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)后臺機(jī)器IP】===================================== \r\n        \/* 此參數(shù)可手動配置也可在程序中自動獲取        *\/\r\n        public const string IP = \"150.24.91.151\";        \/\/=======【代理服務(wù)器設(shè)置】===================================\r\n        \/* 默認(rèn)IP和端口號分別為0.0.0.0和0,此時不開啟代理(如有需要才設(shè)置)        *\/\r\n        public const string PROXY_URL = \"http:\/\/10.152.18.220:8080\";        \/\/=======【上報(bào)信息配置】===================================\r\n        \/* 測速上報(bào)等級,0.關(guān)閉上報(bào); 1.僅錯誤時上報(bào); 2.全量上報(bào)        *\/\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());\/\/隨機(jī)字符串            \/\/簽名\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);\/\/測速上報(bào)\r\n\r\n            return result;\r\n        }<\/pre>

    四.最終開發(fā)的效果<\/h4>\n

    \"\"\"\"\"\"\"\"<\/p>\n

    五.微信公眾號開發(fā)系列導(dǎo)航<\/h4>\n

    1.0初始微信公眾號<\/p>\n

    2.0創(chuàng)建自定義菜單<\/p>\n

    3.0查詢自定義菜單<\/p>\n

    4.0公眾號消息處理<\/p>\n

    5.0微信支付<\/p>\n

    6.0模板消息<\/p>"}

    国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

    Jadual Kandungan
    一.前言
    二.開發(fā)前準(zhǔn)備。
    三.編碼
    四.最終開發(fā)的效果
    五.微信公眾號開發(fā)系列導(dǎo)航
    Rumah applet WeChat pembangunan WeChat .NET微信公眾號開發(fā)(5.0微信支付)實(shí)例詳解

    .NET微信公眾號開發(fā)(5.0微信支付)實(shí)例詳解

    May 03, 2017 am 10:31 AM

    一.前言

    在開始做這個功能之前,我們要做的第一件事情就是思考,如何做這個微信支付,從哪里開始,從哪里入手,官方的sdk說明什么的,有沒有什么官方的demo,還有就是老板給我的一些資料齊全不,那些要申請的接 口什么的都有沒有。

    經(jīng)過自己的一些探索,在老板的催促下終于硬著頭皮做完了這個,很坑很坑的微信支付,在此做一些總結(jié),希望對你們有所幫助,本人能力有限,如果有什么說的不好,希望大家多多包涵。

    二.開發(fā)前準(zhǔn)備。

    ? 1.0微信支付官方開發(fā)者文檔

    ? 2.0官方demo下載?我們用c#所以選擇.net版本 不過這個官方的demo根本跑步起來

    ? 3.0官方demo運(yùn)行起來解決方案??

    ? 4.0微信支付官方.net版之坑你沒商量

    ? 5.0開發(fā)前的微信公眾平臺的一些配置,請務(wù)必認(rèn)真檢查配置.

    三.編碼

    ? 做好了這些準(zhǔn)備工作之后,我們知道微信支付有兩種,1.原生態(tài)的,2.jsapi直接調(diào)用的,我項(xiàng)目中用到的是第二種

    ? 經(jīng)過自己的一些業(yè)務(wù)邏輯處理,來到了我們的訂單詳情頁面,現(xiàn)在需要去點(diǎn)擊我們的支付按鈕去支付,支付頁面pay.aspx代碼如下,

    ? 前臺頁面:

    <script type="text/javascript">               //調(diào)用微信JS api 支付               function jsApiCall()
                   {
                       WeixinJSBridge.invoke(                   &#39;getBrandWCPayRequest&#39;,                   <%=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(&#39;closeWindow&#39;);
                            }
                             
                         }
                        );
                   }
    
                   function callpay()
                   {                   if (typeof WeixinJSBridge == "undefined")
                       {                       if (document.addEventListener)
                           {
                               document.addEventListener(&#39;WeixinJSBridgeReady&#39;, jsApiCall, false);
                           }                       else if (document.attachEvent)
                           {
                               document.attachEvent(&#39;WeixinJSBridgeReady&#39;, jsApiCall);
                               document.attachEvent(&#39;onWeixinJSBridgeReady&#39;, 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">  您確認(rèn)付款<label style="font-size:25px;color:Red"><%=Money%></label>元...</span>
          <p><button type="button" class="btn-pay" title="確認(rèn)支付" onclick="callpay()">立即支付</button></p>
        </p>
    </body>
    </html>

    需要注意的是:

    微信JS API只能在微信內(nèi)置瀏覽器中使用,其他瀏覽器調(diào)用無效。微信提供getBrandWCPayRequest接口供商戶前端網(wǎng)頁調(diào)用,調(diào)用之前微信會鑒定商戶支付權(quán)限,若商戶具有調(diào)起支付的權(quán)限,則將開始支付流程。 這里主要介紹支付前的接口調(diào)用規(guī)則,支付狀態(tài)消息通知機(jī)制請參加下文。接口需要注意:所有傳入?yún)?shù)都是字符串類型!

    getBrandWCPayRequest參數(shù)如表6-5所示。

    參數(shù)

    名稱

    必填

    格式

    說明

    appId

    公眾號id

    字符串類型

    商戶注冊具有支付權(quán)限的公眾號成功后即可獲得;

    timeStamp

    時間戳

    字符串類型,32個字節(jié)以下

    商戶生成,從1970年1月1日00:00:00至今的秒數(shù),即當(dāng)前的時間,且最終需要轉(zhuǎn)換為字符串形式;

    nonceStr

    隨機(jī)字符串

    字符串類型,32個字節(jié)以下

    商戶生成的隨機(jī)字符串;

    package

    訂單詳情擴(kuò)展字符串

    字符串類型,4096個字節(jié)以下

    商戶將訂單信息組成該字符串,具體組成方案參見接口使用說明中package組包幫劣;由商戶按照規(guī)范拼接后傳入;

    signType

    簽名方式

    字符串類型,參數(shù)取值"SHA1"

    按照文檔中所示填入,目前僅支持SHA1;

    paySign

    簽名

    字符串類型

    商戶將接口列表中的參數(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)一處理為用戶遇到錯誤或者 主動放棄,不必細(xì)化區(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的這個過程我們首先要進(jìn)行Oauth2認(rèn)證,在官方的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>
            /// 保存頁面對象,因?yàn)橐陬惖姆椒ㄖ惺褂肞age的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的返回?cái)?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ù)
            * 更詳細(xì)的說明請參考網(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", //隨機(jī)串     
            *   "package" : "prepay_id=u802345jgfjsdfgsdg888",     
            *   "signType" : "MD5",         //微信簽名方式:    
            *   "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名 
            * }
            * @return string 微信瀏覽器調(diào)起JSAPI時的輸入?yún)?shù),json格式可以直接做參數(shù)用
            * 更詳細(xì)的說明請參考網(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)用接口之前先填充各個字段的值,然后進(jìn)行接口通信,    /// 這樣設(shè)計(jì)的好處是可擴(kuò)展性強(qiáng),用戶可隨意對協(xié)議進(jìn)行更改而不用重新設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),    /// 還可以隨意組合出不同的協(xié)議數(shù)據(jù)包,不用為每個協(xié)議設(shè)計(jì)一個數(shù)據(jù)包結(jié)構(gòu)    /// </summary>
        public class WxPayData
        {        public WxPayData()
            {
    
            }        //采用排序的Dictionary的好處是方便對數(shù)據(jù)包進(jìn)行簽名,不用再簽名之前再做一次排序
            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é)點(diǎn)<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();//驗(yàn)證簽名,不通過會拋異常            }            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(&#39;&&#39;);            return buff;
            }        /**
            * @Dictionary格式化成Json
             * @return json串?dāng)?shù)據(jù)        */
            public string ToJson()
            {            string jsonStr = JsonMapper.ToJson(m_values);            return jsonStr;
            }        /**
            * @values格式化成能在Web頁面上顯示的結(jié)果(因?yàn)閣eb頁面上不能直接輸出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();            //在本地計(jì)算新的簽名
                string cal_sign = MakeSign();            if (cal_sign == return_sign)
                {                return true;
                }
    
                Log.Error(this.GetType().ToString(), "WxPayData簽名驗(yàn)證錯誤!");            throw new WxPayException("WxPayData簽名驗(yàn)證錯誤!");
            }        /**
            * @獲取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)后臺機(jī)器IP】===================================== 
            /* 此參數(shù)可手動配置也可在程序中自動獲取        */
            public const string IP = "150.24.91.151";        //=======【代理服務(wù)器設(shè)置】===================================
            /* 默認(rèn)IP和端口號分別為0.0.0.0和0,此時不開啟代理(如有需要才設(shè)置)        */
            public const string PROXY_URL = "http://10.152.18.220:8080";        //=======【上報(bào)信息配置】===================================
            /* 測速上報(bào)等級,0.關(guān)閉上報(bào); 1.僅錯誤時上報(bào); 2.全量上報(bào)        */
            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(                   &#39;getBrandWCPayRequest&#39;,                   <%=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(&#39;closeWindow&#39;);
                            }
                             
                         }
                        );
                   }

    (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());//隨機(jī)字符串            //簽名
                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);//測速上報(bào)
    
                return result;
            }

    四.最終開發(fā)的效果

    五.微信公眾號開發(fā)系列導(dǎo)航

    1.0初始微信公眾號

    2.0創(chuàng)建自定義菜單

    3.0查詢自定義菜單

    4.0公眾號消息處理

    5.0微信支付

    6.0模板消息

    Atas ialah kandungan terperinci .NET微信公眾號開發(fā)(5.0微信支付)實(shí)例詳解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan Laman Web ini
    Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

    Alat AI Hot

    Undress AI Tool

    Undress AI Tool

    Gambar buka pakaian secara percuma

    Undresser.AI Undress

    Undresser.AI Undress

    Apl berkuasa AI untuk mencipta foto bogel yang realistik

    AI Clothes Remover

    AI Clothes Remover

    Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

    Clothoff.io

    Clothoff.io

    Penyingkiran pakaian AI

    Video Face Swap

    Video Face Swap

    Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

    Alat panas

    Notepad++7.3.1

    Notepad++7.3.1

    Editor kod yang mudah digunakan dan percuma

    SublimeText3 versi Cina

    SublimeText3 versi Cina

    Versi Cina, sangat mudah digunakan

    Hantar Studio 13.0.1

    Hantar Studio 13.0.1

    Persekitaran pembangunan bersepadu PHP yang berkuasa

    Dreamweaver CS6

    Dreamweaver CS6

    Alat pembangunan web visual

    SublimeText3 versi Mac

    SublimeText3 versi Mac

    Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

    Topik panas

    Tutorial PHP
    1502
    276
    Kongsi beberapa rangka kerja projek berkaitan AI dan LLM sumber terbuka .NET Kongsi beberapa rangka kerja projek berkaitan AI dan LLM sumber terbuka .NET May 06, 2024 pm 04:43 PM

    Perkembangan teknologi kecerdasan buatan (AI) sedang giat dijalankan hari ini, dan ia telah menunjukkan potensi dan pengaruh yang besar dalam pelbagai bidang. Hari ini Dayao akan berkongsi dengan anda 4 rangka kerja projek berkaitan LLM model AI sumber terbuka .NET, dengan harapan dapat memberi anda sedikit rujukan. https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel ialah kit pembangunan perisian sumber terbuka (SDK) yang direka untuk menyepadukan model bahasa besar (LLM) seperti OpenAI, Azure

    Apakah perbezaan antara pengeluaran halaman H5 dan applet WeChat Apakah perbezaan antara pengeluaran halaman H5 dan applet WeChat Apr 05, 2025 pm 11:51 PM

    H5 lebih fleksibel dan disesuaikan, tetapi memerlukan teknologi mahir; Program mini cepat bermula dan mudah dikekalkan, tetapi dibatasi oleh kerangka WeChat.

    .NET Core Quick Start Tutorial 1. Permulaan: Bercakap Tentang .NET Core .NET Core Quick Start Tutorial 1. Permulaan: Bercakap Tentang .NET Core May 07, 2025 pm 04:54 PM

    1. Asal .Netcore Apabila bercakap tentang .Netcore, kita tidak boleh menyebutkan pendahulunya .NET. Java berada di pusat perhatian pada masa itu, dan Microsoft juga menyukai Java. Mesin maya Java di platform Windows telah dibangunkan oleh Microsoft berdasarkan piawaian JVM. Ia dikatakan sebagai mesin maya Java prestasi terbaik pada masa itu. Walau bagaimanapun, Microsoft mempunyai abacus kecil sendiri, cuba membungkus Java dengan platform Windows dan menambah beberapa ciri khusus Windows. Ketidakpuasan Sun dengan ini membawa kepada pecahan hubungan antara kedua -dua pihak, dan Microsoft kemudian melancarkan .NET. .NET telah meminjam banyak ciri Java sejak penubuhannya dan secara beransur -ansur melepasi Java dalam ciri bahasa dan pembangunan bentuk. Java dalam versi 1.6

    Di mana untuk menukar kata laluan pembayaran WeChat Di mana untuk menukar kata laluan pembayaran WeChat Mar 31, 2024 am 07:39 AM

    1. Buka apl WeChat, klik [Saya] di bahagian bawah antara muka dan pilih pilihan [Perkhidmatan]. 2. Klik [Dompet], klik [Tetapan Pembayaran] di bahagian bawah antara muka dompet dan pilih [Ubah Suai Kata Laluan Pembayaran]. 3. Masukkan kata laluan pembayaran, tetapkan kata laluan pembayaran baharu, isikan kata laluan pembayaran baharu sekali lagi dan klik [Selesai].

    C# .NET: Membina aplikasi dengan ekosistem .NET C# .NET: Membina aplikasi dengan ekosistem .NET Apr 27, 2025 am 12:12 AM

    Bagaimana Membina Aplikasi Menggunakan .NET? Membina aplikasi menggunakan .NET boleh dicapai melalui langkah-langkah berikut: 1) Memahami asas-asas .NET, termasuk C# bahasa dan sokongan pembangunan silang platform; 2) mempelajari konsep teras seperti komponen dan prinsip kerja ekosistem .NET; 3) menguasai penggunaan asas dan lanjutan, dari aplikasi konsol mudah ke operasi WebAPIS dan pangkalan data yang kompleks; 4) terbiasa dengan kesilapan biasa dan teknik debugging, seperti konfigurasi dan isu sambungan pangkalan data; 5) Pengoptimuman prestasi aplikasi dan amalan terbaik, seperti pengaturcaraan dan caching asynchronous.

    Dari web ke desktop: fleksibiliti C# .net Dari web ke desktop: fleksibiliti C# .net Apr 15, 2025 am 12:07 AM

    C#.netisversatileforbothwebanddesktopdevelopment.1) Forweb, useasp.netfordynamicapplications.2) Fordesktop, ExployWindowsFormsor Wpfforrichinterfaces.3) UseXamarinforcross-platformdevelopment, enablingcodesharingacrosswindows, macOS, linux, andmobiledevices.

    C# .NET: Meneroka Konsep Teras dan Asas Pengaturcaraan C# .NET: Meneroka Konsep Teras dan Asas Pengaturcaraan Apr 10, 2025 am 09:32 AM

    C# adalah bahasa pengaturcaraan yang berorientasikan objek moden yang dibangunkan oleh Microsoft dan sebagai sebahagian daripada Rangka Kerja .NET. 1.C# menyokong pengaturcaraan berorientasikan objek (OOP), termasuk enkapsulasi, warisan dan polimorfisme. 2. Pengaturcaraan Asynchronous dalam C# dilaksanakan melalui Async dan menunggu kata kunci untuk meningkatkan respons aplikasi. 3. Gunakan LINQ untuk memproses koleksi data dengan ringkas. 4. Kesilapan umum termasuk pengecualian rujukan null dan pengecualian indeks luar. Kemahiran penyahpepijatan termasuk menggunakan debugger dan pengendalian pengecualian. 5. Pengoptimuman Prestasi termasuk menggunakan StringBuilder dan mengelakkan pembungkusan yang tidak perlu dan unboxing.

    Menggunakan C# .NET Aplikasi ke Azure/AWS: Panduan Langkah demi Langkah Menggunakan C# .NET Aplikasi ke Azure/AWS: Panduan Langkah demi Langkah Apr 23, 2025 am 12:06 AM

    Bagaimana cara menggunakan aplikasi C# .net ke Azure atau AWS? Jawapannya ialah menggunakan Azureappservice dan AwselasticBeansTalk. 1. Pada Azure, mengautomasikan penggunaan menggunakan Azureappservice dan Azurepipelines. 2. Pada AWS, gunakan Amazon ElasticBeansTalk dan AWSLambda untuk melaksanakan penempatan dan pengiraan tanpa pelayan.

    See all articles