微信支付操作流程

微信支付流程:
1、在页面点击支付发生的动作
将订单参数传递后台->后台根据订单参数以及微信相关信息->获取支付所需要的参数->后台处理支付所需要的参数返回给前端->前端获取到支付参数->发起支付请求->支付成功的页面会显示跳回商家所设置的回调路径->后台根据回调路径处理相关业务逻辑;

2、程序案例;从官网中下载相关API

页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>every thing will be will</title>
    <script type="text/javascript" src="../static/js/jquery-3.3.1.min.js"></script>
</head>
<body>
<input type="button" value="进行微信支付" id="payId">

<script type="text/javascript">

    $(function(){
        var appId,timeStamp,nonceStr,package,signType,paySign;

        $("#payId").click(function(){
            pay();
        });

        //从后台获取参数
        function pay(){
            var url = "http://localhost:8062/wxpay/order";
            $.get(url,function(result) {
                appId = result.appId;
                timeStamp = result.timeStamp;
                nonceStr = result.nonceStr;
                package = result.package;
                signType = result.signType;
                paySign = result.paySign;

                if (typeof WeixinJSBridge == "undefined") {
                    if (document.addEventListener) {
                        document.addEventListener('WeixinJSBridgeReady',
                            onBridgeReady, false);
                    } else if (document.attachEvent) {
                        document.attachEvent('WeixinJSBridgeReady',
                            onBridgeReady);
                        document.attachEvent('onWeixinJSBridgeReady',
                            onBridgeReady);
                    }
                    alert("请在微信上进行支付操作!");
                    onBridgeReady();
                } else {
                    onBridgeReady();
                }
            });
        }
        //去微信那边发起支付请求
        function onBridgeReady(){

            alert("appId:"+appId+" "+"timeStamp:"+timeStamp+" "+"nonceStr:"+nonceStr+" "+"package:"+package+" "+"signType:"+signType+" "+"paySign:"+paySign+" ");

            WeixinJSBridge.invoke( 'getBrandWCPayRequest', {
                    "appId":appId,     //公众号名称,由商户传入
                    "timeStamp":timeStamp,         //时间戳,自1970年以来的秒数
                    "nonceStr":nonceStr, //随机串
                    "package":package,
                    "signType":signType,         //微信签名方式:
                    "paySign":paySign //微信签名
                },
                function(res){
                    if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                        //alert('支付成功');
                        console.log("支付成功");
                        //支付成功后跳转的页面
                    }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
                        alert('支付取消');
                    }else if(res.err_msg == "get_brand_wcpay_request:fail"){
                        alert('支付失败');

                        alert(JSON.stringify(res));

                        WeixinJSBridge.call('closeWindow');
                    } //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                });
        }
    })
</script>

</body>
</html>

  后台业务逻辑

所需的参数:

public class WxParam {
    public final static String WX_APPID = "";//商家平台ID,微信平台
    public final static String WX_BODY = ""; //商品描述
    public final static String WX_MCH_ID = "";//商户ID ,微信平台
    public final static String WX_NONCE_STR = "";//随机字符串,UUID
    public final static String WX_OPEN_ID = "";//用户OPENID
    public final static String WX_OUT_TRADE_NO = "";//商户订单号
    public final static String WX_SPBILL_CREATE_IP = "";//终端IP,从请求头拿到
    public final static String WX_TOTAL_FEE = "";//支付金额,单位是分
    public final static String WX_TRADE_TYPE = "";//交易类型;JSAPI
    public final static String WX_NOTIFY_URL = "";//通知地址;用户支付成功后,返回应用程序的接口;
    public final static String WX_SIGN = "";//签名,根据上面10个参数计算获得
    public final static String WX_PATERNERKEY = "";//商家密钥
}

  前端所需参数的处理,以及回调路径

@Controller
@RequestMapping("/wxpay")
public class WxPayAction {

