微信支付

一、微信支付的几种方式

  刷卡支付:“我”--》“钱包”--》“付款”,扫码机器扫描用户二维码,完成支付

  公众号支付:微信公众号内部完成支付功能

  扫码支付:微信打开扫一扫,扫描商户二维码,手动转账

  APP支付:商户内部集成微信SDK,点击支付跳转微信内部完成支付

二、APP支付实现

 A、准备工作

  条件:不需要APP开发结束后才申请,开发期间就可以申请

  1、登录“微信开放平台”:https://open.weixin.qq.com ,认证开发者资质,个人无法认证,需要企业信息。认证大概时间一周

  2、开发者认证通过后,创建应用,需要提供应用Logo、包名(包名与其它应用不能重复),审核大概时间一周;

    审核通过后,会获得微信分享功能,微信支付功能需要另外申请;

    微信分享功能:包名+应用签名

  3、申请微信支付,提供APP截图:首页、支付页、详情页、关于我们、商品页;审核比较严,预留一周时间;

  4、审核通过后,账户邮箱会收到“微信商户平台”账户信息,通过提供的商户平台账号和密码登录商户平台,登录需下载安全证书;

     获取APP秘钥,APP秘钥需要保存好,忘记只能重新获取。

     

  

  5、相关参数整理

    应用签名:微信开放平台创建应用后,生成应用签名,用于 “微信分享”功能
    appid:微信开放平台创建应用后,生成appid,APP的唯一身份标识,“微信分享”、“微信支付”都会使用,无法修改

    AppSecret:微信开放平台创建应用后,验证身份后,生成AppSecret,需好好保存,后期登录无法查看,只能重新生成

    应用包名:包名必须唯一,不能与其它任何已登录应用平台的程序的包路径重复,否则审核不通过

    商户号:”微信支付“申请通过后,收到的邮件中,用于微信支付功能

    APP密钥:来源参考目录4,主要用于“微信支付”API中sign的获取

    

 B、开发实现

  1、统一下单

    微信支付参数配置类

 * @author shb
 *
 */
public class WeiXinConfig {
    
    /**
     * APPId
     */
    public static String appId = "****";
    
    /**
     * 微信支付商户号
     */
    public static String mchId = "****";
    
    /**
     * 签名秘钥
     */
    public static String key = "****";
    
    /**
     * AppSecret
     */
    public static String appSecret = "****";
    
    /**
     * 交易类型
     */
    public static String tradsType = "APP";
    
    /**
     * 如果设置--不能使用信用卡支付
     */
    public static String limitPay = "no_credit";
    
    /**
     * 微信支付回调地址
     */
    public static String notifyUrl = "****";

   /**
    * 统一下单请求地址
    */
    public static String unifiedOrderUrl = "****";

}

    统一下单参数实体

import com.guduo.common.utils.UUIDUitl;

/**
 * 统一下单参数
 * @author shb
 *
 */
public class UnifiedOrderParams {

    //初始化参数
    public UnifiedOrderParams() {
        setAppid(WeiXinConfig.appId);//APPId
        setMchid(WeiXinConfig.mchId);//商户号
        setNoncestr(UUIDUitl.generateUUID());//随机数
        setTradeType(WeiXinConfig.tradsType);//支付类型
        setNotifyUrl(WeiXinConfig.notifyUrl);//支付回调地址
    }
    
    /**
     * 应用id
     */
    private String appid;
    
    /**
     * 商户
     */
    private String mchid;
    
    /**
     * 随机字符串
     */
    private String noncestr;
    
    /**
     * 签名
     */
    private String sign;
    
    /**
     * 商品描述
     */
    private String body;
    
    /**
     * 商品订单号
     */
    private String outTradeNo;
    
    /**
     * 总金额
     */
    private int totalFee;
    
    /**
     * 终端ip
     */
    private String spdillCreateIp;
    
    /**
     * 回调地址
     */
    private String notifyUrl;
    
    /**
     * 交易类型
     */
    private String tradeType;

    public String getAppid() {
        return appid;
    }

    public void setAppid(String appid) {
        this.appid = appid;
    }

    public String getMchid() {
        return mchid;
    }

    public void setMchid(String mchid) {
        this.mchid = mchid;
    }

    public String getNoncestr() {
        return noncestr;
    }

