uniapp+java+微信APP支付
1.微信官方支付地址2.注册微信商户开发平台和商户平台,创建移动应用。3.应用审核通过后,开通APP支付能力,这里需要关联商户平台4.APP支付能力开通后,进入编码阶段。public class WeiChartConfig {/*** 预支付请求地址*/public static final StringPrepayUrl = "https://api.mch.weixin.qq.com/pay
·
1.微信官方支付地址
2.注册微信商户开发平台和商户平台,创建移动应用。
3.应用审核通过后,开通APP支付能力,这里需要关联商户平台
4.APP支付能力开通后,进入编码阶段。
public class WeiChartConfig {
/**
* 预支付请求地址
*/
public static final String PrepayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
/**
* 查询订单地址
*/
public static final String OrderUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
/**
* 关闭订单地址
*/
public static final String CloseOrderUrl = "https://api.mch.weixin.qq.com/pay/closeorder";
/**
* 申请退款地址
*/
public static final String RefundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
/**
* 查询退款地址
*/
public static final String RefundQueryUrl = "https://api.mch.weixin.qq.com/pay/refundquery";
/**
* 下载账单地址
*/
public static final String DownloadBillUrl = "https://api.mch.weixin.qq.com/pay/downloadbill";
/**
* 商户APPID
*/
public static final String AppId = "wx270xxxx";
/**
* 商户账户
*/
public static final String MchId = "160xxxx";
/**
* 商户秘钥
*/
public static final String AppSercret = "d6d5xxx";
/**
* 服务器异步通知页面路径
*/
public static String notify_url = "xxxPay/notify";
/**
* 退款通知地址
*/
public static String refund_notify_url = "";
/**
* 退款需要证书文件,证书文件的地址
*/
public static final String refund_file_path = "xxx";
}
预下单:
Map<String, String> reqMap = new HashMap<String, String>();
reqMap.put("appid", WeiChartConfig.AppId);//appid
reqMap.put("mch_id", WeiChartConfig.MchId);//商户id
reqMap.put("nonce_str", WeiChartUtil.getRandomString());//随机字符串
reqMap.put("body", commodityName);//商品名称
reqMap.put("out_trade_no", paySignParams.getOrderNo()); //商户系统内部的订单号,
if(payPrice.doubleValue() <= 0){
throw new BusinessException("支付金额需要大于0");
}
reqMap.put("total_fee", WeiChartUtil.changeToFen(payPrice.doubleValue())); //订单总金额,单位为分
reqMap.put("spbill_create_ip", WeiChartUtil.getHostIp()); //用户端实际ip
reqMap.put("notify_url", SYS_HOST+WeiChartConfig.notify_url); //通知地址
//交易类型
reqMap.put("trade_type", "APP");
//指定支付方式,no_credit 指定不能使用信用卡支 非必填
//reqMap.put("limit_pay", "no_credit");
reqMap.put("sign", WeiChartUtil.getSign(reqMap));//签名
String reqStr = WeiChartUtil.creatXml(reqMap);//生产xml字符串
String retStr = HttpClientUtil.postHtpps(WeiChartConfig.PrepayUrl, reqStr);
log.info("=======微信预支付返回结果:{}",reqStr);
WeiChartUtil工具类:
import com.alipay.api.AlipayApiException;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
@Slf4j
public class WeiChartUtil{
/**
* 关闭订单
* @param orderId 商户自己的订单号
* @return
*/
public static Map<String, String> closeOrder(String orderId){
Map<String, String> reqMap = new HashMap<String, String>();
reqMap.put("appid", WeiChartConfig.AppId);
reqMap.put("mch_id", WeiChartConfig.MchId);
reqMap.put("nonce_str", getRandomString());
reqMap.put("out_trade_no", orderId); //商户系统内部的订单号,
reqMap.put("sign", getSign(reqMap));
String reqStr = creatXml(reqMap);
String retStr = HttpClientUtil.postHtpps(WeiChartConfig.CloseOrderUrl, reqStr);
return getInfoByXml(retStr);
}
/**
* 查询订单
* @param orderId 商户自己的订单号
* @return
*/
public static String getOrder(String orderId){
Map<String, String> reqMap = new HashMap<String, String>();
reqMap.put("appid", WeiChartConfig.AppId);
reqMap.put("mch_id", WeiChartConfig.MchId);
reqMap.put("nonce_str", getRandomString());
reqMap.put("out_trade_no", orderId); //商户系统内部的订单号,
reqMap.put("sign", getSign(reqMap));
String reqStr = creatXml(reqMap);
String retStr = HttpClientUtil.postHtpps(WeiChartConfig.OrderUrl, reqStr);
return retStr;
}
/**
* 退款
* @param orderId 商户订单号
* @param refundId 退款单号
* @param totralFee 总金额(分)
* @param refundFee 退款金额(分)
* @param opUserId 操作员ID
* @return
*/
public static Map<String, String> refundWei(String orderId,String refundId,String totralFee,String refundFee,String opUserId){
Map<String, String> reqMap = new HashMap<String, String>();
reqMap.put("appid", WeiChartConfig.AppId);
reqMap.put("mch_id", WeiChartConfig.MchId);
reqMap.put("nonce_str", getRandomString());
reqMap.put("out_trade_no", orderId); //商户系统内部的订单号,
reqMap.put("out_refund_no", refundId); //商户退款单号
reqMap.put("total_fee", totralFee); //总金额
reqMap.put("refund_fee", refundFee); //退款金额
reqMap.put("op_user_id", opUserId); //操作员
reqMap.put("sign", getSign(reqMap));
String reqStr = creatXml(reqMap);
String retStr = "";
try{
retStr = HttpClientUtil.postHttplientNeedSSL(WeiChartConfig.RefundUrl, reqStr, WeiChartConfig.refund_file_path, WeiChartConfig.MchId);
}catch(Exception e){
e.printStackTrace();
return null;
}
return getInfoByXml(retStr);
}
/**
* 退款查询
* @param refundId 退款单号
* @return
*/
public static Map<String, String> getRefundWeiInfo(String refundId){
Map<String, String> reqMap = new HashMap<String, String>();
reqMap.put("appid", WeiChartConfig.AppId);
reqMap.put("mch_id", WeiChartConfig.MchId);
reqMap.put("nonce_str", getRandomString());
reqMap.put("out_refund_no", refundId); //商户退款单号
reqMap.put("sign", getSign(reqMap));
String reqStr = creatXml(reqMap);
String retStr = HttpClientUtil.postHtpps(WeiChartConfig.RefundQueryUrl, reqStr);
return getInfoByXml(retStr);
}
/**
* 传入map 生成头为XML的xml字符串,例:<xml><key>123</key></xml>
* @param reqMap
* @return
*/
public static String creatXml(Map<String, String> reqMap){
Set<String> set = reqMap.keySet();
StringBuffer b = new StringBuffer();
b.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
b.append("<xml>");
for(String key : set){
b.append("<"+key+">").append(reqMap.get(key)).append("</"+key+">");
}
b.append("</xml>");
return b.toString();
}
/**
* 得到加密值
* @param map
* @return
*/
public static String getSign(Map<String, String> map){
String[] keys = map.keySet().toArray(new String[0]);
Arrays.sort(keys);
StringBuffer reqStr = new StringBuffer();
for(String key : keys){
String v = map.get(key);
if(v != null && !v.equals("")){
reqStr.append(key).append("=").append(v).append("&");
}
}
reqStr.append("key").append("=").append(WeiChartConfig.AppSercret);
return WeiMd5.encode(reqStr.toString()).toUpperCase();
}
/**
* 得到10 位的时间戳
* 如果在JAVA上转换为时间要在后面补上三个0
* @return
*/
public static String getTenTimes(){
String t = new Date().getTime()+"";
t = t.substring(0, t.length()-3);
return t;
}
/**
* 得到随机字符串
* @return
*/
public static String getRandomString(){
int length = 32;
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for(int i = 0; i < length; ++i){
int number = random.nextInt(62);//[0,62)
sb.append(str.charAt(number));
}
return sb.toString();
}
/**
* 得到本地机器的IP
* @return
*/
public static String getHostIp(){
String ip = "";
try{
ip = InetAddress.getLocalHost().getHostAddress();
}catch(UnknownHostException e){
e.printStackTrace();
}
return ip;
}
public static Map<String, String> getInfoByXml(String xmlStr){
Map<String, String> m = new HashMap<String, String>();
try{
Document d = DocumentHelper.parseText(xmlStr);
Element root = d.getRootElement();
for ( Iterator<?> i = root.elementIterator(); i.hasNext(); ) {
Element element = (Element) i.next();
String name = element.getName();
if(!element.isTextOnly()){
//不是字符串 跳过。确定了微信放回的xml只有根目录
continue;
}else{
m.put(name, element.getTextTrim());
}
}
//对返回结果做校验.去除sign 字段再去加密
String retSign = m.get("sign");
m.remove("sign");
String rightSing = getSign(m);
if(rightSing.equals(retSign)){
return m;
}
}catch(DocumentException e){
e.printStackTrace();
}
return m;
}
/**
* 将金额转换成分
* @param fee 元格式的
* @return 分
*/
public static String changeToFen(Double fee){
String priceStr = "";
if(fee != null){
int p = (int)(fee * 100); //价格变为分
priceStr = Integer.toString(p);
}
return priceStr;
}
/**
* 将map解析成string
* @param param
* @return
*/
public static String GetMapToXML(Map<String,String> param){
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
for (Map.Entry<String,String> entry : param.entrySet()) {
sb.append("<"+ entry.getKey() +">");
sb.append(entry.getValue());
sb.append("</"+ entry.getKey() +">");
}
sb.append("</xml>");
return sb.toString();
}
/**
* xml解析
* @param strxml
* @return
* @throws JDOMException
* @throws IOException
*/
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if(null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = null;
try {
in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
org.jdom.Document doc = builder.build(in);
org.jdom.Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while(it.hasNext()) {
org.jdom.Element e = (org.jdom.Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if(children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = getChildrenText(children);
}
m.put(k, v);
}
}finally {
if(in != null){
in.close();
}
}
return m;
}
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if(!children.isEmpty()) {
Iterator it = children.iterator();
while(it.hasNext()) {
org.jdom.Element e = (org.jdom.Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if(!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
}
/**
* 验证回调签名
* @return
*/
public static boolean isTenpaySign(Map<String, String> map) {
String characterEncoding="utf-8";
String charset = "utf-8";
String signFromAPIResponse = map.get("sign");
if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {
System.out.println("API返回的数据签名数据不存在,有可能被第三方篡改!!!");
return false;
}
System.out.println("服务器回包里面的签名是:" + signFromAPIResponse);
//过滤空 设置 TreeMap
SortedMap<String,String> packageParams = new TreeMap();
for (String parameter : map.keySet()) {
String parameterValue = map.get(parameter);
String v = "";
if (null != parameterValue) {
v = parameterValue.trim();
}
packageParams.put(parameter, v);
}
StringBuffer sb = new StringBuffer();
Set es = packageParams.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(!"sign".equals(k) && null != v && !"".equals(v)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + WeiChartConfig.AppSercret);
//将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
//算出签名
String resultSign = null;
String tobesign = sb.toString();
try{
resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();
}catch (Exception e) {
resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();
}
String tenpaySign = packageParams.get("sign").toUpperCase();
return tenpaySign.equals(resultSign);
}
uniapp支付微信和支付宝的orderInfo不同,支付宝传一个字符串,微信需要时一个object官网地址
微信支付后的回调方法请求RequestMapping
@RequestMapping(value="notify",produces = {"application/json;charset=UTF-8" },method = RequestMethod.POST)
微信回调方法
InputStream inStream = null;
ByteArrayOutputStream outSteam = null;
try {
inStream = request.getInputStream();
outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
String resultxml = new String(outSteam.toByteArray(), "utf-8");
Map<String, String> params = WeiChartUtil.doXMLParse(resultxml);
log.info("=====微信回调返回数据:{}",JSON.toJSONString(params));
Map<String,String> return_data = new HashMap<String,String>();
if (!WeiChartUtil.isTenpaySign(params)) {
log.info("=====微信支付失败。。。");
return_data.put("return_code", "FAIL");
return_data.put("return_msg", "支付失败");
return WeiChartUtil.GetMapToXML(return_data);
} else {
//TODO 业务处理...
log.info("=====微信支付成功。。。");
return_data.put("return_code", "SUCCESS");
return_data.put("return_msg", "OK");
return WeiChartUtil.GetMapToXML(return_data);
}
}finally {
if(outSteam != null){
outSteam.close();
}
if(inStream != null){
inStream.close();
}
}
更多推荐
已为社区贡献3条内容
所有评论(0)