微信雲支付的掃碼支付

前言

之前研究微信雲支付的掃碼支付,我將認爲重要的內容在本文中分享給大家。

微信雲支付相關介紹

微信雲支付的相關特點文檔中已經介紹的很清楚了,這裏就不在介紹了。
微信雲支付文檔

何爲掃碼支付

1.“商戶主動下單,爲每個訂單生成一個二維碼,顧客打開掃一掃進行掃碼後,完成支付”
2.“每個訂單一個單獨的二維碼”
3.“收銀機具需要有給顧客展示二維碼的屏幕,顧客掃碼支付”
4.“希望用戶可以在收銀機上自助點餐的商戶,如肯德基等”

注意:掃碼支付的二維碼是微信和支付各生成一個,並不是共用同一個二維碼

本文介紹掃碼支付的支付和退款後臺接口的編寫,其餘功能可根據這兩個功能中參數的拼接方法,基本都可以實現

掃碼支付

1.準備工作
註冊微信支付和支付寶支付的相關服務商賬號以及微信雲支付的賬號,並配置好門店信息,如device_infos和staff_infos(這些信息在請求門店信息中要返回給客戶端,可以見微信雲支付的請求門店信息的API:請求門店信息)等,具體可以見微信支付、支付寶支付以及微信雲支付的相關文檔。
2.計算認證碼
微信雲支付官方文檔中提供的是C++版的示例代碼,計算認證碼的算法是HMAC-SHA256。如果使用C++開發,請查看C++示例代碼

請求必須傳認證或簽名信息。其中退款請求,傳簽名和簽名算法,其他請求傳認證碼和認證算法。

