1. 程式人生 > >Android微信支付接入

Android微信支付接入

前言:本文主要說明如何在Android專案中接入微信支付,介紹微信支付在專案中的配置,分析微信支付資料與其互動流程,分享個人遇到的坑,以幫助有需要的朋友能更快的在專案中進行微信支付的接入。 
正文: 
1,開發資質申請: 
這個過程在本文中不詳細介紹,總的來說需要企業資質申請微信支付功能以及微信開發者,最終是為了得到APPID和商戶金鑰(後面會詳講這個兩個值怎麼使用) 
2,流程總體介紹 
微信支付總體結構圖: 
這裡寫圖片描述 
訂單資訊:簡單來講就是對訂單的封裝,其中包含了支付金額,支付時間,訂單號,簽名信息等等訂單資訊。這些資訊在專案中一般是由服務端構建的,交付給APP轉發給微信伺服器即可。但是實際情況中服務端可能也沒有做這個工作,那麼訂單資訊也有可能在APP端合成。所以開發時務必和後端開發人員協商好關於訂單資訊構造的工作。(訂單構造詳情見下文) 
支付請求:

即APP在程式中呼叫支付SDK將訂單資訊傳送給微信伺服器,這個過程在程式碼中是很簡單的,微信封裝好了這個請求介面執行一行程式碼即可呼叫(詳情見下文) 
支付結果反饋:微信會在特定回撥介面通知支付介面 
總體上這就是微信支付的結構,操作上稍微複雜的是訂單資訊的構造,容易導致出錯的微信SDK的配置。那麼接下來就具體的一一介紹每個點的實現。 
3,下載官方demo 
官網SDK以及demo下載地址:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319167&token=&lang=zh_CN
 
官方文件地址:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=1_1 
下載完成後將libammsdk.jar匯入到專案中,至於官方demo,建議大家看看就好,不要太相信。因為寫的是在太爛了(不知道為什麼微信這麼大個平臺,開發的demo是如此的不考慮使用者的感受) 
4,實現 
a,匯入jar包 
b,在工程包名下根目錄新建wxapi包,這個wxapi包的位置一定要是包名根目錄,包名也不能錯。(這讓對包名有強迫症的開發者會很不爽,但是沒辦法) 
這裡寫圖片描述 
c,在該包下新建回撥類WXPayEntryActivity,該類的名字一定是在wxapi包下,名字也一定是WXPayEntryActivity
。因為他是微信回撥的介面,如果改變位置或名字,就會導致微信無法將支付結果反饋,從而導致支付失敗。 
這裡寫圖片描述 
(圖中WXEntryActivity是用作微信分享或其他功能的,只做微信支付的朋友可以忽略) 
d,WXPayEntryActivity的程式碼實現以及使用說明: 
該類是不需要開發者自己呼叫的,他是在微信支付後SDK為了回撥通知APP的介面,SDK內部會呼叫該Activity,該Activity的介面佈局可以自定義的設定。 
其具體的回撥介面是該類中的onResp函式,在該函式中可判斷是否支付成功。

public class WXPayEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {

    private IWXAPI api;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wxpay_entry);
        api = WXAPIFactory.createWXAPI(this, "wxAPPID");//這裡填入自己的微信APPID
        api.handleIntent(getIntent(), this);
    }

    @Override
    public void onReq(BaseReq baseReq) {

    }

    @Override
    public void onResp(BaseResp baseResp) {
        Log.d("coyc", "onPayFinish, errCode = " + baseResp.errCode);

        if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
            int errCord = baseResp.errCode;
            if (errCord == 0) {
                App.getInstance().tos("支付成功!");
            } else {
                App.getInstance().tos("支付失敗");
            }
            //這裡接收到了返回的狀態碼可以進行相應的操作,如果不想在這個頁面操作可以把狀態碼存在本地然後finish掉這個頁面,這樣就回到了你調起支付的那個頁面
            //獲取到你剛剛存到本地的狀態碼進行相應的操作就可以了
            finish();
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        api.handleIntent(intent, this);
    }
}

e,AndroidManifest.xml配置:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

        <!-- 微信支付 -->
        <activity
            android:name=".wxapi.WXPayEntryActivity"
            android:exported="true"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:scheme="自己的wxAPPID" />
            </intent-filter>
        </activity>

f,呼叫支付介面:

