關於Android微信支付
前言
最近公司App需要做微信支付這一塊,然後就是被微信支付各種虐。所以覺得有必要把這痛苦的經歷記錄下來。
一.傳送商品訂單給伺服器,然後從伺服器獲取支付請求引數
1.首先註冊,其中api為IWXAPI的例項。
api=WXAPIFactory.createWXAPI(context,APP_ID,false);
api.registerApp(APP_ID);
2.從服務端拿到必要引數後,調支付即可,其中params是自定義的用來儲存從服務端獲取的發起支付請求所需要的引數物件。
if(api!=null){
if(isWXAppInstalled()){
PayReqreq=newPayReq();
req.appId=APP_ID;
req.partnerId=params.getPartnerId();
req.prepayId=params.getPrepayId();
req.packageValue=params.getPackageValue();
req.nonceStr=params.getNonceStr();
req.timeStamp=params.getTimeStamp();
req.sign=params.getSign();
api.sendReq(req);
}
}
3.WXPayEntryActivity支付回撥介面
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private static final String TAG = "WXPayEntryActivity";
private IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pay_result);
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) {
Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
if(resp.errCode == 0){
MyToast.showToast(this,"支付成功");
}else if(resp.errCode == -2){
MyToast.showToast(this,"支付取消");
}
finish();
}
}
}
二.App獲取預支付訂單,然後傳送請求
1.預支付請求資料
/**
* 預支付請求資料
*
* @return
*/
private String genProductArgs() {
StringBuffer xml = new StringBuffer();
try {
String nonceStr = genNonceStr();
xml.append("</xml>");
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));
packageParams.add(new BasicNameValuePair("body", xiaoqu_name+"--"+pay_name));
packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
packageParams.add(new BasicNameValuePair("notify_url", "http://weixin.qq.com"));
packageParams.add(new BasicNameValuePair("out_trade_no", genOutTradNo()));
packageParams.add(new BasicNameValuePair("spbill_create_ip", "127.0.0.1"));
packageParams.add(new BasicNameValuePair("total_fee", pay_num));
packageParams.add(new BasicNameValuePair("trade_type", "APP"));
String sign = genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign));
String xmlstring = toXml(packageParams);
return new String(xmlstring.toString().getBytes(), "ISO8859-1");
} catch (Exception e) {
Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage());
return null;
}
}
2.獲取預支付訂單
/**
* 非同步獲取預支付訂單 prepay_id
*/
private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String, String>> {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(PayOrderActivity.this, "", getString(R.string.getting_prepayid));
}
@Override
protected void onPostExecute(Map<String, String> result) {
if (dialog != null) {
dialog.dismiss();
}
sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n");
resultunifiedorder = result;
//獲取支付請求資料,發起支付請求
genPayReq();
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected Map<String, String> doInBackground(Void... params) {
//獲取預支付訂單
String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
String entity = genProductArgs();
Log.e("entity", entity);
byte[] buf = Util.httpPost(url, entity);
String content = new String(buf);
Log.e("content", content);
Map<String, String> xml = decodeXml(content);
return xml;
}
}
3.全部程式碼
public class PayOrderActivity extends BaseActivity {
private static final String TAG = "PayOrderActivity";
@Bind(R.id.button)
Button button;
PayReq req;
final IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);
// TextView show;
Map<String, String> resultunifiedorder;
StringBuffer sb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pay_order);
ButterKnife.bind(this);
req = new PayReq();
sb = new StringBuffer();
msgApi.registerApp(Constants.APP_ID);
}
@OnClick({R.id.button})
public void onClick(View view) {
switch (view.getId()) {
case R.id.button:
if(pay_id == null||pay_id.length()==0){
MyToast.showToast(PayOrderActivity.this,"請選擇繳費型別");
}else {
GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
getPrepayId.execute();
}
break;
}
}
/**
* 非同步獲取預支付訂單 prepay_id
*/
private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String, String>> {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(PayOrderActivity.this, "", getString(R.string.getting_prepayid));
}
@Override
protected void onPostExecute(Map<String, String> result) {
if (dialog != null) {
dialog.dismiss();
}
sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n");
// show.setText(sb.toString());
resultunifiedorder = result;
genPayReq();
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected Map<String, String> doInBackground(Void... params) {
//獲取預支付訂單
String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
String entity = genProductArgs();
Log.e("entity", entity);
byte[] buf = Util.httpPost(url, entity);
String content = new String(buf);
Log.e("content", content);
Map<String, String> xml = decodeXml(content);
return xml;
}
}
/**
* 獲取支付請求資料,發起支付請求
*/
private void genPayReq() {
req.appId = Constants.APP_ID;
req.partnerId = Constants.MCH_ID;
req.prepayId = resultunifiedorder.get("prepay_id");
req.packageValue = "Sign=WXPay";
req.nonceStr = genNonceStr();
req.timeStamp = String.valueOf(genTimeStamp());
List<NameValuePair> signParams = new LinkedList<NameValuePair>();
signParams.add(new BasicNameValuePair("appid", req.appId));
signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
signParams.add(new BasicNameValuePair("package", req.packageValue));
signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
req.sign = genAppSign(signParams);
sb.append("sign\n" + req.sign + "\n\n");
//SPUtil.put(this, "uid", req.prepayId);
// show.setText(sb.toString());
sendPayReq();
Log.e("PayReq", signParams.toString());
}
/**
* 支付請求籤名
*
* @param params
* @return
*/
private String genAppSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(Constants.API_KEY);
this.sb.append("sign str\n" + sb.toString() + "\n\n");
String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
Log.e("orion", appSign);
return appSign;
}
/**
* 預支付請求資料
*
* @return
*/
private String genProductArgs() {
StringBuffer xml = new StringBuffer();
try {
String nonceStr = genNonceStr();
xml.append("</xml>");
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));
packageParams.add(new BasicNameValuePair("body", "測試商品"));
packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
packageParams.add(new BasicNameValuePair("notify_url", "http://weixin.qq.com"));
packageParams.add(new BasicNameValuePair("out_trade_no", genOutTradNo()));
packageParams.add(new BasicNameValuePair("spbill_create_ip", "127.0.0.1"));
packageParams.add(new BasicNameValuePair("total_fee", pay_num));
packageParams.add(new BasicNameValuePair("trade_type", "APP"));
String sign = genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign));
String xmlstring = toXml(packageParams);
return new String(xmlstring.toString().getBytes(), "ISO8859-1");
} catch (Exception e) {
Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage());
return null;
}
}
/**
* 隨機字串
*
* @return
*/
private String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
/**
* 訂單時間
*
* @return
*/
private long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}
/**
* 隨機產生商戶訂單號
*
* @return
*/
private String genOutTradNo() {
Random random = new Random();
u_id = MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
return u_id;
}
/**
* 生成簽名 獲取預支付訂單簽名
*/
private String genPackageSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(Constants.API_KEY);
String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
Log.e("orion", packageSign);
return packageSign;
}
/**
* 引數轉xml
*
* @param params
* @return
*/
private String toXml(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
sb.append("<xml>");
for (int i = 0; i < params.size(); i++) {
sb.append("<" + params.get(i).getName() + ">");
sb.append(params.get(i).getValue());
sb.append("</" + params.get(i).getName() + ">");
}
sb.append("</xml>");
Log.e("orion", sb.toString());
return sb.toString();
}
/**
* xml 轉Map
*
* @param content
* @return
*/
public Map<String, String> decodeXml(String content) {
try {
Map<String, String> xml = new HashMap<String, String>();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new StringReader(content));
int event = parser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String nodeName = parser.getName();
switch (event) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
if ("xml".equals(nodeName) == false) {
//例項化student物件
xml.put(nodeName, parser.nextText());
}
break;
case XmlPullParser.END_TAG:
break;
}
event = parser.next();
}
return xml;
} catch (Exception e) {
Log.e("orion", e.toString());
}
return null;
}
/**
* 發起支付請求
*/
private void sendPayReq() {
msgApi.registerApp(Constants.APP_ID);
msgApi.sendReq(req);
}
}
接下來就是踩坑
1.微信支付官方demo提供的介面,每個微信賬號只能呼叫一次,再次呼叫時支付返回code值為-1(貌似是因為簽名的原因)
第一次寫這麼多,有錯誤的地方歡迎大家指出 0.0
相關文章
- 關於微信支付,支付寶支付
- 關於支付寶以及微信支付的整合
- 小白急求關於微信支付
- Android 微信支付 微信是否安裝判斷Android
- android微信分享、微信支付的一些坑Android
- android 整合微信支付和支付寶支付其實很簡單Android
- 微信app支付 java後臺接AndroidAPPJavaAndroid
- 關於建行龍支付的聚合支付微信,支付寶 對接PC和H5H5
- 關於Yii2 微信支付回撥地址處理
- 微信支付,支付寶支付
- 支付寶、微信支付(.NET)
- 微信圈圈 - 關於微信那點事
- 微信JSAPI支付JSAPI
- 微信App支付APP
- Android 接入微信支付寶支付Android
- 支付寶微信合單支付
- nodejs微信支付之掃碼支付NodeJS
- 微信、支付寶支付那點事
- PHP-Laravel支付寶支付和微信支付PHPLaravel
- 微信開發超市全反系統,微信支付刷卡支付,微信介面簡單配置!
- Android 仿微信/支付寶 字型大小 調整控制元件Android控制元件
- 微信支付團隊釋出“微信青蛙pro” 支援刷臉支付功能
- 基於Koa2開發微信二維碼掃碼支付相關流程
- 微信小程式之支付微信小程式
- PHP微信支付開發PHP
- 微信jsapi支付 退款介面JSAPI
- uni-app 微信支付APP
- Laravel 搞定支付寶和微信掃碼支付Laravel
- JAVA版微信支付V3—JSAPI支付JavaJSAPI
- 微信App支付:微信支付的appid,appsecret,商戶號mch_id,微信交易支付金鑰(mch_key)在哪裡檢視APP
- 微信支付(weixin-java-pay)Java
- Java 後端微信支付demoJava後端
- 微信小程式的支付流程微信小程式
- 關於微信小程式佈局排列微信小程式
- 微信sdk 公眾號 微信支付 NFC 坑&筆記筆記
- Python實現微信電腦版微信支付收款監聽及支付回撥通知Python
- Python提取支付寶和微信支付二維碼Python
- 微信支付V3 Java jsApi 掃碼支付JavaJSAPI
- 騰訊等關聯公司涉及“微信掃碼支付”侵權