    /**
     * 订单采用微信支付所需的参数接口
     * @param request
     * @return
     */
    @RequestMapping("/order")
    @ResponseBody
    public Map<String,String> orders(HttpServletRequest request){
        try {
            String openId = "用户的openid";
            //存放微信支付所需的参数
            final Map<String,String> paraMap = new HashMap<>();
            // 获取请求ip地址
            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();
            }
            if (ip.indexOf(",") != -1) {
                String[] ips = ip.split(",");
                ip = ips[0].trim();
            }
            String uuid = UUID.randomUUID().toString();
            //
            paraMap.put("appid",WxParam.WX_APPID);
            paraMap.put("body","微信测试商品内容" );
            paraMap.put("mch_id",WxParam.WX_MCH_ID );
            paraMap.put("nonce_str",uuid );
            paraMap.put("openid",openId );
            paraMap.put("out_trade_no",UUID.randomUUID().toString().replaceAll("-", "") );//订单号
            paraMap.put("spbill_create_ip",ip );//终端IP,从请求头拿到
            paraMap.put("total_fee","1" );//支付金额,1分
            paraMap.put("trade_type","JSAPI" );//支付类型
            paraMap.put("notify_url","回调url" );
            //这里的key是商家密钥;这一步将回调路径设置到sign参数里面了
            String sign = WXPayUtil.generateSignedXml(paraMap,WxParam.WX_PATERNERKEY);
            paraMap.put("sign",sign );
            //将map转换为xml
            String xml = WXPayUtil.mapToXml(paraMap);
            // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
            String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            System.out.println("xml为:" + xml);
            //预支付
            String xmlStr = HttpRequestUtil.httpsRequest(unifiedorder_url, "POST", xml);
            System.out.println("预支付返回的信息:"+xmlStr);
            //上面的数据主要是为了获得预支付id;就相当于微信上提交订单(订单包含了回调函数),然后返回一个微信的订单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<>();
            payMap.put("appId",WxParam.WX_APPID );
            //后面为什么要加""
            payMap.put("timeStamp",WXPayUtil.getCurrentTimestamp()+"" );
            payMap.put("nonceStr",WXPayUtil.generateNonceStr() );
            payMap.put("signType","MD5" );
            payMap.put("package","prepay_id="+prepay_id);
            String paySin = WXPayUtil.generateSignature(payMap, WxParam.WX_PATERNERKEY);
            payMap.put("paySign",paySin );
            return payMap;
            
        }catch (Exception e){

        }
        return null;
    }

    /**
     * 回调函数,处理业务逻辑
    * @param request
     *      * @param response
     *      * @return
     */
    @RequestMapping("/notify")
    public String wxCallBack(HttpServletRequest request, HttpServletResponse response){
        InputStream is = null;
        try{
            is = request.getInputStream();
            InputStreamReader isr=new InputStreamReader(is,"utf-8");
            BufferedReader br=new BufferedReader(isr);
            StringBuffer buffer=new StringBuffer();
            String line=null;
            while((line=br.readLine())!=null){
                buffer.append(line);
            }
            //从流中获取
            String xml = buffer.toString();
            Map<String,String> notifyMap = WXPayUtil.xmlToMap(xml);
            System.out.println("微信返回的回调函数信息:"+xml);
            if(notifyMap.get("result_code").equals("SUCCESS")){
                String ordersSn = notifyMap.get("out_trade_no");//商户订单号
                String amountpaid = notifyMap.get("total_fee"); //实际支付金额
                BigDecimal amountPay = (new BigDecimal(amountpaid).divide(new BigDecimal("100"))).setScale(2);// 将分转换成元-实际支付金额:元

                /*
                 * 以下是自己的业务处理------仅做参考 更新order对应字段/已支付金额/状态码
                 */
                System.out.println("===notify===回调方法已经被调!!!");
            }
            // 告诉微信服务器收到信息了,回复微信服务器信息用流发送一个xml即可
            response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
        }catch (Exception e){

        }finally {
            if(is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    

}

  用到的工具类

public class HttpRequestUtil {

    /*
     * 处理https GET/POST请求
     * 请求地址、请求方法、参数
     * */
    public static String httpsRequest(String requestUrl,String requestMethod,String outputStr){
        StringBuffer buffer=null;
        try{
            //创建SSLContext
            SSLContext sslContext=SSLContext.getInstance("SSL");
            TrustManager[] tm={new MyX509TrustManager()};
            //初始化
            sslContext.init(null, tm, new java.security.SecureRandom());;
            //获取SSLSocketFactory对象
            SSLSocketFactory ssf=sslContext.getSocketFactory();
            URL url=new URL(requestUrl);
            HttpsURLConnection conn=(HttpsURLConnection)url.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod(requestMethod);
            //设置当前实例使用的SSLSoctetFactory
            conn.setSSLSocketFactory(ssf);
            conn.connect();
            //往服务器端写内容
            if(null!=outputStr){
                OutputStream os=conn.getOutputStream();
                os.write(outputStr.getBytes("utf-8"));
                os.close();
            }

            //读取服务器端返回的内容
            InputStream is=conn.getInputStream();
            InputStreamReader isr=new InputStreamReader(is,"utf-8");
            BufferedReader br=new BufferedReader(isr);
            buffer=new StringBuffer();
            String line=null;
            while((line=br.readLine())!=null){
                buffer.append(line);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return buffer.toString();
    }
}

  

public class MyX509TrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        // TODO Auto-generated method stub

    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        // TODO Auto-generated method stub

    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // TODO Auto-generated method stub
        return null;
    }

}

  

猜你喜欢

转载自www.cnblogs.com/lazyli/p/11987066.html