Home  >  Article  >  WeChat Applet  >  WeChat payment development-Senparc.Weixin.MP detailed explanation

WeChat payment development-Senparc.Weixin.MP detailed explanation

高洛峰
高洛峰Original
2017-02-13 13:14:203295browse

Official account + WeChat payment SDK: Senparc.Weixin.MP.dll

Enterprise account SDK: Senparc.Weixin.QY.dll

Open platform SDK: Senparc.Weixin.Open. dll

Official address: http://weixin.senparc.com/

Of course, if we want to complete the development of the WeChat payment function of the official account, we need to use the DLL Senparc.Weixin.MP.dll , I checked the official DEMO and tutorials, but there are no instructions related to WeChat payment. I have no choice. Now that I have the source code, I can find it myself.

Open Senparc.Weixin.MP.sln. Based on the classification of the English folder names, it can be initially judged that WeChat payment is encapsulated in the TenPayLib folder, but I also found that there is a name called "TenPayLibV3" " folder, how to choose? After searching online, I came to this conclusion: those applied before September 10, 2014 are version v2, and those applied after that are version v3. The service account I used to test WeChat Pay was just applied for in 2016 and passed the verification, so just use V3 decisively.

Open the TenPayLibV3 folder:

微信支付开发-Senparc.Weixin.MP详解

Multiple class libraries are found here. What does each one do? We will not describe them one by one here. Interested friends can download and take a look. The file header of each category has function instructions and descriptions. According to the official payment instructions of WeChat, we will start the payment directly.

Enter the WeChat official account, click WeChat Payment in the function menu: and click Tutorial-Official Account Payment accordingly

微信支付开发-Senparc.Weixin.MP详解 微信支付开发-Senparc.Weixin.MP详解

Quickly review the document content Review and browse to find the corresponding functions in Senparc.Weixin.MP.dll.

微信支付开发-Senparc.Weixin.MP详解

First configure the payment authorization directory and add a payment test whitelist. Only three payment directories are supported, and the domain name must be ICP registered. The function of the authorization directory is that if you want to initiate a WeChat payment request, the requested link address must be in the authorization directory. Otherwise, the identity is invalid and the payment cannot be successful. Only the personal WeChat ID added to the test whitelist can complete the test of payment in the WeChat payment test directory. If a person who is not in the whitelist initiates a payment application, the payment will not be successful.

After the configuration is completed, how to call it? Let’s continue to look at the official description: H5 call up payment API.

“Open the H5 web page in WeChat browser and execute JS to call up payment. The input and output data format of the interface is JSON.

Note: WeixinJSBridge Built-in objects are not valid in other browsers.

The parameter names in the list are size-sensitive, and signature verification will fail if the case is incorrect. "

OK, here are a few things to explain, the first must be. WeChat browser; secondly, parameters are case-sensitive; thirdly, the data format is JSON.

Official description: As long as the following script is called on the page, the WeChat payment function can be enabled:

function onBridgeReady(){
   WeixinJSBridge.invoke(
       'getBrandWCPayRequest', {
           "appId" : "wx2421b1c4370ec43b",     //公众号名称,由商户传入     
           "timeStamp":" 1395712654",         //时间戳,自1970年以来的秒数     
           "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串     
           "package" : "prepay_id=u802345jgfjsdfgsdg888",     
           "signType" : "MD5",         //微信签名方式:     
           "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
       },
       function(res){     
           if(res.err_msg == "get_brand_wcpay_request:ok" ) {}     // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。 
       }
   ); 
}
if (typeof WeixinJSBridge == "undefined"){
   if( document.addEventListener ){
       document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
   }else if (document.attachEvent){
       document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
       document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
   }
}else{
   onBridgeReady();
}

My calling code: Because I want to call WeChat payment after clicking the button to confirm the payment. Carry out subsequent operations and put the official code into the method

function onBridgeReady() {
            WeixinJSBridge.invoke(
                'getBrandWCPayRequest', {
                    "appId": $('#APPID').val(),     //公众号名称,由商户传入     
                    "timeStamp": $('#Timestamp').val(),         //时间戳,自1970年以来的秒数     
                    "nonceStr": $('#Noncestr').val(), //随机串     
                    "package": $('#package').val(),
                    "signType": "MD5",         //微信签名方式:     
                    "paySign": $('#paySign').val() //微信签名 
                },
                function (res) {
                    if (res.err_msg == "get_brand_wcpay_request:ok") {
                        //支付成功,后续自行处理
                        
                    }
                    else
                    {
                        //支付取消,或者其他错误,自行处理
                    }
                }
            );
        }