IWXAPI api= WXAPIFactory.createWXAPI(context, "wxAPPID",false);//填寫自己的APPID
api.registerApp("wxAPPID");//填寫自己的APPID,註冊本身APP
PayReq req = new PayReq();//PayReq就是訂單資訊物件
//給req物件賦值
req.appId = appid;//APPID
req.partnerId = partnerid;//    商戶號
req.prepayId = prepayid;//  預付款ID
req.nonceStr = getRoundString();//隨機數
req.timeStamp = getTimeStamp();//時間戳
req.packageValue = "Sign=WXPay";//固定值Sign=WXPay
req.sign = sign;//簽名

api.sendReq(req);//將訂單資訊物件傳送給微信伺服器,即傳送支付請求

那麼寫到這裡,上面的PayReq 物件其實是未被賦值的

        req.appId = appid;//APPID
        req.partnerId = partnerid;//    商戶號
        req.prepayId = prepayid;//  預付款ID
        req.nonceStr = getRoundString();//隨機數
        req.timeStamp = getTimeStamp();//時間戳
        req.packageValue = "Sign=WXPay";//固定值Sign=WXPay
        req.sign = sign;//簽名

而且這7個引數是缺一不可的,如果這些引數都是在服務端生成的,那麼在Android開發人員就不用做什麼工作了,將服務端給的值給其賦值就好了,那麼整個微信支付流程也就做完了(一般來講也確實是這個樣子)。但是有些情況下服務端的同事沒有做這些工作,比如說簽名工作等等。那麼這麼這些工作就要在APP本地實現。 
下面我給出隨機數獲取演算法,時間戳獲取演算法,簽名演算法。

private String getRoundString() {

        Random random = new Random();

        return random.nextInt(10000) + "";
    }

    private String getTimeStamp() {
        return new Date().getTime() / 10 + "";
    }
    private String getSign() {
        Map<String, String> map = new HashMap<>();
        map.put("appid", req.appId);
        map.put("partnerid", req.partnerId);
        map.put("prepayid", req.prepayId);
        map.put("package", req.packageValue);
        map.put("noncestr", req.nonceStr);
        map.put("timestamp", req.timeStamp);

        ArrayList<String> sortList = new ArrayList<>();
        sortList.add("appid");
        sortList.add("partnerid");
        sortList.add("prepayid");
        sortList.add("package");
        sortList.add("noncestr");
        sortList.add("timestamp");
        sort(sortList);

        String md5 = "";
        int size = sortList.size();
        for (int k = 0; k < size; k++) {
            if (k == 0) {
                md5 += sortList.get(k) + "=" + map.get(sortList.get(k));
            } else {
                md5 += "&" + sortList.get(k) + "=" + map.get(sortList.get(k));
            }
        }
        String stringSignTemp = md5+"&key=商戶金鑰";//這裡填寫自己的商戶金鑰,所以說如果簽名工作實在服務端完成的,商戶金鑰在APP端是用不到的

        String sign=MD5.Md5(stringSignTemp).toUpperCase();

        return sign;
    }
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.android.pc.util;

import java.security.MessageDigest;

public class MD5 {
    public MD5() {
    }

    public static final String Md5(String s) {
        char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

        try {
            byte[] e = s.getBytes("UTF-8");
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(e);
            byte[] md = mdTemp.digest();
            int j = md.length;
            char[] str = new char[j * 2];
            int k = 0;

            for(int i = 0; i < j; ++i) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 15];
                str[k++] = hexDigits[byte0 & 15];
            }

            return new String(str);
        } catch (Exception var10) {
            return null;
        }
    }
}

商戶號以及預付款ID這個必須是服務端同事給定的值,在APP端是無法程式碼生成的。 
那麼整個微信支付的程式碼工作到這裡就結束了。這裡我將自己封裝的支付類貼出來,僅供參考。

public class WX_Pay {

    public IWXAPI api;
    private PayReq req;

    public WX_Pay(Context context) {

        api = WXAPIFactory.createWXAPI(context, "wxAPPID",false);
    }

    /**
     * 向微信伺服器發起的支付請求
     */
    public void pay(String appid,String partnerid,String prepayid) {

        req = new PayReq();

        req.appId = appid;//APPID
        req.partnerId = partnerid;//    商戶號
        req.prepayId = prepayid;//  預付款ID
        req.nonceStr = getRoundString();//隨機數
        req.timeStamp = getTimeStamp();//時間戳
        req.packageValue = "Sign=WXPay";//固定值Sign=WXPay

        String sign = getSign();
        req.sign = sign;//簽名

        api.registerApp("wxAPPID");
        api.sendReq(req);
    }

