1. 程式人生 > >Android 微信支付_掃碼支付,我來幫你填坑!

Android 微信支付_掃碼支付,我來幫你填坑!

0.概述:

本文講的是微信支付中的掃碼支付的模式二:該模式下,二維碼連結由微信支付返回給商戶,商戶將得到的二維碼連結轉成二維碼圖片,使用者通過掃碼支付,此方式下生成的二維碼2小時內有效。
微信支付官網地址:https://pay.weixin.qq.com/wiki/doc/api/index.html
這裡寫圖片描述

1.掃碼支付步驟:

  • 呼叫統一下單介面可獲取到一個二維碼連結引數code_url
  • 呼叫第三方庫將此連結code_url 轉成二維碼圖片,code_url連結內容為:weixin://wxpay/bizpayurl?sr=xxxx
  • 使用者開啟微信支付掃一掃完成支付
  • 定時呼叫查詢訂單介面確認是否支付是否完成
  • 退款介面

2.支付相關引數:

  • appid 公眾號ID (微信公眾平臺–>開發者中心檢視,商戶的微信支付稽核通過郵件中也會包含該欄位值)
  • mch_id 商戶ID 微信商戶平臺(帳戶中心-商戶資訊-微信支付商戶號)
  • out_trade_no 商戶訂單號(可以使用當前時間毫秒數)
  • key 商戶支付金鑰key(需要自己設定,為32位的金鑰)

3.支付相關介面地址:

4.android stdio使用相關包:

網路相關

compile files('libs/org.apache.httpcomponents.httpclient_4.5.3.jar'
)

二維碼相關:

    compile 'com.google.zxing:core:3.2.1'
    compile 'cn.bingoogolapple:bga-qrcodecore:1.1.7@aar'
    compile 'cn.bingoogolapple:bga-zxing:1.1.7@aar'

5.填坑記錄:

  1. 商戶支付金鑰key是自己設定的,一定和設定的一模一樣,不要有大小寫的轉換。
  2. 退款介面需要用到雙向證書https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_3。因此在程式碼上需要有體現。在android中只用到4箇中的apiclient_cert.p12,官網中說,【證書檔案不能放在web伺服器虛擬目錄,應放在有訪問許可權控制的目錄中,防止被他人下載。商戶伺服器要做好病毒和木馬防護工作,不被非法侵入者竊取證書檔案。】本文中,為了方便,我暫時將其放在assert資料夾中存放,程式碼中也有體現

    String result = null;
    // 證書密碼(預設為商戶ID)
    String password = Constent.VALUE_MCH_ID;
    // 例項化金鑰庫
    KeyStore ks = KeyStore.getInstance("PKCS12");
    // 獲得金鑰庫檔案流
    AssetManager am = context.getResources().getAssets();
    InputStream fis = am.open("apiclient_cert.p12");
    // 載入金鑰庫
    ks.load(fis, password.toCharArray());
    // 關閉金鑰庫檔案流
    fis.close();
    // 例項化金鑰庫
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    // 初始化金鑰工廠
    kmf.init(ks, password.toCharArray());
    // 建立SSLContext
    SSLContext sslContext = SSLContexts.custom()
            .loadKeyMaterial(ks, Constent.VALUE_MCH_ID.toCharArray())       //載入證書密碼,預設為商戶ID
            .build();
    sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
    // 獲取SSLSocketFactory物件
    SSLSocketFactory ssf = sslContext.getSocketFactory();
    

    4.還有很多坑,待補充….

6.1.終端呼叫統一下單介面,得到code_url

//1 統一下單
public String unifiedOrder() {
    SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();
    parameterMap.put(Constent.APPID, Constent.VALUE_APPID);//公眾號ID
    parameterMap.put(Constent.MCH_ID, Constent.VALUE_MCH_ID);//商戶號
    parameterMap.put(Constent.DEVICE_INFO, "");//裝置號
    parameterMap.put(Constent.NONCE_STR, PayCommonUtil.getRandomString(32));//隨機字串
    parameterMap.put(Constent.BODY, "");//商品描述
    parameterMap.put(Constent.SIGN_TYPE, Constent.MD);//簽名型別
    parameterMap.put(Constent.DETAIL, "");//商品詳情
    parameterMap.put(Constent.ATTACH, "");//附加資料
    time = System.currentTimeMillis() + "";
    parameterMap.put(Constent.OUT_TRADE_NO, time);//商戶訂單號
    parameterMap.put(Constent.FEE_TYPE, Constent.CNY);//標價幣種
    parameterMap.put(Constent.TOTAL_FEE, "");//標價金額
    parameterMap.put(Constent.SPBILL_CREATE_IP, "");//終端IP
    parameterMap.put(Constent.TIME_START, System.currentTimeMillis() + "");//交易起始時間
    //非同步接收微信支付結果通知的回撥地址,通知url必須為外網可訪問的,不能攜帶引數。
    parameterMap.put(Constent.NOTIFY_URL, "");//通知地址(支付結果通知)
    parameterMap.put(Constent.TRADE_TYPE, Constent.NATIVE);//交易型別
    parameterMap.put(Constent.PRODUCT_ID, "");//商品ID(和裝置ID一起需知,掃碼支付時必須傳)
    parameterMap.put(Constent.LIMIT_PAY, Constent.NO_CREDIT);//指定支付方式
    parameterMap.put(Constent.SIGN, PayCommonUtil.createSign(Constent.UTF, parameterMap));//簽名
    String requestXML = PayCommonUtil.getRequestXml(parameterMap);//將請求組裝成xml形式
    String result = PayCommonUtil.httpsRequest(
            Constent.URL_TONGYI_XIADAN, Constent.POST,
            requestXML);//呼叫統一支付介面返回String型別字串
    Map<String, String> map = null;
    try {
        map = PayCommonUtil.xmlToMap(result);//將返回的結果轉為map形式
    } catch (Exception e) {
        e.printStackTrace();
    }
    return map.get(Constent.CODE_URL);//得到code_url用來生成二維碼
}

6.2.終端使用code_url生成二維碼

    private void createQRCode() {
        //匿名內部類導致Activity記憶體洩漏的問題待解決
        new AsyncTask<Void, Void, Bitmap>() {
            @Override
            protected Bitmap doInBackground(Void... params) {
                System.out.println("ds>>>  生成二維碼成功");
                return QRCodeEncoder.syncEncodeQRCode(unifiedOrder(), BGAQRCodeUtil.dp2px(WechatPaymentActivity.this, 150));
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                if (bitmap != null) {
                    iv.setImageBitmap(bitmap);
                } else {
                    System.out.println("ds>>>  生成二維碼失敗");
                }
            }
        }.execute();
    }

6.3.使用者開啟微信支付掃一掃完成支付

無程式碼,不需終端操作

6.4.終端定時呼叫查詢訂單介面確認是否支付是否完成

注意:1.在主執行緒中不能進行網路操作 2.需要做定時操作

handler2.post(runnable2);//在main中呼叫

Handler handler2 = new Handler();

Runnable runnable2 = new Runnable() {
    @Override
    public void run() {
        new Thread(new Runnable() {//每次都要開一個執行緒去查詢訂單情況,直到有使用者支付成功的結果。
            @Override
            public void run() {
                checkOrder();
            }
        }).start();
        handler2.postDelayed(runnable2, 5000);
    }
};

// 2 查詢訂單
public void checkOrder() {
    SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();
    parameterMap.put(Constent.APPID, Constent.VALUE_APPID);//公眾號ID
    parameterMap.put(Constent.MCH_ID, Constent.VALUE_MCH_ID);//商戶號
    parameterMap.put(Constent.OUT_TRADE_NO, time);//商戶訂單號
    parameterMap.put(Constent.NONCE_STR, PayCommonUtil.getRandomString(32));//隨機字串
    parameterMap.put(Constent.SIGN, PayCommonUtil.createSign(Constent.UTF, parameterMap));//簽名
    String requestXML = PayCommonUtil.getRequestXml(parameterMap);//將請求組裝成xml形式
    String result = PayCommonUtil.httpsRequest(
            Constent.URL_CHAXUN_DINGDAN, Constent.POST,
            requestXML);//呼叫查詢訂單介面返回String型別字串
    Map<String, String> map = null;
    try {
        if (result != null)
            map = PayCommonUtil.xmlToMap(result);//將返回的結果轉為map形式
    } catch (Exception e) {
        e.printStackTrace();
    }
    if (map != null)
        packageParams = PayCommonUtil.getSortedMap(map);//將map中空的過濾掉
    if (packageParams != null && PayCommonUtil.isTenpaySign(Constent.UTF, packageParams, Constent.VALUE_API_KEY)) {
        handler.post(runnable);//在新的執行緒去匹配返回的資訊,做相應的UI變化
    } else {
        System.out.println("通知簽名驗證失敗");
    }
}

Handler handler = new Handler();

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        try {
            updateUI(packageParams);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

private void updateUI(SortedMap<Object, Object> packageParams) throws InterruptedException {
    String result_code = (String) packageParams.get(Constent.RESULT_CODE);
    String return_code = (String) packageParams.get(Constent.RETURN_CODE);
    String trade_state = (String) packageParams.get(Constent.TRADE_STATE);
    String trade_state_desc = (String) packageParams.get(Constent.TRADE_STATE_DESC);
    String error_code = (String) packageParams.get(Constent.ERROR_CODE);
    System.out.println("ds>>>  result_code=" + result_code + ", return_code=" + return_code + ", trade_state=" + trade_state);
    System.out.println("ds>>>  trade_state_desc=" + trade_state_desc + ", error_code=" + error_code);
    if (result_code.equals(Constent.SUCCESS) && return_code.equals(Constent.SUCCESS) && trade_state.equals(Constent.SUCCESS)) {
        handler2.removeCallbacks(runnable2);
        //支付成功,做相關邏輯。
    } else if (Constent.PAYERROR.equals(packageParams.get(Constent.TRADE_STATE))) {
        handler2.removeCallbacks(runnable2);
        //支付失敗,做相關邏輯。
    }
}

6.5.退款介面

    //5 如果驗證失敗,需申請退款
    public void refundMoney() throws Exception {
    SortedMap<String,Object>parameterMap=new TreeMap<String,Object>();
    parameterMap.put(Constent.APPID, Constent.VALUE_APPID);//公眾號ID
    parameterMap.put(Constent.MCH_ID, Constent.VALUE_MCH_ID);//商戶號
    parameterMap.put(Constent.OUT_TRADE_NO, getIntent().getStringExtra(Constent.VALUE_OUT_TRADE_NO));//商戶訂單號
    parameterMap.put(Constent.NONCE_STR, PayCommonUtil.getRandomString(32));//隨機字串
    parameterMap.put(Constent.SIGN_TYPE, "MD5");
    parameterMap.put(Constent.OUT_REFUND_NO, System.currentTimeMillis() + "");//商戶退款單號
    parameterMap.put(Constent.TOTAL_FEE, "1");//訂單金額
    parameterMap.put(Constent.REFUND_FEE, "1");//退款金額
    parameterMap.put(Constent.REFUND_FEE_TYPE, "CNY");//貨幣種類
    parameterMap.put(Constent.REFUND_DESC, "商品驗證失敗");//退款原因
    parameterMap.put(Constent.REFUND_ACCOUNT, "refund reason");//退款資金來源
    parameterMap.put(Constent.SIGN, PayCommonUtil.createSign("UTF-8", parameterMap));//簽名
    String requestXML = PayCommonUtil.getRequestXml(parameterMap);
    System.out.println("ds>>> requestXML3 = " + requestXML);
    String result = PayCommonUtil.httpsRequest(ValidateIdcardActivity.this, requestXML);
    System.out.println("ds>>> result3 = " + result);
    Map<String, String> map = null;
    try {
        map = PayCommonUtil.xmlToMap(result);
    } catch (Exception e) {
        e.printStackTrace();
    }
    SortedMap<Object, Object> packageParams = PayCommonUtil.getSortedMap(map);
    String key = Constent.VALUE_API_KEY;
    String result_code = (String) packageParams.get(Constent.RESULT_CODE);
    String mch_id = (String) packageParams.get(Constent.MCH_ID);//商戶號
    String total_fee = (String) packageParams.get(Constent.TOTAL_FEE);//總金額
    String trade_state = (String) packageParams.get(Constent.TRADE_STATE);//交易狀態
    System.out.println("ds>>>   trade_state:" + trade_state);
    System.out.println("ds>>>   mch_id:" + mch_id);
    System.out.println("ds>>>   total_fee:" + total_fee);
    if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {
        handleResult(packageParams, result_code, mch_id, total_fee, trade_state);
    } else {
        System.out.println("通知簽名驗證失敗");
    }
}

private void handleResult(final SortedMap<Object, Object> packageParams, final String result_code, final String mch_id, final String total_fee, final String trade_state) {
    handler.post(new Runnable() {
        @Override
        public void run() {
            if (Constent.SUCCESS.equals(result_code)) {
                tv_validating.setText(getString(R.string.txt_validate_timeout));
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finish();
            } else {
                System.out.println("退款失敗,錯誤資訊:" + packageParams.get("err_code"));
            }
        }
    });
}
  Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                refundMoney();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
   new Thread(runnable).start();

6.6 使用到的工具類


public class PayCommonUtil {
    //判斷簽名是否正確
    public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (!"sign".equals(k) && null != v && !"".equals(v)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + API_KEY);
        //算出摘要
        String mysign = MD5Encode(sb.toString(), characterEncoding).toLowerCase();
        String tenpaySign = ((String) packageParams.get("sign")).toLowerCase();
        return tenpaySign.equals(mysign);
    }

    //生成簽名
    public static String createSign(String characterEncoding, SortedMap<String, Object> parameters) {
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + Constent.VALUE_API_KEY);
        String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

    private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));

        return resultSb.toString();
    }

    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            resultString = byteArrayToHexString(md.digest(resultString
                    .getBytes("UTF-8")));
        } catch (Exception exception) {
        }
        return resultString;
    }

    //隨機字串生成
    public static String getRandomString(int length) { //length表示生成字串的長度
        String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    //請求xml組裝
    public static String getRequestXml(SortedMap<String, Object> parameters) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            sb.append("<" + key + ">" + value + "</" + key + ">");
        }
        sb.append("</xml>");
        return sb.toString();
    }

    //請求方法
    public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        try {
            URL url = new URL(requestUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 設定請求方式(GET/POST)
            conn.setRequestMethod(requestMethod);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            // 當outputStr不為null時向輸出流寫資料
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意編碼格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }
            // 從輸入流讀取返回內容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            // 釋放資源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            return buffer.toString();
        } catch (ConnectException ce) {
            System.out.println("連線超時");
            ce.printStackTrace();
        } catch (Exception e) {
            System.out.println("https請求異常");
            e.printStackTrace();
        }
        return null;
    }

    public static String httpsRequest(Context context, String data) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException, CertificateException, NoSuchProviderException {
        String result = null;
        // 證書密碼(預設為商戶ID)
        String password = Constent.VALUE_MCH_ID;
        // 例項化金鑰庫
        KeyStore ks = KeyStore.getInstance("PKCS12");
        // 獲得金鑰庫檔案流
        AssetManager am = context.getResources().getAssets();
        InputStream fis = am.open("apiclient_cert.p12");
        // 載入金鑰庫
        ks.load(fis, password.toCharArray());
        // 關閉金鑰庫檔案流
        fis.close();
        // 例項化金鑰庫
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        // 初始化金鑰工廠
        kmf.init(ks, password.toCharArray());
        // 建立SSLContext
        SSLContext sslContext = SSLContexts.custom()
                .loadKeyMaterial(ks, Constent.VALUE_MCH_ID.toCharArray())       //載入證書密碼,預設為商戶ID
                .build();
        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
        // 獲取SSLSocketFactory物件
        SSLSocketFactory ssf = sslContext.getSocketFactory();
        URL url = new URL(Constent.URL_TUIKUAN);
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        //設定當前例項使用的SSLSocketFactory
        conn.setSSLSocketFactory(ssf);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.connect();
        DataOutputStream out = new DataOutputStream(
                conn.getOutputStream());
        if (data != null)
            out.writeBytes(data);
        out.flush();
        out.close();
        //獲取輸入流
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        int code = conn.getResponseCode();
        if (HttpsURLConnection.HTTP_OK == code) {
            String temp = in.readLine();
            while (temp != null) {
                if (result != null)
                    result += temp;
                else
                    result = temp;
                temp = in.readLine();
            }
        }
        return result;
    }

    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        try {
            Map<String, String> data = new HashMap<String, String>();
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            try {
                stream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return data;
        } catch (Exception ex) {
            ex.printStackTrace();
            throw ex;
        }

    }

    @NonNull
    public static SortedMap<Object, Object> getSortedMap(Map<String, String> map) {
        //過濾空 設定 TreeMap
        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        Iterator it = map.keySet().iterator();
        while (it.hasNext()) {
            String parameter = (String) it.next();
            String parameterValue = map.get(parameter);

            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }
        return packageParams;
    }
}

後話:由於微信支付相關所有的程式碼和請求都是在android端做,因此有了這篇文章的存在,記錄下來為了和我一樣更多的人可以高效工作完成微信支付相關。有程式碼上的錯誤,歡迎大家及時指出。

相關推薦

Android 支付_支付

0.概述: 本文講的是微信支付中的掃碼支付的模式二:該模式下,二維碼連結由微信支付返回給商戶,商戶將得到的二維碼連結轉成二維碼圖片,使用者通過掃碼支付,此方式下生成的二維碼2小時內有效。 微信支付官網地址:https://pay.weixin.qq.com/

統一下單_公眾號支付_支付

微信掃碼支付流程圖:https://pay.weixin.qq.com/wiki/doc/api/native_sl.php?chapter=6_5&index=4 微信公眾號支付流程圖:https://pay.weixin.qq.com/wiki/doc/api/

破解WiFi密碼如何操作?一招檢視密碼

對用手機使用者來說我們使用最多的軟體莫過於騰訊的微信了!對於使用最為廣泛的軟體來說,如果能夠幫助我們解決網路問題那無疑是最好的,因為有時你們破解wifi還要下載一大堆破解軟體。現在直接通過微信就能破解WIFI了。而且還能檢視破解密碼。 下面小編就和你們講解一下吧: 一

支付代理加盟 支付支付申請條件

微信支付代理 微信支付加盟 支付寶支付掃碼申請我們先了解一下移動支付收單服務優勢吧? 加入采寶移動支付收單的優勢: 一、收單方式更為的快速,便捷,顧客只要在準備付錢時打開支付寶錢包或微信錢包給收銀員用掃描槍掃一下就完成交易了,不用找零,不用簽字,資金實時到賬,更杜絕了假幣風險。 二、政

支付----PC支付(查詢支付訂單判斷是否支付成功)

微信支付 c#webapi建議前端輪番查詢訂單狀態 #region 查詢掃碼訂單狀態 /// <summary> /// 查詢掃碼支付狀態 /// </summary> /// <param name=&

支付支付、公眾號支付、H5支付、小程序支付相關業務流程分析總結

doc bsp 說明 引入 red 內容 bubuko url參數 數據 前言 很久以來,一直想寫一篇微信支付有關的總結文檔;一方面是總結自己的一些心得,另一方面也可以幫助別人,但是因種種原因未能完全理解透徹微信支付的幾大支付方式,今天有幸做一些總結上的文章,也趁此機會,將

關於tp5使用支付寶app支付支付

<?php /** * Created by PhpStorm. * User: ljy * Date: 17/10/14 * Time: 下午3:33 */ namespace app\api\controller; use Pingpp\Pingpp; use Pingpp\Charge

PHP支付支付

在手機微信端進行微信支付,直接調起JSAPI支付,這可以實現在微信裡邊的開的頁面進行支付,比如微商城,微信端JSAPI支付詳見:;但有時候商城還有PC端,需要在PC端使用微信支付,則需要PC端生成支付二維碼,然後微信掃碼完成支付。例如: 這裡主要講一下PC端掃碼支付以及退

支付之-支付-模式2(模式1)

微信商戶申請開通:https://pay.weixin.qq.com/service_provider/index.shtml 注意:開通公眾賬號之後,然後根據流程開通相對應的商戶平臺 開發文件

一個PHP檔案搞定支付系列之原生支付支付

<?php header('Content-type:text/html; Charset=utf-8'); $mchid = 'xxxxx'; //微信支付商戶號 PartnerID 通過微信支付商戶資料稽核後郵件傳送 $appid = 'xxxxx'; //公眾號APPID 通過

