、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

Android二维码扫描我们可以调用Zing.jar包,用人家写好的代码,我们只需要根据自己的需要修改布局即可.下面我简单介绍一下Android我们怎么来用和修改人家的代码.

1、下载Zing.jar包http://download.csdn.net/detail/u013132758/9361939

2、解压导入项目可以用了。

效图如下:

详细介绍一下如何根据自己的需求来修改代码:

首先在AndroidMainfest。xml中添加权限

<!-- 开启闪光灯权限 -->   
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>

<uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.CAMERA" />
    
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

1、项目结构如下所示

2、若修改扫描框的大小可在CameraManager里面修改参数width,height该项目中我设置为0.7倍的屏幕宽度。

CameraManager.java

package com.zm.app.zxing.camera;/** Copyright (C) 2008 ZXing authors** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import java.io.IOException;
import java.util.List;import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.Build;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;import com.zm.app.zxing.camera.PlanarYUVLuminanceSource;/*** This object wraps the Camera service object and expects to be the only one talking to it. The* implementation encapsulates the steps needed to take preview-sized images, which are used for* both preview and decoding.**/
public final class CameraManager {private static final String TAG = CameraManager.class.getSimpleName();private static CameraManager cameraManager;static final int SDK_INT; // Later we can use Build.VERSION.SDK_INTstatic {int sdkInt;try {sdkInt = Integer.parseInt(Build.VERSION.SDK);} catch (NumberFormatException nfe) {// Just to be safesdkInt = 10000;}SDK_INT = sdkInt;}private final Context context;private final CameraConfigurationManager configManager;private Camera camera;private Rect framingRect;private Rect framingRectInPreview;private boolean initialized;private boolean previewing;private final boolean useOneShotPreviewCallback;/*** Preview frames are delivered here, which we pass on to the registered handler. Make sure to* clear the handler so it will only receive one message.*/private final PreviewCallback previewCallback;/** Autofocus callbacks arrive here, and are dispatched to the Handler which requested them. */private final AutoFocusCallback autoFocusCallback;/*** Initializes this static object with the Context of the calling Activity.** @param context The Activity which wants to use the camera.*/public static void init(Context context) {if (cameraManager == null) {cameraManager = new CameraManager(context);}}/*** Gets the CameraManager singleton instance.** @return A reference to the CameraManager singleton.*/public static CameraManager get() {return cameraManager;}private CameraManager(Context context) {this.context = context;this.configManager = new CameraConfigurationManager(context);// Camera.setOneShotPreviewCallback() has a race condition in Cupcake, so we use the older// Camera.setPreviewCallback() on 1.5 and earlier. For Donut and later, we need to use// the more efficient one shot callback, as the older one can swamp the system and cause it// to run out of memory. We can't use SDK_INT because it was introduced in the Donut SDK.//useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > Build.VERSION_CODES.CUPCAKE;useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > 3; // 3 = CupcakepreviewCallback = new PreviewCallback(configManager, useOneShotPreviewCallback);autoFocusCallback = new AutoFocusCallback();}/*** Opens the camera driver and initializes the hardware parameters.** @param holder The surface object which the camera will draw preview frames into.* @throws IOException Indicates the camera driver failed to open.*/public void openDriver(SurfaceHolder holder) throws IOException {if (camera == null) {camera = Camera.open();if (camera == null) {throw new IOException();}camera.setPreviewDisplay(holder);if (!initialized) {initialized = true;configManager.initFromCameraParameters(camera);}configManager.setDesiredCameraParameters(camera);//FIXME//     SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);//�Ƿ�ʹ��ǰ��
//      if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
//        FlashlightManager.enableFlashlight();
//      }FlashlightManager.enableFlashlight();}}public void openLight(){if (camera != null) {Camera.Parameters parameter;parameter = camera.getParameters();parameter.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);camera.setParameters(parameter);}}public void offLight(){if (camera != null) {Camera.Parameters parameter;parameter = camera.getParameters();parameter.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);camera.setParameters(parameter);}}/*** Closes the camera driver if still in use.*/public void closeDriver() {if (camera != null) {FlashlightManager.disableFlashlight();camera.release();camera = null;}}/*** Asks the camera hardware to begin drawing preview frames to the screen.*/public void startPreview() {if (camera != null && !previewing) {camera.startPreview();previewing = true;}}/*** Tells the camera to stop drawing preview frames.*/public void stopPreview() {if (camera != null && previewing) {if (!useOneShotPreviewCallback) {camera.setPreviewCallback(null);}camera.stopPreview();previewCallback.setHandler(null, 0);autoFocusCallback.setHandler(null, 0);previewing = false;}}/*** A single preview frame will be returned to the handler supplied. The data will arrive as byte[]* in the message.obj field, with width and height encoded as message.arg1 and message.arg2,* respectively.** @param handler The handler to send the message to.* @param message The what field of the message to be sent.*/public void requestPreviewFrame(Handler handler, int message) {if (camera != null && previewing) {previewCallback.setHandler(handler, message);if (useOneShotPreviewCallback) {camera.setOneShotPreviewCallback(previewCallback);} else {camera.setPreviewCallback(previewCallback);}}}/*** Asks the camera hardware to perform an autofocus.** @param handler The Handler to notify when the autofocus completes.* @param message The message to deliver.*/public void requestAutoFocus(Handler handler, int message) {if (camera != null && previewing) {autoFocusCallback.setHandler(handler, message);//Log.d(TAG, "Requesting auto-focus callback");camera.autoFocus(autoFocusCallback);}}/*** Calculates the framing rect which the UI should draw to show the user where to place the* barcode. This target helps with alignment as well as forces the user to hold the device* far enough away to ensure the image will be in focus.** @return The rectangle to draw on screen in window coordinates.*/public Rect getFramingRect() {Point screenResolution = configManager.getScreenResolution();if (framingRect == null) {if (camera == null) {return null;}DisplayMetrics metrics = context.getResources().getDisplayMetrics();//定义扫描矿的宽和高分别为0.7倍的屏幕宽度和高度int width = (int)(metrics.widthPixels*0.7);int height = width;int leftOffset = (screenResolution.x - width) / 2;int topOffset = (screenResolution.y - height) / 2;framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);Log.d(TAG, "Calculated framing rect: " + framingRect);}return framingRect;}/*** Like {@link #getFramingRect} but coordinates are in terms of the preview frame,* not UI / screen.*/public Rect getFramingRectInPreview() {if (framingRectInPreview == null) {Rect rect = new Rect(getFramingRect());Point cameraResolution = configManager.getCameraResolution();Point screenResolution = configManager.getScreenResolution();//modify here
//      rect.left = rect.left * cameraResolution.x / screenResolution.x;
//      rect.right = rect.right * cameraResolution.x / screenResolution.x;
//      rect.top = rect.top * cameraResolution.y / screenResolution.y;
//      rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;rect.left = rect.left * cameraResolution.y / screenResolution.x;rect.right = rect.right * cameraResolution.y / screenResolution.x;rect.top = rect.top * cameraResolution.x / screenResolution.y;rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;framingRectInPreview = rect;}return framingRectInPreview;}/*** 通过设置Camera打开闪光灯*/public void turnLightOn(){Log.e(TAG,"闪光灯相机=======没开");if (camera == null){Log.e(TAG,"闪光灯相机没开");return;}Log.e(TAG,"闪光灯相机====%%%%%%%===没开");Camera.Parameters parameters = camera.getParameters();if (parameters == null){return;}List flashModes = parameters.getSupportedFlashModes();if (flashModes == null){return;}String flashMode = parameters.getFlashMode();
//    Log.i(TAG, Flash mode:  + flashMode);
//    Log.i(TAG, Flash modes:  + flashModes);
//    // 闪光灯关闭状态if (!Camera.Parameters.FLASH_MODE_TORCH.equals(flashMode)){// Turn on the flashif (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)){parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);camera.setParameters(parameters);camera.startPreview();}else{}}}/*** 通过设置Camera关闭闪光灯**/public void turnLightOff(){if (camera == null){Log.e(TAG,"闪光灯相机没开");return;}Camera.Parameters parameters = camera.getParameters();if (parameters == null){return;}List flashModes = parameters.getSupportedFlashModes();String flashMode = parameters.getFlashMode();// Check if camera flash existsif (flashModes == null){return;}// 闪光灯打开状态if (!Camera.Parameters.FLASH_MODE_OFF.equals(flashMode)){// Turn off the flashif (flashModes.contains(Camera.Parameters.FLASH_MODE_OFF)){parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);camera.setParameters(parameters);}else{Log.e(TAG, "FLASH_MODE_OFF not supported");}}}/*** Converts the result points from still resolution coordinates to screen coordinates.** @param points The points returned by the Reader subclass through Result.getResultPoints().* @return An array of Points scaled to the size of the framing rect and offset appropriately*         so they can be drawn in screen coordinates.*//*public Point[] convertResultPoints(ResultPoint[] points) {Rect frame = getFramingRectInPreview();int count = points.length;Point[] output = new Point[count];for (int x = 0; x < count; x++) {output[x] = new Point();output[x].x = frame.left + (int) (points[x].getX() + 0.5f);output[x].y = frame.top + (int) (points[x].getY() + 0.5f);}return output;}*//*** A factory method to build the appropriate LuminanceSource object based on the format* of the preview buffers, as described by Camera.Parameters.** @param data A preview frame.* @param width The width of the image.* @param height The height of the image.* @return A PlanarYUVLuminanceSource instance.*/public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {Rect rect = getFramingRectInPreview();int previewFormat = configManager.getPreviewFormat();String previewFormatString = configManager.getPreviewFormatString();switch (previewFormat) {// This is the standard Android format which all devices are REQUIRED to support.// In theory, it's the only one we should ever care about.case PixelFormat.YCbCr_420_SP:// This format has never been seen in the wild, but is compatible as we only care// about the Y channel, so allow it.case PixelFormat.YCbCr_422_SP:return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,rect.width(), rect.height());default:// The Samsung Moment incorrectly uses this variant instead of the 'sp' version.// Fortunately, it too has all the Y data up front, so we can read it.if ("yuv420p".equals(previewFormatString)) {return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,rect.width(), rect.height());}}throw new IllegalArgumentException("Unsupported picture format: " +previewFormat + '/' + previewFormatString);}public Context getContext() {return context;}}

3、要修改扫描界面,自己画界面可在ViewfinderView中修改

ViewfinderView.java

package com.zm.app.zxing.view;import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;import com.example.qr_codescan.R;
import com.google.zxing.ResultPoint;
import java.util.Collection;
import java.util.HashSet;/*** Created by leiqi on 15-12-9.*/
public class ViewfinderView extends View {private static final String TAG = "log";/*** 刷新界面的时间*/private static final long ANIMATION_DELAY = 10L;private static final int OPAQUE = 0xFF;/*** 四个绿色边角对应的长度*/private int ScreenRate;/*** 四个绿色边角对应的宽度*/private static final int CORNER_WIDTH = 5;/*** 扫描框中的中间线的宽度*/private static final int MIDDLE_LINE_WIDTH = 5;/*** 扫描框中的中间线的与扫描框左右的间隙*/private static final int MIDDLE_LINE_PADDING = 5;/*** 中间那条线每次刷新移动的距离*/private static final int SPEEN_DISTANCE = 5;/*** 手机的屏幕密度*/private static float density;/*** 字体大小*/private static final int TEXT_SIZE = 18;private static final int TEXT_SIZE1 = 22;/*** 字体距离扫描框下面的距离*/private static final int TEXT_PADDING_TOP = 30;/*** 画笔对象的引用*/private Paint paint;/*** 中间滑动线的最顶端位置*/private int slideTop;/*** 中间滑动线的最底端位置*/private int slideBottom;/*** 将扫描的二维码拍下来,这里没有这个功能,暂时不考虑*/private Bitmap resultBitmap;private final int maskColor;private final int resultColor;private final int resultPointColor;private Collection<ResultPoint> possibleResultPoints;private Collection<ResultPoint> lastPossibleResultPoints;boolean isFirst;public ViewfinderView(Context context, AttributeSet attrs) {super(context, attrs);density = context.getResources().getDisplayMetrics().density;//将像素转换成dpScreenRate = (int) (20 * density);paint = new Paint();Resources resources = getResources();maskColor = resources.getColor(R.color.viewfinder_mask);resultColor = resources.getColor(R.color.result_view);resultPointColor = resources.getColor(R.color.possible_result_points);possibleResultPoints = new HashSet<ResultPoint>(5);}@Overridepublic void onDraw(Canvas canvas) {//中间的扫描框,你要修改扫描框的大小,去CameraManager里面修改Rect frame = com.zm.app.zxing.camera.CameraManager.get().getFramingRect();if (frame == null) {return;}//初始化中间线滑动的最上边和最下边if (!isFirst) {isFirst = true;slideTop = frame.top;slideBottom = frame.bottom;}//获取屏幕的宽和高int width = canvas.getWidth();int height = canvas.getHeight();paint.setColor(resultBitmap != null ? resultColor : maskColor);//画出扫描框外面的阴影部分,共四个部分,扫描框的上面到屏幕上面,扫描框的下面到屏幕下面//扫描框的左边面到屏幕左边,扫描框的右边到屏幕右边canvas.drawRect(0, 0, width, frame.top, paint);canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1,paint);canvas.drawRect(0, frame.bottom + 1, width, height, paint);if (resultBitmap != null) {// Draw the opaque result bitmap over the scanning rectanglepaint.setAlpha(OPAQUE);canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);} else {
//          //画扫描框上面的字
//          paint.setColor(Color.rgb(255,255,255));
//          paint.setTextSize(TEXT_SIZE1 * density);
//          paint.setAlpha(0x40);
//          paint.setTypeface(Typeface.create("System", Typeface.BOLD));
//          canvas.drawText(getResources().getString(R.string.Return_car), frame.left, (float) (frame.top - (float) TEXT_PADDING_TOP * density), paint);//画扫描框边上的角,总共8个部分paint.setColor(Color.rgb(33,134,116));canvas.drawRect(frame.left, frame.top, frame.left + ScreenRate,frame.top + CORNER_WIDTH, paint);canvas.drawRect(frame.left, frame.top, frame.left + CORNER_WIDTH, frame.top+ ScreenRate, paint);canvas.drawRect(frame.right - ScreenRate, frame.top, frame.right,frame.top + CORNER_WIDTH, paint);canvas.drawRect(frame.right - CORNER_WIDTH, frame.top, frame.right, frame.top+ ScreenRate, paint);canvas.drawRect(frame.left, frame.bottom - CORNER_WIDTH, frame.left+ ScreenRate, frame.bottom, paint);canvas.drawRect(frame.left, frame.bottom - ScreenRate,frame.left + CORNER_WIDTH, frame.bottom, paint);canvas.drawRect(frame.right - ScreenRate, frame.bottom - CORNER_WIDTH,frame.right, frame.bottom, paint);canvas.drawRect(frame.right - CORNER_WIDTH, frame.bottom - ScreenRate,frame.right, frame.bottom, paint);//绘制中间的线,每次刷新界面,中间的线往下移动SPEEN_DISTANCEslideTop += SPEEN_DISTANCE;if (slideTop >= frame.bottom) {slideTop = frame.top;}canvas.drawRect(frame.left + MIDDLE_LINE_PADDING, slideTop - MIDDLE_LINE_WIDTH / 2, frame.right - MIDDLE_LINE_PADDING, slideTop + MIDDLE_LINE_WIDTH / 2, paint);//画扫描框下面的字paint.setColor(Color.WHITE);paint.setTextSize(TEXT_SIZE * density);paint.setAlpha(0x40);paint.setTypeface(Typeface.create("System", Typeface.BOLD));canvas.drawText(getResources().getString(R.string.scan_text), frame.left, (float) (frame.bottom + (float) TEXT_PADDING_TOP * density), paint);Collection<ResultPoint> currentPossible = possibleResultPoints;Collection<ResultPoint> currentLast = lastPossibleResultPoints;if (currentPossible.isEmpty()) {lastPossibleResultPoints = null;} else {possibleResultPoints = new HashSet<ResultPoint>(5);lastPossibleResultPoints = currentPossible;paint.setAlpha(OPAQUE);paint.setColor(resultPointColor);for (ResultPoint point : currentPossible) {canvas.drawCircle(frame.left + point.getX(), frame.top+ point.getY(), 6.0f, paint);}}if (currentLast != null) {paint.setAlpha(OPAQUE / 2);paint.setColor(resultPointColor);for (ResultPoint point : currentLast) {canvas.drawCircle(frame.left + point.getX(), frame.top+ point.getY(), 3.0f, paint);}}//只刷新扫描框的内容,其他地方不刷新postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top,frame.right, frame.bottom);}}public void drawViewfinder() {resultBitmap = null;invalidate();}/*** Draw a bitmap with the result points highlighted instead of the live* scanning display.** @param barcode An image of the decoded barcode.*/public void drawResultBitmap(Bitmap barcode) {resultBitmap = barcode;invalidate();}public void addPossibleResultPoint(ResultPoint point) {possibleResultPoints.add(point);}}

4、打开关闭闪光灯

打开关闭闪光灯直接调用

CameraManager.get().openLight();

CameraManager.get().offLight();

public void openLight(){if (camera != null) {Camera.Parameters parameter;parameter = camera.getParameters();parameter.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);camera.setParameters(parameter);}}public void offLight(){if (camera != null) {Camera.Parameters parameter;parameter = camera.getParameters();parameter.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);camera.setParameters(parameter);}}

【Android 学习】之二维码扫描开发(闪光灯功能)相关推荐

