java服务端微信APP支付接口详解

一、微信APP支付接入商户服务中心

[申请流程指引] (https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317780&token=84f23b4e9746c5963128711f225476cfd49ccf8c&lang=zh_CN)

二、开始开发

1、配置相关的配置信息

1.1、配置appid(Android)、mch_id(ios)、微信支付后的回调地址

1

2

3

4

5

6

7

sys.properties配置文件:

 

  appid=wx***************1

  mch_id=1********2

  notify_url=http://6*.***.***.**/returnmsg.do

 

//回调通知的地址,一定是要可以直接访问的地址

2、微信支付–下单

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

@ResponseBody

@RequestMapping(value = "/weixinpay.do", produces = "text/html;charset=UTF-8",method={RequestMethod.POST})

  public static String weixinpay(String body, //商品描述

      String detail, //商品详情

      String attach, //附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据

      String out_trade_no, //商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号

      String total_price, //订单总金额,单位为分,详见支付金额

      String spbill_create_ip //用户端实际ip

 

      ) throws Exception {

 

    WeixinConfigUtils config = new WeixinConfigUtils();

    //参数组

    String appid = config.appid;//微信开放平台审核通过的应用APPID

    System.out.println("appid是:"+appid);

    String mch_id = config.mch_id;

    System.out.println("mch_id是:"+mch_id);

    String nonce_str = RandCharsUtils.getRandomString(16);

    System.out.println("随机字符串是:"+nonce_str);

 

 

    body = body;//"测试微信支付0.01_2";

    detail = detail;//"0.01_元测试开始";

    //attach = attach;//"备用参数,先留着,后面会有用的";

    //String out_trade_no = OrderUtil.getOrderNo();//"2015112500001000811017342394";

 

    double totalfee =0;

    try{

      totalfee=Double.parseDouble(total_price);单位是分,即是0.01元

    }catch (Exception e) {

      totalfee=0;

    }

    int total_fee=(int) (totalfee*100);

    spbill_create_ip = spbill_create_ip;//"127.0.0.1";

 

    String time_start = RandCharsUtils.timeStart();

    System.out.println(time_start);

    String time_expire = RandCharsUtils.timeExpire();

    System.out.println(time_expire);

    String notify_url = config.notify_url;

    System.out.println("notify_url是:"+notify_url);

    String trade_type = "APP";

 

    //参数:开始生成签名

    SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();

    parameters.put("appid", appid);

    parameters.put("mch_id", mch_id);

    parameters.put("nonce_str", nonce_str);

    parameters.put("body", body);

    //parameters.put("nonce_str", nonce_str);

    parameters.put("detail", detail);

    parameters.put("attach", attach);

    parameters.put("out_trade_no", out_trade_no);

    parameters.put("total_fee", total_fee);

    parameters.put("time_start", time_start);

    parameters.put("time_expire", time_expire);

    parameters.put("notify_url", notify_url);

    parameters.put("trade_type", trade_type);

    parameters.put("spbill_create_ip", spbill_create_ip);

 

    String sign = WXSignUtils.createSign("UTF-8", parameters);

    System.out.println("签名是:"+sign);

 

 

    Unifiedorder unifiedorder = new Unifiedorder();

    unifiedorder.setAppid(appid);

    unifiedorder.setMch_id(mch_id);

    unifiedorder.setNonce_str(nonce_str);

    unifiedorder.setSign(sign);

    unifiedorder.setBody(body);

    unifiedorder.setDetail(detail);

    unifiedorder.setAttach(attach);

    unifiedorder.setOut_trade_no(out_trade_no);

    unifiedorder.setTotal_fee(total_fee);

    unifiedorder.setSpbill_create_ip(spbill_create_ip);

    unifiedorder.setTime_start(time_start);

    unifiedorder.setTime_expire(time_expire);

    unifiedorder.setNotify_url(notify_url);

    unifiedorder.setTrade_type(trade_type);

 

    System.out.println(MD5Utils.md5("fenxiangzhuyi") + "========================");

 

    //构造xml参数

    String xmlInfo = HttpXmlUtils.xmlInfo(unifiedorder);

 

    String wxUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";

 

    String method = "POST";

 

    String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();

 

    System.out.println(weixinPost);

 

    ParseXMLUtils.jdomParseXml(weixinPost);

 

 

 

    String json = JsonUtil.xml2jsonString(weixinPost);

 

    System.out.println("=========================================================");

 

    Bean b = JsonUtil.getSingleBean(json, Bean.class);

    if(null!=b){

      WeixinOrder weixin = b.getXml();

      //参数:开始生成签名

      SortedMap<Object,Object> par = new TreeMap<Object,Object>();

      par.put("appid", weixin.getAppid());

      par.put("partnerid", weixin.getMch_id());

      par.put("prepayid", weixin.getPrepay_id());

      par.put("package", "Sign=WXPay");

      par.put("noncestr", weixin.getNonce_str());

 

      //时间戳

       Date date = new Date();

       long time = date.getTime();

       //mysq 时间戳只有10位 要做处理

       String dateline = time + "";

       dateline = dateline.substring(0, 10);

 

      par.put("timestamp", dateline);

 

      String signnew = WXSignUtils.createSign("UTF-8", par);

      System.out.println("再次签名是:"+signnew);

 

 

      SetPay setPay = new SetPay();

 

      setPay.setAppid(weixin.getAppid());

      setPay.setPartnerid(weixin.getMch_id());

      setPay.setPrepayid(weixin.getPrepay_id());

      setPay.setNoncestr(weixin.getNonce_str());

 

      setPay.setTimestamp(dateline);

      setPay.setSign(signnew);

      setPay.setPack("Sign=WXPay");

 

      JSONObject js = JSONObject.fromObject(setPay);

      StringBuilder msg = new StringBuilder();

      msg.append("{\"code\":\"1\",");

      msg.append("\"msg\":\"查询成功!\",");

      msg.append("\"datas\":");

      msg.append(js.toString());

      msg.append("}");

 

      System.out.println(js);

 

      return msg.toString();

    }

    StringBuilder msg = new StringBuilder();

    msg.append("{\"code\":\"1\",");

    msg.append("\"msg\":\"查询成功!\",");

    msg.append("\"datas\":");

    msg.append("支付失败!");

    msg.append("}");

 

 

    return msg.toString();

 

  }

