1、创建任务类
- 签名算法
签名生成的通用步骤如下:
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3
第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特别注意以下重要规则:
因为 我们服务器人员什么都没写,所以下面的生成预支付ID需要我们自己写
◆ 参数名ASCII码从小到大排序(字典序);
◆ 如果参数的值为空不参与签名;
◆ 参数名区分大小写;
◆ 验证调用返回或微信主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。
◆ 微信接口可能增加字段,验证签名时必须支持增加的扩展字段
/**
* 微信支付的任务类
*/
public class WebChatPay extends AsyncTask<Object, Void, Map<String, String>> {
private Context mContext;
private ProgressDialog dialog;
private PayOrderBean mOrder;
private IWXAPI msgApi; //我们开发者调用的接口
private PayReq req;//支付请求参数
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(mContext, "提示",
UIUtils.getInloadMsg());
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
msgApi = WXAPIFactory.createWXAPI(mContext, Config.WX_APPID, false);
req = new PayReq();
if (dialog != null && !dialog.isShowing()) {
dialog.show();
}
}
/**
* 1..先获取预支付交易会话PrepayId
*/
@Override
protected Map<String, String> doInBackground(Object... params) {
this.mContext = (Context) params[0];
this.mOrder = (PayOrderBean) params[1];
msgApi.registerApp(Config.WX_APPID);
String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//请求微信官方统一的支付URL获取会话ID(这个要服务器人员写的)
String entity = genProductArgs(mOrder);//生成产品参数发起统一付款的请求
byte[] buf = Util.httpPost(url, entity);
String content = new String(buf != null ? buf : new byte[0]);
return decodeXml(content);
}
/**
* 2..获取到预支付交易会话PrepayId后,发送支付请求
*/
@Override
protected void onPostExecute(Map<String, String> result) {
if (dialog != null) {
dialog.dismiss();
}
String prepayID = result.get("prepay_id"); //获取商品的预支付交易会话ID
if (TextUtils.isEmpty(prepayID)) {
UIUtils.showToast(mContext, "没有获得PrepayId,错误代码为:" +
result.get("return_code") + "--错误信息为:" + result.get("return_msg"));
return;
}
//发送支付请求
genPayReq(result);
}
/**
* 1.1 生成获取PrepayId 的参数
* 注:请求参数必须按照ASCII排序
*/
private String genProductArgs(PayOrderBean order) {
try {
String nonceStr = genNonceStr();
List<NameValuePair> packageParams = new LinkedList<>();
packageParams.add(new BasicNameValuePair("appid", order.getAppID())); //应用ID
packageParams.add(new BasicNameValuePair("body", "aaa"));//商品描述
packageParams.add(new BasicNameValuePair("mch_id", order.getPartnerID())); //商户号
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr)); //随机字符串
packageParams.add(new BasicNameValuePair("notify_url", order.getNoticeUrlForWx()));//回调地址
packageParams.add(new BasicNameValuePair("out_trade_no", order.getOrderNum()));//订单号
packageParams.add(new BasicNameValuePair("spbill_create_ip", "127.0.0.1"));//用户端实际ip
packageParams.add(new BasicNameValuePair("total_fee", order.getPrice()));//金额
packageParams.add(new BasicNameValuePair("trade_type", "APP")); //支付类型
String sign = genAppSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign)); //签名
String xmlstring = toXml(packageParams);
return new String(xmlstring.toString().getBytes(), "ISO-8859-1");
} catch (Exception e) {
return null;
}
}
/**
*1.2 生成签名
*/
private String genAppSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
for (NameValuePair param : params) {
if (!TextUtils.isEmpty(param.getName()) && !TextUtils.isEmpty(param.getValue())) {
sb.append(param.getName());
sb.append('=');
sb.append(param.getValue());
sb.append('&');
}
}
sb.append("key=").append(mOrder.getSecretKey()); //商户密钥
String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
return packageSign;
}
/**
* 获取随机字符串
*/
private String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(32)).getBytes());
}
/**
* 生成XML格式的文件
*/
private String toXml(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
sb.append("<xml>");
for (NameValuePair param : params) {
sb.append("<").append(param.getName()).append(">");
sb.append(param.getValue());
sb.append("</").append(param.getName()).append(">");
}
sb.append("</xml>");
return sb.toString();
}
/**
* 解析XML
*/
public Map<String, String> decodeXml(String content) {
try {
Map<String, String> xmlMap = 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)) {
// 实例化student对象
xmlMap.put(nodeName, parser.nextText());
}
break;
case XmlPullParser.END_TAG:
break;
}
event = parser.next();
}
return xmlMap;
} catch (Exception e) {
Log.e("orion", e.toString());
}
return null;
}
/**
* 3..生成支付参数,发送请求
*/
private void genPayReq(Map<String, String> result) {
req.appId = mOrder.getAppID(); //用户APPid
req.nonceStr = genNonceStr(); //随机字符串
req.packageValue = "Sign=WXPay"; //固定的
req.partnerId = mOrder.getPartnerID(); //商户ID
req.prepayId = result.get("prepay_id"); //会话ID ,这个最中意
req.timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
//把支付参数也都生成签名文件
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);
msgApi.sendReq(req);//生成付款请求,提交付款申请
}
}
2.导入Demo里的类
3.清单文件配置下
<!-- 微信支付-->
<receiver
android:name=".wxpay.AppRegister">
<intent-filter>
<action android:name="com.enjoydecorate" />
</intent-filter>
</receiver>
<activity android:name=".wxapi.WXPayEntryActivity"/>
4.点击支付
case R.id.id_bt_submit: //支付提交
new WebChatPay().execute(this,orderBean);
break;
5.支付后的回调
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);
setContentView(R.layout.pay_result);
api = WXAPIFactory.createWXAPI(this, Config.WX_APPID);
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
/**
* ,微信APP会返回到商户APP并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码,
* 如果支付成功则去后台查询支付结果再展示用户实际支付结果。
* 注意一定不能以客户端返回作为用户支付的结果,应以服务器端的接收的支付通知或查询API返回的结果为准
*/
public void onResp(BaseResp resp) {
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) { //支付成功的回调码
UIUtils.showToast(this, "支付成功");
LogUtils.d("resp.errCode===" + resp.errCode);
}
}
}
6.需要注意的地方
如果你集成了微信的分享,那么支付的jar包就不要导入,重复会引起错误