如何用Angular实现表单交互,对接Java SOAP支付API并展示结果
Java+Angular支付验证对接指导
已实现Java版支付验证SOAP XML API,代码可携带SOAPAction请求头及XML请求体调用支付API并获取响应。现需通过Angular构建前端表单,收集用户输入的CardNum、CardType、CardCVC等参数传给Java;Java调用支付API后,将Transaction ID、Order Status、Order Reason、Transaction Status Payment等结果返回至前端展示。本人是Java和Angular新手,求相关指导。
附现有Java代码:
import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.net.HttpURLConnection; import java.net.URL; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; public class Send_XML_Post_Request_1 { public static void main(String[] args) { try { String url = "https://onepay-services.uat.aws.emagin.eu/api/soap/payment"; URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty("Content-Type","text/xml"); con.setRequestProperty("SOAPAction","http://www.allianz-assistance.com/emagin/services/PaymentService/1.0/authorize"); String CardType="VISA"; String CardNum = "4444333322221111"; String CardCVC = "425"; String xml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"" + " xmlns:ns=\"http://www.allianz-assistance.com/emagin/services/PaymentService/1.0\">" + "<soapenv:Header/>" + " <soapenv:Body>" + " <tns:authorize=\"1.0\" xmlns:tns=\"http://www.allianz-assistance.com/emagin/services/PaymentService/1.0\" xmlns:emagin=\"http://www.mondial-assistance.com/ecommerce/schema/\">" + " <tns:globalRequestId>paymentOrder</tns:globalRequestId>" + " <tns:authentication>" + " <tns:userId>AWC_LIFEEUR</tns:userId>" + " <tns:password>awclifeeur$2018</tns:password>" + " </tns:authentication>" + " <tns:accountId>ACCOUNT_AWC_LIFEEUR</tns:accountId>" + " <tns:customerInformation>" + " <tns:partnerCode>ALS</tns:partnerCode>" + " <tns:buCode>CH</tns:buCode>" + " </tns:customerInformation>" + " <tns:paymentInformation>" + " <tns:paymentHolder>" + " <tns:name>Charlie</tns:name>" + " <tns:email>charlie@allianz.com</tns:email>" + " <tns:address>" + " <tns:address>11/22 Street1 Road1</tns:address>" + " <tns:city>Penang</tns:city>" + " <tns:country>ID</tns:country>" + " </tns:address>" + " </tns:paymentHolder>" + " <tns:amount currency=\"USD\">33.33</tns:amount>" + " <tns:cardInformation>" + " <tns:cardType>" + CardType + "</tns:cardType>" + " <tns:cardNumber>" + CardNum +"</tns:cardNumber>" + " <tns:cvc>" + CardCVC + "</tns:cvc>" + " <tns:expiryDate month=\"10\" year=\"2023\"/>" + " </tns:cardInformation>" + " <tns:shopperInformation>" + " <tns:browser>" + " <tns:userAgentHeader>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36</tns:userAgentHeader>" + " <tns:acceptHeader>application/json, text/plain, */*</tns:acceptHeader>" + " </tns:browser>" + " <tns:ipAddress>103.233.174.2</tns:ipAddress>" + " <tns:sessionId>1</tns:sessionId>" + " </tns:shopperInformation>" + " </tns:paymentInformation>" + " </tns:authorize>" + " </soapenv:Body>" + "</soapenv:Envelope>"; con.setDoOutput(true); DataOutputStream wr = new DataOutputStream(con.getOutputStream()); wr.writeBytes(xml); wr.flush(); wr.close(); String responseStatus = con.getResponseMessage(); System.out.println(responseStatus); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); //System.out.println("response:" + response.toString()); Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(new InputSource(new StringReader(response.toString()))); NodeList errNodes = doc.getElementsByTagName("ns2:paymentStatus"); if (errNodes.getLength() > 0) { Element err = (Element)errNodes.item(0); System.out.println("Transaction ID -"+err.getElementsByTagName("ns2:paymentTransactionId").item(0).getTextContent()); System.out.println("Order Status -"+err.getElementsByTagName("ns2:orderStatus").item(0).getTextContent()); System.out.println("Order Reason -"+err.getElementsByTagName("ns2:orderReason").item(0).getTextContent()); System.out.println("Transaction Status -"+err.getElementsByTagName("ns2:paymentTransactionStatus").item(0).getTextContent()); } else { // success } } catch (Exception e) { System.out.println(e); } }
一、Java后端改造(搭建Web接口)
原有代码是本地运行的main方法,需要改造成可接收前端请求的Web接口,推荐用Spring Boot(新手易上手):
1. 创建Spring Boot项目
用Spring Initializr选择Web依赖生成项目,导入IDE即可。
2. 封装SOAP调用逻辑为工具类
把支付调用代码抽成工具类,接收前端参数并返回解析后的结果:
import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import javax.xml.parsers.DocumentBuilderFactory; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.Map; public class PaymentSoapUtil { public static Map<String, String> callPaymentApi(String cardType, String cardNum, String cardCvc) { Map<String, String> result = new HashMap<>(); try { String url = "https://onepay-services.uat.aws.emagin.eu/api/soap/payment"; URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty("Content-Type", "text/xml"); con.setRequestProperty("SOAPAction", "http://www.allianz-assistance.com/emagin/services/PaymentService/1.0/authorize"); // 构造SOAP请求XML,替换为前端传入的参数 String xml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"" + " xmlns:ns=\"http://www.allianz-assistance.com/emagin/services/PaymentService/1.0\">" + "<soapenv:Header/>" + " <soapenv:Body>" + " <tns:authorize xmlns:tns=\"http://www.allianz-assistance.com/emagin/services/PaymentService/1.0\" xmlns:emagin=\"http://www.mondial-assistance.com/ecommerce/schema/\">" + " <tns:globalRequestId>paymentOrder</tns:globalRequestId>" + " <tns:authentication>" + " <tns:userId>AWC_LIFEEUR</tns:userId>" + " <tns:password>awclifeeur$2018</tns:password>" + " </tns:authentication>" + " <tns:accountId>ACCOUNT_AWC_LIFEEUR</tns:accountId>" + " <tns:customerInformation>" + " <tns:partnerCode>ALS</tns:partnerCode>" + " <tns:buCode>CH</tns:buCode>" + " </tns:customerInformation>" + " <tns:paymentInformation>" + " <tns:paymentHolder>" + " <tns:name>Charlie</tns:name>" + " <tns:email>charlie@allianz.com</tns:email>" + " <tns:address>" + " <tns:address>11/22 Street1 Road1</tns:address>" + " <tns:city>Penang</tns:city>" + " <tns:country>ID</tns:country>" + " </tns:address>" + " </tns:paymentHolder>" + " <tns:amount currency=\"USD\">33.33</tns:amount>" + " <tns:cardInformation>" + " <tns:cardType>" + cardType + "</tns:cardType>" + " <tns:cardNumber>" + cardNum +"</tns:cardNumber>" + " <tns:cvc>" + cardCvc + "</tns:cvc>" + " <tns:expiryDate month=\"10\" year=\"2023\"/>" + " </tns:cardInformation>" + " <tns:shopperInformation>" + " <tns:browser>" + " <tns:userAgentHeader>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36</tns:userAgentHeader>" + " <tns:acceptHeader>application/json, text/plain, */*</tns:acceptHeader>" + " </tns:browser>" + " <tns:ipAddress>103.233.174.2</tns:ipAddress>" + " <tns:sessionId>1</tns:sessionId>" + " </tns:shopperInformation>" + " </tns:paymentInformation>" + " </tns:authorize>" + " </soapenv:Body>" + "</soapenv:Envelope>"; con.setDoOutput(true); DataOutputStream wr = new DataOutputStream(con.getOutputStream()); wr.writeBytes(xml); wr.flush(); wr.close(); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); // 解析SOAP响应 Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() .parse(new InputSource(new StringReader(response.toString()))); NodeList errNodes = doc.getElementsByTagName("ns2:paymentStatus"); if (errNodes.getLength() > 0) { Element err = (Element) errNodes.item(0); result.put("transactionId", err.getElementsByTagName("ns2:paymentTransactionId").item(0).getTextContent()); result.put("orderStatus", err.getElementsByTagName("ns2:orderStatus").item(0).getTextContent()); result.put("orderReason", err.getElementsByTagName("ns2:orderReason").item(0).getTextContent()); result.put("transactionStatus", err.getElementsByTagName("ns2:paymentTransactionStatus").item(0).getTextContent()); } else { result.put("orderStatus", "SUCCESS"); result.put("orderReason", "无错误信息"); } } catch (Exception e) { result.put("orderStatus", "FAILED"); result.put("orderReason", e.getMessage()); } return result; } }
3. 编写Controller接收前端请求
创建RestController,接收前端POST请求,调用工具类并返回结果:
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.Map; @RestController @CrossOrigin(origins = "http://localhost:4200") // 允许Angular本地端口跨域 public class PaymentController { @PostMapping("/api/payment/verify") public Map<String, String> verifyPayment(@RequestBody Map<String, String> params) { String cardType = params.get("cardType"); String cardNum = params.get("cardNum"); String cardCvc = params.get("cardCvc"); return PaymentSoapUtil.callPaymentApi(cardType, cardNum, cardCvc); } }
4. 跨域说明
上面的@CrossOrigin注解已处理本地开发的跨域问题,生产环境建议在Spring Boot配置类中统一配置跨域规则。
二、Angular前端实现
1. 创建Angular项目
终端执行:
ng new payment-app cd payment-app
2. 生成支付组件
ng generate component payment-form
3. 编写表单模板(payment-form.component.html)
创建表单收集参数,添加提交按钮和结果展示区域:
<div class="payment-form-container"> <h2>支付验证</h2> <form (ngSubmit)="onSubmit(paymentForm)" #paymentForm="ngForm"> <div class="form-group"> <label>卡类型</label> <select name="cardType" ngModel required> <option value="VISA">VISA</option> <option value="MASTERCARD">MasterCard</option> </select> </div> <div class="form-group"> <label>卡号</label> <input type="text" name="cardNum" ngModel required placeholder="4444333322221111"> </div> <div class="form-group"> <label>CVC码</label> <input type="text" name="cardCvc" ngModel required placeholder="123"> </div> <button type="submit" [disabled]="!paymentForm.valid">提交验证</button> </form> <!-- 结果展示区域 --> <div class="result-container" *ngIf="paymentResult"> <h3>验证结果</h3> <p><strong>交易ID:</strong>{{ paymentResult.transactionId }}</p> <p><strong>订单状态:</strong>{{ paymentResult.orderStatus }}</p> <p><strong>订单原因:</strong>{{ paymentResult.orderReason }}</p> <p><strong>交易状态:</strong>{{ paymentResult.transactionStatus }}</p> </div> </div>
4. 编写组件逻辑(payment-form.component.ts)
引入HttpClient,实现提交请求和结果处理:
import { Component } from '@angular/core
相关产品推荐
相关产品推荐

