個人我的網站如何實現支付功能?java
想必不少程序員都有過想開發一個本身的網站來得到一些額外的收入,但作這件事會遇到支付這個問題。目前我的網站是沒法實現支付功能的。程序員
今天我就給你們分享一下個人實現方案:《基於xposed逆向微信、支付寶、雲閃付來實現我的免籤支付方案》web
測試頁面(點我) 微信
接下來給你們簡單分享一下實現過程,這個過程實際上是很是複雜的,關鍵點在於如何逆向微信支付寶雲閃付這些App,找到核心函數鉤子,而後寫一個hook程序來模擬調用這些方法,來實現根據服務端傳過來的金額,訂單號自動調用微信支付寶生成支付二維碼的函數獲得相對應的支付二維碼再傳給服務端,而後監聽微信支付寶的支付成功消息最終回調給服務端實現支付成功通知。這裏面用到的核心技術點有:xposed逆向框架、apk反編譯,網絡抓包,apk動態調試等技術。websocket
像微信支付寶這些apk反編譯後的代碼基本上都是天書同樣的,嚴重混淆過的代碼。想從中找到核心代碼並不是易事,下面我貼一些核心代碼吧。網絡
hook微信二維碼生成函數session
private void hookQRCreat(final ClassLoader appClassLoader, final Context context) { Class<?> clazz = XposedHelpers.findClass("com.tencent.mm.plugin.collect.b.s", appClassLoader); XposedBridge.hookAllMethods(clazz, "a", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { } @Override protected void afterHookedMethod(MethodHookParam param) { try { LogUtils.log("hookQRCreat start:"); QrBean qrBean = new QrBean(); qrBean.setChannel(QrBean.WECHAT); Field moneyField = XposedHelpers.findField(param.thisObject.getClass(), "kcp"); Double money = (Double) moneyField.get(param.thisObject); LogUtils.log("hookQRCreat money:"+money.toString()); Field markField = XposedHelpers.findField(param.thisObject.getClass(), "desc"); String mark = (String) markField.get(param.thisObject); LogUtils.log("hookQRCreat mark:"+mark); Field payurlField = XposedHelpers.findField(param.thisObject.getClass(), "kco"); String payurl = (String) payurlField.get(param.thisObject); LogUtils.log("hookQRCreat payurl:"+payurl); qrBean.setMark_sell(mark); qrBean.setUrl(payurl); LogUtils.log( "com.tencent.mm.plugin.collect.b.s qrBean:"+ JSON.toJSONString(qrBean)); Intent broadCastIntent = new Intent(); broadCastIntent.putExtra("data", qrBean.toString()); broadCastIntent.setAction(HookMain.RECEIVE_QR_WECHAT); // broadCastIntent.setComponent( new ComponentName( "com.sjk.tpay" , // "com.sjk.tpay.ReceiverMain") ); context.sendBroadcast(broadCastIntent); LogUtils.log("hookQRCreat end:"+JSON.toJSONString(param)); }catch (Exception e){ LogUtils.log("hookQRCreat exception:"+Log.getStackTraceString(e)); } } }); }
hook支付寶二維碼生成函數app
private void hookQRCreat(final ClassLoader appClassLoader, final Context context) { XposedHelpers.findAndHookMethod("com.alipay.mobile.payee.ui.PayeeQRSetMoneyActivity", appClassLoader, "a", XposedHelpers.findClass("com.alipay.transferprod.rpc.result.ConsultSetAmountRes", appClassLoader), new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { Field moneyField = XposedHelpers.findField(param.thisObject.getClass(), "g"); String money = (String) moneyField.get(param.thisObject); Field markField = XposedHelpers.findField(param.thisObject.getClass(), "c"); Object markObject = markField.get(param.thisObject); String mark = (String) XposedHelpers.callMethod(markObject, "getUbbStr"); Object consultSetAmountRes = param.args[0]; Field consultField = XposedHelpers.findField(consultSetAmountRes.getClass(), "qrCodeUrl"); String payurl = (String) consultField.get(consultSetAmountRes); Field consultField2 = XposedHelpers.findField(consultSetAmountRes .getClass(), "printQrCodeUrl"); String payurloffline = (String) consultField2.get(consultSetAmountRes); QrBean qrBean = new QrBean(); qrBean.setChannel(QrBean.ALIPAY); qrBean.setMark_sell(mark); qrBean.setUrl(payurl); Intent broadCastIntent = new Intent() .putExtra("data", qrBean.toString()) .setAction(RECEIVE_QR_ALIPAY); context.sendBroadcast(broadCastIntent); } }); }
hook雲閃付二維碼生成函數框架
public static void GenQrCode(final String paramString1, final String paramString2, final String bankName, final String bankNo) { new Thread(new Runnable() { public void run() { try { Object obj1 = paramString2; Object obj2 = new BigDecimal(paramString1); obj2 = ((BigDecimal) obj2).setScale(2, RoundingMode.HALF_UP).toPlainString().replace(".", ""); // LogUtils.getInstance().saveLog("GenQrCode begin :" + obj1 + obj2); Object obj3 = new StringBuilder(); ((StringBuilder) obj3).append("https://pay.95516.com/pay-web/restlet/qr/p2pPay/applyQrCode?txnAmt="); ((StringBuilder) obj3).append(MainHook.Enc((String) obj2)); ((StringBuilder) obj3).append("&cityCode="); ((StringBuilder) obj3).append(MainHook.Enc(MainHook.getcityCd())); ((StringBuilder) obj3).append("&comments="); ((StringBuilder) obj3).append(MainHook.Enc((String) obj1)); ((StringBuilder) obj3).append("&virtualCardNo="); // ((StringBuilder) obj3).append(MainHook.encvirtualCardNo); CardInfo cardInfo = getEncvirtualCardNo(bankName, bankNo); if (cardInfo == null) { throw new Exception("找不到對應的下單卡"); } cardInfo.setAccount(ysfAccount); ((StringBuilder) obj3).append(Enc(cardInfo.getVirtualCardNo())); obj1 = ((StringBuilder) obj3).toString(); obj2 = HttpHelper.getInstance().getOkHttpClient(); obj3 = new okhttp3.Request.Builder(); Request.Builder localBuilder = ((Request.Builder) obj3).url((String) obj1).header("X-Tingyun-Id", MainHook.getXTid()); // LogUtils.getInstance().saveLog("GenQrCode url:" + obj1); obj3 = new StringBuilder(); ((StringBuilder) obj3).append("0;"); ((StringBuilder) obj3).append(System.currentTimeMillis()); obj3 = ((OkHttpClient) obj2).newCall(localBuilder.header("X-Tingyun-Lib-Type-N-ST", ((StringBuilder) obj3).toString()) .header("sid", MainHook.getSid()).header("urid", MainHook.geturid()).header("cityCd", MainHook.getcityCd()) .header("locale", "zh-CN").header("User-Agent", "Android CHSP").header("dfpSessionId", MainHook.getDfpSessionId()) .header("gray", MainHook.getgray()).header("key_session_id", "").header("Host", "pay.95516.com").build()).execute().body().string(); obj1 = MainHook.Dec((String) obj3); obj2 = new StringBuilder(); ((StringBuilder) obj2).append("GenQrCode RSP=>"); ((StringBuilder) obj2).append((String) obj1); MainHook.mlog(obj2.toString()); try { obj2 = new JSONObject((String) obj1); String certificate = ((JSONObject) obj2).getJSONObject("params").getString("certificate"); QRInfo qrInfo = new QRInfo(certificate, paramString2); qrInfo.setRemark(JSON.toJSONString(cardInfo)); String body = JSON.toJSONString(qrInfo); Intent localIntent = new Intent("websocket.sendmsg"); localIntent.putExtra("data", "qr:" + body); MainHook.getContext().sendBroadcast(localIntent); } catch (Exception ex) { LogUtils.getInstance().saveLog("二維碼廣播發送異常:" + ex.getMessage()); } return; } catch (Exception ex) { LogUtils.getInstance().saveLog("GenQrCode異常:" + ex.getMessage()); } } }).start(); }
有問題的朋友能夠給我留言或者加我Q好友socket