Maison >Applet WeChat >Développement WeChat >Développement du paiement WeChat-Senparc.Weixin.MP explication détaillée
SDK de paiement WeChat du compte officiel : Senparc.Weixin.MP.dll
SDK du compte entreprise : Senparc.Weixin.QY.dll
SDK de la plateforme ouverte : Senparc.Weixin.Open.dll
Adresse officielle : http://weixin.senparc.com/
Bien sûr, si nous voulons achever le développement de la fonction de paiement WeChat du compte officiel, nous devons utiliser le DLL Senparc.Weixin.MP.dll. J'ai vérifié la DÉMO et les tutoriels officiels, mais il n'y a aucune instruction relative au paiement WeChat. Je n'ai pas le choix. Maintenant que j'ai le code source, je peux le trouver moi-même.
Ouvrez Senparc.Weixin.MP.sln Sur la base de la classification des noms de dossiers anglais, nous pouvons dans un premier temps juger que le paiement WeChat est encapsulé dans le dossier TenPayLib, mais j'ai également trouvé qu'il existe un fichier nommé " Dossier TenPayLibV3" ", comment choisir ? Après une recherche en ligne, je suis arrivé à cette conclusion : celles appliquées avant le 10 septembre 2014 sont la version v2, et celles appliquées après sont la version v3. Le compte de service que j'ai utilisé pour tester WeChat Pay vient d'être demandé en 2016 et a réussi la vérification, il suffit donc d'utiliser la V3 de manière décisive.
Ouvrez le dossier TenPayLibV3 :
Il existe plusieurs bibliothèques de classes ici. Que fait chacune d'elles ? Nous ne les décrirons pas un par un ici. Les amis intéressés peuvent télécharger et jeter un œil. L'en-tête du fichier de chaque catégorie a une description et une description de la fonction. Selon les instructions de paiement officielles de WeChat, nous commencerons le paiement directement.
Entrez le compte officiel WeChat, cliquez sur Paiement WeChat dans le menu des fonctions : et cliquez sur le tutoriel d'utilisation - paiement du compte officiel en conséquence
Révisez rapidement le contenu du document Examinez et parcourez pour trouver les fonctions correspondantes dans Senparc.Weixin.MP.dll.
Configurez d'abord le répertoire d'autorisation de paiement et ajoutez une liste blanche de test de paiement. Seuls trois répertoires de paiement sont pris en charge et le nom de domaine doit être enregistré auprès d'ICP. La fonction du répertoire d'autorisation est que si vous souhaitez lancer une demande de paiement WeChat, l'adresse du lien demandée doit être dans le répertoire d'autorisation, sinon l'identité est invalide et le paiement ne peut pas aboutir. Seul le compte WeChat personnel ajouté à la liste blanche de test peut effectuer le test de paiement dans le répertoire de test de paiement WeChat. Si une personne qui ne figure pas dans la liste blanche lance une demande de paiement, le paiement échouera.
Une fois la configuration terminée, comment l'appeler ? Continuons à regarder la description officielle : H5 appelle l'API de paiement
« Ouvrez la page Web H5 dans le navigateur WeChat et exécutez JS pour appeler le paiement. Le format des données d'entrée et de sortie de l'interface est JSON <.>
Remarque : les objets intégrés de WeixinJSBridge ne sont pas valides dans les autres navigateurs Les noms de paramètres dans la liste sont sensibles à la taille et la vérification de la signature échouera si la casse est incorrecte. > OK, voici quelques choses à expliquer, la première doit être le navigateur WeChat ; deuxièmement, les paramètres sont sensibles à la casse ; troisièmement, le format des données est JSON ; Description officielle : Tant que le script suivant est appelé sur la page, la fonction de paiement WeChat peut être activée :Mon code d'appel : Parce que je veux appeler après avoir cliqué sur le pour confirmer le paiement. WeChat Pay effectue les opérations suivantes et met le code officiel dans la méthode
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(); }
D'accord, alors d'où viennent ces paramètres, et quels sont-ils ? Analysons-les un par un :
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 { //支付取消,或者其他错误,自行处理 } } ); }appId : Tous ceux qui développent WeChat devraient le savoir. Le compte officiel se trouve dans le menu développeur timeStamp : timestamp, la description officielle est « depuis 1970 ». " "Secondes", ne vous inquiétez pas, vous pouvez certainement le trouver dans la bibliothèque de paiement nonceStr : L'explication officielle est la chaîne aléatoire "e61463f8efa94090b1f366cccfbbb444". Voir l'algorithme de génération de nombres aléatoires pour plus de détails. Il s'avère qu'il s'agit d'un ensemble de règles et d'algorithmes de cryptage. Les amis qui ont réalisé des interfaces de requête d'URL doivent savoir que les méthodes de signature de chaîne JSON de certaines entreprises sont similaires à celles-ci. package : identifiant de prépaiement, qui peut être obtenu en appelant l'interface de commande unifiée de l'API officielle signType : chaîne "MD5" paySign : l'explication officielle est la signature WeChat "70EA570631E4BB79628FBCA90534C63FF7FADD89", d'accord, je l'ai enduré et j'ai jeté un œil à l'algorithme de génération de signature. Il semble être similaire à une chaîne aléatoire À ce stade, la description officielle de l'interface a été comprise très clairement, donc. l'étape suivante consiste à résoudre le problème de l'appel de WeChat. Comment dois-je utiliser ces paramètres de paiement via Senparc.Weixin.MP.dll ? Puisque nous devons d’abord appeler l’interface de commande unifiée pour obtenir l’identifiant de commande prépayée, étudions d’abord comment obtenir cet identifiant.
官方给出了详细说明,我们不在赘述,各参数研究按照上述接口的方式自行研究解决,唯一区别在于,调用官方接口需要传入一个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中文网!