    @NonNull
    private String getSign() {
        Map<String, String> map = new HashMap<>();
        map.put("appid", req.appId);
        map.put("partnerid", req.partnerId);
        map.put("prepayid", req.prepayId);
        map.put("package", req.packageValue);
        map.put("noncestr", req.nonceStr);
        map.put("timestamp", req.timeStamp);

        ArrayList<String> sortList = new ArrayList<>();
        sortList.add("appid");
        sortList.add("partnerid");
        sortList.add("prepayid");
        sortList.add("package");
        sortList.add("noncestr");
        sortList.add("timestamp");
        sort(sortList);

        String md5 = "";
        int size = sortList.size();
        for (int k = 0; k < size; k++) {
            if (k == 0) {
                md5 += sortList.get(k) + "=" + map.get(sortList.get(k));
            } else {
                md5 += "&" + sortList.get(k) + "=" + map.get(sortList.get(k));
            }
        }
        String stringSignTemp = md5+"&key=商戶金鑰";

        String sign=MD5.Md5(stringSignTemp).toUpperCase();

        return sign;
    }

    private String getRoundString() {

        Random random = new Random();

        return random.nextInt(10000) + "";
    }

    private String getTimeStamp() {
        return new Date().getTime() / 10 + "";
    }


    private static void sort(ArrayList<String> strings) {
        Collections.sort(strings);
    }
}

那麼在APP中這樣使用就好

WX_Pay pay = new WX_Pay(getContext());
pay.pay(str1,str2,str3);

5,錯誤小結:本人在開發中遇到過兩個錯誤 
a,無法起調微信支付介面:錯誤原因是沒有將WXPayEntryActivity 類放在在wxapi包下。 
b,支付失敗:錯誤原因是在簽名演算法中忘記將商戶金鑰簽名。 
這裡基本可以總結下錯誤型別: 
1,起調失敗:工程配置錯誤 
2,支付訂單報錯:訂單資訊錯誤 
c,千萬注意微信支付要編譯為release版才能通過支付測試

相關推薦

Android支付接入

前言:本文主要說明如何在Android專案中接入微信支付,介紹微信支付在專案中的配置,分析微信支付資料與其互動流程,分享個人遇到的坑,以幫助有需要的朋友能更快的在專案中進行微信支付的接入。 正文: 1,開發資質申請: 這個過程在本文中不詳細介紹,總的來說需要企業資質申請微信支

Android app 第三方支付接入詳解

微信支付做了好幾遍了,都沒有出現什麼棘手的問題,下面一一為大家分享一下,歡迎吐槽。 還是老樣子,接入微信的支付要第一步新增微信支付官方的包libammsdk.jar 首先就處理略坑的一個問題,app應用簽名和包名的問題。 商戶在微信開放平臺申請開發應用後,微信開放平臺會生成APP的唯一標識AP

Android app 第三方支付接入

微信支付做了好幾遍了,都沒有出現什麼棘手的問題,下面一一為大家分享一下,歡迎吐槽。 還是老樣子,接入微信的支付要第一步新增微信支付官方的包libammsdk.jar首先就處理略坑的一個問題,app應用簽名和包名的問題。商戶在微信開放平臺申請開發應用後,微信開放平臺會生成APP

Android支付支付接入總結

