因爲項目需求,加入這2個功能記錄一些須要注意的地方java
一.微信支付android
微信支付在2016年4月份左右稍微調整了一下支付過程,可是文檔卻沒怎麼更新,這也是百度上爲何那麼多開發者都說微信是個大坑. 身爲一個大型互聯網公司,作的事卻沒法讓人理解.express
相比之下,支付寶就好太多了.json
微信支付須要注意地方:api
1.要先申請 "商家端"帳戶, 須要提交公司信息, 我的很差申請的. 申請成功後,須要去 建立一個應用服務器
建立應用須要 注意2個地方 微信
1>包名, 若是是Android studio開發 ,這個包名要用以下圖所示位置的包名, 而不是 androidmanifest.xml中的,由於他倆可能不同,要如下圖爲準,固然若是是eclipse開發那就以androidmanifest.xml裏面的包名爲準了.網絡
2>簽名, 這個簽名不能用 debug.keystore(Eclipse的簽名後綴是.keystore), 或者 debug.jks(Androidstudio把後綴名換了), 要用本身建立的的簽名文件,好比 shop.jsk , shop.keystore去生成簽名,或者選擇之前本身建立好的,都行,只有不是debug的就行.app
android studio生成簽名截圖以下: 點擊Teminal 啓動後,輸入圖中命令,後面是你jks所在位置. 以後回車 輸入密碼, 獲得MD5值, 它就是微信建立應用時用到的簽名,須要去掉冒號,把大寫所有改爲小寫便可. 固然微信還給咱們提供了簽名工具apk, 你能夠把本身的工程打包後,安裝到手機,而後啓動微信的簽名apk,輸入包名便可獲得簽名, 你能夠拿它對比一下用命令行獲得的簽名是否一致, 若是不一致那就說明一個問題 " 你的應用沒有通過打包" , 不要經過編譯工具直接部署 到手機,這樣獲得的簽名是不對的. 必定要是打包後的.eclipse
當測試微信的時候,也須要把打包後的apk安裝到手機才能測試支付,若是隻能調起一次微信,第二次沒法調起,那就是簽名或者 appid這一塊有問題,檢查一下. 不過我發現IOS不存在這個問題, 每次都能調起微信.
二.下面說下微信在工程中建立須要注意地方:
1. 若是你的包名是com.xxx.text 那麼你須要在test以後建立一個包名 com.xxx.text.wxapi, 必須是wxapi,不能錯了. 而後必須拷貝一個類過來:WXPayEntryActivity.java ,這個類的做用是微信支付後,接收微信的支付結果的. 你能夠不作任何修改,直接拿來用就行,固然若是你想更改裏面的佈局,也是徹底OK的, 我對他作了一下修改,代碼以下, 我修改了2個地方,代碼中給出了註釋
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler{ private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity"; private IWXAPI api; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //1.第一個修改的地方 我刪掉了,它自帶的 佈局, 固然若是你想保留,徹底OK.由於佈局太難看因此我幹掉他了 api = WXAPIFactory.createWXAPI(this, Constants.APP_ID); api.handleIntent(getIntent(), this); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); api.handleIntent(intent, this); } @Override public void onReq(BaseReq req) {} @Override public void onResp(BaseResp resp) { //2.這是我修改的第二個地方, 原版的是彈出一個對話框, 我以爲太醜,而且原版也沒有給出詳細問題提示,只給出了 0, -1 ,-2 這樣會讓客戶不明因此,因此我替換成以下3個文本. 此外 //原版支付後,不會直接跳轉到 你的應用,須要按一次 返回鍵,才行, 因此我加入了finish()便於在提示後,直接返回個人應用 if(resp.errCode==0){ Toast.makeText(this,"支付成功!",Toast.LENGTH_SHORT).show(); }else if(resp.errCode==-1){ Toast.makeText(this,"支付失敗!",Toast.LENGTH_SHORT).show(); }else if(resp.errCode==-2){ Toast.makeText(this,"取消支付!",Toast.LENGTH_SHORT).show(); } finish(); } }
2. androidmainfest.xml 的配置,直接上代碼,這裏只須要注意一個地方那就是 appid
<activity android:name=".wxapi.WXPayEntryActivity" android:label="@string/app_name" android:exported="true" //必須爲true android:launchMode="singleTop"> //必須單例 </activity> <receiver android:name=".wxapi.AppRegister"> <intent-filter> <action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" /> </intent-filter> </receiver>
<activity android:name=".ui.PayActivity" //這是我本身定義的支付Activity, 本身修更名字便可 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="wxbdc42b2a35e9884e"/> //這裏就是 APPID ,必須和你申請的 應用的 appid保持一致 .不然沒法支付,注意,注意,注意 </intent-filter> </activity>
3.下面是我項目中的支付代碼, 先說下支付流程, 首先你要 讓負責接口的,給你一個接口, 這個接口 須要app端傳遞 商品的基本信息過去,好比 商品名字 , 描述,訂單號 ,價格等等.也不須要傳遞太多東西, 我就傳遞了 以上我列舉的4個 ,有人會問 "微信不是幫咱們生成了一個 訂單號嗎?" 我幹嗎還要傳遞給他, 我傳遞的這個訂單號,是用於退款使用的. 因此我要傳遞一個, 這個訂單號,在我 下單的同時, 會生成一個隨機數, 固然這都是 後臺 接口弄得,你只須要拿來使用就好了.
說的有點亂了,給個步驟吧
1>傳遞商品信息給咱們本身的後臺
2>咱們本身的後臺會拿着這些商品信息 而後加上 + 商戶號id+商戶祕鑰 (申請商家端時獲取的), 給咱們app端返回一個json,該json中包含7個字段,須要解析,後面給出代碼
3>咱們解析後, 經過 api.sendReq(req); 調用微信支付
代碼以下:
float total3 = orderTotalPrice * 100; //注意微信支付付款 是按照分爲單位的,須要把商品價格 乘以100 ,而後強轉爲 int類型 ,這裏(int)total3
param ="?ordertype="+"old"+"&sworkOrderCode="+out_trade_no+"&serviceFee=" +(int)total3+"&serviceItem="+orderItem.orderName.trim()+"&serviceClass="+orderItem.serviceItem.trim();
testWxPay(v);//開始解析接口給咱們返回的json
參數:old 是,一個版本區分,由於公司的多個app都用到了微信支付,而且他們都有關聯,因此你能夠直接無視該參數,該參數僅用於我本身的項目
參數:out_trade_no 是我從咱們的接口獲取到的隨機訂單號
參數:(int)total3 是商品價格, "分" 爲單位,必須轉爲 整形, 也不知道 int會不會越界,反正我用了int,你可用long
參數:serviceItem 商品名字
參數:serviceClass商品描述
public void testWxPay(View view) { new Thread(new Runnable() { @Override public void run() { String url = HttpUrl.host1+"WeiXinApi.asmx/CreatePrePay_id"+param; Log.e("xxx",url); ToastUtil.shortToastInBackgroundThread(getActivity(), "獲取訂單中..."); try { byte[] buf = Util.httpGet(url); if (buf != null && buf.length > 0) { String content = new String(buf); Log.e("get server pay params", content); JSONObject json = new JSONObject(content); if (null != json && !json.has("retcode")) { req = new PayReq(); req.appId = json.getString("appid"); //appid req.partnerId = json.getString("partnerid"); //商戶號 req.prepayId = json.getString("prepayid"); //預支付交易會話id req.nonceStr = json.getString("noncestr"); //隨機字符串,不超過32位 req.timeStamp = json.getString("timestamp");//時間戳 req.packageValue = json.getString("package");//擴展字段 req.sign = json.getString("sign");//簽名信息MD5加密後的 ToastUtil.shortToastInBackgroundThread(getActivity(), "正常調起支付"); toPay(); } else { Log.d("PAY_GET", "返回錯誤" + json.getString("retmsg")); ToastUtil.shortToastInBackgroundThread(getActivity(), "返回錯誤" + json.getString("retmsg")); } } else { Log.d("PAY_GET", "服務器請求錯誤"); ToastUtil.shortToastInBackgroundThread(getActivity(), "服務器請求錯誤"); } } catch (Exception e) { Log.e("PAY_GET", "異常:" + e.getMessage()); ToastUtil.shortToastInBackgroundThread(getActivity(), "異常:" + e.getMessage()); } } }).start();} private void toPay() { // 在支付以前,若是應用沒有註冊到微信,應該先調用IWXMsg.registerApp將應用註冊到微信 api.registerApp(Constants.APP_ID); api.sendReq(req); Log.e("跳轉結果--",api.sendReq(req)+""); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); toPay(); } };
整個支付代碼很是少,一共就這麼多. 須要注意的一點是, 解析的 7個 參數中, sign 是咱們本身服務端 二次加密獲得的,這裏容易出錯, 固然我說的是接口裏面容易出錯,和咱們app端沒有半毛錢關係, 由於這個 加密,老版本微信是咱們 app端生成的, 新版的 是由接口生成的,咱們直接拿來用.
sign 生成過程是: 前6個參數+ 商家祕鑰 通過MD5加密就獲得了. (這個加密用的前6個參數,須要安裝字母排序,不能亂用,商家祕鑰不需排序放到最後便可,固然這都是接口的須要完成的,咱們app端 瞭解便可)
若是這個sign 接口沒有弄好, 極容易出錯,沒法調起支付頁. 我在作的時候,就是由於接口的生成sign時,少寫一個 = 鏈接符形成的.
------------------------------------------------------------------------------------------------------------------------------------------
三.支付寶支付
支付寶支付相對來講要簡單的多了, 比較穩定寫得清晰明瞭,一看即懂. 直接上代碼吧 ,我去網絡太卡了,剛纔寫了半天,圖片沒法加載,把我寫得從新毀了,先保存吧,等會再上支付寶的.
流程以下:
1.申請帳號,一樣須要提交一些公司資料
2.下載須要資源,sdk ,文檔什麼的, 而後去配置工程
1>在工程中建立一個包存放支付寶所需資源,好比個人
導入alipaySdk-20160427.jar , 目前最新版.
2>androidmainfest.xml中的配置
<!--支付寶--> <activity android:name="com.alipay.sdk.app.H5PayActivity" //H5頁面, 若是手機沒有安裝支付寶,調起這個 android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind" > </activity> <activity android:name="com.alipay.sdk.auth.AuthActivity" android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind" > </activity>
權限信息
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
3.獲取私鑰, 公鑰
命令以下:
RSA密鑰生成命令
生成RSA私鑰
openssl>genrsa -out rsa_private_key.pem 1024
生成RSA公鑰
openssl>rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
將RSA私鑰轉換成PKCS8格式
openssl>pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt
命令使用的工具在 這裏: E:\支付寶錢包支付接口開發包2.0標準版(20160428)\DEMO\openssl\bin --> openssl.exe
雙擊啓動,截圖以下: 而後輸入上面命令,就能夠獲得了.最後會生成相應的文件,可是後綴好像不是txt,你改爲txt就能看了.具體過程文檔說的很清楚,我也記不太清了,作了1周就忘記了,這記性 ...
打開紅框框中的2個文件,裏面就用公鑰和私鑰信息了, 注意紅色部分不能要,只要中間的, 你最好把中間部分回車去掉,改爲1行,否則可能會由於回車形成出錯
配置貌似也就這麼多了吧. 比較少,文檔也很清楚.
4.下面給出代碼吧,截圖了後面數據不能泄露了,公司的信息
此處點擊 : "支付寶"支付這個 線性佈局,執行支付功能
rlZfb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { pay(v); } });
/** * call alipay sdk pay. 調用SDK支付 */ public void pay(View v) { if (TextUtils.isEmpty(PARTNER) || TextUtils.isEmpty(RSA_PRIVATE) || TextUtils.isEmpty(SELLER)) { new AlertDialog.Builder(this).setTitle("警告").setMessage("須要配置PARTNER | RSA_PRIVATE| SELLER") .setPositiveButton("肯定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialoginterface, int i) { // finish(); } }).show(); return; } //獲得訂單信息 String orderInfo = null; //待支付列表item對象 orderInfo = getOrderInfo(orderItem.getServiceCode(), orderTotalPrice); String sign = sign(orderInfo); try { /** * 僅需對sign 作URL編碼 */ sign = URLEncoder.encode(sign, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } /** * 完整的符合支付寶參數規範的訂單信息 */ final String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType(); Runnable payRunnable = new Runnable() { @Override public void run() { // 構造PayTask 對象--該對象主要爲商戶提供訂單支付功能 PayTask alipay = new PayTask(getActivity()); // 調用支付接口,獲取支付結果 String result = alipay.pay(payInfo, true); Message msg = new Message(); msg.what = SDK_PAY_FLAG; msg.obj = result; mHandler.sendMessage(msg); } }; // 必須異步調用 Thread payThread = new Thread(payRunnable); payThread.start(); }
/** * create the order info. 建立訂單信息 * subject 商品名字 */ private String getOrderInfo(String subject, float price) { // 簽約合做者身份ID String orderInfo = "partner=" + "\"" + PARTNER + "\""; // 簽約賣家支付寶帳號 orderInfo += "&seller_id=" + "\"" + SELLER + "\""; // 商戶網站惟一訂單號 //orderInfo += "&out_trade_no=" + "\"" + getOutTradeNo() + "\""; orderInfo += "&out_trade_no=" + "\"" + out_trade_no + "\""; // 商品名稱 orderInfo += "&subject=" + "\"" + subject + "\""; // 商品詳情 //orderInfo += "&body=" + "\"" + body + "\""; // 商品金額 orderInfo += "&total_fee=" + "\"" + price + "\""; // 服務器異步通知頁面路徑 --- 調用服務端地址 //orderInfo += "¬ify_url=" + "\"" + "http://notify.msp.hk/notify.htm" + "\""; //ToastUtils.show(getActivity(),subject+price); Log.e("xxxx", subject + price); orderInfo += "¬ify_url=" + "\"" + "http://xxx.xxx.xxx/HomeWorkOrder.asmx/WorkOrderPayed" + "\"";//此處是接口端給的一個 地址,找他們要吧.... // 服務接口名稱, 固定值 orderInfo += "&service=\"mobile.securitypay.pay\""; // 支付類型, 固定值 orderInfo += "&payment_type=\"1\""; // 參數編碼, 固定值 orderInfo += "&_input_charset=\"utf-8\""; // 設置未付款交易的超時時間 // 默認30分鐘,一旦超時,該筆交易就會自動被關閉。 // 取值範圍:1m~15d。 // m-分鐘,h-小時,d-天,1c-當天(不管交易什麼時候建立,都在0點關閉)。 // 該參數數值不接受小數點,如1.5h,可轉換爲90m。 orderInfo += "&it_b_pay=\"30m\""; // extern_token爲通過快登受權獲取到的alipay_open_id,帶上此參數用戶將使用受權的帳戶進行支付 // orderInfo += "&extern_token=" + "\"" + extern_token + "\""; // 支付寶處理完請求後,當前頁面跳轉到商戶指定頁面的路徑,可空 orderInfo += "&return_url=\"m.alipay.com\""; // 調用銀行卡支付,需配置此參數,參與簽名, 固定值 (須要簽約《無線銀行卡快捷支付》才能使用) // orderInfo += "&paymethod=\"expressGateway\""; return orderInfo; }
大多數都是支付寶代碼,貼着也沒意思, 只不過修改了訂單信息而已. 後面的再也不貼了. demo和文檔已經很是清楚了. 支付寶退款很簡單,只須要發送訂單號給咱們本身的接口便可,其餘的由接口去實現.
以上就是全部代碼了.寫得很差 ,勿噴!!