題目裏說的我的收款指的不是普通的掃個碼,而是說那種能夠支持回調的,例如網上商城支付以後,商城能夠知道支付狀態而且自動修改訂單的狀態爲「已支付」。這種支付的形式,不管是微信、支付寶仍是銀聯,目前都是不對我的開放的,必須有企業資質才能申請。可是對於不少開發者而言,有時候就是一個小小的驗證性應用,想要擁有支付功能,而本身又沒有企業資質,天然無法申請到微信支付寶這種接口,甚至連第三方的聚合支付(Ping++)也是沒法申請的。本文就介紹一種利用我的支付寶(微信也是能夠的)本身實現支付功能的思路,成本是一部舊的安卓手機,其餘的都是徹底免費的,配合支付寶的收款碼(提現免費),能夠作到零費率。api
這個方案的基本思路是很是簡單的,跟以前你們經常使用的用爬蟲爬取網頁帳單數據相似,可是這裏咱們用的是手機App。相對來講,截取手機App的推送消息更爲簡單,不須要應爲微信支付寶的各類反爬措施;可是缺點是可以獲取到的信息較少,沒有諸如流水號、付款人之類的信息,只有一個金額。服務器
因此,咱們的思路就是:微信
這個方案裏的關鍵問題有如下幾個:網絡
這個問題其實網上已經有不少的解決方案了,其利用的是Android中的NotificationListenerService
這個類,經過註冊這個Listener,能夠在推送通知彈出來的時候,獲取到其發送的App、標題、內容等信息。咱們最關心的就是App和推送內容。併發
判斷髮送App的包爲支付寶的包,而後再從推送的內容中獲取到具體的內容,便可獲得付款金額。ide
示例代碼以下:高併發
public class AlipayNotificationListenerService extends NotificationListenerService { public AlipayNotificationListenerService() { } @Override public void onNotificationPosted(StatusBarNotification sbn) { // 這裏能夠拿到包名,能夠按照須要判斷。 String packageName = sbn.getPackageName(); Notification notification = sbn.getNotification(); if (notification == null) { return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Log.e("SevenNLS","in 1"); Bundle extras = notification.extras; if (extras != null) { // 這裏是具體的title和content,能夠從中提取金額 String title = extras.getString(Notification.EXTRA_TITLE, ""); String content = extras.getString(Notification.EXTRA_TEXT, ""); Log.d("Zachary", "title:" + title + " content:" + content); } } } @Override public void onListenerConnected() { Log.e("Zachary","connected"); } }
固然,爲了讓這個App可以順利進行,還要給它獲取通知的權限,保證它不被清理等等,須要作一些相應的保護措施。微信支付
剛纔咱們說過,服務器收到App發來的收款信息以後,還須要找到對應的訂單。這一步是相對比較難的一步,由於咱們知道相同金額的訂單可能有不少,到底哪個纔是剛剛支付的訂單呢?網站
這裏,咱們能夠再詳細思考一下,其實這個訂單不只僅是由這個金額肯定的,而是一個多元組共同肯定的。最簡單的一種實現方式就是 (訂單金額-支付狀態)。經過這個二元組能夠肯定一個訂單。其含義是,若是這個訂單已經支付過了,那麼我在查找訂單的時候,就能夠不用理會它了,我只須要查找(指定金額-未支付)的訂單就能夠了。ui
這樣能夠基本解決這個問題。可是,咱們考慮到除了正常支付外,還有可能會有另一些狀況。好比用戶建立了訂單以後,忽然不想支付了,沒有進行接下來的操做。或者說,有人惡意在網站上建立了大量的訂單而且不支付。 這樣的後果是,這些訂單的狀態永遠都是未支付
,當你想要繼續建立訂單的時候,就會受到限制,不能建立跟這些訂單相同金額的訂單,不然你的系統將沒法分辨究竟是哪一筆訂單被支付了。
爲了應對這種狀況,咱們想到其實不少的支付都是有時間限制的,也就是說,訂單是有有效期的,一旦過了有效期,訂單就不能被支付了。因此咱們也能夠給訂單加一個有效時間的限制,好比5分鐘,一旦五分鐘內沒有被支付,就認爲這個訂單已經失效了。這時,訂單的肯定方式就變成了一個三元組(訂單金額-支付狀態-是否過時)。查找的時候,只須要查找(指定金額-未支付-未過時)的訂單就能夠了。也就是說,任意一個訂單,最多隻會佔用這個金額5分鐘,一旦超過五分鐘,無論支付與否,你均可以繼續建立相同金額的訂單了。
可是這樣咱們仍是以爲不滿意,特別是對於某些支付金額相對單一的狀況,可能每次都須要建立相同金額的訂單,這樣的話,再最壞狀況下咱們只能每隔五分鐘處理一個訂單,這個效率能夠說是很是低效了。
在這裏,咱們提出了一種trade-off的解決方法。通常的正常支付是不會使用這種方式的,也難以接受,可是對於咱們來講,爲了不企業資質的認證和手續費,在必定程度上是能夠接受的。
這種方式就是,當目前系統中已經有了某一金額的訂單的時候,若是咱們要繼續建立相同金額的訂單,那麼咱們就在指定金額上進行上下浮動,好比下浮一分錢,這樣金額就能夠和以前的訂單區分開來,避免出現不能同時支付的狀況。這樣,雖然咱們在高併發狀況下可能會有必定的損失(同時支付的人越多,差距越大),可是知足了咱們的高併發要求。
友情提示:若是金額發生浮動,能夠告訴用戶這是隨機立減,必定程度上能夠避免訂價和實際支付金額的差距帶來的問題。(這種狀況下就只能下浮,不能上浮,否則就變成隨機立加了)。
整體上來講,我認爲這種方案對於普通的我的用戶來講,是一種能夠接受的方案。其優缺點總結以下:
參考:
PaysApi: www.paysapi.com