public class AliPay { /*支付寶支付結果碼*/ private static final String PAY_OK = "9000";// 支付成功 private static final String PAY_WAIT_CONFIRM = "8

Android 支付支付支付 快速接入

先放上接入兩個支付平臺的官方文件地址 一、支付寶支付 匯入開發資源 在商戶應用工程的AndroidManifest.xml檔案裡面新增宣告: <activity android:name="com.ali

支付接入完全解析之Android客戶端(2)

前段時間在一個App中接入了微信支付功能,想來也穩定執行快一個月了,回頭想想自己接入微信支付時候踩過的坑,決定寫一篇自己當初想要搜尋的文章,文章準備分3篇完成。 第一篇:微信支付前期準備 第二篇:微信支付接入客戶端部分(以Android為例

支付接入(Android/IOS(swift)/Java後臺)

除按照微信登入方式接入外還需進行如下操作: 建立 包名.wxapi.WXPayEntryActivity 檔案,保證內容如下(WechartUtils下面會給出): import android.app.Activity; import android.os.Bundle; imp

Android支付支付支付快速接入

一、支付寶接入1、建立應用並獲取APPID開發者中心中建立您的應用,會為您生成應用唯一標識(APPID),並且可以申請開通開放產品使用許可權,通過APPID您的應用才能呼叫開放產品的介面能力。在“我的應用”中按下圖方式檢視APPID。2、新增支付功能3、簽約(涉及到收費)4、

iOS客戶端的支付接入

對於一個iOS的APP,如果有一些虛擬的商品或者服務需要通過線上支付來收費的話,一般有幾種主流的選擇。 如果是通過APP呼叫支付平臺APP的思路的話,一個是調起支付寶客戶端,一個則是調起微信支付。 實際上,從程式碼的角度,調起支付APP就是把一些關鍵的引數通過一定方式打包成為一個訂單,

Android 支付的統一下單

準備工作 申請微信開發者賬號,新增應用及申請開通微信支付功能,如 檢視開通流程 統一下單的介面文件: 檢視介面 開發 ①下載sdk: sdk和demo下載 ②可以匯入包 在build.gradle檔案中,新增如下依賴即可: depende

android 支付,body為中文字元,簽名錯誤

微信支付訂單生產方法: /** * 根據您的訂單資訊 生成 微信產品支付訂單資訊 */ private String createWeChatOrder() { StringBuffer xml = new StringBuffer();

android支付詳細步驟

此篇僅限於android客戶端整合微信支付 微信支付和支付寶相比的話裡面的坑還是很多的,但是導包導的倒是很簡單,就在在build.gradle檔案中,新增一條依賴就行: dependencies { implementation 'com.tencent.mm.opensdk:wec

Android支付無法掉起支付的原因

1.第一種原因就是上邊的這些引數有問題。一般都是祕鑰有問題。需自己登陸商家版後臺修改  2.需要知道微信支付是需要打包才能執行。這也是蛋疼的一點,測試只能通過log和Toast來推斷。掉不起來可以去微信開放平臺看自己配置的引數是否正確。 3.微信支付跟支付寶支付

Android 支付demo

經常有朋友問我微信支付怎麼做,我就納悶了,微信開發者平臺不是有詳細的介紹和demo嗎?他們說那個demo執行不了,於是今天我就來試了試,果然有問題,不過是小問題,稍微改下就可以了。 首先進入 微信開發者平臺 https://open.weixin.qq.com/cgi-b

Android支付,通知回撥方法

import java.io.IOException; import java.io.StringReader; import java.util.HashMap; import java.util.List; import java.util.Map; import j

Android支付詳細流程(包括手機端和伺服器端)

相關檔案下載地址:http://download.csdn.net/detail/s_alics/9383437點選開啟連結 **************************************************************************

Android支付SDK的細微注意點

首先這個demo是Eclipse專案,在用Eclipse匯入進來後會報"com.tencent.mm.sdk"這個路徑找不到,原因有2個: 1.wechat-sdk-android-with-mta的包沒有匯入,右鍵選中包,build path->add to l

android 支付 + node.js 服務端

實現微信支付有很多方式,至於開始菜鳥的我使用app支付,後期考慮安全性問題,只好把統一下單,得到prepay_id之後再次簽名sign全在服務端寫了,廢話不多說,進入操作。 做任何東西,我喜歡瞭解整個流程,然後一步一步做起來,開始看清微信支付業務流程圖 業務流程步驟寫的很

PHP支付--接入支付SDK,生成訂單二維碼進行掃碼支付

在PHP開發微信支付中接入支付SDK,生成訂單二維碼進行掃碼支付,實際運用中做出一些整理,以便後期查閱。整體流程如下圖; 微信支付官方流程:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 1、當我們選擇使用掃碼支付,

關於android支付支付支付的整合

最近專案中要整合微信和支付寶支付 在沒有接觸支付之間 覺得還是比較難的 但真正去實現的時候還是比較簡單的 就是有不少坑要去踩過之後才知道 支付寶支付 : 對於支付寶支付 我個人理解還是比較簡單的 https://open.alipay.com/platform/home.h