Okay, so where do these parameters come from and what are they? Let’s analyze them one by one:

appId: Everyone who develops WeChat should know this. The official account can be found in the developer menu

timeStamp: timestamp, the official description is “since 1970” "Seconds", don't worry, you can definitely find

from the payment library. nonceStr: The official explanation is the random string "e61463f8efa94090b1f366cccfbbb444". What does it mean? See the random number generation algorithm for details. It turns out to be a set of encryption rules and algorithms. Friends who have done URL request interfaces should know that some companies’ JSON string signature methods are similar to this.

Package: Prepayment ID, which can be obtained by calling the official API unified ordering interface

SignType: String "MD5"

paySign: The official explanation is the WeChat signature "70EA570631E4BB79628FBCA90534C63FF7FADD89" , Okay, I endured it, and I took a look at the signature generation algorithm. It seems to be like a random string

At this point, the official interface description has been understood very clearly, so the next step is to solve the problem of calling WeChat How should I use these payment parameters through Senparc.Weixin.MP.dll? Since we need to first call the unified ordering interface to obtain the prepaid order ID, well, let's first study how to obtain this ID.

  官方给出了详细说明,我们不在赘述,各参数研究按照上述接口的方式自行研究解决,唯一区别在于,调用官方接口需要传入一个XML,那很好办,拼接一下就可以了,预支付调用方法如下:

//这里通过官方的一个实体,用户自行使用,我这里是直接读取的CONFIG文件
private static Senparc.Weixin.MP.TenPayLibV3.TenPayV3Info tenPayV3Info = new Senparc.Weixin.MP.TenPayLibV3.TenPayV3Info(ConfigurationManager.AppSettings["corpId"], ConfigurationManager.AppSettings["corpSecret"], ConfigurationManager.AppSettings["mch_id"]
                    , ConfigurationManager.AppSettings["key"], ConfigurationManager.AppSettings["v3url"]);

        /// <summary>
        /// 微信预支付
        /// </summary>
        /// <param name="attach"></param>
        /// <param name="body"></param>
        /// <param name="openid"></param>
        /// <param name="price"></param>
        /// <param name="orderNum"></param>
        /// <returns></returns>
        public static string PayInfo(string attach, string body, string openid, string price, string orderNum = "1833431773763549")
        {
            RequestHandler requestHandler = new RequestHandler(HttpContext.Current);
            //微信分配的公众账号ID(企业号corpid即为此appId)
            requestHandler.SetParameter("appid", tenPayV3Info.AppId);
            //附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
            requestHandler.SetParameter("attach", attach);
            //商品或支付单简要描述
            requestHandler.SetParameter("body", body);
            //微信支付分配的商户号
            requestHandler.SetParameter("mch_id", tenPayV3Info.MchId);
            //随机字符串,不长于32位。
            requestHandler.SetParameter("nonce_str", TenPayUtil.GetNoncestr());
            //接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。
            requestHandler.SetParameter("notify_url", tenPayV3Info.TenPayV3Notify);
            //trade_type=JSAPI,此参数必传,用户在商户公众号appid下的唯一标识。
            requestHandler.SetParameter("openid", openid);
            //商户系统内部的订单号,32个字符内、可包含字母,自己生成
            requestHandler.SetParameter("out_trade_no", orderNum);
            //APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。
            requestHandler.SetParameter("spbill_create_ip", "127.0.0.1");
            //订单总金额,单位为分,做过银联支付的朋友应该知道,代表金额为12位,末位分分
            requestHandler.SetParameter("total_fee", price);
            //取值如下:JSAPI,NATIVE,APP,我们这里使用JSAPI
            requestHandler.SetParameter("trade_type", "JSAPI");
            //设置KEY
            requestHandler.SetKey(tenPayV3Info.Key);

            requestHandler.CreateMd5Sign();
            requestHandler.GetRequestURL();
            requestHandler.CreateSHA1Sign();
            string data = requestHandler.ParseXML();
            requestHandler.GetDebugInfo();

            //获取并返回预支付XML信息
            return TenPayV3.Unifiedorder(data);
        }
    }

好的,拿到预支付订单的返回数据,一切又都好办了,根据返回参数的不同,自行解决,我们只关心调用正确的过程,操作继续,在返回的正确XML数据中,我们获取到了 88a638634f96c4d5385af75458953c57be5c8d72abc5b0647c20ab3ed87e8a806688e7ad0e17c5b2c6aa450a6c842cf4(官方示例),好的,开始在页面做支付吧!

这里,我封装了一个实体,用来传输常用的数据,当然,各位也可以参考Senparc.Weixin.MP.dll提供的实体类。

