微信APP支付

来源:互联网 发布:编程入门教学视频 编辑:程序博客网 时间:2024/04/30 13:14

微信APP支付

说明:此微信支付前端使用的是Angularjs,ionic ,
支付插件是cordova-plugin-wechat(插件下载地址:https://github.com/xu-li/cordova-plugin-wechat);

一、微信APP支付步骤

1.进入微信开放平台https://open.weixin.qq.com/注册;
2.登录进去创建移动应用,填写应用签名和应用包名(很重要包名的填写规则及签名,详见https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5微信开发文档),并申请微信支付功能;
3.获得微信商户平台账号,获得微信商户号及应用APPID
4.微信APP支付开发文档地址https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=1_2 (不看这微信开发文档,我就不说啥了再见
好了废话不说了,下面贴APP支付代码

二、微信APP支付代码

1、微信的支付工具类
package com.huaxia.traffic.app.util;import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.net.MalformedURLException;import java.net.URL;import java.util.Date;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.SortedMap;import javax.net.ssl.HttpsURLConnection;import org.jdom.Document;import org.jdom.Element;import org.jdom.input.SAXBuilder;import org.springframework.util.DigestUtils;public class WxPayUtil {    //发送https POST 请求    public static String httpsPost(String httpsUrl, String xmlStr) {                  BufferedReader in = null;        InputStreamReader inputStreamReader = null;        InputStream inputStream = null;        HttpsURLConnection urlCon = null;         try {              urlCon = (HttpsURLConnection) (new URL(httpsUrl)).openConnection();              urlCon.setDoInput(true);              urlCon.setDoOutput(true);              urlCon.setRequestMethod("POST");              urlCon.setRequestProperty("Content-Length",                      String.valueOf(xmlStr.getBytes().length));              urlCon.setUseCaches(false);              urlCon.getOutputStream().write(xmlStr.getBytes("utf-8"));            urlCon.getOutputStream().flush();            inputStream = urlCon.getInputStream();            inputStreamReader = new InputStreamReader(inputStream,"utf-8");            in = new BufferedReader(inputStreamReader);              String line;              StringBuffer sb = new StringBuffer();            while ((line = in.readLine()) != null) {                  sb.append(line);              }              System.out.println(sb.toString());            return sb.toString();        } catch (MalformedURLException e) {              e.printStackTrace();          } catch (IOException e) {              e.printStackTrace();          } catch (Exception e) {              e.printStackTrace();          }finally{        try {in.close();inputStreamReader.close();inputStream.close();inputStream = null;        urlCon.disconnect();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}                   }                return null;    }                   //将SortedMap转换成xml格式的String    @SuppressWarnings({  "rawtypes" })public static String getReqXml(SortedMap<Object, Object> map){    StringBuffer sb =new StringBuffer();    sb.append("<xml>");    Set<?> es = map.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("attach".equalsIgnoreCase(k) ||     "body".equalsIgnoreCase(k) ||    "sign".equalsIgnoreCase(k)){    sb.append("<"+k+">"+"<![CDATA["+v+"]]>"+"</"+k+">");    }else{    sb.append("<"+k+">"+v+"</"+k+">");    }    }    sb.append("</xml>");    return sb.toString();    }//微信签名   @SuppressWarnings("rawtypes")public static String createSign(SortedMap<Object, Object> map,String key){StringBuffer sb =new StringBuffer();Set<?> es = map.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)){        sb.append(k + "=" + v + "&");        }    }        sb.append("key="+key);    String md5Val = DigestUtils.md5DigestAsHex(getContentBytes(sb.toString(), "UTF-8")).toUpperCase();    return md5Val;}    private static byte[] getContentBytes(String content, String charset) {        if (charset == null || "".equals(charset)) {            return content.getBytes();        }        try {            return content.getBytes(charset);        } catch (UnsupportedEncodingException e) {            throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);        }    }    //将XML格式的String转换成MAP    @SuppressWarnings({ "rawtypes" })public static Map<String,String> doXmlParse(String xmlStr){    if(xmlStr == null || "".equals(xmlStr)){    return null;    }    xmlStr = xmlStr.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");    Map<String,String> m = new HashMap<String,String>();    InputStream in = null;    try {in = new ByteArrayInputStream(xmlStr.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 = getChildrenText(children);}m.put(k, v);}    } catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} finally{try {in.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}    return m;    }        @SuppressWarnings("rawtypes")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(getChildrenText(list));}sb.append(value);sb.append("</"+name+">");    }    }    return sb.toString();    }}
2.微信统一下单
package com.huaxia.traffic.app.selfservice.service.impl;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.InputStreamReader;import java.security.KeyStore;import java.util.Date;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Map.Entry;import java.util.Set;import java.util.SortedMap;import java.util.TreeMap;import java.util.UUID;import javax.net.ssl.SSLContext;import javax.servlet.http.HttpServletRequest;import org.apache.http.HttpEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpPost;import org.apache.http.conn.ssl.SSLConnectionSocketFactory;import org.apache.http.conn.ssl.SSLContexts;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Value;import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Service;import com.huaxia.traffic.app.selfservice.bean.OrderRequestBean;import com.huaxia.traffic.app.selfservice.domain.PayLog;import com.huaxia.traffic.app.selfservice.service.WxPayService;import com.huaxia.traffic.app.util.WxPayUtil;@Servicepublic class WxPayServiceImpl implements WxPayService{/**     * Logger for this class     */    private static final Logger logger = Logger.getLogger(PayServiceImpl.class);    @Value("${wxpay.appid}")    private String appid;        @Value("${wxpay.attach}")    private String attach;        @Value("${wxpay.mchid}")    private String mchid;        @Value("${wxpay.notifyUrl}")    private String notifyUrl;//调起支付后的回调地址 里面有响应信息        @Value("${wxpay.tradeType}")    private String tradeType;        @Value("${wxpay.key}")//微信商户平台API安全里面自己设置 签名要用    private String key;        @Value("${wxpay.unifiedorderUrl}")    private String unifiedorderUrl;//统一下单地址        @Value("${wxpay.refundUrl}")    private String refundUrl;//退款地址        @Value("${wxpay.certCatalog}")    private String certCatalog;//微信证书地址,退单要用;微信商户平台里面自己去下载        /**     * 统一下单     */@Overridepublic Map<String,String> uniformOrder(OrderRequestBean orderRequestBean,HttpServletRequest request) {// TODO Auto-generated method stubString ip = request.getRemoteAddr();SortedMap<Object, Object> map = new TreeMap<Object, Object>();map.put("appid", appid);map.put("attach", attach);map.put("body", "APP——流量加油站-手机流量充值");map.put("mch_id", mchid);map.put("nonce_str", UUID.randomUUID().toString().replace("-", ""));map.put("notify_url", notifyUrl);map.put("out_trade_no", orderRequestBean.getOutTradeNo());map.put("spbill_create_ip", ip);map.put("total_fee", (int)(orderRequestBean.getFee()*100));map.put("trade_type", tradeType);String sign = WxPayUtil.createSign(map,key);map.put("sign", sign);String xmlStr = WxPayUtil.getReqXml(map);logger.info(xmlStr);String backInfo = WxPayUtil.httpsPost(unifiedorderUrl, xmlStr);Map<String,String> m = WxPayUtil.doXmlParse(backInfo);return m;}/** * 生成支付订单 */public Map<String,String> payOrder(Map<String,String>  m){SortedMap<Object, Object> map = new TreeMap<Object, Object>();String prepayid = m.get("prepay_id");String timestamp = Long.toString((new Date().getTime())/1000);Map<String,String> returnMap = new HashMap<String, String>();map.put("appid", appid);map.put("partnerid",mchid);map.put("prepayid",prepayid);map.put("package","Sign=WXPay");map.put("noncestr",UUID.randomUUID().toString().replace("-", ""));map.put("timestamp",timestamp);String sign = WxPayUtil.createSign(map,key);map.put("sign", sign);Set<Entry<Object, Object>> entry = map.entrySet();Iterator<Entry<Object, Object>> it = entry.iterator();while (it.hasNext()) {Entry<Object, Object> e = it.next();returnMap.put(e.getKey().toString(), e.getValue().toString());} String xmlStr = WxPayUtil.getReqXml(map);logger.info(xmlStr);return returnMap;}/** * 生成退单 */public String refundOrder(PayLog payLog) {// TODO Auto-generated method stubSortedMap<Object, Object> map = new TreeMap<Object, Object>();map.put("appid", appid);map.put("mch_id", mchid);map.put("nonce_str", UUID.randomUUID().toString().replace("-", ""));map.put("op_user_id", mchid);map.put("out_trade_no", payLog.getSerialNumber());map.put("out_refund_no",  UUID.randomUUID().toString().replace("-", ""));map.put("total_fee", (int)(payLog.getFee()*100));map.put("refund_fee", (int)(payLog.getFee()*100));String sign = WxPayUtil.createSign(map,key);map.put("sign", sign);String xmlStr = WxPayUtil.getReqXml(map);logger.info(xmlStr);return xmlStr;}/** * 退单 */@Async@Overridepublic String refund(String strXml){// TODO Auto-generated method stubString text = "";try {KeyStore keyStore = KeyStore.getInstance("PKCS12");FileInputStream instream = new FileInputStream(new File(certCatalog));try {keyStore.load(instream, mchid.toCharArray());} finally {instream.close();}SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchid.toCharArray()).build();SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();try {HttpPost httppost = new HttpPost(refundUrl);StringEntity se = new StringEntity(strXml);httppost.setEntity(se);System.out.println("executing request" + httppost.getRequestLine());CloseableHttpResponse response = httpclient.execute(httppost);try {HttpEntity entity = response.getEntity();logger.info("----------------------------------------");logger.info(response.getStatusLine());if (entity != null) {logger.info("Response content length: "+ entity.getContentLength());BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));while ((text = bufferedReader.readLine()) != null) {logger.info(text);}}EntityUtils.consume(entity);} finally {response.close();}} finally {httpclient.close();}return text;} catch (Exception e) {e.printStackTrace();}return null;}}

3.页面调起支付

var params = {    partnerid: '10000100', // merchant id    prepayid: 'wx201411101639507cbf6ffd8b0779950874', // prepay id    noncestr: '1add1a30ac87aa2db72f57a2375d8fec', // nonce    timestamp: '1439531364', // timestamp    sign: '0CB01533B8C1EF103065174F50BCA001', // signed string};Wechat.sendPaymentRequest(params, function () {    alert("Success");}, function (reason) {    alert("Failed: " + reason);});
4.支付成功后获取微信返回的支付信息 
@Override    @ResponseBody    @RequestMapping("/wxNotify")    public ReturnBean wxNotify(HttpServletRequest request){    System.out.println("---success--");     InputStream is;try {is = request.getInputStream();String xml = this.inputStream2String(is, "UTF-8");logger.info(xml);System.out.println(xml);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}         /**     * 后面把xml转成Map根据数据作逻辑处理     */     return null;    }


0 0
原创粉丝点击