• 微信扫码支付开发


    一.QR Code(二维码) 

      二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,用若干个与二进制相对应的几何形体来表示文字数值信息。

    二.维码生成插件qrious

      qrious是一款基于HTML5 Canvas的纯JS二维码生成插件。通过qrious.js可以快速生成各种二维码,你可以控制二维码的尺寸颜色,还可以将生成的二维码进行Base64编码。  

      下面的代码即可生成一张二维码

    <html>
    <head>
    <title>二维码入门小demo</title>
    </head>
    <body>
    <img id="qrious">
    <script src="qrious.min.js"></script>
    <script>
     var qr = new QRious({
           element:document.getElementById('qrious'),
           size:250,        level:'H',       value:'http://www.baidu.cn'
        });
    </script>
    </body>
    </html>

      其中的JS插件地址 https://neocotic.com/qrious/ 

      qrious.js二维码插件的可用配置参数如下:

      

    三.微信扫码支付

      1.微信扫码支付申请

        微信扫码支付是商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。该模式适用于PC   网站支付、实体店单品或订单支付、媒体广告支付等场景。

        具体步骤参考微信支付官网

      2.需求 

        1)在支付页面上生成支付二维码,并显示订单号和金额

        2)用户拿出手机,打开微信扫描页面上的二维码,然后在微信中完成支付

      2.实现思路

        商户后台系统先调用微信支付的统一下单接口,微信后台系统返回链接参数code_url,商户后台系统将code_url值生成二维码图片,用户使用微信客户端扫码后发起支付。注意:code_url有效期为2小时,过期后扫码不能再发起支付。

        官方API 详细说明了调用流程,并配有时序图。

      3.微信支付SDK

        使用微信支付SDK,在maven工程中引入依赖

    <dependency>
        <groupId>com.github.wxpay</groupId>
        <artifactId>wxpay-sdk</artifactId>
        <version>0.0.3</version>
    </dependency> 

        我们主要会用到微信支付SDK的以下功能:

        1)获取随机字符串

          WXPayUtil.generateNonceStr()

        2)MAP转换为XML字符串(自动添加签名)

           WXPayUtil.generateSignedXml(param, partnerkey)

        3)XML字符串转换为MAP 

          WXPayUtil.xmlToMap(result)

      4.HttpClient工具类   

    import java.io.IOException;
    import java.security.GeneralSecurityException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.text.ParseException;
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLException;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.apache.http.Consts;
    import org.apache.http.HttpEntity;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.client.methods.HttpPut;
    import org.apache.http.client.methods.HttpUriRequest;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLContextBuilder;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.conn.ssl.TrustStrategy;
    import org.apache.http.conn.ssl.X509HostnameVerifier;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;
    
    /**
     * http请求客户端
     * 
     * @author Administrator
     * 
     */
    public class HttpClient {
        private String url;
        private Map<String, String> param;
        private int statusCode;
        private String content;
        private String xmlParam;
        private boolean isHttps;
    
        public boolean isHttps() {
            return isHttps;
        }
    
        public void setHttps(boolean isHttps) {
            this.isHttps = isHttps;
        }
    
        public String getXmlParam() {
            return xmlParam;
        }
    
        public void setXmlParam(String xmlParam) {
            this.xmlParam = xmlParam;
        }
    
        public HttpClient(String url, Map<String, String> param) {
            this.url = url;
            this.param = param;
        }
    
        public HttpClient(String url) {
            this.url = url;
        }
    
        public void setParameter(Map<String, String> map) {
            param = map;
        }
    
        public void addParameter(String key, String value) {
            if (param == null)
                param = new HashMap<String, String>();
            param.put(key, value);
        }
    
        public void post() throws ClientProtocolException, IOException {
            HttpPost http = new HttpPost(url);
            setEntity(http);
            execute(http);
        }
    
        public void put() throws ClientProtocolException, IOException {
            HttpPut http = new HttpPut(url);
            setEntity(http);
            execute(http);
        }
    
        public void get() throws ClientProtocolException, IOException {
            if (param != null) {
                StringBuilder url = new StringBuilder(this.url);
                boolean isFirst = true;
                for (String key : param.keySet()) {
                    if (isFirst)
                        url.append("?");
                    else
                        url.append("&");
                    url.append(key).append("=").append(param.get(key));
                }
                this.url = url.toString();
            }
            HttpGet http = new HttpGet(url);
            execute(http);
        }
    
        /**
         * set http post,put param
         */
        private void setEntity(HttpEntityEnclosingRequestBase http) {
            if (param != null) {
                List<NameValuePair> nvps = new LinkedList<NameValuePair>();
                for (String key : param.keySet())
                    nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
                http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
            }
            if (xmlParam != null) {
                http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
            }
        }
    
        private void execute(HttpUriRequest http) throws ClientProtocolException,
                IOException {
            CloseableHttpClient httpClient = null;
            try {
                if (isHttps) {
                    SSLContext sslContext = new SSLContextBuilder()
                            .loadTrustMaterial(null, new TrustStrategy() {
                                // 信任所有
                                public boolean isTrusted(X509Certificate[] chain,
                                        String authType)
                                        throws CertificateException {
                                    return true;
                                }
                            }).build();
                    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                            sslContext);
                    httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
                            .build();
                } else {
                    httpClient = HttpClients.createDefault();
                }
                CloseableHttpResponse response = httpClient.execute(http);
                try {
                    if (response != null) {
                        if (response.getStatusLine() != null)
                            statusCode = response.getStatusLine().getStatusCode();
                        HttpEntity entity = response.getEntity();
                        // 响应内容
                        content = EntityUtils.toString(entity, Consts.UTF_8);
                    }
                } finally {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                httpClient.close();
            }
        }
    
        public int getStatusCode() {
            return statusCode;
        }
    
        public String getContent() throws ParseException, IOException {
            return content;
        }
    
    }
    View Code

        HttpClient通俗的讲就是模拟了浏览器的行为,如果我们需要在后端向某一地址提交数据获取结果,就可以使用HttpClient。

        HttpClient工具类使用的步骤:

    HttpClient client=new HttpClient(请求的url地址);
    client.setHttps(true);//是否是https协议
    client.setXmlParam(xmlParam);//发送的xml数据
    client.post();//执行post请求
    String result = client.getContent(); //获取结果

        

    三.关键代码

      1.加入工具类HttpClient.java ,并添加依赖

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>              
    </dependency>

      配置文件weixinpay.properties

    appid=
    partner=
    partnerkey=
    notifyurl=  

      appid: 微信公众账号或开放平台APP的唯一标识

      partner:财付通平台的商户账号

      partnerkey:财付通平台的商户密钥

      notifyurl:  回调地址

      2.服务层代码

    @Service
    public class WeixinPayServiceImpl implements WeixinPayService {
    
        @Value("${appid}")
        private String appid;
        
        @Value("${partner}")
        private String partner;
        
        @Value("${partnerkey}")
        private String partnerkey;
        
        /**
         * 生成二维码
         * @return
         */
        public Map createNative(String out_trade_no,String total_fee){
            //1.创建参数
            Map<String,String> param=new HashMap();//创建参数
            param.put("appid", appid);//公众号
            param.put("mch_id", partner);//商户号
            param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串        
            param.put("body", "xiangmu");//商品描述
            param.put("out_trade_no", out_trade_no);//商户订单号
            param.put("total_fee",total_fee);//总金额(分)
            param.put("spbill_create_ip", "127.0.0.1");//IP
            param.put("notify_url", "http://baidu.com");//回调地址(随便写)
            param.put("trade_type", "NATIVE");//交易类型
            try {
                //2.生成要发送的xml 
                String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);
                System.out.println(xmlParam);    
                HttpClient client=new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
                client.setHttps(true);
                client.setXmlParam(xmlParam);
                client.post();        
                //3.获得结果 
                String result = client.getContent();
                System.out.println(result);
                Map<String, String> resultMap = WXPayUtil.xmlToMap(result);            
                Map<String, String> map=new HashMap<>();
                map.put("code_url", resultMap.get("code_url"));//支付地址
                map.put("total_fee", total_fee);//总金额
                map.put("out_trade_no",out_trade_no);//订单号
                return map;
            } catch (Exception e) {
                e.printStackTrace();
                return new HashMap<>();
            }            
        }
    }
    View Code

      注:签名sign在SDK工具中自动生成

       3.控制层

    /**
     * 支付控制层
     * @author Administrator
     *
     */
    @RestController
    @RequestMapping("/pay")
    public class PayController {
        @Reference
        private  WeixinPayService weixinPayService;
        
        /**
         * 生成二维码
         * @return
         */
        @RequestMapping("/createNative")
        public Map createNative(){
            IdWorker idworker=new IdWorker();        
            return weixinPayService.createNative(idworker.nextId()+"","1");        
        }
    }
    View Code

      4.前端调用

      

    app.service('payService',function($http){
        //本地支付
        this.createNative=function(){
            return $http.get('pay/createNative.do');
        }    
    });
    View Code

      

    app.controller('payController' ,function($scope ,payService){    
        //本地生成二维码
        $scope.createNative=function(){
            payService.createNative().success(
                function(response){
                    $scope.money=  (response.total_fee/100).toFixed(2) ;    //金额
                    $scope.out_trade_no= response.out_trade_no;//订单号
                    //二维码
                    var qr = new QRious({
                        element:document.getElementById('qrious'),
                        size:250,
                        level:'H',
                        value:response.code_url
                     });                
                }
            );        
        }        
    });

    设置二维码图片的ID

    <p class="red"></p>                      
             <div class="fl code">
                  <img id="qrious">
                  <div class="saosao">
                      <p>请使用微信扫一扫</p>
                      <p>扫描二维码支付</p>
             </div>
    </div>

    显示订单号

    订单号:{{out_trade_no}}

    显示金额

    <em  class="orange money">¥{{money}}</em>元

     

     

     

  • 相关阅读:
    机器学习(十七)— SVD奇异值分解
    机器学习(十五)— Apriori算法、FP Growth算法
    机器学习(十四)— kMeans算法
    深度学习—反卷积的理解
    【ECMAScript5】ECMAScript5中有关数组的常用方法
    【window】window10永久关闭更新
    【js】使用javascript 实现静态网页分页效果
    【vue】钩子函数生命周期
    【vue】vue中ref用法
    【vue-waring】element UI 由版本1.4.12 升级到element-ui@2.0.10
  • 原文地址:https://www.cnblogs.com/cracker13/p/9996591.html
Copyright © 2020-2023  润新知