public class ShareInfo
    {
        string corpId = string.Empty;
        public string CorpId
        {
            get { return corpId; }
            set { corpId = value; }
        }
        string ticket = string.Empty;

        public string Ticket
        {
            get { return ticket; }
            set { ticket = value; }
        }
        string noncestr = string.Empty;

        public string Noncestr
        {
            get { return noncestr; }
            set { noncestr = value; }
        }
        string timestamp = string.Empty;

        public string Timestamp
        {
            get { return timestamp; }
            set { timestamp = value; }
        }

        private string paySign = string.Empty;
        public string PaySign
        {
            get { return paySign; }
            set { paySign = value; }
        }

        private string package = string.Empty;

        public string Package
        {
            get { return package; }
            set { package = value; }
        }
    }

我们继续,来看一下支付接口需要用到的参数如何获取:

public static ShareInfo GetPayInfo(string prepayid)
        {
            shareInfo = new ShareInfo();
            //检查是否已经注册jssdk
            if (!JsApiTicketContainer.CheckRegistered(corpId))
            {
                JsApiTicketContainer.Register(corpId, corpSecret);
            }
            JsApiTicketResult jsApiTicket = JsApiTicketContainer.GetTicketResult(corpId);
            JSSDKHelper jssdkHelper = new JSSDKHelper();
            shareInfo.Ticket = jsApiTicket.ticket;
            shareInfo.CorpId = corpId.ToLower();
            shareInfo.Noncestr = JSSDKHelper.GetNoncestr().ToLower();
            shareInfo.Timestamp = JSSDKHelper.GetTimestamp().ToLower();
            shareInfo.Package="prepay_id=" + prepayid.ToLower();

            RequestHandler requestHandler = new RequestHandler(HttpContext.Current);

            requestHandler.SetParameter("appId", shareInfo.CorpId);
            requestHandler.SetParameter("timeStamp", shareInfo.Timestamp);
            requestHandler.SetParameter("nonceStr", shareInfo.Noncestr);
            requestHandler.SetParameter("package", shareInfo.Package);
            requestHandler.SetParameter("signType", "MD5");

            requestHandler.SetKey(tenPayV3Info.Key);
            requestHandler.CreateMd5Sign();
            requestHandler.GetRequestURL();
            requestHandler.CreateSHA1Sign();
            shareInfo.PaySign = (requestHandler.GetAllParameters()["sign"]).ToString();
            return shareInfo;
        }

这样,支付接口需要用到的参数,就都封装在ShareInfo里了,好吧,调用之后,我们回到页面的后置代码中,或者你采用的ORM对应代码中去,将参数输出到页面

//处理页面支付调用信息
                    ShareInfo shareInfo = TenPayModule.GetPayInfo(prepayid);
                    System.Web.HttpContext.Current.Response.Write(string.Format("<input type=\"hidden\" id=\"Noncestr\" runat=\"server\" value=\"{0}\" />", shareInfo.Noncestr));
                    System.Web.HttpContext.Current.Response.Write(string.Format("<input type=\"hidden\" id=\"Timestamp\" runat=\"server\" value=\"{0}\" />", shareInfo.Timestamp));
                    System.Web.HttpContext.Current.Response.Write(string.Format("<input type=\"hidden\" id=\"APPID\" runat=\"server\" value=\"{0}\" />", shareInfo.CorpId));
                    System.Web.HttpContext.Current.Response.Write(string.Format("<input type=\"hidden\" id=\"paySign\" runat=\"server\" value=\"{0}\" />", shareInfo.PaySign));
                    System.Web.HttpContext.Current.Response.Write(string.Format("<input type=\"hidden\" id=\"package\" runat=\"server\" value=\"{0}\" />", shareInfo.Package));

好的,写到这里,大家参照上面的JS代码,就可以完成整个的支付功能了。最后,再附送一个生成商家订单号的方法,代码如下:

public string GetOrderNumber()
        {
            string Number = DateTime.Now.ToString("yyMMddHHmmss");
            return Number + Next(1000, 1).ToString();
        }
        private static int Next(int numSeeds, int length)
        {
            byte[] buffer = new byte[length]; 
            System.Security.Cryptography.RNGCryptoServiceProvider Gen = new System.Security.Cryptography.RNGCryptoServiceProvider();
            Gen.GetBytes(buffer);
            uint randomResult = 0x0; 
            for (int i = 0; i < length; i++)
            {
                randomResult |= ((uint)buffer[i] << ((length - 1 - i) * 8));
            }
            return (int)(randomResult % numSeeds);
        }

更多微信支付开发-Senparc.Weixin.MP详解 相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn