En esta sección, primero escribiremos una demostración simple para probar el proceso de pago de Yibao. Después de familiarizarnos con este proceso, haremos un desarrollo real. Debido a que es una demostración, no consideré algunos patrones de diseño, sino que solo implementé directamente la función de pago. Para implementar funciones de pago, Yibao requiere la API que nos proporciona. Entonces, la pregunta es que lo más importante al usar una plataforma de pago de terceros es obtener la API de la plataforma. Primero debemos obtener sus API y documentos de desarrollo, y luego podemos hacer un mayor desarrollo.
1. Obtenga la API de Yibao
El primer paso para obtener la API es registrar una cuenta en Yibao. Esta cuenta es la cuenta del comerciante. Después de que el comprador paga, depositará el dinero en la cuenta, y el comerciante lo retirará a la tarjeta bancaria por sí mismo. Yibao cobrará una cierta tarifa de manejo durante el proceso de retiro. Este es el modelo de ganancias de Yibao. Sin embargo, el requisito previo para el registro exitoso es que debe tener un sitio web o una empresa, Bara, Bara, etc. De todos modos, debe estar calificado para postularse. Yibao revisará este punto. Solo cuando lo cumpla, le permitirá registrarse y proporcionarle su interfaz. No todos pueden registrarse. Lo usé tan bien como otros registrados, pero no tenía nada yo mismo ... No pude registrarme ... lo sé, pero en general, cuando me desarrollé en una empresa, no habría este problema. Debe haber una cuenta. Lo más importante es dominar el proceso de desarrollo y las tecnologías relacionadas.
2. Prueba el proceso de pago
Con la API oficial y los documentos técnicos, puede comenzar a desarrollar. Aquí escribimos principalmente una demostración simple para probar el proceso de pago de Yibao. La estructura de la demostración es muy simple, un servlet, un filtro, dos páginas JSP y una clase de herramienta cifrada. Servlet se ocupa del lado del servidor Yibao. Hacemos un procesamiento relacionado con la interfaz Yibao. El filtro se utiliza para lidiar con posibles problemas de confusión chinos. Uno de los dos JSP es la página frontal.
Primero analicemos el proceso de solicitud de pago, como se muestra a continuación:
Ok, analicemos el código relevante en la demostración en detalle:
2.1 Página de prueba de recepción
Primero, echemos un vistazo al código específico del índice de la página de recepción.jsp
<%@ Page Language = "Java" PageEncoding = "UTF-8"%> <! DocType html público "-// w3c // dtd html 4.01 transitional // en"> <html> <foad> <bitle> front office home </bitle> </boad> <body> <hb1> Demo de pago en línea </h1> action="${pageContext.request.contextPath }/servlet/PayServlet" method="post"> The order number for this shopping<input type="text" name="p2_Order" /><br> money<input type="text" name="p3_Amt" value="0.01"/><br> Industrial and Commercial Bank of China<input type="radio" value="ICBC-NET" name = "PD_FRPID"> Construction Bank <input type = "Radio" valor = "ccb-net" name = "pd_frpid"> <br> <input type = "subt" value = "subsit"/> <input type = "Hidden" value = "pay" name = "status"/> </form> </body> </html>De la página JSP anterior, podemos ver que los valores del atributo de nombre en estas etiquetas de entrada son muy extraños, PI_Function (i = 0,1,2, ..., 9), y por supuesto tengo otros valores. Esto requiere referirse al documento oficial de Yibao. Estos nombres representan los atributos correspondientes y se pasarán al Sevlet para su procesamiento. Con respecto a estos valores de atributos, tengo una imagen de la siguiente manera:
Algunos de estos nombres de parámetros se transmiten desde la recepción en proyectos reales, como el número de pedido escrito anteriormente, cuánto cuesta pagar, y estos se tomarán cuando se confirma el pedido. Si se requieren otros parámetros, deben especificarse en el servlet. Si no se requieren los campos, pueden estar vacíos. El vacío aquí no es nulo, sino "", que se mencionará en el servlet más tarde.
Echemos un vistazo a los valores de valor correspondientes en los dos bancos. Yibao proporcionará los valores de valor de todos los bancos que admite. Estos son fijos y no se pueden modificar. Aquí hay dos bancos para probar el efecto.
El último campo oculto se usa para juzgar en el servlet. Ya sea un pago o una declaración después de que el pago sea exitoso, se explicará en el Sevlet a continuación.
2.2 Solicitudes de manejo de servlet
El servlet maneja principalmente solicitudes relacionadas a Yibao. Hay dos partes del contenido. Una parte es enviar texto sin formato y texto de cifrado a Yibao, y la otra parte es juzgar el texto sin formato y el texto de cifrado enviado por Yibao. Echemos un vistazo al código de implementación específico en la demostración:
La clase pública PayServlet extiende httpservlet {public void doget (httpservletRequest solicitud, respuesta httpservletResponse) lanza ServletException, ioexception {string status = requit.getParameter ("status"); if (status.equals ("pay")) {// se paga el campo oculto en index.jsp, por lo que la parte de pago se procesa // la clave de cifrado se usa en el algoritmo de cifrado y proporciona el intermediario de pago. Cada comerciante tiene una cadena única KeyValue = "W0P75WMZ203FR46R5I70V556WHHFA94J14YW5J6VUH4YO3NRL5JSQF3C416777"; // 1: Asignar valores a los parámetros. Estos parámetros (es decir, texto plano) se definen en el documento proporcionado por Yibao. No podemos cambiar la cadena de nombre p0_cmd = formatString ("comprar"); Cadena p1_merid = formatString ("10000940764"); Cadena p2_order = formatString (request.getParameter ("p2_order")); Cadena p3_amt = formatString (request.getParameter ("p3_amt")); Cadena p4_cur = formatString ("cny"); Cadena p5_pid = ""; Cadena p6_pcat = ""; Cadena p7_pdesc = ""; Cadena p8_url = "http://www.tongji.edu.cn"; // Esta es la página a la que salta después de que el pago sea exitoso. Puede configurarlo como la página de inicio del centro comercial. Esta demostración es suficiente para usar la página de inicio de la Universidad de Tongji ... cadena P9_SAF = "0"; Cadena pa_mp = ""; Cadena pd_frpid = formatString (request.getParameter ("pd_frpid")); PD_FRPID = PD_FRPID.TOUPPERCASE (); Cadena pr_needResponse = "0"; Cadena hmac = formatString (""); // HMAC se usa para almacenar texto cifrado/*Todo el texto de formación anterior está envuelto con el método FormatString. El método está a continuación, principalmente convertir NULL a "" *porque NULL no se puede convertir en cifrado *// Resolver problemas de seguridad de datos: CORNET el texto sin formato ---> CIPHERTEXT y luego entregar el texto de la formación y el cifrado a yibao // después de yibao los datos, encriptados, el texto transmitido y lo compara con el texto transmitido, no tiene el texto de la transmisión, no se transmite el texto de la transmisión, no se transmite el texto de la transmisión, y los datos transmitidos, no lo han transmitido como el que se transmite, no lo ha hecho. Tampared con (el comerciante y Yibao usan la misma clave al encriptar) // Agregar datos de texto sin formato a StringBuffer, tenga en cuenta que el orden de la apertura no se puede cambiar, de lo contrario, el texto cifrado generado será diferente. // debe escribir estrictamente de acuerdo con el nombre del documento oficial de Yibao, porque Yibao se agrega de acuerdo con el orden en el documento. InfoBuffer = new StringBuffer (); infoBuffer.append (P0_CMD); infobuffer.append (p1_merid); infoBuffer.append (P2_order); infoBuffer.append (P3_amt); infoBuffer.append (P4_cur); infobuffer.append (p5_pid); infobuffer.append (p6_pcat); infobuffer.append (p7_pdesc); infoBuffer.append (P8_URL); infoBuffer.append (P9_SAF); infobuffer.append (pa_mp); infoBuffer.append (PD_FRPID); infobuffer.append (pr_needResponse); // El cifrado cifrado se almacena en HMAC, y el algoritmo de cifrado Yibao lo proporcionará, porque también tiene que usar el mismo algoritmo HMAC = digestUtil.hmacSign (Infobuffer.ToString (), Keyvalue); // Almacene tanto el texto sin formato como el texto de cifrado en request.setAttribute request.setAttribute ("P0_CMD", P0_CMD); request.setAttribute ("P1_Merid", P1_Merid); request.setAttribute ("P2_order", P2_order); request.setAttribute ("p3_amt", p3_amt); request.setAttribute ("P4_cur", p4_cur); request.setAttribute ("p5_pid", p5_pid); request.setAttribute ("p6_pcat", p6_pcat); request.setAttribute ("P7_PDESC", P7_PDESC); request.setAttribute ("P8_URL", P8_URL); request.setAttribute ("P9_SAF", P9_SAF); request.setAttribute ("pa_mp", pa_mp); request.setAttribute ("PD_FRPID", PD_FRPID); request.setAttribute ("PR_NeedResponse", PR_NeedResponse); request.setAttribute ("HMAC", HMAC); System.out.println ("HMAC->" + HMAC); // omita a reqpay.jsp y envíe esta información a yibao request.getRequestDIsPatcher ("/reqpay.jsp"). Reenviar (solicitud, respuesta); } else if (status.equals ("éxito")) {// Lo que viene de Yibao es el éxito, el procesamiento devuelve la parte de verificación PrintWriter out = Response.getWriter (); Cadena keyValue = "W0P75WMZ203FR46R5I70V556WHHFA94J14YW5J6VUH4YO3NRL5JSQF3C41677"; // Obtener todas las cadenas de texto sin formato r0_cmd = formatString (request.getParameter ("R0_CMD")); Cadena p1_merid = request.getParameter ("p1_merid"); Cadena r1_code = formatString (request.getParameter ("r1_code")); Cadena r2_trxid = formatString (request.getParameter ("r2_trxid")); Cadena r3_amt = formatString (request.getParameter ("r3_amt")); Cadena r4_cur = formatString (request.getParameter ("r4_cur")); Cadena r5_pid = new String (FormatString (request.getParameter ("R5_pid")). GetBytes ("ISO-8859-1"), "UTF-8"); Cadena r6_order = formatString (request.getParameter ("r6_order")); Cadena r7_uid = formatString (request.getParameter ("r7_uid")); Cadena r8_mp = new String (FormatString (request.getParameter ("R8_MP")). GetBytes ("ISO-8859-1"), "UTF-8"); Cadena r9_btype = formatString (request.getParameter ("r9_btype")); // Agregar datos a la cadena de texto sin formato hmac = formatString (request.getParameter ("HMAC")); StringBuffer Infobuffer = new StringBuffer (); infobuffer.append (p1_merid); infoBuffer.append (R0_CMD); infoBuffer.append (r1_code); infoBuffer.append (R2_TRXID); infoBuffer.append (R3_amt); infoBuffer.append (R4_cur); infoBuffer.append (R5_PID); infoBuffer.append (R6_order); infoBuffer.append (R7_UID); infoBuffer.append (R8_MP); infoBuffer.append (R9_BType); // Cifrar la cadena de texto sin formato devuelto md5 = digestUtil.hmacSign (infoBuffer.ToString (), keyValue); // Determinar si el texto cifrado es igual al ISOK booleano de la firma de datos transmitido = MD5.Equals (HMAC); if (isok && r1_code.equals ("1")) {// r1_code es 1 para indicar el éxito // cambiar el estado de pedido exitoso a pagado y mostrar la información de éxito de pago al usuario // llamar a la interfaz de servicio de correo electrónico, el servicio de envío de SMS, etc.//print aquí ~ out.println ("El número de pedido es:" + R6_order + "La cantidad de pago es:" + R3_amt); } else {out.println ("fallas !!!"); }}} public void dopost (httpservletRequest solicitud, respuesta httpservletResponse) arroja servletException, ioexception {doget (solicitud, respuesta); } Cadena formatString (texto de cadena) {if (text == null) {return ""; } Texto de retorno; }}2.3 Algoritmo de cifrado
Yibao proporciona el algoritmo de cifrado utilizado para convertir el texto plano en texto cifrado. Solo necesitamos usarlo para convertir el texto plano en texto cifrado. El algoritmo es el siguiente:
public class DigestUtil {String static privado EncodingCharset = "UTF-8"; public static String HMACSign (String Avalue, String AKey) {byte k_ipad [] = new Byte [64]; byte k_opad [] = nuevo byte [64]; byte keyb []; valor de byte []; intente {keyB = akey.getBytes (EncodingCharset); valor = avalue.getBytes (EncodingCharset); } catch (UnsupportedEncodingException e) {keyB = akey.getBytes (); valor = avalue.getBytes (); } Arrays.fill (k_ipad, keyb.length, 64, (byte) 54); Arrays.fill (k_opad, keyb.length, 64, (byte) 92); for (int i = 0; i <keyb.length; i ++) {k_ipad [i] = (byte) (keyb [i] ^ 0x36); k_opad [i] = (byte) (keyb [i] ^ 0x5c); } MessageDigest md = null; intente {md = messageDigest.getInstance ("md5"); } catch (nosuchalgorithMexception e) {return null; } md.update (k_ipad); md.update (valor); byte dg [] = md.digest (); md.reset (); md.update (k_opad); md.update (DG, 0, 16); dg = md.digest (); return toHex (dg); } public static string toHex (byte input []) {if (input == null) return null; StringBuffer output = new StringBuffer (input.length * 2); for (int i = 0; i <input.length; i ++) {int current = input [i] & 0xff; if (corriente <16) output.append ("0"); output.append (Integer.ToString (actual, 16)); } return output.ToString (); } public static string gethmac (string [] args, clave de cadena) {if (args == null || args.length == 0) {return (null); } StringBuffer str = new StringBuffer (); para (int i = 0; i <args.length; i ++) {str.append (args [i]); } return (HMACSign (str.ToString (), key)); } / ** * @param avalue * @return * / public static string digest (string avalue) {avalue = avalue.trim (); valor de byte []; intente {value = avalue.getBytes (EncodingCharset); } catch (UnsupportedEncodingException e) {value = avalue.getBytes (); } MessageDigest md = null; intente {md = messageDigest.getInstance ("sha"); } Catch (nosuchalgorithMexception e) {E.PrintStackTrace (); regresar nulo; } return toHex (md.digest (valor)); } // public static void main (string [] args) {// parámetro 1: texto de formación (datos a estar encriptados) parámetro 2: clave system.out.println (digestuTil.hmacSign ("11111", "ABC")); System.out.println (DigestUtil.hmacSign ("11111", "abd")); // Resolver problemas de seguridad de datos: cifre el texto sin formato ---> Texto secreto y el texto sin formato a Yibao // Después de que Yibao obtenga los datos, cifre el texto sin formato transmitido y compare con el texto de cifrado transmitido. Si los datos iguales no se han manipulado (el comerciante y Yibao usan la misma clave al encriptar)}}No he estudiado demasiado el algoritmo de cifrado. Parece ser el algoritmo de cifrado MD5 de segunda generación. De todos modos, simplemente arroje el texto sin formato y definitivamente se encriptará en un texto cifrado. Echemos un vistazo a la página reqpay.jsp:
<%@page lenguaje = "java" contentType = "text/html; charset = gbk"%> <html> <fead> <title> a la página de yeepay </title> </head> <body> <form name = "yeepay" Action = 'https: //wwww.yeepay.com/app-merchant-Proxy/Node' Methode type='hidden' name='p0_Cmd' value='${requestScope.p0_Cmd}'> <input type='hidden' name='p1_MerId' value='${requestScope.p1_MerId}'> <input type='hidden' name='p2_Order' value='${requestScope.p2_Order}'> <input type = 'Hidden' name = 'p3_amt' value = '$ {requestscope.p3_amt}'> <input type = 'Hidden' name = 'P4_cur' valor = '$ {requestscope.p4_cur}'> <input type = 'hidden' name = 'p5_pid' value = '$ {requestscope.p5_pid}'> '>' '' hidden = '' 'HoVe name='p6_Pcat' value='${requestScope.p6_Pcat}'> <input type='hidden' name='p7_Pdesc' value='${requestScope.p7_Pdesc}'> <input type='hidden' name='p8_Url' value='${requestScope.p8_Url}'> <input type='hidden' name='p9_SAF' value='${requestScope.p9_SAF}'> <input type='hidden' name='pa_MP' value='${requestScope.pa_MP}'> <input type='hidden' name='pa_MP' value='${requestScope.pa_MP}'> <input type='hidden' name='pa_MP' valor = '$ {requestscope.pa_mp}'> <input type = 'Hidden' name = 'pd_frpid' value = '$ {requestscope.pd_frpid}'> <input type = "Hidden" name = "pr_needResponse" value = "$ {requitscope.pr_NeedResponse}"> <input type = 'hidden' name = 'hMACC' value = '$ {requestscope.hmac}'> <input type = 'enviar'/> </form> </body> </html> De hecho, esta página es muy simple. Es pasar el texto sin formato y el texto de cifrado a Yibao a través de la forma <form> . La URL receptora de Yibao es https://www.yeepay.com/app-merchant-proxy/node . Esto también es proporcionado por el funcionario de Yibao, y podemos escribir este. De hecho, solo hay un botón submit . Haga clic en el botón submit para enviar el texto sin formato y el texto de cifrado. Echemos un vistazo a los resultados de la prueba:
3. Resultados de pago de prueba
Índice de recepción de prueba simple.jsp ~~~:
Después de enviar, irá a Reqpay y JSP. El efecto después de hacer clic en el botón Enviar es el siguiente. Probaremos tanto ICBC como CCB:
No hay problema con el proceso de pago. Originalmente planeé pagar 1 centavo a ICBC para ver los resultados después de que se completó el pago, pero descubrí que el escudo U ha expirado porque es más conveniente usar Alipay ahora ... No actualicé el escudo U, pero abrí el pago electrónico a través de ICBC, por lo que también puedo usar el pago electrónico en la interfaz anterior, por lo que pagué 1 centavo generosamente ~ el resultado es un seguimiento:: el resultado sigue:::: el resultado sigue:::: el resultado sigue::: el resultado::: el resultado::::
Luego saltará a la página que especificamos antes, es decir, la Universidad de Tongji ... está bien, la prueba se completa y todo el proceso de pago ha terminado!
Esta sección prueba principalmente a través de una demostración simple para ver si se puede conectar a la interfaz de pago del banco. Ahora la prueba está bien, se ha conectado y puede pagar como siempre más adelante. Presentemos la demostración simple. Luego continuaremos desarrollando el módulo de pago en línea de nuestro proyecto de centro comercial en línea anterior.
Dirección original: http://blog.csdn.net/eson_15/article/details/51447492
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.