Maison > Applet WeChat > Développement WeChat > Exemple détaillé de développement de compte public .NET WeChat (paiement WeChat 5.0)

Exemple détaillé de développement de compte public .NET WeChat (paiement WeChat 5.0)

Y2J
Libérer: 2017-05-03 10:31:30
original
3657 Les gens l'ont consulté

1. Avant-propos

Avant de commencer à utiliser cette fonction, la première chose que nous devons faire est de réfléchir à comment effectuer ce paiement WeChat, par où commencer, par où commencer, les instructions officielles du SDK et etc., y a-t-il une démo officielle, et si les informations que le patron m'a données sont complètes, et si les interfaces pour lesquelles postuler sont disponibles.

Après quelques explorations par moi-même, j'ai finalement terminé cela sous l'impulsion de mon patron. Le paiement WeChat est très déroutant. Je vais faire un résumé ici, j'espère que cela vous sera utile. . S’il y a quelque chose que j’ai dit qui n’est pas bon, j’espère que vous me le supporterez.

2. Préparation avant développement.

Documentation officielle du développeur WeChat Pay 1.0

Téléchargement de la démo officielle 2.0 Nous utilisons c#, nous avons donc choisi la version .net, mais cette démo officielle ne fonctionne pas du tout

La démo officielle 3.0 fonctionne Solution

Les pièges de la version officielle .net de WeChat Payment 4.0 ne sont pas négociables

Certaines configurations de la plateforme publique WeChat avant le développement de la 5.0, assurez-vous de vérifier la configuration avec soin

3. 🎜>

Après avoir terminé ces préparatifs, nous savons qu'il existe deux types de paiement WeChat, 1. Celui d'origine, 2. Celui directement appelé par jsapi Le second est utilisé dans mon projet

. Après quelques traitements de logique métier, nous sommes arrivés à notre Sur la page des détails de la commande, vous devez maintenant cliquer sur notre bouton de paiement pour payer. Le code pay.aspx sur la page de paiement est le suivant,

Avant. page :

<script type="text/javascript">               //调用微信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;//支付成功后的跳转页面

                        }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">  您确认付款<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>
Copier après la connexion
Il convient de noter que :

L'API WeChat JS ne peut être utilisée que dans le navigateur intégré de WeChat et les appels provenant d'autres navigateurs ne sont pas valides. WeChat fournit l'interface getBrandWCPayRequest permettant à la page Web frontale du commerçant d'appeler. Avant d'appeler, WeChat identifiera l'autorité de paiement du commerçant. Si le commerçant a le pouvoir d'initier le paiement, le processus de paiement commencera. Cette section présente principalement les règles d'appel de l'interface avant le paiement. Veuillez vous référer au mécanisme de notification des messages d'état du paiement ci-dessous. L'interface est à noter : tous les paramètres entrants sont des types chaînes !

Les paramètres getBrandWCPayRequest sont présentés dans le tableau 6-5.

timeStamp timestamp est Type de chaîne, moins de 32 octetsGénéré par le commerçant, le nombre de secondes depuis 00:00:00 du 1er janvier 1970 jusqu'à nos jours, c'est-à-dire le heure actuelle, Et enfin doit être converti en forme de chaîne nonceStrChaîne aléatoire est de type chaîne, de moins de 32 octets une chaîne aléatoire générée par le commerçant <🎜 ; >colissignType ;

Paramètres

Nom

Obligatoire

Format

Description

appId

Identifiant de compte officiel

Oui

Type de chaîne

Il peut être obtenu une fois que le commerçant a enregistré avec succès un compte public avec autorisation de paiement

< ; 🎜>

chaîne étendue des détails de la commande

est

Type de chaîne, moins de 4096 octets

Le commerçant compose les informations de commande dans cette chaîne Pour le schéma de composition spécifique, veuillez vous référer à l'aide au regroupement de packages. dans les instructions d'utilisation de l'interface ; Épissé par le commerçant conformément aux spécifications

<🎜 ; >Méthode de signature

est un type de chaîne de

La valeur du paramètre est "SHA1"

<. 🎜> comme indiqué dans le document. Actuellement, prend uniquement en charge SHA1

paySign

签名

字符串类型