    public void setNoncestr(String noncestr) {
        this.noncestr = noncestr;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getOutTradeNo() {
        return outTradeNo;
    }

    public void setOutTradeNo(String outTradeNo) {
        this.outTradeNo = outTradeNo;
    }

    public int getTotalFee() {
        return totalFee;
    }

    public void setTotalFee(int totalFee) {
        this.totalFee = totalFee;
    }

    public String getSpdillCreateIp() {
        return spdillCreateIp;
    }

    public void setSpdillCreateIp(String spdillCreateIp) {
        this.spdillCreateIp = spdillCreateIp;
    }

    public String getNotifyUrl() {
        return notifyUrl;
    }

    public void setNotifyUrl(String notifyUrl) {
        this.notifyUrl = notifyUrl;
    }

    public String getTradeType() {
        return tradeType;
    }

    public void setTradeType(String tradeType) {
        this.tradeType = tradeType;
    }
    
}
统一下单:请求参数封装xml
import org.apache.commons.codec.digest.DigestUtils;
import com.guduo.common.utils.UUIDUitl;
import com.guduo.common.weixinPay.config.UnifiedOrderReqParams;
import com.guduo.common.weixinPay.config.WxConfig;

/**
 * 统一下单:请求参数封装xml
 *     1、
 * @author shb
 *
 */
public class UnifiedOrderParamsXml {
    
    /**
     * 封装统一下单请求对象
     * @param ip
     * @param type
     * @param totalFee
     * @return
     */
    public static UnifiedOrderReqParams getParams(String ip,String type,int totalFee)
    {
        UnifiedOrderReqParams params = new UnifiedOrderReqParams();
        params.setBody(type);
        params.setOutTradeNo(UUIDUitl.generateUUID());
        params.setSpdillCreateIp(ip);
        params.setTotalFee(totalFee);
        //调用sign方法,获取sign
        params.setSign(getUnifiedOrderSign(params));
        return params;
    }
    
    /**
     * 统一下单:获取sign
     * @param params:
     * @return
     */
    public static String getUnifiedOrderSign(UnifiedOrderReqParams params)
    {
        //获取请求字段排序
        String stringA = new UnifiedOrderSignXml().getBuffer(params);
        //拼接API秘钥
        String stringSignTemp = stringA+"&key="+WxConfig.key;
        String sign = DigestUtils.md5Hex(stringSignTemp).toUpperCase();
        return sign;
    }
    
    /**
     * 统一下单请求参数封装
     * @param params
     * @return
     */
    public static String getXmlInfo(UnifiedOrderReqParams params)
    {
        //封装xml请求
        StringBuilder sb = new StringBuilder();  
        sb.append("<xml>");
        //封装应用id
        sb.append("<appid>");
        sb.append("<![CDATA[");
        sb.append(params.getAppid());
        sb.append("]]>");
        sb.append("</appid>");

        //封装商品描述
        sb.append("<body>");
        sb.append("<![CDATA[");
        sb.append(params.getBody());
        sb.append("]]>");
        sb.append("</body>");
        
        //封装商户号
        sb.append("<mch_id>");
        sb.append("<![CDATA[");
        sb.append(params.getMchid());
        sb.append("]]>");
        sb.append("</mch_id>");
        
        //封装随机字符串
        sb.append("<nonce_str>");
        sb.append("<![CDATA[");
        sb.append(params.getNoncestr());
        sb.append("]]>");
        sb.append("</nonce_str>");
        
        //封装通知地址
        sb.append("<notify_url>");
        sb.append("<![CDATA[");
        sb.append(params.getNotifyUrl());
        sb.append("]]>");
        sb.append("</notify_url>");
        
        //封装商户订单号
        sb.append("<out_trade_no>");
        sb.append("<![CDATA[");
        sb.append(params.getOutTradeNo());
        sb.append("]]>");
        sb.append("</out_trade_no>");
        
        //封装终端ip
        sb.append("<spbill_create_ip>");
        sb.append("<![CDATA[");
        sb.append(params.getSpdillCreateIp());
        sb.append("]]>");
        sb.append("</spbill_create_ip>");
        
        //封装总金额
        sb.append("<total_fee>");
        sb.append("<![CDATA[");
        sb.append(params.getTotalFee());
        sb.append("]]>");
        sb.append("</total_fee>");
        
        //封装交易类型
        sb.append("<trade_type>");
        sb.append("<![CDATA[");
        sb.append(params.getTradeType());
        sb.append("]]>");
        sb.append("</trade_type>");
        
        //封装签名
        sb.append("<sign>");
        sb.append("<![CDATA[");
        sb.append(params.getSign());
        sb.append("]]>");
        sb.append("</sign>");
        
        sb.append("</xml>");
        return sb.toString();
    }
}

   

统一下单:封装sign
/**
 * 统一下单:封装sign
 * @author shb
 *
 */
public class UnifiedOrderSignXml {
    