  1. Android二维码扫描开发(一):实现思路与原理

    2019独角兽企业重金招聘Python工程师标准>>> Android二维码扫描开发(一):实现思路与原理 Android二维码扫描开发(二):YUV图像格式详解 Android二维 ...

  2. android利用zbar二维码扫描-(解决中文乱码及扫描区域定义)

    写在最前(这是对上一篇博文的问题做的更新[android利用zbar二维码扫描]) project下载   zbarLib编译project  project下载0积分 bug 在2.3的系统中Hol ...

  3. [转载]android利用zbar二维码扫描-(解决中文乱码及扫描区域定义)

    写在最前(这是对上一篇博文的问题做的更新[android利用zbar二维码扫描]) 前天早上登陆CSDN时候一条消息:一网友提出了两点疑惑 扫描框目前只是做的假象,是全屏的图片进行解析 中文乱码现象 ...

  4. Android 基于Zxing二维码扫描的光速实现

    Android 十分钟光速实现二维码扫描 前言 在项目中要使用到二维码的相关内容,我们第一时间想到的是使用大名鼎鼎的zxing或者ZBar开源框架: github-zxing官方库的地址 github ...

  5. Android 应用之二维码扫描登录

    下面介绍二维码扫描登录原理, 首先需要web服务端,和app客户端. web服务端主要工作是生成二维码,检测客户端提交信息正确性,更新网页界面. app客户端主要工作是扫描二维码,提交账户信息(此不是 ...

  6. Android实现一维二维码扫描生成功能(一)-zxing导入现有项目

    前言 目前二维码扫描功能很流行也非常成熟了,而zxing项目也是目前可以说是最流行的二维码扫描方面的开源项目了,很多大神都对zxing进行了封装,github上也有很多好用的二维码开源库,但是我更喜欢 ...

  7. Android 9 实现二维码扫描处理(BGAQRCode-Android) 笔记

    首先声明,本笔记是在下面这位大佬的代码基础上改的,本人会将实现过程中出现的问题和经验写在下面,本笔记可以结合github上作者的readme一起看: https://github.com/bingoo ...

  8. Android快速实现二维码扫描--Zxing

    Android中二维码扫描的最常用库是zxing和zbar,zxing项目地址为https://github.com/zxing/zxing,目前还有多个人在维护.zbar主要用C来写的,对速度有要求 ...

  9. Android 集成zxing二维码扫描、自定义

    项目主要有zxing的基本使用,包含扫描回调.连续扫描.自定义扫描框: 一.依赖库 implementation 'com.journeyapps:zxing-android-embedded:4.3 ...

最新文章

  1. 第一章:点云中的滤波问题---Filters
  2. 详细讲解设计LOGO思维方式和方法【转】
  3. 【小白学PyTorch】15.TF2实现一个简单的服装分类任务
  4. 这是我在网上安的第一个窝!
  5. AI x 量化:华尔街老司机解密智能投资正确姿势
  6. 「云」发展的怎么样了?
  7. python env_#!/usr/bin/env python 有什么用?
  8. B - Ada and Queue
  9. Hadoop学习笔记(七)
  10. “迭代期内无变更”与敏捷开发产品版本规划
  11. 如何在MySQL中设置外键约束
  12. 常用文本编辑器 editor 的常用插件 —— CopyEdit
  13. 【图神经网络】 漫谈图神经网络 (一)
  14. 简单搞一下 Oracle 存储过程测试!
  15. DPDK QOS2 -- DPDK的QOS框架
  16. 伪原创工具哪个好用,自媒体伪原创文章生成器软件
  17. 开发微信小程序需要服务器吗?
  18. 解决:RSA host key for [ip] has changed and you have requested strict checking.
  19. scrollViewDidEndDragging和scrollViewDidEndDecelerating有什么区别呢
  20. 某游戏客户流失情况数据分析

热门文章

  1. 怎么申请注册微信小程序-微信小程序教程1
  2. 存在感应雷达模块 毫米波雷达传感器 智能生活技术应用
  3. 微信内分享网页自定义标题,图片,描述
  4. 用python画好看的图片,几张好看的HTML图片和利用Python画的好看的图
  5. 智慧灯杆新功能:微雾降尘
  6. 高职对口计算机试题ppt,高职单招中职计算机练习卷和答案.doc
  7. android 紫外线传感器,Arduino光线传感器-UV Sensor V1.0-ML8511紫外线传感器
  8. 《黑马程序员》 正则的匹配 切割 替换 获取的操作演示
  9. Error: While importing ‘run_app_dev‘, an ImportError was raised.
  10. java开发-微信支付