Android 一行代码解决支付宝、微信、银联支付

2024-01-24 01:48

本文主要是介绍Android 一行代码解决支付宝、微信、银联支付,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在Android 中只要提到支付,就必然会使用支付宝、微信、银联这三大支付渠道,所以只要遇到支付需求,就必须去跟着三大支付渠道的文档去对接,每次都是体力活,能不能把三大支付渠写成统一的支付模块,只需要对支付所需要的信息进行配置,一句方法调用即可完成支付?

这篇博客就是完成这个需求的,下面让我来详细说明实现步骤。

准备

  1. 请务必到支付宝、银联、微信,下载好Android所需要的SDK备用。
  2. 支付宝Sdk 使用的是蚂蚁金服下的2.0版本。
  3. 银联支付,请使用2016年12月后发布的版本,因为该版本已经将插件支付和内置支付合并在一起了。不需要检测是否安装插件。

支付所需数据

支付宝

字段说明
orderInfo支付宝2.0SDK中在服务器端生成好的订单信息

参考网址:

https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.R90GnU&treeId=59&articleId=103663&docType=1

使用建造者模式,创建支付宝支付所需数据

public class AliPayConfig {private String orderInfo;private Activity context;private AliPayConfig() {}public String getOrderInfo() {return orderInfo;}public Activity getContext() {return context;}public static class Builder {private String orderInfo;private Activity context;public Builder() {super();}public AliPayConfig.Builder with(Activity context) {this.context = context;return this;}/*** 设置支付宝支付OrderInfo** @param orderInfo* @return*/public AliPayConfig.Builder setOrderInfo(String orderInfo) {this.orderInfo = orderInfo;return this;}public AliPayConfig build() {AliPayConfig aliPayPayConfig = new AliPayConfig();aliPayPayConfig.context = this.context;aliPayPayConfig.orderInfo = this.orderInfo;return aliPayPayConfig;}}
}

微信

字段说明
appId微信支付AppID
partnerId支付商户号
prepayId预支付码(重要)
packageValuepackageValue
nonceStrnonceStr
timeStamp时间戳
sign签名

参考网址:

https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12&index=2

使用建造者模式创建微信支付所需数据

public class WeiXinPayConfig {private Activity context;private String appId;private String partnerId;private String prepayId;private String packageValue;private String nonceStr;private String timeStamp;private String sign;private WeiXinPayConfig() {}public Activity getContext() {return context;}public String getAppId() {return appId;}public String getPartnerId() {return partnerId;}public String getPrepayId() {return prepayId;}public String getPackageValue() {return packageValue;}public String getNonceStr() {return nonceStr;}public String getTimeStamp() {return timeStamp;}public String getSign() {return sign;}public static class Builder {private Activity context;//微信支付AppIDprivate String appId;//微信支付商户号private String partnerId;//预支付码(重要)private String prepayId;//"Sign=WXPay"private String packageValue = "Sign=WXPay";private String nonceStr;//时间戳private String timeStamp;//签名private String sign;public Builder() {super();}public Builder with(Activity context) {this.context = context;return this;}/*** 设置微信支付AppID** @param appId* @return*/public Builder setAppId(String appId) {this.appId = appId;return this;}/*** 微信支付商户号** @param partnerId* @return*/public Builder setPartnerId(String partnerId) {this.partnerId = partnerId;return this;}/*** 设置预支付码(重要)** @param prepayId* @return*/public Builder setPrepayId(String prepayId) {this.prepayId = prepayId;return this;}/*** 设置** @param packageValue* @return*/public Builder setPackageValue(String packageValue) {this.packageValue = packageValue;return this;}/*** 设置** @param nonceStr* @return*/public Builder setNonceStr(String nonceStr) {this.nonceStr = nonceStr;return this;}/*** 设置时间戳** @param timeStamp* @return*/public Builder setTimeStamp(String timeStamp) {this.timeStamp = timeStamp;return this;}/*** 设置签名** @param sign* @return*/public Builder setSign(String sign) {this.sign = sign;return this;}public WeiXinPayConfig build() {WeiXinPayConfig weiXinPayConfig = new WeiXinPayConfig();weiXinPayConfig.context = this.context;//微信支付AppIDweiXinPayConfig.appId = this.appId;//微信支付商户号weiXinPayConfig.partnerId = this.partnerId;//预支付码(重要)weiXinPayConfig.prepayId = this.prepayId;//"Sign=WXPay"weiXinPayConfig.packageValue = this.packageValue;weiXinPayConfig.nonceStr = this.nonceStr;//时间戳weiXinPayConfig.timeStamp = this.timeStamp;//签名weiXinPayConfig.sign = this.sign;return weiXinPayConfig;}}
}

银联

字段说明
tradeCode文档中描述的Tn
serverModel文档中描述的serverModel

参考网址:

https://open.unionpay.com/ajweb/help/file/techFile?productId=3

手机控件支付开发包(Android 版/app开发包/控件使用指南/中国银联手机支付控件接入指南Android.doc

使用建造者模式创建银联所需数据

public class UnionBankPayConfig {private Activity context;private String tradeCode;private String serverModel;private UnionBankPayConfig() {}public Activity getContext() {return context;}public String getTradeCode() {return tradeCode;}public String getServerModel() {return serverModel;}public static class Builder {private Activity context;private String tradeCode;private String serverModel;public Builder() {super();}public UnionBankPayConfig.Builder with(Activity context) {this.context = context;return this;}/*** 设置银联支付Tn** @param tradeCode* @return*/public UnionBankPayConfig.Builder setTradeCode(String tradeCode) {this.tradeCode = tradeCode;return this;}/*** 设置银联支付服务模式** @param serverModel “00” – 银联正式环境 ,“01” – 银联测试环境,该环境中不发生真实交易* @return*/public UnionBankPayConfig.Builder setServerModel(String serverModel) {this.serverModel = serverModel;return this;}public UnionBankPayConfig build() {UnionBankPayConfig unionBankPayConfig = new UnionBankPayConfig();unionBankPayConfig.context = this.context;unionBankPayConfig.tradeCode = this.tradeCode;unionBankPayConfig.serverModel = this.serverModel;return unionBankPayConfig;}}
}

抽象PayFunction

根据阅读三家支付渠道文档,发现,其实大致步骤可以归结为两步。

  1. 检查是否安装有支付渠道插件
  2. 支付,获取同步返回信息

提取共性,创建PayFunction接口

public interface PayFunction {void payOrder();void checkPayState(CheckStateListener checkStateListener);
}

支付宝


import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.widget.Toast;import com.alipay.sdk.app.PayTask;
import com.ta.utdid2.android.utils.StringUtils;import org.unreal.common.pay.CheckStateListener;
import org.unreal.common.pay.PayFunction;
import org.unreal.common.pay.PayResultListener;import java.util.Map;public class AliPay implements PayFunction {private static final int SDK_PAY_FLAG = 1;private static final int SDK_CHECK_FLAG = 2;private AliPayConfig config;private PayResultListener listener;private Handler mHandler;private CheckStateListener checkStateListener;public AliPay(PayResultListener listener) {this.listener = listener;}@Overridepublic void payOrder() {Runnable checkRunnable = new Runnable() {@Overridepublic void run() {// 构造PayTask 对象PayTask payTask = new PayTask(config.getContext());// 调用查询接口,获取查询结果Map<String, String> result = payTask.payV2(config.getOrderInfo(), true);Message msg = new Message();msg.what = SDK_PAY_FLAG;msg.obj = result;mHandler.sendMessage(msg);}};Thread payThread = new Thread(checkRunnable);payThread.start();}@Overridepublic void checkPayState(CheckStateListener checkStateListener) {this.checkStateListener = checkStateListener;Runnable checkRunnable = new Runnable() {@Overridepublic void run() {// 构造PayTask 对象PayTask payTask = new PayTask(config.getContext());// 调用查询接口,获取查询结果String result = payTask.getVersion();Message msg = new Message();msg.what = SDK_CHECK_FLAG;msg.obj = result;mHandler.sendMessage(msg);}};Thread checkThread = new Thread(checkRunnable);checkThread.start();}public AliPay setConfig(final AliPayConfig config) {this.config = config;// 支付宝返回此次支付结果及加签,建议对支付宝签名信息拿签约时支付宝提供的公钥做验签
//                        String resultInfo = payResult.getResult();
// 判断resultStatus 为“9000”则代表支付成功,具体状态码代表含义可参考接口文档
// 判断resultStatus 为非“9000”则代表可能支付失败
// “8000”代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)
// 其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case SDK_PAY_FLAG: {PayResult payResult = new PayResult((Map<String, String>) msg.obj);// 支付宝返回此次支付结果及加签,建议对支付宝签名信息拿签约时支付宝提供的公钥做验签
//                        String resultInfo = payResult.getResult();String resultStatus = payResult.getResultStatus();// 判断resultStatus 为“9000”则代表支付成功,具体状态码代表含义可参考接口文档if (TextUtils.equals(resultStatus, "9000")) {Toast.makeText(config.getContext(), "支付宝支付成功", Toast.LENGTH_SHORT).show();if (listener != null) listener.onPaySuccess();} else {// 判断resultStatus 为非“9000”则代表可能支付失败// “8000”代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)if (TextUtils.equals(resultStatus, "8000")) {Toast.makeText(config.getContext(), "支付宝支付结果确认中", Toast.LENGTH_SHORT).show();if (listener != null) listener.onPayConfirming();} else {// 其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误Toast.makeText(config.getContext(), "支付宝支付失败", Toast.LENGTH_SHORT).show();if (listener != null) listener.onPayFailure();}}break;}case SDK_CHECK_FLAG: {if (listener != null) {if (StringUtils.isEmpty(msg.obj.toString())) {Toast.makeText(config.getContext(), "没有安装支付宝或支付宝版本过低,无法使用支付宝支付!", Toast.LENGTH_SHORT).show();checkStateListener.checkState(false);} else {checkStateListener.checkState(true);}}break;}default:break;}}};return this;}
}

这种实现方案有漏洞,没有使用公钥验证返回值是否合法,有风险。


import android.text.TextUtils;import java.util.Map;public class PayResult {private String resultStatus;private String result;private String memo;public PayResult(Map<String, String> rawResult) {if (rawResult == null) {return;}for (String key : rawResult.keySet()) {if (TextUtils.equals(key, "resultStatus")) {resultStatus = rawResult.get(key);} else if (TextUtils.equals(key, "result")) {result = rawResult.get(key);} else if (TextUtils.equals(key, "memo")) {memo = rawResult.get(key);}}}@Overridepublic String toString() {return "resultStatus={" + resultStatus + "};memo={" + memo+ "};result={" + result + "}";}/*** @return the resultStatus*/public String getResultStatus() {return resultStatus;}/*** @return the memo*/public String getMemo() {return memo;}/*** @return the result*/public String getResult() {return result;}
}

微信

package com.drawthink.pay.weixin;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.Toast;import com.drawthink.pay.PayModule;
import com.drawthink.pay.PayResultListener;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;public class WeiXinPay implements PayModule {//微信支付核心apiprivate IWXAPI mWXApi;private PayResultListener listener;private WeiXinPayConfig weiXinPayConfig;private BroadcastReceiver receiver;public WeiXinPay(WeiXinPayConfig weiXinPayConfig) {this.weiXinPayConfig = weiXinPayConfig;mWXApi = WXAPIFactory.createWXAPI(weiXinPayConfig.getContext(), null);mWXApi.registerApp(weiXinPayConfig.getAppId());onEvent();}@Overridepublic PayModule setOnPayResultListener(PayResultListener listener) {this.listener = listener;return this;}@Overridepublic void payOrder() {PayReq request = new PayReq();request.appId = weiXinPayConfig.getAppId();request.partnerId = weiXinPayConfig.getPartnerId();request.prepayId = weiXinPayConfig.getPrepayId();request.packageValue =weiXinPayConfig.getPackageValue() != null? weiXinPayConfig.getPackageValue() : "Sign=WXPay";request.nonceStr = weiXinPayConfig.getNonceStr();request.timeStamp = weiXinPayConfig.getTimeStamp();request.sign = weiXinPayConfig.getSign();request.signType = weiXinPayConfig.getSignType();mWXApi.sendReq(request);}@Overridepublic void checkPayState() {if(listener != null){if(!mWXApi.isWXAppInstalled()){Toast.makeText(weiXinPayConfig.getContext(), "没有安装微信,无法使用微信支付!", Toast.LENGTH_SHORT).show();}if(!mWXApi.isWXAppSupportAPI()){Toast.makeText(weiXinPayConfig.getContext(), "当前微信版本过低,无法使用微信支付,请升级微信!", Toast.LENGTH_SHORT).show();}listener.onPayCheck(mWXApi.isWXAppInstalled() && mWXApi.isWXAppSupportAPI());}}
//重要!!!因微信的支付结果回调在yourpackagename.wxapi.WXPayEntryActivity.java中,为了统一处理,所以就在WXPayEntryActivity 中通过本地广播发了一个通知,来处理回调private void onEvent() {
//        0 成功  展示成功页面
//        -1    错误  可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。
//        -2    用户取消    无需处理。发生场景:用户不支付了,点击取消,返回APP。IntentFilter filter = new IntentFilter("org.unreal.pay.weiXinPayResult");//        0 成功  展示成功页面
//  -1  错误       -2 用户取消receiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {int errCode = intent.getIntExtra("errCode", -1);if (errCode == BaseResp.ErrCode.ERR_OK) { //        0 成功    展示成功页面WeiXinPay.this.listener.onPaySuccess();} else {//  -1  错误       -2 用户取消WeiXinPay.this.listener.onPayFailure();}LocalBroadcastManager.getInstance(weiXinPayConfig.getContext()).unregisterReceiver(receiver);}};LocalBroadcastManager.getInstance(weiXinPayConfig.getContext()).registerReceiver(receiver,filter);}
}

yourpackagename.wxapi.WXPayEntryActivity.java

package com.drawthink.hospital.wxapi;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.SyncStateContract;
import android.support.v4.content.LocalBroadcastManager;import com.tencent.mm.opensdk.constants.ConstantsAPI;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;public class WXPayEntryActivity  extends Activity implements IWXAPIEventHandler {private IWXAPI api;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);api = WXAPIFactory.createWXAPI(this, null);api.handleIntent(getIntent(), this);}@Overrideprotected void onNewIntent(Intent intent) {super.onNewIntent(intent);setIntent(intent);api.handleIntent(intent, this);}@Overridepublic void onReq(BaseReq req) {}@Overridepublic void onResp(BaseResp resp) {/*** 微信支付成功回调会开启一个activity,并执行onResp方法,我不希望出现这个界面,所以finish了,在这之前,我发送一个广播* 在广播中我做了回调后的操作**/if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {//发送广播,为intent添加的String必须一致,接收广播处LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("org.unreal.pay.weiXinPayResult").putExtra("errCode", resp.errCode));}finish();}
}

银联


import android.content.Intent;
import android.widget.Toast;import com.unionpay.UPPayAssistEx;import org.unreal.common.pay.CheckStateListener;
import org.unreal.common.pay.PayFunction;
import org.unreal.common.pay.PayResultListener;public class UnionBankPay implements PayFunction {private PayResultListener listener;private UnionBankPayConfig config;public UnionBankPay(PayResultListener listener) {this.listener = listener;}@Overridepublic void payOrder() {UPPayAssistEx.startPay(config.getContext(), null, null, config.getTradeCode(), config.getServerModel());}@Overridepublic void checkPayState(CheckStateListener checkStateListener) {checkStateListener.checkState(true);}public void processPayResponse(Intent data) {if (data == null) {return;}String msg = "";/** 支付控件返回字符串:success、fail、cancel 分别代表支付成功,支付失败,支付取消*/String str = data.getExtras().getString("pay_result");if ("success".equalsIgnoreCase(str)) {// 17-3-3 此处任务只要返回Success 即认为支付成功,此处逻辑会有风险// 如果想对结果数据验签,可使用下面这段代码,但建议不验签,直接去商户后台查询交易结果// result_data结构见c)result_data参数说明
//            if (data.hasExtra("result_data")) {
                String result = data.getExtras().getString("result_data");
                try {
                    JSONObject resultJson = new JSONObject(result);
//                    String sign = resultJson.getString("sign");
//                    String dataOrg = resultJson.getString("data");
                    // 此处的verify建议送去商户后台做验签
                    // 如要放在手机端验,则代码必须支持更新证书
//                    boolean ret = verify(dataOrg, sign, mMode);
//                    if (ret) {
//                        // 验签成功,显示支付结果
//                        msg = "支付成功!";
//                    } else {
//                        // 验签失败
//                        msg = "支付失败!";
//                    }
                } catch (JSONException e) {
                }
//            }// 结果result_data为成功时,去商户后台查询一下再展示成功Toast.makeText(config.getContext(), "银联支付成功", Toast.LENGTH_SHORT).show();if (listener != null) {listener.onPaySuccess();}} else if ("fail".equalsIgnoreCase(str)) {Toast.makeText(config.getContext(), "银联支付失败", Toast.LENGTH_SHORT).show();if (listener != null) {listener.onPayFailure();}} else if ("cancel".equalsIgnoreCase(str)) {if (listener != null) {Toast.makeText(config.getContext(), "银联支付失败,用户取消了支付", Toast.LENGTH_SHORT).show();listener.onPaySuccess();}}}public UnionBankPay setConfig(UnionBankPayConfig config) {this.config = config;return this;}
}

此代码也没有进行远程验证,仅通过支付控件返回字符串判断支付结果,有风险!

检查是否安装支付渠道插件回调接口

主要用于检查插件是否安装,抹除掉同步、异步检查的差别,统一采用回调接口方式来返回检查结果


public interface CheckStateListener {//true 表示 控件安装 false 表示 控件版本过低 或 控件未安装void checkState(boolean state);
}

支付结果回调接口

主要用于支付结果的获取,支付宝提供了三个支付结果,银联、微信提供了两个支付结果。接口设计取了支付宝接口的三个状态,包含了微信、银联支付结果。

public interface PayResultListener {//支付成功void onPaySuccess();//支付失败(包含取消支付)void onPayFailure();//支付结果等待确认中(仅支付宝提供该状态)void onPayConfirming();
}

PayFacade 类,支付调用入口


import android.content.Intent;import org.unreal.common.pay.impl.alipay.AliPay;
import org.unreal.common.pay.impl.alipay.AliPayConfig;
import org.unreal.common.pay.impl.unionbank.UnionBankPay;
import org.unreal.common.pay.impl.unionbank.UnionBankPayConfig;
import org.unreal.common.pay.impl.weixin.WeiXinPay;
import org.unreal.common.pay.impl.weixin.WeiXinPayConfig;public class PayFacade {private static UnionBankPay unionBankPay;private static WeiXinPay weiXinPay;private static AliPay aliPay;boolean unionBank = false;public PayFacade(PayResultListener listener){if(aliPay == null) {aliPay = new AliPay(listener);}if(weiXinPay == null) {weiXinPay = new WeiXinPay(listener);}if(unionBankPay == null) {unionBankPay = new UnionBankPay(listener);}}public boolean isUnionBank() {return unionBank;}public void unionProcessResult(Intent intent){unionBankPay.processPayResponse(intent);}public void pay(final AliPayConfig aliPayConfig) {aliPay.setConfig(aliPayConfig);pay(aliPay);unionBank = false;}public void pay(WeiXinPayConfig weiXinPayConfig){weiXinPay.setConfig(weiXinPayConfig);pay(weiXinPay);unionBank = false;}public void pay(UnionBankPayConfig unionBankPayConfig){unionBankPay.setConfig(unionBankPayConfig);pay(unionBankPay);unionBank = true;}private void pay(final PayFunction payModule){payModule.checkPayState(new CheckStateListener(){@Overridepublic void checkState(boolean state) {if(state){payModule.payOrder();}}});}
}

因为银联的回调需要在onActivityForResult方法中执行,为了调用者不许关心处理过程,特意封装了isUnionBank方法,来进一步处理银联回调。

使用


import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;import org.unreal.common.application.R;
import org.unreal.common.pay.PayFacade;
import org.unreal.common.pay.PayResultListener;
import org.unreal.common.pay.impl.alipay.AliPayConfig;
import org.unreal.common.pay.impl.unionbank.UnionBankPayConfig;
import org.unreal.common.pay.impl.weixin.WeiXinPayConfig;import butterknife.ButterKnife;
import butterknife.OnClick;public class MainActivity extends AppCompatActivity {private PayFacade facade;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);initPayFacade();}private void initPayFacade() {facade = new PayFacade(new PayResultListener(){@Overridepublic void onPaySuccess() {}@Overridepublic void onPayFailure() {}@Overridepublic void onPayConfirming() {}});}@OnClick({R.id.button2, R.id.button3, R.id.button4})public void onClick(View view) {switch (view.getId()) {case R.id.button2://支付宝支付(测试参数,请配合实际场景,从服务器取到后,装配到pay方法中使用)//facade.pay(new AliPayConfig.Builder().with(this).build());break;case R.id.button3://微信支付(测试参数,请配合实际场景,从服务器取到后,装配到pay方法中使用)//facade.pay(new WeiXinPayConfig.Builder().with(this).build());break;case R.id.button4://银联支付(测试参数,请配合实际场景,从服务器取到后,装配到pay方法中使用)//facade.pay(new UnionBankPayConfig.Builder().with(this).build());break;}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {//银联需要在onActivityResult处理支付结果,为了简化调用者处理,此处判断是否使用银联支付,如果使用银联支付,则将data 传递给封装好的处理方法来处理if(facade.isUnionBank()){facade.unionProcessResult(data);}super.onActivityResult(requestCode, resultCode, data);}
}

代码地址

https://github.com/ChineseLincoln/Dagger2Mvp/tree/v3

v3 分之下,pay library项目

这篇关于Android 一行代码解决支付宝、微信、银联支付的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/638191

相关文章

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

解决systemctl reload nginx重启Nginx服务报错:Job for nginx.service invalid问题

《解决systemctlreloadnginx重启Nginx服务报错:Jobfornginx.serviceinvalid问题》文章描述了通过`systemctlstatusnginx.se... 目录systemctl reload nginx重启Nginx服务报错:Job for nginx.javas

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

Mysql DATETIME 毫秒坑的解决

《MysqlDATETIME毫秒坑的解决》本文主要介绍了MysqlDATETIME毫秒坑的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 今天写代码突发一个诡异的 bug,代码逻辑大概如下。1. 新增退款单记录boolean save = s

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

解决Cron定时任务中Pytest脚本无法发送邮件的问题

《解决Cron定时任务中Pytest脚本无法发送邮件的问题》文章探讨解决在Cron定时任务中运行Pytest脚本时邮件发送失败的问题,先优化环境变量,再检查Pytest邮件配置,接着配置文件确保SMT... 目录引言1. 环境变量优化:确保Cron任务可以正确执行解决方案:1.1. 创建一个脚本1.2. 修

python多进程实现数据共享的示例代码

《python多进程实现数据共享的示例代码》本文介绍了Python中多进程实现数据共享的方法,包括使用multiprocessing模块和manager模块这两种方法,具有一定的参考价值,感兴趣的可以... 目录背景进程、进程创建进程间通信 进程间共享数据共享list实践背景 安卓ui自动化框架,使用的是

Mysql8.0修改配置文件my.ini的坑及解决

《Mysql8.0修改配置文件my.ini的坑及解决》使用记事本直接编辑my.ini文件保存后,可能会导致MySQL无法启动,因为MySQL会以ANSI编码读取该文件,解决方法是使用Notepad++... 目录Myhttp://www.chinasem.cnsql8.0修改配置文件my.ini的坑出现的问题