    /**
     * 按照参数名ASCII字典排序请求字段
     * @param params
     * @return
     */
    public String getBuffer(UnifiedOrderReqParams params)
    {
        //拼接请求字符串
        StringBuffer sb = new StringBuffer();
        //封装应用id
        sb.append("appid=");
        sb.append(params.getAppid());
        sb.append("&");

        //封装商品描述
        sb.append("body=");
        sb.append(params.getBody());
        sb.append("&");
        
        //封装商户号
        sb.append("mch_id=");
        sb.append(params.getMchid());
        sb.append("&");
        
        //封装随机字符串
        sb.append("nonce_str=");
        sb.append(params.getNoncestr());
        sb.append("&");
        
        //封装通知地址
        sb.append("notify_url=");
        sb.append(params.getNotifyUrl());
        sb.append("&");
        
        //封装商户订单号
        sb.append("out_trade_no=");
        sb.append(params.getOutTradeNo());
        sb.append("&");
        
        /*//封装签名
        sb.append("sign=");
        sb.append(params.getSign());
        sb.append("&");*/
        
        //封装终端ip
        sb.append("spbill_create_ip=");
        sb.append(params.getSpdillCreateIp());
        sb.append("&");
        
        //封装总金额
        sb.append("total_fee=");
        sb.append(params.getTotalFee());
        sb.append("&");
        
        //封装交易类型
        sb.append("trade_type=");
        sb.append(params.getTradeType());
        return sb.toString();
    }
}

 

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.xml.sax.InputSource;

/**
 * xml解析工具:针对微信通讯参数要求
 * @author shb
 *
 */
public class XmlUtil {
    
    /**
     * 获取子节点内容
     * @param root
     * @param elementName
     * @return
     */
    public static String getChildElement(Element root,String elementName)
    {
        Element element = root.getChild(elementName);
        return element.getText();
    }
    
    /**
     * jdom解析xml
     * @param is
     * @return
     */
    public static Map<String, String> jdomUtil(InputSource is)
    {
        Map<String, String> map = new HashMap<String, String>();
        try{
            // 创建一个新的SAXBuilder
            SAXBuilder sb = new SAXBuilder();
            // 通过输入源构造一个Document
            Document doc = sb.build(is);
            Element root = doc.getRootElement();// 指向根节点
            @SuppressWarnings("unchecked")
            List<Element> es = root.getChildren();
            if (es != null && es.size() != 0) {
                for (Element element : es) {
                    map.put(element.getName(), element.getText());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }
}
/**
 * 微信支付工具类
 * @author shb
 *
 */
public class WxPayUtil {
    
    /**
     * 调用微信统一下单接口
     * @param ip:请求终端ip
     * @param orderType:交易类型
     * @param totalFee:交易金额,单位为分
     * @return
     */
    public static Map<String,String> unifiedOrderRequest(String ip,String orderType,int totalFee)
    {
        CloseableHttpClient httpclient = HttpClients.createDefault(); 
        Map<String, String> map = new HashMap<String, String>();
        //获取封装好的请求参数
        UnifiedOrderReqParams params = UnifiedOrderParamsXml.getParams(ip, orderType, totalFee);
        try {
            HttpPost httppost = new HttpPost(WxConfig.unifiedOrderUrl);  
            StringEntity entity = new StringEntity(UnifiedOrderParamsXml.getXmlInfo(params), "utf-8");
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            httppost.setEntity(entity);
            CloseableHttpResponse result = httpclient.execute(httppost);
            int code = result.getStatusLine().getStatusCode();
            System.out.println(code);
            String message = EntityUtils.toString(result.getEntity(),"UTF-8");
            StringReader sr = new StringReader(message);  
            InputSource is = new InputSource(sr);  
            System.out.println(message);
            map = XmlUtil.jdomUtil(is);
            for (Map.Entry<String, String> entry : map.entrySet()) {  
                System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());  
            }  
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            // 关闭连接,释放资源    
            try {  
                httpclient.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            } 
        }
        return map;
    }
}

 

 

/**
 * 支付回调返回结果
 * @author shb
 *
 */
public class NotifyXml {
    
    /**
     * 解析回调返回的数据
     * @param body
     * @return
     */
    public static Map<String, String> getNotifyParams(String body)
    {
        Map<String, String> params= new HashMap<String, String>();
        Reader io = new StringReader(body);
        try {
            Document doc = new SAXBuilder().build(io);
            Element root = doc.getRootElement();
            String resultCode = XmlUtil.getChildElement(root, "result_code");//支付结果
            String returnMsg = XmlUtil.getChildElement(root, "return_msg");//返回信息,如非空,为错误原因
            String orderNo = XmlUtil.getChildElement(root, "out_trade_no");//系统订单号
            String transactionId = XmlUtil.getChildElement(root, "transaction_id");//微信订单号
            String returnCode = XmlUtil.getChildElement(root, "return_code");//请求结果
            
            //封装
            params.put("resultCode", resultCode);
            params.put("returnMsg",returnMsg );
            params.put("orderNo",orderNo );
            params.put("transactionId",transactionId );
            params.put("returnCode",returnCode );
            
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return params;
    }
    
    /**
     * 封装回调返回结果
     * @param body
     * @return
     */
    public static String notifyReback()
    {
        StringBuffer reback = new StringBuffer();
        reback.append("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
        return reback.toString();
    }
    public static void main(String[] args) {
        System.out.println(notifyReback());
    }
}

 

posted @ 2016-10-29 13:49  刘广平  阅读(212)  评论(0编辑  收藏  举报