Android技术

Android接入微信支付

2018-12-18  本文已影响0人  赛德赛高

公司要求开通微信支付功能,在此记录一下实现步骤。

一:准备工作

1.首先需要在微信开放平台注册账号。微信开放平台

2.注册成功后点击上方管理中心进行应用创建。

image

3.创建应用成功后,开通微信支付功能需要进行开发者资格认证。

(认证步骤大概是先支付300块开始认证,然后微信这边会给开通的公户上打很小的一笔钱,需要我们做的就是讲打款截图以及申请公函发给微信方,资料提交完毕后大概1到2天就ok了。)

微信认证申请公函怎么填写_百度经验

4.微信支付成功开通后可以获得商户号,凭借商户号登录商户平台配置API密钥(生成预支付订单号需要)。

image
至此准备工作大功告成~撒花~

二:接入微信支付

1.业务流程说明

如下图所示,共有六个步骤。虽然微信官方强烈建议统一下单放在服务端去做,但是因为种种原因,以下步骤全部放在app端进行。

image

2.app实现流程

1.首先添加gradle依赖:

在app module目录下的build.gralde中添加
前阵子公司要求开通微信支付功能,在此记录一下实现步骤。

一:准备工作

1.首先需要在微信开放平台注册账号。微信开放平台

2.注册成功后点击上方管理中心进行应用创建。

image

3.创建应用成功后,开通微信支付功能需要进行开发者资格认证。

(认证步骤大概是先支付300块开始认证,然后微信这边会给开通的公户上打很小的一笔钱,需要我们做的就是讲打款截图以及申请公函发给微信方,资料提交完毕后大概1到2天就ok了。)

微信认证申请公函怎么填写_百度经验

4.微信支付成功开通后可以获得商户号,凭借商户号登录商户平台配置API密钥(生成预支付订单号需要)。

image
至此准备工作大功告成~撒花~

二:接入微信支付

1.业务流程说明

如下图所示,共有六个步骤。虽然微信官方强烈建议统一下单放在服务端去做,但是因为种种原因,以下步骤全部放在app端进行。


image

2.app实现流程

1.首先添加gradle依赖:

在app module目录下的build.gralde中添加

dependencies {
    //微信SDK接入
    implementation 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
}

2.设置相关权限

<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

3.创建wxapi目录,并创建WXPayEntryActivity(注意需要在我们的包目录下创建wxapi目录,结构如图所示)


image.png

4.WXPayEntryActivity实现IWXAPIEventHandler接口,此页面会回调微信支付的结果。

public class WXPayEntryActivity extends AppCompatActivity implements IWXAPIEventHandler {

    private IWXAPI api;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        api = WXAPIFactory.createWXAPI(this, Macro.APP_ID);//这里填入自己的微信APPID
        api.handleIntent(getIntent(), this);
    }

    @Override
    public void onReq(BaseReq baseReq) {

    }

    @Override
    public void onResp(BaseResp baseResp) {

        if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
            int errCord = baseResp.errCode;
            if (errCord == 0) {
                Toast.makeText(this, "支付成功", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(this, "支付失败", Toast.LENGTH_LONG).show();
            }
            //这里接收到了返回的状态码可以进行相应的操作,如果不想在这个页面操作可以把状态码存在本地然后finish掉这个页面,这样就回到了你调起支付的那个页面
            //获取到你刚刚存到本地的状态码进行相应的操作就可以了
            finish();
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        api.handleIntent(intent, this);
    }
}

