微信App支付(一)

来源:互联网 发布:java泛型方法调用 编辑:程序博客网 时间:2024/04/30 14:00

微信app支付签名
在这里记录自己微信app支付(java后台)中,遇到的问题,方便日后查阅,也方便有需要的小伙伴。
微信app支付流程:组合业务参数签名,然后发送给微信统一下单接口,得到微信返回的预支付id:prepay_id再二次签名后把参数给app端,调起微信支付。

parameters.put("appid", WeixinConfig.appid);//微信分配的公众账号ID(企业号corpid即为此appId),例如:wxd678efh567hg6787parameters.put("mch_id", WeixinConfig.mch_id); // 微信支付分配的商户号parameters.put("nonce_str", nonce_str);// 随机字符串:数字+大写字母的组合,32位parameters.put("body", WeixinConfig.body); // 商品或支付单简要描述,格式:需传入应用市场上的APP名字-实际商品名称,天天爱消除-游戏充值。parameters.put("out_trade_no", out_trade_no);// 商户系统内部的订单号parameters.put("total_fee", total_fee);// 总金额 单位为分,不能带小数parameters.put("notify_url", WeixinConfig.notify_url);// 接收微信支付异步通知回调地址parameters.put("trade_type", WeixinConfig.trade_type);// 交易类型:APPparameters.put("spbill_create_ip", WeixinConfig.spbill_create_ip);// APP和网页支付提交[用户端ip],Native支付填调用微信支付API的机器IP。

以上是第一次签名必须传的一些参数,如果业务有需求还可以参考微信支付文档的选填参数列表。

public class WXSignUtils {    // http://mch.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3    // 商户Key:改成公司申请的即可    // 32位密码设置地址:http://www.sexauth.com/ jdex1hvufnm1sdcb0e81t36k0d0f15nc    /**     * 微信支付签名算法sign     * @param characterEncoding     * @param parameters     * @return     */    public static String createSign(String characterEncoding, Map<String, String> parameters) {        List<String> keys = new ArrayList<String>(parameters.keySet());        Collections.sort(keys);        String prestr = "";        for (int i = 0; i < keys.size(); i++) {            String key = keys.get(i);            String value = parameters.get(key);            if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符                prestr = prestr + key + "=" + value;            } else {                prestr = prestr + key + "=" + value + "&";            }        }        prestr = prestr + "&" + "key=" + WeixinConfig.private_key;        System.out.println("字符串拼接后是:" + prestr.toString());        String sign = MD5Util.MD5Encode(prestr.toString(), characterEncoding).toUpperCase();        return sign;    }}以上是签名方法,里面的MD5Util就是一般的MD5加密, Collections.sort(keys)这个排序一定要排序,不然签名错误。Key就是api密钥,是当时设置在微信平台里的32位密钥,这个密钥设置好以后就无法再查看,所以一定要本地保存。
    /**     * 构造xml参数     * @param xml     * @return     */    public static String xmlInfo(Unifiedorder unifiedorder){        //构造xml参数的时候,至少包含所有必传参数        /*         * <xml>               <appid>wx2421b1c4370ec43b</appid>               <attach>支付测试</attach>               <body>JSAPI支付测试</body>               <mch_id>10000100</mch_id>               <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>               <notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>               <openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>               <out_trade_no>1415659990</out_trade_no>               <spbill_create_ip>14.23.150.211</spbill_create_ip>               <total_fee>1</total_fee>               <trade_type>JSAPI</trade_type>               <sign>0CB01533B8C1EF103065174F50BCA001</sign>            </xml>         */        if(unifiedorder!=null){            StringBuffer bf = new StringBuffer();            bf.append("<xml>");            bf.append("<appid><![CDATA[");            bf.append(unifiedorder.getAppid());            bf.append("]]></appid>");            bf.append("<mch_id><![CDATA[");            bf.append(unifiedorder.getMch_id());            bf.append("]]></mch_id>");            bf.append("<nonce_str><![CDATA[");            bf.append(unifiedorder.getNonce_str());            bf.append("]]></nonce_str>");            bf.append("<sign><![CDATA[");            bf.append(unifiedorder.getSign());            bf.append("]]></sign>");            bf.append("<body><![CDATA[");            bf.append(unifiedorder.getBody());            bf.append("]]></body>");            /*bf.append("<detail><![CDATA[");            bf.append(unifiedorder.getDetail());            bf.append("]]></detail>");            bf.append("<attach><![CDATA[");            bf.append(unifiedorder.getAttach());            bf.append("]]></attach>");*/            bf.append("<out_trade_no><![CDATA[");            bf.append(unifiedorder.getOut_trade_no());            bf.append("]]></out_trade_no>");            bf.append("<total_fee><![CDATA[");            bf.append(unifiedorder.getTotal_fee());            bf.append("]]></total_fee>");            bf.append("<spbill_create_ip><![CDATA[");            bf.append(unifiedorder.getSpbill_create_ip());            bf.append("]]></spbill_create_ip>");            /*bf.append("<time_start><![CDATA[");            bf.append(unifiedorder.getTime_start());            bf.append("]]></time_start>");            bf.append("<time_expire><![CDATA[");            bf.append(unifiedorder.getTime_expire());            bf.append("]]></time_expire>");*/            bf.append("<notify_url><![CDATA[");            bf.append(unifiedorder.getNotify_url());            bf.append("]]></notify_url>");            bf.append("<trade_type><![CDATA[");            bf.append(unifiedorder.getTrade_type());            bf.append("]]></trade_type>");            bf.append("</xml>");            return bf.toString();        }        return "";    }

以上是就是微信以XML的形式发送请求的包装。

    public static String httpsRequest(String requestUrl, String requestMethod, String output) {        try{            URL url = new URL(requestUrl);            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();            connection.setDoOutput(true);            connection.setDoInput(true);            connection.setUseCaches(false);            connection.setRequestMethod(requestMethod);            if (null != output) {                OutputStream outputStream = connection.getOutputStream();                outputStream.write(output.getBytes("UTF-8"));                outputStream.close();            }            // 从输入流读取返回内容            InputStream inputStream = connection.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;            connection.disconnect();            return buffer.toString();        }catch(Exception ex){            ex.printStackTrace();        }        return "";    }

以上就是把之前打包好的xml(output)发送到微信统一下单接口requestUrl,requestMethod为post请求。签名没问题,微信会返回预支付id:prepay_id

    finalpackage.put("appid", WeixinConfig.appid); // appid    finalpackage.put("timestamp", timestamp); // 时间戳 十位    finalpackage.put("noncestr", nonce_string); // 随机字符串    finalpackage.put("package", "Sign=WXPay"); // 固定值    finalpackage.put("partnerid", WeixinConfig.mch_id); // 商户id(微信商户平台获取)    finalpackage.put("prepayid", prepay_id); // 第一次请求微信,成功后,返回的参数

再把这六个参数用同样的方法签名,把得到的签名和上述参与签名的参数传给app端。
然后app端就可以调起微信支付了。

1 0
原创粉丝点击