計算認證碼的方法:

    public static String caculateAuthenCode(String key, String data) {
        Mac sha256_HMAC = null;
        String hash = null;
        try {
            sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            hash = DatatypeConverter.printHexBinary(sha256_HMAC.doFinal(data.getBytes("UTF-8")));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return hash;
    }

其中參數key是雲支付提供的“認證祕鑰”裏的字符串,data是你要加密的數據,也就是組織好的json格式的參數。
這裏寫圖片描述
3.請求門店信息
因爲掃碼支付的有些請求參數需要在請求門店信息接口返回的數據中獲取,例如調用微信雲支付的請求門店信息的接口,來獲取門店賬號(out_shop_id)、終端設備號(device_id)、店員ID(staff_id)以及終端類型(terminal_type)。
根據查詢門店信息接口文檔,編寫請求參數request_content和authen_info,如下

{
    "request_content": "{\"out_mch_id\":\"雲支付分配給服務商的帳號\",\"out_sub_mch_id\":\"雲支付分配給子商戶的帳號\",\"nonce_str\":\"26f827a651761f7d\",\"page_num\":1,\"page_size\":100}",
    "authen_info": {
        "a": {
            "authen_code": "計算得到的認證碼",
            "authen_type": 1
        }
    }
}

請求示例代碼

  public String request(String url, String requestContent, AuthenInfo authenInfo) {
        String responseContent = null;
        try {
            CloseableHttpClient client = HttpClients.createDefault();
            HttpPost post = new HttpPost();
            post.setURI(new URI(url));
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("request_content", "\"" + requestContent + "\"");//json字符串
            jsonObject.put("authen_info", authenInfo);//json對象
            StringEntity urlEncodedFormEntity = new StringEntity(jsonObject.toString(), "utf-8");//解決中文亂碼問題
            urlEncodedFormEntity.setContentEncoding("UTF-8");
            urlEncodedFormEntity.setContentType("application/json");//發送json數據需要設置contentType
            post.setEntity(urlEncodedFormEntity);
            CloseableHttpResponse response = client.execute(post);
            HttpEntity entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return responseContent;
    }

值得注意的是參數request_content的結構是json字符串,參數authen_info是json對象,見上面的代碼。
status爲0代表請求成功
從返回的內容中獲取門店賬號(out_shop_id)、終端設備號(device_id)、店員ID(staff_id)以及終端類型(terminal_type)

3.根據微信雲支付的掃碼支付接口文檔,編寫請求參數
我們可以根據文檔中給的參數的類型,編寫javabean 然後組織成json字符串,例如

請求內容:

{
    "pay_mch_key": {
        "pay_platform": 1,
        "out_mch_id": "雲支付分配給服務商的帳號,固定20個數字或者字母",
        "out_sub_mch_id": "雲支付分配給子商戶的帳號,固定20個數字或者字母",
        "out_shop_id": "雲支付唯一標識門店的賬號"
    },
    "pay_content": {
        "out_trade_no": "雲支付訂單前綴46f827a751761fff",
        "total_fee": 60,
        "fee_type": "CNY",
        "body": "訂單介紹",
        "wxpay_pay_content_ext": {
            "attach": "1",
            "goods_tag": "1234",
            "product_id": "spidSPBH129I902",
            "limit_pay": "no_credit"
        }
    },
    "order_client": {
        "device_id": "終端設備號",
        "staff_id": "店員ID",
        "terminal_type": 終端類型,
        "sdk_version": "SDK",
        "spbill_create_ip": "調用雲支付API的機器IP"
    },
    "nonce_str": "16f827a651761f77"
}

認證信息

    {
        "a": {
            "authen_code": "計算得到的認證碼",
            "authen_type": 1
        }
    }

完成的請求參數結構

{
    "request_content": "{\"pay_mch_key\":{\"pay_platform\":1,\"out_mch_id\":\"雲支付分配給服務商的帳號\",\"out_sub_mch_id\":\"雲支付分配給子商戶的帳號\",\"out_shop_id\":\"雲支付唯一標識門店的賬號\"},\"pay_content\":{\"out_trade_no\":\"雲支付訂單前綴46f827a751761fff\",\"total_fee\":60,\"fee_type\":\"CNY\",\"body\":\"訂單介紹\",\"wxpay_pay_content_ext\":{\"attach\":\"1\",\"goods_tag\":\"1234\",\"product_id\":\"spidSPBH129I902\",\"limit_pay\":\"no_credit\"}},\"order_client\":{\"device_id\":\"終端設備號\",\"staff_id\":\"店員ID\",\"terminal_type\":終端類型,\"sdk_version\":\"SDK\",\"spbill_create_ip\":\"調用雲支付API的機器IP\"},\"nonce_str\":\"16f827a651761f77\"}",
    "authen_info": {
        "a": {
            "authen_code": "通過計算得到的認證碼",
            "authen_type": 1
        }
    }
}

值得注意的是,

爲了保護不同商戶的訂單號不重複,雲支付爲每個服務商錄入的子商戶分配了“雲支付訂單前綴”,在雲支付後臺的商戶詳情中可以看到,該商戶的訂單和退款單必須以雲支付子商戶號做前綴。

out_trade_no是雲支付訂單前綴加自定義字符串構成,比如,我的雲支付訂單前綴是ABCdfFS,則我可以設置訂單號爲
ABCdfFS46f827a7517,訂單前綴跟自定義字符串之前不能有特殊字符“+”或者“-”等

請求示例代碼

    public String request(String url, String requestContent, AuthenInfo authenInfo) {
        String responseContent = null;
        try {
            CloseableHttpClient client = HttpClients.createDefault();
            HttpPost post = new HttpPost();
            post.setURI(new URI(url));
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("request_content", "\"" + requestContent + "\"");//json字符串
            jsonObject.put("authen_info", authenInfo);//json對象
            StringEntity urlEncodedFormEntity = new StringEntity(jsonObject.toString(), "utf-8");//解決中文亂碼問題
            urlEncodedFormEntity.setContentEncoding("UTF-8");
            urlEncodedFormEntity.setContentType("application/json");//發送json數據需要設置contentType
            post.setEntity(urlEncodedFormEntity);
            CloseableHttpResponse response = client.execute(post);
            HttpEntity entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return responseContent;
    }

請求成功,返回數據示例:

這裏寫圖片描述

根據請求得到的code_url,Android或iOS端就可以生成二維碼進行展示了

值得注意的是,訂單是有過期時間的,可以自己指定過期時間(見文檔),也可以不指定,不指定過期時間的話,默認過期時間是1分半鐘,也就是說,如果此時沒有掃碼支付,這個訂單就過期了,得重新生成一個訂單並請求獲取二維碼。

下一篇文章:微信雲支付的退款

OVER

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章