ps:(这是一个activity记得在manifest里注册)
5.准备代码结束,按照业务流程开始工作。
步骤一:在app中选择商品,记录金额和商品名称,请求微信统一下单接口(如果统一下单放在服务端做的话直接访问你们自己的后端接口让他给我们返回预支付id就可以了。)
步骤二:获取预支付id,这里是在app端做的。

 /**
     * 获取预支付交易会话标识
     */
    private void getReturnMsg() {
        nonceStr = generateNonceStr();
        outTradeNo = getOutTradeNo();
        StringBuffer xmlString = new StringBuffer();
        xmlString.append("</xml>");
        List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
        packageParams.add(new BasicNameValuePair("appid", "你的appid"));
        packageParams.add(new BasicNameValuePair("body", str));//商品描述,商品或支付单简要描述,必填
        packageParams.add(new BasicNameValuePair("mch_id", "你的商户id"));   //商户ID
        packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));//随机字符串
        packageParams.add(new BasicNameValuePair("notify_url", "www.baidu.com"));//不知道怎么填,随便填了一个
        packageParams.add(new BasicNameValuePair("out_trade_no", outTradeNo));//商户系统内部的订单号,32个字符内、可包含字母,必填
        packageParams.add(new BasicNameValuePair("spbill_create_ip", GetIp()));//APP和网页支付提交用户端ip.必填
        packageParams.add(new BasicNameValuePair("total_fee", "订单金额"));//订单总金额,只能为整数.必填
        packageParams.add(new BasicNameValuePair("trade_type", "APP"));//取值如下:JSAPI,NATIVE,APP,WAP,必填
        packageParams.add(new BasicNameValuePair("sign", getpreSign()));  //签名
        String xmlstring = toXml(packageParams);
        try {
            xmlstring = new String(xmlstring.getBytes("UTF-8"), "ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        final String finalXmlstring = xmlstring;
    new Thread() {
            public void run() {
                try {
                    URL url = new URL("https://api.mch.weixin.qq.com/pay/unifiedorder");
                    HttpURLConnection conn = null;
                    conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
                    conn.setRequestMethod("POST");
                    conn.setUseCaches(false);
                    conn.setDoInput(true);
                    conn.setDoOutput(true);
                    conn.setConnectTimeout(10000);
                    conn.setReadTimeout(10000);
                    DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
                    dos.write(finalXmlstring.getBytes("utf-8"));//params就是上面生成的xml内容
                    dos.flush();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
                    String line = null;
                    StringBuffer strBuf = new StringBuffer();
                    while ((line = reader.readLine()) != null) {
                        strBuf.append(line);
                    }
                    dos.close();
                    reader.close();
                    rs = strBuf.toString();
                    handler.sendEmptyMessage(0);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

微信端接受xml格式参数,所以需要将参数转为xml格式,下面是上边方法中的toXml方法。

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>");
        return sb.toString();
    }

调用此方法可以成功获得预支付id,我把获得签名的方法也贴出来,其他的方法都比较简单。

 private String getpreSign() {
        SortedMap<Object, Object> map = new TreeMap<Object, Object>();
        map.put("body", str);//商品描述
        map.put("mch_id", "你的商户平台id");//商户平台id
        map.put("appid", "你的appId");//app的id
        map.put("nonce_str", nonceStr);//随机字符串
        map.put("notify_url", "www.baidu.com");//异步回调api
        map.put("spbill_create_ip", GetIp());//支付ip
        map.put("out_trade_no", outTradeNo);/商户系统内部的订单号,32个字符内、可包含字母,必填
        map.put("total_fee", "支付金额");//真实金额
        map.put("trade_type", "APP");
        String characterEncoding = "UTF-8";
        return createSign(characterEncoding, map);
    }

    public static String createSign(String characterEncoding, SortedMap<Object, Object> parameters) {
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + "你的密钥");
        String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
        return sign;
    }

步骤三和四:调用getReturnMsg()后微信会返回预支付id给我们,按照签名规范重新生成签名,调用微信支付。

Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Map<String, String> xml = new HashMap<String, String>();
            Document doc = null;
            try {
                doc = (Document) DocumentHelper.parseText(rs);
            } catch (DocumentException e) {
                e.printStackTrace();
            }
            Element root = doc.getRootElement();
            List<Element> list = root.elements();
            for (Element e : list) {
                xml.put(e.getName(), e.getText());
            }
            if (xml != null) {
                IWXAPI wxapi = WXAPIFactory.createWXAPI(WxPayActivity.this, "你的appID");
                wxapi.registerApp("你的appID");
                PayReq req = new PayReq();
                req.appId = xml.get("appid");
                req.partnerId = xml.get("mch_id");
                req.prepayId = xml.get("prepay_id");
                req.packageValue = "Sign=WXPay";
                req.nonceStr = xml.get("nonce_str");
                req.timeStamp = String.valueOf(System.currentTimeMillis()/10);
                SortedMap<Object, Object> map = new TreeMap<Object, Object>();
                map.put("appid", "你的appID");
                map.put("noncestr", req.nonceStr);
                map.put("package",  req.packageValue);
                map.put("partnerid", req.partnerId);
                map.put("prepayid", req.prepayId);
                map.put("timestamp", req.timeStamp);
                String characterEncoding = "UTF-8";
                req.sign = createSign(characterEncoding, map);
                wxapi.sendReq(req);
            }
        }
    };

至此弹出微信支付页面,大功告成,支付结果会在WXPayEntryActivity中回调。

@Override
    public void onResp(BaseResp baseResp) {

        if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
            int errCord = baseResp.errCode;
            if (errCord == 0) {
                Toast.makeText(this, "支付成功", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(this, "支付失败", Toast.LENGTH_LONG).show();
            }
            //这里接收到了返回的状态码可以进行相应的操作,如果不想在这个页面操作可以把状态码存在本地然后finish掉这个页面,这样就回到了你调起支付的那个页面
            //获取到你刚刚存到本地的状态码进行相应的操作就可以了
            finish();
        }
    }

疑问:("body", str));//商品描述,商品或支付单简要描述,必填,
这个body无法给中文,会显示乱码,有没有大神能帮忙解决一下,感激不尽。谢谢~~

上一篇 下一篇

猜你喜欢

热点阅读