1. Подготовка
Бесчисленные люди спрашивали о разработке модели первой, поэтому я разместил его здесь только для справки. Я объяснил разницу между первым режимом и два раза. Это не что иное, как QR -код Mode One для продукта, а QR -код второго режима предназначен для порядка. Мне не нужно говорить о других конкретных деталях. Вы можете перейти к официальному документу, чтобы самостоятельно просмотреть документ, а затем выбрать режим один или второй режим, и это зависит от вашего бизнеса.
1.1. Связанные параметры конфигурации
На публичной платформе можно найти четыре веща, в то время как APP_ID и APP_SECRET можно найти, в то время как MCH_ID и API_KEY находятся на торговой платформе, особенно API_KEY должны быть установлены на торговой платформе. Эта вещь связана с правильностью проверки параметров, поэтому она должна быть установлена правильно. Модель 1 платежа QR -кода на самом деле аналогична модели платежного платежа QR -кода 2. Официальный адрес документа в режиме первого здесь: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
1.2. Связанные концепции
Здесь я сначала хочу исправить концепцию. Во время разработки второй модели я упомянул такую концепцию, как «адрес обратного вызова платежа». Его функция заключается в том, что после сканирования клиента и завершения платежа серверу WeChat необходимо получить доступ к адресу, предоставленному нами, и отправить нам результаты оплаты, чтобы мы могли проверить заказ на доставку. Это относительно распространенная концепция и имя для других платежных инструментов. Однако позже я просмотрел документы на официальном веб -сайте WeChat и обнаружил, что в первой разработке модели они назвали этот «URL -адрес асинхронного уведомления» вместо «адрес образа платежа», но, по сути, это относится к тому же значению. Но почему я упоминаю об этой вещи здесь? Это связано с тем, что в первом режиме на самом деле есть еще один так называемый «обратный вызов платежа», который называется «URL-обратный вызов платежного вызовов». Эта вещь отличается от «URL -адреса асинхронного уведомления» выше. Можно просто понять, что на нашем сервере это интерфейс, который поможет в выполнении заказов. Разработка режима первым требует сотрудничества двух интерфейсов «сканировать QR -код, чтобы выплатить URL -адрес обратного вызова» и «URL -адрес асинхронного уведомления», поэтому каждый должен различить его здесь.
«URL -адрес Async уведомлений» устанавливается при вызове единого единого интерфейса. Это может быть установлено динамически, пока этот интерфейс получает параметры отклика параметров в соответствии с соответствующими правилами. «Сканирование QR -кода для оплаты URL -адреса обратного вызова» является относительно фиксированным. Он установлен на публичной платформе WeChat. Для вступления в силу требуется около 10 минут. После входа на общедоступную платформу WeChat выберите WeChat Pay, и вы можете найти ее на вкладке «Конфигурация разработки»:
Здесь нам нужно настроить адрес нашего собственного сервера (и снова сказать общедоступный сетевой адрес, чтобы сервер WeChat мог найти вас).
1.3. Среда развития
Я использую самый базовый сервис 3.0 в качестве образца среды здесь. Что касается ссылки сторонних пакетов JAR, по сравнению с разработкой Model 2, в дополнение к использованию операции XML JDOM, существует пакет QR-кода Google ZXING и пакет Log4J. Как показано на рисунке ниже:
Чтобы облегчить отладку, рекомендуется сначала снизить корректировку в этой среде, прежде чем пересадить ее в реальное проект.
2. Развитие и практическая боевая бой
Прежде чем начать, я предлагаю вам пойти в официальный документ, чтобы хорошо взглянуть на таблицу времени. После понимания диаграммы времени написание кода не является сложной задачей. Конечно, если вы не можете понять картинку, вы также можете попытаться понять ее в сочетании с моим следующим кодом.
2.1. QR Code Generation
Прежде всего, есть QR -код. Контент в QR -коде - это ссылка, а форма:
weixin: // wxpay/bizpayurl? sign = xxxxx & appid = xxxxx & mch_id = xxxxx & product_id = xxxxx & time_stamp = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Для получения подробной информации вы можете обратиться к официальному режиму документа для генерации правил QR -кода. Затем нам нужно сгенерировать QR -код для этой ссылки. Я использовал здесь Google ZXING, чтобы генерировать QR -код.
пакет com.wqy; импортировать java.io.ioexception; импортировать java.io.outputstream; импортировать java.util.hashmap; импортировать java.util.iterator; импортировать java.util.map; импортировать java.util.set; Импорт java.util.sortedMap; импортировать java.util.treemap; Импорт javax.servlet.servletexception; Импорт javax.servlet.annotation.webservlet; Импорт javax.servlet.http.httpservlet; Импорт javax.servlet.http.httpservletrequest; Импорт javax.servlet.http.httpservletresponse; Импорт org.apache.log4j.logger; Импорт com.google.zxing.barcodeformat; импорт com.google.zxing.encodehinttype; Импорт com.google.zxing.multiformatTwriter; Импорт com.google.zxing.writerexception; Import com.google.zxing.client.j2se.matrixtoImageWriter; Импорт com.google.zxing.common.bitmatrix; import com.google.zxing.qrcode.decoder.errorcorrectionlevel; импорт com.wqy.util.paycommonutil; Импорт com.wqy.util.payconfigutil; /** * Класс реализации сервиса Pay1 */@Webservlet ("/pay1") открытый класс Pay1 Extens httpservlet {private static final long serialversionuid = 1l; Private Static Logger logger = logger.getLogger (pay1.class); Public Static Int DefaultWidthandHeight = 200; / ** * @see httpservlet#httpservlet () */ public pay1 () {super (); // TODO Автогенерированный конструктор stub}/ ** * @see httpservlet#doget (httpservlectrequest, httpservletresponse * response) */ protected void doget (httpservletrequest, httpservletrespons nonce_str = paycommonutil.getnonce_str (); DOLD TIME_STAMP = SYSTEM.CurrentTimeMillis () / 1000; String product_id = "hd_goodsssss_10"; String key = payconfigutil.api_key; // ключ сортировки <Object, Object> PackageParams = new TreeMap <Object, Object> (); packageparams.put ("appid", payconfigutil.app_id); packageparams.put ("mch_id", payconfigutil.mch_id); packageparams.put ("time_stamp", string.valueof (time_stamp)); packageparams.put ("nonce_str", nonce_str); packageparams.put ("product_id", product_id); String sign = paycommonutil.createSign ("utf-8", packageparams, key); // md5 hash packageparams.put ("sign", sign); // генерировать параметры string str = tourlparams (packageparams); String payurl = "weixin: // wxpay/bizpayurl?" + str; logger.info ("payurl:"+payurl); // генерировать карту QR -кода <encodehinttype, object> ntsts = new Hashmap <encodehinttype, object> (); // генерировать карту QR -кода <encodeHintType, Object> (); // Укажите уровень коррекции ошибок nts.put (encodehinttype.error_correction, error -rocrrectionlevel.l); // указать формат кодирования nts.put (encodehinttype.character_set, "utf-8"); nts.put (encodehinttype.margin, 1); try {bitmatrix bitmatrix = new multiformatwriter (). Encode (payurl, barcodeformat.qr_code, defaultwidthandheight, defaultwidthandheight, подсказка); OutputStream out = response.getOutputStream (); MatrixtoImageWriter.WritetoStream (Bitmatrix, "Png", OUT); // Выход qr out.flush (); out.close (); } catch (writerexception e) {// todo автоматически сгенерированный блок e.printstacktrace (); }} public String TourlParams (sortedMap <Object, Object> packageParams) {// Фактически, вы не можете отсортировать StringBuffer sb = new StringBuffer (); Set es = packageParams.EntrySet (); Итератор IT = es.iterator (); while (it.hasnext ()) {map.entry entry = (map.entry) it.next (); String k = (string) entry.getKey (); String v = (string) entry.getValue (); if (null! = v &&! "". Equals (v)) {sb.append (k + "=" + v + "&"); }} sb.deletecharat (sb.length ()-1); // удалить последний и return sb.tostring (); } / ** * @see httpservlet#dopost (httpservlectrequest, httpservletresponse * response) * / Защищенный void dopost (httpservletrequest, httpservletresponse response) throhs servletexception, ioexception {// todo aut-genegered-response stube (respectexception, ioexception {// todo aut-generated method staff (respectexception, ratesexception {// todo aute-generated method); }} 2.2. Сканировать интерфейс URL обратного вызова платежного вызова
Когда клиент сканирует вышеупомянутый двухзначный код с WeChat, сервер WeChat получит доступ к этому интерфейсу. Здесь нам нужно выполнить единый заказ, чтобы получить идентификатор сеанса транзакции. Основной процесс обработки заключается в следующем:
1) получать параметры, отправленные сервером WeChat, и выполните проверку подписи параметров;
2) Выберите параметр Product_id, который является единственным параметром, который можно передавать через QR -код. Другие параметры могут быть введены в соответствии с официальным режимом документа 1.1;
3) Обработайте свой собственный бизнес в соответствии с Product_ID, таким как расчет суммы платежа, генерирование номеров заказа и т. Д.;
4) Вызовите унифицированный отдельный интерфейс, чтобы получить идентификатор сеанса транзакции PRIPAY_ID;
4.1) Подготовьте соответствующие параметры (например, Appid, MCH_ID, сумма оплаты, номер заказа, описание продукта и т. Д.), Вызовите WeChat, чтобы объединить отдельный интерфейс (аналогично единому отдельному интерфейсу вызова режима 2). Обратите внимание на вышеупомянутый «URL-адрес асинхронного уведомления», который является асинхронным интерфейсом URL-адреса уведомления, который будет упомянут позже. Для конкретных параметров обратитесь к официальному документу, чтобы объединить параметры единого запроса;
4.2) получить параметры, возвращаемые единым отдельным интерфейсом, и проверить параметры;
4.3) Выберите параметр PREPAY_ID, который является идентификатором сеанса транзакции, который чрезвычайно важен. Другие параметры могут быть направлены в официальный документ, чтобы вернуть результат;
5) Подготовьте соответствующие параметры (например, Appid, MCH_ID, return_code, pread_id и т. Д.), И ответьте на первоначальный обратный вызов платежа (если вышеуказанные шаги неверны, если проверка входа не удается, вы можете вернуть параметры ошибки на сервер WeChat). Для конкретных параметров, пожалуйста, обратитесь к официальному режиму документов 1.2 Выходные параметры.
пакет com.wqy; Импорт java.io.bufferedOutputStream; Импорт java.io.bufferedReader; импортировать java.io.ioexception; Импорт java.io.inputStreamReader; Импорт java.io.inputStreamReader; Импорт java.util.sortedMap; импортировать java.util.treemap; Импорт javax.servlet.servletexception; Импорт javax.servlet.annotation.webservlet; Импорт javax.servlet.http.httpservlet; Импорт javax.servlet.http.httpservletrequest; Импорт javax.servlet.http.httpservletresponse; Импорт org.apache.log4j.logger; Импорт com.wqy.util.httputil; импорт com.wqy.util.paycommonutil; Импорт com.wqy.util.payconfigutil; /** * Класс реализации сервиса notify1 */@webservlet ("/notify1") public class notify1 расширяет httpservlet {private static final long long serialversionuid = 1l; Private Static Logger logger = logger.getLogger (notify1.class); / ** * @see httpservlet#httpservlet () */ public notify1 () {super (); // TODO Автогенерированный конструктор stub}/ ** * @see httpservlet#doget (httpservlectrequest, httpservletresponse * response) */ Защищенная void doget (httpservletrequest, httpservletrespons xml inputstream inputstream; StringBuffer sb = new StringBuffer (); inputStream = request.getInputStream (); Строка S; BufferedReader in = new BufferedReader (New InputStreamReader (inputStream, "UTF-8")); while ((s = in.readline ())! = null) {sb.append (s); } in.close (); inputstream.close (); SortedMap <Object, Object> PackageParams = paycommonutil.xmlConverttomap (sb.toString ()); logger.info (packageparams); // Информация об учетной записи string key = payconfigutil.api_key; // Ключевая строка resxml = ""; // обратная связь с WeChat Server // Verification IF (PAYCOMMONUTIL.IstenPaysign ("UTF-8", PACKERPARAMS, KEY)) {// Appid OpenID MCH_ID IS_SUBSCRIBE NONCE_STR PRODUCT_ID SIGN // UNITING ONGING STRING OPNECTID = (String) PACKERAM.GEL (oNCE_STID "); String product_id = (string) packageparams.get ("product_id"); // prese product_id, рассчитывать цену и т. Д. String out_trade_no = string.valueof (system.currenttimemillis ()); // Номер заказа строка order_price = "1"; // цена ПРИМЕЧАНИЕ: Единица цены делится на строковую корпус = product_id; // Имя продукта установлено в string_id atture = "XXX Store"; // дополнительная строка данных nonce_str0 = paycommonutil.getnonce_str (); // Получить инициативу компьютера IP String SPBILL_CREATE_IP = PAYCONFIGUTIL.CREATE_IP; String Trade_type = "Native"; SortedMap <Object, Object> UnifiedParams = new TreeMap <Object, Object> (); UnifiedParams.put ("appid", payconfigutil.app_id); // UnifiedParams.put ("MCH_ID", PAYCONFIGUTIL.MCH_ID); // UnifiedParams.put ("out_trade_no", out_trade_no); // UnifiedParams.put ("product_id", product_id); UnifiedParams.put («тело», тело); // UnifiedParams.put («Прикрепить», прикрепить); UnifiedParams.put ("total_fee", order_price); // должен быть UnifiedParams.put ("nonce_str", nonce_str0); // должен быть UnifiedParams.put ("spbill_create_ip", spbill_create_ip); // должен быть UnifiedParams.put ("trade_type", trade_type); // должен быть UnifiedParams.put ("openID", openID); UnifiedParams.put ("notify_url", payconfigutil.notify_url); // асинхронное уведомление url string sign0 = paycommonutil.createSign ("utf-8", UnifiedParams, Key); UnifiedParams.put ("sign", sign0); // Signature String requestxml = paycommonutil.getRequestxml (UnifiedParams); logger.info (requestxml); // Unified Interface String rxml = httputil.postdata (payconfigutil.ufdoder_url, requestxml); // Unified Single Recsion SortedMap <Object, Object> Reparams = paycommonutil.xmlConverttomap (rxml); logger.info (reparams); // Проверьте if (paycommonutil.istenpaysign ("utf-8", reparams, key)) {// объединить параметры, возвращаемые одной строкой preapay_id = (string) reparams.get ("prepay_id"); // идентификация сеанса транзакции действительна в течение 2 часов строки nonce_str1 = paycommonutil.getnonce_str (); SortedMap <объект, объект> resparams = new TreeMap <Object, Object> (); resparams.put ("return_code", "успех"); // resparams.put ("return_msg", "ok"); resparams.put ("appid", payconfigutil.app_id); // resparams.put ("mch_id", payconfigutil.mch_id); resparams.put ("nonce_str", nonce_str1); // resparams.put ("prepay_id", pread_id); // resparams.put ("result_code", "успех"); // должен быть resparams.put ("err_code_des", "ok"); String sign1 = paycommonutil.createSign ("utf-8", resparams, key); resparams.put ("sign", sign1); // signature resxml = paycommonutil.getrequestxml (resparams); logger.info (resxml); } else {logger.info ("ошибка проверки подписи"); resxml = "<xml>" + "<return_code> <! [cdata [fail]]> </return_code>" + "<return_msg> <! [cdata [ошибка проверки подписи]]]> </return_msg>" + "</xml>"; }} else {logger.info ("ошибка проверки подписи"); resxml = "<xml>" + "<return_code> <! [cdata [fail]]> </return_code>" + "<return_msg> <! [cdata [ошибка проверки подписи]]]> </return_msg>" + "</xml>"; } // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- out.write (resxml.getbytes ()); out.flush (); out.close (); } / ** * @see httpservlet#dopost (httpservlectrequest, httpservletresponse * response) * / Защищенный void dopost (httpservletrequest, httpservletresponse response) throhs servletexception, ioexception {// todo aut-genegered-response stube (respectexception, ioexception {// todo aut-generated method staff (respectexception, ratesexception {// todo aute-generated method); }}На этом этапе заказ пользователя WeChat покажет сумму, которая будет выплачена, и описание продукта, а затем ждать, пока клиент завершит платеж.
2.3. Асинхронное уведомление о интерфейсе URL
Когда пользователь завершает операцию оплаты на WeChat, сервер WeChat асинхронно уведомит интерфейс и отправит нам окончательный результат оплаты, чтобы мы могли проверить заказ на доставку и другие операции. Обратите внимание, что этот интерфейс точно такой же, как разработка модели 2. Общий процесс выглядит следующим образом:
1) получать параметры, отправленные сервером WeChat, и выполните проверку подписи параметров;
2) Установите параметры result_code, номер заказа out_trade_no, сумма заказа Total_fee и другие связанные с бизнесом параметры. Конкретные параметры могут быть направлены на параметры уведомления об общем уведомлении о результатах оплаты в официальном документе;
3) обработка бизнеса, например, проверка номера заказа и суммы заказа, изменение статуса заказа и т. Д.;
4) Подготовьте соответствующие параметры (return_code и return_msg) и ответьте на сервер WeChat.
Обратите внимание, что если WeChat получает ответы продавца, которые не являются успешными или временами, и WeChat считает, что уведомление не удалось, WeChat регулярно переоценит уведомления через определенные стратегии для увеличения уровня успеха уведомлений максимально, но WeChat не гарантирует, что уведомление будет успешным в конце концов. (Частота уведомлений 15/15/30/1800/1800/1800/1800/1800/1800/3600, Блок: Секунды)
пакет com.wqy; Импорт java.io.bufferedOutputStream; Импорт java.io.bufferedReader; импортировать java.io.ioexception; Импорт java.io.inputStreamReader; Импорт java.io.inputStreamReader; Импорт java.util.sortedMap; Импорт javax.servlet.servletexception; Импорт javax.servlet.annotation.webservlet; Импорт javax.servlet.http.httpservlet; Импорт javax.servlet.http.httpservletrequest; Импорт javax.servlet.http.httpservletresponse; Импорт org.apache.log4j.logger; импорт com.wqy.util.paycommonutil; Импорт com.wqy.util.payconfigutil; /** * Класс реализации сервиса re_notify */@webservlet ("/re_notify") открытый класс re_notify extends httpservlet {private static final long serialversionuid = 1l; Private Static Logger logger = logger.getLogger (re_notify.class); / ** * @see httpservlet#httpservlet () */ public re_notify () {super (); // TODO Автогенерированный конструктор stub}/ ** * @see httpservlet#doget (httpservlectrequest, httpservletresponse * response) */ Защищенная void doget (httpservletrequest, httpservletrespons параметры inputstream inputstream; StringBuffer sb = new StringBuffer (); inputStream = request.getInputStream (); Строка S; BufferedReader in = new BufferedReader (New InputStreamReader (inputStream, "UTF-8")); while ((s = in.readline ())! = null) {sb.append (s); } in.close (); inputstream.close (); SortedMap <Object, Object> PackageParams = paycommonutil.xmlConverttomap (sb.toString ()); logger.info (packageparams); // Информация об учетной записи string key = payconfigutil.api_key; // string string resxml = ""; // обратная связь с WeChat Server // Определите, является ли подпись правильной if (paycommonutil.istenpaysign ("utf-8", packageparams, key)) {// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------. out_trade_no = (string) packageparams.get ("out_trade_no"); String total_fee = (string) packageparams.get ("total_fee"); logger.info ("mch_id:" + mch_id); logger.info ("openid:" + openid); logger.info ("is_subscribe:" + is_subscribe); logger.info ("out_trade_no:" + out_trade_no); logger.info ("total_fee:" + total_fee); /////////////////////////////////// Execute your own business logic ////////////////// logger.info("Payment successful"); // уведомление WeChat. Асинхронное подтверждение успешно. Должен написать это. В противном случае фон будет уведомлен все время. Через восемь раз вы подумаете, что транзакция потерпела неудачу. resxml = "<xml>" + "<return_code> <! [cdata [успех]]> </return_code>" + "<return_msg> <! [cdata [ok]]> </return_msg>" + "</xml>"; } else {logger.info ("Ошибка оплаты, сообщение об ошибке:" + packageparams.get ("err_code")); resxml = "<xml>" + "<return_code> <! [cdata [fail]]> </return_code>" + "<return_msg> <! [cdata [сообщение пусто]]> </return_msg>" + "</xml>"; }} else {logger.info ("ошибка проверки подписи"); resxml = "<xml>" + "<return_code> <! [cdata [fail]]> </return_code>" + "<return_msg> <! [cdata [ошибка проверки подписи]]]> </return_msg>" + "</xml>"; } // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- BufferedOutputStream (response.getOutputStream ()); out.write (resxml.getbytes ()); out.flush (); out.close (); } / ** * @see httpservlet#dopost (httpservlectrequest, httpservletresponse * response) * / Защищенный void dopost (httpservletrequest, httpservletresponse response) throhs servletexception, ioexception {// todo aut-genegered-response stube (respectexception, ioexception {// todo aut-generated method staff (respectexception, ratesexception {// todo aute-generated method); }} 3. Результаты теста
3.1. Ссылка сгенерированной платежной QR -кода
3.2. Параметры, полученные с помощью URL -адреса платежного обратного вызова
3.3. Инициировать единые параметры единого запроса
3.4. Объединить отдельные параметры возврата
3.5. Окончательные параметры ответа интерфейса URL -адреса вызовов платежа
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.