1. 준비
수많은 사람들이 Model One의 개발에 대해 물었으므로 참조로 여기에 게시했습니다. 모드 1과 모드의 차이를 여러 번 설명했습니다. 모드 1의 QR 코드가 제품에 대한 것이고 모드 2의 QR 코드는 순서를위한 것입니다. 다른 특정 세부 사항에 대해 이야기 할 필요가 없습니다. 공식 문서로 이동하여 문서를 직접보고 모드 1 또는 모드 2를 선택하면 비즈니스에 따라 다릅니다.
1.1. 관련 구성 매개 변수
APP_ID 및 APP_SECRET 이전에는 4 가지가 공개 플랫폼에서 찾을 수 있으며 MCH_ID 및 API_KEY는 가맹점 플랫폼에서 찾을 수 있으며, 특히 API_Key는 판매자 플랫폼에서 설정해야합니다. 이것은 매개 변수 검증의 정확성과 관련이 있으므로 올바르게 설정해야합니다. QR 코드 결제 모델 1은 실제로 QR 코드 지불 모델 2와 유사합니다. 실제로 APP_ID, MCH_ID 및 API_KEY 만 사용하며 다른 것을 사용하지 않습니다. One의 공식 문서 주소는 여기에 있습니다 : https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
1.2. 관련 개념
여기서는 먼저 개념을 수정하고 싶습니다. 두 번째 모델을 개발하는 동안 "지불 콜백 주소"와 같은 개념을 언급했습니다. 기능은 고객이 스캔하고 결제를 완료 한 후에 WeChat 서버가 당사가 제공 한 주소에 액세스하고 지불 결과를 보내어 배송 주문을 확인할 수 있도록해야한다는 것입니다. 이것은 다른 지불 도구의 비교적 일반적인 개념이며 이름입니다. 그러나 나중에 WeChat의 공식 웹 사이트에서 문서를 살펴 보았고 모델의 첫 번째 개발에서 그들은 이것을 "지불 콜백 주소"대신 "비동기 알림 URL"이라고 불렀지 만 본질적으로 동일한 의미를 나타냅니다. 하지만 왜 여기에 이것을 언급합니까? 모드 1에는 실제로 "스캔 코드 결제 콜백 URL"이라는 소위 "지불 콜백"이 있기 때문입니다. 이것은 위의 "비동기 알림 URL"과 다릅니다. 주문 완료를 돕기 위해 서버의 인터페이스라는 것을 간단히 이해할 수 있습니다. 모드 1의 개발에는 "콜백 URL을 지불하기 위해 QR 코드를 스캔"및 "비동기 알림 URL"의 두 인터페이스의 협력이 필요하므로 모든 사람이 여기에 구별해야합니다.
Unified 단일 인터페이스를 호출 할 때 "비동기 알림 URL"이 설정됩니다. 이 인터페이스가 관련 규칙에 따라 매개 변수 응답 매개 변수를 수신하는 한 동적으로 설정할 수 있습니다. "콜백 URL을 지불하기 위해 QR 코드를 스캔"은 비교적 고정되어 있습니다. WeChat Public 플랫폼에 설정되어 있습니다. 설정 후 발효하는 데 약 10 분이 걸립니다. WeChat Public 플랫폼에 로그인 한 후 WeChat Pay를 선택하면 개발 구성 탭에서 찾을 수 있습니다.
여기서 우리는 자체 서버의 주소를 설정해야합니다 (WeChat 서버가 귀하를 찾을 수 있도록 공개 네트워크 주소를 다시 말하십시오).
1.3. 개발 환경
여기에서 가장 기본적인 서블릿 3.0을 샘플 환경으로 사용하고 있습니다. XML 작동 JDOM을 사용하는 것 외에도 Model 2의 개발과 비교하여 타사 JAR 패키지의 참조와 관련하여 Google Zxing QR 코드 패키지 및 Log4J 패키지가 있습니다. 아래 그림과 같이 :
디버깅을 용이하게하기 위해서는 실제 프로젝트에 이식하기 전에이 환경의 조정을 먼저 낮추는 것이 좋습니다.
2. 개발과 실제 전투
시작하기 전에 타이밍 차트를 잘 살펴보기 위해 공식 문서로 이동하는 것이 좋습니다. 타이밍 차트를 이해 한 후 코드를 작성하는 것은 어려운 작업이 아닙니다. 물론 사진을 이해할 수 없다면 다음 코드와 함께 사진을 이해하려고 노력할 수도 있습니다.
2.1. QR 코드 생성
우선 QR 코드가 있습니다. QR 코드의 내용은 링크이며 양식은 다음과 같습니다.
Weixin : // wxpay/bizpayurl? sign = xxxxx & appid = xxxxx & mch_id = xxxxx & product_id = xxxxx & time_stamp = xxxxx & nonce_str = xxxxxxxx & noncexxxxx
자세한 내용은 공식 문서 모드를 참조하여 QR 코드 규칙을 생성 할 수 있습니다. 다음 으로이 링크에 대한 QR 코드를 생성해야합니다. QR 코드를 생성하기 위해 Google Zxing을 사용했습니다.
패키지 com.wqy; import java.io.ioexception; import java.io.outputStream; java.util.hashmap import; import java.util.iterator; java.util.map import; java.util.set import; java.util.sortedMap import; Java.util.treemap import; javax.servlet.servletexception import; javax.servlet.annotation.webservlet import; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.apache.log4j.logger; import com.google.zxing.barcodeformat; import com.google.zxing.encodehinttype; import com.google.zxing.multiformatwriter; import com.google.zxing.writerexception; import com.google.zxing.client.j2se.matrixtoimagewriter; import com.google.zxing.common.bitmatrix; import com.google.zxing.qrcode.decoder.errorcorrectionlevel; import com.wqy.util.paycommonutil; import com.wqy.util.payconfigutil; /** * Servlet 구현 클래스 Pay1 */@webservlet ( "/pay1") public class pay1은 httpservlet {private static final long serialversionuid = 1L; 개인 정적 로거 로거 = logger.getLogger (pay1.class); public static int defaultWidthandHeight = 200; / ** * @httpservlet#httpservlet () */ public pay1 () {super (); // TODO 자동 생성 생성자 Stub}/ ** * @ @httpservlet#doget (httpservletrequest 요청, httpservletrequest * responsk) */ protected void doget (httpservletrequest 요청) = paycommonutil.getNonce_str (); Long Time_stamp = System.CurrentTimeMillis () / 1000; 문자열 product_id = "hd_goodssssss_10"; 문자열 key = payconfigutil.api_key; // key sortedMap <개체, 객체> packageparams = new Treemap <개체, 개체> (); 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); 문자열 표시 = PayCommonUtil.createsign ( "UTF-8", PackageParams, Key); // MD5 HASH PACKETPARAMS.PUT ( "부호", 부호); // 매개 변수 생성 문자열 str = tourlparams (PackageParams); String Payurl = "Weixin : // wxpay/bizpayurl?" + str; logger.info ( "payurl :"+payurl); // QR 코드 맵 생성 <EncodeHintType, Object> hints = new Hashmap <EncodeHintType, Object> (); // QR 코드 맵 생성 <EncodeHintType, Object> (); // 오류 수정 레벨 hints.put (encodehinttype.error_correction, errorcorrectionlevel.l)을 지정합니다. // 인코딩 형식을 지정합니다. hints.put (encodehinttype.margin, 1); {bitmatrix bitmatrix = new multiformatwriter (). encode (payurl, barcodeformat.qr_code, defaultWidThandHeight, defaultWidThandHeight, 힌트); outputStream out = response.getOutputStream (); matrixtoImageWriter.writeToStream (bitmatrix, "png", out); // qr code 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 (); 문자열 k = (문자열) entry.getKey (); 문자열 v = (문자열) entry.getValue (); if (null! = v &&! "". }} sb.deletecharat (sb.length () -1); // last & return sb.toString (); } / ** * @ @httpservlet#dopost (httpservletrequest request, httpservletresponse * response) * / protected void dopost (httpservletrequest request, httpservletResponse 응답) wrows servletexception, ioexception, ioexception {// auto-genderated method (요청, 응답); }} 2.2. 결제 콜백 URL 인터페이스를 스캔하십시오
고객이 위의 2 자리 코드를 WeChat으로 스캔하면 WeChat 서버는이 인터페이스에 액세스합니다. 여기서는 트랜잭션 세션 식별자를 얻으려면 통합 주문을 완료해야합니다. 처리의 주요 프로세스는 다음과 같습니다.
1) WeChat 서버에서 보낸 매개 변수를 수신하고 매개 변수의 서명 검증을 수행합니다.
2) QR 코드를 통해 전송할 수있는 유일한 매개 변수 인 Product_ID 매개 변수를 꺼내십시오. 다른 매개 변수는 공식 문서 모드 1.1에 따라 입력 할 수 있습니다.
3) 지불 금액 계산, 주문 번호 생성 등과 같은 Product_id에 따라 자신의 사업을 처리합니다.
4) Unified Single 인터페이스에 전화하여 트랜잭션 세션 식별자 pleray_id를 얻습니다.
4.1) 관련 매개 변수 (예 : APPID, MCH_ID, 지불 금액, 주문 번호, 제품 설명 등)를 준비하고 WeChat에 전화하여 단일 인터페이스를 통합합니다 (모드 2 호출의 통합 단일 인터페이스와 유사). 나중에 언급 될 비동기 알림 URL 인터페이스 인 위에서 언급 한 "비동기 알림 URL"에주의하십시오. 특정 매개 변수의 경우 단일 요청 매개 변수를 통합하려면 공식 문서를 참조하십시오.
4.2) Unified 단일 인터페이스에 의해 반환 된 매개 변수를 수신하고 매개 변수를 확인하십시오.
4.3) 트랜잭션 세션 식별자 인 매개 변수 propay_id를 꺼내십시오. 이는 매우 중요합니다. 다른 매개 변수는 결과를 반환하기 위해 공식 문서를 참조 할 수 있습니다.
5) 관련 매개 변수 (예 : AppID, MCH_ID, return_Code, Propay_ID 등)를 준비하고 초기 결제 콜백에 응답하십시오 (위의 단계가 잘못된 경우 로그인 확인이 실패하면 오류 매개 변수를 WECHAT 서버로 반환 할 수 있음). 특정 매개 변수는 공식 문서 모드 1.2 출력 매개 변수를 참조하십시오.
패키지 com.wqy; import java.io.bufferedOutputStream; import java.io.bufferedReader; import java.io.ioexception; import java.io.inputStreamReader; import java.io.inputStreamReader; java.util.sortedMap import; Java.util.treemap import; javax.servlet.servletexception import; javax.servlet.annotation.webservlet import; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.apache.log4j.logger; import com.wqy.util.httputil; import com.wqy.util.paycommonutil; import com.wqy.util.payconfigutil; /** * 서블릿 구현 클래스 notify1 */@webservlet ( "/notify1") public class notify1은 httpservlet {private static final long serialversionuid = 1L; 개인 정적 로거 로거 = logger.getLogger (notify1.class); / ** * @httpservlet#httpservlet () */ public notify1 () {super (); // TODO 자동 생성 생성자 Stub}/ ** * @ @httpservlet#doget (httpservletrequest 요청, httpservletreponse * responsk) */ protected void doget (httpservletrequest 요청, httpservletrequest 응답) servletexception, ioexception {// to-gerated a a-gerated a a a-gerated {// httpservletrequest 요청). 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 <개체, 개체> packageparams = paycommonutil.xmlconverttomap (sb.tostring ()); logger.info (PackageParams); // 계정 정보 문자열 키 = PayConfigutil.api_key; // key string resxml = ""; // wechat 서버에 피드백 // 가입자 확인 if (paycommonutil.istenpaysign ( "utf-8", packageparams, key)) {// appid openid mch_id is_subscribe nonce_str product_id // unify unify unpeniid = packagesparams ( "openid"); String product_id = (String) packageparams.get ( "product_id"); // Parse Product_ID, 가격 계산 등 String out_trade_no = String.Valueof (System.CurrentTimeMillis ()); // 주문 번호 문자열 order_price = "1"; // 가격 참고 : 가격 단위는 문자열 body = product_id로 나뉩니다. // 제품 이름은 product_id String으로 설정됩니다. // 추가 데이터 문자열 nonce_str0 = paycommonutil.getNonce_str (); // 시작 컴퓨터 IP 문자열 SPBILL_CREATE_IP = PAYCONFIGUTIL.CREATE_IP; String trade_type = "기본"; SortedMap <객체, 개체> UnifiedParams = new Treemap <개체, 개체> (); 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 ( "Body", Body); // 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 문자열 sign0 = paycommonutil.createsign ( "UTF-8", UnifiedParams, key); unifiedparams.put ( "부호", sign0); // 서명 문자열 requestXml = paycommonutil.getRequestxml (unifiedparams); logger.info (requestxml); // Unified 단일 인터페이스 문자열 rxml = httputil.postData (payConfigUtil.ufdoder_url, requestXml); // Unified 단일 응답 SortedMap <개체, 객체> Reparams = paycommonutil.xmlconverttomap (rxml); logger.info (Reparams); // (paycommonutil.istenPaysign ( "utf-8", reparams, key)) {// 단일 문자열 prepay_id = (string) reparams.get ( "prepay_id")에 의해 반환 된 매개 변수를 통합합니다. // 트랜잭션 세션 식별 2 시간 이내에 유효한 문자열 nonce_str1 = paycommonutil.getNonce_str (); SortedMap <객체, 개체> resparams = new Treemap <개체, 개체> (); resparams.put ( "return_code", "success"); // 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", prepay_id); // resparams.put ( "result_code", "success"); // resparams.put이어야합니다 ( "err_code_des", "ok"); 문자열 sign1 = paycommonutil.createsign ( "utf-8", resparams, key); resparams.put ( "sign", sign1); // 서명 resxml = paycommonutil.getRequestxml (resparams); logger.info (resxml); } else {logger.info ( "서명 확인 오류"); resxml = "<xml>" + "<return_code> <! }} else {logger.info ( "서명 확인 오류"); resxml = "<xml>" + "<return_code> <! } //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ BufferedOutputStream( response.getOutputStream()); out.write (resxml.getBytes ()); out.flush (); out.close (); } / ** * @ @httpservlet#dopost (httpservletrequest request, httpservletresponse * response) * / protected void dopost (httpservletrequest request, httpservletResponse 응답) wrows servletexception, ioexception, ioexception {// auto-genderated 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; import java.io.bufferedOutputStream; import java.io.bufferedReader; import java.io.ioexception; import java.io.inputStreamReader; import java.io.inputStreamReader; java.util.sortedMap import; javax.servlet.servletexception import; javax.servlet.annotation.webservlet import; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.apache.log4j.logger; import com.wqy.util.paycommonutil; import com.wqy.util.payconfigutil; /** * 서블릿 구현 클래스 re_notify */@webservlet ( "/re_notify") public class re_notify 확장 httpservlet {private static final long serialversionuid = 1l; 개인 정적 로거 로거 = logger.getLogger (re_notify.class); / ** * @httpservlet#httpservlet () */ public re_notify () {super (); // TODO 자동 생성 생성자 Stub}/ ** * @ @httpservlet#doget (httpservletrequest 요청, httpservletreponse * responsk) */ protected void doget (httpservletrequest 요청, httpservletrequest 응답) servletexception, ioexception {// to-gerated a a-gerated a a a-gerated {// httpservletrequest 요청). 매개 변수 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 <개체, 개체> packageparams = paycommonutil.xmlconverttomap (sb.tostring ()); logger.info (PackageParams); // 계정 정보 문자열 키 = PayConfigutil.api_key; // 키 스트링 resxml = ""; // WeChat 서버에 대한 피드백 // 서명이 올바른지 여부를 결정하십시오 (PayCommonUtil.istenPaysign ( "UTF-8", PackageParams, key)) {// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- out_trade_no = (문자열) 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); ///////////////////////////////////////////////////////////////// Logger.info) ( "결제 성공"); // weChat에 알립니다. 비동기 확인이 성공적입니다. 그것을 써야합니다. 그렇지 않으면 배경에 항상 알림을받습니다. 8 번 후에는 거래가 실패했다고 생각할 것입니다. resxml = "<xml>" + "<return_code> <! } else {logger.info ( "지불 실패, 오류 메시지 :" + packageparams.get ( "err_code")); resxml = "<xml>" + "<return_code> <! }} else {logger.info ( "서명 확인 오류"); resxml = "<xml>" + "<return_code> <! } // ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------ BufferedOutputStream out = new BufferedOutputStream (response.getOutputStream ()); out.write (resxml.getBytes ()); out.flush (); out.close (); } / ** * @ @httpservlet#dopost (httpservletrequest request, httpservletresponse * response) * / protected void dopost (httpservletrequest request, httpservletResponse 응답) wrows servletexception, ioexception, ioexception {// auto-genderated method (요청, 응답); }} 3. 테스트 결과
3.1. 생성 된 결제 QR 코드 링크
3.2. 결제 콜백 URL 인터페이스에서 수신 한 매개 변수
3.3. 통합 단일 요청 매개 변수를 시작하십시오
3.4. 단일 반환 매개 변수를 통합하십시오
3.5. 결제 콜백 URL 인터페이스의 최종 응답 매개 변수
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.