android 微信支付

来源:互联网 发布:Mac照片循环播放软件 编辑:程序博客网 时间:2024/05/17 08:15

微信开放平台有demo和开发文档,但是对于我第一次写支付真的不够细致、具体好吗!


第一步先申请一个APPID,然后添加依赖包--》libammsdk.jar,以及WXPayEntryActivity类。类的路径为  包名.wxapi。下载的demo里都有这些内容。记得要在清单中注册

<activity    android:name=".wxapi.WXPayEntryActivity"    android:exported="true"    android:launchMode="singleTop" />


使用微信支付前要将APP注册到微信

private IWXAPI msgApi;HashMap<String, String> content = new HashMap<String, String>();private boolean isPay = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    // 将该app注册到微信    msgApi = WXAPIFactory.createWXAPI(App.getInstance(), null);}

要使用到的一些方法(全是博主在网上找的,忘记出处了。)

/** * 获取本地IP的方法 */public String getLocalIpAddress() {    try {        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {            NetworkInterface intf = en.nextElement();            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {                InetAddress inetAddress = enumIpAddr.nextElement();                if (!inetAddress.isLoopbackAddress()) {                    return inetAddress.getHostAddress().toString();                }            }        }    } catch (SocketException ex) {    }    return null;}/** * 获取WIFI的IP */private String getWifiIp() {    //获取wifi服务    WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);    //判断wifi是否开启    if (!wifiManager.isWifiEnabled()) {        wifiManager.setWifiEnabled(true);    }    WifiInfo wifiInfo = wifiManager.getConnectionInfo();    int ipAddress = wifiInfo.getIpAddress();    String ip = intToIp(ipAddress);    return ip;}private String intToIp(int i) {    return (i & 0xFF) + "." +            ((i >> 8) & 0xFF) + "." +            ((i >> 16) & 0xFF) + "." +            (i >> 24 & 0xFF);}
/** * 生成随机字符串 */public static String genOutTradNo() {    Random random = new Random();    return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());}/** * 签名工具 */public static String genAppSign(Map<String, String> params) {    Map<String, String> sortMap = new TreeMap<String, String>(params);    StringBuilder sb = new StringBuilder();    for (Map.Entry<String, String> s : sortMap.entrySet()) {        String k = s.getKey();        String v = s.getValue();        if ("".equals(v) || v == null) {// 过滤空值            continue;        }        sb.append(k).append("=").append(v).append("&");    }    sb.append("key=");    sb.append(App.API_KEY);    String appSign = MD5.md5(sb.toString()).toUpperCase();    LogOut("=====AppSign=====", appSign);    return appSign;}
/* public static String md5(String string) {     byte[] encodeBytes = null;     try {         encodeBytes = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));     } catch (NoSuchAlgorithmException neverHappened) {         throw new RuntimeException(neverHappened);     } catch (UnsupportedEncodingException neverHappened) {         throw new RuntimeException(neverHappened);     }     return toHexString(encodeBytes); }*/
/** * 转换成xml */public static String toXml(Map<String, String> params) {    StringBuilder sb = new StringBuilder();    sb.append("<xml>");    for (Map.Entry<String, String> s : params.entrySet()) {        sb.append("<" + s.getKey() + ">");        sb.append(s.getValue());        sb.append("</" + s.getKey() + ">");    }    sb.append("</xml>");    LogOut("=====xml=====", sb.toString());    return sb.toString();}/** * 解析xml */public static HashMap<String, String> decodeXml(String content) {    try {        HashMap<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) {        LogOut("orion", e.toString());    }    return null;}
/*将字符串转为时间戳*/public static long getStringToDate(String time) {    sf = new SimpleDateFormat("yyyy-MM-dd HH:mm");    Date date = new Date();    try{        date = sf.parse(time);    } catch(ParseException e) {        e.printStackTrace();    }    return date.getTime();}public static long getTimeStr(){    return (getStringToDate(getCurrentDate())/1000);}


准备工作做好就可以开始写支付代码了,根据文档先是统一下单。因为要签名,所以先将除签名外的字段都添加到HashMap中。订单号是自己设置的,我是设置成了时间戳+10位随机数。这里尤其要注意的一点是notify_url,这是接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。这个地址很重要,微信支付结果全部会返到这个地址,如果在APP端接收会出现一些意料之外的后果。所以,一定要在后台处理微信回调结果!一定要在后台处理!后台处理!重要的事情说三遍!地址让后台给你。

content.clear();// 每次使用前记得要清空String ip = getWifiIp();if ("".equals(ip)) {    ip = getLocalIpAddress();}content.put("body", "等级提升");content.put("total_fee", 1 + "");// 微信以分为单位content.put("appid", App.API_ID);// 申请的应用IDcontent.put("mch_id", App.MCH_ID);// 商户号content.put("nonce_str", CommTools.genOutTradNo());// 随机字符串String orderNum = CommTools.getTimeStr() + CommTools.genOutTradNo().substring(0, 9);content.put("out_trade_no", orderNum);// 商户订单号content.put("spbill_create_ip", ip);content.put("notify_url", "http://www.weixin.qq.com/wxpay/pay.php");// 通知地址content.put("trade_type", "APP");

然后调用写好的签名工具生成签名,开放平台有签名算法,并且有校验签名是否正确的工具。将生成的签名也放入map中,然后转换成xml。

String sign = CommTools.genAppSign(content);content.put("sign", sign);String xml = CommTools.toXml(content);

我的项目用的xutils3.0,已经都封装好了,这里我就直接使用它的post方法,将xml添加进去,发送给微信给出的

URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

回调成功,使用decodeXml()解析微信返回的数据,获得prepayid,实例化一个map,存取数据生成签名,调起微信支付接口

String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";requestParams = new RequestParams(url);requestParams.setBodyContent(xml);x.http().post(requestParams, new Callback.CommonCallback<String>() {    @Override    public void onSuccess(String result) {        LogOut(result);        Map<String, String> xml = CommTools.decodeXml(result);        PayReq request = new PayReq();        HashMap<String, String> map = new HashMap<String, String>();        request.appId = App.API_ID;        map.put("appid", App.API_ID);        request.partnerId = xml.get("mch_id");// 商户号        map.put("partnerid", xml.get("mch_id"));        request.prepayId = xml.get("prepay_id");// 预支付交易会话ID        map.put("prepayid", xml.get("prepay_id"));        request.packageValue = "Sign=WXPay";// 扩展字段        map.put("package", "Sign=WXPay");        request.nonceStr = xml.get("nonce_str");        map.put("noncestr", xml.get("nonce_str"));        String time = CommTools.getTimeStr() + "";        request.timeStamp = time;        map.put("timestamp", time);        request.sign = CommTools.genAppSign(map);        msgApi.registerApp(App.API_ID);        msgApi.sendReq(request);        isPay = true;    }    @Override    public void onError(Throwable ex, boolean isOnCallback) {    }    @Override    public void onCancelled(CancelledException cex) {    }    @Override    public void onFinished() {    }});

在WXPayEntryActivity类中获取返回值并保存在本地,setConfig()是我封装好的方法,你也可以使用SharedPreferences保存值,我的博客中有关于SharedPreferences的使用。最后记得finish()

public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {    private IWXAPI api;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        api = WXAPIFactory.createWXAPI(this, App.API_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) {        if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {            setConfig("resp", resp.errCode + "");// 将返回结果保存在本地            finish();        }    }}

我写了个对话框用于显示微信支付结果,写在了onResume()方法中

@Overrideprotected void onResume() {    super.onResume();    if (isPay) {        LayoutInflater inflaterDl = LayoutInflater.from(this);        FrameLayout layout = (FrameLayout) inflaterDl.inflate(R.layout.dialog_pay_result, null);        //对话框        final Dialog dialog = new AlertDialog.Builder(ActivityMyPoints.this).create();        dialog.show();        dialog.getWindow().setContentView(layout);        TextView message = (TextView) layout.findViewById(R.id.message);        ImageView state = (ImageView) layout.findViewById(R.id.iv_pay_statu);        switch (Integer.valueOf(getConfig("resp"))) {            case 0:                message.setText("支付成功");                state.setImageResource(R.drawable.pay_success);                break;            case -1:                message.setText("支付失败");                state.setImageResource(R.drawable.pay_fail);                break;            case -2:                message.setText("取消支付");                state.setImageResource(R.drawable.pay_fail);                break;            default:                break;        }        // 确定按钮        Button btnOK = (Button) layout.findViewById(R.id.positiveButton);        btnOK.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                initData();// 刷新界面                dialog.dismiss();            }        });        isPay = false;    } else {    }}

感兴趣的可以参考我的界面

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:background="@drawable/dialog_shape"    android:clickable="true">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_gravity="center"        android:orientation="vertical">        <ImageView            android:id="@+id/iv_pay_statu"            android:layout_marginTop="20dp"            android:layout_width="50dp"            android:layout_height="50dp"            android:scaleType="centerInside"            android:layout_gravity="center_horizontal"            android:src="@drawable/pay_success"/>            <TextView                android:id="@+id/message"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center_horizontal"                android:layout_margin="10dp"                android:text="支付成功"                android:textColor="#333"                android:textSize="20sp" />            <Button                android:id="@+id/positiveButton"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginLeft="20dp"                android:layout_marginRight="20dp"                android:layout_marginBottom="10dp"                android:layout_marginTop="20dp"                android:background="#526CFD"                android:text="确定"                android:textColor="#fff"                android:textSize="16sp" />    </LinearLayout></FrameLayout>

写完了!调试的时候一定要匹配应用签名,很多人直接运行会发现不能跳转到微信,那是因为app有一个debug签名和一个正式签名,一定要确保与开放平台填写的签名、包名保持一致。


获取应用签名的方法  获取应用签名

SharedPreferences存值  SharedPreferences轻量级存储


0 0
原创粉丝点击