商户将接口列表中的参数按照指定方式迚行签名,签名方式使用signType中标示的签名方式,具体签名方案参见接口使用说明中签名帮劣;由商户按照规范签名后传入;

表6-5 getBrandWCPayRequest参数

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的返回结果 get_brand_wcpay_request:ok 仅在用户成功完成支付时返回。由于前端交互复杂,get_brand_wcpay_request:cancel 或者 get_brand_wcpay_request:fail 可以统一处理为用户遇到错误或者 主动放弃,不必细化区分。

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 +
Copier après la connexion

在这里需要我们注意的是:jsApiPay.openid = common.GetOpenId();

在支付的时候,我们需要首先获取用户的openId,然而获取用户openId的这个过程我们首先要进行Oauth2认证,在官方的demo中提供了JsApiPay.cs这个核心类库,里面已经有这个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 构造函数        /// <summary>
        /// 构造函数        /// </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
            {                //构造网页授权获取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
                {                    //触发微信返回code码         
                    Context.Response.Redirect(url);//Redirect函数会抛出ThreadAbortException异常,不用处理这个异常                }                catch (System.Threading.ThreadAbortException ex)
                {
                }
            }
        }        
        #endregion

        #region 通过用户授权获取AccessToken和OpenId        /// <summary>
        /// 通过用户授权获取AccessToken和OpenId        /// </summary>
        /// <param name="code"></param>
        public  void GetOpenidAndAccessTokenFromCode(string code)
        {            try
            {                //构造获取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以获取数据
                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
    }
Copier après la connexion

 public class JsApiPay
    {        /// <summary>
        /// 保存页面对象,因为要在类的方法中使用Page的Request对象        /// </summary>
        private Page page {get;set;}        /// <summary>
        /// openid用于调用统一下单接口        /// </summary>
        public string openid { get; set; }        /// <summary>
        /// access_token用于获取收货地址js函数入口参数        /// </summary>
        public string access_token { get; set; }        /// <summary>
        /// 商品金额,用于统一下单        /// </summary>
        public int total_fee { get; set; }        /// <summary>
        /// 订单Id        /// </summary>
        public string orderid { get; set; }        /// <summary>
        /// 统一下单接口返回结果        /// </summary>
        public WxPayData unifiedOrderResult { get; set; } 

        public JsApiPay(Page page)
        {            this.page = page;
        }        /**
        * 
        * 网页授权获取用户基本信息的全部过程
        * 详情请参看网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
        * 第一步:利用url跳转获取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
            {                //构造网页授权获取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
                {                    //触发微信返回code码         
                    page.Response.Redirect(url);//Redirect函数会抛出ThreadAbortException异常,不用处理这个异常                }                catch(System.Threading.ThreadAbortException ex)
                {
                }
            }
        }        /**
        * 
        * 通过code换取网页授权access_token和openid的返回数据,正确时返回的JSON数据包如下:
        * {
        *  "access_token":"ACCESS_TOKEN",
        *  "expires_in":7200,
        *  "refresh_token":"REFRESH_TOKEN",
        *  "openid":"OPENID",
        *  "scope":"SCOPE",
        *  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
        * }
        * 其中access_token可用于获取共享收货地址
        * openid是微信支付jsapi支付接口统一下单时必须的参数
        * 更详细的说明请参考网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
        * @失败时抛异常WxPayException        */
        public void GetOpenidAndAccessTokenFromCode(string code)
        {            try
            {                //构造获取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以获取数据
                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());
            }
        }        /**
         * 调用统一下单,获得下单结果
         * @return 统一下单结果
         * @失败时抛异常WxPayException         */
        public WxPayData GetUnifiedOrderResult()
        {            //统一下单
            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)
        {            //统一下单
            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;
        }        /**
        *  
        * 从统一下单成功返回的数据中获取微信浏览器调起jsapi支付所需的参数,
        * 微信浏览器调起JSAPI时的输入参数格式如下:
        * {
        *   "appId" : "wx2421b1c4370ec43b",     //公众号名称,由商户传入     
        *   "timeStamp":" 1395712654",         //时间戳,自1970年以来的秒数     
        *   "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串     
        *   "package" : "prepay_id=u802345jgfjsdfgsdg888",     
        *   "signType" : "MD5",         //微信签名方式:    
        *   "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
        * }
        * @return string 微信浏览器调起JSAPI时的输入参数,json格式可以直接做参数用
        * 更详细的说明请参考网页端调起支付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函数入口参数,详情请参考收货地址共享接口:http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?

chapter=7_9
        * @return string 共享收货地址js函数需要的参数,json格式可以直接做参数使用        */
        public string GetEditAddressParameters()
        {            string parameter = "";            try
            {                string host = page.Request.Url.Host;                string path = page.Request.Path;                string queryString = page.Request.Url.Query;                //这个地方要注意,参与签名的是网页授权获取用户信息时微信后台回传的完整url
                string url = "http://" + 

host + path + queryString;                //构造需要用SHA1算法加密的数据
                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函数入口参数
                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"));                //转为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;
        }
    }
Copier après la connexion

JsApiPay

微信支付协议接口数据类WxPayData.cs官方都有相应的代码.

 /// <summary>
    /// 微信支付协议接口数据类,所有的API接口通信都依赖这个数据结构,    /// 在调用接口之前先填充各个字段的值,然后进行接口通信,    /// 这样设计的好处是可扩展性强,用户可随意对协议进行更改而不用重新设计数据结构,    /// 还可以随意组合出不同的协议数据包,不用为每个协议设计一个数据包结构    /// </summary>
    public class WxPayData
    {        public WxPayData()
        {

        }        //采用排序的Dictionary的好处是方便对数据包进行签名,不用再签名之前再做一次排序
        private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();        /**
        * 设置某个字段的值
        * @param key 字段名
         * @param value 字段值        */
        public void SetValue(string key, object value)
        {
            m_values[key] = value;
        }        /**
        * 根据字段名获取某个字段的值
        * @param key 字段名
         * @return key对应的字段值        */
        public object GetValue(string key)
        {            object o = null;
            m_values.TryGetValue(key, out o);            return o;
        }        /**
         * 判断某个字段是否已设置
         * @param key 字段名
         * @return 若字段key已被设置,则返回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转成xml
        * @return 经转换得到的xml串
        * @throws WxPayException
        **/
        public string ToXml()
        {            //数据为空时不能转化为xml格式
            if (0 == m_values.Count)
            {
                Log.Error(this.GetType().ToString(), "WxPayData数据为空!");                throw new WxPayException("WxPayData数据为空!");
            }            string xml = "<xml>";            foreach (KeyValuePair<string, object> pair in m_values)
            {                //字段值不能为null,会影响后续流程
                if (pair.Value == null)
                {
                    Log.Error(this.GetType().ToString(), "WxPayData内部含有值

为null的字段!");                    throw new WxPayException("WxPayData内部含有值为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类型不能含有其他数据类型                {
                    Log.Error(this.GetType().ToString(), "WxPayData字段数据类

型错误!");                    throw new WxPayException("WxPayData字段数据类型错误!");
                }
            }
            xml += "</xml>";            return xml;
        }        /**
        * @将xml转为WxPayData对象并返回对象内部的数据
        * @param string 待转换的xml串
        * @return 经转换得到的Dictionary
        * @throws WxPayException        */
        public SortedDictionary<string, object> FromXml(string xml)
        {            if (string.IsNullOrEmpty(xml))
            {
                Log.Error(this.GetType().ToString(), "将空的xml串转换为

WxPayData不合法!");                throw new WxPayException("将空的xml串转换为WxPayData不合法!");
            }

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xml);
            XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
            XmlNodeList nodes = xmlNode.ChildNodes;            foreach (XmlNode xn in nodes)
            {
                XmlElement xe = (XmlElement)xn;
                m_values[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中            }            
            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格式转化成url参数格式
        * @ 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内部含有值

为null的字段!");                    throw new WxPayException("WxPayData内部含有值为null的字段!");
                }                if (pair.Key != "sign" && pair.Value.ToString() != "")
                {
                    buff += pair.Key + "=" + pair.Value + "&";
                }
            }
            buff = buff.Trim(&#39;&&#39;);            return buff;
        }        /**
        * @Dictionary格式化成Json
         * @return json串数据        */
        public string ToJson()
        {            string jsonStr = JsonMapper.ToJson(m_values);            return jsonStr;
        }        /**
        * @values格式化成能在Web页面上显示的结果(因为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内部含有值

为null的字段!");                    throw new WxPayException("WxPayData内部含有值为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()
        {            //转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"));
            }            //所有字符转为大写
            return sb.ToString().ToUpper();
        }        /**
        * 
        * 检测签名是否正确
        * 正确返回true,错误抛异常        */
        public bool CheckSign()
        {            //如果没有设置签名,则跳过检测
            if (!IsSet("sign"))
            {
               Log.Error(this.GetType().ToString(), "WxPayData签名存在但不合法

!");               throw new WxPayException("WxPayData签名存在但不合法!");
            }            //如果设置了签名但是签名为空,则抛异常
            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;
        }
    }
Copier après la connexion

WxPayData

配置文件信息

    /**
    *     配置账号信息    */
    public class WxPayConfig
    {        //=======【基本信息设置】=====================================
        /* 微信公众号信息配置
        * APPID:绑定支付的APPID(必须配置)
        * MCHID:商户号(必须配置)
        * KEY:商户支付密钥,参考开户邮件设置(必须配置)
        * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置)        */
        public const string APPID = "wx14e3e56f3";        public const string MCHID = "12352";        public const string KEY = "BB6BE71D7CED49A79409C9";        public const string APPSECRET = "76eb33f66129692da1624f1";        //=======【证书路径设置】===================================== 
        /* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要)        */
        public const string SSLCERT_PATH = "cert/apiclient_cert.p12";        public const string SSLCERT_PASSWORD = "123502";        //=======【支付结果通知url】===================================== 
        /* 支付结果通知回调url,用于商户接收支付结果        */
        public const string NOTIFY_URL = "http://www.baidu.com/ResultPay.aspx";        //=======【商户系统后台机器IP】===================================== 
        /* 此参数可手动配置也可在程序中自动获取        */
        public const string IP = "150.24.91.151";        //=======【代理服务器设置】===================================
        /* 默认IP和端口号分别为0.0.0.0和0,此时不开启代理(如有需要才设置)        */
        public const string PROXY_URL = "http://10.152.18.220:8080";        //=======【上报信息配置】===================================
        /* 测速上报等级,0.关闭上报; 1.仅错误时上报; 2.全量上报        */
        public const int REPORT_LEVENL = 1;        //=======【日志级别】===================================
        /* 日志等级,0.不输出日志;1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息        */
        public const int LOG_LEVENL =3;
    }
Copier après la connexion

WxPayConfig

接着我们在看2行关键的代码:

                            WxPayData unifiedOrderResult == jsApiPay.GetJsApiParameters();
Copier après la connexion

此时如果wxJsApiParam变量能够顺利拿到值,那么我们前台页面的:<%=wxJsApiParam%>z这里就可以获取到我们要传递的参数,这时候就可以调用微信支付的接口,打开我们的付款页面如图所示:

               //调用微信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;);
                        }
                         
                     }
                    );
               }
Copier après la connexion

(JsApiPay.cs)得到下单结果:

        public WxPayData GetUnifiedOrderResult(string body)
        {            //统一下单
            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;
        }
Copier après la connexion

(WxPayApi.cs)统一下单接口:

        /**
        * 
        * 统一下单
        * @param WxPaydata inputObj 提交给统一下单API的参数
        * @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";            //检测必填参数
            if (!inputObj.IsSet("out_trade_no"))
            {                throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");
            }            else if (!inputObj.IsSet("body"))
            {                throw new WxPayException("缺少统一支付接口必填参数body!");
            }            else if (!inputObj.IsSet("total_fee"))
            {                throw new WxPayException("缺少统一支付接口必填参数total_fee!");
            }            else if (!inputObj.IsSet("trade_type"))
            {                throw new WxPayException("缺少统一支付接口必填参数trade_type!");
            }            //关联参数
            if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
            {                throw new WxPayException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
            }            if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
            {                throw new WxPayException("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
            }            //异步通知url未设置,则使用配置文件中的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;
        }
Copier après la connexion

四.最终开发的效果

五.微信公众号开发系列导航

1.0初始微信公众号

2.0创建自定义菜单

3.0查询自定义菜单

4.0公众号消息处理

5.0微信支付

6.0模板消息

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal