1. 程式人生 > >微信掃碼支付與生成二維碼

微信掃碼支付與生成二維碼

@param 開源 生成二維碼 退出 lin pack java 金額 als

二維碼

  (1) 容錯級別

    L(低) 7%的碼字可以被恢復。

    M級(中) 的碼字的15%可以被恢復。

    Q級(四分)的碼字的25%可以被恢復。

    H級(高) 的碼字的30%可以被恢復。

  (2) 二維碼生成插件qrious

    qrious是一款基於HTML5 Canvas的純JS二維碼生成插件。通過qrious.js可以快速生成各種二維碼,你可以控制二維碼的尺寸顏色,還可以將生成的二維碼進行Base64編碼。

    qrious.js二維碼插件的可用配置參數如下:

參數

類型

默認值

描述

background

String

"white"

二維碼的背景顏色。

foreground

String

"black"

二維碼的前景顏色。

level

String

"L"

二維碼的誤差校正級別(L, M, Q, H)

mime

String

"image/png"

二維碼輸出為圖片時的MIME類型。

size

Number

100

二維碼的尺寸,單位像素。

value

String

""

需要編碼為二維碼的值

web引入qrious.js

qrious.min.js

微信支付SDK

  (1) 解壓WxPayAPI_JAVA_v3.zip

  (2) 將解壓的maven工程導入到IDE(eclipse)

  (3) 打成jar包,並安裝到maven倉庫

mvn install:install-file -Dfile=d:\setup\wxpay-sdk-0.0.3.jar -DgroupId=com.github.wxpay -DartifactId=wxpay-sdk -Dversion=0.0.3 -Dpackaging=jar

  (4) 在要使用微信掃碼支付的工程引入依賴

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

HttpClient工具類

  HttpClientApache Jakarta Common下的子項目,用來提供高效的、最新的、功能豐富的支持HTTP協議的客戶端編程工具包,並且它支持HTTP協議最新的版本和建議。HttpClient已經應用在很多的項目中,比如Apache Jakarta上很著名的另外兩個開源項目CactusHTMLUnit都使用了HttpClient

  HttpClient通俗的講就是模擬了瀏覽器的行為,如果我們需要在後端向某一地址提交數據獲取結果,就可以使用HttpClient.

  關於HttpClient(原生)相對比較麻煩,進行封裝,使用封裝後的工具類HttpClient(對原生HttpClient進行了封裝)

HttpClient工具類使用的步驟 

HttpClient client=new HttpClient(請求的url地址);
client.setHttps(true);//是否是https協議
client.setXmlParam(xmlParam);//發送的xml數據
client.post();//執行post請求
String result = client.getContent(); //獲取結果

添加配置文件weixinpay.properties

## 微信公眾賬號或開放平臺APP的唯一標識
appid=****************
## 財付通平臺的商戶賬號
partner=*********
## 財付通平臺的商戶密鑰
partnerkey=*********************************
## 回調地址
notifyurl=http://a31ef7db.ngrok.io/WeChatPay/WeChatPayNotify

將二維碼插件QRious拷貝到web plugins目錄中

後端代碼(ServiceImpl)

@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", "xxx");//商品描述
        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://www.xxx.cn");//回調地址(隨便寫)
        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<>();
        }            
    }
}

後端代碼(Controller)

