最新版支付寶整合
基本步驟及遇到的問題:
生成公鑰私鑰
解壓:
點選進入 然後再雙擊:
然後會生成:
pkcs8: 私鑰
public_key:公鑰
遇到的問題:
關於 付款成功後,回撥地址 可以給個介面的地址
app支付報錯ALI40247
1.沒有APP支付許可權導致
檢查您使用的這個appid是否簽約過APP支付這個介面的許可權。
2.有移動支付介面(介面名稱:mobile.securitypay.pay)許可權沒有app支付介面(介面名稱:alipay.trade.app.pay)許可權。以為可以使用APP支付介面,這是兩個介面如果有移動支付介面(介面名稱:mobile.securitypay.pay)許可權想使 用APP支付介面(介面名稱:alipay.trade.app.pay),可以進行重新簽約參考《介面簽約方案》第三步
帖子地址:
3.如果已經簽約了APP支付介面,還是報這個錯誤
需要檢查商戶公鑰上傳的位置是否正確
a.移動支付介面(介面名稱:mobile.securitypay.pay)的上傳合作伙伴金鑰管理
b.app支付介面(介面名稱:alipay.trade.app.pay)的上傳開放平臺金鑰管理
注意:使用的介面不同上傳位置不同
這個介面應該使用開放平臺金鑰管理裡面的金鑰,檢查您這個介面使用的appid下面的公鑰(自己上傳的商戶公鑰)和支付寶報公鑰。因為沒有上傳商戶公鑰或者使用的商戶公鑰和商戶私鑰不匹配也會導致這個錯誤
4.請求支付編碼問題和沒有做url encode
編碼:就是請求了utf-8 但是用了gbk的編碼
encode:app支付介面(介面名稱:alipay.trade.app.pay)對請求字串的所有一級value(biz_content作為一個value)進行encode。
5.管理中心》我的應用》狀態》(注意:)已上線才可以使用否則也會報這個錯誤
申請上線需要填寫 申請資料
6.檢查應用是否已經上線
app支付報錯ALI38173 / AE050001205:
檢查請求引數,對照我們的線上文件檢視,比如:引數少了、多了、亂碼、名稱不對,還有必傳引數是否都請求提交給支付寶了等等。請求引數的檢視連結:
關於給伺服器傳參,讓伺服器返回 拉起支付寶的字串:
我把簽名刪除了一些 下面是返回的字串 是當做 orderInfo 用來拉起支付的:
app_id=2017021405666842&biz_content=%7B%22timeout_express%22%3A%2230m%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%22%E6%89%BE%E6%B4%BB%E7%BD%91%E7%A7%AF%E5%88%86%E5%85%85%E5%80%BC%22%2C%22body%22%3A%22%E6%89%BE%E6%B4%BB%E7%BD%91%E7%A7%AF%E5%88%86%E5%85%85%E5%80%BC%22%2C%22out_trade_no%22%3A%22021811340336879%22%7D&charset=UTF-8&format=JSON&method=alipay.trade.app.pay¬ify_url=http%3A%2F%2Fzhaohuo.chuangkeweilai.cn%2Finclude%2Fpayment%2Falipayapp%2Fnotify_url.php&sign_type=RSA×tamp=2017-02-18+11%3A34%3A03&version=1.0&sign=ADus0ZXHq600d3RFWWE8tiUNm%2Fisr%2FxZtWDit%2FL%2FVNOygTRLaJKlyfEWgN9v%2Bf9v5TkixWE5L9UPK6wM36E0MQOMJM8kG8i8xC6B4ss6ujExFZaGBDexLQMrOHXccxwzlNS0LKZE2uInrznlecjDwMyqHpPIyKs4kUwPmoAAQ1Hj2kxe6a99BA%3D%3D
一些固定的可在 後臺固定 可以只傳一些可變的引數
傳參時 到後臺會遇到 biz_content 中 轉義 \ 的問題
php的處理:
(上面的方法)該方法返回的data --- 就是 拉起支付 所需的 orderInfo
php端 回撥地址中的處理:
安卓端的處理:
case 2: // ToastUtils.showToast(mContext,"支付寶支付"); Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(AliPayParams.APPID, et_chongzhi.getText().toString().trim(), "餘額充值", "充值", "C"+System.currentTimeMillis()+"_"+user_id); StringBuilder sb = new StringBuilder(); List<String> keys = new ArrayList<String>(params.keySet()); Collections.sort(keys); for (int i = 0; i < keys.size(); i++) { if (i == keys.size()-1){ sb.append(keys.get(i)+"="+params.get(keys.get(i))); }else { sb.append(keys.get(i) + "=" + params.get(keys.get(i)) + "&"); } } map.clear(); map.put("prestr",sb.toString()); LogUtils.e(mContext,"請求傳的東西prestr",sb.toString()); for (Map.Entry<String, String> m: params.entrySet()){ map.put(m.getKey(),m.getValue()); } requestNet_POST(NetPath.REQUEST_INFO_SIGN,ALIPAY,map); break;
----- 下面這個方法為 demo的 OrderInfoUtil2_0 裡面的
public static Map<String, String> buildOrderParamMap(String app_id,String total_amount,String productSubject,String productDesc,String orderNo) { Map<String, String> keyValues = new HashMap<String, String>(); keyValues.put("app_id", app_id); keyValues.put("biz_content", "{\"timeout_express\":\"30m\"," + "\"product_code\":\"QUICK_MSECURITY_PAY\"," + "\"total_amount\":\""+total_amount+"\"," + "\"subject\":\""+productSubject+"\"," + "\"body\":\""+productDesc+"\"," + "\"out_trade_no\":\"" + orderNo + "\"}"); // 下面的這些引數 我們這邊選擇了 在後臺固定 所以我都註釋掉了 // keyValues.put("notify_url", "http://yanglao.wbkeji.cn/index.php/Api/Payment/alipayNotify"); // keyValues.put("charset", "utf-8"); // // keyValues.put("method", "alipay.trade.app.pay"); // keyValues.put("format", "JSON"); // // keyValues.put("sign_type", "RSA"); // "2016-07-29 16:55:53" // SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // Date date = new Date(System.currentTimeMillis()); // Log.e("Time:",simpleDateFormat.format(date)); // keyValues.put("timestamp", simpleDateFormat.format(date)); // // keyValues.put("version", "1.0"); return keyValues; }
public void onSucceedPaser(int what, Gson gson, Response<String> response) { super.onSucceedPaser(what, gson, response); // LogUtils.e(mContext,"請求成功的字串:",response.get()); switch (what){ case ALIPAY: try { GetPrivateKeyBean alibean = gson.fromJson(response.get(),GetPrivateKeyBean.class); if (alibean!=null){ if (!TextUtils.isEmpty(alibean.getData())){ // LogUtils.e(mContext,"private key1:",alibean.getData()); payV2(alibean.getData()); } } }catch (Exception e){ LogUtils.e(mContext,"解析錯誤",""); } break; } }
/** * 支付寶支付業務 * * @param */ public void payV2(String ssign) { LogUtils.e(mContext,"返回的 : "+ssign,""); final String orderInfo = ssign; Runnable payRunnable = new Runnable() { @Override public void run() { PayTask alipay = new PayTask(Me_ShoppingCart_Order_Pay.this); Map<String, String> result = alipay.payV2(orderInfo, true); Log.i("msp", result.toString()); Message msg = new Message(); msg.what = SDK_PAY_FLAG; msg.obj = result; mHandler.sendMessage(msg); } }; Thread payThread = new Thread(payRunnable); payThread.start(); }
private static final int SDK_PAY_FLAG = 1; private static final int ALIPAY = 1; final Map<String,String> strmap = new HashMap<String, String>(); @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { @SuppressWarnings("unused") public void handleMessage(Message msg) { switch (msg.what) { case SDK_PAY_FLAG: { @SuppressWarnings("unchecked") PayResult payResult = new PayResult((Map<String, String>) msg.obj); /** 對於支付結果,請商戶依賴服務端的非同步通知結果。同步通知結果,僅作為支付結束的通知。 */ String resultInfo = payResult.getResult();// 同步返回需要驗證的資訊 String resultStatus = payResult.getResultStatus(); // 判斷resultStatus 為9000則代表支付成功 if (TextUtils.equals(resultStatus, "9000")) { // 該筆訂單是否真實支付成功,需要依賴服務端的非同步通知。 Toast.makeText(Me_ShoppingCart_Order_Pay.this, "支付成功", Toast.LENGTH_SHORT).show(); } else { // 該筆訂單真實的支付結果,需要依賴服務端的非同步通知。 Toast.makeText(Me_ShoppingCart_Order_Pay.this, "支付失敗", Toast.LENGTH_SHORT).show(); } break; } default: break; } }; };
關於簽名:
.net php 後臺的 直接使用非pkcs8 格式的私鑰
java後臺 使用pkcs8格式的私鑰
兩種格式的私鑰生成的簽名是相同的
關於驗籤:
驗籤時使用的是支付寶公鑰 (不是應用公鑰)
如果驗籤使用應用公鑰 則會驗籤失敗