APP银联支付(微信、支付宝、云闪付)
2022-04-13
1.导入pom.xml
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
2.编写工具类
package com.slodon.bbc.business.util;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* app银联支付:微信、支付宝、云闪付
*
* @author dell
*/
public class UnionPayUtil {
static String appId = "********";
static String appKey = "********";
static String authorization;
/**
* 商户号
*/
static String mid = "********";
/**
* 终端号
*/
static String tid = "********";
/**
* 系统编号
*/
static String msgSrcId = "********";
/**
* 微信下单
*/
static String wxPlaceOrderUrl = "https://api-mop.chinaums.com/v1/netpay/wx/app-pre-order";
/**
* 支付宝下单
*/
static String aliPlaceOrderUrl = "https://api-mop.chinaums.com/v1/netpay/trade/precreate";
/**
* 银联云闪付下单
*/
static String unionPlaceOrderUrl = "https://api-mop.chinaums.com/v1/netpay/uac/app-order";
/**
* 订单查询
*/
static String queryOrderUrl = "https://api-mop.chinaums.com/v1/netpay/query";
/**
* 退款
*/
static String refundOrderUrl = "https://api-mop.chinaums.com/v1/netpay/refund";
/**
* 退款查询
*/
static String refundQueryUrl = "https://api-mop.chinaums.com/v1/netpay/refund-query";
/**
* 订单关闭
*/
static String closeOrderUrl = "https://api-mop.chinaums.com/v1/netpay/close";
/**
* 支付结果通知地址
*/
static String notifyUrl = "********************";
public static void main(String[] args) throws Exception {
placeOrder();
}
/**
* app下单
*
* @throws Exception
*/
public static String placeOrder() throws Exception {
/* post参数,格式:JSON */
JSONObject json = new JSONObject();
json.put("requestTimestamp", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
json.put("merOrderId", getMerOrderId(msgSrcId));
json.put("notifyUrl", notifyUrl);
json.put("mid", mid);
json.put("tid", tid);
// 微信子商户appId,必传
json.put("subAppId", "**************");
// 业务类型
json.put("instMid", "APPDEFAULT");
// 支付总金额
json.put("totalAmount", 1);
// 交易类型,微信必传
json.put("tradeType", "APP");
String placeOrderUrl = wxPlaceOrderUrl;
System.out.println("请求报文:\n" + json);
String send = this.send(placeOrderUrl, json.toString());
System.out.println("返回结果:\n" + send);
return send;
}
/**
* 订单查询
*/
public static void queryOrder() throws Exception {
JSONObject json = new JSONObject();
json.put("requestTimestamp", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
json.put("mid", mid);
json.put("tid", tid);
json.put("instMid", "APPDANDEFAULT");
// 商户订单号,支付交易生成的商户订单号
json.put("merOrderId", "***********");
System.out.println("请求报文:\n" + json);
String send = this.send(queryOrderUrl, json.toString());
System.out.println("返回结果:\n" + send);
}
/**
* 退款
*
* @throws Exception
*/
public static void refundOrder() throws Exception {
/* post参数,格式:JSON */
JSONObject json = new JSONObject();
json.put("requestTimestamp", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
json.put("mid", mid);
json.put("tid", tid);
json.put("instMid", "APPDANDEFAULT");
// 商户订单号,支付交易生成的商户订单号
json.put("merOrderId", "***********");
json.put("refundAmount", 1);
Map<String, Object> subOrders = new HashMap<>();
subOrders.put("totalAmount", 1);
subOrders.put("mid", mid);
json.put("subOrders", subOrders);
json.put("platformAmount", 1);
json.put("refundOrderId", getMerOrderId(msgSrcId));
json.put("billDate", DateFormatUtils.format(new Date(), "yyyy-MM-dd"));
System.out.println("请求报文:\n" + json);
String send = this.send(refundOrderUrl, json.toString());
System.out.println("返回结果:\n" + send);
}
/**
* 退款查询
*
* @throws Exception
*/
public static void refundQuery() throws Exception {
/* post参数,格式:JSON */
JSONObject json = new JSONObject();
json.put("requestTimestamp", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
json.put("mid", mid);
json.put("tid", tid);
json.put("instMid", "APPDANDEFAULT");
// 商户订单号,支付交易生成的商户订单号
json.put("merOrderId", "**************");
System.out.println("请求报文:\n" + json);
String send = this.send(refundQueryUrl, json.toString());
System.out.println("返回结果:\n" + send);
}
/**
* 用户创建订单之后,对未支付的订单进行关闭操作
*/
public static void close() throws Exception {
/* post参数,格式:JSON */
JSONObject json = new JSONObject();
json.put("requestTimestamp", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
json.put("mid", mid);
json.put("tid", tid);
json.put("instMid", "APPDEFAULT");
// 商户订单号,支付交易生成的商户订单号
json.put("merOrderId", "************");
System.out.println("请求报文:\n" + json);
String send = this.send(closeOrderUrl, json.toString());
System.out.println("返回结果:\n" + send);
}
/**
* 发送请求
*
* @param url
* @return
* @throws Exception
*/
public static String send(String url, String entity) throws Exception {
authorization = getOpenBodySig(appId, appKey, entity);
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Authorization", authorization);
StringEntity se = new StringEntity(entity, "UTF-8");
se.setContentType("application/json");
httpPost.setEntity(se);
CloseableHttpResponse response = httpClient.execute(httpPost);
HttpEntity entity1 = response.getEntity();
String resStr = null;
if (entity1 != null) {
resStr = EntityUtils.toString(entity1, "UTF-8");
}
httpClient.close();
response.close();
return resStr;
}
/**
* open-body-sig方式获取到Authorization 的值
*
* @return
* @throws Exception
*/
public static String getOpenBodySig(String appId, String appKey, String body) throws Exception {
String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String nonce = UUID.randomUUID().toString().replace("-", "");
byte[] data = body.getBytes("UTF-8");
InputStream is = new ByteArrayInputStream(data);
String bodyDigest = testSHA256(is);
String str1_C = appId + timestamp + nonce + bodyDigest;
byte[] localSignature = hmacSHA256(str1_C.getBytes(), appKey.getBytes());
String localSignatureStr = Base64.encodeBase64String(localSignature);
System.out.println("Authorization:\n" + "OPEN-BODY-SIG AppId=" + "\"" + appId + "\"" + ", Timestamp=" + "\"" + timestamp + "\"" + ", Nonce=" + "\"" + nonce + "\"" + ", Signature=" + "\"" + localSignatureStr + "\"\n");
return ("OPEN-BODY-SIG AppId=" + "\"" + appId + "\"" + ", Timestamp=" + "\"" + timestamp + "\"" + ", Nonce=" + "\"" + nonce + "\"" + ", Signature=" + "\"" + localSignatureStr + "\"");
}
/**
* 进行加密
*
* @param is
* @return 加密后的结果
*/
private static String testSHA256(InputStream is) {
try {
return DigestUtils.sha256Hex(is);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @param data
* @param key
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
*/
public static byte[] hmacSHA256(byte[] data, byte[] key) throws NoSuchAlgorithmException, InvalidKeyException {
String algorithm = "HmacSHA256";
Mac mac = Mac.getInstance(algorithm);
mac.init(new SecretKeySpec(key, algorithm));
return mac.doFinal(data);
}
/**
* 获取到订单号
*
* @return 商户订单号 {来源编号(4位)}{时间(yyyyMMddmmHHssSSS)(17位)}{7位随机数}
*/
public static String getMerOrderId(String msgSrcId) {
return msgSrcId + DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS") + RandomStringUtils.randomNumeric(7);
}
/**
* 获取到退货订单号refundOrderId
*
* @return 商户订单号 {来源编号(4位)}{时间(yyyyMMddmmHHssSSS)(17位)}{7位随机数}
*/
public static String getRefundOrderId(String msgSrcId) {
return msgSrcId + DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS") + RandomStringUtils.randomNumeric(7);
}
}