微信支付H5调用支付详解(java版)

最近项目需要微信支付,然后看了下微信公众号支付,,虽然不难,但是细节还是需要注意的,用了大半天时间写了个demo,并且完整的测试了一下支付流程,下面分享一下微信公众号支付的经验。

一、配置公众号微信支付 

需要我们配置微信公众号支付地址和测试白名单。

比如:支付JS页面的地址为 http://www.xxx.com/shop/pay/

那此处配置www.xxx.com/shop/pay/

二、开发流程

借用微信公众号支付api(地址 http://pay.weixin.qq.com/wiki/doc/api/index.PHP?chapter=7_4),我们需要开发的为红色标记出的。如下:

三、向微信服务器端下订单

调用统一下单接口,这样就能获取微信支付的prepay_id(http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1)。

在调用该接口前有几个字段是H5支付必须填写的openid

3.1 获取openid

可以通过网页授权形式(http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html

在微信中发送如下链接
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=要跳转的下订单的url&response_type=code&scope=snsapi_base&state=123#wechat_redirect

3.2 下订单获取prepay_id

代码如下,实际上是通过post发送一个xml 文件,获取微信服务器端发送过来的prepay_id。

import java.io.ByteArrayInputStream;
import javaioIOException;
import javaioInputStream;
import javaioUnsupportedEncodingException;
import javautilDate;
import javautilHashMap;
import javautilIterator;
import javautilMap;
import javautilMapEntry;
import javautilRandom; 

import javaxservlethttpHttpServletRequest;
import javaxservlethttpHttpServletResponse; 

import orgapachecommonscodecdigestDigestUtils;
import orgspringframeworkstereotypeController;
import orgspringframeworkwebbindannotationRequestMapping;
import orgxmlpullvXmlPullParser;
import orgxmlpullvXmlPullParserException;
import orgxmlpullvXmlPullParserFactory; 

import comfasterxmljacksondatabindJsonNode;
import comgsonoauthOauth;
import comgsonoauthPay;
import comgsonutilHttpKit;
import comsyutilDatetimeUtil;
import comsyutilJsonUtil; 

@Controller
@RequestMapping("/pay")
public class WXPayController { 

  @RequestMapping(value = "wxprepaydo")
  public void jspay(HttpServletRequest request, HttpServletResponse response, String callback) throws Exception {
    // 获取openid
    String openId = SessionUtilgetAtt(request, "openId");
    if (openId == null) {
      openId = getUserOpenId(request);
    } 

    String appid = "wx16691fcb0523c1a4";
    String paternerKey = "ININGFENG1234567fdfwfdfd1ss234567"; 

    String out_trade_no = getTradeNo();
    Map<String, String> paraMap = new HashMap<String, String>();
    paraMapput("appid", appid);
    paraMapput("attach", "测试");
    paraMapput("body", "测试购买支付");
    paraMapput("mch_id", "10283271");
    paraMapput("nonce_str", create_nonce_str());
    paraMapput("openid", openId);
    paraMapput("out_trade_no", out_trade_no);
    paraMapput("spbill_create_ip", getAddrIp(request));
    paraMapput("total_fee", "1");
    paraMapput("trade_type", "JSAPI");
    paraMapput("notify_url", "http://wwwxxxco/bank/page/wxnotify");
    String sign = getSign(paraMap, paternerKey);
    paraMapput("sign", sign); 

    // 统一下单 https://apimchweixinqqcom/pay/unifiedorder
    String url = "https://apimchweixinqqcom/pay/unifiedorder"; 

    String xml = ArrayToXml(paraMap); 

    String xmlStr = HttpKitpost(url, xml); 

    // 预付商品id
    String prepay_id = ""; 

    if (xmlStrindexOf("SUCCESS") != -1) {
      Map<String, String> map = doXMLParse(xmlStr);
      prepay_id = (String) mapget("prepay_id");
    } 

    Map<String, String> payMap = new HashMap<String, String>();
    payMapput("appId", appid);
    payMapput("timeStamp", create_timestamp());
    payMapput("nonceStr", create_nonce_str());
    payMapput("signType", "MD5");
    payMapput("package", "prepay_id=" + prepay_id);
    String paySign = getSign(payMap, paternerKey); 

    payMapput("pg", prepay_id);
    payMapput("paySign", paySign); 

    WebUtilresponse(response, WebUtilpackJsonp(callback, JsonUtilwarpJsonNodeResponse(JsonUtilobjectToJsonNode(payMap))toString()));
  } 

  /**
   * map转成xml
   *
   * @param arr
   * @return
   */
  public String ArrayToXml(Map<String, String> arr) {
    String xml = "<xml>"; 

    Iterator<Entry<String, String>> iter = arrentrySet()iterator();
    while (iterhasNext()) {
      Entry<String, String> entry = iternext();
      String key = entrygetKey();
      String val = entrygetValue();
      xml += "<" + key + ">" + val + "</" + key + ">";
    } 

    xml += "</xml>";
    return xml;
  } 

  // 获取openId
  private String getUserOpenId(HttpServletRequest request) throws Exception {
    String code = requestgetParameter("code");
    if (code == null) {
      String openId = requestgetParameter("openId");
      return openId;
    }
    Oauth o = new Oauth();
    String token = ogetToken(code);
    JsonNode node = JsonUtilStringToJsonNode(token);
    String openId = nodeget("openid")asText();
    return openId;
  } 

  private String create_nonce_str() {
      String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
      String res = "";
      for (int i = 0; i < 16; i++) {
        Random rd = new Random();
        res += charscharAt(rdnextInt(charslength() - 1));
      }
      return res;
  } 

  private String getAddrIp(HttpServletRequest request){
    return requestgetRemoteAddr();
  } 

  private String create_timestamp() {
    return LongtoString(SystemcurrentTimeMillis() / 1000);
  } 

  private String getTradeNo(){
    String timestamp = DatetimeUtilformatDate(new Date(), DatetimeUtilDATETIME_PATTERN);
    return "HZNO" + timestamp;
  } 

  private String getSign(Map<String, String> params, String paternerKey )
      throws UnsupportedEncodingException {
    String string1 = PaycreateSign(params, false);
    String stringSignTemp = string1 + "&key=" + paternerKey;
    String signValue = DigestUtilsmd5Hex(stringSignTemp)toUpperCase();
    return signValue;
  } 

  private Map<String, String> doXMLParse(String xml)
      throws XmlPullParserException, IOException { 

    InputStream inputStream = new ByteArrayInputStream(xmlgetBytes()); 

    Map<String, String> map = null; 

    XmlPullParser pullParser = XmlPullParserFactorynewInstance()
        newPullParser(); 

    pullParsersetInput(inputStream, "UTF-8"); // 为xml设置要解析的xml数据 

    int eventType = pullParsergetEventType(); 

    while (eventType != XmlPullParserEND_DOCUMENT) {
      switch (eventType) {
      case XmlPullParserSTART_DOCUMENT:
        map = new HashMap<String, String>();
        break; 

      case XmlPullParserSTART_TAG:
        String key = pullParsergetName();
        if (keyequals("xml"))
          break; 

        String value = pullParsernextText();
        mapput(key, value); 

        break; 

      case XmlPullParserEND_TAG:
        break; 

      } 

      eventType = pullParsernext(); 

    } 

    return map;
  } 

}

四、H5支付

H5支付其实很简单,只需要调用微信内嵌浏览器的js方法就行(http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=7_7

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://wwwspringframeworkorg/tags" %>
<%
  String path = requestgetContextPath();
  String basePath = requestgetScheme() + "://" + requestgetServerName() + ":" + requestgetServerPort() + path + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 01 Transitional//EN" "http://wwwworg/TR/html4/loosedtd">
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=0, maximum-scale=0, user-scalable=0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="format-detection" content="telephone=no" />
<title>测试支付</title>
<link href="/css/csscss?v=0" rel="stylesheet" type="text/css">
</head> 

<body>
  <div class="index_box">
    <div class="apply_name">微信js支付测试</div> 

    <div class="branch_con">
      <ul>
        <li><span class="name">测试支付信息</span></li>
      </ul>
      <p class="cz_btn"><a href="javascript:pay();" class="btn_1">立即支付</a></p>
    </div>
  </div> 

  <script type="text/javascript" src="/js/zeptominjs"></script>
  <script type="text/javascript" src="/js/commonjs"></script>
  <script type="text/javascript"> 

  var appId = urlparameter("appId");
  var timeStamp = urlparameter("timeStamp");
  var nonceStr = urlparameter("nonceStr");
  var pg = urlparameter("pg");
  var signType = urlparameter("signType");
  var paySign = urlparameter("paySign"); 

   function onBridgeReady(){ 

      WeixinJSBridgeinvoke(
        'getBrandWCPayRequest', {
          "appId" : appId,   //公众号名称,由商户传入
          "timeStamp": timeStamp,     //时间戳,自1970年以来的秒数
          "nonceStr" : nonceStr, //随机串
          "package" : "prepay_id=" + pg,
          "signType" : signType,     //微信签名方式:
          "paySign" : paySign  //微信签名
        }, 

        function(res){
          if(reserr_msg == "get_brand_wcpay_request:ok" ) { 

            alert("支付成功");
          }   // 使用以上方式判断前端返回,微信团队郑重提示:reserr_msg将在用户支付成功后返回  ok,但并不保证它绝对可靠。
        }
      );
    } 

    function pay(){ 

      if (typeof WeixinJSBridge == "undefined"){
        if( documentaddEventListener ){
          documentaddEventListener('WeixinJSBridgeReady', onBridgeReady, false);
        }else if (documentattachEvent){
          documentattachEvent('WeixinJSBridgeReady', onBridgeReady);
          documentattachEvent('onWeixinJSBridgeReady', onBridgeReady);
        }
      }else{
        onBridgeReady();
      }  

    }
  </script>
</body>
</html>

效果如下

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java微信公众号开发案例

    微信公众号开发一般是针对企业和组织的,个人一般只能申请订阅号,并且调用的接口有限,下面我们就来简单的描述下接入公众号的步骤: 1.首先你需要一个邮箱在微信公众号平台进行注册:      注册的方式有订阅号.公众号.小程序和企业号,个人我们这里只能选择订阅号 2.注册完后,我们登录到公众号平台--->开发--->基本配置,这里需要填写URL和token,URL就是我们使用服务器的接口: 3.Java Web服务器程序编译好且在服务器上部署可以运行的话,可在微信公众号进行在线接口调试: 1).选择

  • 第三方网站微信登录java代码实现

    前两个星期在公司中的项目加上了微信登录.绑定的功能,在这里做个记录! 一.开发前知识 1.微信开放平台与微信公众平台的区别 1.1 微信公众平台: ① 地址:https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN ② 微信公众平台面向的是普通的用户,比如自媒体和媒体,企业官方微信公众账号运营人员使用,当然你所在的团队或者公司有实力去开发一些内容,也可以调用公众平台里面的接口,比如自定义菜单,自动回复,查询功能. 1.2

  • java开发微信分享到朋友圈功能

    微信分享功能开发 用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路. 一.服务器端程序 package com.wiimedia.controller; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.ParseException; import

  • java实现微信支付(服务端)

    废话不多说,直接看代码. RequestHandler requestHandler = new RequestHandler(super.getRequest(),super.getResponse()); //获取token //两小时内有效,两小时后重新获取 Token = requestHandler.GetToken(); //更新token 到应用中 requestHandler.getTokenReal(); System.out.println("微信支付获取token=====

  • 微信java开发之实现微信主动推送消息

    1.拉取access_token2.拉取用户信息3.主动推送消息4.接口貌似要申请权限5.依赖httpclient4.2.3 和jackson 2.2.1 复制代码 代码如下: public class WeixinAPIHelper { /**  * 获取token接口  */ private String getTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=

  • Java开发微信公众号接收和被动回复普通消息

    上篇说完了如何接入微信公众号,本文说一下微信公众号的最基本功能:普通消息的接收和回复.说到普通消息,那么什么是微信公众号所定义的普通消息呢,微信开发者文档中提到的接收的普通消息包括如下几类: 1.文本消息 2.图片消息 3.语音消息 4.视频消息 5.小视频消息 6.地理位置消息 7.链接消息(被动回复的消息) 被动回复的普通消息包括: 1.回复文本消息 2.回复图片消息 3.回复语音消息 4.回复视频消息 5.回复音乐消息 6.回复图文消息 其实接收消息和被动回复消息这两个动作是不分家的,这本

  • java开发微信公众号支付

    最近做了微信公众号支付的开发,由于是第一次做也摸索了几天的时间,也只是达到了实现功能的水平,并没有太多考虑到性能问题,所以这篇文章比较适合初学者. 微信公众号支付的总体其实很简单,大致就分为三步.第一步需要获取用户授权:第二步调用统一下单接口获取预支付id:第三步H5调起微信支付的内置的js.下面介绍具体每一步的开发流程. 一    首先要明确微信公众号支付属于网页版支付,所以相较于app的直接调取微信支付要多一步微信授权.也就是需要获取用户的openid.微信公众号使用的交易类型是JSAPI,

  • Java通过JsApi方式实现微信支付

    要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回.由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分. 示例代码如下: function onBridgeReady(){ WeixinJSBridge

  • Java编程调用微信分享功能示例

    本文实例讲述了Java编程调用微信分享功能.分享给大家供大家参考,具体如下: 这篇文章介绍如何使用java开发微信分享功能,因为工作,已经开发完成,可使用. 如果想要自定义微信的分享功能,首先在自己的页面内首先使用AJAX.下面我具体举例. 首先是在页面内写入请求后台的AJAX /** * 调用微信分享接口 * */ public void WXConfig(){ String url = getPara("href"); WXConfigController scan = new W

  • java实现微信公众平台自定义菜单的创建示例

    复制代码 代码如下: import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL; import org.json.JSONObject; public class MenuUtil { /**  * 获得ACC

  • Java实现仿微信红包分配规则

    最近过年发红包拜年成为一种新的潮流,作为程序猿对算法的好奇远远要大于对红包的好奇,这里介绍一种自己想到的一种随机红包分配策略,还请大家多多指教. 算法介绍 一.红包金额限制 对于微信红包,我们知道没人随机的最小红包是1分,最大金额是200元,这里我们同样来设置红包的范围,下面代码我们统一金钱的单位为分. //最小红包额度 private static final int MINMONEY = 1; //最大红包额度 private static final int MAXMONEY = 200

  • java微信公众号开发(搭建本地测试环境)

    俗话说,工欲善其事,必先利其器.要做微信公众号开发,两样东西不可少,那就是要有一个用来测试的公众号,还有一个用来调式代码的开发环境. 测试公众号 微信公众号有订阅号.服务号.企业号,在注册的时候看到这样的信息,只有订阅号可以个人申请,服务号和企业号要有企业资质才可以.这里所说的微信公众号开发指的是订阅号和服务号. 另外,未认证的个人订阅号有一些接口是没有权限的,并且目前个人订阅号已不支持微信认证,也就是说个人订阅号无法调用一些高级的权限接口,下图就是一个未认证的个人订阅号所具备权限列表,像生成二

随机推荐