Недавно я был связан с некоторыми вещами о выплате WeChat в моей работе. Я видел, что демо, которые я дал, были все версии PHP, и я действительно не был удовлетворен платежными документами WeChat. Получив множество ловушек, я был бездействующим, чтобы сделать резюме.
1. Подготовка
Чтобы разработать WeChat, вы должны сначала подать заявку на общедоступную учетную запись. После того, как заявка будет успешной, вы будете отправлены вам по электронной почте. Общественная учетная запись содержит документы разработки, необходимую информацию во время разработки и запрос данных для тестирования.
2. Инструменты
1. MD5 класс инструментов шифрования
пакет com.pay.utils.weixin; import java.security.messagedigest; public class 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'}; try {byte [] btinput = s.getbytes (); // Получить MessageDigest объект алгоритма Digest MD5. // Обновление Digest mdinst.update (btinput); // Получите Byte Ciphertext Byte [] md = mdinst.digest (); // преобразовать шифровый текст в шестнадцатеричную форму int j = md.length; char str [] = new char [j * 2]; int k = 0; for (int i = 0; i <j; i ++) {byte byte0 = md [i]; str [k ++] = hexdigits [byte0 >>> 4 & 0xf]; str [k ++] = hexdigits [byte0 & 0xf]; } вернуть новую строку (str); } catch (Exception e) {e.printstackTrace (); вернуть ноль; }}}2. Commonutil Tool Class , используемый для замены XML, необходимого для WeChat. Следующая возврата новой строки (xml.tostring (). Getbytes (), "iso8859-1"); Измените UTF-8 в классе инструментов на ISO8859-1, в противном случае китайский текст в заказе WeChat будет выглядеть искаженным, и его можно отобразить правильно после изменения.
пакет com.pay.utils.weixin; импорт java.io.unsupportedencodingexception; import java.net.urlencoder; import java.util.*; import java.util.map.entry; public class commonutil {public static String createnoncest (int) {String Chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789"; String res = ""; for (int i = 0; i <length; i ++) {случайный rd = new random (); res += chars.indexof (rd.nextint (chars.length () - 1)); } return res; } public Static String createNONCESTR () {string chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789"; String res = ""; for (int i = 0; i <16; i ++) {случайный rd = new random (); res += chars.charat (rd.nextint (chars.length () - 1)); } return res; } public Static String formatqueryparamap (hashmap <string, string> параметры) бросает sdkruntimeexception {String buff = ""; try {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 ()). ToString (). CompareTo (o2.getKey ());}); for (int i = 0; i <infoids.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 (Exception e) {бросить новый sdkruntimeexception (e.getmessage ()); } return Buff; } public Static String formatbizqueryparamap (hashmap <string, string> paramap, boolean urlencode) бросает sdkruntimeexception {String buff = ""; try {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 ()). ToString (). CompareTo (o2.getKey ());}); for (int i = 0; i <infoids.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 (Exception e) {бросить новый sdkruntimeexception (e.getmessage ()); } return Buff; } public static boolean isNumeric (string str) {if (str.matches ("// d *")) {return true; } else {return false; }} public Static String ArrayToxml (hashmap <string, string> arr) {string xml = "<xml>"; Iterator <entry <string, string >> iter = arr.EntrySet (). Iterator (); while (iter.hasnext ()) {intpirt <string, string> intry = iter.next (); String key = entry.getKey (); String val = entry.getValue (); if (isnumeric (val)) {xml + = "<" + key + ">" + val + "</" + key + ">"; } else xml + = "<" + key + "> <! [cdata [" + val + "]]> </" + key + ">"; } xml += "</xml>"; try {return new String (xml.toString (). getBytes (), "iso8859-1"); } catch (unsupportedencodingexception e) {// todo автоматически сгенерированный блок e.printstacktrace (); } возвращаться ""; }}3. ClientCustomssl Class , используемый для генерации знаков и создания пакета заказов weChat com.pay.utils.weixin;
Импорт java.util.arraylist; импорт java.util.collections; импорт java.util.comparator; импорт java.util.hashmap; import java.util.list; import java.util.map; импорт org.springframework.util.stringutils;/** * * * */public Class ClientCustomssl {public static String getBizSign (hashmap <String, String> bizobj) Throws sdkruntimeexception {hashmap <String, String> BizParameters = new Hashmap <string, string> (); List <map.enter <string, string >> Infoids = new ArrayList <map.Entry <string, string >> (bizobj.entryset ()); System.out.println (Infoids); Collections.sort (Infoids, новый компаратор <map.entry <String, String >> () {public int compare (map.entry <string, string> o1, map.entry <string, string> o2) {return (o1.getkey ()). ToString (). Compareto (o2.getkey ());}); System.out.out.out.ourn System.out.println (Infoids); for (int i = 0; i <infoids.size (); i ++) {map.entry <string, string> item = infoids.get (i); if (item.getkey ()! = "") {bizparameters.put (item.getkey (). tolowercase (), item.getValue ()); }} //bizparameters.put("key "," 1234567812345678123456781234567812345671 "); String bizstring = commonutil.formatbizqueryparamap (bizparameters, false); bizstring += "& key = 123456781234567812345671"; System.out.println ("***************"); System.out.println (bizstring); // return sha1util.sha1 (bizstring); вернуть md5util.md5 (bizstring); } / ** * weChat create order * @param noncestr * @param orderdescribe * @param orderno * @param price * @param timestart * @param timeexpire * @return * @throws sdkruntimeexcept Sdkruntimeexception {hashmap <string, string> nativeobj = new hashmap <string, string> (); NativeObj.put («Appid», «См. Общественный счет»); // идентификатор публичной учетной записи NativeObj.put ("MCH_ID", "См. Электронная почта"); // Номер продавца nativeobj.put ("nonce_str", noncest); // случайная строка nativeobj.put ("body", orderdescribe); // Описание продукта nativeObj.put («Прикрепить», «Трейено»); // Прикрепленные данные nativeobj.put ("out_trade_no", orderno); // Номер заказа торговца (Global Unique) CnitiveObj.put ("total_fee", цена); // Общая сумма (единица составляет цента, не может быть принята с десятичными точками) NativeObj.put ("spbill_create_ip", "192.168.0.144"); // терминал ip nativeobj.put ("time_start", timestart); // время начала транзакции nativeobj.put ("time_expire", timeexpire); // Время окончания транзакции nativeobj.put ("notify_url", canmentizedpropertiplaceholderconfigurer.getContextProperty ("wxurl")+"/weixin_callback/weixincallback/init.action"); // Адрес уведомления о вызове NativeObj.put ("trade_type", "Native"); // Тип транзакции строка string = getBizSign (NativeObj); NativeObj.put ("sign", sign.touppercase ()); return commonutil.arraytoxml (NativeObj); } /*** weChat Заказ платежный запрос* @param noncestr* @param orderdescribe* @param orderno* @param price* @param timestart* @param timeexpire* @return* @trows sdkruntimeexception* /public static searchnativepackage (String TransactionId, String OutTradeno, String noncestraN {Hashmap <string, string> nativeobj = new hashmap <string, string> (); nativeobj.put ("appid", "см. Публичная учетная запись"); // публичная учетная запись idnativeObj.put ("mch_id", "см. Электронное письмо"); // Номер продавца nativeobj.put ("nonce_str", noncest); // случайная строка if (! Stringutils.isempty (transactionId)) {nativeObj.put ("transaction_id", transactionId); } if (! stringUtils.isempty (outtradeno)) {nativeobj.put ("out_trade_no", outtradeno); // случайная строка} string sign = getBizSign (nativeObj); nativeobj.put ("sign", sign.touppercase ()); return commonutil.arraytoxml (NativeObj); /*** weChat refund* @param outtradeno* @param utuprefundno* @param totalfee* @param totalfee* @param refundfee* @return* @throws sdkruntimeexception*/public static String refundnativepackage (String Outttrodeno, String uptufundno, String totalfee, String, строка, строка, строка, строка, строка, строка, string, string, строка, string, string, noncestre Sdkruntimeexception {hashmap <string, string> nativeobj = new hashmap <string, string> (); nativeobj.put («appid», «см. Публичная учетная запись»); // public udnativeObj.put («mch_id», «см. Электронное письмо»); // Merchant number nativeObj.put («nonce_str», не CnecestR); NativeObj.put ("out_trade_no", outttradeno); // Номер заказа торговцев (глобальный уникальный) Nativeobj.put ("out_refund_no", utrefundno); // Число заказа за возврат торговли (глобальный уникальный) Cnitieobj.put ("total_fee", Totalfee); NativeObj.put ("refund_fee", refundfee); // Сумма возврата (единица в центах, не может занять десятичные очки) CnitiveObj.put ("op_user_id", "mail"); String sign = getBizSign (NativeObj); NativeObj.put ("sign", sign.touppercase ()); return uryutil.arraytoxml (NativeObj);}/*** weChat заплатить* @param noncestr* @param orderdescribe* @param orderno* @param price* @param timestart* @param timeexpire* @return* @throws scruntim CreateJSapiPackage (String noncest, String ordescribe, String orderno, String Price, String TimeStart, String TimeExpire, String OpenID) Throws Sdkruntimeexception {hashmap <String> nativeObj = new Hashmap <String, String> (); ContiveObj.put ("Appid", "See Public kescount"); // publicob -idt.put ("appid", "See Public keclile"); OpenID); // Общественная учетная запись idnativeObj.put ("mCh_id", "см. электронную почту") // Число торговцев NativeObj.put ("nonce_str", noncest); // случайная строка NativeObj.put ("body", orderdescribe); // Описание продукта NativeObj.put ("Прикрепить", "Tradeno"); // Прикрепить данные. orderno); // Номер продавца (глобальный уникальный) nativeobj.put ("total_fee", price); // Общая сумма (единица составляет цент, не может занять десятичные очки) cnietobj.put ("spbill_create_ip", "192.168.0.144"); // терминальный iPnativeObj.put (time_start ', timestart); NativeObj.put ("time_expire", TimeExpire) // Время окончания транзакции nativeobj.put ("notify_url", campactizedpropertiplaceholderconfigurer.getContextProperty ("wxurl")+"/weixin_callback/weixincallback/init.action"); // уведомление адресат. "Jsapi"); // Тип транзакции string sign = getBizSign (NativeObj); NativeObj.put ("sign", sign.touppercase ()); return urdutil.arraytoxml (nativeobj);}/*** Закрытие закрытия на weChat* @param noncestr* @param orderdescribe* @param orderno* @param price* @param timestart* @param timeexpire* @param openid* @return* @throws sdkruntimeexcept Throws sdkruntimeexception {hashmap <string, string> nativeobj = new hashmap <string, string> (); nativeobj.put ("appid", "см. публичную учетную запись"); // public udnativeObj.put ("mch_id", "см. электронное письмо"); // Merchant Number. номер заказа (глобально уникальный) nativeobj.put ("nonce_str", noncestr); // случайная строка строка sint = getBizSign (NativeObj); nativeObj.put ("sign", sign.touppercase ()); return commonutil.arraytoxml (NativeObj);}} 4. Позвоните в интерфейс платежа WeChat
пакет com.pay.controller.weixin; import java.io.file; import java.io.fileinputstream; import java.security.keystore; import java.text.simpledateformat; import java.util.date; import java.util.list; import javax.net.ssl.sslcexttext; javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; импорт net.sf.json.jsonarray; импорт net.sf.json.jsonobject; импорт org.apache.http.httpentity; org.apache.http.client.methods.closablehttpresponse; import org.apache.http.client.methods.httppost; import org.apache.http.conn.ssl.sslconcectionsockectectory; import org.apache.http.conn.ssl.sslcontectionsoctectoro org.apache.http.entity.stringentity; import org.apache.http.impl.client.closablehttpclient; import org.apache.http.impl.client.httpclients; import org.apache.http.util.entityUtils; импорт org.dom4 org.dom4j.documenthelper; import org.dom4j.element; импорт org.dom4j.io.saxreader; import org.springframework.beans.factory.annotation.autowired; import org.springframework.http.httpstatus; importframework.http.httpstatus; importbramework.w.nansebration.AnbIntPARTISTARSERSERBITIOR org.springframework.web.bind.annotation.requestmapping; import org.springframework.web.bind.annotation.requestmethod; импорт org.springframework.web.bindtation.ressonseStatus; импорт org.spramework.web.bindtation.resttatus; импорт org.spramework.web.bindtation.resttatus; com.pay.bo.payhistants.import com.pay.constants.payhistorypaystatus; import com.pay.constants.payhistorypaytype; импорт com.pay.service.weixinpayservice; импорт. com.pay.utils.weixin.customizedpropertiplaceholderconfigurer;@restcontroller@requestmapping ("/pay") public class weixinpaycontroller {@autowired weixinpayservice weixinpayservice; Частный статический длинный стандарт = 1662652800000L; /** * Возвращает URL, который генерирует QR -код * @param запрос * @param response * @return */@requestmapping (value = "/geturl", method = requestmethod.post) @ResponsEStatus (httpStatus.ok) public Object getUrl (httpserserseson JsonObject.fromObject (тело); PAYHIST PH = NULL; // LIST <MAP <String, Object >> TD = weixInpayservice.getTrade (orderno); Дата DT = новая дата (); SimpleDateFormat SDF = new SimpleDateFormat ("yyyyMmddhhmmss"); String 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)); String Price = math.round (float.valueof (jsono.get ("цена"). ToString ())*100)+""; Долгое время expirestrold = dt.gettime (); Long timenew = long.parselong (cumpizedpropertyplaceholderconfigurer.getContextProperty ("weixin.send2finish.overtime"). ToString ()); Давний TimeExpirenew = TimeExpiRestRestold+Timenew; Дата dttimeexpire = новая дата (TimeExpirenew); SimpleDateFormat DTSDF = new SimpleDateFormat ("yyyyMmddhhmmss"); String TimeExpire = dtsdf.format (dttimeexpire) .toString (); System.out.println ("noncests =="+noncest); System.out.println ("orderno =="+jsono.get ("orderno"). ToString ()); System.out.println ("цена =="+цена); System.out.println ("timeStart =="+noncestr); System.out.println ("TimeExpire =="+TimeExpire); JsonObject result = (jsonObject) seturl (noncestr, "order", tradepayno, цена, не Cestr, TimeExpire); if (result.get ("status"). toString (). equals ("success")) {ph = new payhist (); 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 ()); } return Result; } catch (Exception e) {e.printstackTrace (); JsonObject result = new jsonObject (); result.put ("status", "ошибка"); result.put ("msg", e.getmessage ()); // return result.tostring (); } return null; } public Object seturl (String noncest, String orderdescribe, String orderno, String Price, String TimeStart, String TimeExpire) {try {KeyStore KeyStore = KeyStore.getInstance ("PKCS12"); FileInputStream inStream = new FileInputStream (новый файл (абсолютный путь сертификата WeChat)); try {keystore.load (instriam, "Merchant Id" .tochararray ()); } наконец {enterstream.close (); } // Доверие собственного CA и всех саморегистрированных Certs SSLContext sslContext = sslContexts.custom (). // Разрешение TLSV1 Протокол только sslConnectionsocketCactory sslsf = new sslConnectionsockeCtectory (sslContext, new String [] {"tlsv1"}, null, sslConnectionsocteckectectectory.ally_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/unififiedorder"); String xml = clientCustomsSl.creatEnativePackage (noncestryDescribe, OrderNo, Price, TimeStart, TimeExpire); try {stryentity se = new строгость (xml); httppost.setentity (se); System.out.println («выполнение запроса» + httppost.getRequestline ()); ClosableHttpresponse responsentry = httpclient.execute (httppost); try {httpentity entity = responsentry.getentity (); System.out.println ("-----------------------------------------"); System.out.println (responseNtry.getStatusLine ()); if (Entity! = null) {System.out.println ("Длина содержимого ответа:" + entity.getContentLength ()); /* BufferedReader BufferedReader = new BufferedReader (New InputStreamReader (entity.getContent ())); Строка текст; while ((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 (); Document Documentxml = DocumentHelper.parsetext (xml); Element rooteltxml = documentxml.getrootelement (); if (resultcode.equals ("success")) {System.out.println ("================= PREANTE_ID ================== System.out.println ("================= Знак ======================================== result.put ("weixinpayurl", rootelt.elementtext ("code_url")); result.put ("predayid", rootelt.elementtext ("prepay_id")); result.put («статус», «успех»); result.put ("msg", "успех"); } else {result.put ("status", "false"); result.put ("msg", rootelt.elementtext ("err_code_des")); } return Result; } Entityutils.consume (Entity); } наконец {responseNtry.close (); }} наконец {httpclient.close (); } return null; } catch (Exception e) {e.printstackTrace (); JsonObject result = new jsonObject (); result.put ("status", "ошибка"); result.put ("msg", e.getmessage ()); результат возврата; }}} httpclient jar package и JSON JAR Package: Скачать адрес.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.