React Native 中实现原生android集成微信支付

本文介绍如何在React Native项目中集成微信支付功能,包括创建必要的Java类、配置React Native模块及权限、实现支付流程等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Andorid端代码

1、使用android studio 打开react native 中的android目录
2、漫长的编译等待后。。。在app/src/main/java/com/.shopapp目录下新建一个名为‘wxapi’的package。

3、在wxapi下面创建三个java类,如下:

WxApiConfig.java

package com.shopapp.wxapi;

/**
 * Created by CR
 */

public class WxApiConfig {

    public final static String WX_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; // 微信统一下单接口
    public final static String NOTIFY_URL = "http://www.weixin.qq.com/wxpay/pay.php"; // 回调接口


}

WxApiModule.java

package com.shopapp.wxapi;

import android.util.Log;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.shopapp.common.SystemUtils;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.xml.sax.InputSource;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;

import javax.annotation.Nullable;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

/**
 * Created by CR on 2017/12/25.
 * 微信支付集成
 */

public class WxApiModule extends ReactContextBaseJavaModule {

    private final ReactApplicationContext reactContext;
    private IWXAPI msgApi;
    private static String appId;
    private static String appKey;
    private static final String LOF_TAG = "WxApiModule";


    public WxApiModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    public ReactApplicationContext getCurrentContext() {
        return reactContext;
    }

    @Override
    public String getName() {
        return "WxApi";
    }

    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        return super.getConstants();
    }

    /**
     * @Author CR
     * @Date 2017/12/25
     * 初始化微信接口
     */
    @ReactMethod
    public void initWxApi(String aid) {
        appId = aid;
        msgApi = WXAPIFactory.createWXAPI(reactContext, appId);
    }

    /**
     * @Author CR
     * @Date 2017/12/25
     * 启动微信
     */
    @ReactMethod
    public void startWx(com.facebook.react.bridge.Callback successCallback) {
        try {
            msgApi.openWXApp();
            successCallback.invoke("success",111);
        }catch (Exception e){
            e.printStackTrace();
            Log.v(LOF_TAG, e.toString());
        }

    }


    /**
     * @Author CR
     * @Date 2017/12/25
     * 微信支付调用
     */
    @ReactMethod
    public void doWxPay(ReadableMap readableMap, com.facebook.react.bridge.Callback successCallback) {



        Log.v(LOF_TAG, "请求的参数是:" + readableMap.toString());
        // 封装处理请求参数
        final String mch_id = readableMap.getString("mch_id"); // 商户号
        Log.v(LOF_TAG, "接收到的商户号是:" + mch_id);
        String nonce_str = UUID.randomUUID().toString(); // 随.机字符串,不长于32位。
        // String device_info = "WEB"; // 终端设备号(门店号或收银设备ID),默认请传"WEB"。
        String body = "某某某公司-测试收款";// 商品描述交易字段格式根据不同的应用场景按照以下格式:APP——需传入应用市场上的APP名字-实际商品名称,天天爱消除-游戏充值。
        String out_trade_no = readableMap.getString("out_trade_no"); //商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
        Log.v(LOF_TAG, "接收到的内部订单号是:" + out_trade_no);
        int total_fee = readableMap.getInt("total_fee"); // 订单总金额,单位为分
        Log.v(LOF_TAG, "接收到的订单总金额:" + total_fee);
        String spbill_create_ip = SystemUtils.getIPAddress(reactContext); // 用户端实际ip
        Log.v(LOF_TAG, "IP地址是:" + spbill_create_ip);
        String trade_type = "APP"; // 支付类型
        String notify_url = WxApiConfig.NOTIFY_URL; // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。

        SortedMap<String, Object> params = new TreeMap<String, Object>();
        params.put("appid", appId);
        params.put("mch_id", mch_id);
        params.put("nonce_str", nonce_str);
        params.put("body", body);
        params.put("out_trade_no", out_trade_no);
        params.put("total_fee", total_fee);
        params.put("spbill_create_ip", spbill_create_ip);
        params.put("trade_type", trade_type);
        params.put("notify_url", notify_url);
        String mySign = createSign(params);
        params.put("sign", mySign);

        // 调用统一下单接口
        SystemUtils.PostUrl(WxApiConfig.WX_ORDER_URL, params, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.v(LOF_TAG, "请求失败");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String responseStr = response.body().string();
                Log.v(LOF_TAG, "请求成功");
                Log.v(LOF_TAG, "返回信息:" + responseStr);
                //
                Map<String, String> map = readStringXmlOut(responseStr);
                String return_code = map.get("return_code");
                String return_msg = map.get("return_msg");
                String result_code = map.get("result_code");
                if("SUCCESS".equals(result_code) && "SUCCESS".equals(return_code)){

                    String prepay_id = map.get("result_code");

                    // 调起微信支付
                    PayReq req = new PayReq();
                    SortedMap<String, Object> paramsPay = new TreeMap<String, Object>();
                    paramsPay.put("appId",appId);
                    paramsPay.put("partnerId",mch_id);
                    paramsPay.put("prepayId",prepay_id);
                    paramsPay.put("packageValue","Sign=WXPay");
                    String nonce_str_pay = UUID.randomUUID().toString();
                    String timeStamp = System.currentTimeMillis()+"";
                    paramsPay.put("nonceStr",nonce_str_pay);

                    req.appId = appId;
                    req.partnerId = mch_id;
                    req.prepayId = prepay_id;
                    req.packageValue = "Sign=WXPay";
                    req.nonceStr = nonce_str_pay;
                    req.timeStamp = timeStamp;
                    String signPay = createSign(paramsPay);
                    req.sign = signPay;
                    msgApi.sendReq(req);
                }
                Log.v(LOF_TAG, "return_code=" + return_code);
                Log.v(LOF_TAG, "return_msg=" + return_msg);
            }
        });

    }

    /**
     * @Author CR
     * @Date 2017/12/25
     * 微信支付签名算法
     */
    @SuppressWarnings("unchecked")
    private static String createSign(SortedMap<String, 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=" + appKey);
        String sign = new String(Hex.encodeHex(DigestUtils.md5(sb.toString())));
        return sign.toUpperCase();
    }

    private static Map<String, String> readStringXmlOut(String xml) {
        Map<String, String> map = new HashMap<String, String>();
        SAXBuilder builder = new SAXBuilder(false);
        try {
            Document document = builder.build(new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8"))));
            Element xmls = document.getRootElement();
            List xmlList = xmls.getChildren();
            for (int i = 0, len = xmlList.size(); i < len; i++) {
                Element e = (Element) xmlList.get(i);
                map.put(e.getName(), e.getText());
            }
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return map;
    }


}

WxApiPackage.java

package com.shopapp.wxapi;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by CR on 2017/12/25.
 */

public class WxApiPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new WxApiModule(reactContext));
        return modules;

    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}
