zoukankan      html  css  js  c++  java
  • 微信支付---统一下单

    微信支付---统一下单

    身为一个码农,总是需要要学习一些新的知识来丰富自己的羽翼,让自己能够在程序员的道路上走的更远,更稳。

    最近在研究关于微信支付的接口调用:微信支付开发文档

    接口连接:URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

    请求参数、返回字段、错误码、请阅读:统一下单开发文档

     请求参数格式和信息例:

    <xml>
       <return_code><![CDATA[SUCCESS]]></return_code>//返回状态码
       <return_msg><![CDATA[OK]]></return_msg>//返回信息
       <appid><![CDATA[wx2421b1c4370ec43b]]></appid>//公众账号ID
       <mch_id><![CDATA[10000100]]></mch_id>//商户号
       <device_info><![CDATA[1000]]></device_info>//设备号
       <nonce_str><![CDATA[TN55wO9Pba5yENl8]]></nonce_str>//随机字符串
       <sign><![CDATA[BDF0099C15FF7BC6B1585FBB110AB635]]></sign>//签名
       <result_code><![CDATA[SUCCESS]]></result_code>//业务结果
       <openid><![CDATA[oUpF8uN95-Ptaags6E_roPHg7AG0]]></openid>//用户标识
       <is_subscribe><![CDATA[Y]]></is_subscribe>//是否关注公众账号
       <trade_type><![CDATA[MICROPAY]]></trade_type>//交易类型
       <bank_type><![CDATA[CCB_DEBIT]]></bank_type>//付款银行
       <total_fee>1</total_fee>//订单金额——单位分
       <fee_type><![CDATA[CNY]]></fee_type>//货币种类
       <transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>//微信支付订单号
       <out_trade_no><![CDATA[1415757673]]></out_trade_no>//商户订单号
       <attach><![CDATA[订单额外描述]]></attach>//附加数据
       <time_end><![CDATA[20141111170043]]></time_end>//支付完成时间
       <trade_state><![CDATA[SUCCESS]]></trade_state>//交易状态
    </xml>

    统一下订单发起请求:

    package com.daat.front.pay.web.actions;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Random;
    import java.util.Set;
    import java.util.SortedMap;
    import java.util.TreeMap;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    
    import com.daat.front.base.web.actions.BaseAction;
    import com.daat.front.base.web.tools.WebUtils;
    import com.daat.front.pay.sdk.common.RandomStringGenerator;
    import com.daat.front.pay.sdk.common.Util;
    import com.daat.front.pay.web.util.WechatURLs;
    import com.daat.front.weixin.sdk.base.domain.constant.WXAppConstant;
    import com.daat.front.weixin.sdk.base.exception.WXException;
    import com.daat.front.weixin.sdk.util.MD5Util;
    import com.daat.front.weixin.sdk.util.TenpayUtil;
    import com.daat.front.weixin.sdk.util.WXHttpUtil; 
    
    public class pay extends BaseAction {
    
        
        public static void main(String[] args) {
            
        }
        
        
        /**
         * 商户发起生成预付单请求
         * @return
         */
        public String unifiedOrder(){
            Map map = WebUtils.getParameterMap();//获取前台数据
            String appid = WXAppConstant.APP_ID;//appid
            String mch_id = WXAppConstant.MCH_ID;//微信支付商户号
            String nonce_str =getRandomStringByLength(8);//随机码
            String body = map.get("bodyName").toString();//商品描述
            String out_trade_no = map.get("outTradeNo").toString();//商品订单号
            String product_id = map.get("productId").toString();//商品编号
            String total_fee = (int)(Float.valueOf(map.get("totalFee").toString()).floatValue()*100)+"";//总金额 分
            String time_start =getCurrTime();//交易起始时间(订单生成时间非必须)
            String trade_type = "NATIVE";//公众号支付
            String notify_url = "http://"+"域名"+"/"+"项目名"+"回调地址.do";//回调函数
            SortedMap<String, String> params = new TreeMap<String, String>();
            params.put("appid", appid);
            params.put("mch_id", mch_id);
            params.put("device_info", "WEB"); //设备号
            params.put("nonce_str", nonce_str);
            params.put("body", body);//商品描述
            params.put("out_trade_no", out_trade_no);
            params.put("product_id", product_id);
            params.put("total_fee", total_fee);
            params.put("time_start", time_start);
            params.put("trade_type", trade_type);
            params.put("notify_url", notify_url); 
            String sign = "";//签名(该签名本应使用微信商户平台的API证书中的密匙key,但此处使用的是微信公众号的密匙APP_SECRET)
            sign = getSign(params);
            //参数xml化
            String xmlParams = parseString2Xml(params,sign);
            //判断返回码
            String jsonStr = "";
            try {
                jsonStr = WXHttpUtil.doPost(WechatURLs.prepayOrderUrl, xmlParams);// 调用支付接口
            } catch (WXException e) {
                e.printStackTrace();
            }
            if (jsonStr.indexOf("FAIL") == -1 && jsonStr.trim().length() > 0) {//成功
                model.put("result_code", "SUCCESS");
            } else {//失败
                try {
                    Map resultMap = new HashMap();
                    resultMap = getMapFromXML(jsonStr);// 解析返回值
                    if(resultMap!=null&&"SUCCESS".equals(resultMap.get("return_code").toString())){
                        //通信接口二级错误
                        model.put("result_code", resultMap.get("result_code"));
                        model.put("error_code", resultMap.get("err_code"));
                        model.put("result_msg", resultMap.get("err_code_des"));
                    }else{
                        //通信接口一级错误
                        model.put("result_code", "FAIL");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return "success";
        }
        
        /**
         * 参数进行XML化
         * @param map,sign
         * @return
         */
        public static String parseString2Xml(Map<String, String> map,String sign){
            StringBuffer sb = new StringBuffer();
            sb.append("<xml>");
            Set es = map.entrySet();
            Iterator iterator = es.iterator();
            while(iterator.hasNext()){
                Map.Entry entry = (Map.Entry)iterator.next();
                String k = (String)entry.getKey();
                String v = (String)entry.getValue();
                sb.append("<"+k+">"+v+"</"+k+">");
            }
            sb.append("<sign>"+sign+"</sign>");
            sb.append("</xml>");
            return sb.toString();
        }
        /**
         * 获取签名 md5加密(微信支付必须用MD5加密)
         * 获取支付签名
         * @param params
         * @return
         */
        public static String getSign(SortedMap<String, String> params){
            String sign = null;
            StringBuffer sb = new StringBuffer();
            Set es = params.entrySet();
            Iterator iterator = es.iterator();
            while(iterator.hasNext()){
                Map.Entry entry = (Map.Entry)iterator.next();
                String k = (String)entry.getKey();
                String v = (String)entry.getValue();
                if (null != v && !"".equals(v) && !"sign".equals(k)&& !"key".equals(k)) {
                    sb.append(k+"="+v+"&");
                }
            }
            sb.append("key="+WXAppConstant.APP_SECRET);
            sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
            return sign;
        }
        public static Map<String,Object> getMapFromXML(String xmlString) throws ParserConfigurationException, IOException, SAXException {
            //这里用Dom的方式解析回包的最主要目的是防止API新增回包字段
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            InputStream is =  Util.getStringStream(xmlString);
            Document document = builder.parse(is);
            //获取到document里面的全部结点
            NodeList allNodes = document.getFirstChild().getChildNodes();
            Node node;
            Map<String, Object> map = new HashMap<String, Object>();
            int i=0;
            while (i < allNodes.getLength()) {
                node = allNodes.item(i);
                if(node instanceof Element){
                    map.put(node.getNodeName(),node.getTextContent());
                }
                i++;
            }
            return map;
        }
        /**
         * 获取一定长度的随机字符串
         * @param length 指定字符串长度
         * @return 一定长度的字符串
         */
        public static String getRandomStringByLength(int length) {
            String base = "abcdefghijklmnopqrstuvwxyz0123456789";
            Random random = new Random();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < length; i++) {
                int number = random.nextInt(base.length());
                sb.append(base.charAt(number));
            }
            return sb.toString();
        }
        /**
         * 获取当前时间 yyyyMMddHHmmss
         * @return String
         */ 
        public static String getCurrTime() {
            Date now = new Date();
            SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            String s = outFormat.format(now);
            return s;
        }
    }

    预付单成功返回信息

    测试支付返回信息:
    <xml>
    <return_code><![CDATA[SUCCESS]]></return_code>
    <return_msg><![CDATA[OK]]></return_msg>
    <appid><![CDATA[wx13842d984810c06b]]></appid>
    <mch_id><![CDATA[1355962702]]></mch_id>
    <device_info><![CDATA[WEB]]></device_info>
    <nonce_str><![CDATA[uUaaXpCCnERVXE6R]]></nonce_str>
    <sign><![CDATA[E9A1087F5A0C5F8EBCF26F3C7A842022]]></sign>
    <result_code><![CDATA[SUCCESS]]></result_code>
    <openid><![CDATA[oD7UhwESE3wh22Uz6PqdCXRyR-pA]]></openid>
    <is_subscribe><![CDATA[Y]]></is_subscribe>
    <trade_type><![CDATA[NATIVE]]></trade_type>
    <bank_type><![CDATA[CFT]]></bank_type>
    <total_fee>2</total_fee>
    <fee_type><![CDATA[CNY]]></fee_type>
    <transaction_id><![CDATA[4002722001201610247590660332]]></transaction_id>
    <out_trade_no><![CDATA[1477296302523]]></out_trade_no>
    <attach><![CDATA[]]></attach>
    <time_end><![CDATA[20161024155820]]></time_end>
    <trade_state><![CDATA[SUCCESS]]></trade_state>
    <cash_fee>2</cash_fee>
    </xml>
  • 相关阅读:
    keepalive高可用集群(nginx)
    nginx负载均衡
    linux-------lnmp安装
    nginx编译安装
    Django+MySQL安装配置详解(Linux)[更新为1.8.2版]
    linux性能监控——CPU、Memory、IO、Network
    linux 时钟时间,用户CPU时间,系统CPU时间 .
    指针用作传出参数时,需要二级指针
    僵尸进程&孤儿进程
    XHProf是一个分层PHP性能分析工具。
  • 原文地址:https://www.cnblogs.com/fxwl/p/6000094.html
Copyright © 2011-2022 走看看