微信APP支付(Java后台生成签名具体步骤)

public class PayCommonUtil {
    //定义签名,微信根据参数字段的ASCII码值进行排序 加密签名,故使用SortMap进行参数排序    public static String createSign(String characterEncoding,SortedMap<String,String> parameters){        StringBuffer sb = new StringBuffer();        Set es = parameters.entrySet();        Iterator it = es.iterator();        while(it.hasNext()) {            Map.Entry entry = (Map.Entry)it.next();            String k = (String)entry.getKey();            Object v = entry.getValue();            if(null != v && !"".equals(v)                    && !"sign".equals(k) && !"key".equals(k)) {                sb.append(k + "=" + v + "&");            }        }        sb.append("key=" + ConstantUtil.PARTNER_KEY);//最后加密时添加商户密钥,由于key值放在最后,所以不用添加到SortMap里面去,单独处理,编码方式采用UTF-8        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();        return sign;    }
 
//将封装好的参数转换成Xml格式类型的字符串

public static String getRequestXml(SortedMap<String,String> parameters){        StringBuffer sb = new StringBuffer();        sb.append("<xml>");        Set es = parameters.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".equalsIgnoreCase(k)){

}            else if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)) {                sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");            }            else {                sb.append("<"+k+">"+v+"</"+k+">");            }        }        sb.append("<"+"sign"+">"+"<![CDATA["+parameters.get("sign")+"]]></"+"sign"+">");        sb.append("</xml>");        return sb.toString();    }}
 
//微信Md5加密工具
public class MD5Util {

private static String byteArrayToHexString(byte b[]) {      StringBuffer resultSb = new StringBuffer();      for (int i = 0; i < b.length; i++)         resultSb.append(byteToHexString(b[i]));

return resultSb.toString();   }

private static String byteToHexString(byte b) {      int n = b;      if (n < 0)         n += 256;      int d1 = n / 16;      int d2 = n % 16;      return hexDigits[d1] + hexDigits[d2];   }

public static String MD5Encode(String origin, String charsetname) {      String resultString = null;      try {         resultString = new String(origin);         MessageDigest md = MessageDigest.getInstance("MD5");         if (charsetname == null || "".equals(charsetname))            resultString = byteArrayToHexString(md.digest(resultString                  .getBytes()));         else            resultString = byteArrayToHexString(md.digest(resultString                  .getBytes(charsetname)));      } catch (Exception exception) {      }      return resultString;   }

private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",         "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

}
 
//微信返回的结果为Xml格式的字符串,XmlUtil主要用于解析结果
public class XMLUtil {

/**    * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的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 = new ByteArrayInputStream(strxml.getBytes("UTF-8"));      SAXBuilder builder = new SAXBuilder();      Document doc = builder.build(in);      Element root = doc.getRootElement();      List list = root.getChildren();      Iterator it = list.iterator();      while(it.hasNext()) {         Element e = (Element) it.next();         String k = e.getName();         String v = "";         List children = e.getChildren();         if(children.isEmpty()) {            v = e.getTextNormalize();         } else {            v = XMLUtil.getChildrenText(children);         }

m.put(k, v);      }

//关闭流      in.close();

return m;   }

/**    * 获取子结点的xml    * @param children    * @return String    */   public static String getChildrenText(List children) {      StringBuffer sb = new StringBuffer();      if(!children.isEmpty()) {         Iterator it = children.iterator();         while(it.hasNext()) {            Element e = (Element) it.next();            String name = e.getName();            String value = e.getTextNormalize();            List list = e.getChildren();            sb.append("<" + name + ">");            if(!list.isEmpty()) {               sb.append(XMLUtil.getChildrenText(list));            }            sb.append(value);            sb.append("</" + name + ">");         }      }

return sb.toString();   }

/**    * 获取xml编码字符集    * @param strxml    * @return    * @throws IOException    * @throws JDOMException    */   public static String getXMLEncoding(String strxml) throws JDOMException, IOException {      InputStream in = HttpClientUtil.String2Inputstream(strxml);      SAXBuilder builder = new SAXBuilder();      Document doc = builder.build(in);      in.close();      return (String)doc.getProperty("encoding");   }}
 
//发送https
public class CommonUtil {    private static Logger log = LoggerFactory.getLogger(CommonUtil.class);    /**     * 发送https请求     * @param requestUrl 请求地址     * @param requestMethod 请求方式(GET、POST)     * @param outputStr 提交的数据     * @return 返回微信服务器响应的信息     */    public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {        try {            // 创建SSLContext对象,并使用我们指定的信任管理器初始化            MyX509TrustManager[] tm = { new MyX509TrustManager() };            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");            sslContext.init(null, tm, new java.security.SecureRandom());            // 从上述SSLContext对象中得到SSLSocketFactory对象            SSLSocketFactory ssf = sslContext.getSocketFactory();            URL url = new URL(requestUrl);            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();            conn.setSSLSocketFactory(ssf);            conn.setDoOutput(true);            conn.setDoInput(true);            conn.setUseCaches(false);            // 设置请求方式(GET/POST)            conn.setRequestMethod(requestMethod);            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");            // 当outputStr不为null时向输出流写数据            if (null != outputStr) {                OutputStream outputStream = conn.getOutputStream();                // 注意编码格式                outputStream.write(outputStr.getBytes("UTF-8"));                outputStream.close();            }            // 从输入流读取返回内容            InputStream inputStream = conn.getInputStream();            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);            String str = null;            StringBuffer buffer = new StringBuffer();            while ((str = bufferedReader.readLine()) != null) {                buffer.append(str);            }            // 释放资源            bufferedReader.close();            inputStreamReader.close();            inputStream.close();            inputStream = null;            conn.disconnect();            return buffer.toString();        } catch (ConnectException ce) {            log.error("连接超时:{}", ce);        } catch (Exception e) {            log.error("https请求异常:{}", e);        }        return null;    }

/**     * 获取接口访问凭证     *     * @param appid 凭证     * @param appsecret 密钥     * @return     *//*    public static Token getToken(String appid, String appsecret) {        Token token = null;        String requestUrl = ConfigUtil.TOKEN_URL.replace("APPID", appid).replace("APPSECRET", appsecret);        // 发起GET请求获取凭证        JSONObject jsonObject = JSONObject.fromObject(httpsRequest(requestUrl, "GET", null));

if (null != jsonObject) {            try {                token = new Token();                token.setAccessToken(jsonObject.getString("access_token"));                token.setExpiresIn(jsonObject.getInt("expires_in"));            } catch (JSONException e) {                token = null;                // 获取token失败                log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));            }        }        return token;    }    public static String urlEncodeUTF8(String source){        String result = source;        try {            result = java.net.URLEncoder.encode(source,"utf-8");        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        }        return result;    }*/}
 
重点:封装参数调用统一下单接口,生成prepay_id(预支付订单Id)
/** * 微信支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return  */private String generateOrderInfoByWeiXinPay(String orderId, float actualPay,HttpServletRequest request,HttpServletResponse response) throws Exception{   String notify_url = propertiesService.WEI_XIN_NOTIFY_URL;//回调地址   String uuid = IdGen.uuid();   System.out.print("uuid" + uuid);   SortedMap<String, String> signParams = new TreeMap<String, String>();   signParams.put("appid", ConstantUtil.APP_ID);//app_id   signParams.put("body","测试");//商品参数信息   signParams.put("mch_id", ConstantUtil.PARTNER);//微信商户账号   signParams.put("nonce_str", uuid);//32位不重复的编号   signParams.put("notify_url", notify_url);//回调页面   signParams.put("out_trade_no", orderId);//订单编号   signParams.put("spbill_create_ip",request.getRemoteAddr() );//请求的实际ip地址   signParams.put("total_fee","1");//支付金额 单位为分   signParams.put("trade_type", "APP");付款类型为APP   String sign = PayCommonUtil.createSign("UTF-8", signParams);//生成签名   signParams.put("sign", sign);   signParams.remove("key");//调用统一下单无需key(商户应用密钥)   String requestXml = PayCommonUtil.getRequestXml(signParams);//生成Xml格式的字符串   String result = CommonUtil.httpsRequest   (ConstantUtil.UNIFIED_ORDER_URL, "POST", requestXml);//以post请求的方式调用统一下单接口
(注:ConstantUtil.UNIFIED_ORDER_URL=https://api.mch.weixin.qq.com/pay/unifiedorder;
 
返回的result成功结果取出prepay_id:
Map map = XMLUtil.doXMLParse(result);String return_code=(String) map.get("return_code");String prepay_id =null;String returnSign=null;String returnNonce_str=null;if (return_code.contains("SUCCESS")){   prepay_id=(String) map.get("prepay_id");//获取到prepay_id}StringBuffer weiXinVo=new StringBuffer();long currentTimeMillis = System.currentTimeMillis();//生成时间戳long second = currentTimeMillis / 1000L;(转换成秒)String seconds = String.valueOf(second).substring(0, 10);(截取前10位)SortedMap<String, String> signParam = new TreeMap<String, String>();signParam.put("appid", ConstantUtil.APP_ID);//app_idsignParam.put("partnerid", ConstantUtil.PARTNER);//微信商户账号signParam.put("prepayid", prepay_id);//预付订单idsignParam.put("package", "Sign=WXPay");//默认sign=WXPaysignParam.put("noncestr", uuid);//自定义不重复的长度不长于32位signParam.put("timestamp",seconds);//北京时间时间戳String signAgain = PayCommonUtil.createSign("UTF-8", signParam);//再次生成签名signParams.put("sign", signAgain);weiXinVo.append("appid=").append(ConstantUtil.APP_ID).append("&partnerid=").append(ConstantUtil.PARTNER).append("&prepayid=").append(prepay_id).append("&package=Sign=WXPay").append("&noncestr=").append(uuid).append("&timestamp=").append(seconds).append("&sign=").append(signAgain);//拼接参数返回给移动端return weiXinVo.toString();
 
 
(注:感谢IOS团队的联调支持)
 
 
时间: 2024-10-07 05:23:12

微信APP支付(Java后台生成签名具体步骤)的相关文章

微信APP支付-java后台实现

不说废话,直接上代码 先是工具类(注意签名时要排序): 1 import java.io.BufferedReader; 2 import java.io.ByteArrayInputStream; 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.InputStream; 6 import java.io.InputStreamReader; 7 import java.io.OutputStre

支付宝APP支付(Java后台生成签名具体步骤)

/** *支付宝支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return */ private String getOrderInfoByAliPay(String orderId,float actualPay) { //回调页面 String ali_call_back_url = propertiesService.ALI_CALL_BACK_URL; String seller_id = propertiesService.

支付宝APP支付,Java后台生成的签名的过程

/** *支付宝支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return */ private String getOrderInfoByAliPay(String orderId,float actualPay) { //回调页面 String ali_call_back_url = propertiesService.ALI_CALL_BACK_URL; String seller_id = propertiesService.

支付宝APP支付之Java后台生成签名具体步骤

/** *支付宝支付 * @param orderId 订单编号 * @param actualPay 实际支付金额 * @return */ private String getOrderInfoByAliPay(String orderId,float actualPay) { //回调页面 String ali_call_back_url = propertiesService.ALI_CALL_BACK_URL; String seller_id = propertiesService.

微信App支付(JAVA端)

low话不多说,直接上代码! 红色框框是核心jar包! 黑色框框是获取客户端的IP地址工具类! 紫色框框是微信支付的流程代码! 蓝色框框是订单实体类! 由于小黑我技术不咋地,所以以下代码仅供参考,copy过去后是跑不起来的,不过可以经过改动代码使其跑起来,反正思路是这样的! (代码处如有发现错误的自行矫正修改,例如没有对事务控制,逻辑有误等!! 还有,大神看也,不喜勿喷) 此处代码就是用来调用微信支付SDK的,然后SDK会返回几个参数,这几个参数就是给APP端(IOS/安卓)调起支付的参数!! 

支付宝app支付java后台流程及原理分析

java版支付宝app支付流程及原理分析 本实例是基于springmvc框架编写     一.流程步骤         1.执行流程           当手机端app(就是你公司开发的app)在支付页面时,调起服务端(后台第1个创建订单接口)接口,后台把需要调起支付宝支付的参数返回给手机端,手机端拿到         这些参数后,拉起支付宝支付环境完成支付,完成支付后会调异步通知(第2个接口),此时需要给支付宝返回成功或者失败信息,成功后会调用同步通知(第3个接口)         返回支付成

微信app支付python代码实现

微信app支付python代码(使用weixin-python==0.5.4) 微信app支付python代码(python2) python3应该差不多, 官方文档: https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1 业务流程: 商户系统和微信支付系统主要交互说明: #步骤1:用户在商户APP中选择商品,提交订单,选择微信支付. 用户在app页面选择商品,确定数量,提交订单,提供必要的参数 app支付需要的前端参数 1

.Net后台实现微信APP支付

上一节分享了微信小程序支付的后台,这一节来分享一下微信APP支付的后台.微信APP支付和微信小程序差别不大,微信APP支付后台不需要微信登录凭证.后台下单时交易类型(trade_type)不再是"JSAPI",而是"APP".商户后台传递给支付端的下单参数也有所不同.由于微信小程序支付和APP支付使用的APPID不同,索性直接写了两套支付,不再在代码里区分究竟该使用小程序支付的配置参数还是APP支付的参数. 官方是这样介绍的 具体实现: 新建AppPayConfig

微信app支付(android端+java后台)

本文讲解使用微信支付接口完成在android开发的原生态app中完成微信支付功能, 文章具体讲解了前端android如何集成微信支付功能以及后台如何组装前端需要支付信息, 话不多话, 具体看文章内容吧00:00 / 07:03正常 本实例项目运行条件: 开发环境: [Android Studio] 到微信开放平台注册帐号并且创建移动应用 https://open.weixin.qq.com/cgi-bin/frame?t=home/app_tmpl&lang=zh_CN Column 1 Col