微信公众号微信支付

 

步骤一.首先 你要有一个微信公众号  和公众号对应的微信商户号 

  1) 先申请一个微信公众号 

    https://kf.qq.com/faq/120911VrYVrA151013MfYvYV.html

    官网教程  做微信支付  我们要的是服务号。  订阅号不能做微信支付

  2) 申请微信商户号

    https://jingyan.baidu.com/article/15622f24d389b3fdfcbea5d1.html

 

步骤二.配置信息 

  1)配置信息  设置网页授权域名  和 

     微信公众平台-->公众号设置-->功能设置

 

  

 

 先把这个文件下载过来  放到 你要设置的域名 根目录下  这样才会设置成功 不要带http

  

  2)配置支付目录  

    商户平台-->产品中心-->开发配置(传送门:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3),且最多可以同时设置5个目录

    

 

    好 到这一步  配置信息就完成了

 

步骤三.开发要提供的参数

   公众APPIDwx15*********a8  (开发需要的)

  开发者密码APPSECEPT : c210***************892d7  (开发需要的)

 

  商户ID14******42  (开发需要的)

  API密钥:5d5************b35b  (开发需要的)

 

   微信公众平台-->基本设置

 

 

 公众APPID 和 APPSECEPT 我们就有了 

 商户平台-->账号中心-->商户信息

 

 商户ID 也有了 我们还差一个 API密钥

商户平台-->账号中心-->API安全

 

 

 

 好了 现在 配置 和参数 我们已经全部都有了  想在开始代码了 

 

 

步骤四:开发流程:

  微信支付 (说白了就是调用官方文档的“统一下单”接口,之后将微信服务器返回的参数做个加工后,返回到前台(JSP页面)) 文档地址 

  https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_20&index=1

  文档主要讲 请求地址是  

  https://api.mch.weixin.qq.com/pay/unifiedorder

  入参有很多   其中的必填参数有:

  1.        appid APPID (已有)

  2.        mch_id 商户ID (已有)

  3.        nonce_str 随机字符串(可以用UUID生成)

  4.        sign 签名

  5.        body 所支付的名称

  6.        out_trade_no 咱们自己所提供的订单号,需要唯一(可以是时间戳)

  7.        total_fee 支付金额

  8.        spbill_create_ip IP地址(获取ip地址)

  9.        notify_url 回调地址(支付成功后的通知地址)

  10.       trade_type 支付类型(默认写  咱们是公众号支付此处给“JSAPI”)

  11.       openid 支付人的微信公众号对应的唯一标识

 

好 我们先获取  openid

1.获取OpenID 时 要先获取 code 也是去请求微信的地址 

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

入参

APPID: 公众号 APPID

redirect_uri: 回调地址 就是访问这个链接后跳转到哪个地址去 

response_type:就直接写 code   

scope:应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )

 

state:重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节

#wechat_redirect:必填不用管

回参

code:返回的 code参数

state:上面传的 state参数

2.获取OpenID  也是请求地址 

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

入参

APPID:  公众号 APPID

secret:开发者密码  APPSECEPT 

code:上面获取的code 参数

grant_type:直接写  authorization_code

回参

{
    "access_token":"ACCESS_TOKEN",
    "expires_in":7200,
    "refresh_token":"REFRESH_TOKEN",
    "openid":"OPENID",
    "scope":"SCOPE"
 }

OpenID 就是我们要 

 

 1.        appid APPID (已有)

  2.        mch_id 商户ID (已有)

  3.        nonce_str 随机字符串(可以用UUID生成)

  4.        sign 签名

  5.        body 所支付的名称 

  6.        out_trade_no 咱们自己所提供的订单号,需要唯一(可以是时间戳)

  7.        total_fee 支付金额   1 为1分钱

  8.        spbill_create_ip IP地址(获取ip地址)

  9.        notify_url 回调地址(支付成功后的通知地址)

  10.       trade_type 支付类型 咱们是公众号支付此处给“JSAPI”

  11.       openid 支付人的微信公众号对应的唯一标识 (openid 我们也有了)

现在 我们只差 sing了 

用WXPayUtil中的

generateSignature(Map<String, String> data, String key, SignType signType)

方法,data是将除了sign外,其他10个参数放到map中,key是四大配置参数中的API秘钥(paternerKey)

sign_type  也可以通过 WXPayUtil 中的方法获取   主要是表明 加密方式 
WXPayConstants.SignType sign_type = WXPayConstants.SignType.MD5;

这些方法都在 wxpay-sdk-0.0.3.jar 这个jar包里
String sign = WXPayUtil.generateSignature(map, AppMchKey, sign_type);

这就生成了 sing 了 把 sing 也 加到 data 里去
调用 mapToXml(Map<String, String> data)

会把 map 转换成 xml
String reqestHtml =WXPayUtil.mapToXml(map);