/**
 * 支付控制層
 * @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");        
    }
}

前端代碼,先引入angular.js

angular.min.js

base.js

var app = angular.module(‘xxx‘, []);

Service.js

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

Controller.js

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),// 根據id選擇元素
                    size:250,
                    level:‘H‘,
                    value:response.code_url
                 });                
            }
        );        
    }        
});

html頁面

  引入js

<script type="text/javascript" src="plugins/angularjs/angular.min.js">  </script>
    <script type="text/javascript" src="js/base.js">  </script>
    <script type="text/javascript" src="js/service/payService.js">  </script>
    <script type="text/javascript" src="js/controller/payController.js">  </script>
    <script type="text/javascript" src="plugins/qrious.min.js"></script>

  指令

<body ng-app="pinyougou" ng-controller="payController" ng-init="createNative()">

  html代碼

<p class="red"></p>                      
         <div class="fl code">
              <img id="qrious">
              <div class="saosao">
                  <p>請使用微信掃一掃</p>
                  <p>掃描二維碼支付</p>
         </div>
</div>

微信掃碼支付狀態

  後端(ServiceImpl)

@Override
    public Map queryPayStatus(String out_trade_no) {
        Map param=new HashMap();
        param.put("appid", appid);//公眾賬號ID
        param.put("mch_id", partner);//商戶號
        param.put("out_trade_no", out_trade_no);//訂單號
        param.put("nonce_str", WXPayUtil.generateNonceStr());//隨機字符串
        String url="https://api.mch.weixin.qq.com/pay/orderquery";        
        try {
            String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);    
            HttpClient client=new HttpClient(url);
            client.setHttps(true);
            client.setXmlParam(xmlParam);
            client.post();
            String result = client.getContent();            
            Map<String, String> map = WXPayUtil.xmlToMap(result);
            System.out.println(map);
            return map;            
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }    
    }

後端代碼(Controller)

/**
     * 查詢支付狀態
     * @param out_trade_no
     * @return
     */
    @RequestMapping("/queryPayStatus")
    public Result queryPayStatus(String out_trade_no){
        Result result=null;
     int x = 0;     
while(true){ //調用查詢接口 Map<String,String> map = weixinPayService.queryPayStatus(out_trade_no); if(map==null){//出錯 result=new Result(false, "支付出錯"); break; } if(map.get("trade_state").equals("SUCCESS")){//如果成功 result=new Result(true, "支付成功"); break; } try { Thread.sleep(3000);//間隔三秒 } catch (InterruptedException e) { e.printStackTrace(); }
        //為了不讓循環無休止地運行,我們定義一個循環變量,如果這個變量超過了這個值則退出循環,設置時間為5分鐘
        x++;
        if(x>=100){
          result=new Result(false, "二維碼超時");
          //1.調用微信的關閉訂單接口(學員實現)
          Map<String,String> payresult = weixinPayService.closePay(out_trade_no);
          if( !"SUCCESS".equals(payresult.get("result_code")) ){//如果返回結果是正常關閉
            if("ORDERPAID".equals(payresult.get("err_code"))){
              result=new Result(true, "支付成功");
              seckillOrderService.saveOrderFromRedisToDb(userId, Long.valueOf(out_trade_no), map.get("transaction_id"));
              }
          }
          if(result.isSuccess()==false){
            System.out.println("超時,取消訂單");
            //2.調用刪除
            seckillOrderService.deleteOrderFromRedis(userId, Long.valueOf(out_trade_no));
          }
          break;
        } } return result; }

前端js

  Controller.js

//查詢支付狀態 
    queryPayStatus=function(out_trade_no){
        payService.queryPayStatus(out_trade_no).success(
            function(response){
                if(response.success){
                    location.href="paysuccess.html";
                }else{
            if(response.message==‘二維碼超時‘){
              location.href="payTimeOut.html";
            }else{
              location.href="payfail.html";
            } } } ); }

  Service.js

  修改createNative方法

//本地生成二維碼
    $scope.createNative=function(){
        payService.createNative().success(
            function(response){
                ..........                
                 queryPayStatus(response.out_trade_no);//查詢支付狀態                
            }
        );        
    }

關閉微信掃碼支付

  後端代碼(ServiceImpl)

@Override
    public Map closePay(String out_trade_no) {
        Map param=new HashMap();
        param.put("appid", appid);//公眾賬號ID
        param.put("mch_id", partner);//商戶號
        param.put("out_trade_no", out_trade_no);//訂單號
        param.put("nonce_str", WXPayUtil.generateNonceStr());//隨機字符串
        String url="https://api.mch.weixin.qq.com/pay/closeorder";
        try {
            String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);
            HttpClient client=new HttpClient(url);
            client.setHttps(true);
            client.setXmlParam(xmlParam);
            client.post();
            String result = client.getContent();
            Map<String, String> map = WXPayUtil.xmlToMap(result);
            System.out.println(map);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }        
    }

後端代碼(Controller)
  修改queryPayStatus方法

前端代碼

  修改queryPayStatus方法

微信掃碼支付與生成二維碼