2.1、微信支付签名算法sign

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

package com.wx.weixincontroller.pay.weixin.Utils;

 

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

import java.util.SortedMap;

 

import com.wx.weixin.utils.MD5Utils;

 

/**

 * 微信支付签名

 * @author iYjrg_xiebin

 * @date 2016年10月25日下午4:47:07

 */

public class WXSignUtils {

  //http://mch.weixin.qq.com/wiki/doc/api/index.php?chapter=4_3

  //商户Key:改成公司申请的即可

  //32位密码设置地址:http://www.sexauth.com/ jdex1hvufnm1sdcb0e81t36k0d0f15nc

 

  private static String Key = "***cb**e**ef**c*e*d***e*fd***cb*";

 

  /**

   * 微信支付签名算法sign

   * @param characterEncoding

   * @param parameters

   * @return

   */

  @SuppressWarnings("rawtypes")

  public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){

 

 

    StringBuffer sb = new StringBuffer();

    Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)

    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=" + Key);

    System.out.println("字符串拼接后是:"+sb.toString());

    String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();

    return sign;

  }

 

}

2.2、POST提交XML格式的参数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

package com.wx.weixincontroller.pay.weixin.Utils;

 

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.net.HttpURLConnection;

import java.net.MalformedURLException;

import java.net.URL;

 

import javax.net.ssl.HttpsURLConnection;

 

import com. com.wx.weixin.wxcontroller.pay.weixin.entity.Unifiedorder;

 

/**

 * post提交xml格式的参数

 * @author iYjrg_xiebin

 * @date 2016年10月25日下午3:33:38

 */

public class HttpXmlUtils {

 

  /**

   * 开始post提交参数到接口

   * 并接受返回

   * @param url

   * @param xml

   * @param method

   * @param contentType

   * @return

   */