post请求 https://api.mch.weixin.qq.com/pay/unifiedorder
String xmlStr = sendPost(url,reqestHtml);


成功放回的数据
<xml>
 
  <return_code><![CDATA[SUCCESS]]></return_code>
 
<return_msg><![CDATA[OK]]></return_msg>
 
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
 
<mch_id><![CDATA[10000100]]></mch_id>
 
<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
 
<openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
 
<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
 
<result_code><![CDATA[SUCCESS]]></result_code>
 
<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
 
<trade_type><![CDATA[JSAPI]]></trade_type>
 
</xml>
调用 WXPayUtil.xmlToMap(respondResult) 把 xml 转换成 map 
Map<String, String> map = WXPayUtil.xmlToMap(respondResult);

 

其中 只有 prepay_id 是我们要的 

 

我们要放回个前端的参数是  

1.        appId:四大参数之一的APPID;

2.        timestamp:时间戳(newDate()即可)

3.        nonceStr:随机字符串,再次用WXPayUtil中的generateNonceStr()即可;

4.        package:就tm是它用到了prepay_id,但是还不是直接取值,还非要固定格式的,值的格式例如:”prepay_id= wx2018…250…9981…666”

5.        signType:写MD5就好

6.        paySign:签名 

        if (xmlStr.indexOf("SUCCESS") != -1) {

                Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);

                prepay_id = (String) map.get("prepay_id");

            }

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

            payMap.put("appId", appID);

            payMap.put("timeStamp", getCurrentTimestamp()+"");

            payMap.put("nonceStr", WXPayUtil.generateNonceStr());

            payMap.put("signType", "MD5");

            payMap.put("package", "prepay_id=" + prepay_id);

            String paySign = WXPayUtil.generateSignature(payMap, AppMchKey);// AppMchKey 为api秘钥
       payMap.put("paySign", paySign);
      
return payMap;

这就完成了 代码 

后端代码  有一些方法 可以自己写 

package com.wizrole.hospital.wechat.controller;

import com.github.wxpay.sdk.WXPayUtil;
import com.wizrole.hospital.healthCard.util.HttpRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

import static com.wizrole.hospital.wechat.service.WechatService.*;
import static com.wizrole.hospital.wechat.util.XmlUtil.getCurrentTimestamp;
import static com.wizrole.hospital.wechat.util.XmlUtil.getIpAddr;

public class Test {

