程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 微信JSAPI支付 跟 所遇到的那些坑,jsapi

微信JSAPI支付 跟 所遇到的那些坑,jsapi

編輯:關於.NET

微信JSAPI支付 跟 所遇到的那些坑,jsapi


首先介紹一下我在調用微信支付接口使用的是 weixin.senparc SDK,非常方便好用開源的一個微信開發SDK。

weixin.senparc SDK 官網:http://weixin.senparc.com/

先去下載下來Senparc.Weixin SDK。

在調起支付接口之前,需要先要調用統一下單接口,商戶系統先調用該接口在微信支付服務後台生成預支付交易單,返回正確的預支付交易回話標識後再在APP裡面調起支付。

 微信 JsApi支付 在這個目錄下 Senparc.Weixin.MP.Sample.Controllers 找到JsApi支付。

public ActionResult JsApi(string code, string state)
        {
            if (string.IsNullOrEmpty(code))
            {
                return Content("您拒絕了授權!");
            }

            if (!state.Contains("|"))
            {
                //這裡的state其實是會暴露給客戶端的,驗證能力很弱,這裡只是演示一下
                //實際上可以存任何想傳遞的數據,比如用戶ID,並且需要結合例如下面的Session["OAuthAccessToken"]進行驗證
                return Content("驗證失敗!請從正規途徑進入!1001");
            }
            try
            {


                //獲取產品信息
                var stateData = state.Split('|');
                int productId = 0;
                ProductModel product = null;
                if (int.TryParse(stateData[0], out productId))
                {
                    int hc = 0;
                    if (int.TryParse(stateData[1], out hc))
                    {
                        var products = ProductModel.GetFakeProductList();
                        product = products.FirstOrDefault(z => z.Id == productId);
                        if (product == null || product.GetHashCode() != hc)
                        {
                            return Content("商品信息不存在,或非法進入!1002");
                        }
                        ViewData["product"] = product;
                    }
                }

                //通過,用code換取access_token
                var openIdResult = OAuthApi.GetAccessToken(TenPayV3Info.AppId, TenPayV3Info.AppSecret, code);
                if (openIdResult.errcode != ReturnCode.請求成功)
                {
                    return Content("錯誤:" + openIdResult.errmsg);
                }

                string sp_billno = Request["order_no"];
                if (string.IsNullOrEmpty(sp_billno))
                {
                    //生成訂單10位序列號,此處用時間和隨機數生成,商戶根據自己調整,保證唯一
                    sp_billno = string.Format("{0}{1}{2}", TenPayV3Info.MchId, DateTime.Now.ToString("yyyyMMdd"),
                        TenPayV3Util.BuildRandomStr(10));
                }
                else
                {
                    sp_billno = Request["order_no"];
                }

                var timeStamp = TenPayV3Util.GetTimestamp();
                var nonceStr = TenPayV3Util.GetNoncestr();

                var body = product == null ? "test" : product.Name;
                var price = product == null ? 100 : product.Price * 100;
                var xmlDataInfo = new TenPayV3UnifiedorderRequestData(TenPayV3Info.AppId, TenPayV3Info.MchId, body, sp_billno, price, Request.UserHostAddress, TenPayV3Info.TenPayV3Notify, TenPayV3Type.JSAPI, openIdResult.openid, TenPayV3Info.Key, nonceStr);
                var result = TenPayV3.Unifiedorder(xmlDataInfo);//調用統一訂單接口

                //JsSdkUiPackage jsPackage = new JsSdkUiPackage(TenPayV3Info.AppId, timeStamp, nonceStr,);
                var package = string.Format("prepay_id={0}", result.prepay_id);

                ViewData["appId"] = TenPayV3Info.AppId;
                ViewData["timeStamp"] = timeStamp;
                ViewData["nonceStr"] = nonceStr;
                ViewData["package"] = package;
                ViewData["paySign"] = TenPayV3.GetJsPaySign(TenPayV3Info.AppId, timeStamp, nonceStr, package, TenPayV3Info.Key);

                return View();
            }
            catch (Exception ex)
            {
                var msg = ex.Message;
                msg += "<br>" + ex.StackTrace;
                msg += "<br>==Source==<br>" + ex.Source;

                if (ex.InnerException != null)
                {
                    msg += "<br>===InnerException===<br>" + ex.InnerException.Message;
                }
                return Content(msg);
            }
        }

 

先在微信服務後台生成預支付交易單,獲得預支付訂單號。

先說說在統一下單這裡遇到的坑。

 