  public static String xmlHttpProxy(String url,String xml,String method,String contentType){

    InputStream is = null;

    OutputStreamWriter os = null;

 

    try {

      URL _url = new URL(url);

      HttpURLConnection conn = (HttpURLConnection) _url.openConnection();

      conn.setDoInput(true); 

      conn.setDoOutput(true); 

      conn.setRequestProperty("Content-type", "text/xml");

      conn.setRequestProperty("Pragma:", "no-cache");

      conn.setRequestProperty("Cache-Control", "no-cache");

      conn.setRequestMethod("POST");

      os = new OutputStreamWriter(conn.getOutputStream());

      os.write(new String(xml.getBytes(contentType)));

      os.flush();

 

      //返回值

      is = conn.getInputStream();

      return getContent(is, "utf-8");

    } catch (MalformedURLException e) {

      e.printStackTrace();

    } catch (IOException e) {

      e.printStackTrace();

    } finally{

      try {

        if(os!=null){os.close();}

        if(is!=null){is.close();}

      } catch (IOException e) {

        e.printStackTrace();

      }

    }

    return null;

  }

 

  /**

   * 解析返回的值

   * @param is

   * @param charset

   * @return

   */

  public static String getContent(InputStream is, String charset) {

    String pageString = null;

    InputStreamReader isr = null;

    BufferedReader br = null;

    StringBuffer sb = null;

    try {

      isr = new InputStreamReader(is, charset);

      br = new BufferedReader(isr);

      sb = new StringBuffer();

      String line = null;

      while ((line = br.readLine()) != null) {

        sb.append(line + "\n");

      }

      pageString = sb.toString();

    } catch (Exception e) {

      e.printStackTrace();

    } finally {

      try {

        if (is != null){

          is.close();

        }

        if(isr!=null){

          isr.close();

        }

        if(br!=null){

          br.close();

        }

      } catch (IOException e) {

        e.printStackTrace();

      }

      sb = null;

    }

    return pageString;

  }

 

  /**

   * 构造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 "";

  }

 

 

 

 

  /**

   * post请求并得到返回结果

   * @param requestUrl

   * @param requestMethod

   * @param output

   * @return

   */

  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 "";

  }

 

}

3、微信支付–回调通知业务处理

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

//通知处理类

@ResponseBody

@RequestMapping(value = "/returnmsg.do", produces = "text/html;charset=UTF-8",method={RequestMethod.POST})

   public String returnmsg(HttpServletRequest request, HttpServletResponse response) throws Exception {

 

     // 解析结果存储在HashMap

     Map<String, String> map = new HashMap<String, String>();

     InputStream inputStream = request.getInputStream();

 

     // 读取输入流

     SAXReader reader = new SAXReader();

     Document document = reader.read(inputStream);

     // 得到xml根元素

     Element root = document.getRootElement();

     // 得到根元素的所有子节点

     List<Element> elementList = root.elements();

 

     // 遍历所有子节点

     for (Element e : elementList) {

       map.put(e.getName(), e.getText());

     }

 

     JSONObject json = JSONObject.fromObject(map);

 

     System.out.println("===消息通知的结果:" + json.toString() + "==========================");

     System.out.println("===return_code===" + map.get("return_code"));

     System.out.println("===return_msg===" + map.get("return_msg"));

     System.out.println("===out_trade_no===" + map.get("out_trade_no"));

 

     //验证签名的过程

 

     //判断是否支付成功

     if(map.get("return_code").equals("SUCCESS")) {

 

         /**

         *支付成功之后的业务处理

         */

 

         // 释放资源

         inputStream.close();

         inputStream = null;

 

 

         //bis.close();

         return "SUCCESS";

       }

 

     }

     if (map.get("return_code").equals("FAIL")) {

 

       /**

        *支付失败后的业务处理

        */

 

         // 释放资源

         inputStream.close();

 

         inputStream = null;

 

         return "SUCCESS";

       }

 

 

     }

 

     // 释放资源

     inputStream.close();

     inputStream = null;

 

     return "SUCCESS";

 

   }

如有不足请指教.

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值