    @RequestMapping(value = "testPay" , method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Map orders(HttpServletRequest request) {

    
     String code= request.getParameter("code");
 
    //页面获取openId接口
 
    String getopenid_url = https://api.weixin.qq.com/sns/oauth2/access_token;
 
    String param="appid="+你appid+"&secret="+你secret+"&code="+code+"&grant_type=authorization_code";
 
    //向微信服务器发送get请求获取openIdStr
 
    String openIdStr = HttpRequest.sendGet(getopenid_url, param);
 
    JSONObject json = JSONObject.parseObject(openIdStr);//转成Json格式
 
    String openId = json.getString("openid");//获取openId

try { Map<String, String> paraMap = new HashMap<String, String>(); //获取请求ip地址 String ip = getIpAddr(request); String body = request.getParameter("body"); String total_fee = request.getParameter("total_fee");//支付金额 String out_trade_no = String.valueOf(getCurrentTimestamp()); //订单号 paraMap.put("appid",appID);//公众号ID paraMap.put("body", "尧舜商城-订单结算"); paraMap.put("mch_id",AppMchId);//商户号 ID paraMap.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串 paraMap.put("openid", openid);//OpenID paraMap.put("out_trade_no", out_trade_no);//订单号 paraMap.put("spbill_create_ip", ip); paraMap.put("total_fee","1"); paraMap.put("trade_type", "JSAPI"); paraMap.put("notify_url","http://wizrole.natapp1.cc/Wechat/notifyUrl.do");// 此路径是微信服务器调用支付结果通知路径随意写 String sign = WXPayUtil.generateSignature(paraMap, AppMchKey); paraMap.put("sign", sign); String xml = WXPayUtil.mapToXml(paraMap);//将所有参数(map)转xml格式 // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; String xmlStr = HttpRequest.sendPost(unifiedorder_url, xml);//发送post请求"统一下单接口"返回预支付id:prepay_id //以下内容是返回前端页面的json数据 String prepay_id = "";//预支付id if (xmlStr.indexOf("SUCCESS") != -1) { Map<String, String> map = WXPayUtil.xmlToMap(xmlStr); prepay_id = (String) map.get("prepay_id"); } Map<String, String> payMap = new HashMap<String, String>(); payMap.put("appId", appID); payMap.put("timeStamp", getCurrentTimestamp()+""); payMap.put("nonceStr", WXPayUtil.generateNonceStr()); payMap.put("signType", "MD5"); payMap.put("package", "prepay_id=" + prepay_id); String paySign = WXPayUtil.generateSignature(payMap, AppMchKey); payMap.put("paySign", paySign); return payMap; } catch (Exception e) { e.printStackTrace(); } return null; } }
/**
     * 获取客户端IP地址
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
    }
package com.wizrole.hospital.healthCard.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

public class HttpRequest {
    private static final Logger log = LoggerFactory.getLogger(HttpRequest.class);

    /**
     * 发送GET请求
     * @param url
     * @param param
     * @return
     */
    public static String sendGet(String url , String param){
        String result = "";
        BufferedReader in = null;
        HttpURLConnection connection = null;
        try {
            log.info("发起请求  URL为[" + url + "], 请求方式 [GET], 参数为: " + param);
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString.replaceAll(" ",""));
            connection = (HttpURLConnection)realUrl.openConnection();
            connection.setRequestProperty("accept" , "*/*");
            connection.setRequestProperty("connection" , "Keep-Alive");
            connection.setRequestProperty("user-agent" , "Mozilla/4.0(compatible; MSIE 6.0; Windows NT5.1:SV1");
            connection.connect();
            Map<String , List<String>> map = connection.getHeaderFields();
            for (String key : map.keySet()){
                System.out.println("----------------------------|   " + key + "--->" + map.get(key));
            }
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null){
                result += line;
            }
        }catch (Exception e){
            log.error("发送GET请求出现异常 : " + e);
            e.printStackTrace();
        }finally {
            try{
                connection.disconnect();
                if(in != null){
                    in.close();
                }
            }catch (Exception e1){
                e1.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 发送POST请求
     * @param url
     * @param param
     * @return
     * @throws UnsupportedEncodingException 
     */
    public static String sendPost(String url , String param){
        BufferedWriter out = null;
        BufferedReader in = null;
        HttpURLConnection conn = null;
        StringBuffer result = new StringBuffer();
        try {
            //param = new String(param.getBytes() , "utf-8");
            log.info("发起请求  URL为[" + url + "], 请求方式 [POST], 参数为: " + param);
            URL realUrl = new URL(url);
            conn = (HttpURLConnection)realUrl.openConnection();
            conn.setRequestProperty("Content-Type","application/json; charset=utf-8");
            conn.setRequestProperty("accept" , "*/*");
            conn.setRequestProperty("connection" , "Keep-Alive");
            conn.setRequestProperty("user-agent" , "Mozilla/4.0(compatible; MSIE 6.0; Windows NT5.1:SV1");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            out = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(),"UTF-8"));
            out.write(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));
//            Map<String , List<String>> map1 = conn.getRequestProperties();
            conn.connect();
//            for (String key : map1.keySet()){
//                System.out.println("---------------------------->   " + key + "--->" + map1.get(key));
//            }
            Map<String , List<String>> map = conn.getHeaderFields();
            for (String key : map.keySet()){
                System.out.println("----------------------------|   " + key + "--->" + map.get(key));
            }
            
            String line = null;
            while ((line = in.readLine())!=null){
                result.append(line); 
            }
            
            log.info("出参 : " + result.toString());
        }catch (Exception e){
            log.error("发送POST请求出现异常 : " + e);
            e.printStackTrace();
        }finally {
            try{
                conn.disconnect();
                if(out != null){
                    out.close();
                }
                if(in != null){
                    in.close();
                }
            }catch (Exception e1){
                e1.printStackTrace();
            }
        }
        return result.toString();
    }

}

 

 

前端代码

 

var a = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=appid&redirect_uri=http://wizrole.natapp1.cc/index.html&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
   location.href = a;

在index.html 页面写 下面这段js

 
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
var code = getQueryString("code");
//调取微信支付
function pay(){ openid = $("#openId").text(); $.ajax({ url:"/testPay", type:"POST", dataType: 'json', data:{ code:code, body:"测试", total_fee:"1" }, success: function (data) { if (data.return_msg == "OK") { WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId": data.appid, //公众号名称,由商户传入 "timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数 "nonceStr": data.nonce_str, //随机串 "package": "prepay_id=" + data.prepay_id, "signType": "MD5", //微信签名方式: "paySign": data.sign //微信签名 }, function (res) { if (res.err_msg == "get_brand_wcpay_request:ok") { alert("支付成功,订单受理中"); } else if (res.err_msg == "get_brand_wcpay_request:cancel") { //取消订单 self.cancelOrder(orderdata.order_no, function (status) { if (status == 1) { alert("支付已取消"); } else if (status == 2) { alert("订单取消失败,请联系管理员") } }); } else if (res.err_msg == "get_brand_wcpay_request:fail") { //取消订单 self.cancelOrder(orderdata.order_no, function (status) { if (status == 1) { alert("支付失败"); } else if (status == 2) { alert("订单取消失败,请联系管理员") } }); } } ); } } }) }

 

 

  

 

posted @ 2019-06-18 17:03  closeIt  阅读(1567)  评论(0编辑  收藏  举报