支付支付相關程式碼(Java)

          最近開發網站過程,需要引入支付過程,第三方支付中最火的莫過於支付寶支付和微信支付,下邊藉助微信支付官網上的文件,寫一下接入微信支付之掃碼支付的流程 相對支付寶支付而言,微信支付的開發文件寫的相當的low,demo寫的一點都不簡潔,下邊寫一下微信掃碼支付的

java--spring boot支付服務端實現含程式碼(app支付支付等)

最近在弄支付寶、微信支付等的事,發現這兩家的文件都寫得很差,demo也讓人看的雲裡霧裡。所以寫篇部落格,來儘量減少後來的同學走的彎路。 首先,若是要做app支付的話,在微信第三方平臺申請APP,若是安卓的話上傳你的keystore和包名,ios上傳bundle id,微信會

支付支付開發:遇到的及解決辦法(附:Ecshop 支付外掛)

      前段時間幫一個朋友的基於ecshop開發的商城加入微信掃描支付功能,本以為是很簡單的事兒——下載官方sdk或開發幫助文件,按著裡面的做就ok了,誰知折騰了兩三天的時間才算搞定,中間也帶著疑問在網上找了不少技術文章,卻發現都只是比較粗略的寫他們是怎麼開發接入的,並沒有解決我遇到的問題...,唉,有時

8. PHP接入微的三種支付:APP支付、公眾號支付支付

微信的支付邏輯與支付寶的支付有一些差別。為了讓客戶端忽略這些差別,統一呼叫。本sdk做了對應處理。 # SDK呼叫 微信支付不同介面需要的引數會有差別。請大家在使用介面時,仔細檢視文件。 use Payment\ChargeContext; use

Android登入、分享、支付

前言 大部分的app都有接入第三方sdk的需求。例如第三方登入需要接入微信、QQ、微博。第三方支付需要接入微信、支付寶、銀聯。 這些我都有使用過,都有使用過他們的sdk,感覺最麻煩的就是微信,不能直接除錯,得用正式的簽名進行簽名才能除錯。還有他們官方的demo也是跑不

支付支付開發——當面付條碼支付支付

找到 生成二維碼 uil ebr eqv 超過 id號 xe8 trigger 本文介紹支付寶中當面付下屬的條碼支付、掃碼支付、訂單查詢、退款申請的集成開發過程。 本文分為以下五個部分: 條碼支付和掃碼支付介紹 申請應用 密鑰生成及配置 API及SDK集成 條碼支付、

小程序-點餐系統設計

設計 小程序 點餐 規格 程序 消費 信號 備註 狀態 實體:   消費者(id,微信號)   商家(id,商家名,商家簡介,營業執照)   菜單(id,商家,菜品名,菜品介紹,菜品照片,大,中,小)   訂單(id,商家,消費者,創建時間,數量,狀態,總價,收付款,,完成

支付支付的解決方案及掃描槍的選擇

場景 運行 時代 發展 工作 配方 過萬 落地 服務質量 應用背景: 移動互聯網時代的發展是不可逆的,未來大眾的消費習慣都在移動端。如何利用條碼,連接消費者和商戶,並通過手機完成支付,使整個支付過程更加便捷、更加靈活。支付寶以超強的創新能力和市場開拓能力,成為條碼支付的領導

公眾號登陸原理及程式碼實現

1.使用者開啟公眾號點選掃碼功能(注意我們用 scancode_waitmsg這種型別即可)  2.使用者掃描了二維碼會給微信傳送資訊,然後微信把資訊以XML格式傳送給我們的伺服器 3.接收資料,並把資料保存於資料庫或者快取,程式碼如下: $wechatObj = new

該如何解決公眾號登陸PC?

電腦端通過微信公眾號網頁或H5頁面的登陸資訊掃碼登陸解決方案。 至今為止還不是很完善,所以免費提供。 頁面LOW到爆,畢竟是程式猿寫的。後面有需要的話我再讓我們團隊的設計師重新設計過頁面。暫時只是研究用途,就不勞煩設計師了。 如果你們有需要的話可以自行下載修改。 有任何問題