4、在MainApplication文件中的getPackages()方法中添加new WxApiPackage(),代码如下:
@Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
            new RCTCameraPackage(),
              new WxApiPackage()
      );
    }
5、在AndroidManifest.xml文件中加入对应的wifi权限,如下
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
6、在com.shopapp目录下还有一个公共代码模块common包,代码如下:

SystemUtils.java

package com.shopapp.common;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.util.Log;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;

/**
 * Created by CR on 2017/12/26.
 * 系统工具类
 */

public class SystemUtils {

    private static final String LOG_TAG = "SystemUtils";

    public static String getIPAddress(Context context) {
        NetworkInfo info = ((ConnectivityManager) context
                .getSystemService(context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
        if (info != null && info.isConnected()) {
            if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
                try {
                    //Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();
                    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() && inetAddress instanceof Inet4Address) {
                                return inetAddress.getHostAddress();
                            }
                        }
                    }
                } catch (SocketException e) {
                    e.printStackTrace();
                }

            } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址
                return ipAddress;
            }
        } else {
            //当前无网络连接,请在设置中打开网络
            Log.v(LOG_TAG, "当前无网络连接,请在设置中打开网络");
        }
        return null;
    }

    /**
     * 将得到的int类型的IP转换为String类型
     *
     * @param ip
     * @return
     */
    private static String intIP2StringIP(int ip) {
        return (ip & 0xFF) + "." +
                ((ip >> 8) & 0xFF) + "." +
                ((ip >> 16) & 0xFF) + "." +
                (ip >> 24 & 0xFF);
    }


    public static void PostUrl(String url, Map<String, Object> paramsMap, Callback callback) {
        try {
            OkHttpClient okHttpClient = new OkHttpClient();
            FormBody.Builder formBodyBuilder = new FormBody.Builder();

            for (String key : paramsMap.keySet()) {
                formBodyBuilder.add(key, paramsMap.get(key).toString());
            }
            FormBody formBody = formBodyBuilder.build();
            final Request request = new Request.Builder()
                    .url(url)
                    .post(formBody)
                    .build();
            Call call = okHttpClient.newCall(request);
            call.enqueue(callback);

        } catch (Exception e) {
            Log.e(LOG_TAG, e.toString());
        }
    }


}
7、此处用到的一些jar包gradle路径如下:

android/app/build.gradle

   dependencies {
    compile project(':react-native-camera')
    compile fileTree(dir: "libs", include: ["*.jar"])
    compile "com.android.support:appcompat-v7:23.0.1"
    compile "com.facebook.react:react-native:+"  // From node_modules
    compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
    compile group: 'commons-codec', name: 'commons-codec', version: '1.10'
    compile group: 'jdom', name: 'jdom', version: '1.0'
}

react native端代码

在根目录下新增modulesImport.js,代码如下:

'use strict';
import {NativeModules} from 'react-native';

module.exports = {
    WxApi: NativeModules.WxApi
}

在index.js入口文件中初始化微信api,如下:


import {WxApi} from './modulesImport';

WxApi.initWxApi("这里是微信appid,可以写到配置文件然后引入");

AppRegistry.registerComponent('xxx', () => App);

然后在其他页面就可以通过引入WxApi这个模块进行后台自定义方法的调用,如:

例如WxDemo.js页面

import React, { Component } from 'react';
import {
    Image,
    Alert,
    Button,
    Text,
    View
} from 'react-native';
import {WxApi} from '../../modulesImport';
export default class WxDemo extends Component<{}> {

    render() {
        return (
            <View>
                <Button
                    onPress={()=>{
                        //WxApi.startWx(null);
                        //这里展示下回调函数的使用
                        WxApi.startWx((param1,param2)=>{
                            console.log(param1);
                            console.log(param2);
                        });
                    }}
                    title="点击启动微信"
                    color="#841584"
                />
            </View>
        );
    }


}

这样就可以调用android中自定义的各种方法了。
后续功能持续更新中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值