في الآونة الأخيرة ، تعرضت لبعض الأشياء حول دفع WeChat في عملي. لقد رأيت أن العروض التوضيحية التي قدمتها كانت جميعها إصدارات PHP ، ولم أكن راضية حقًا عن مستندات دفع WeChat. بعد تجربة العديد من المزالق ، كنت خاملاً لإجراء ملخص.
1. التحضير
لتطوير WeChat ، يجب عليك أولاً التقدم للحصول على حساب عام. بعد نجاح التطبيق ، سيتم إرسالك إليك عبر البريد الإلكتروني. يحتوي الحساب العام على مستندات التطوير والمعلومات اللازمة أثناء التطوير والاستعلام عن البيانات للاختبار.
2. الأدوات
1.MD5 فئة أدوات التشفير
package com.pay.utils.weixin ؛ استيراد java.security.messagedigest ؛ الفئة العامة md5util {public Final Static String Md5 (String s) {char hexdigits [] = {'0' ، '1' ، '2' ، '3' ، '4' ، '5' ، '6' ، '7' ، '8' ، '9' ، 'a' ، 'b' ، 'c' ، 'd' ، 'e' ، 'f'} ؛ حاول {byte [] btinput = s.getBytes () ؛ // احصل على كائن messagedigest من خوارزمية MD5 Digest MessAgedigest mdinst = messagedigest.getInstance ("MD5") ؛ // تحديث Digest mdinst.update (btinput) ؛ // احصل على byte ciphertext [] md = mdinst.digest () ؛ // تحويل النص المشفر إلى نموذج سلسلة hex int j = md.length ؛ char str [] = new Char [J * 2] ؛ int k = 0 ؛ لـ (int i = 0 ؛ i <j ؛ i ++) {byte byte0 = md [i] ؛ str [k ++] = hexDigits [byte0 >>> 4 & 0xf] ؛ str [k ++] = hexDigits [byte0 & 0xf] ؛ } إرجاع سلسلة جديدة (str) ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ العودة لاغية. }}}2. فئة أدوات CommonUtil ، تستخدم لاستبدال XML المطلوبة لـ WeChat. الإرجاع التالي سلسلة جديدة (xml.toString (). getBytes () ، "ISO8859-1") ؛ تغيير UTF-8 في فئة الأدوات إلى ISO8859-1 ، وإلا فإن النص الصيني في ترتيب WeChat سيظهر مشوه ، ويمكن عرضه بشكل صحيح بعد التغيير.
package com.pay.utils.weixin ؛ import java.io.unsupportedencodingexception ؛ import java.net.urlencoder ؛ import java.util.*؛ import java.util.map.entry "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789" ؛ سلسلة الدقة = "" ؛ لـ (int i = 0 ؛ i <length ؛ i ++) {random rd = new random () ؛ res += chars.indexof (rd.nextint (chars.length () - 1)) ؛ } return res ؛ } السلسلة الثابتة العامة CreateNonCestr () {String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ؛ سلسلة الدقة = "" ؛ لـ (int i = 0 ؛ i <16 ؛ i ++) {random rd = new random () ؛ res += chars.charat (rd.nextint (chars.length () - 1)) ؛ } return res ؛ } السلسلة الثابتة العامة formatqueryparamap (hashmap <string ، string> parameters) يلقي sdkruntimeException {string buff = "" ؛ حاول {list <map.entry <string ، string >> infoids = new ArrayList <map.entry <string ، string >> (parameters.entryset ()) ؛ collections.sort (infoids ، مقارن جديد <map.entry <string ، string >> () {public int compare (map.entry <string ، string> o1 ، map.entry <string ، string> o2) {return (o1.getkey ()). لـ (int i = 0 ؛ i <finfoids.size () ؛ i ++) {map.entry <string ، string> item = infoids.get (i) ؛ if (item.getKey ()! = "") {buff + = item.getKey () + "=" + urlencoder.encode (item.getValue () ، "utf-8") + "&" ؛ }} if (buff.isempty () == false) {buff = buff.subString (0 ، buff.length () - 1) ؛ }} catch (استثناء e) {رمي sdkruntimeException (e.getMessage ()) ؛ } إرجاع برتقالي ؛ ) جرب {list <map.entry <string ، string >> infoids = new ArrayList <map.entry <string ، string >> (paramap.entryset ()) ؛ collections.sort (infoids ، مقارن جديد <map.entry <string ، string >> () {public int compare (map.entry <string ، string> o1 ، map.entry <string ، string> o2) {return (o1.getkey ()). لـ (int i = 0 ؛ i <finfoids.size () ؛ i ++) {map.entry <string ، string> item = infoids.get (i) ؛ //system.out.println (item.getKey ()) ؛ if (item.getKey ()! = "") {string key = item.getKey () ؛ string val = item.getValue () ؛ if (urlencode) {val = urlencoder.encode (val ، "utf-8") ؛ } buff + = key.toLowerCase () + "=" + val + "&" ؛ }} if (buff.isempty () == false) {buff = buff.subString (0 ، buff.length () - 1) ؛ }} catch (استثناء e) {رمي sdkruntimeException (e.getMessage ()) ؛ } إرجاع برتقالي ؛ } isnumeric isnumeric (String str) {if (str.matches ("// d *")) {return true ؛ } آخر {return false ؛ }} سلسلة ثابتة arraytoxml (HashMap <string ، arr) {string xml = "<xml>" ؛ iterator <intrad <string ، string >> iter = arr.entrySet (). iterator () ؛ بينما (iter.hasnext ()) {entry <string ، string> entrate = iter.next () ؛ مفتاح السلسلة = intpling.getKey () ؛ string val = enter.getValue () ؛ if (isNumeric (val)) {xml + = "<" + key + ">" + val + "</" + key + ">" ؛ } آخر xml + = "<" + key + "> <! } xml += "</xml>" ؛ حاول {return new string (xml.toString (). getBytes () ، "ISO8859-1") ؛ } catch (UnsupportedEncodingException e) {// todo catch catch e.printstacktrace () ؛ } يعود ""؛ }}3. ClientCustomssl Class ، تستخدم لإنشاء علامات وإنشاء حزمة طلب WeChat com.pay.utils.weixin ؛
استيراد java.util.arraylist ؛ استيراد java.util.collections ؛ استيراد java.util.comparator ؛ استيراد java.util.hashmap ؛ استيراد java.util.list ؛ استيراد java.util.map ؛ */clientcustomssl clientcustomsl {public static string getBizSign (hashmap <string ، string> bizobj) يلقي sdkruntimeexception {hashmap <string ، string> bizparameters = new hashmap <string ، string> () ؛ قائمة <map.entry <string ، string >> infoids = new ArrayList <map.entry <string ، string >> (bizobj.entryset ()) ؛ system.out.println (infoids) ؛ collections.sort (infoids ، new Cookerator <map.entry <string ، string >> () {public int compare (map.entry <string ، string> o1 ، map.entry <string ، string> o2) {return (o1.getKey ()). tostring (). system.out.println (infoids) ؛ لـ (int i = 0 ؛ i <finfoids.size () ؛ i ++) {map.entry <string ، string> item = infoids.get (i) ؛ if (item.getKey ()! = "") {bizparameters.put (item.getKey (). tolowercase () ، item.getValue ()) ؛ }} //bizparameters.put("key "،" 1234567812345678123456781234567812345671 ") ؛ سلسلة bizstring = commonutil.formatbizqueryparamap (bizparameters ، false) ؛ BizString += "& Key = 123456781234567812345671" ؛ System.out.println ("***************") ؛ system.out.println (bizstring) ؛ // return sha1uTil.sha1 (bizstring) ؛ إرجاع md5util.md5 (bizstring) ؛ } / ** * wechat إنشاء ترتيب * param noncestr * param orderdescribe * param orderno * param price * param timestart * param timeExpire * @thrats sdkruntimeexception * / public static staticpackage (سلسلة noncestr ، سلسلة ترتيب ، sdkruntimeException {hashMap <string ، string> nativeObj = new hashmap <string ، string> () ؛ nativeObj.put ("appid" ، "انظر الحساب العام") ؛ // account id public nativeObj.put ("MCH_ID" ، "انظر البريد الإلكتروني") ؛ // Number Merchant NativeObj.put ("nonce_str" ، noncestr) ؛ // Random String nativeObj.put ("body" ، orderdescribe) ؛ // وصف المنتج الأصليين ("إرفاق" ، "Tradeno") ؛ // Data Data nativeObj.put ("Out_trade_no" ، orderno) ؛ // رقم أمر التاجر (Global Exhine) nativeObj.put ("Total_fee" ، السعر) ؛ . // terminal IP nativeObj.put ("time_start" ، mutestart) ؛ // Transaction Time NativeObj.put ("time_expire" ، timeExpire) ؛ // End Time time nativeObj.put ("notify_url" ، CustomProperTyPlaterConfigurer.getContextProperty ("wxurl")+"/weixin_callback/weixincallback/init.action") ؛ // عنوان إشعار رد الاتصال nativeObj.put ("Trade_type" ، "Native") ؛ // علامة سلسلة نوع المعاملة = getBizSign (nativeObj) ؛ nativeObj.put ("sign" ، sign.toupperCase ()) ؛ إرجاع commonutil.arraytoxml (nativeObj) ؛ } /*** استعلام دفع طلب WeChat* param noncestr* param orderdescribe* param orderno* param price* param timestart* param timeExpire* @return* throws sdkruntimeexception* /public static stringpackage (string tracentid ، stringtradeno {hashmap <string ، string> nativeObj = new hashmap <string ، string> () ؛ nativeObj.put ("appid" ، "انظر الحساب العام") ؛ // الحساب العام idnativeObj.put ("MCH_ID" ، "انظر البريد الإلكتروني") ؛ // Number Merchant NativeObj.put ("nonce_str" ، noncestr) ؛ // سلسلة عشوائية if (! stringUtils.isempty (TransactionId)) {nativeObj.put ("Transaction_id" ، TransactionId) ؛ } if (! stringUtils.isempty (OutTradeno)) {nativeObj.put ("out_trade_no" ، OutTradeno) ؛ // random string} string sign = getBizSign (nativeObj) ؛ nativeObj.put ("sign" ، sign.touppercase ()) ؛ إرجاع commonutil.arraytoxml (nativeObj) ؛ /*** WeChat Readdrant* param outtradeno* param outrefundno* param totalfee* param totalfee* param reneftfee* @return* throws sdkruntimeexception*/public static relectionpackage (string outtradeno ، string outtrefundno sdkruntimeexception {hashmap <string ، string> nativeObj = new hashmap <string ، string> () ؛ nativeObj.put ("appid" ، "انظر الحساب العام") ؛ // الحساب العام idnativeObj.put ("mch_id" ، "انظر البريد الإلكتروني") NativeObj.put ("Out_trade_no" ، OutTradeno) ؛ // رقم الطلب التجاري (Global Exhine) NativeObj.put ("Out_Refund_No" ، Outrefundno) ؛ // رقم ترتيب استرداد المبلغ التجاري (Global Exhine) NativeObj.put ("REWND_FEE" ، REWNDFEE) ؛ // مبلغ الاسترداد (الوحدة بالسنتات ، لا يمكن أن تأخذ نقاطًا عشرية) علامة سلسلة = getBizSign (nativeObj) ؛ nativeObj.put ("sign" ، sign.touppercase ()) ؛ إرجاع commonutil.arraytoxml (nativeObj) ؛}/*** wechat ليتم دفعه* param noncestr* param orderdescribe* param orderno* param price* param timeStart* param timeexpire* @return CreateJSapiPackage (سلسلة noncestr ، order orderdescribe ، order orderno ، سعر السلسلة ، سلسلة الطابع الزمني ، سلسلة timeExpire ، سلسلة مفتوحة) يلقي sdkruntimeexception {hashmap <string ، string> nativeObj = new hashmap <string ، string> () ؛ OpenID) ؛ // حساب public idnativeObj.put ("mch_id" ، "انظر البريد الإلكتروني") // رقم تجاري nativeObj.put ("nonce_str" ، noncestr) ؛ // string random nativeobj.put ("body" ، orderdescribe) ؛ // وصف المنتج الأصلي (إرفاق "،" Tradeno " OrderNo) ؛ // رقم الطلب التجاري (Global Exhine) nativeObj.put ("Total_fee" ، السعر) ؛ // الإجمالي المبلغ (الوحدة مئوية ، لا يمكن أن تأخذ نقاطًا عشرية) nativeObj.put ("time_expire" ، timeExpire) // نهاية المعاملة وقت nativeObj.put ("notify_url" ، CustomProperTyPlateHOlderConfigurer.getContextProperty ("wxurl")+"/weixin_callback/weixincallback/init.action") ؛ "jsapi") ؛ // علامة سلسلة نوع المعاملة = getBizSign (nativeObj) ؛ nativeObj.put ("sign" ، sign.touppercase ()) ؛ إرجاع commonutil.arraytoxml (nativeObj) ؛}/*** ترتيب إغلاق على WeChat* param noncestr* param orderdescribe* param orderno* @param price* param timestart* param timeExpire* param openid* @throws sdkruntimeexception* sdkruntimeexception {hashmap <string ، string> nativeObj = new hashmap <string ، string> () ؛ nativeObj.put ("appid" ، "انظر الحساب العام") ؛ // الحساب العام idnativeObj.put ("mch_id" ، "انظر البريد الإلكتروني") (فريدة من نوعها على المستوى العالمي) nativeObj.put ("nonce_str" ، noncestr) ؛ // علامة سلسلة عشوائية = getBizSign (nativeObj) ؛ nativeObj.put ("sign" ، sign.touppercase ()) ؛ إرجاع commonutil.arraytoxml (nativeObj) ؛}} 4. اتصل بواجهة الدفع WeChat
package com.pay.controller.weixin ؛ استيراد java.io.file ؛ استيراد java.io.fileinputstream ؛ استيراد java.security.keystore ؛ استيراد java.text.simpleTaTformat ؛ استيراد java.util.date javax.servlet.http.httpservletrequest ؛ import javax.servlet.http.htpservletresponse ؛ import net.sf.json.jsonarray ؛ import net.sf.json.jsonobject ؛ import org.http.htpentity ؛ org.apache.http.client.methods.closablehttpresponse ؛ import org.apache.http.client.methods.httppost ؛ import org.apache.http.conn.ssl.sslconnectionfactory ؛ org.apache.http.entity.stringentity ؛ import org.apache.http.impl.client.closablehttpclient ؛ import org.apache.http.impl.client.httpclients ؛ import org.http.Util.entityutils ؛ import orgdom4j.document ؛ org.dom4j.documentHelper ؛ استيراد org.dom4j.element ؛ استيراد org.dom4j.io.saxreader ؛ استيراد org.springframework.beans.factory.annotation. org.springframework.web.bind.annotation.requestbody ؛ استيراد org.springframework.web.bind.annotation.requestmapping ؛ استيراد org.springframework.web.bind.annotation.requestmethod ؛ استيراد org.springframework org.springframework.web.bind.annotation.restController ؛ import com.pay.bo.payhistants.import com.pay.constants.payhistorypaystatus ؛ import com.pay.constants.payhistorypaype ؛ com.pay.utils.weixin.clientcustomssl ؛ استيراد com.pay.utils.weixin.closeweixinorderutils ؛ استيراد com.pay.utils.weixin.customizedPropertyplyderConfigurer ؛ reprontroller@requestmapp WeixinPayservice ؛ Static Static Long Standate = 1662652800000L ؛ /** * إرجاع عنوان URL الذي ينشئ رمز QR * request request * param response * return */ @requestmapping (value = "/geturl" ، method = requestMethod.post) responsestatus (httpstatus.ok) geturl geturl (httpservletresponse ، @requestbody body) jsonobject.fromObject (الجسم) ؛ parhist ph = null ؛ // list <map <string ، object >> td = weixinpayservice.gettrade (orderno) ؛ تاريخ dt = تاريخ جديد () ؛ SimplEdateFormat SDF = جديد spiStFormat ("Yyyymmddhhmmss") ؛ سلسلة noncestr = sdf.format (dt) .toString () ؛ التاريخ الآن = تاريخ جديد () ؛ String TradePayNo = jsono.get ("orderno"). toString ()+string.format ("٪ 10d" ، standardtime - now.getTime ()). substring (0 ، 10) ؛ system.out.println ("订单标号 orderno ========"+jsono.get ("orderno"). toString ()) ؛ System.out.println ("10 位随机数 ========"+string.format ("٪ 10D" ، standardtime - now.getTime ()). Substring (0 ، 10)) ؛ سعر السلسلة = Math.Round (float.valueof (jsono.get ("Price"). ToString ())*100)+"" ؛ TimeExpirTrold = dt.getTime () ؛ Long timenew = long.parselong (CustomProperTyPlateHOlderConfigurer.getContextProperty ("Weixin.Send2Finish.Overtime"). ToString ()) ؛ TimeExpirEnew = timeExpirestrold+TimEnew ؛ Date dttimeexpire = تاريخ جديد (timeExpirenew) ؛ SimpleDateFormat DTSDF = جديد simpledateFormat ("Yyyymmddhhmmss") ؛ string timeExpire = dtsdf.format (dttimeexpire) .toString () ؛ System.out.println ("noncestr =="+noncestr) ؛ System.out.println ("orderno =="+jsono.get ("orderno"). toString ()) ؛ System.out.println ("Price =="+Price) ؛ System.out.println ("MIDESTART =="+noncestr) ؛ system.out.println ("timeExpire =="+timeExpire) ؛ JSonObject Result = (jsonobject) seturl (noncestr ، "order" ، tradepayno ، price ، noncestr ، timeExpire) ؛ if (result.get ("status"). Ph.SetTradePayurl (result.getString ("WeixinPayurl")) ؛ // هذا الحقل هو رابط دفع. يمكنك إنشاء رمز QR لمسح الرمز لدفع Ph.SetPayTradeno (jsono.get ("orderno"). ToString ()) ؛ Ph.SetTradePayno (TradePayno) ؛ Ph.SetPayStatus (payhistorypaystatus.wechat_pay_status_wait) ؛ Ph.SetPayType (payhistorypaytype.wechat) ؛ Ph.SetAppkey (jsono.getString ("appkey"). ToString ()) ؛ Ph.SetPayAmount (السعر) ؛ result.put ("paytradeno" ، ph.getPayTradeno ()) ؛ result.put ("TradePayno" ، ph.getTradePayno ()) ؛ result.put ("paystatus" ، ph.getPayStatus ()) ؛ result.put ("paytype" ، ph.getPayType ()) ؛ } نتيجة الإرجاع ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ JSonObject Result = New JSonObject () ؛ result.put ("الحالة" ، "خطأ") ؛ result.put ("msg" ، e.getMessage ()) ؛ // return result.toString () ؛ } إرجاع فارغ ؛ } الكائن العام seturl (سلسلة noncestr ، string orderdescribe ، string orderno ، سعر السلسلة ، الطابع الزمني للسلسلة ، string timeExpire) {try {keystore keystore = keystore.getInstance ("pkcs12") ؛ FileInputStream Instream = جديد fileInputStream (ملف جديد (المسار المطلق لشهادة WeChat)) ؛ حاول {keystore.load (instream ، "merchant id" .tochararray ()) ؛ } أخيرًا {entersream.close () ؛ } // Trust Own CA وجميع certs sslcontext sslcontext = sslcontexts.custom (). loadkeymaterial (keystore ، <span style = "font-family: arial ، helvetica ، sans-serif ؛"> merchant id </span> .tocharray ()). // السماح بروتوكول TLSV1 فقط SSLConnectionsCONKEFFACTORY SSLSF = جديد SSLConnectionSOCKETFACTORY (SSLCONTEXT ، سلسلة جديدة [] {"TLSV1" ، null ، sslConnectionSocketFactory.allow_all_hostname_verifier) ؛ closablehttpclient httpclient = httpclients.custom () .SetSslsocketFactory (sslsf) .build () ؛ // httpget httpget = new // httpget ("https://api.mch.weixin.qq.com/secapi/pay/refund") ؛ httppost httppost = new httppost ("https://api.mch.weixin.qq.com/pay/unifiedorder") ؛ String xml = clientcustomssl.createenativePackage (noncestr ، orderdescribe ، orderno ، price ، mathestart ، timeExpire) ؛ حاول {stringentity se = new striterity (xml) ؛ httppost.setentity (se) ؛ system.out.println ("request request" + httppost.getRequestLine ()) ؛ closablehttpresponse desponseentry = httpclient.execute (httppost) ؛ جرب {httpentity unitity = responseentry.getentity () ؛ System.out.println ("----------------------------------------------") ؛ System.out.println (reponseentry.getStatusLine ()) ؛ if (ectity! = null) {system.out.println ("طول محتوى الاستجابة:" + entity.getContentLength ()) ؛ /* BufferedReader BufferedReader = جديد BufferEdReader (New InputStreamReader (entity.getContent ())) ؛ نص سلسلة بينما ((text = bufferedReader.ReadLine ()))! = null) {system.out.println ("======================"+text) ؛ }*/ SaxReader SaxReader = New SaxReader () ؛ وثيقة المستند = saxreader.read (entity.getContent ()) ؛ element rootelt = document.getRootElement () ؛ System.out.println ("Root Node:" + rootelt.getName ()) ؛ System.out.println ("==="+rootelt.elementText ("result_code")) ؛ System.out.println ("==="+rootelt.elementText ("return_msg")) ؛ string resultcode = rootelt.elementText ("result_code") ؛ JSonObject Result = New JSonObject () ؛ documentxml = documentHelper.Parsetext (XML) ؛ element rooteltxml = documentxml.getRootElement () ؛ if (resultCode.equals ("Success")) {system.out.println ("================== prepay_id ====================================" System.out.println ("========================================"+ rooteltxml.elementText ("sign")) ؛ result.put ("weixinpayurl" ، rootelt.elementText ("code_url")) ؛ result.put ("prepayid" ، rootelt.elementText ("prepay_id")) ؛ result.put ("الحالة" ، "النجاح") ؛ النتيجة. } آخر {result.put ("الحالة" ، "false") ؛ result.put ("msg" ، rootelt.elementText ("err_code_des")) ؛ } نتيجة الإرجاع ؛ } entityUtils.consume (الكيان) ؛ } أخيرًا {responseentry.close () ؛ }} أخيرًا {httpclient.close () ؛ } إرجاع فارغ ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ JSonObject Result = New JSonObject () ؛ result.put ("الحالة" ، "خطأ") ؛ result.put ("msg" ، e.getMessage ()) ؛ نتيجة العودة }}} حزمة httpclient جرة وحزمة JSON جرة: تنزيل عنوان.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.