1.在統一下單的時候解析返回結果,一直出現以下問題:您沒有JSAPI支付權限

<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[您沒有JSAPI支付權限]]></return_msg>
</xml>

 

1)先看看你的公眾號微信支付設置是否正確。

關於如何配置微信支付:可以參考這個 http://jingyan.baidu.com/article/77b8dc7fef360d6174eab690.html

2)檢查你的授權目錄是否正確,格式要這樣,後面記得別漏了一個/   例如:http://test.cn/u/

3)檢查需要傳過去的賬戶參數,上公眾號還有商戶號檢查你的賬戶參數是否正確。我在開發當中就出現,微信公眾號商戶號,appid 是分別不同兩個公眾號的,坑啊,找了好久,覺得不對勁,原來是給的配置參數密鑰不對。

 這裡詳細說一下對應的參數:

MCHID:商戶號(必須配置,開戶郵件中可查看),商戶申請微信支付後,由微信支付分配的商戶收款賬號。

APPID:微信開放平台審核通過的應用APPID,appid是微信公眾賬號或開放平台APP的唯一標識,在公眾平台申請公眾賬號或者在開放平台申請APP賬號後,微信會自動分配對應的appid用於標識該應用。可在微信公眾平台-->開發者中心查看,商戶的微信支付審核通過郵件中也會包含該字段值.

KEY:商戶支付密鑰,參考開戶郵件設置(必須配置,登錄商戶平台自行設置),交易過程生成簽名的密鑰,僅保留在商戶系統和微信支付後台,不會在網絡中傳播。商戶妥善保管該Key,切勿在網絡中傳輸,不能在其他客戶端中存儲,保證key不會被洩漏。商戶可根據郵件提示登錄微信商戶平台進行設置。也可按一下路徑設置:微信商戶平台(pay.weixin.qq.com)-->賬戶設置-->API安全-->密鑰設置.
APPSECRET:公眾帳號secert(僅JSAPI支付的時候需要配置, 登錄公眾平台,進入開發者中心可設置)

 

2.在統一下單,解析返回來的結果我出現了商戶號mch_id與appid不匹配這個問題

<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[商戶號mch_id與appid不匹配]]></return_msg>
</xml>

原因是我拿到的商戶號不是這個公眾號的。一定要檢查是不是這個公眾號的商戶號。

 

3.在統一下單,解析返回來的結果出現 appid and openid not match,appid和openid不匹配。

<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[appid and openid not match]]></return_msg>
</xml>

原因是我這個用戶的openid 不是這個公眾號的

 

3.在統一下單,解析返回來的結果出現 CDATA[openid is invalid],openid無效

<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[openid is invalid]]></return_msg>
</xml>

原因是,傳過去不是有效的opendid。不小心看錯了,把用戶id 當做openid傳過去了。

 

當統一下單成功,會返回以下格式的參數

<xml>
   <return_code><![CDATA[SUCCESS]]></return_code>
   <return_msg><![CDATA[OK]]></return_msg>
   <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
   <mch_id><![CDATA[10000100]]></mch_id>
   <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
   <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
   <result_code><![CDATA[SUCCESS]]></result_code>
   <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
   <trade_type><![CDATA[APP]]></trade_type>
</xml>

解析獲得預支付單號:

string prepayId = res.Element("xml").Element("prepay_id").Value; //獲取預支付訂單號

給頁面對應地參數

                ViewData["appId"] = TenPayV3Info.AppId;
                ViewData["timeStamp"] = timeStamp;
                ViewData["nonceStr"] = nonceStr;
                ViewData["package"] = package;
                ViewData["paySign"] = TenPayV3.GetJsPaySign(TenPayV3Info.AppId, timeStamp, nonceStr, package, TenPayV3Info.Key);

靜態頁面js調用:

wx.chooseWXPay({
    timestamp: 0, // 支付簽名時間戳,注意微信jssdk中的所有使用timestamp字段均為小寫。但最新版的支付後台生成簽名使用的timeStamp字段名需大寫其中的S字符
    nonceStr: '', // 支付簽名隨機串,不長於 32 位
    package: '', // 統一支付接口返回的prepay_id參數值,提交格式如:prepay_id=***)
    signType: '', // 簽名方式,默認為'SHA1',使用新版支付需傳入'MD5'
    paySign: '', // 支付簽名
    success: function (res) {
        if (res.err_msg == "get_brand_wcpay_request:ok") {//支付成功
 
       } else {
//支付失敗
}
  // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功後返回ok,但並不保證它絕對可靠。 } });

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved