maven
<!-- 微信支付-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.15</version>
</dependency>
<!-- 阿里支付-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.40.16.ALL</version>
</dependency>
接口 PaymentCodeGenerator
public interface PaymentCodeGenerator {
String generatePaymentCode(String orderNo, BigDecimal totalAmount,
String description) throws Exception;
}
支付宝的实现 AliPaymentCodeGenerator
官方:https://opendocs.alipay.com/open/59da99d0_alipay.trade.page.pay?pathHash=e26b497f&scene=22
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import java.math.BigDecimal;
public class AliPaymentCodeGenerator implements PaymentCodeGenerator {
private PaymentConf paymentConfig;
public AliPaymentCodeGenerator(PaymentConf paymentConfig) {
this.paymentConfig = paymentConfig;
}
@Override
public String generatePaymentCode(String orderNo, BigDecimal totalAmount, String description) throws Exception {
// 初始化SDK
AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
// 构造请求参数以调用接口
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
// 设置商户订单号
model.setOutTradeNo(orderNo);
// 设置订单总金额
model.setTotalAmount(totalAmount.toString());
// 设置订单标题
model.setSubject(description);
// 设置产品码
model.setProductCode("FAST_INSTANT_TRADE_PAY");
request.setBizModel(model);
request.setNotifyUrl(paymentConfig.getCallBack());
AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "POST");
String pageRedirectionData = response.getBody();
if (response.isSuccess()) {
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}
return pageRedirectionData;
}
private AlipayConfig getAlipayConfig() {
String privateKey = paymentConfig.getPrivateKey();
String alipayPublicKey = paymentConfig.getAlipayPublicKey();
AlipayConfig alipayConfig = new AlipayConfig();
alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
alipayConfig.setAppId(paymentConfig.getAppId());
alipayConfig.setPrivateKey(privateKey);
alipayConfig.setFormat("json");
alipayConfig.setAlipayPublicKey(alipayPublicKey);
alipayConfig.setCharset("UTF-8");
alipayConfig.setSignType("RSA2");
return alipayConfig;
}
public static void main(String[] args) {
PaymentConf paymentConf = new PaymentConf();
paymentConf.setAppId("");// 你的appId;
paymentConf.setPrivateKey("");//你的应用私钥
paymentConf.setAlipayPublicKey("");//你的支付宝公钥
paymentConf.setCallBack("");//你的回调接口
AliPaymentCodeGenerator generator = new AliPaymentCodeGenerator(
paymentConf
);
try {
String s = generator.generatePaymentCode(
"11111111111",
new BigDecimal(0.01),
"保证金"
);
System.out.println("成功:");
} catch (Exception e) {
System.out.println("报错:" + e.getMessage());
}
}
}
微信付款码 V2 WechatPaymentCodeV2Generator
官方:https://pay.weixin.qq.com/doc/v2/merchant/4011936530
import org.gin.exceptions.ServiceException;
import org.gin.util.XmlUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import javax.net.ssl.HttpsURLConnection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
public class WechatPaymentCodeV2Generator implements PaymentCodeGenerator {
private static final String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
private final PaymentConf paymentConfig;
public WechatPaymentCodeV2Generator(PaymentConf paymentConfig) {
this.paymentConfig = paymentConfig;
}
@Override
public String generatePaymentCode(String orderNo, BigDecimal totalAmount, String description) throws Exception {
InetAddress inetAddress = InetAddress.getLocalHost();
Integer amount=totalAmount.multiply(new BigDecimal(100)).intValue();
Map<String, String> params = prepareRequestParams(orderNo, amount.toString(), description, inetAddress);
// 签名
String sign = generateSign(params, paymentConfig.getMchKey());
params.put("sign", sign);
String xmlParam = XmlUtil.mapToXml(params);
String responseXml = sendPostRequest(UNIFIEDORDER_URL, xmlParam);
// 解析返回结果
Map<String, String> resultMap = convertXMLToMap(responseXml);
return processResponse(resultMap);
}
private Map<String, String> prepareRequestParams(String orderNo, String totalAmount, String description, InetAddress inetAddress) {
Map<String, String> params = new HashMap<>();
params.put("appid", paymentConfig.getAppId());
params.put("mch_id", paymentConfig.getMchId());
params.put("nonce_str", generateNonceStr());
params.put("body", description);
params.put("out_trade_no", orderNo);
Integer amount = new BigDecimal(totalAmount).multiply(new BigDecimal(100)).intValue();
params.put("total_fee", amount.toString());
params.put("spbill_create_ip", inetAddress.getHostAddress());
params.put("notify_url", paymentConfig.getCallBack());
params.put("trade_type", "NATIVE"); // 微信扫码支付
return params;
}
private String generateNonceStr() {
return UUID.randomUUID().toString().replace("-", "");
}
private String generateSign(Map<String, String> params, String appKey) throws NoSuchAlgorithmException {
Map<String, String> sortedMap = new TreeMap<>(params);
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
sb.append("key=").append(appKey);
return md5(sb.toString()).toUpperCase();
}
private String md5(String str) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
byte[] hashBytes = messageDigest.digest(str.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
hexString.append("0");
}
hexString.append(hex);
}
return hexString.toString();
}
private String sendPostRequest(String url, String xmlParam) throws IOException {
HttpsURLConnection conn = (HttpsURLConnection) new URL(url).openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/xml");
conn.setDoOutput(true);
try (OutputStream out = conn.getOutputStream()) {
out.write(xmlParam.getBytes(StandardCharsets.UTF_8));
out.flush();
}
StringBuilder response = new StringBuilder();
try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = in.readLine()) != null) {
response.append(line);
}
}
conn.disconnect();
return response.toString();
}
private Map<String, String> convertXMLToMap(String xmlString) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(new StringReader(xmlString));
Document document = builder.parse(inputSource);
return parseElementToMap(document.getDocumentElement());
}
private Map<String, String> parseElementToMap(Element element) {
Map<String, String> map = new HashMap<>();
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
map.put(node.getNodeName(), node.getTextContent().trim());
}
}
return map;
}
private String processResponse(Map<String, String> resultMap) throws ServiceException {
if ("SUCCESS".equals(resultMap.get("return_code"))) {
return resultMap.get("code_url");
} else {
String returnMsg = resultMap.get("return_msg");
throw new ServiceException("Error in response: " + returnMsg);
}
}
}
微信扫码支付 V3 WechatPaymentCodeGenerator
官方:https://pay.weixin.qq.com/doc/v3/merchant/4012791877
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import java.math.BigDecimal;
public class WechatPaymentCodeGenerator implements PaymentCodeGenerator{
/** 商户API私钥路径 */
public static String privateKeyPath = "你自己的私钥路径";
/** 商户证书序列号 */
public static String merchantSerialNumber = "商户序列号";
private PaymentConf paymentConfig;
public WechatPaymentCodeGenerator(PaymentConf paymentConfig) {
this.paymentConfig = paymentConfig;
}
@Override
public String generatePaymentCode(String orderNo, BigDecimal totalAmount, String description) throws Exception {
Config config =
new RSAAutoCertificateConfig.Builder()
.merchantId(paymentConfig.getMchId())
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(paymentConfig.getMchKey())
.build();
// 构建service
NativePayService service = new NativePayService.Builder().config(config).build();
// request.setXxx(val)设置所需参数,具体参数可见Request定义
PrepayRequest request = new PrepayRequest();
Amount amount = new Amount();
amount.setTotal(totalAmount.multiply(new BigDecimal(100)).intValue());
request.setAmount(amount);
request.setAppid(paymentConfig.getAppId());
request.setMchid(paymentConfig.getMchId());
request.setDescription(description);
request.setNotifyUrl(paymentConfig.getCallBack());
request.setOutTradeNo(orderNo);
// 调用下单方法,得到应答
PrepayResponse response = service.prepay(request);
// 使用微信扫描 code_url 对应的二维码,即可体验Native支付
return response.getCodeUrl();
}
public static void main(String[] args) throws Exception {
PaymentConf paymentConf=new PaymentConf();
paymentConf.setAppId("你自己的appId");
paymentConf.setMchId("你自己的商户id");
paymentConf.setMchKey("你的商户key");
WechatPaymentCodeGenerator generator=new WechatPaymentCodeGenerator(paymentConf);
String s=generator.generatePaymentCode(
"111111",new BigDecimal(1),"保证金"
);
System.out.println(s);
}
}
工厂
package org.gin.paymentcode;
public class PaymentCodeGeneratorFactory {
/**
*
* @param paymentMethod 支付方式 3支付宝;1微信
* @param paymentConfig
* @return PaymentCodeGenerator
*/
public static PaymentCodeGenerator getQRCodeGenerator(Integer paymentMethod, PaymentConf paymentConfig) {
if (paymentMethod==1) {
return new WechatPaymentCodeV2Generator(paymentConfig);
}
if (paymentMethod==3) {
return new AliPaymentCodeGenerator(paymentConfig);
}
throw new IllegalArgumentException("Unsupported payment method: " + paymentMethod);
}
}
实际使用
String paymentPath = PaymentCodeGeneratorFactory.getQRCodeGenerator(
businessType, paymentConf
).generatePaymentCode(
orderNo, deposit,
"保证金"
);
工具类
XmlUtil
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.util.Map;
public class XmlUtil {
public static String mapToXml(Map<String, String> map) throws Exception {
DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
Element root = document.createElement("parameters");
document.appendChild(root);
for (Map.Entry<String, String> entry : map.entrySet()) {
Element element = document.createElement(entry.getKey());
element.appendChild(document.createTextNode(entry.getValue()));
root.appendChild(element);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
DOMSource source = new DOMSource(document);
transformer.transform(source, result);
return writer.toString();
}
}